summaryrefslogtreecommitdiff
path: root/cli/factory.rs
diff options
context:
space:
mode:
authorDavid Sherret <dsherret@users.noreply.github.com>2023-05-01 14:35:23 -0400
committerGitHub <noreply@github.com>2023-05-01 14:35:23 -0400
commit9efed4c7a3d32de62e9c9b5e0c6712ce97637abb (patch)
treeaa370f95df93c71f6c57d6a01a50b4df1955ee57 /cli/factory.rs
parent30628288ce2b411ca3def46129a4606073e16bac (diff)
refactor(cli): remove ProcState - add CliFactory (#18900)
This removes `ProcState` and replaces it with a new `CliFactory` which initializes our "service structs" on demand. This isn't a performance improvement at the moment for `deno run`, but might unlock performance improvements in the future.
Diffstat (limited to 'cli/factory.rs')
-rw-r--r--cli/factory.rs669
1 files changed, 669 insertions, 0 deletions
diff --git a/cli/factory.rs b/cli/factory.rs
new file mode 100644
index 000000000..69560cf54
--- /dev/null
+++ b/cli/factory.rs
@@ -0,0 +1,669 @@
+// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
+
+use crate::args::CliOptions;
+use crate::args::DenoSubcommand;
+use crate::args::Flags;
+use crate::args::Lockfile;
+use crate::args::StorageKeyResolver;
+use crate::args::TsConfigType;
+use crate::cache::Caches;
+use crate::cache::DenoDir;
+use crate::cache::EmitCache;
+use crate::cache::HttpCache;
+use crate::cache::NodeAnalysisCache;
+use crate::cache::ParsedSourceCache;
+use crate::emit::Emitter;
+use crate::file_fetcher::FileFetcher;
+use crate::graph_util::ModuleGraphBuilder;
+use crate::graph_util::ModuleGraphContainer;
+use crate::http_util::HttpClient;
+use crate::module_loader::CjsResolutionStore;
+use crate::module_loader::CliModuleLoaderFactory;
+use crate::module_loader::ModuleLoadPreparer;
+use crate::module_loader::NpmModuleLoader;
+use crate::node::CliCjsEsmCodeAnalyzer;
+use crate::node::CliNodeCodeTranslator;
+use crate::npm::create_npm_fs_resolver;
+use crate::npm::CliNpmRegistryApi;
+use crate::npm::CliNpmResolver;
+use crate::npm::NpmCache;
+use crate::npm::NpmResolution;
+use crate::npm::PackageJsonDepsInstaller;
+use crate::resolver::CliGraphResolver;
+use crate::tools::check::TypeChecker;
+use crate::util::progress_bar::ProgressBar;
+use crate::util::progress_bar::ProgressBarStyle;
+use crate::watcher::FileWatcher;
+use crate::watcher::FileWatcherReporter;
+use crate::worker::CliMainWorkerFactory;
+use crate::worker::CliMainWorkerOptions;
+use crate::worker::HasNodeSpecifierChecker;
+
+use deno_core::error::AnyError;
+use deno_core::parking_lot::Mutex;
+
+use deno_runtime::deno_node;
+use deno_runtime::deno_node::analyze::NodeCodeTranslator;
+use deno_runtime::deno_node::NodeResolver;
+use deno_runtime::deno_tls::rustls::RootCertStore;
+use deno_runtime::deno_web::BlobStore;
+use deno_runtime::inspector_server::InspectorServer;
+use deno_semver::npm::NpmPackageReqReference;
+use import_map::ImportMap;
+use log::warn;
+use std::cell::RefCell;
+use std::future::Future;
+use std::path::PathBuf;
+use std::sync::Arc;
+
+pub struct CliFactoryBuilder {
+ maybe_sender: Option<tokio::sync::mpsc::UnboundedSender<Vec<PathBuf>>>,
+}
+
+impl CliFactoryBuilder {
+ pub fn new() -> Self {
+ Self { maybe_sender: None }
+ }
+
+ pub fn with_watcher(
+ mut self,
+ sender: tokio::sync::mpsc::UnboundedSender<Vec<PathBuf>>,
+ ) -> Self {
+ self.maybe_sender = Some(sender);
+ self
+ }
+
+ pub async fn build_from_flags(
+ self,
+ flags: Flags,
+ ) -> Result<CliFactory, AnyError> {
+ Ok(self.build_from_cli_options(Arc::new(CliOptions::from_flags(flags)?)))
+ }
+
+ pub fn build_from_cli_options(self, options: Arc<CliOptions>) -> CliFactory {
+ CliFactory {
+ maybe_sender: RefCell::new(self.maybe_sender),
+ options,
+ services: Default::default(),
+ }
+ }
+}
+
+struct Deferred<T>(once_cell::unsync::OnceCell<T>);
+
+impl<T> Default for Deferred<T> {
+ fn default() -> Self {
+ Self(once_cell::unsync::OnceCell::default())
+ }
+}
+
+impl<T> Deferred<T> {
+ pub fn get_or_try_init(
+ &self,
+ create: impl FnOnce() -> Result<T, AnyError>,
+ ) -> Result<&T, AnyError> {
+ self.0.get_or_try_init(create)
+ }
+
+ pub fn get_or_init(&self, create: impl FnOnce() -> T) -> &T {
+ self.0.get_or_init(create)
+ }
+
+ pub async fn get_or_try_init_async(
+ &self,
+ create: impl Future<Output = Result<T, AnyError>>,
+ ) -> Result<&T, AnyError> {
+ if self.0.get().is_none() {
+ // todo(dsherret): it would be more ideal if this enforced a
+ // single executor and then we could make some initialization
+ // concurrent
+ let val = create.await?;
+ _ = self.0.set(val);
+ }
+ Ok(self.0.get().unwrap())
+ }
+}
+
+#[derive(Default)]
+struct CliFactoryServices {
+ dir: Deferred<DenoDir>,
+ caches: Deferred<Arc<Caches>>,
+ file_fetcher: Deferred<Arc<FileFetcher>>,
+ http_client: Deferred<HttpClient>,
+ emit_cache: Deferred<EmitCache>,
+ emitter: Deferred<Arc<Emitter>>,
+ graph_container: Deferred<Arc<ModuleGraphContainer>>,
+ lockfile: Deferred<Option<Arc<Mutex<Lockfile>>>>,
+ maybe_import_map: Deferred<Option<Arc<ImportMap>>>,
+ maybe_inspector_server: Deferred<Option<Arc<InspectorServer>>>,
+ root_cert_store: Deferred<RootCertStore>,
+ blob_store: Deferred<BlobStore>,
+ parsed_source_cache: Deferred<Arc<ParsedSourceCache>>,
+ resolver: Deferred<Arc<CliGraphResolver>>,
+ file_watcher: Deferred<Arc<FileWatcher>>,
+ maybe_file_watcher_reporter: Deferred<Option<FileWatcherReporter>>,
+ module_graph_builder: Deferred<Arc<ModuleGraphBuilder>>,
+ module_load_preparer: Deferred<Arc<ModuleLoadPreparer>>,
+ node_code_translator: Deferred<Arc<CliNodeCodeTranslator>>,
+ node_fs: Deferred<Arc<dyn deno_node::NodeFs>>,
+ node_resolver: Deferred<Arc<NodeResolver>>,
+ npm_api: Deferred<Arc<CliNpmRegistryApi>>,
+ npm_cache: Deferred<Arc<NpmCache>>,
+ npm_resolver: Deferred<Arc<CliNpmResolver>>,
+ npm_resolution: Deferred<Arc<NpmResolution>>,
+ package_json_deps_installer: Deferred<Arc<PackageJsonDepsInstaller>>,
+ text_only_progress_bar: Deferred<ProgressBar>,
+ type_checker: Deferred<Arc<TypeChecker>>,
+ cjs_resolutions: Deferred<Arc<CjsResolutionStore>>,
+}
+
+pub struct CliFactory {
+ maybe_sender:
+ RefCell<Option<tokio::sync::mpsc::UnboundedSender<Vec<PathBuf>>>>,
+ options: Arc<CliOptions>,
+ services: CliFactoryServices,
+}
+
+impl CliFactory {
+ pub async fn from_flags(flags: Flags) -> Result<Self, AnyError> {
+ CliFactoryBuilder::new().build_from_flags(flags).await
+ }
+
+ pub fn from_cli_options(options: Arc<CliOptions>) -> Self {
+ CliFactoryBuilder::new().build_from_cli_options(options)
+ }
+
+ pub fn cli_options(&self) -> &Arc<CliOptions> {
+ &self.options
+ }
+
+ pub fn deno_dir(&self) -> Result<&DenoDir, AnyError> {
+ self
+ .services
+ .dir
+ .get_or_try_init(|| self.options.resolve_deno_dir())
+ }
+
+ pub fn caches(&self) -> Result<&Arc<Caches>, AnyError> {
+ self.services.caches.get_or_try_init(|| {
+ let caches = Arc::new(Caches::new(self.deno_dir()?.clone()));
+ // Warm up the caches we know we'll likely need based on the CLI mode
+ match self.options.sub_command() {
+ DenoSubcommand::Run(_) => {
+ _ = caches.dep_analysis_db();
+ _ = caches.node_analysis_db();
+ }
+ DenoSubcommand::Check(_) => {
+ _ = caches.dep_analysis_db();
+ _ = caches.node_analysis_db();
+ _ = caches.type_checking_cache_db();
+ }
+ _ => {}
+ }
+ Ok(caches)
+ })
+ }
+
+ pub fn blob_store(&self) -> &BlobStore {
+ self.services.blob_store.get_or_init(BlobStore::default)
+ }
+
+ pub fn root_cert_store(&self) -> Result<&RootCertStore, AnyError> {
+ self
+ .services
+ .root_cert_store
+ .get_or_try_init(|| self.options.resolve_root_cert_store())
+ }
+
+ pub fn text_only_progress_bar(&self) -> &ProgressBar {
+ self
+ .services
+ .text_only_progress_bar
+ .get_or_init(|| ProgressBar::new(ProgressBarStyle::TextOnly))
+ }
+
+ pub fn http_client(&self) -> Result<&HttpClient, AnyError> {
+ self.services.http_client.get_or_try_init(|| {
+ HttpClient::new(
+ Some(self.root_cert_store()?.clone()),
+ self.options.unsafely_ignore_certificate_errors().clone(),
+ )
+ })
+ }
+
+ pub fn file_fetcher(&self) -> Result<&Arc<FileFetcher>, AnyError> {
+ self.services.file_fetcher.get_or_try_init(|| {
+ Ok(Arc::new(FileFetcher::new(
+ HttpCache::new(&self.deno_dir()?.deps_folder_path()),
+ self.options.cache_setting(),
+ !self.options.no_remote(),
+ self.http_client()?.clone(),
+ self.blob_store().clone(),
+ Some(self.text_only_progress_bar().clone()),
+ )))
+ })
+ }
+
+ pub fn maybe_lockfile(&self) -> &Option<Arc<Mutex<Lockfile>>> {
+ self
+ .services
+ .lockfile
+ .get_or_init(|| self.options.maybe_lockfile())
+ }
+
+ pub fn npm_cache(&self) -> Result<&Arc<NpmCache>, AnyError> {
+ self.services.npm_cache.get_or_try_init(|| {
+ Ok(Arc::new(NpmCache::new(
+ self.deno_dir()?.npm_folder_path(),
+ self.options.cache_setting(),
+ self.http_client()?.clone(),
+ self.text_only_progress_bar().clone(),
+ )))
+ })
+ }
+
+ pub fn npm_api(&self) -> Result<&Arc<CliNpmRegistryApi>, AnyError> {
+ self.services.npm_api.get_or_try_init(|| {
+ Ok(Arc::new(CliNpmRegistryApi::new(
+ CliNpmRegistryApi::default_url().to_owned(),
+ self.npm_cache()?.clone(),
+ self.http_client()?.clone(),
+ self.text_only_progress_bar().clone(),
+ )))
+ })
+ }
+
+ pub async fn npm_resolution(&self) -> Result<&Arc<NpmResolution>, AnyError> {
+ self
+ .services
+ .npm_resolution
+ .get_or_try_init_async(async {
+ let npm_api = self.npm_api()?;
+ Ok(Arc::new(NpmResolution::from_serialized(
+ npm_api.clone(),
+ self
+ .options
+ .resolve_npm_resolution_snapshot(npm_api)
+ .await?,
+ self.maybe_lockfile().as_ref().cloned(),
+ )))
+ })
+ .await
+ }
+
+ pub fn node_fs(&self) -> &Arc<dyn deno_node::NodeFs> {
+ self
+ .services
+ .node_fs
+ .get_or_init(|| Arc::new(deno_node::RealFs))
+ }
+
+ pub async fn npm_resolver(&self) -> Result<&Arc<CliNpmResolver>, AnyError> {
+ self
+ .services
+ .npm_resolver
+ .get_or_try_init_async(async {
+ let npm_resolution = self.npm_resolution().await?;
+ let npm_fs_resolver = create_npm_fs_resolver(
+ self.node_fs().clone(),
+ self.npm_cache()?.clone(),
+ self.text_only_progress_bar(),
+ CliNpmRegistryApi::default_url().to_owned(),
+ npm_resolution.clone(),
+ self.options.node_modules_dir_path(),
+ );
+ Ok(Arc::new(CliNpmResolver::new(
+ npm_resolution.clone(),
+ npm_fs_resolver,
+ self.maybe_lockfile().as_ref().cloned(),
+ )))
+ })
+ .await
+ }
+
+ pub async fn package_json_deps_installer(
+ &self,
+ ) -> Result<&Arc<PackageJsonDepsInstaller>, AnyError> {
+ self
+ .services
+ .package_json_deps_installer
+ .get_or_try_init_async(async {
+ let npm_api = self.npm_api()?;
+ let npm_resolution = self.npm_resolution().await?;
+ Ok(Arc::new(PackageJsonDepsInstaller::new(
+ npm_api.clone(),
+ npm_resolution.clone(),
+ self.options.maybe_package_json_deps(),
+ )))
+ })
+ .await
+ }
+
+ pub async fn maybe_import_map(
+ &self,
+ ) -> Result<&Option<Arc<ImportMap>>, AnyError> {
+ self
+ .services
+ .maybe_import_map
+ .get_or_try_init_async(async {
+ Ok(
+ self
+ .options
+ .resolve_import_map(self.file_fetcher()?)
+ .await?
+ .map(Arc::new),
+ )
+ })
+ .await
+ }
+
+ pub async fn resolver(&self) -> Result<&Arc<CliGraphResolver>, AnyError> {
+ self
+ .services
+ .resolver
+ .get_or_try_init_async(async {
+ Ok(Arc::new(CliGraphResolver::new(
+ self.options.to_maybe_jsx_import_source_config(),
+ self.maybe_import_map().await?.clone(),
+ self.options.no_npm(),
+ self.npm_api()?.clone(),
+ self.npm_resolution().await?.clone(),
+ self.package_json_deps_installer().await?.clone(),
+ )))
+ })
+ .await
+ }
+
+ pub fn file_watcher(&self) -> Result<&Arc<FileWatcher>, AnyError> {
+ self.services.file_watcher.get_or_try_init(|| {
+ let watcher = FileWatcher::new(
+ self.options.clone(),
+ self.cjs_resolutions().clone(),
+ self.graph_container().clone(),
+ self.maybe_file_watcher_reporter().clone(),
+ self.parsed_source_cache()?.clone(),
+ );
+ watcher.init_watcher();
+ Ok(Arc::new(watcher))
+ })
+ }
+
+ pub fn maybe_file_watcher_reporter(&self) -> &Option<FileWatcherReporter> {
+ let maybe_sender = self.maybe_sender.borrow_mut().take();
+ self
+ .services
+ .maybe_file_watcher_reporter
+ .get_or_init(|| maybe_sender.map(FileWatcherReporter::new))
+ }
+
+ pub fn emit_cache(&self) -> Result<&EmitCache, AnyError> {
+ self.services.emit_cache.get_or_try_init(|| {
+ Ok(EmitCache::new(self.deno_dir()?.gen_cache.clone()))
+ })
+ }
+
+ pub fn parsed_source_cache(
+ &self,
+ ) -> Result<&Arc<ParsedSourceCache>, AnyError> {
+ self.services.parsed_source_cache.get_or_try_init(|| {
+ Ok(Arc::new(ParsedSourceCache::new(
+ self.caches()?.dep_analysis_db(),
+ )))
+ })
+ }
+
+ pub fn emitter(&self) -> Result<&Arc<Emitter>, AnyError> {
+ self.services.emitter.get_or_try_init(|| {
+ let ts_config_result = self
+ .options
+ .resolve_ts_config_for_emit(TsConfigType::Emit)?;
+ if let Some(ignored_options) = ts_config_result.maybe_ignored_options {
+ warn!("{}", ignored_options);
+ }
+ let emit_options: deno_ast::EmitOptions =
+ ts_config_result.ts_config.into();
+ Ok(Arc::new(Emitter::new(
+ self.emit_cache()?.clone(),
+ self.parsed_source_cache()?.clone(),
+ emit_options,
+ )))
+ })
+ }
+
+ pub async fn node_resolver(&self) -> Result<&Arc<NodeResolver>, AnyError> {
+ self
+ .services
+ .node_resolver
+ .get_or_try_init_async(async {
+ Ok(Arc::new(NodeResolver::new(
+ self.node_fs().clone(),
+ self.npm_resolver().await?.clone(),
+ )))
+ })
+ .await
+ }
+
+ pub async fn node_code_translator(
+ &self,
+ ) -> Result<&Arc<CliNodeCodeTranslator>, AnyError> {
+ self
+ .services
+ .node_code_translator
+ .get_or_try_init_async(async {
+ let caches = self.caches()?;
+ let node_analysis_cache =
+ NodeAnalysisCache::new(caches.node_analysis_db());
+ let cjs_esm_analyzer = CliCjsEsmCodeAnalyzer::new(node_analysis_cache);
+
+ Ok(Arc::new(NodeCodeTranslator::new(
+ cjs_esm_analyzer,
+ self.node_fs().clone(),
+ self.node_resolver().await?.clone(),
+ self.npm_resolver().await?.clone(),
+ )))
+ })
+ .await
+ }
+
+ pub async fn type_checker(&self) -> Result<&Arc<TypeChecker>, AnyError> {
+ self
+ .services
+ .type_checker
+ .get_or_try_init_async(async {
+ Ok(Arc::new(TypeChecker::new(
+ self.caches()?.clone(),
+ self.options.clone(),
+ self.node_resolver().await?.clone(),
+ self.npm_resolver().await?.clone(),
+ )))
+ })
+ .await
+ }
+
+ pub async fn module_graph_builder(
+ &self,
+ ) -> Result<&Arc<ModuleGraphBuilder>, AnyError> {
+ self
+ .services
+ .module_graph_builder
+ .get_or_try_init_async(async {
+ Ok(Arc::new(ModuleGraphBuilder::new(
+ self.options.clone(),
+ self.resolver().await?.clone(),
+ self.npm_resolver().await?.clone(),
+ self.parsed_source_cache()?.clone(),
+ self.maybe_lockfile().clone(),
+ self.emit_cache()?.clone(),
+ self.file_fetcher()?.clone(),
+ self.type_checker().await?.clone(),
+ )))
+ })
+ .await
+ }
+
+ pub fn graph_container(&self) -> &Arc<ModuleGraphContainer> {
+ self.services.graph_container.get_or_init(Default::default)
+ }
+
+ pub fn maybe_inspector_server(&self) -> &Option<Arc<InspectorServer>> {
+ self
+ .services
+ .maybe_inspector_server
+ .get_or_init(|| self.options.resolve_inspector_server().map(Arc::new))
+ }
+
+ pub async fn module_load_preparer(
+ &self,
+ ) -> Result<&Arc<ModuleLoadPreparer>, AnyError> {
+ self
+ .services
+ .module_load_preparer
+ .get_or_try_init_async(async {
+ Ok(Arc::new(ModuleLoadPreparer::new(
+ self.options.clone(),
+ self.graph_container().clone(),
+ self.maybe_lockfile().clone(),
+ self.maybe_file_watcher_reporter().clone(),
+ self.module_graph_builder().await?.clone(),
+ self.parsed_source_cache()?.clone(),
+ self.text_only_progress_bar().clone(),
+ self.resolver().await?.clone(),
+ self.type_checker().await?.clone(),
+ )))
+ })
+ .await
+ }
+
+ pub fn cjs_resolutions(&self) -> &Arc<CjsResolutionStore> {
+ self.services.cjs_resolutions.get_or_init(Default::default)
+ }
+
+ /// Gets a function that can be used to create a CliMainWorkerFactory
+ /// for a file watcher.
+ pub async fn create_cli_main_worker_factory_func(
+ &self,
+ ) -> Result<Arc<dyn Fn() -> CliMainWorkerFactory>, AnyError> {
+ let emitter = self.emitter()?.clone();
+ let graph_container = self.graph_container().clone();
+ let module_load_preparer = self.module_load_preparer().await?.clone();
+ let parsed_source_cache = self.parsed_source_cache()?.clone();
+ let resolver = self.resolver().await?.clone();
+ let blob_store = self.blob_store().clone();
+ let cjs_resolutions = self.cjs_resolutions().clone();
+ let node_code_translator = self.node_code_translator().await?.clone();
+ let options = self.cli_options().clone();
+ let main_worker_options = self.create_cli_main_worker_options()?;
+ let node_fs = self.node_fs().clone();
+ let root_cert_store = self.root_cert_store()?.clone();
+ let node_resolver = self.node_resolver().await?.clone();
+ let npm_resolver = self.npm_resolver().await?.clone();
+ let maybe_inspector_server = self.maybe_inspector_server().clone();
+ Ok(Arc::new(move || {
+ CliMainWorkerFactory::new(
+ StorageKeyResolver::from_options(&options),
+ npm_resolver.clone(),
+ node_resolver.clone(),
+ Box::new(CliHasNodeSpecifierChecker(graph_container.clone())),
+ blob_store.clone(),
+ Box::new(CliModuleLoaderFactory::new(
+ &options,
+ emitter.clone(),
+ graph_container.clone(),
+ module_load_preparer.clone(),
+ parsed_source_cache.clone(),
+ resolver.clone(),
+ NpmModuleLoader::new(
+ cjs_resolutions.clone(),
+ node_code_translator.clone(),
+ node_resolver.clone(),
+ ),
+ )),
+ root_cert_store.clone(),
+ node_fs.clone(),
+ maybe_inspector_server.clone(),
+ main_worker_options.clone(),
+ )
+ }))
+ }
+
+ pub async fn create_cli_main_worker_factory(
+ &self,
+ ) -> Result<CliMainWorkerFactory, AnyError> {
+ let node_resolver = self.node_resolver().await?;
+ Ok(CliMainWorkerFactory::new(
+ StorageKeyResolver::from_options(&self.options),
+ self.npm_resolver().await?.clone(),
+ node_resolver.clone(),
+ Box::new(CliHasNodeSpecifierChecker(self.graph_container().clone())),
+ self.blob_store().clone(),
+ Box::new(CliModuleLoaderFactory::new(
+ &self.options,
+ self.emitter()?.clone(),
+ self.graph_container().clone(),
+ self.module_load_preparer().await?.clone(),
+ self.parsed_source_cache()?.clone(),
+ self.resolver().await?.clone(),
+ NpmModuleLoader::new(
+ self.cjs_resolutions().clone(),
+ self.node_code_translator().await?.clone(),
+ node_resolver.clone(),
+ ),
+ )),
+ self.root_cert_store()?.clone(),
+ self.node_fs().clone(),
+ self.maybe_inspector_server().clone(),
+ self.create_cli_main_worker_options()?,
+ ))
+ }
+
+ fn create_cli_main_worker_options(
+ &self,
+ ) -> Result<CliMainWorkerOptions, AnyError> {
+ Ok(CliMainWorkerOptions {
+ argv: self.options.argv().clone(),
+ debug: self
+ .options
+ .log_level()
+ .map(|l| l == log::Level::Debug)
+ .unwrap_or(false),
+ coverage_dir: self.options.coverage_dir(),
+ enable_testing_features: self.options.enable_testing_features(),
+ has_node_modules_dir: self.options.has_node_modules_dir(),
+ inspect_brk: self.options.inspect_brk().is_some(),
+ inspect_wait: self.options.inspect_wait().is_some(),
+ is_inspecting: self.options.is_inspecting(),
+ is_npm_main: self.options.is_npm_main(),
+ location: self.options.location_flag().clone(),
+ maybe_binary_npm_command_name: {
+ let mut maybe_binary_command_name = None;
+ if let DenoSubcommand::Run(flags) = self.options.sub_command() {
+ if let Ok(pkg_ref) = NpmPackageReqReference::from_str(&flags.script) {
+ // if the user ran a binary command, we'll need to set process.argv[0]
+ // to be the name of the binary command instead of deno
+ let binary_name = pkg_ref
+ .sub_path
+ .as_deref()
+ .unwrap_or(pkg_ref.req.name.as_str());
+ maybe_binary_command_name = Some(binary_name.to_string());
+ }
+ }
+ maybe_binary_command_name
+ },
+ origin_data_folder_path: Some(self.deno_dir()?.origin_data_folder_path()),
+ seed: self.options.seed(),
+ unsafely_ignore_certificate_errors: self
+ .options
+ .unsafely_ignore_certificate_errors()
+ .clone(),
+ unstable: self.options.unstable(),
+ })
+ }
+}
+
+struct CliHasNodeSpecifierChecker(Arc<ModuleGraphContainer>);
+
+impl HasNodeSpecifierChecker for CliHasNodeSpecifierChecker {
+ fn has_node_specifier(&self) -> bool {
+ self.0.graph().has_node_specifier
+ }
+}