2023-01-02 16:00:42 -05:00
|
|
|
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
|
2020-09-05 20:34:02 -04:00
|
|
|
|
2022-06-29 11:51:11 -04:00
|
|
|
use crate::args::CliOptions;
|
2022-06-28 16:45:55 -04:00
|
|
|
use crate::args::DenoSubcommand;
|
2022-06-27 16:54:09 -04:00
|
|
|
use crate::args::Flags;
|
2022-11-25 17:00:28 -05:00
|
|
|
use crate::args::Lockfile;
|
2022-11-25 18:29:48 -05:00
|
|
|
use crate::args::TsConfigType;
|
|
|
|
use crate::args::TsTypeLib;
|
2022-06-27 16:54:09 -04:00
|
|
|
use crate::args::TypeCheckMode;
|
2021-10-10 17:26:22 -04:00
|
|
|
use crate::cache;
|
2022-11-25 19:04:30 -05:00
|
|
|
use crate::cache::DenoDir;
|
2022-07-12 18:58:39 -04:00
|
|
|
use crate::cache::EmitCache;
|
2022-07-19 11:58:18 -04:00
|
|
|
use crate::cache::FastInsecureHasher;
|
2022-11-28 17:28:54 -05:00
|
|
|
use crate::cache::HttpCache;
|
2022-10-01 06:15:56 -04:00
|
|
|
use crate::cache::NodeAnalysisCache;
|
2022-08-22 12:14:59 -04:00
|
|
|
use crate::cache::ParsedSourceCache;
|
2022-07-12 18:58:39 -04:00
|
|
|
use crate::cache::TypeCheckCache;
|
2022-07-19 11:58:18 -04:00
|
|
|
use crate::emit::emit_parsed_source;
|
2020-11-05 19:38:21 -05:00
|
|
|
use crate::file_fetcher::FileFetcher;
|
2021-12-16 05:45:41 -05:00
|
|
|
use crate::graph_util::graph_lock_or_exit;
|
2023-02-09 22:00:23 -05:00
|
|
|
use crate::graph_util::graph_valid_with_cli_options;
|
2022-11-18 17:28:14 -05:00
|
|
|
use crate::http_util::HttpClient;
|
2022-08-20 11:31:33 -04:00
|
|
|
use crate::node;
|
2022-09-06 06:57:28 -04:00
|
|
|
use crate::node::NodeResolution;
|
2023-01-24 09:05:54 -05:00
|
|
|
use crate::npm::resolve_graph_npm_info;
|
2022-09-13 11:59:01 -04:00
|
|
|
use crate::npm::NpmCache;
|
2022-08-20 11:31:33 -04:00
|
|
|
use crate::npm::NpmPackageReference;
|
2023-02-09 22:00:23 -05:00
|
|
|
use crate::npm::NpmPackageReq;
|
2022-08-20 11:31:33 -04:00
|
|
|
use crate::npm::NpmPackageResolver;
|
2022-11-08 14:17:24 -05:00
|
|
|
use crate::npm::RealNpmRegistryApi;
|
2022-11-02 10:47:02 -04:00
|
|
|
use crate::resolver::CliResolver;
|
2022-09-02 10:54:40 -04:00
|
|
|
use crate::tools::check;
|
2022-11-28 17:28:54 -05:00
|
|
|
use crate::util::progress_bar::ProgressBar;
|
2022-12-12 20:52:10 -05:00
|
|
|
use crate::util::progress_bar::ProgressBarStyle;
|
2020-10-22 20:50:15 -04:00
|
|
|
|
2022-08-23 10:30:14 -04:00
|
|
|
use deno_ast::MediaType;
|
2021-11-16 09:02:28 -05:00
|
|
|
use deno_core::anyhow::anyhow;
|
|
|
|
use deno_core::anyhow::Context;
|
2021-10-10 17:26:22 -04:00
|
|
|
use deno_core::error::custom_error;
|
2022-10-21 11:20:18 -04:00
|
|
|
use deno_core::error::generic_error;
|
2020-09-14 12:48:57 -04:00
|
|
|
use deno_core::error::AnyError;
|
2021-07-06 23:48:01 -04:00
|
|
|
use deno_core::parking_lot::Mutex;
|
2021-12-16 05:45:41 -05:00
|
|
|
use deno_core::parking_lot::RwLock;
|
2022-12-09 09:40:48 -05:00
|
|
|
use deno_core::resolve_url_or_path;
|
2021-09-29 04:47:24 -04:00
|
|
|
use deno_core::CompiledWasmModuleStore;
|
2020-01-05 11:56:18 -05:00
|
|
|
use deno_core::ModuleSpecifier;
|
2021-09-10 21:38:24 -04:00
|
|
|
use deno_core::SharedArrayBufferStore;
|
2021-12-16 05:45:41 -05:00
|
|
|
use deno_graph::source::Loader;
|
2022-11-02 10:47:02 -04:00
|
|
|
use deno_graph::source::Resolver;
|
2023-02-09 22:00:23 -05:00
|
|
|
use deno_graph::ModuleGraph;
|
|
|
|
use deno_graph::ModuleKind;
|
|
|
|
use deno_graph::Resolution;
|
2021-09-10 21:38:24 -04:00
|
|
|
use deno_runtime::deno_broadcast_channel::InMemoryBroadcastChannel;
|
2022-11-30 18:07:32 -05:00
|
|
|
use deno_runtime::deno_node::NodeResolutionMode;
|
2021-12-01 11:13:11 -05:00
|
|
|
use deno_runtime::deno_tls::rustls::RootCertStore;
|
2021-09-10 21:38:24 -04:00
|
|
|
use deno_runtime::deno_web::BlobStore;
|
|
|
|
use deno_runtime::inspector_server::InspectorServer;
|
2023-01-07 11:25:34 -05:00
|
|
|
use deno_runtime::permissions::PermissionsContainer;
|
2021-09-10 21:38:24 -04:00
|
|
|
use import_map::ImportMap;
|
2022-01-13 18:17:56 -05:00
|
|
|
use log::warn;
|
2023-02-09 22:00:23 -05:00
|
|
|
use std::collections::HashMap;
|
2021-06-19 10:14:43 -04:00
|
|
|
use std::collections::HashSet;
|
2021-09-24 11:10:42 -04:00
|
|
|
use std::ops::Deref;
|
2022-06-08 06:07:25 -04:00
|
|
|
use std::path::PathBuf;
|
2022-10-28 15:53:55 -04:00
|
|
|
use std::sync::atomic::AtomicBool;
|
|
|
|
use std::sync::atomic::Ordering;
|
2019-11-04 10:38:52 -05:00
|
|
|
use std::sync::Arc;
|
|
|
|
|
|
|
|
/// This structure represents state of single "deno" program.
|
|
|
|
///
|
|
|
|
/// It is shared by all created workers (thus V8 isolates).
|
2021-09-24 11:10:42 -04:00
|
|
|
#[derive(Clone)]
|
|
|
|
pub struct ProcState(Arc<Inner>);
|
|
|
|
|
|
|
|
pub struct Inner {
|
2022-11-25 19:04:30 -05:00
|
|
|
pub dir: DenoDir,
|
2023-02-03 14:15:16 -05:00
|
|
|
pub file_fetcher: Arc<FileFetcher>,
|
2022-12-12 21:30:44 -05:00
|
|
|
pub http_client: HttpClient,
|
2022-06-29 11:51:11 -04:00
|
|
|
pub options: Arc<CliOptions>,
|
2022-07-19 11:58:18 -04:00
|
|
|
pub emit_cache: EmitCache,
|
|
|
|
pub emit_options: deno_ast::EmitOptions,
|
|
|
|
pub emit_options_hash: u64,
|
2023-02-09 22:00:23 -05:00
|
|
|
graph_data: Arc<RwLock<GraphData>>,
|
2020-10-23 17:01:54 -04:00
|
|
|
pub lockfile: Option<Arc<Mutex<Lockfile>>>,
|
2021-11-08 20:26:39 -05:00
|
|
|
pub maybe_import_map: Option<Arc<ImportMap>>,
|
2020-09-25 04:24:51 -04:00
|
|
|
pub maybe_inspector_server: Option<Arc<InspectorServer>>,
|
2022-06-28 16:45:55 -04:00
|
|
|
pub root_cert_store: RootCertStore,
|
2021-07-05 09:34:37 -04:00
|
|
|
pub blob_store: BlobStore,
|
2021-05-22 12:08:24 -04:00
|
|
|
pub broadcast_channel: InMemoryBroadcastChannel,
|
2021-07-06 13:42:52 -04:00
|
|
|
pub shared_array_buffer_store: SharedArrayBufferStore,
|
2021-09-29 04:47:24 -04:00
|
|
|
pub compiled_wasm_module_store: CompiledWasmModuleStore,
|
2022-08-22 12:14:59 -04:00
|
|
|
pub parsed_source_cache: ParsedSourceCache,
|
2022-12-13 07:53:32 -05:00
|
|
|
pub maybe_resolver: Option<Arc<CliResolver>>,
|
2022-06-08 06:07:25 -04:00
|
|
|
maybe_file_watcher_reporter: Option<FileWatcherReporter>,
|
2022-10-01 06:15:56 -04:00
|
|
|
pub node_analysis_cache: NodeAnalysisCache,
|
2022-09-13 11:59:01 -04:00
|
|
|
pub npm_cache: NpmCache,
|
|
|
|
pub npm_resolver: NpmPackageResolver,
|
2022-08-20 11:31:33 -04:00
|
|
|
pub cjs_resolutions: Mutex<HashSet<ModuleSpecifier>>,
|
2022-09-09 15:57:39 -04:00
|
|
|
progress_bar: ProgressBar,
|
2022-10-28 15:53:55 -04:00
|
|
|
node_std_graph_prepared: AtomicBool,
|
2019-11-04 10:38:52 -05:00
|
|
|
}
|
|
|
|
|
2021-09-24 11:10:42 -04:00
|
|
|
impl Deref for ProcState {
|
|
|
|
type Target = Arc<Inner>;
|
|
|
|
fn deref(&self) -> &Self::Target {
|
|
|
|
&self.0
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl ProcState {
|
2022-06-28 16:45:55 -04:00
|
|
|
pub async fn build(flags: Flags) -> Result<Self, AnyError> {
|
2022-06-29 11:51:11 -04:00
|
|
|
Self::from_options(Arc::new(CliOptions::from_flags(flags)?)).await
|
2022-06-28 16:45:55 -04:00
|
|
|
}
|
|
|
|
|
2022-06-29 11:51:11 -04:00
|
|
|
pub async fn from_options(
|
|
|
|
options: Arc<CliOptions>,
|
2022-06-28 16:45:55 -04:00
|
|
|
) -> Result<Self, AnyError> {
|
2022-06-29 11:51:11 -04:00
|
|
|
Self::build_with_sender(options, None).await
|
2022-06-08 06:07:25 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
pub async fn build_for_file_watcher(
|
2022-06-28 16:45:55 -04:00
|
|
|
flags: Flags,
|
2022-06-08 06:07:25 -04:00
|
|
|
files_to_watch_sender: tokio::sync::mpsc::UnboundedSender<Vec<PathBuf>>,
|
|
|
|
) -> Result<Self, AnyError> {
|
2022-06-28 16:45:55 -04:00
|
|
|
// resolve the config each time
|
2022-06-29 11:51:11 -04:00
|
|
|
let cli_options = Arc::new(CliOptions::from_flags(flags)?);
|
2022-06-28 16:45:55 -04:00
|
|
|
let ps =
|
2022-06-29 11:51:11 -04:00
|
|
|
Self::build_with_sender(cli_options, Some(files_to_watch_sender.clone()))
|
2022-06-28 16:45:55 -04:00
|
|
|
.await?;
|
2023-02-03 14:15:16 -05:00
|
|
|
ps.init_watcher();
|
|
|
|
Ok(ps)
|
|
|
|
}
|
2022-06-08 06:07:25 -04:00
|
|
|
|
2023-02-03 14:15:16 -05:00
|
|
|
/// Reset all runtime state to its default. This should be used on file
|
|
|
|
/// watcher restarts.
|
|
|
|
pub fn reset_for_file_watcher(&mut self) {
|
|
|
|
self.0 = Arc::new(Inner {
|
|
|
|
dir: self.dir.clone(),
|
|
|
|
options: self.options.clone(),
|
|
|
|
emit_cache: self.emit_cache.clone(),
|
|
|
|
emit_options_hash: self.emit_options_hash,
|
|
|
|
emit_options: self.emit_options.clone(),
|
|
|
|
file_fetcher: self.file_fetcher.clone(),
|
|
|
|
http_client: self.http_client.clone(),
|
|
|
|
graph_data: Default::default(),
|
|
|
|
lockfile: self.lockfile.clone(),
|
|
|
|
maybe_import_map: self.maybe_import_map.clone(),
|
|
|
|
maybe_inspector_server: self.maybe_inspector_server.clone(),
|
|
|
|
root_cert_store: self.root_cert_store.clone(),
|
|
|
|
blob_store: Default::default(),
|
|
|
|
broadcast_channel: Default::default(),
|
|
|
|
shared_array_buffer_store: Default::default(),
|
|
|
|
compiled_wasm_module_store: Default::default(),
|
|
|
|
parsed_source_cache: self.parsed_source_cache.reset_for_file_watcher(),
|
|
|
|
maybe_resolver: self.maybe_resolver.clone(),
|
|
|
|
maybe_file_watcher_reporter: self.maybe_file_watcher_reporter.clone(),
|
|
|
|
node_analysis_cache: self.node_analysis_cache.clone(),
|
|
|
|
npm_cache: self.npm_cache.clone(),
|
|
|
|
npm_resolver: self.npm_resolver.clone(),
|
|
|
|
cjs_resolutions: Default::default(),
|
|
|
|
progress_bar: self.progress_bar.clone(),
|
|
|
|
node_std_graph_prepared: AtomicBool::new(false),
|
|
|
|
});
|
|
|
|
self.init_watcher();
|
|
|
|
}
|
2022-06-08 06:07:25 -04:00
|
|
|
|
2023-02-03 14:15:16 -05:00
|
|
|
// Add invariant files like the import map and explicit watch flag list to
|
|
|
|
// the watcher. Dedup for build_for_file_watcher and reset_for_file_watcher.
|
|
|
|
fn init_watcher(&self) {
|
|
|
|
let files_to_watch_sender = match &self.0.maybe_file_watcher_reporter {
|
|
|
|
Some(reporter) => &reporter.sender,
|
|
|
|
None => return,
|
|
|
|
};
|
|
|
|
if let Some(watch_paths) = self.options.watch_paths() {
|
|
|
|
files_to_watch_sender.send(watch_paths.clone()).unwrap();
|
|
|
|
}
|
|
|
|
if let Ok(Some(import_map_path)) = self
|
2022-06-29 11:51:11 -04:00
|
|
|
.options
|
2022-06-29 20:41:48 -04:00
|
|
|
.resolve_import_map_specifier()
|
2022-06-28 16:45:55 -04:00
|
|
|
.map(|ms| ms.and_then(|ref s| s.to_file_path().ok()))
|
2022-06-08 06:07:25 -04:00
|
|
|
{
|
2023-02-03 14:15:16 -05:00
|
|
|
files_to_watch_sender.send(vec![import_map_path]).unwrap();
|
2022-06-08 06:07:25 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
async fn build_with_sender(
|
2022-06-29 11:51:11 -04:00
|
|
|
cli_options: Arc<CliOptions>,
|
2022-06-08 06:07:25 -04:00
|
|
|
maybe_sender: Option<tokio::sync::mpsc::UnboundedSender<Vec<PathBuf>>>,
|
|
|
|
) -> Result<Self, AnyError> {
|
2021-07-05 09:34:37 -04:00
|
|
|
let blob_store = BlobStore::default();
|
2021-05-22 12:08:24 -04:00
|
|
|
let broadcast_channel = InMemoryBroadcastChannel::default();
|
2021-07-06 13:42:52 -04:00
|
|
|
let shared_array_buffer_store = SharedArrayBufferStore::default();
|
2021-09-29 04:47:24 -04:00
|
|
|
let compiled_wasm_module_store = CompiledWasmModuleStore::default();
|
2022-06-29 11:51:11 -04:00
|
|
|
let dir = cli_options.resolve_deno_dir()?;
|
2022-11-25 19:04:30 -05:00
|
|
|
let deps_cache_location = dir.deps_folder_path();
|
2022-11-28 17:28:54 -05:00
|
|
|
let http_cache = HttpCache::new(&deps_cache_location);
|
2022-06-29 11:51:11 -04:00
|
|
|
let root_cert_store = cli_options.resolve_root_cert_store()?;
|
|
|
|
let cache_usage = cli_options.cache_setting();
|
2022-12-12 20:52:10 -05:00
|
|
|
let progress_bar = ProgressBar::new(ProgressBarStyle::TextOnly);
|
2022-11-18 17:28:14 -05:00
|
|
|
let http_client = HttpClient::new(
|
|
|
|
Some(root_cert_store.clone()),
|
2022-12-08 11:50:09 -05:00
|
|
|
cli_options.unsafely_ignore_certificate_errors().clone(),
|
2022-11-18 17:28:14 -05:00
|
|
|
)?;
|
2020-11-05 19:38:21 -05:00
|
|
|
let file_fetcher = FileFetcher::new(
|
2020-02-19 08:17:13 -05:00
|
|
|
http_cache,
|
2020-11-05 19:38:21 -05:00
|
|
|
cache_usage,
|
2022-06-29 11:51:11 -04:00
|
|
|
!cli_options.no_remote(),
|
2022-11-18 17:28:14 -05:00
|
|
|
http_client.clone(),
|
2021-07-05 09:34:37 -04:00
|
|
|
blob_store.clone(),
|
2022-09-09 15:57:39 -04:00
|
|
|
Some(progress_bar.clone()),
|
2023-01-25 16:51:04 -05:00
|
|
|
);
|
2019-11-04 10:38:52 -05:00
|
|
|
|
2022-11-02 11:32:30 -04:00
|
|
|
let lockfile = cli_options.maybe_lock_file();
|
2020-05-29 10:32:15 -04:00
|
|
|
|
2023-01-25 15:13:40 -05:00
|
|
|
let maybe_import_map = cli_options
|
|
|
|
.resolve_import_map(&file_fetcher)
|
|
|
|
.await?
|
|
|
|
.map(Arc::new);
|
2022-06-28 16:45:55 -04:00
|
|
|
let maybe_inspector_server =
|
2022-06-29 11:51:11 -04:00
|
|
|
cli_options.resolve_inspector_server().map(Arc::new);
|
2020-09-25 04:24:51 -04:00
|
|
|
|
2022-11-02 10:47:02 -04:00
|
|
|
let maybe_cli_resolver = CliResolver::maybe_new(
|
|
|
|
cli_options.to_maybe_jsx_import_source_config(),
|
|
|
|
maybe_import_map.clone(),
|
|
|
|
);
|
|
|
|
let maybe_resolver = maybe_cli_resolver.map(Arc::new);
|
2021-11-24 10:55:10 -05:00
|
|
|
|
2022-06-08 06:07:25 -04:00
|
|
|
let maybe_file_watcher_reporter =
|
|
|
|
maybe_sender.map(|sender| FileWatcherReporter {
|
|
|
|
sender,
|
|
|
|
file_paths: Arc::new(Mutex::new(vec![])),
|
|
|
|
});
|
|
|
|
|
2022-07-19 11:58:18 -04:00
|
|
|
let ts_config_result =
|
|
|
|
cli_options.resolve_ts_config_for_emit(TsConfigType::Emit)?;
|
|
|
|
if let Some(ignored_options) = ts_config_result.maybe_ignored_options {
|
|
|
|
warn!("{}", ignored_options);
|
|
|
|
}
|
|
|
|
let emit_cache = EmitCache::new(dir.gen_cache.clone());
|
2022-08-22 12:14:59 -04:00
|
|
|
let parsed_source_cache =
|
|
|
|
ParsedSourceCache::new(Some(dir.dep_analysis_db_file_path()));
|
2022-11-08 14:17:24 -05:00
|
|
|
let registry_url = RealNpmRegistryApi::default_url();
|
2022-09-13 11:59:01 -04:00
|
|
|
let npm_cache = NpmCache::from_deno_dir(
|
2022-08-22 11:35:04 -04:00
|
|
|
&dir,
|
2022-09-13 11:59:01 -04:00
|
|
|
cli_options.cache_setting(),
|
2022-11-18 17:28:14 -05:00
|
|
|
http_client.clone(),
|
2022-09-13 11:59:01 -04:00
|
|
|
progress_bar.clone(),
|
|
|
|
);
|
2022-11-08 14:17:24 -05:00
|
|
|
let api = RealNpmRegistryApi::new(
|
2022-09-13 11:59:01 -04:00
|
|
|
registry_url,
|
|
|
|
npm_cache.clone(),
|
2022-12-12 21:30:44 -05:00
|
|
|
http_client.clone(),
|
2022-09-13 11:59:01 -04:00
|
|
|
progress_bar.clone(),
|
|
|
|
);
|
2023-01-24 09:05:54 -05:00
|
|
|
let npm_resolver = NpmPackageResolver::new_with_maybe_lockfile(
|
2022-09-13 11:59:01 -04:00
|
|
|
npm_cache.clone(),
|
|
|
|
api,
|
2022-09-07 09:33:51 -04:00
|
|
|
cli_options.no_npm(),
|
2022-09-22 11:17:02 -04:00
|
|
|
cli_options
|
|
|
|
.resolve_local_node_modules_folder()
|
|
|
|
.with_context(|| "Resolving local node_modules folder.")?,
|
2023-01-24 09:05:54 -05:00
|
|
|
lockfile.as_ref().cloned(),
|
|
|
|
)
|
|
|
|
.await?;
|
2022-10-01 06:15:56 -04:00
|
|
|
let node_analysis_cache =
|
|
|
|
NodeAnalysisCache::new(Some(dir.node_analysis_db_file_path()));
|
2022-07-19 11:58:18 -04:00
|
|
|
|
2022-09-07 15:06:18 -04:00
|
|
|
let emit_options: deno_ast::EmitOptions = ts_config_result.ts_config.into();
|
2021-09-24 11:10:42 -04:00
|
|
|
Ok(ProcState(Arc::new(Inner {
|
2019-11-04 10:38:52 -05:00
|
|
|
dir,
|
2022-06-29 11:51:11 -04:00
|
|
|
options: cli_options,
|
2022-07-19 11:58:18 -04:00
|
|
|
emit_cache,
|
|
|
|
emit_options_hash: FastInsecureHasher::new()
|
2022-09-07 15:06:18 -04:00
|
|
|
.write_hashable(&emit_options)
|
2022-07-19 11:58:18 -04:00
|
|
|
.finish(),
|
2022-09-07 15:06:18 -04:00
|
|
|
emit_options,
|
2023-02-03 14:15:16 -05:00
|
|
|
file_fetcher: Arc::new(file_fetcher),
|
2022-12-12 21:30:44 -05:00
|
|
|
http_client,
|
2021-10-19 10:01:46 -04:00
|
|
|
graph_data: Default::default(),
|
2019-11-04 10:38:52 -05:00
|
|
|
lockfile,
|
2020-05-29 10:32:15 -04:00
|
|
|
maybe_import_map,
|
2020-09-25 04:24:51 -04:00
|
|
|
maybe_inspector_server,
|
2022-06-28 16:45:55 -04:00
|
|
|
root_cert_store,
|
2021-07-05 09:34:37 -04:00
|
|
|
blob_store,
|
2021-05-22 12:08:24 -04:00
|
|
|
broadcast_channel,
|
2021-07-06 13:42:52 -04:00
|
|
|
shared_array_buffer_store,
|
2021-09-29 04:47:24 -04:00
|
|
|
compiled_wasm_module_store,
|
2022-08-22 12:14:59 -04:00
|
|
|
parsed_source_cache,
|
2021-11-24 10:55:10 -05:00
|
|
|
maybe_resolver,
|
2022-06-08 06:07:25 -04:00
|
|
|
maybe_file_watcher_reporter,
|
2022-10-01 06:15:56 -04:00
|
|
|
node_analysis_cache,
|
2022-09-13 11:59:01 -04:00
|
|
|
npm_cache,
|
2022-08-20 11:31:33 -04:00
|
|
|
npm_resolver,
|
|
|
|
cjs_resolutions: Default::default(),
|
2022-09-09 15:57:39 -04:00
|
|
|
progress_bar,
|
2022-10-28 15:53:55 -04:00
|
|
|
node_std_graph_prepared: AtomicBool::new(false),
|
2021-09-24 11:10:42 -04:00
|
|
|
})))
|
2019-11-04 10:38:52 -05:00
|
|
|
}
|
|
|
|
|
2021-11-15 18:25:52 -05:00
|
|
|
/// This method must be called for a module or a static importer of that
|
|
|
|
/// module before attempting to `load()` it from a `JsRuntime`. It will
|
2021-12-16 05:45:41 -05:00
|
|
|
/// populate `self.graph_data` in memory with the necessary source code, write
|
|
|
|
/// emits where necessary or report any module graph / type checking errors.
|
2022-11-10 16:03:28 -05:00
|
|
|
#[allow(clippy::too_many_arguments)]
|
2022-03-23 09:54:22 -04:00
|
|
|
pub async fn prepare_module_load(
|
2021-09-24 11:10:42 -04:00
|
|
|
&self,
|
2022-03-10 20:33:02 -05:00
|
|
|
roots: Vec<ModuleSpecifier>,
|
2021-10-10 17:26:22 -04:00
|
|
|
is_dynamic: bool,
|
2022-06-28 16:45:55 -04:00
|
|
|
lib: TsTypeLib,
|
2023-01-07 11:25:34 -05:00
|
|
|
root_permissions: PermissionsContainer,
|
|
|
|
dynamic_permissions: PermissionsContainer,
|
2021-04-28 14:17:04 -04:00
|
|
|
) -> Result<(), AnyError> {
|
2022-11-23 13:34:44 -05:00
|
|
|
log::debug!("Preparing module load.");
|
2022-10-24 12:40:27 -04:00
|
|
|
let _pb_clear_guard = self.progress_bar.clear_guard();
|
2022-10-28 15:53:55 -04:00
|
|
|
|
2021-10-10 17:26:22 -04:00
|
|
|
let mut cache = cache::FetchCacher::new(
|
2022-07-19 11:58:18 -04:00
|
|
|
self.emit_cache.clone(),
|
2021-10-10 17:26:22 -04:00
|
|
|
self.file_fetcher.clone(),
|
2023-01-05 12:33:09 -05:00
|
|
|
root_permissions,
|
|
|
|
dynamic_permissions,
|
2021-10-10 17:26:22 -04:00
|
|
|
);
|
2022-06-29 11:51:11 -04:00
|
|
|
let maybe_imports = self.options.to_maybe_imports()?;
|
2022-11-02 10:47:02 -04:00
|
|
|
let maybe_resolver =
|
|
|
|
self.maybe_resolver.as_ref().map(|r| r.as_graph_resolver());
|
2022-06-08 06:07:25 -04:00
|
|
|
let maybe_file_watcher_reporter: Option<&dyn deno_graph::source::Reporter> =
|
|
|
|
if let Some(reporter) = &self.maybe_file_watcher_reporter {
|
|
|
|
Some(reporter)
|
|
|
|
} else {
|
|
|
|
None
|
|
|
|
};
|
|
|
|
|
2022-08-22 12:14:59 -04:00
|
|
|
let analyzer = self.parsed_source_cache.as_analyzer();
|
2023-02-09 22:00:23 -05:00
|
|
|
|
2022-11-23 13:34:44 -05:00
|
|
|
log::debug!("Creating module graph.");
|
2023-02-09 22:00:23 -05:00
|
|
|
let mut graph = self.graph_data.read().graph_inner_clone();
|
|
|
|
|
|
|
|
// Determine any modules that have already been emitted this session and
|
|
|
|
// should be skipped.
|
|
|
|
let reload_exclusions: HashSet<ModuleSpecifier> =
|
|
|
|
graph.specifiers().map(|(s, _)| s.clone()).collect();
|
|
|
|
|
|
|
|
graph
|
|
|
|
.build(
|
|
|
|
roots.clone(),
|
|
|
|
&mut cache,
|
|
|
|
deno_graph::BuildOptions {
|
|
|
|
is_dynamic,
|
|
|
|
imports: maybe_imports,
|
|
|
|
resolver: maybe_resolver,
|
|
|
|
module_analyzer: Some(&*analyzer),
|
|
|
|
reporter: maybe_file_watcher_reporter,
|
|
|
|
},
|
|
|
|
)
|
|
|
|
.await;
|
2022-02-27 08:38:45 -05:00
|
|
|
|
2022-12-06 14:12:51 -05:00
|
|
|
// If there is a lockfile, validate the integrity of all the modules.
|
|
|
|
if let Some(lockfile) = &self.lockfile {
|
|
|
|
graph_lock_or_exit(&graph, &mut lockfile.lock());
|
|
|
|
}
|
2021-10-10 17:26:22 -04:00
|
|
|
|
2023-01-24 09:05:54 -05:00
|
|
|
let (npm_package_reqs, has_node_builtin_specifier) = {
|
2023-02-09 22:00:23 -05:00
|
|
|
graph_valid_with_cli_options(&graph, &roots, &self.options)?;
|
2021-12-16 05:45:41 -05:00
|
|
|
let mut graph_data = self.graph_data.write();
|
2023-02-09 22:00:23 -05:00
|
|
|
graph_data.update_graph(Arc::new(graph));
|
2023-01-24 09:05:54 -05:00
|
|
|
(
|
2023-02-09 22:00:23 -05:00
|
|
|
graph_data.npm_packages.clone(),
|
|
|
|
graph_data.has_node_builtin_specifier,
|
2023-01-24 09:05:54 -05:00
|
|
|
)
|
2022-08-20 11:31:33 -04:00
|
|
|
};
|
|
|
|
|
2022-10-28 15:53:55 -04:00
|
|
|
if !npm_package_reqs.is_empty() {
|
|
|
|
self.npm_resolver.add_package_reqs(npm_package_reqs).await?;
|
2022-08-23 10:39:19 -04:00
|
|
|
self.prepare_node_std_graph().await?;
|
2021-12-16 05:45:41 -05:00
|
|
|
}
|
|
|
|
|
2023-01-24 09:05:54 -05:00
|
|
|
if has_node_builtin_specifier
|
|
|
|
&& self.options.type_check_mode() != TypeCheckMode::None
|
|
|
|
{
|
|
|
|
self
|
|
|
|
.npm_resolver
|
|
|
|
.inject_synthetic_types_node_package()
|
|
|
|
.await?;
|
|
|
|
}
|
|
|
|
|
2022-10-24 12:40:27 -04:00
|
|
|
drop(_pb_clear_guard);
|
2022-09-09 15:57:39 -04:00
|
|
|
|
2022-07-19 11:58:18 -04:00
|
|
|
// type check if necessary
|
2023-01-24 08:23:19 -05:00
|
|
|
let is_std_node = roots.len() == 1 && roots[0] == *node::MODULE_ALL_URL;
|
2023-02-09 22:00:23 -05:00
|
|
|
if self.options.type_check_mode() != TypeCheckMode::None
|
|
|
|
&& !is_std_node
|
|
|
|
&& !self.graph_data.read().is_type_checked(&roots, lib)
|
|
|
|
{
|
2022-11-23 13:34:44 -05:00
|
|
|
log::debug!("Type checking.");
|
2022-07-19 11:58:18 -04:00
|
|
|
let maybe_config_specifier = self.options.maybe_config_file_specifier();
|
2023-02-09 22:00:23 -05:00
|
|
|
let (graph, has_node_builtin_specifier) = {
|
|
|
|
let graph_data = self.graph_data.read();
|
|
|
|
(
|
|
|
|
Arc::new(graph_data.graph.segment(&roots)),
|
|
|
|
graph_data.has_node_builtin_specifier,
|
|
|
|
)
|
|
|
|
};
|
2022-09-02 10:54:40 -04:00
|
|
|
let options = check::CheckOptions {
|
2022-07-19 11:58:18 -04:00
|
|
|
type_check_mode: self.options.type_check_mode(),
|
|
|
|
debug: self.options.log_level() == Some(log::Level::Debug),
|
|
|
|
maybe_config_specifier,
|
|
|
|
ts_config: self
|
|
|
|
.options
|
|
|
|
.resolve_ts_config_for_emit(TsConfigType::Check { lib })?
|
|
|
|
.ts_config,
|
|
|
|
log_checks: true,
|
|
|
|
reload: self.options.reload_flag()
|
2023-01-24 08:23:19 -05:00
|
|
|
&& !roots.iter().all(|r| reload_exclusions.contains(r)),
|
2023-02-09 22:00:23 -05:00
|
|
|
has_node_builtin_specifier,
|
2021-12-16 05:45:41 -05:00
|
|
|
};
|
2022-07-19 11:58:18 -04:00
|
|
|
let check_cache =
|
|
|
|
TypeCheckCache::new(&self.dir.type_checking_cache_db_file_path());
|
2023-02-09 22:00:23 -05:00
|
|
|
let check_result =
|
|
|
|
check::check(graph, &check_cache, &self.npm_resolver, options)?;
|
|
|
|
self.graph_data.write().set_type_checked(&roots, lib);
|
2022-07-19 11:58:18 -04:00
|
|
|
if !check_result.diagnostics.is_empty() {
|
|
|
|
return Err(anyhow!(check_result.diagnostics));
|
2021-10-10 17:26:22 -04:00
|
|
|
}
|
2022-07-19 11:58:18 -04:00
|
|
|
log::debug!("{}", check_result.stats);
|
2021-10-10 17:26:22 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
// any updates to the lockfile should be updated now
|
2021-04-28 14:17:04 -04:00
|
|
|
if let Some(ref lockfile) = self.lockfile {
|
2021-07-06 23:48:01 -04:00
|
|
|
let g = lockfile.lock();
|
2021-04-28 14:17:04 -04:00
|
|
|
g.write()?;
|
|
|
|
}
|
|
|
|
|
2022-11-23 13:34:44 -05:00
|
|
|
log::debug!("Prepared module load.");
|
|
|
|
|
2021-04-28 14:17:04 -04:00
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2022-12-09 09:40:48 -05:00
|
|
|
/// Helper around prepare_module_load that loads and type checks
|
|
|
|
/// the provided files.
|
|
|
|
pub async fn load_and_type_check_files(
|
|
|
|
&self,
|
|
|
|
files: &[String],
|
|
|
|
) -> Result<(), AnyError> {
|
|
|
|
let lib = self.options.ts_type_lib_window();
|
|
|
|
|
|
|
|
let specifiers = files
|
|
|
|
.iter()
|
|
|
|
.map(|file| resolve_url_or_path(file))
|
|
|
|
.collect::<Result<Vec<_>, _>>()?;
|
|
|
|
self
|
|
|
|
.prepare_module_load(
|
|
|
|
specifiers,
|
|
|
|
false,
|
|
|
|
lib,
|
2023-01-07 11:25:34 -05:00
|
|
|
PermissionsContainer::allow_all(),
|
|
|
|
PermissionsContainer::allow_all(),
|
2022-12-09 09:40:48 -05:00
|
|
|
)
|
|
|
|
.await
|
|
|
|
}
|
|
|
|
|
2022-08-23 10:39:19 -04:00
|
|
|
/// Add the builtin node modules to the graph data.
|
|
|
|
pub async fn prepare_node_std_graph(&self) -> Result<(), AnyError> {
|
2022-10-28 15:53:55 -04:00
|
|
|
if self.node_std_graph_prepared.load(Ordering::Relaxed) {
|
|
|
|
return Ok(());
|
|
|
|
}
|
|
|
|
|
2023-02-09 22:00:23 -05:00
|
|
|
let mut graph = self.graph_data.read().graph_inner_clone();
|
|
|
|
let mut loader = self.create_graph_loader();
|
|
|
|
let analyzer = self.parsed_source_cache.as_analyzer();
|
|
|
|
graph
|
|
|
|
.build(
|
|
|
|
vec![node::MODULE_ALL_URL.clone()],
|
|
|
|
&mut loader,
|
|
|
|
deno_graph::BuildOptions {
|
|
|
|
module_analyzer: Some(&*analyzer),
|
|
|
|
..Default::default()
|
|
|
|
},
|
|
|
|
)
|
|
|
|
.await;
|
|
|
|
|
|
|
|
self.graph_data.write().update_graph(Arc::new(graph));
|
2022-10-28 15:53:55 -04:00
|
|
|
self.node_std_graph_prepared.store(true, Ordering::Relaxed);
|
2022-08-23 10:39:19 -04:00
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2022-08-20 11:31:33 -04:00
|
|
|
fn handle_node_resolve_result(
|
|
|
|
&self,
|
2022-09-06 06:57:28 -04:00
|
|
|
result: Result<Option<node::NodeResolution>, AnyError>,
|
2022-08-20 11:31:33 -04:00
|
|
|
) -> Result<ModuleSpecifier, AnyError> {
|
|
|
|
let response = match result? {
|
|
|
|
Some(response) => response,
|
2022-10-21 11:20:18 -04:00
|
|
|
None => return Err(generic_error("not found")),
|
2022-08-20 11:31:33 -04:00
|
|
|
};
|
2022-09-06 06:57:28 -04:00
|
|
|
if let NodeResolution::CommonJs(specifier) = &response {
|
2022-08-20 11:31:33 -04:00
|
|
|
// remember that this was a common js resolution
|
|
|
|
self.cjs_resolutions.lock().insert(specifier.clone());
|
2022-09-06 06:57:28 -04:00
|
|
|
} else if let NodeResolution::BuiltIn(specifier) = &response {
|
|
|
|
return node::resolve_builtin_node_module(specifier);
|
2022-08-20 11:31:33 -04:00
|
|
|
}
|
2022-09-06 06:57:28 -04:00
|
|
|
Ok(response.into_url())
|
2022-08-20 11:31:33 -04:00
|
|
|
}
|
|
|
|
|
2022-03-23 09:54:22 -04:00
|
|
|
pub fn resolve(
|
2021-09-24 11:10:42 -04:00
|
|
|
&self,
|
2021-10-10 17:26:22 -04:00
|
|
|
specifier: &str,
|
|
|
|
referrer: &str,
|
2023-01-10 08:35:44 -05:00
|
|
|
permissions: &mut PermissionsContainer,
|
2021-10-10 17:26:22 -04:00
|
|
|
) -> Result<ModuleSpecifier, AnyError> {
|
2021-11-23 16:30:52 -05:00
|
|
|
if let Ok(referrer) = deno_core::resolve_url_or_path(referrer) {
|
2022-08-20 11:31:33 -04:00
|
|
|
if self.npm_resolver.in_npm_package(&referrer) {
|
|
|
|
// we're in an npm package, so use node resolution
|
|
|
|
return self
|
|
|
|
.handle_node_resolve_result(node::node_resolve(
|
|
|
|
specifier,
|
|
|
|
&referrer,
|
2022-11-30 18:07:32 -05:00
|
|
|
NodeResolutionMode::Execution,
|
2022-08-20 11:31:33 -04:00
|
|
|
&self.npm_resolver,
|
2023-01-10 08:35:44 -05:00
|
|
|
permissions,
|
2022-08-20 11:31:33 -04:00
|
|
|
))
|
|
|
|
.with_context(|| {
|
2023-01-27 10:43:16 -05:00
|
|
|
format!("Could not resolve '{specifier}' from '{referrer}'.")
|
2022-08-20 11:31:33 -04:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2021-12-16 05:45:41 -05:00
|
|
|
let graph_data = self.graph_data.read();
|
2023-02-09 22:00:23 -05:00
|
|
|
let graph = &graph_data.graph;
|
|
|
|
let maybe_resolved = match graph.get(&referrer) {
|
|
|
|
Some(module) => module
|
|
|
|
.dependencies
|
|
|
|
.get(specifier)
|
|
|
|
.map(|d| (&module.specifier, &d.maybe_code)),
|
2021-11-23 16:30:52 -05:00
|
|
|
_ => None,
|
2021-10-19 10:01:46 -04:00
|
|
|
};
|
|
|
|
|
2021-11-23 16:30:52 -05:00
|
|
|
match maybe_resolved {
|
2023-02-09 22:00:23 -05:00
|
|
|
Some((found_referrer, Resolution::Ok(resolved))) => {
|
|
|
|
let specifier = &resolved.specifier;
|
2022-08-20 11:31:33 -04:00
|
|
|
if let Ok(reference) = NpmPackageReference::from_specifier(specifier)
|
|
|
|
{
|
2022-11-13 10:42:15 -05:00
|
|
|
if !self.options.unstable()
|
|
|
|
&& matches!(found_referrer.scheme(), "http" | "https")
|
|
|
|
{
|
|
|
|
return Err(custom_error(
|
|
|
|
"NotSupported",
|
2023-01-27 10:43:16 -05:00
|
|
|
format!("importing npm specifiers in remote modules requires the --unstable flag (referrer: {found_referrer})"),
|
2022-11-13 10:42:15 -05:00
|
|
|
));
|
|
|
|
}
|
|
|
|
|
2022-08-20 11:31:33 -04:00
|
|
|
return self
|
|
|
|
.handle_node_resolve_result(node::node_resolve_npm_reference(
|
|
|
|
&reference,
|
2022-11-30 18:07:32 -05:00
|
|
|
NodeResolutionMode::Execution,
|
2022-08-20 11:31:33 -04:00
|
|
|
&self.npm_resolver,
|
2023-01-10 08:35:44 -05:00
|
|
|
permissions,
|
2022-08-20 11:31:33 -04:00
|
|
|
))
|
2023-01-27 10:43:16 -05:00
|
|
|
.with_context(|| format!("Could not resolve '{reference}'."));
|
2022-08-20 11:31:33 -04:00
|
|
|
} else {
|
|
|
|
return Ok(specifier.clone());
|
|
|
|
}
|
|
|
|
}
|
2023-02-09 22:00:23 -05:00
|
|
|
Some((_, Resolution::Err(err))) => {
|
2021-11-23 16:30:52 -05:00
|
|
|
return Err(custom_error(
|
|
|
|
"TypeError",
|
|
|
|
format!("{}\n", err.to_string_with_range()),
|
|
|
|
))
|
2021-10-10 17:26:22 -04:00
|
|
|
}
|
2023-02-09 22:00:23 -05:00
|
|
|
Some((_, Resolution::None)) | None => {}
|
2020-09-24 18:31:17 -04:00
|
|
|
}
|
2021-10-10 17:26:22 -04:00
|
|
|
}
|
2021-10-19 10:01:46 -04:00
|
|
|
|
2023-01-24 09:05:54 -05:00
|
|
|
// Built-in Node modules
|
|
|
|
if let Some(module_name) = specifier.strip_prefix("node:") {
|
|
|
|
return node::resolve_builtin_node_module(module_name);
|
|
|
|
}
|
|
|
|
|
2021-11-24 10:55:10 -05:00
|
|
|
// FIXME(bartlomieju): this is a hacky way to provide compatibility with REPL
|
|
|
|
// and `Deno.core.evalContext` API. Ideally we should always have a referrer filled
|
|
|
|
// but sadly that's not the case due to missing APIs in V8.
|
2022-12-13 07:53:32 -05:00
|
|
|
let is_repl = matches!(self.options.sub_command(), DenoSubcommand::Repl(_));
|
|
|
|
let referrer = if referrer.is_empty() && is_repl {
|
2023-01-14 23:06:46 -05:00
|
|
|
deno_core::resolve_url_or_path("./$deno$repl.ts")?
|
2020-09-24 18:31:17 -04:00
|
|
|
} else {
|
2023-01-14 23:06:46 -05:00
|
|
|
deno_core::resolve_url_or_path(referrer)?
|
2020-10-22 20:50:15 -04:00
|
|
|
};
|
2021-11-24 10:55:10 -05:00
|
|
|
|
2022-12-13 07:53:32 -05:00
|
|
|
// FIXME(bartlomieju): this is another hack way to provide NPM specifier
|
|
|
|
// support in REPL. This should be fixed.
|
|
|
|
if is_repl {
|
|
|
|
let specifier = self
|
|
|
|
.maybe_resolver
|
|
|
|
.as_ref()
|
2023-01-24 08:23:19 -05:00
|
|
|
.and_then(|resolver| resolver.resolve(specifier, &referrer).ok())
|
2022-12-13 07:53:32 -05:00
|
|
|
.or_else(|| ModuleSpecifier::parse(specifier).ok());
|
|
|
|
if let Some(specifier) = specifier {
|
|
|
|
if let Ok(reference) = NpmPackageReference::from_specifier(&specifier) {
|
|
|
|
return self
|
|
|
|
.handle_node_resolve_result(node::node_resolve_npm_reference(
|
|
|
|
&reference,
|
|
|
|
deno_runtime::deno_node::NodeResolutionMode::Execution,
|
|
|
|
&self.npm_resolver,
|
2023-01-10 08:35:44 -05:00
|
|
|
permissions,
|
2022-12-13 07:53:32 -05:00
|
|
|
))
|
2023-01-27 10:43:16 -05:00
|
|
|
.with_context(|| format!("Could not resolve '{reference}'."));
|
2022-12-13 07:53:32 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-11-02 10:47:02 -04:00
|
|
|
if let Some(resolver) = &self.maybe_resolver {
|
2023-01-24 08:23:19 -05:00
|
|
|
resolver.resolve(specifier, &referrer)
|
2021-10-10 17:26:22 -04:00
|
|
|
} else {
|
2021-11-24 10:55:10 -05:00
|
|
|
deno_core::resolve_import(specifier, referrer.as_str())
|
|
|
|
.map_err(|err| err.into())
|
2020-07-02 11:54:51 -04:00
|
|
|
}
|
2020-05-29 10:32:15 -04:00
|
|
|
}
|
|
|
|
|
2022-07-19 11:58:18 -04:00
|
|
|
pub fn cache_module_emits(&self) -> Result<(), AnyError> {
|
2023-02-09 22:00:23 -05:00
|
|
|
let graph = self.graph();
|
|
|
|
for module in graph.modules() {
|
|
|
|
let is_emittable = module.kind != ModuleKind::External
|
|
|
|
&& matches!(
|
|
|
|
module.media_type,
|
2022-08-23 10:30:14 -04:00
|
|
|
MediaType::TypeScript
|
|
|
|
| MediaType::Mts
|
|
|
|
| MediaType::Cts
|
|
|
|
| MediaType::Jsx
|
|
|
|
| MediaType::Tsx
|
|
|
|
);
|
2023-02-09 22:00:23 -05:00
|
|
|
if is_emittable {
|
|
|
|
if let Some(code) = &module.maybe_source {
|
2022-08-23 10:30:14 -04:00
|
|
|
emit_parsed_source(
|
|
|
|
&self.emit_cache,
|
|
|
|
&self.parsed_source_cache,
|
2023-02-09 22:00:23 -05:00
|
|
|
&module.specifier,
|
|
|
|
module.media_type,
|
2022-08-23 10:30:14 -04:00
|
|
|
code,
|
|
|
|
&self.emit_options,
|
|
|
|
self.emit_options_hash,
|
|
|
|
)?;
|
|
|
|
}
|
2021-12-16 05:45:41 -05:00
|
|
|
}
|
2021-10-19 10:01:46 -04:00
|
|
|
}
|
2022-07-19 11:58:18 -04:00
|
|
|
Ok(())
|
2019-11-04 10:38:52 -05:00
|
|
|
}
|
2022-07-01 11:50:16 -04:00
|
|
|
|
2022-10-20 13:23:21 -04:00
|
|
|
/// Creates the default loader used for creating a graph.
|
|
|
|
pub fn create_graph_loader(&self) -> cache::FetchCacher {
|
|
|
|
cache::FetchCacher::new(
|
2022-07-19 11:58:18 -04:00
|
|
|
self.emit_cache.clone(),
|
2022-07-01 11:50:16 -04:00
|
|
|
self.file_fetcher.clone(),
|
2023-01-07 11:25:34 -05:00
|
|
|
PermissionsContainer::allow_all(),
|
|
|
|
PermissionsContainer::allow_all(),
|
2022-10-20 13:23:21 -04:00
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub async fn create_graph(
|
|
|
|
&self,
|
2023-01-24 08:23:19 -05:00
|
|
|
roots: Vec<ModuleSpecifier>,
|
2022-10-20 13:23:21 -04:00
|
|
|
) -> Result<deno_graph::ModuleGraph, AnyError> {
|
|
|
|
let mut cache = self.create_graph_loader();
|
|
|
|
self.create_graph_with_loader(roots, &mut cache).await
|
|
|
|
}
|
|
|
|
|
|
|
|
pub async fn create_graph_with_loader(
|
|
|
|
&self,
|
2023-01-24 08:23:19 -05:00
|
|
|
roots: Vec<ModuleSpecifier>,
|
2022-10-20 13:23:21 -04:00
|
|
|
loader: &mut dyn Loader,
|
|
|
|
) -> Result<deno_graph::ModuleGraph, AnyError> {
|
2022-07-01 11:50:16 -04:00
|
|
|
let maybe_imports = self.options.to_maybe_imports()?;
|
2022-11-02 10:47:02 -04:00
|
|
|
|
|
|
|
let maybe_cli_resolver = CliResolver::maybe_new(
|
|
|
|
self.options.to_maybe_jsx_import_source_config(),
|
|
|
|
self.maybe_import_map.clone(),
|
|
|
|
);
|
|
|
|
let maybe_graph_resolver =
|
|
|
|
maybe_cli_resolver.as_ref().map(|r| r.as_graph_resolver());
|
2022-08-22 12:14:59 -04:00
|
|
|
let analyzer = self.parsed_source_cache.as_analyzer();
|
2022-07-01 11:50:16 -04:00
|
|
|
|
2023-02-09 22:00:23 -05:00
|
|
|
let mut graph = ModuleGraph::default();
|
|
|
|
graph
|
|
|
|
.build(
|
|
|
|
roots,
|
|
|
|
loader,
|
|
|
|
deno_graph::BuildOptions {
|
|
|
|
is_dynamic: false,
|
|
|
|
imports: maybe_imports,
|
|
|
|
resolver: maybe_graph_resolver,
|
|
|
|
module_analyzer: Some(&*analyzer),
|
|
|
|
reporter: None,
|
|
|
|
},
|
|
|
|
)
|
|
|
|
.await;
|
2022-08-20 11:31:33 -04:00
|
|
|
|
2022-11-11 21:26:14 -05:00
|
|
|
// add the found npm package requirements to the npm resolver and cache them
|
2023-01-24 09:05:54 -05:00
|
|
|
let graph_npm_info = resolve_graph_npm_info(&graph);
|
|
|
|
if !graph_npm_info.package_reqs.is_empty() {
|
|
|
|
self
|
|
|
|
.npm_resolver
|
|
|
|
.add_package_reqs(graph_npm_info.package_reqs)
|
|
|
|
.await?;
|
|
|
|
}
|
|
|
|
if graph_npm_info.has_node_builtin_specifier
|
|
|
|
&& self.options.type_check_mode() != TypeCheckMode::None
|
|
|
|
{
|
|
|
|
self
|
|
|
|
.npm_resolver
|
|
|
|
.inject_synthetic_types_node_package()
|
|
|
|
.await?;
|
2022-08-20 11:31:33 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
Ok(graph)
|
2022-07-01 11:50:16 -04:00
|
|
|
}
|
2023-02-09 22:00:23 -05:00
|
|
|
|
|
|
|
pub fn graph(&self) -> Arc<ModuleGraph> {
|
|
|
|
self.graph_data.read().graph.clone()
|
|
|
|
}
|
2019-11-04 10:38:52 -05:00
|
|
|
}
|
|
|
|
|
2023-01-10 10:28:10 -05:00
|
|
|
#[derive(Clone, Debug)]
|
2022-06-08 06:07:25 -04:00
|
|
|
struct FileWatcherReporter {
|
|
|
|
sender: tokio::sync::mpsc::UnboundedSender<Vec<PathBuf>>,
|
|
|
|
file_paths: Arc<Mutex<Vec<PathBuf>>>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl deno_graph::source::Reporter for FileWatcherReporter {
|
|
|
|
fn on_load(
|
|
|
|
&self,
|
|
|
|
specifier: &ModuleSpecifier,
|
|
|
|
modules_done: usize,
|
|
|
|
modules_total: usize,
|
|
|
|
) {
|
|
|
|
let mut file_paths = self.file_paths.lock();
|
|
|
|
if specifier.scheme() == "file" {
|
|
|
|
file_paths.push(specifier.to_file_path().unwrap());
|
|
|
|
}
|
|
|
|
|
|
|
|
if modules_done == modules_total {
|
|
|
|
self.sender.send(file_paths.drain(..).collect()).unwrap();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2023-02-09 22:00:23 -05:00
|
|
|
|
|
|
|
#[derive(Debug, Default)]
|
|
|
|
struct GraphData {
|
|
|
|
graph: Arc<ModuleGraph>,
|
|
|
|
/// The npm package requirements from all the encountered graphs
|
|
|
|
/// in the order that they should be resolved.
|
|
|
|
npm_packages: Vec<NpmPackageReq>,
|
|
|
|
/// If the graph had a "node:" specifier.
|
|
|
|
has_node_builtin_specifier: bool,
|
|
|
|
checked_libs: HashMap<TsTypeLib, HashSet<ModuleSpecifier>>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl GraphData {
|
|
|
|
/// Store data from `graph` into `self`.
|
|
|
|
pub fn update_graph(&mut self, graph: Arc<ModuleGraph>) {
|
|
|
|
let mut has_npm_specifier_in_graph = false;
|
|
|
|
|
|
|
|
for (specifier, _) in graph.specifiers() {
|
|
|
|
match specifier.scheme() {
|
|
|
|
"node" => {
|
|
|
|
// We don't ever set this back to false because once it's
|
|
|
|
// on then it's on globally.
|
|
|
|
self.has_node_builtin_specifier = true;
|
|
|
|
}
|
|
|
|
"npm" => {
|
|
|
|
if !has_npm_specifier_in_graph
|
|
|
|
&& NpmPackageReference::from_specifier(specifier).is_ok()
|
|
|
|
{
|
|
|
|
has_npm_specifier_in_graph = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
|
|
|
|
if has_npm_specifier_in_graph && self.has_node_builtin_specifier {
|
|
|
|
break; // exit early
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if has_npm_specifier_in_graph {
|
|
|
|
self.npm_packages = resolve_graph_npm_info(&graph).package_reqs;
|
|
|
|
}
|
|
|
|
self.graph = graph;
|
|
|
|
}
|
|
|
|
|
|
|
|
// todo(dsherret): remove the need for cloning this (maybe if we used an AsyncRefCell)
|
|
|
|
pub fn graph_inner_clone(&self) -> ModuleGraph {
|
|
|
|
(*self.graph).clone()
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Mark `roots` and all of their dependencies as type checked under `lib`.
|
|
|
|
/// Assumes that all of those modules are known.
|
|
|
|
pub fn set_type_checked(
|
|
|
|
&mut self,
|
|
|
|
roots: &[ModuleSpecifier],
|
|
|
|
lib: TsTypeLib,
|
|
|
|
) {
|
|
|
|
let entries = self.graph.walk(
|
|
|
|
roots,
|
|
|
|
deno_graph::WalkOptions {
|
|
|
|
check_js: true,
|
|
|
|
follow_dynamic: true,
|
|
|
|
follow_type_only: true,
|
|
|
|
},
|
|
|
|
);
|
|
|
|
let checked_lib_set = self.checked_libs.entry(lib).or_default();
|
|
|
|
for (specifier, _) in entries {
|
|
|
|
checked_lib_set.insert(specifier.clone());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Check if `roots` are all marked as type checked under `lib`.
|
|
|
|
pub fn is_type_checked(
|
|
|
|
&self,
|
|
|
|
roots: &[ModuleSpecifier],
|
|
|
|
lib: TsTypeLib,
|
|
|
|
) -> bool {
|
|
|
|
match self.checked_libs.get(&lib) {
|
|
|
|
Some(checked_lib_set) => roots.iter().all(|r| {
|
|
|
|
let found = self.graph.resolve(r);
|
|
|
|
checked_lib_set.contains(&found)
|
|
|
|
}),
|
|
|
|
None => false,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|