summaryrefslogtreecommitdiff
path: root/cli/standalone/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to 'cli/standalone/mod.rs')
-rw-r--r--cli/standalone/mod.rs449
1 files changed, 275 insertions, 174 deletions
diff --git a/cli/standalone/mod.rs b/cli/standalone/mod.rs
index 24ba7c9db..cbd14db4f 100644
--- a/cli/standalone/mod.rs
+++ b/cli/standalone/mod.rs
@@ -10,7 +10,7 @@ use crate::args::get_root_cert_store;
use crate::args::npm_pkg_req_ref_to_binary_command;
use crate::args::CaData;
use crate::args::CacheSetting;
-use crate::args::PackageJsonDepsProvider;
+use crate::args::PackageJsonInstallDepsProvider;
use crate::args::StorageKeyResolver;
use crate::cache::Caches;
use crate::cache::DenoDirProvider;
@@ -25,7 +25,6 @@ use crate::npm::CliNpmResolverManagedSnapshotOption;
use crate::npm::NpmCacheDir;
use crate::resolver::CjsResolutionStore;
use crate::resolver::CliNodeResolver;
-use crate::resolver::MappedSpecifierResolver;
use crate::resolver::NpmModuleLoader;
use crate::util::progress_bar::ProgressBar;
use crate::util::progress_bar::ProgressBarStyle;
@@ -35,6 +34,10 @@ use crate::worker::CliMainWorkerOptions;
use crate::worker::ModuleLoaderAndSourceMapGetter;
use crate::worker::ModuleLoaderFactory;
use deno_ast::MediaType;
+use deno_config::package_json::PackageJsonDepValue;
+use deno_config::workspace::MappedResolution;
+use deno_config::workspace::MappedResolutionError;
+use deno_config::workspace::WorkspaceResolver;
use deno_core::anyhow::Context;
use deno_core::error::generic_error;
use deno_core::error::type_error;
@@ -48,6 +51,7 @@ use deno_core::ModuleSpecifier;
use deno_core::ModuleType;
use deno_core::RequestedModuleType;
use deno_core::ResolutionKind;
+use deno_npm::npm_rc::ResolvedNpmRc;
use deno_runtime::deno_fs;
use deno_runtime::deno_node::analyze::NodeCodeTranslator;
use deno_runtime::deno_node::NodeResolutionMode;
@@ -59,7 +63,9 @@ use deno_runtime::deno_tls::RootCertStoreProvider;
use deno_runtime::WorkerExecutionMode;
use deno_runtime::WorkerLogLevel;
use deno_semver::npm::NpmPackageReqReference;
+use eszip::EszipRelativeFileBaseUrl;
use import_map::parse_from_json;
+use std::borrow::Cow;
use std::rc::Rc;
use std::sync::Arc;
@@ -75,9 +81,43 @@ use self::binary::load_npm_vfs;
use self::binary::Metadata;
use self::file_system::DenoCompileFileSystem;
-struct SharedModuleLoaderState {
+struct WorkspaceEszipModule {
+ specifier: ModuleSpecifier,
+ inner: eszip::Module,
+}
+
+struct WorkspaceEszip {
eszip: eszip::EszipV2,
- mapped_specifier_resolver: MappedSpecifierResolver,
+ root_dir_url: ModuleSpecifier,
+}
+
+impl WorkspaceEszip {
+ pub fn get_module(
+ &self,
+ specifier: &ModuleSpecifier,
+ ) -> Option<WorkspaceEszipModule> {
+ if specifier.scheme() == "file" {
+ let specifier_key = EszipRelativeFileBaseUrl::new(&self.root_dir_url)
+ .specifier_key(specifier);
+ let module = self.eszip.get_module(&specifier_key)?;
+ let specifier = self.root_dir_url.join(&module.specifier).unwrap();
+ Some(WorkspaceEszipModule {
+ specifier,
+ inner: module,
+ })
+ } else {
+ let module = self.eszip.get_module(specifier.as_str())?;
+ Some(WorkspaceEszipModule {
+ specifier: ModuleSpecifier::parse(&module.specifier).unwrap(),
+ inner: module,
+ })
+ }
+ }
+}
+
+struct SharedModuleLoaderState {
+ eszip: WorkspaceEszip,
+ workspace_resolver: WorkspaceResolver,
node_resolver: Arc<CliNodeResolver>,
npm_module_loader: Arc<NpmModuleLoader>,
}
@@ -122,44 +162,92 @@ impl ModuleLoader for EmbeddedModuleLoader {
};
}
- let maybe_mapped = self
- .shared
- .mapped_specifier_resolver
- .resolve(specifier, &referrer)?
- .into_specifier();
-
- // npm specifier
- let specifier_text = maybe_mapped
- .as_ref()
- .map(|r| r.as_str())
- .unwrap_or(specifier);
- if let Ok(reference) = NpmPackageReqReference::from_str(specifier_text) {
- return self
- .shared
- .node_resolver
- .resolve_req_reference(
- &reference,
- &referrer,
- NodeResolutionMode::Execution,
- )
- .map(|res| res.into_url());
- }
+ let mapped_resolution =
+ self.shared.workspace_resolver.resolve(specifier, &referrer);
- let specifier = match maybe_mapped {
- Some(resolved) => resolved,
- None => deno_core::resolve_import(specifier, referrer.as_str())?,
- };
+ match mapped_resolution {
+ Ok(MappedResolution::PackageJson {
+ dep_result,
+ sub_path,
+ alias,
+ ..
+ }) => match dep_result.as_ref().map_err(|e| AnyError::from(e.clone()))? {
+ PackageJsonDepValue::Req(req) => self
+ .shared
+ .node_resolver
+ .resolve_req_with_sub_path(
+ req,
+ sub_path.as_deref(),
+ &referrer,
+ NodeResolutionMode::Execution,
+ )
+ .map(|res| res.into_url()),
+ PackageJsonDepValue::Workspace(version_req) => {
+ let pkg_folder = self
+ .shared
+ .workspace_resolver
+ .resolve_workspace_pkg_json_folder_for_pkg_json_dep(
+ alias,
+ version_req,
+ )?;
+ Ok(
+ self
+ .shared
+ .node_resolver
+ .resolve_package_sub_path_from_deno_module(
+ pkg_folder,
+ sub_path.as_deref(),
+ &referrer,
+ NodeResolutionMode::Execution,
+ )?
+ .into_url(),
+ )
+ }
+ },
+ Ok(MappedResolution::Normal(specifier))
+ | Ok(MappedResolution::ImportMap(specifier)) => {
+ if let Ok(reference) =
+ NpmPackageReqReference::from_specifier(&specifier)
+ {
+ return self
+ .shared
+ .node_resolver
+ .resolve_req_reference(
+ &reference,
+ &referrer,
+ NodeResolutionMode::Execution,
+ )
+ .map(|res| res.into_url());
+ }
+
+ if specifier.scheme() == "jsr" {
+ if let Some(module) = self.shared.eszip.get_module(&specifier) {
+ return Ok(module.specifier);
+ }
+ }
- if specifier.scheme() == "jsr" {
- if let Some(module) = self.shared.eszip.get_module(specifier.as_str()) {
- return Ok(ModuleSpecifier::parse(&module.specifier).unwrap());
+ self
+ .shared
+ .node_resolver
+ .handle_if_in_node_modules(specifier)
}
+ Err(err)
+ if err.is_unmapped_bare_specifier() && referrer.scheme() == "file" =>
+ {
+ // todo(dsherret): return a better error from node resolution so that
+ // we can more easily tell whether to surface it or not
+ let node_result = self.shared.node_resolver.resolve(
+ specifier,
+ &referrer,
+ NodeResolutionMode::Execution,
+ );
+ if let Ok(Some(res)) = node_result {
+ return Ok(res.into_url());
+ }
+ Err(err.into())
+ }
+ Err(err) => Err(err.into()),
}
-
- self
- .shared
- .node_resolver
- .handle_if_in_node_modules(specifier)
}
fn load(
@@ -215,27 +303,23 @@ impl ModuleLoader for EmbeddedModuleLoader {
);
}
- let Some(module) =
- self.shared.eszip.get_module(original_specifier.as_str())
- else {
+ let Some(module) = self.shared.eszip.get_module(original_specifier) else {
return deno_core::ModuleLoadResponse::Sync(Err(type_error(format!(
"Module not found: {}",
original_specifier
))));
};
let original_specifier = original_specifier.clone();
- let found_specifier =
- ModuleSpecifier::parse(&module.specifier).expect("invalid url in eszip");
deno_core::ModuleLoadResponse::Async(
async move {
- let code = module.source().await.ok_or_else(|| {
+ let code = module.inner.source().await.ok_or_else(|| {
type_error(format!("Module not found: {}", original_specifier))
})?;
let code = arc_u8_to_arc_str(code)
.map_err(|_| type_error("Module source is not utf-8"))?;
Ok(deno_core::ModuleSource::new_with_redirect(
- match module.kind {
+ match module.inner.kind {
eszip::ModuleKind::JavaScript => ModuleType::JavaScript,
eszip::ModuleKind::Json => ModuleType::Json,
eszip::ModuleKind::Jsonc => {
@@ -247,7 +331,7 @@ impl ModuleLoader for EmbeddedModuleLoader {
},
ModuleSourceCode::String(code.into()),
&original_specifier,
- &found_specifier,
+ &module.specifier,
None,
))
}
@@ -324,10 +408,10 @@ pub async fn run(
mut eszip: eszip::EszipV2,
metadata: Metadata,
) -> Result<i32, AnyError> {
- let main_module = &metadata.entrypoint;
let current_exe_path = std::env::current_exe().unwrap();
let current_exe_name =
current_exe_path.file_name().unwrap().to_string_lossy();
+ let maybe_cwd = std::env::current_dir().ok();
let deno_dir_provider = Arc::new(DenoDirProvider::new(None));
let root_cert_store_provider = Arc::new(StandaloneRootCertStoreProvider {
ca_stores: metadata.ca_stores,
@@ -341,119 +425,109 @@ pub async fn run(
));
// use a dummy npm registry url
let npm_registry_url = ModuleSpecifier::parse("https://localhost/").unwrap();
- let root_path = std::env::temp_dir()
- .join(format!("deno-compile-{}", current_exe_name))
- .join("node_modules");
- let npm_cache_dir =
- NpmCacheDir::new(root_path.clone(), vec![npm_registry_url.clone()]);
+ let root_path =
+ std::env::temp_dir().join(format!("deno-compile-{}", current_exe_name));
+ let root_dir_url = ModuleSpecifier::from_directory_path(&root_path).unwrap();
+ let main_module = root_dir_url.join(&metadata.entrypoint_key).unwrap();
+ let root_node_modules_path = root_path.join("node_modules");
+ let npm_cache_dir = NpmCacheDir::new(
+ root_node_modules_path.clone(),
+ vec![npm_registry_url.clone()],
+ );
let npm_global_cache_dir = npm_cache_dir.get_cache_location();
let cache_setting = CacheSetting::Only;
- let (package_json_deps_provider, fs, npm_resolver, maybe_vfs_root) =
- match metadata.node_modules {
- Some(binary::NodeModules::Managed {
- node_modules_dir,
- package_json_deps,
- }) => {
- // this will always have a snapshot
- let snapshot = eszip.take_npm_snapshot().unwrap();
- let vfs_root_dir_path = if node_modules_dir {
- root_path
- } else {
- npm_cache_dir.root_dir().to_owned()
- };
- let vfs = load_npm_vfs(vfs_root_dir_path.clone())
- .context("Failed to load npm vfs.")?;
- let maybe_node_modules_path = if node_modules_dir {
- Some(vfs.root().to_path_buf())
- } else {
- None
- };
- let package_json_deps_provider =
- Arc::new(PackageJsonDepsProvider::new(
- package_json_deps.map(|serialized| serialized.into_deps()),
- ));
- let fs = Arc::new(DenoCompileFileSystem::new(vfs))
- as Arc<dyn deno_fs::FileSystem>;
- let npm_resolver =
- create_cli_npm_resolver(CliNpmResolverCreateOptions::Managed(
- CliNpmResolverManagedCreateOptions {
- snapshot: CliNpmResolverManagedSnapshotOption::Specified(Some(
- snapshot,
- )),
- maybe_lockfile: None,
- fs: fs.clone(),
- http_client_provider: http_client_provider.clone(),
- npm_global_cache_dir,
- cache_setting,
- text_only_progress_bar: progress_bar,
- maybe_node_modules_path,
- package_json_deps_provider: package_json_deps_provider.clone(),
- npm_system_info: Default::default(),
- // Packages from different registries are already inlined in the ESZip,
- // so no need to create actual `.npmrc` configuration.
- npmrc: create_default_npmrc(),
- },
- ))
- .await?;
- (
- package_json_deps_provider,
- fs,
- npm_resolver,
- Some(vfs_root_dir_path),
- )
- }
- Some(binary::NodeModules::Byonm { package_json_deps }) => {
- let vfs_root_dir_path = root_path;
- let vfs = load_npm_vfs(vfs_root_dir_path.clone())
- .context("Failed to load npm vfs.")?;
- let node_modules_path = vfs.root().join("node_modules");
- let package_json_deps_provider =
- Arc::new(PackageJsonDepsProvider::new(
- package_json_deps.map(|serialized| serialized.into_deps()),
- ));
- let fs = Arc::new(DenoCompileFileSystem::new(vfs))
- as Arc<dyn deno_fs::FileSystem>;
- let npm_resolver =
- create_cli_npm_resolver(CliNpmResolverCreateOptions::Byonm(
- CliNpmResolverByonmCreateOptions {
- fs: fs.clone(),
- root_node_modules_dir: node_modules_path,
- },
- ))
- .await?;
- (
- package_json_deps_provider,
- fs,
- npm_resolver,
- Some(vfs_root_dir_path),
- )
- }
- None => {
- let package_json_deps_provider =
- Arc::new(PackageJsonDepsProvider::new(None));
- let fs = Arc::new(deno_fs::RealFs) as Arc<dyn deno_fs::FileSystem>;
- let npm_resolver =
- create_cli_npm_resolver(CliNpmResolverCreateOptions::Managed(
- CliNpmResolverManagedCreateOptions {
- snapshot: CliNpmResolverManagedSnapshotOption::Specified(None),
- maybe_lockfile: None,
- fs: fs.clone(),
- http_client_provider: http_client_provider.clone(),
- npm_global_cache_dir,
- cache_setting,
- text_only_progress_bar: progress_bar,
- maybe_node_modules_path: None,
- package_json_deps_provider: package_json_deps_provider.clone(),
- npm_system_info: Default::default(),
- // Packages from different registries are already inlined in the ESZip,
- // so no need to create actual `.npmrc` configuration.
- npmrc: create_default_npmrc(),
- },
- ))
- .await?;
- (package_json_deps_provider, fs, npm_resolver, None)
- }
- };
+ let (fs, npm_resolver, maybe_vfs_root) = match metadata.node_modules {
+ Some(binary::NodeModules::Managed { node_modules_dir }) => {
+ // this will always have a snapshot
+ let snapshot = eszip.take_npm_snapshot().unwrap();
+ let vfs_root_dir_path = if node_modules_dir.is_some() {
+ root_path.clone()
+ } else {
+ npm_cache_dir.root_dir().to_owned()
+ };
+ let vfs = load_npm_vfs(vfs_root_dir_path.clone())
+ .context("Failed to load npm vfs.")?;
+ let maybe_node_modules_path = node_modules_dir
+ .map(|node_modules_dir| vfs_root_dir_path.join(node_modules_dir));
+ let fs = Arc::new(DenoCompileFileSystem::new(vfs))
+ as Arc<dyn deno_fs::FileSystem>;
+ let npm_resolver =
+ create_cli_npm_resolver(CliNpmResolverCreateOptions::Managed(
+ CliNpmResolverManagedCreateOptions {
+ snapshot: CliNpmResolverManagedSnapshotOption::Specified(Some(
+ snapshot,
+ )),
+ maybe_lockfile: None,
+ fs: fs.clone(),
+ http_client_provider: http_client_provider.clone(),
+ npm_global_cache_dir,
+ cache_setting,
+ text_only_progress_bar: progress_bar,
+ maybe_node_modules_path,
+ npm_system_info: Default::default(),
+ package_json_deps_provider: Arc::new(
+ // this is only used for installing packages, which isn't necessary with deno compile
+ PackageJsonInstallDepsProvider::empty(),
+ ),
+ // create an npmrc that uses the fake npm_registry_url to resolve packages
+ npmrc: Arc::new(ResolvedNpmRc {
+ default_config: deno_npm::npm_rc::RegistryConfigWithUrl {
+ registry_url: npm_registry_url.clone(),
+ config: Default::default(),
+ },
+ scopes: Default::default(),
+ registry_configs: Default::default(),
+ }),
+ },
+ ))
+ .await?;
+ (fs, npm_resolver, Some(vfs_root_dir_path))
+ }
+ Some(binary::NodeModules::Byonm {
+ root_node_modules_dir,
+ }) => {
+ let vfs_root_dir_path = root_path.clone();
+ let vfs = load_npm_vfs(vfs_root_dir_path.clone())
+ .context("Failed to load vfs.")?;
+ let root_node_modules_dir = vfs.root().join(root_node_modules_dir);
+ let fs = Arc::new(DenoCompileFileSystem::new(vfs))
+ as Arc<dyn deno_fs::FileSystem>;
+ let npm_resolver = create_cli_npm_resolver(
+ CliNpmResolverCreateOptions::Byonm(CliNpmResolverByonmCreateOptions {
+ fs: fs.clone(),
+ root_node_modules_dir,
+ }),
+ )
+ .await?;
+ (fs, npm_resolver, Some(vfs_root_dir_path))
+ }
+ None => {
+ let fs = Arc::new(deno_fs::RealFs) as Arc<dyn deno_fs::FileSystem>;
+ let npm_resolver =
+ create_cli_npm_resolver(CliNpmResolverCreateOptions::Managed(
+ CliNpmResolverManagedCreateOptions {
+ snapshot: CliNpmResolverManagedSnapshotOption::Specified(None),
+ maybe_lockfile: None,
+ fs: fs.clone(),
+ http_client_provider: http_client_provider.clone(),
+ npm_global_cache_dir,
+ cache_setting,
+ text_only_progress_bar: progress_bar,
+ maybe_node_modules_path: None,
+ npm_system_info: Default::default(),
+ package_json_deps_provider: Arc::new(
+ // this is only used for installing packages, which isn't necessary with deno compile
+ PackageJsonInstallDepsProvider::empty(),
+ ),
+ // Packages from different registries are already inlined in the ESZip,
+ // so no need to create actual `.npmrc` configuration.
+ npmrc: create_default_npmrc(),
+ },
+ ))
+ .await?;
+ (fs, npm_resolver, None)
+ }
+ };
let has_node_modules_dir = npm_resolver.root_node_modules_path().is_some();
let node_resolver = Arc::new(NodeResolver::new(
@@ -471,9 +545,42 @@ pub async fn run(
node_resolver.clone(),
npm_resolver.clone().into_npm_resolver(),
));
- let maybe_import_map = metadata.maybe_import_map.map(|(base, source)| {
- Arc::new(parse_from_json(base, &source).unwrap().import_map)
- });
+ let workspace_resolver = {
+ let import_map = match metadata.workspace_resolver.import_map {
+ Some(import_map) => Some(
+ import_map::parse_from_json_with_options(
+ root_dir_url.join(&import_map.specifier).unwrap(),
+ &import_map.json,
+ import_map::ImportMapOptions {
+ address_hook: None,
+ expand_imports: true,
+ },
+ )?
+ .import_map,
+ ),
+ None => None,
+ };
+ let pkg_jsons = metadata
+ .workspace_resolver
+ .package_jsons
+ .into_iter()
+ .map(|(relative_path, json)| {
+ let path = root_dir_url
+ .join(&relative_path)
+ .unwrap()
+ .to_file_path()
+ .unwrap();
+ let pkg_json =
+ deno_config::package_json::PackageJson::load_from_value(path, json);
+ Arc::new(pkg_json)
+ })
+ .collect();
+ WorkspaceResolver::new_raw(
+ import_map,
+ pkg_jsons,
+ metadata.workspace_resolver.pkg_json_resolution,
+ )
+ };
let cli_node_resolver = Arc::new(CliNodeResolver::new(
Some(cjs_resolutions.clone()),
fs.clone(),
@@ -482,11 +589,11 @@ pub async fn run(
));
let module_loader_factory = StandaloneModuleLoaderFactory {
shared: Arc::new(SharedModuleLoaderState {
- eszip,
- mapped_specifier_resolver: MappedSpecifierResolver::new(
- maybe_import_map.clone(),
- package_json_deps_provider.clone(),
- ),
+ eszip: WorkspaceEszip {
+ eszip,
+ root_dir_url,
+ },
+ workspace_resolver,
node_resolver: cli_node_resolver.clone(),
npm_module_loader: Arc::new(NpmModuleLoader::new(
cjs_resolutions,
@@ -498,7 +605,6 @@ pub async fn run(
};
let permissions = {
- let maybe_cwd = std::env::current_dir().ok();
let mut permissions =
metadata.permissions.to_options(maybe_cwd.as_deref())?;
// if running with an npm vfs, grant read access to it
@@ -561,7 +667,7 @@ pub async fn run(
is_npm_main: main_module.scheme() == "npm",
skip_op_registration: true,
location: metadata.location,
- argv0: NpmPackageReqReference::from_specifier(main_module)
+ argv0: NpmPackageReqReference::from_specifier(&main_module)
.ok()
.map(|req_ref| npm_pkg_req_ref_to_binary_command(&req_ref))
.or(std::env::args().next()),
@@ -571,7 +677,6 @@ pub async fn run(
unsafely_ignore_certificate_errors: metadata
.unsafely_ignore_certificate_errors,
unstable: metadata.unstable_config.legacy_flag_enabled,
- maybe_root_package_json_deps: package_json_deps_provider.deps().cloned(),
create_hmr_runner: None,
create_coverage_collector: None,
},
@@ -592,11 +697,7 @@ pub async fn run(
deno_core::JsRuntime::init_platform(None);
let mut worker = worker_factory
- .create_main_worker(
- WorkerExecutionMode::Run,
- main_module.clone(),
- permissions,
- )
+ .create_main_worker(WorkerExecutionMode::Run, main_module, permissions)
.await?;
let exit_code = worker.run().await?;