mirror of
https://github.com/denoland/deno.git
synced 2025-03-03 17:34:47 -05:00
refactor(ext/node): allow injecting NodeFs
from CLI (#18829)
This allows providing a `NodeFs` as part of the `WorkerOptions`.
This commit is contained in:
parent
bb74e75a04
commit
aa286fdecb
24 changed files with 1631 additions and 1687 deletions
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
use deno_core::snapshot_util::*;
|
use deno_core::snapshot_util::*;
|
||||||
use deno_core::Extension;
|
use deno_core::Extension;
|
||||||
|
@ -361,7 +362,10 @@ fn create_cli_snapshot(snapshot_path: PathBuf) {
|
||||||
deno_http::deno_http::init_ops(),
|
deno_http::deno_http::init_ops(),
|
||||||
deno_io::deno_io::init_ops(Default::default()),
|
deno_io::deno_io::init_ops(Default::default()),
|
||||||
deno_fs::deno_fs::init_ops::<_, PermissionsContainer>(false, StdFs),
|
deno_fs::deno_fs::init_ops::<_, PermissionsContainer>(false, StdFs),
|
||||||
deno_node::deno_node::init_ops::<deno_runtime::RuntimeNodeEnv>(None),
|
deno_node::deno_node::init_ops::<deno_runtime::RuntimeNodeEnv>(
|
||||||
|
None,
|
||||||
|
Some(Arc::new(deno_node::RealFs)),
|
||||||
|
),
|
||||||
cli::init_ops_and_esm(), // NOTE: This needs to be init_ops_and_esm!
|
cli::init_ops_and_esm(), // NOTE: This needs to be init_ops_and_esm!
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,6 @@ use crate::file_fetcher::get_source_from_bytes;
|
||||||
use crate::file_fetcher::map_content_type;
|
use crate::file_fetcher::map_content_type;
|
||||||
use crate::file_fetcher::SUPPORTED_SCHEMES;
|
use crate::file_fetcher::SUPPORTED_SCHEMES;
|
||||||
use crate::lsp::logging::lsp_warn;
|
use crate::lsp::logging::lsp_warn;
|
||||||
use crate::node::CliNodeResolver;
|
|
||||||
use crate::npm::CliNpmRegistryApi;
|
use crate::npm::CliNpmRegistryApi;
|
||||||
use crate::npm::NpmResolution;
|
use crate::npm::NpmResolution;
|
||||||
use crate::npm::PackageJsonDepsInstaller;
|
use crate::npm::PackageJsonDepsInstaller;
|
||||||
|
@ -39,8 +38,8 @@ use deno_graph::Resolution;
|
||||||
use deno_runtime::deno_node;
|
use deno_runtime::deno_node;
|
||||||
use deno_runtime::deno_node::NodeResolution;
|
use deno_runtime::deno_node::NodeResolution;
|
||||||
use deno_runtime::deno_node::NodeResolutionMode;
|
use deno_runtime::deno_node::NodeResolutionMode;
|
||||||
|
use deno_runtime::deno_node::NodeResolver;
|
||||||
use deno_runtime::deno_node::PackageJson;
|
use deno_runtime::deno_node::PackageJson;
|
||||||
use deno_runtime::deno_node::RealFs;
|
|
||||||
use deno_runtime::permissions::PermissionsContainer;
|
use deno_runtime::permissions::PermissionsContainer;
|
||||||
use deno_semver::npm::NpmPackageReq;
|
use deno_semver::npm::NpmPackageReq;
|
||||||
use deno_semver::npm::NpmPackageReqReference;
|
use deno_semver::npm::NpmPackageReqReference;
|
||||||
|
@ -1057,7 +1056,7 @@ impl Documents {
|
||||||
&self,
|
&self,
|
||||||
specifiers: Vec<String>,
|
specifiers: Vec<String>,
|
||||||
referrer_doc: &AssetOrDocument,
|
referrer_doc: &AssetOrDocument,
|
||||||
maybe_node_resolver: Option<&Arc<CliNodeResolver>>,
|
maybe_node_resolver: Option<&Arc<NodeResolver>>,
|
||||||
) -> Vec<Option<(ModuleSpecifier, MediaType)>> {
|
) -> Vec<Option<(ModuleSpecifier, MediaType)>> {
|
||||||
let referrer = referrer_doc.specifier();
|
let referrer = referrer_doc.specifier();
|
||||||
let dependencies = match referrer_doc {
|
let dependencies = match referrer_doc {
|
||||||
|
@ -1071,7 +1070,7 @@ impl Documents {
|
||||||
// we're in an npm package, so use node resolution
|
// we're in an npm package, so use node resolution
|
||||||
results.push(Some(NodeResolution::into_specifier_and_media_type(
|
results.push(Some(NodeResolution::into_specifier_and_media_type(
|
||||||
node_resolver
|
node_resolver
|
||||||
.resolve::<RealFs>(
|
.resolve(
|
||||||
&specifier,
|
&specifier,
|
||||||
referrer,
|
referrer,
|
||||||
NodeResolutionMode::Types,
|
NodeResolutionMode::Types,
|
||||||
|
@ -1419,7 +1418,7 @@ impl Documents {
|
||||||
fn resolve_dependency(
|
fn resolve_dependency(
|
||||||
&self,
|
&self,
|
||||||
specifier: &ModuleSpecifier,
|
specifier: &ModuleSpecifier,
|
||||||
maybe_node_resolver: Option<&Arc<CliNodeResolver>>,
|
maybe_node_resolver: Option<&Arc<NodeResolver>>,
|
||||||
) -> Option<(ModuleSpecifier, MediaType)> {
|
) -> Option<(ModuleSpecifier, MediaType)> {
|
||||||
if let Ok(npm_ref) = NpmPackageReqReference::from_specifier(specifier) {
|
if let Ok(npm_ref) = NpmPackageReqReference::from_specifier(specifier) {
|
||||||
return node_resolve_npm_req_ref(npm_ref, maybe_node_resolver);
|
return node_resolve_npm_req_ref(npm_ref, maybe_node_resolver);
|
||||||
|
@ -1454,12 +1453,12 @@ impl Documents {
|
||||||
|
|
||||||
fn node_resolve_npm_req_ref(
|
fn node_resolve_npm_req_ref(
|
||||||
npm_req_ref: NpmPackageReqReference,
|
npm_req_ref: NpmPackageReqReference,
|
||||||
maybe_node_resolver: Option<&Arc<CliNodeResolver>>,
|
maybe_node_resolver: Option<&Arc<NodeResolver>>,
|
||||||
) -> Option<(ModuleSpecifier, MediaType)> {
|
) -> Option<(ModuleSpecifier, MediaType)> {
|
||||||
maybe_node_resolver.map(|node_resolver| {
|
maybe_node_resolver.map(|node_resolver| {
|
||||||
NodeResolution::into_specifier_and_media_type(
|
NodeResolution::into_specifier_and_media_type(
|
||||||
node_resolver
|
node_resolver
|
||||||
.resolve_npm_req_reference::<RealFs>(
|
.resolve_npm_req_reference(
|
||||||
&npm_req_ref,
|
&npm_req_ref,
|
||||||
NodeResolutionMode::Types,
|
NodeResolutionMode::Types,
|
||||||
&mut PermissionsContainer::allow_all(),
|
&mut PermissionsContainer::allow_all(),
|
||||||
|
|
|
@ -9,6 +9,7 @@ use deno_core::serde_json;
|
||||||
use deno_core::serde_json::json;
|
use deno_core::serde_json::json;
|
||||||
use deno_core::serde_json::Value;
|
use deno_core::serde_json::Value;
|
||||||
use deno_core::ModuleSpecifier;
|
use deno_core::ModuleSpecifier;
|
||||||
|
use deno_runtime::deno_node;
|
||||||
use deno_runtime::deno_node::NodeResolver;
|
use deno_runtime::deno_node::NodeResolver;
|
||||||
use deno_runtime::deno_node::PackageJson;
|
use deno_runtime::deno_node::PackageJson;
|
||||||
use deno_runtime::deno_web::BlobStore;
|
use deno_runtime::deno_web::BlobStore;
|
||||||
|
@ -79,7 +80,6 @@ use crate::file_fetcher::FileFetcher;
|
||||||
use crate::graph_util;
|
use crate::graph_util;
|
||||||
use crate::http_util::HttpClient;
|
use crate::http_util::HttpClient;
|
||||||
use crate::lsp::urls::LspUrlKind;
|
use crate::lsp::urls::LspUrlKind;
|
||||||
use crate::node::CliNodeResolver;
|
|
||||||
use crate::npm::create_npm_fs_resolver;
|
use crate::npm::create_npm_fs_resolver;
|
||||||
use crate::npm::CliNpmRegistryApi;
|
use crate::npm::CliNpmRegistryApi;
|
||||||
use crate::npm::CliNpmResolver;
|
use crate::npm::CliNpmResolver;
|
||||||
|
@ -103,7 +103,7 @@ pub struct StateSnapshot {
|
||||||
pub cache_metadata: cache::CacheMetadata,
|
pub cache_metadata: cache::CacheMetadata,
|
||||||
pub documents: Documents,
|
pub documents: Documents,
|
||||||
pub maybe_import_map: Option<Arc<ImportMap>>,
|
pub maybe_import_map: Option<Arc<ImportMap>>,
|
||||||
pub maybe_node_resolver: Option<Arc<CliNodeResolver>>,
|
pub maybe_node_resolver: Option<Arc<NodeResolver>>,
|
||||||
pub maybe_npm_resolver: Option<Arc<CliNpmResolver>>,
|
pub maybe_npm_resolver: Option<Arc<CliNpmResolver>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -449,6 +449,7 @@ fn create_lsp_structs(
|
||||||
let resolution =
|
let resolution =
|
||||||
Arc::new(NpmResolution::from_serialized(api.clone(), None, None));
|
Arc::new(NpmResolution::from_serialized(api.clone(), None, None));
|
||||||
let fs_resolver = create_npm_fs_resolver(
|
let fs_resolver = create_npm_fs_resolver(
|
||||||
|
Arc::new(deno_node::RealFs),
|
||||||
npm_cache.clone(),
|
npm_cache.clone(),
|
||||||
&progress_bar,
|
&progress_bar,
|
||||||
registry_url.clone(),
|
registry_url.clone(),
|
||||||
|
@ -700,9 +701,11 @@ impl Inner {
|
||||||
self.npm_resolution.snapshot(),
|
self.npm_resolution.snapshot(),
|
||||||
None,
|
None,
|
||||||
));
|
));
|
||||||
|
let node_fs = Arc::new(deno_node::RealFs);
|
||||||
let npm_resolver = Arc::new(CliNpmResolver::new(
|
let npm_resolver = Arc::new(CliNpmResolver::new(
|
||||||
npm_resolution.clone(),
|
npm_resolution.clone(),
|
||||||
create_npm_fs_resolver(
|
create_npm_fs_resolver(
|
||||||
|
node_fs.clone(),
|
||||||
self.npm_cache.clone(),
|
self.npm_cache.clone(),
|
||||||
&ProgressBar::new(ProgressBarStyle::TextOnly),
|
&ProgressBar::new(ProgressBarStyle::TextOnly),
|
||||||
self.npm_api.base_url().clone(),
|
self.npm_api.base_url().clone(),
|
||||||
|
@ -711,7 +714,8 @@ impl Inner {
|
||||||
),
|
),
|
||||||
None,
|
None,
|
||||||
));
|
));
|
||||||
let node_resolver = Arc::new(NodeResolver::new(npm_resolver.clone()));
|
let node_resolver =
|
||||||
|
Arc::new(NodeResolver::new(node_fs, npm_resolver.clone()));
|
||||||
Arc::new(StateSnapshot {
|
Arc::new(StateSnapshot {
|
||||||
assets: self.assets.snapshot(),
|
assets: self.assets.snapshot(),
|
||||||
cache_metadata: self.cache_metadata.clone(),
|
cache_metadata: self.cache_metadata.clone(),
|
||||||
|
|
|
@ -12,7 +12,6 @@ use crate::graph_util::ModuleGraphBuilder;
|
||||||
use crate::graph_util::ModuleGraphContainer;
|
use crate::graph_util::ModuleGraphContainer;
|
||||||
use crate::node;
|
use crate::node;
|
||||||
use crate::node::CliNodeCodeTranslator;
|
use crate::node::CliNodeCodeTranslator;
|
||||||
use crate::node::CliNodeResolver;
|
|
||||||
use crate::proc_state::CjsResolutionStore;
|
use crate::proc_state::CjsResolutionStore;
|
||||||
use crate::proc_state::FileWatcherReporter;
|
use crate::proc_state::FileWatcherReporter;
|
||||||
use crate::proc_state::ProcState;
|
use crate::proc_state::ProcState;
|
||||||
|
@ -51,7 +50,7 @@ use deno_lockfile::Lockfile;
|
||||||
use deno_runtime::deno_node;
|
use deno_runtime::deno_node;
|
||||||
use deno_runtime::deno_node::NodeResolution;
|
use deno_runtime::deno_node::NodeResolution;
|
||||||
use deno_runtime::deno_node::NodeResolutionMode;
|
use deno_runtime::deno_node::NodeResolutionMode;
|
||||||
use deno_runtime::deno_node::RealFs;
|
use deno_runtime::deno_node::NodeResolver;
|
||||||
use deno_runtime::permissions::PermissionsContainer;
|
use deno_runtime::permissions::PermissionsContainer;
|
||||||
use deno_semver::npm::NpmPackageReqReference;
|
use deno_semver::npm::NpmPackageReqReference;
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
|
@ -244,7 +243,7 @@ pub struct CliModuleLoader {
|
||||||
graph_container: Arc<ModuleGraphContainer>,
|
graph_container: Arc<ModuleGraphContainer>,
|
||||||
module_load_preparer: Arc<ModuleLoadPreparer>,
|
module_load_preparer: Arc<ModuleLoadPreparer>,
|
||||||
node_code_translator: Arc<CliNodeCodeTranslator>,
|
node_code_translator: Arc<CliNodeCodeTranslator>,
|
||||||
node_resolver: Arc<CliNodeResolver>,
|
node_resolver: Arc<NodeResolver>,
|
||||||
parsed_source_cache: Arc<ParsedSourceCache>,
|
parsed_source_cache: Arc<ParsedSourceCache>,
|
||||||
resolver: Arc<CliGraphResolver>,
|
resolver: Arc<CliGraphResolver>,
|
||||||
}
|
}
|
||||||
|
@ -387,7 +386,7 @@ impl CliModuleLoader {
|
||||||
self.root_permissions.clone()
|
self.root_permissions.clone()
|
||||||
};
|
};
|
||||||
// translate cjs to esm if it's cjs and inject node globals
|
// translate cjs to esm if it's cjs and inject node globals
|
||||||
self.node_code_translator.translate_cjs_to_esm::<RealFs>(
|
self.node_code_translator.translate_cjs_to_esm(
|
||||||
specifier,
|
specifier,
|
||||||
&code,
|
&code,
|
||||||
&mut permissions,
|
&mut permissions,
|
||||||
|
@ -466,7 +465,7 @@ impl ModuleLoader for CliModuleLoader {
|
||||||
if self.node_resolver.in_npm_package(referrer) {
|
if self.node_resolver.in_npm_package(referrer) {
|
||||||
// we're in an npm package, so use node resolution
|
// we're in an npm package, so use node resolution
|
||||||
return self
|
return self
|
||||||
.handle_node_resolve_result(self.node_resolver.resolve::<RealFs>(
|
.handle_node_resolve_result(self.node_resolver.resolve(
|
||||||
specifier,
|
specifier,
|
||||||
referrer,
|
referrer,
|
||||||
NodeResolutionMode::Execution,
|
NodeResolutionMode::Execution,
|
||||||
|
@ -492,7 +491,7 @@ impl ModuleLoader for CliModuleLoader {
|
||||||
return match graph.get(specifier) {
|
return match graph.get(specifier) {
|
||||||
Some(Module::Npm(module)) => self
|
Some(Module::Npm(module)) => self
|
||||||
.handle_node_resolve_result(
|
.handle_node_resolve_result(
|
||||||
self.node_resolver.resolve_npm_reference::<RealFs>(
|
self.node_resolver.resolve_npm_reference(
|
||||||
&module.nv_reference,
|
&module.nv_reference,
|
||||||
NodeResolutionMode::Execution,
|
NodeResolutionMode::Execution,
|
||||||
&mut permissions,
|
&mut permissions,
|
||||||
|
@ -554,7 +553,7 @@ impl ModuleLoader for CliModuleLoader {
|
||||||
{
|
{
|
||||||
return self
|
return self
|
||||||
.handle_node_resolve_result(
|
.handle_node_resolve_result(
|
||||||
self.node_resolver.resolve_npm_req_reference::<RealFs>(
|
self.node_resolver.resolve_npm_req_reference(
|
||||||
&reference,
|
&reference,
|
||||||
NodeResolutionMode::Execution,
|
NodeResolutionMode::Execution,
|
||||||
&mut permissions,
|
&mut permissions,
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
|
||||||
|
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
use std::sync::Arc;
|
|
||||||
|
|
||||||
use deno_ast::swc::common::SyntaxContext;
|
use deno_ast::swc::common::SyntaxContext;
|
||||||
use deno_ast::view::Node;
|
use deno_ast::view::Node;
|
||||||
|
@ -15,15 +14,11 @@ use deno_core::error::AnyError;
|
||||||
use deno_runtime::deno_node::analyze::CjsAnalysis as ExtNodeCjsAnalysis;
|
use deno_runtime::deno_node::analyze::CjsAnalysis as ExtNodeCjsAnalysis;
|
||||||
use deno_runtime::deno_node::analyze::CjsEsmCodeAnalyzer;
|
use deno_runtime::deno_node::analyze::CjsEsmCodeAnalyzer;
|
||||||
use deno_runtime::deno_node::analyze::NodeCodeTranslator;
|
use deno_runtime::deno_node::analyze::NodeCodeTranslator;
|
||||||
use deno_runtime::deno_node::NodeResolver;
|
|
||||||
|
|
||||||
use crate::cache::NodeAnalysisCache;
|
use crate::cache::NodeAnalysisCache;
|
||||||
use crate::npm::CliNpmResolver;
|
|
||||||
use crate::util::fs::canonicalize_path_maybe_not_exists;
|
use crate::util::fs::canonicalize_path_maybe_not_exists;
|
||||||
|
|
||||||
pub type CliNodeCodeTranslator =
|
pub type CliNodeCodeTranslator = NodeCodeTranslator<CliCjsEsmCodeAnalyzer>;
|
||||||
NodeCodeTranslator<CliCjsEsmCodeAnalyzer, Arc<CliNpmResolver>>;
|
|
||||||
pub type CliNodeResolver = NodeResolver<Arc<CliNpmResolver>>;
|
|
||||||
|
|
||||||
/// Resolves a specifier that is pointing into a node_modules folder.
|
/// Resolves a specifier that is pointing into a node_modules folder.
|
||||||
///
|
///
|
||||||
|
|
|
@ -23,6 +23,7 @@ use deno_npm::resolution::NpmResolutionSnapshot;
|
||||||
use deno_npm::NpmPackageCacheFolderId;
|
use deno_npm::NpmPackageCacheFolderId;
|
||||||
use deno_npm::NpmPackageId;
|
use deno_npm::NpmPackageId;
|
||||||
use deno_runtime::deno_core::futures;
|
use deno_runtime::deno_core::futures;
|
||||||
|
use deno_runtime::deno_node::NodeFs;
|
||||||
use deno_runtime::deno_node::NodePermissions;
|
use deno_runtime::deno_node::NodePermissions;
|
||||||
use deno_runtime::deno_node::NodeResolutionMode;
|
use deno_runtime::deno_node::NodeResolutionMode;
|
||||||
use deno_runtime::deno_node::PackageJson;
|
use deno_runtime::deno_node::PackageJson;
|
||||||
|
@ -43,6 +44,7 @@ use super::common::NpmPackageFsResolver;
|
||||||
/// and resolves packages from it.
|
/// and resolves packages from it.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct LocalNpmPackageResolver {
|
pub struct LocalNpmPackageResolver {
|
||||||
|
fs: Arc<dyn NodeFs>,
|
||||||
cache: Arc<NpmCache>,
|
cache: Arc<NpmCache>,
|
||||||
progress_bar: ProgressBar,
|
progress_bar: ProgressBar,
|
||||||
resolution: Arc<NpmResolution>,
|
resolution: Arc<NpmResolution>,
|
||||||
|
@ -53,6 +55,7 @@ pub struct LocalNpmPackageResolver {
|
||||||
|
|
||||||
impl LocalNpmPackageResolver {
|
impl LocalNpmPackageResolver {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
|
fs: Arc<dyn NodeFs>,
|
||||||
cache: Arc<NpmCache>,
|
cache: Arc<NpmCache>,
|
||||||
progress_bar: ProgressBar,
|
progress_bar: ProgressBar,
|
||||||
registry_url: Url,
|
registry_url: Url,
|
||||||
|
@ -60,6 +63,7 @@ impl LocalNpmPackageResolver {
|
||||||
resolution: Arc<NpmResolution>,
|
resolution: Arc<NpmResolution>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
fs,
|
||||||
cache,
|
cache,
|
||||||
progress_bar,
|
progress_bar,
|
||||||
resolution,
|
resolution,
|
||||||
|
@ -149,9 +153,10 @@ impl NpmPackageFsResolver for LocalNpmPackageResolver {
|
||||||
if sub_dir.is_dir() {
|
if sub_dir.is_dir() {
|
||||||
// if doing types resolution, only resolve the package if it specifies a types property
|
// if doing types resolution, only resolve the package if it specifies a types property
|
||||||
if mode.is_types() && !name.starts_with("@types/") {
|
if mode.is_types() && !name.starts_with("@types/") {
|
||||||
let package_json = PackageJson::load_skip_read_permission::<
|
let package_json = PackageJson::load_skip_read_permission(
|
||||||
deno_runtime::deno_node::RealFs,
|
&*self.fs,
|
||||||
>(sub_dir.join("package.json"))?;
|
sub_dir.join("package.json"),
|
||||||
|
)?;
|
||||||
if package_json.types.is_some() {
|
if package_json.types.is_some() {
|
||||||
return Ok(sub_dir);
|
return Ok(sub_dir);
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,7 @@ use deno_npm::resolution::NpmResolutionSnapshot;
|
||||||
use deno_npm::resolution::PackageReqNotFoundError;
|
use deno_npm::resolution::PackageReqNotFoundError;
|
||||||
use deno_npm::resolution::SerializedNpmResolutionSnapshot;
|
use deno_npm::resolution::SerializedNpmResolutionSnapshot;
|
||||||
use deno_npm::NpmPackageId;
|
use deno_npm::NpmPackageId;
|
||||||
|
use deno_runtime::deno_node;
|
||||||
use deno_runtime::deno_node::NodePermissions;
|
use deno_runtime::deno_node::NodePermissions;
|
||||||
use deno_runtime::deno_node::NodeResolutionMode;
|
use deno_runtime::deno_node::NodeResolutionMode;
|
||||||
use deno_runtime::deno_node::NpmResolver;
|
use deno_runtime::deno_node::NpmResolver;
|
||||||
|
@ -269,6 +270,7 @@ impl NpmResolver for CliNpmResolver {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create_npm_fs_resolver(
|
pub fn create_npm_fs_resolver(
|
||||||
|
fs: Arc<dyn deno_node::NodeFs>,
|
||||||
cache: Arc<NpmCache>,
|
cache: Arc<NpmCache>,
|
||||||
progress_bar: &ProgressBar,
|
progress_bar: &ProgressBar,
|
||||||
registry_url: Url,
|
registry_url: Url,
|
||||||
|
@ -277,6 +279,7 @@ pub fn create_npm_fs_resolver(
|
||||||
) -> Arc<dyn NpmPackageFsResolver> {
|
) -> Arc<dyn NpmPackageFsResolver> {
|
||||||
match maybe_node_modules_path {
|
match maybe_node_modules_path {
|
||||||
Some(node_modules_folder) => Arc::new(LocalNpmPackageResolver::new(
|
Some(node_modules_folder) => Arc::new(LocalNpmPackageResolver::new(
|
||||||
|
fs,
|
||||||
cache,
|
cache,
|
||||||
progress_bar.clone(),
|
progress_bar.clone(),
|
||||||
registry_url,
|
registry_url,
|
||||||
|
|
|
@ -19,7 +19,6 @@ use crate::http_util::HttpClient;
|
||||||
use crate::module_loader::ModuleLoadPreparer;
|
use crate::module_loader::ModuleLoadPreparer;
|
||||||
use crate::node::CliCjsEsmCodeAnalyzer;
|
use crate::node::CliCjsEsmCodeAnalyzer;
|
||||||
use crate::node::CliNodeCodeTranslator;
|
use crate::node::CliNodeCodeTranslator;
|
||||||
use crate::node::CliNodeResolver;
|
|
||||||
use crate::npm::create_npm_fs_resolver;
|
use crate::npm::create_npm_fs_resolver;
|
||||||
use crate::npm::CliNpmRegistryApi;
|
use crate::npm::CliNpmRegistryApi;
|
||||||
use crate::npm::CliNpmResolver;
|
use crate::npm::CliNpmResolver;
|
||||||
|
@ -38,6 +37,7 @@ use deno_core::ModuleSpecifier;
|
||||||
use deno_core::SharedArrayBufferStore;
|
use deno_core::SharedArrayBufferStore;
|
||||||
|
|
||||||
use deno_runtime::deno_broadcast_channel::InMemoryBroadcastChannel;
|
use deno_runtime::deno_broadcast_channel::InMemoryBroadcastChannel;
|
||||||
|
use deno_runtime::deno_node;
|
||||||
use deno_runtime::deno_node::analyze::NodeCodeTranslator;
|
use deno_runtime::deno_node::analyze::NodeCodeTranslator;
|
||||||
use deno_runtime::deno_node::NodeResolver;
|
use deno_runtime::deno_node::NodeResolver;
|
||||||
use deno_runtime::deno_tls::rustls::RootCertStore;
|
use deno_runtime::deno_tls::rustls::RootCertStore;
|
||||||
|
@ -79,7 +79,8 @@ pub struct Inner {
|
||||||
pub module_graph_builder: Arc<ModuleGraphBuilder>,
|
pub module_graph_builder: Arc<ModuleGraphBuilder>,
|
||||||
pub module_load_preparer: Arc<ModuleLoadPreparer>,
|
pub module_load_preparer: Arc<ModuleLoadPreparer>,
|
||||||
pub node_code_translator: Arc<CliNodeCodeTranslator>,
|
pub node_code_translator: Arc<CliNodeCodeTranslator>,
|
||||||
pub node_resolver: Arc<CliNodeResolver>,
|
pub node_fs: Arc<dyn deno_node::NodeFs>,
|
||||||
|
pub node_resolver: Arc<NodeResolver>,
|
||||||
pub npm_api: Arc<CliNpmRegistryApi>,
|
pub npm_api: Arc<CliNpmRegistryApi>,
|
||||||
pub npm_cache: Arc<NpmCache>,
|
pub npm_cache: Arc<NpmCache>,
|
||||||
pub npm_resolver: Arc<CliNpmResolver>,
|
pub npm_resolver: Arc<CliNpmResolver>,
|
||||||
|
@ -150,6 +151,7 @@ impl ProcState {
|
||||||
module_graph_builder: self.module_graph_builder.clone(),
|
module_graph_builder: self.module_graph_builder.clone(),
|
||||||
module_load_preparer: self.module_load_preparer.clone(),
|
module_load_preparer: self.module_load_preparer.clone(),
|
||||||
node_code_translator: self.node_code_translator.clone(),
|
node_code_translator: self.node_code_translator.clone(),
|
||||||
|
node_fs: self.node_fs.clone(),
|
||||||
node_resolver: self.node_resolver.clone(),
|
node_resolver: self.node_resolver.clone(),
|
||||||
npm_api: self.npm_api.clone(),
|
npm_api: self.npm_api.clone(),
|
||||||
npm_cache: self.npm_cache.clone(),
|
npm_cache: self.npm_cache.clone(),
|
||||||
|
@ -245,7 +247,9 @@ impl ProcState {
|
||||||
npm_snapshot,
|
npm_snapshot,
|
||||||
lockfile.as_ref().cloned(),
|
lockfile.as_ref().cloned(),
|
||||||
));
|
));
|
||||||
|
let node_fs = Arc::new(deno_node::RealFs);
|
||||||
let npm_fs_resolver = create_npm_fs_resolver(
|
let npm_fs_resolver = create_npm_fs_resolver(
|
||||||
|
node_fs.clone(),
|
||||||
npm_cache,
|
npm_cache,
|
||||||
&progress_bar,
|
&progress_bar,
|
||||||
npm_registry_url,
|
npm_registry_url,
|
||||||
|
@ -308,11 +312,14 @@ impl ProcState {
|
||||||
let node_analysis_cache =
|
let node_analysis_cache =
|
||||||
NodeAnalysisCache::new(caches.node_analysis_db(&dir));
|
NodeAnalysisCache::new(caches.node_analysis_db(&dir));
|
||||||
let cjs_esm_analyzer = CliCjsEsmCodeAnalyzer::new(node_analysis_cache);
|
let cjs_esm_analyzer = CliCjsEsmCodeAnalyzer::new(node_analysis_cache);
|
||||||
|
let node_resolver =
|
||||||
|
Arc::new(NodeResolver::new(node_fs.clone(), npm_resolver.clone()));
|
||||||
let node_code_translator = Arc::new(NodeCodeTranslator::new(
|
let node_code_translator = Arc::new(NodeCodeTranslator::new(
|
||||||
cjs_esm_analyzer,
|
cjs_esm_analyzer,
|
||||||
|
node_fs.clone(),
|
||||||
|
node_resolver.clone(),
|
||||||
npm_resolver.clone(),
|
npm_resolver.clone(),
|
||||||
));
|
));
|
||||||
let node_resolver = Arc::new(NodeResolver::new(npm_resolver.clone()));
|
|
||||||
let type_checker = Arc::new(TypeChecker::new(
|
let type_checker = Arc::new(TypeChecker::new(
|
||||||
dir.clone(),
|
dir.clone(),
|
||||||
caches.clone(),
|
caches.clone(),
|
||||||
|
@ -365,6 +372,7 @@ impl ProcState {
|
||||||
maybe_file_watcher_reporter,
|
maybe_file_watcher_reporter,
|
||||||
module_graph_builder,
|
module_graph_builder,
|
||||||
node_code_translator,
|
node_code_translator,
|
||||||
|
node_fs,
|
||||||
node_resolver,
|
node_resolver,
|
||||||
npm_api,
|
npm_api,
|
||||||
npm_cache,
|
npm_cache,
|
||||||
|
|
|
@ -190,6 +190,7 @@ fn create_web_worker_callback(
|
||||||
root_cert_store: Some(ps.root_cert_store.clone()),
|
root_cert_store: Some(ps.root_cert_store.clone()),
|
||||||
seed: ps.options.seed(),
|
seed: ps.options.seed(),
|
||||||
module_loader,
|
module_loader,
|
||||||
|
node_fs: Some(ps.node_fs.clone()),
|
||||||
npm_resolver: None, // not currently supported
|
npm_resolver: None, // not currently supported
|
||||||
create_web_worker_cb,
|
create_web_worker_cb,
|
||||||
preload_module_cb: web_worker_cb.clone(),
|
preload_module_cb: web_worker_cb.clone(),
|
||||||
|
@ -285,6 +286,7 @@ pub async fn run(
|
||||||
should_break_on_first_statement: false,
|
should_break_on_first_statement: false,
|
||||||
should_wait_for_inspector_session: false,
|
should_wait_for_inspector_session: false,
|
||||||
module_loader,
|
module_loader,
|
||||||
|
node_fs: Some(ps.node_fs.clone()),
|
||||||
npm_resolver: None, // not currently supported
|
npm_resolver: None, // not currently supported
|
||||||
get_error_class_fn: Some(&get_error_class_name),
|
get_error_class_fn: Some(&get_error_class_name),
|
||||||
cache_storage_dir: None,
|
cache_storage_dir: None,
|
||||||
|
|
|
@ -9,6 +9,7 @@ use deno_core::error::AnyError;
|
||||||
use deno_graph::Module;
|
use deno_graph::Module;
|
||||||
use deno_graph::ModuleGraph;
|
use deno_graph::ModuleGraph;
|
||||||
use deno_runtime::colors;
|
use deno_runtime::colors;
|
||||||
|
use deno_runtime::deno_node::NodeResolver;
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
|
|
||||||
|
@ -21,7 +22,6 @@ use crate::cache::Caches;
|
||||||
use crate::cache::DenoDir;
|
use crate::cache::DenoDir;
|
||||||
use crate::cache::FastInsecureHasher;
|
use crate::cache::FastInsecureHasher;
|
||||||
use crate::cache::TypeCheckCache;
|
use crate::cache::TypeCheckCache;
|
||||||
use crate::node::CliNodeResolver;
|
|
||||||
use crate::npm::CliNpmResolver;
|
use crate::npm::CliNpmResolver;
|
||||||
use crate::tsc;
|
use crate::tsc;
|
||||||
use crate::version;
|
use crate::version;
|
||||||
|
@ -42,7 +42,7 @@ pub struct TypeChecker {
|
||||||
deno_dir: DenoDir,
|
deno_dir: DenoDir,
|
||||||
caches: Arc<Caches>,
|
caches: Arc<Caches>,
|
||||||
cli_options: Arc<CliOptions>,
|
cli_options: Arc<CliOptions>,
|
||||||
node_resolver: Arc<CliNodeResolver>,
|
node_resolver: Arc<NodeResolver>,
|
||||||
npm_resolver: Arc<CliNpmResolver>,
|
npm_resolver: Arc<CliNpmResolver>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,7 +51,7 @@ impl TypeChecker {
|
||||||
deno_dir: DenoDir,
|
deno_dir: DenoDir,
|
||||||
caches: Arc<Caches>,
|
caches: Arc<Caches>,
|
||||||
cli_options: Arc<CliOptions>,
|
cli_options: Arc<CliOptions>,
|
||||||
node_resolver: Arc<CliNodeResolver>,
|
node_resolver: Arc<NodeResolver>,
|
||||||
npm_resolver: Arc<CliNpmResolver>,
|
npm_resolver: Arc<CliNpmResolver>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
|
|
@ -4,7 +4,6 @@ use crate::args::CliOptions;
|
||||||
use crate::args::Flags;
|
use crate::args::Flags;
|
||||||
use crate::args::TaskFlags;
|
use crate::args::TaskFlags;
|
||||||
use crate::colors;
|
use crate::colors;
|
||||||
use crate::node::CliNodeResolver;
|
|
||||||
use crate::npm::CliNpmResolver;
|
use crate::npm::CliNpmResolver;
|
||||||
use crate::proc_state::ProcState;
|
use crate::proc_state::ProcState;
|
||||||
use crate::util::fs::canonicalize_path;
|
use crate::util::fs::canonicalize_path;
|
||||||
|
@ -13,7 +12,7 @@ use deno_core::anyhow::Context;
|
||||||
use deno_core::error::AnyError;
|
use deno_core::error::AnyError;
|
||||||
use deno_core::futures;
|
use deno_core::futures;
|
||||||
use deno_core::futures::future::LocalBoxFuture;
|
use deno_core::futures::future::LocalBoxFuture;
|
||||||
use deno_runtime::deno_node::RealFs;
|
use deno_runtime::deno_node::NodeResolver;
|
||||||
use deno_semver::npm::NpmPackageNv;
|
use deno_semver::npm::NpmPackageNv;
|
||||||
use deno_task_shell::ExecuteResult;
|
use deno_task_shell::ExecuteResult;
|
||||||
use deno_task_shell::ShellCommand;
|
use deno_task_shell::ShellCommand;
|
||||||
|
@ -236,13 +235,12 @@ impl ShellCommand for NpmPackageBinCommand {
|
||||||
|
|
||||||
fn resolve_npm_commands(
|
fn resolve_npm_commands(
|
||||||
npm_resolver: &CliNpmResolver,
|
npm_resolver: &CliNpmResolver,
|
||||||
node_resolver: &CliNodeResolver,
|
node_resolver: &NodeResolver,
|
||||||
) -> Result<HashMap<String, Rc<dyn ShellCommand>>, AnyError> {
|
) -> Result<HashMap<String, Rc<dyn ShellCommand>>, AnyError> {
|
||||||
let mut result = HashMap::new();
|
let mut result = HashMap::new();
|
||||||
let snapshot = npm_resolver.snapshot();
|
let snapshot = npm_resolver.snapshot();
|
||||||
for id in snapshot.top_level_packages() {
|
for id in snapshot.top_level_packages() {
|
||||||
let bin_commands =
|
let bin_commands = node_resolver.resolve_binary_commands(&id.nv)?;
|
||||||
node_resolver.resolve_binary_commands::<RealFs>(&id.nv)?;
|
|
||||||
for bin_command in bin_commands {
|
for bin_command in bin_commands {
|
||||||
result.insert(
|
result.insert(
|
||||||
bin_command.to_string(),
|
bin_command.to_string(),
|
||||||
|
|
|
@ -4,7 +4,6 @@ use crate::args::TsConfig;
|
||||||
use crate::args::TypeCheckMode;
|
use crate::args::TypeCheckMode;
|
||||||
use crate::cache::FastInsecureHasher;
|
use crate::cache::FastInsecureHasher;
|
||||||
use crate::node;
|
use crate::node;
|
||||||
use crate::node::CliNodeResolver;
|
|
||||||
use crate::util::checksum;
|
use crate::util::checksum;
|
||||||
use crate::util::path::mapped_specifier_for_tsc;
|
use crate::util::path::mapped_specifier_for_tsc;
|
||||||
|
|
||||||
|
@ -35,7 +34,7 @@ use deno_graph::ResolutionResolved;
|
||||||
use deno_runtime::deno_node;
|
use deno_runtime::deno_node;
|
||||||
use deno_runtime::deno_node::NodeResolution;
|
use deno_runtime::deno_node::NodeResolution;
|
||||||
use deno_runtime::deno_node::NodeResolutionMode;
|
use deno_runtime::deno_node::NodeResolutionMode;
|
||||||
use deno_runtime::deno_node::RealFs;
|
use deno_runtime::deno_node::NodeResolver;
|
||||||
use deno_runtime::permissions::PermissionsContainer;
|
use deno_runtime::permissions::PermissionsContainer;
|
||||||
use deno_semver::npm::NpmPackageReqReference;
|
use deno_semver::npm::NpmPackageReqReference;
|
||||||
use lsp_types::Url;
|
use lsp_types::Url;
|
||||||
|
@ -307,7 +306,7 @@ pub struct Request {
|
||||||
pub debug: bool,
|
pub debug: bool,
|
||||||
pub graph: Arc<ModuleGraph>,
|
pub graph: Arc<ModuleGraph>,
|
||||||
pub hash_data: u64,
|
pub hash_data: u64,
|
||||||
pub maybe_node_resolver: Option<Arc<CliNodeResolver>>,
|
pub maybe_node_resolver: Option<Arc<NodeResolver>>,
|
||||||
pub maybe_tsbuildinfo: Option<String>,
|
pub maybe_tsbuildinfo: Option<String>,
|
||||||
/// A vector of strings that represent the root/entry point modules for the
|
/// A vector of strings that represent the root/entry point modules for the
|
||||||
/// program.
|
/// program.
|
||||||
|
@ -331,7 +330,7 @@ struct State {
|
||||||
graph: Arc<ModuleGraph>,
|
graph: Arc<ModuleGraph>,
|
||||||
maybe_tsbuildinfo: Option<String>,
|
maybe_tsbuildinfo: Option<String>,
|
||||||
maybe_response: Option<RespondArgs>,
|
maybe_response: Option<RespondArgs>,
|
||||||
maybe_node_resolver: Option<Arc<CliNodeResolver>>,
|
maybe_node_resolver: Option<Arc<NodeResolver>>,
|
||||||
remapped_specifiers: HashMap<String, ModuleSpecifier>,
|
remapped_specifiers: HashMap<String, ModuleSpecifier>,
|
||||||
root_map: HashMap<String, ModuleSpecifier>,
|
root_map: HashMap<String, ModuleSpecifier>,
|
||||||
current_dir: PathBuf,
|
current_dir: PathBuf,
|
||||||
|
@ -341,7 +340,7 @@ impl State {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
graph: Arc<ModuleGraph>,
|
graph: Arc<ModuleGraph>,
|
||||||
hash_data: u64,
|
hash_data: u64,
|
||||||
maybe_node_resolver: Option<Arc<CliNodeResolver>>,
|
maybe_node_resolver: Option<Arc<NodeResolver>>,
|
||||||
maybe_tsbuildinfo: Option<String>,
|
maybe_tsbuildinfo: Option<String>,
|
||||||
root_map: HashMap<String, ModuleSpecifier>,
|
root_map: HashMap<String, ModuleSpecifier>,
|
||||||
remapped_specifiers: HashMap<String, ModuleSpecifier>,
|
remapped_specifiers: HashMap<String, ModuleSpecifier>,
|
||||||
|
@ -637,7 +636,7 @@ fn resolve_graph_specifier_types(
|
||||||
}
|
}
|
||||||
Some(Module::Npm(module)) => {
|
Some(Module::Npm(module)) => {
|
||||||
if let Some(node_resolver) = &state.maybe_node_resolver {
|
if let Some(node_resolver) = &state.maybe_node_resolver {
|
||||||
let maybe_resolution = node_resolver.resolve_npm_reference::<RealFs>(
|
let maybe_resolution = node_resolver.resolve_npm_reference(
|
||||||
&module.nv_reference,
|
&module.nv_reference,
|
||||||
NodeResolutionMode::Types,
|
NodeResolutionMode::Types,
|
||||||
&mut PermissionsContainer::allow_all(),
|
&mut PermissionsContainer::allow_all(),
|
||||||
|
@ -655,9 +654,7 @@ fn resolve_graph_specifier_types(
|
||||||
let specifier =
|
let specifier =
|
||||||
node::resolve_specifier_into_node_modules(&module.specifier);
|
node::resolve_specifier_into_node_modules(&module.specifier);
|
||||||
NodeResolution::into_specifier_and_media_type(
|
NodeResolution::into_specifier_and_media_type(
|
||||||
node_resolver
|
node_resolver.url_to_node_resolution(specifier).ok(),
|
||||||
.url_to_node_resolution::<RealFs>(specifier)
|
|
||||||
.ok(),
|
|
||||||
)
|
)
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
@ -678,7 +675,7 @@ fn resolve_non_graph_specifier_types(
|
||||||
// we're in an npm package, so use node resolution
|
// we're in an npm package, so use node resolution
|
||||||
Ok(Some(NodeResolution::into_specifier_and_media_type(
|
Ok(Some(NodeResolution::into_specifier_and_media_type(
|
||||||
node_resolver
|
node_resolver
|
||||||
.resolve::<RealFs>(
|
.resolve(
|
||||||
specifier,
|
specifier,
|
||||||
referrer,
|
referrer,
|
||||||
NodeResolutionMode::Types,
|
NodeResolutionMode::Types,
|
||||||
|
@ -692,7 +689,7 @@ fn resolve_non_graph_specifier_types(
|
||||||
// we don't need this special code here.
|
// we don't need this special code here.
|
||||||
// This could occur when resolving npm:@types/node when it is
|
// This could occur when resolving npm:@types/node when it is
|
||||||
// injected and not part of the graph
|
// injected and not part of the graph
|
||||||
let maybe_resolution = node_resolver.resolve_npm_req_reference::<RealFs>(
|
let maybe_resolution = node_resolver.resolve_npm_req_reference(
|
||||||
&npm_ref,
|
&npm_ref,
|
||||||
NodeResolutionMode::Types,
|
NodeResolutionMode::Types,
|
||||||
&mut PermissionsContainer::allow_all(),
|
&mut PermissionsContainer::allow_all(),
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
|
||||||
|
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::rc::Rc;
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use deno_ast::ModuleSpecifier;
|
use deno_ast::ModuleSpecifier;
|
||||||
|
@ -14,7 +13,6 @@ use deno_core::ModuleId;
|
||||||
use deno_runtime::colors;
|
use deno_runtime::colors;
|
||||||
use deno_runtime::deno_node;
|
use deno_runtime::deno_node;
|
||||||
use deno_runtime::deno_node::NodeResolution;
|
use deno_runtime::deno_node::NodeResolution;
|
||||||
use deno_runtime::deno_node::RealFs;
|
|
||||||
use deno_runtime::fmt_errors::format_js_error;
|
use deno_runtime::fmt_errors::format_js_error;
|
||||||
use deno_runtime::ops::worker_host::CreateWebWorkerCb;
|
use deno_runtime::ops::worker_host::CreateWebWorkerCb;
|
||||||
use deno_runtime::ops::worker_host::WorkerEventCb;
|
use deno_runtime::ops::worker_host::WorkerEventCb;
|
||||||
|
@ -259,15 +257,13 @@ pub async fn create_custom_worker(
|
||||||
ps.npm_resolver
|
ps.npm_resolver
|
||||||
.add_package_reqs(vec![package_ref.req.clone()])
|
.add_package_reqs(vec![package_ref.req.clone()])
|
||||||
.await?;
|
.await?;
|
||||||
let node_resolution = ps
|
let node_resolution =
|
||||||
.node_resolver
|
ps.node_resolver.resolve_binary_export(&package_ref)?;
|
||||||
.resolve_binary_export::<RealFs>(&package_ref)?;
|
|
||||||
let is_main_cjs = matches!(node_resolution, NodeResolution::CommonJs(_));
|
let is_main_cjs = matches!(node_resolution, NodeResolution::CommonJs(_));
|
||||||
(node_resolution.into_url(), is_main_cjs)
|
(node_resolution.into_url(), is_main_cjs)
|
||||||
} else if ps.options.is_npm_main() {
|
} else if ps.options.is_npm_main() {
|
||||||
let node_resolution = ps
|
let node_resolution =
|
||||||
.node_resolver
|
ps.node_resolver.url_to_node_resolution(main_module)?;
|
||||||
.url_to_node_resolution::<RealFs>(main_module)?;
|
|
||||||
let is_main_cjs = matches!(node_resolution, NodeResolution::CommonJs(_));
|
let is_main_cjs = matches!(node_resolution, NodeResolution::CommonJs(_));
|
||||||
(node_resolution.into_url(), is_main_cjs)
|
(node_resolution.into_url(), is_main_cjs)
|
||||||
} else {
|
} else {
|
||||||
|
@ -345,7 +341,8 @@ pub async fn create_custom_worker(
|
||||||
should_break_on_first_statement: ps.options.inspect_brk().is_some(),
|
should_break_on_first_statement: ps.options.inspect_brk().is_some(),
|
||||||
should_wait_for_inspector_session: ps.options.inspect_wait().is_some(),
|
should_wait_for_inspector_session: ps.options.inspect_wait().is_some(),
|
||||||
module_loader,
|
module_loader,
|
||||||
npm_resolver: Some(Rc::new(ps.npm_resolver.clone())),
|
node_fs: Some(ps.node_fs.clone()),
|
||||||
|
npm_resolver: Some(ps.npm_resolver.clone()),
|
||||||
get_error_class_fn: Some(&errors::get_error_class_name),
|
get_error_class_fn: Some(&errors::get_error_class_name),
|
||||||
cache_storage_dir,
|
cache_storage_dir,
|
||||||
origin_storage_dir,
|
origin_storage_dir,
|
||||||
|
@ -468,7 +465,8 @@ fn create_web_worker_callback(
|
||||||
format_js_error_fn: Some(Arc::new(format_js_error)),
|
format_js_error_fn: Some(Arc::new(format_js_error)),
|
||||||
source_map_getter: Some(Box::new(module_loader.clone())),
|
source_map_getter: Some(Box::new(module_loader.clone())),
|
||||||
module_loader,
|
module_loader,
|
||||||
npm_resolver: Some(Rc::new(ps.npm_resolver.clone())),
|
node_fs: Some(ps.node_fs.clone()),
|
||||||
|
npm_resolver: Some(ps.npm_resolver.clone()),
|
||||||
worker_type: args.worker_type,
|
worker_type: args.worker_type,
|
||||||
maybe_inspector_server,
|
maybe_inspector_server,
|
||||||
get_error_class_fn: Some(&errors::get_error_class_name),
|
get_error_class_fn: Some(&errors::get_error_class_name),
|
||||||
|
@ -492,6 +490,8 @@ fn create_web_worker_callback(
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use deno_core::resolve_path;
|
use deno_core::resolve_path;
|
||||||
use deno_core::FsModuleLoader;
|
use deno_core::FsModuleLoader;
|
||||||
|
@ -520,6 +520,7 @@ mod tests {
|
||||||
should_break_on_first_statement: false,
|
should_break_on_first_statement: false,
|
||||||
should_wait_for_inspector_session: false,
|
should_wait_for_inspector_session: false,
|
||||||
module_loader: Rc::new(FsModuleLoader),
|
module_loader: Rc::new(FsModuleLoader),
|
||||||
|
node_fs: Some(Arc::new(deno_node::RealFs)),
|
||||||
npm_resolver: None,
|
npm_resolver: None,
|
||||||
get_error_class_fn: None,
|
get_error_class_fn: None,
|
||||||
cache_storage_dir: None,
|
cache_storage_dir: None,
|
||||||
|
|
|
@ -5,6 +5,7 @@ use std::collections::VecDeque;
|
||||||
use std::fmt::Write;
|
use std::fmt::Write;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
use deno_core::anyhow::Context;
|
use deno_core::anyhow::Context;
|
||||||
use deno_core::ModuleSpecifier;
|
use deno_core::ModuleSpecifier;
|
||||||
|
@ -12,11 +13,11 @@ use once_cell::sync::Lazy;
|
||||||
|
|
||||||
use deno_core::error::AnyError;
|
use deno_core::error::AnyError;
|
||||||
|
|
||||||
use crate::package_exports_resolve;
|
|
||||||
use crate::NodeFs;
|
use crate::NodeFs;
|
||||||
use crate::NodeModuleKind;
|
use crate::NodeModuleKind;
|
||||||
use crate::NodePermissions;
|
use crate::NodePermissions;
|
||||||
use crate::NodeResolutionMode;
|
use crate::NodeResolutionMode;
|
||||||
|
use crate::NodeResolver;
|
||||||
use crate::NpmResolver;
|
use crate::NpmResolver;
|
||||||
use crate::PackageJson;
|
use crate::PackageJson;
|
||||||
use crate::PathClean;
|
use crate::PathClean;
|
||||||
|
@ -64,23 +65,26 @@ pub trait CjsEsmCodeAnalyzer {
|
||||||
) -> Result<HashSet<String>, AnyError>;
|
) -> Result<HashSet<String>, AnyError>;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct NodeCodeTranslator<
|
pub struct NodeCodeTranslator<TCjsEsmCodeAnalyzer: CjsEsmCodeAnalyzer> {
|
||||||
TCjsEsmCodeAnalyzer: CjsEsmCodeAnalyzer,
|
|
||||||
TNpmResolver: NpmResolver,
|
|
||||||
> {
|
|
||||||
cjs_esm_code_analyzer: TCjsEsmCodeAnalyzer,
|
cjs_esm_code_analyzer: TCjsEsmCodeAnalyzer,
|
||||||
npm_resolver: TNpmResolver,
|
fs: Arc<dyn NodeFs>,
|
||||||
|
node_resolver: Arc<NodeResolver>,
|
||||||
|
npm_resolver: Arc<dyn NpmResolver>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<TCjsEsmCodeAnalyzer: CjsEsmCodeAnalyzer, TNpmResolver: NpmResolver>
|
impl<TCjsEsmCodeAnalyzer: CjsEsmCodeAnalyzer>
|
||||||
NodeCodeTranslator<TCjsEsmCodeAnalyzer, TNpmResolver>
|
NodeCodeTranslator<TCjsEsmCodeAnalyzer>
|
||||||
{
|
{
|
||||||
pub fn new(
|
pub fn new(
|
||||||
cjs_esm_code_analyzer: TCjsEsmCodeAnalyzer,
|
cjs_esm_code_analyzer: TCjsEsmCodeAnalyzer,
|
||||||
npm_resolver: TNpmResolver,
|
fs: Arc<dyn NodeFs>,
|
||||||
|
node_resolver: Arc<NodeResolver>,
|
||||||
|
npm_resolver: Arc<dyn NpmResolver>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
cjs_esm_code_analyzer,
|
cjs_esm_code_analyzer,
|
||||||
|
fs,
|
||||||
|
node_resolver,
|
||||||
npm_resolver,
|
npm_resolver,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -105,7 +109,7 @@ impl<TCjsEsmCodeAnalyzer: CjsEsmCodeAnalyzer, TNpmResolver: NpmResolver>
|
||||||
/// For all discovered reexports the analysis will be performed recursively.
|
/// For all discovered reexports the analysis will be performed recursively.
|
||||||
///
|
///
|
||||||
/// If successful a source code for equivalent ES module is returned.
|
/// If successful a source code for equivalent ES module is returned.
|
||||||
pub fn translate_cjs_to_esm<Fs: NodeFs>(
|
pub fn translate_cjs_to_esm(
|
||||||
&self,
|
&self,
|
||||||
specifier: &ModuleSpecifier,
|
specifier: &ModuleSpecifier,
|
||||||
source: &str,
|
source: &str,
|
||||||
|
@ -142,7 +146,7 @@ impl<TCjsEsmCodeAnalyzer: CjsEsmCodeAnalyzer, TNpmResolver: NpmResolver>
|
||||||
handled_reexports.insert(reexport.to_string());
|
handled_reexports.insert(reexport.to_string());
|
||||||
|
|
||||||
// First, resolve relate reexport specifier
|
// First, resolve relate reexport specifier
|
||||||
let resolved_reexport = self.resolve::<Fs>(
|
let resolved_reexport = self.resolve(
|
||||||
&reexport,
|
&reexport,
|
||||||
&referrer,
|
&referrer,
|
||||||
// FIXME(bartlomieju): check if these conditions are okay, probably
|
// FIXME(bartlomieju): check if these conditions are okay, probably
|
||||||
|
@ -154,7 +158,9 @@ impl<TCjsEsmCodeAnalyzer: CjsEsmCodeAnalyzer, TNpmResolver: NpmResolver>
|
||||||
// Second, read the source code from disk
|
// Second, read the source code from disk
|
||||||
let reexport_specifier =
|
let reexport_specifier =
|
||||||
ModuleSpecifier::from_file_path(&resolved_reexport).unwrap();
|
ModuleSpecifier::from_file_path(&resolved_reexport).unwrap();
|
||||||
let reexport_file_text = Fs::read_to_string(&resolved_reexport)
|
let reexport_file_text = self
|
||||||
|
.fs
|
||||||
|
.read_to_string(&resolved_reexport)
|
||||||
.with_context(|| {
|
.with_context(|| {
|
||||||
format!(
|
format!(
|
||||||
"Could not find '{}' ({}) referenced from {}",
|
"Could not find '{}' ({}) referenced from {}",
|
||||||
|
@ -208,7 +214,7 @@ impl<TCjsEsmCodeAnalyzer: CjsEsmCodeAnalyzer, TNpmResolver: NpmResolver>
|
||||||
Ok(translated_source)
|
Ok(translated_source)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resolve<Fs: NodeFs>(
|
fn resolve(
|
||||||
&self,
|
&self,
|
||||||
specifier: &str,
|
specifier: &str,
|
||||||
referrer: &ModuleSpecifier,
|
referrer: &ModuleSpecifier,
|
||||||
|
@ -223,10 +229,8 @@ impl<TCjsEsmCodeAnalyzer: CjsEsmCodeAnalyzer, TNpmResolver: NpmResolver>
|
||||||
let referrer_path = referrer.to_file_path().unwrap();
|
let referrer_path = referrer.to_file_path().unwrap();
|
||||||
if specifier.starts_with("./") || specifier.starts_with("../") {
|
if specifier.starts_with("./") || specifier.starts_with("../") {
|
||||||
if let Some(parent) = referrer_path.parent() {
|
if let Some(parent) = referrer_path.parent() {
|
||||||
return file_extension_probe::<Fs>(
|
return self
|
||||||
parent.join(specifier),
|
.file_extension_probe(parent.join(specifier), &referrer_path);
|
||||||
&referrer_path,
|
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
todo!();
|
todo!();
|
||||||
}
|
}
|
||||||
|
@ -245,15 +249,16 @@ impl<TCjsEsmCodeAnalyzer: CjsEsmCodeAnalyzer, TNpmResolver: NpmResolver>
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let package_json_path = module_dir.join("package.json");
|
let package_json_path = module_dir.join("package.json");
|
||||||
if Fs::exists(&package_json_path) {
|
if self.fs.exists(&package_json_path) {
|
||||||
let package_json = PackageJson::load::<Fs>(
|
let package_json = PackageJson::load(
|
||||||
&self.npm_resolver,
|
&*self.fs,
|
||||||
|
&*self.npm_resolver,
|
||||||
permissions,
|
permissions,
|
||||||
package_json_path.clone(),
|
package_json_path.clone(),
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
if let Some(exports) = &package_json.exports {
|
if let Some(exports) = &package_json.exports {
|
||||||
return package_exports_resolve::<Fs>(
|
return self.node_resolver.package_exports_resolve(
|
||||||
&package_json_path,
|
&package_json_path,
|
||||||
package_subpath,
|
package_subpath,
|
||||||
exports,
|
exports,
|
||||||
|
@ -261,7 +266,6 @@ impl<TCjsEsmCodeAnalyzer: CjsEsmCodeAnalyzer, TNpmResolver: NpmResolver>
|
||||||
NodeModuleKind::Esm,
|
NodeModuleKind::Esm,
|
||||||
conditions,
|
conditions,
|
||||||
mode,
|
mode,
|
||||||
&self.npm_resolver,
|
|
||||||
permissions,
|
permissions,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -269,12 +273,13 @@ impl<TCjsEsmCodeAnalyzer: CjsEsmCodeAnalyzer, TNpmResolver: NpmResolver>
|
||||||
// old school
|
// old school
|
||||||
if package_subpath != "." {
|
if package_subpath != "." {
|
||||||
let d = module_dir.join(package_subpath);
|
let d = module_dir.join(package_subpath);
|
||||||
if Fs::is_dir(&d) {
|
if self.fs.is_dir(&d) {
|
||||||
// subdir might have a package.json that specifies the entrypoint
|
// subdir might have a package.json that specifies the entrypoint
|
||||||
let package_json_path = d.join("package.json");
|
let package_json_path = d.join("package.json");
|
||||||
if Fs::exists(&package_json_path) {
|
if self.fs.exists(&package_json_path) {
|
||||||
let package_json = PackageJson::load::<Fs>(
|
let package_json = PackageJson::load(
|
||||||
&self.npm_resolver,
|
&*self.fs,
|
||||||
|
&*self.npm_resolver,
|
||||||
permissions,
|
permissions,
|
||||||
package_json_path,
|
package_json_path,
|
||||||
)?;
|
)?;
|
||||||
|
@ -285,7 +290,7 @@ impl<TCjsEsmCodeAnalyzer: CjsEsmCodeAnalyzer, TNpmResolver: NpmResolver>
|
||||||
|
|
||||||
return Ok(d.join("index.js").clean());
|
return Ok(d.join("index.js").clean());
|
||||||
}
|
}
|
||||||
return file_extension_probe::<Fs>(d, &referrer_path);
|
return self.file_extension_probe(d, &referrer_path);
|
||||||
} else if let Some(main) = package_json.main(NodeModuleKind::Cjs) {
|
} else if let Some(main) = package_json.main(NodeModuleKind::Cjs) {
|
||||||
return Ok(module_dir.join(main).clean());
|
return Ok(module_dir.join(main).clean());
|
||||||
} else {
|
} else {
|
||||||
|
@ -294,6 +299,33 @@ impl<TCjsEsmCodeAnalyzer: CjsEsmCodeAnalyzer, TNpmResolver: NpmResolver>
|
||||||
}
|
}
|
||||||
Err(not_found(specifier, &referrer_path))
|
Err(not_found(specifier, &referrer_path))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn file_extension_probe(
|
||||||
|
&self,
|
||||||
|
p: PathBuf,
|
||||||
|
referrer: &Path,
|
||||||
|
) -> Result<PathBuf, AnyError> {
|
||||||
|
let p = p.clean();
|
||||||
|
if self.fs.exists(&p) {
|
||||||
|
let file_name = p.file_name().unwrap();
|
||||||
|
let p_js =
|
||||||
|
p.with_file_name(format!("{}.js", file_name.to_str().unwrap()));
|
||||||
|
if self.fs.is_file(&p_js) {
|
||||||
|
return Ok(p_js);
|
||||||
|
} else if self.fs.is_dir(&p) {
|
||||||
|
return Ok(p.join("index.js"));
|
||||||
|
} else {
|
||||||
|
return Ok(p);
|
||||||
|
}
|
||||||
|
} else if let Some(file_name) = p.file_name() {
|
||||||
|
let p_js =
|
||||||
|
p.with_file_name(format!("{}.js", file_name.to_str().unwrap()));
|
||||||
|
if self.fs.is_file(&p_js) {
|
||||||
|
return Ok(p_js);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(not_found(&p.to_string_lossy(), referrer))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn esm_code_from_top_level_decls(
|
fn esm_code_from_top_level_decls(
|
||||||
|
@ -455,30 +487,6 @@ fn parse_specifier(specifier: &str) -> Option<(String, String)> {
|
||||||
Some((package_name, package_subpath))
|
Some((package_name, package_subpath))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn file_extension_probe<Fs: NodeFs>(
|
|
||||||
p: PathBuf,
|
|
||||||
referrer: &Path,
|
|
||||||
) -> Result<PathBuf, AnyError> {
|
|
||||||
let p = p.clean();
|
|
||||||
if Fs::exists(&p) {
|
|
||||||
let file_name = p.file_name().unwrap();
|
|
||||||
let p_js = p.with_file_name(format!("{}.js", file_name.to_str().unwrap()));
|
|
||||||
if Fs::is_file(&p_js) {
|
|
||||||
return Ok(p_js);
|
|
||||||
} else if Fs::is_dir(&p) {
|
|
||||||
return Ok(p.join("index.js"));
|
|
||||||
} else {
|
|
||||||
return Ok(p);
|
|
||||||
}
|
|
||||||
} else if let Some(file_name) = p.file_name() {
|
|
||||||
let p_js = p.with_file_name(format!("{}.js", file_name.to_str().unwrap()));
|
|
||||||
if Fs::is_file(&p_js) {
|
|
||||||
return Ok(p_js);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Err(not_found(&p.to_string_lossy(), referrer))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn not_found(path: &str, referrer: &Path) -> AnyError {
|
fn not_found(path: &str, referrer: &Path) -> AnyError {
|
||||||
let msg = format!(
|
let msg = format!(
|
||||||
"[ERR_MODULE_NOT_FOUND] Cannot find module \"{}\" imported from \"{}\"",
|
"[ERR_MODULE_NOT_FOUND] Cannot find module \"{}\" imported from \"{}\"",
|
||||||
|
|
112
ext/node/lib.rs
112
ext/node/lib.rs
|
@ -27,7 +27,6 @@ mod package_json;
|
||||||
mod path;
|
mod path;
|
||||||
mod polyfill;
|
mod polyfill;
|
||||||
mod resolution;
|
mod resolution;
|
||||||
mod resolver;
|
|
||||||
|
|
||||||
pub use package_json::PackageJson;
|
pub use package_json::PackageJson;
|
||||||
pub use path::PathClean;
|
pub use path::PathClean;
|
||||||
|
@ -35,22 +34,13 @@ pub use polyfill::is_builtin_node_module;
|
||||||
pub use polyfill::resolve_builtin_node_module;
|
pub use polyfill::resolve_builtin_node_module;
|
||||||
pub use polyfill::NodeModulePolyfill;
|
pub use polyfill::NodeModulePolyfill;
|
||||||
pub use polyfill::SUPPORTED_BUILTIN_NODE_MODULES;
|
pub use polyfill::SUPPORTED_BUILTIN_NODE_MODULES;
|
||||||
pub use resolution::get_closest_package_json;
|
|
||||||
pub use resolution::get_package_scope_config;
|
|
||||||
pub use resolution::legacy_main_resolve;
|
|
||||||
pub use resolution::package_exports_resolve;
|
|
||||||
pub use resolution::package_imports_resolve;
|
|
||||||
pub use resolution::package_resolve;
|
|
||||||
pub use resolution::path_to_declaration_path;
|
|
||||||
pub use resolution::NodeModuleKind;
|
pub use resolution::NodeModuleKind;
|
||||||
|
pub use resolution::NodeResolution;
|
||||||
pub use resolution::NodeResolutionMode;
|
pub use resolution::NodeResolutionMode;
|
||||||
pub use resolution::DEFAULT_CONDITIONS;
|
pub use resolution::NodeResolver;
|
||||||
pub use resolver::NodeResolution;
|
|
||||||
pub use resolver::NodeResolver;
|
|
||||||
|
|
||||||
pub trait NodeEnv {
|
pub trait NodeEnv {
|
||||||
type P: NodePermissions;
|
type P: NodePermissions;
|
||||||
type Fs: NodeFs;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait NodePermissions {
|
pub trait NodePermissions {
|
||||||
|
@ -71,24 +61,26 @@ pub struct NodeFsMetadata {
|
||||||
pub is_dir: bool,
|
pub is_dir: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait NodeFs {
|
pub trait NodeFs: std::fmt::Debug + Send + Sync {
|
||||||
fn current_dir() -> io::Result<PathBuf>;
|
fn current_dir(&self) -> io::Result<PathBuf>;
|
||||||
fn metadata<P: AsRef<Path>>(path: P) -> io::Result<NodeFsMetadata>;
|
fn metadata(&self, path: &Path) -> io::Result<NodeFsMetadata>;
|
||||||
fn is_file<P: AsRef<Path>>(path: P) -> bool;
|
fn is_file(&self, path: &Path) -> bool;
|
||||||
fn is_dir<P: AsRef<Path>>(path: P) -> bool;
|
fn is_dir(&self, path: &Path) -> bool;
|
||||||
fn exists<P: AsRef<Path>>(path: P) -> bool;
|
fn exists(&self, path: &Path) -> bool;
|
||||||
fn read_to_string<P: AsRef<Path>>(path: P) -> io::Result<String>;
|
fn read_to_string(&self, path: &Path) -> io::Result<String>;
|
||||||
fn canonicalize<P: AsRef<Path>>(path: P) -> io::Result<PathBuf>;
|
fn canonicalize(&self, path: &Path) -> io::Result<PathBuf>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
pub struct RealFs;
|
pub struct RealFs;
|
||||||
|
|
||||||
impl NodeFs for RealFs {
|
impl NodeFs for RealFs {
|
||||||
fn current_dir() -> io::Result<PathBuf> {
|
fn current_dir(&self) -> io::Result<PathBuf> {
|
||||||
#[allow(clippy::disallowed_methods)]
|
#[allow(clippy::disallowed_methods)]
|
||||||
std::env::current_dir()
|
std::env::current_dir()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn metadata<P: AsRef<Path>>(path: P) -> io::Result<NodeFsMetadata> {
|
fn metadata(&self, path: &Path) -> io::Result<NodeFsMetadata> {
|
||||||
#[allow(clippy::disallowed_methods)]
|
#[allow(clippy::disallowed_methods)]
|
||||||
std::fs::metadata(path).map(|metadata| {
|
std::fs::metadata(path).map(|metadata| {
|
||||||
// on most systems, calling is_file() and is_dir() is cheap
|
// on most systems, calling is_file() and is_dir() is cheap
|
||||||
|
@ -100,35 +92,35 @@ impl NodeFs for RealFs {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn exists<P: AsRef<Path>>(path: P) -> bool {
|
fn exists(&self, path: &Path) -> bool {
|
||||||
#[allow(clippy::disallowed_methods)]
|
#[allow(clippy::disallowed_methods)]
|
||||||
std::fs::metadata(path).is_ok()
|
std::fs::metadata(path).is_ok()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_file<P: AsRef<Path>>(path: P) -> bool {
|
fn is_file(&self, path: &Path) -> bool {
|
||||||
#[allow(clippy::disallowed_methods)]
|
#[allow(clippy::disallowed_methods)]
|
||||||
std::fs::metadata(path)
|
std::fs::metadata(path)
|
||||||
.map(|m| m.is_file())
|
.map(|m| m.is_file())
|
||||||
.unwrap_or(false)
|
.unwrap_or(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_dir<P: AsRef<Path>>(path: P) -> bool {
|
fn is_dir(&self, path: &Path) -> bool {
|
||||||
#[allow(clippy::disallowed_methods)]
|
#[allow(clippy::disallowed_methods)]
|
||||||
std::fs::metadata(path).map(|m| m.is_dir()).unwrap_or(false)
|
std::fs::metadata(path).map(|m| m.is_dir()).unwrap_or(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_to_string<P: AsRef<Path>>(path: P) -> io::Result<String> {
|
fn read_to_string(&self, path: &Path) -> io::Result<String> {
|
||||||
#[allow(clippy::disallowed_methods)]
|
#[allow(clippy::disallowed_methods)]
|
||||||
std::fs::read_to_string(path)
|
std::fs::read_to_string(path)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn canonicalize<P: AsRef<Path>>(path: P) -> io::Result<PathBuf> {
|
fn canonicalize(&self, path: &Path) -> io::Result<PathBuf> {
|
||||||
#[allow(clippy::disallowed_methods)]
|
#[allow(clippy::disallowed_methods)]
|
||||||
std::path::Path::canonicalize(path.as_ref())
|
std::path::Path::canonicalize(path)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait NpmResolver {
|
pub trait NpmResolver: std::fmt::Debug + Send + Sync {
|
||||||
/// Resolves an npm package folder path from an npm package referrer.
|
/// Resolves an npm package folder path from an npm package referrer.
|
||||||
fn resolve_package_folder_from_package(
|
fn resolve_package_folder_from_package(
|
||||||
&self,
|
&self,
|
||||||
|
@ -177,57 +169,6 @@ pub trait NpmResolver {
|
||||||
) -> Result<(), AnyError>;
|
) -> Result<(), AnyError>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: NpmResolver + ?Sized> NpmResolver for Arc<T> {
|
|
||||||
fn resolve_package_folder_from_package(
|
|
||||||
&self,
|
|
||||||
specifier: &str,
|
|
||||||
referrer: &ModuleSpecifier,
|
|
||||||
mode: NodeResolutionMode,
|
|
||||||
) -> Result<PathBuf, AnyError> {
|
|
||||||
(**self).resolve_package_folder_from_package(specifier, referrer, mode)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn resolve_package_folder_from_path(
|
|
||||||
&self,
|
|
||||||
path: &Path,
|
|
||||||
) -> Result<PathBuf, AnyError> {
|
|
||||||
(**self).resolve_package_folder_from_path(path)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn resolve_package_folder_from_deno_module(
|
|
||||||
&self,
|
|
||||||
pkg_nv: &NpmPackageNv,
|
|
||||||
) -> Result<PathBuf, AnyError> {
|
|
||||||
(**self).resolve_package_folder_from_deno_module(pkg_nv)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn resolve_pkg_id_from_pkg_req(
|
|
||||||
&self,
|
|
||||||
req: &NpmPackageReq,
|
|
||||||
) -> Result<NpmPackageId, PackageReqNotFoundError> {
|
|
||||||
(**self).resolve_pkg_id_from_pkg_req(req)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn resolve_nv_ref_from_pkg_req_ref(
|
|
||||||
&self,
|
|
||||||
req_ref: &NpmPackageReqReference,
|
|
||||||
) -> Result<NpmPackageNvReference, PackageReqNotFoundError> {
|
|
||||||
(**self).resolve_nv_ref_from_pkg_req_ref(req_ref)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn in_npm_package(&self, specifier: &ModuleSpecifier) -> bool {
|
|
||||||
(**self).in_npm_package(specifier)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn ensure_read_permission(
|
|
||||||
&self,
|
|
||||||
permissions: &mut dyn NodePermissions,
|
|
||||||
path: &Path,
|
|
||||||
) -> Result<(), AnyError> {
|
|
||||||
(**self).ensure_read_permission(permissions, path)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub static NODE_GLOBAL_THIS_NAME: Lazy<String> = Lazy::new(|| {
|
pub static NODE_GLOBAL_THIS_NAME: Lazy<String> = Lazy::new(|| {
|
||||||
let now = std::time::SystemTime::now();
|
let now = std::time::SystemTime::now();
|
||||||
let seconds = now
|
let seconds = now
|
||||||
|
@ -582,11 +523,18 @@ deno_core::extension!(deno_node,
|
||||||
"zlib.ts",
|
"zlib.ts",
|
||||||
],
|
],
|
||||||
options = {
|
options = {
|
||||||
maybe_npm_resolver: Option<Rc<dyn NpmResolver>>,
|
maybe_npm_resolver: Option<Arc<dyn NpmResolver>>,
|
||||||
|
fs: Option<Arc<dyn NodeFs>>,
|
||||||
},
|
},
|
||||||
state = |state, options| {
|
state = |state, options| {
|
||||||
|
let fs = options.fs.unwrap_or_else(|| Arc::new(RealFs));
|
||||||
|
state.put(fs.clone());
|
||||||
if let Some(npm_resolver) = options.maybe_npm_resolver {
|
if let Some(npm_resolver) = options.maybe_npm_resolver {
|
||||||
state.put(npm_resolver);
|
state.put(npm_resolver.clone());
|
||||||
|
state.put(Rc::new(NodeResolver::new(
|
||||||
|
fs,
|
||||||
|
npm_resolver,
|
||||||
|
)))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
|
@ -13,6 +13,7 @@ use std::cell::RefCell;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
use crate::resolution;
|
use crate::resolution;
|
||||||
use crate::NodeEnv;
|
use crate::NodeEnv;
|
||||||
|
@ -20,6 +21,7 @@ use crate::NodeFs;
|
||||||
use crate::NodeModuleKind;
|
use crate::NodeModuleKind;
|
||||||
use crate::NodePermissions;
|
use crate::NodePermissions;
|
||||||
use crate::NodeResolutionMode;
|
use crate::NodeResolutionMode;
|
||||||
|
use crate::NodeResolver;
|
||||||
use crate::NpmResolver;
|
use crate::NpmResolver;
|
||||||
use crate::PackageJson;
|
use crate::PackageJson;
|
||||||
|
|
||||||
|
@ -31,7 +33,7 @@ where
|
||||||
P: NodePermissions + 'static,
|
P: NodePermissions + 'static,
|
||||||
{
|
{
|
||||||
let resolver = {
|
let resolver = {
|
||||||
let resolver = state.borrow::<Rc<dyn NpmResolver>>();
|
let resolver = state.borrow::<Arc<dyn NpmResolver>>();
|
||||||
resolver.clone()
|
resolver.clone()
|
||||||
};
|
};
|
||||||
let permissions = state.borrow_mut::<P>();
|
let permissions = state.borrow_mut::<P>();
|
||||||
|
@ -96,10 +98,11 @@ pub fn op_require_node_module_paths<Env>(
|
||||||
where
|
where
|
||||||
Env: NodeEnv + 'static,
|
Env: NodeEnv + 'static,
|
||||||
{
|
{
|
||||||
|
let fs = state.borrow::<Arc<dyn NodeFs>>().clone();
|
||||||
// Guarantee that "from" is absolute.
|
// Guarantee that "from" is absolute.
|
||||||
let from = deno_core::resolve_path(
|
let from = deno_core::resolve_path(
|
||||||
&from,
|
&from,
|
||||||
&(Env::Fs::current_dir()).context("Unable to get CWD")?,
|
&(fs.current_dir()).context("Unable to get CWD")?,
|
||||||
)
|
)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.to_file_path()
|
.to_file_path()
|
||||||
|
@ -191,7 +194,7 @@ fn op_require_resolve_deno_dir(
|
||||||
request: String,
|
request: String,
|
||||||
parent_filename: String,
|
parent_filename: String,
|
||||||
) -> Option<String> {
|
) -> Option<String> {
|
||||||
let resolver = state.borrow::<Rc<dyn NpmResolver>>();
|
let resolver = state.borrow::<Arc<dyn NpmResolver>>();
|
||||||
resolver
|
resolver
|
||||||
.resolve_package_folder_from_package(
|
.resolve_package_folder_from_package(
|
||||||
&request,
|
&request,
|
||||||
|
@ -204,7 +207,7 @@ fn op_require_resolve_deno_dir(
|
||||||
|
|
||||||
#[op]
|
#[op]
|
||||||
fn op_require_is_deno_dir_package(state: &mut OpState, path: String) -> bool {
|
fn op_require_is_deno_dir_package(state: &mut OpState, path: String) -> bool {
|
||||||
let resolver = state.borrow::<Rc<dyn NpmResolver>>();
|
let resolver = state.borrow::<Arc<dyn NpmResolver>>();
|
||||||
resolver.in_npm_package_at_path(&PathBuf::from(path))
|
resolver.in_npm_package_at_path(&PathBuf::from(path))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -264,7 +267,8 @@ where
|
||||||
{
|
{
|
||||||
let path = PathBuf::from(path);
|
let path = PathBuf::from(path);
|
||||||
ensure_read_permission::<Env::P>(state, &path)?;
|
ensure_read_permission::<Env::P>(state, &path)?;
|
||||||
if let Ok(metadata) = Env::Fs::metadata(&path) {
|
let fs = state.borrow::<Arc<dyn NodeFs>>().clone();
|
||||||
|
if let Ok(metadata) = fs.metadata(&path) {
|
||||||
if metadata.is_file {
|
if metadata.is_file {
|
||||||
return Ok(0);
|
return Ok(0);
|
||||||
} else {
|
} else {
|
||||||
|
@ -285,7 +289,8 @@ where
|
||||||
{
|
{
|
||||||
let path = PathBuf::from(request);
|
let path = PathBuf::from(request);
|
||||||
ensure_read_permission::<Env::P>(state, &path)?;
|
ensure_read_permission::<Env::P>(state, &path)?;
|
||||||
let mut canonicalized_path = Env::Fs::canonicalize(&path)?;
|
let fs = state.borrow::<Arc<dyn NodeFs>>().clone();
|
||||||
|
let mut canonicalized_path = fs.canonicalize(&path)?;
|
||||||
if cfg!(windows) {
|
if cfg!(windows) {
|
||||||
canonicalized_path = PathBuf::from(
|
canonicalized_path = PathBuf::from(
|
||||||
canonicalized_path
|
canonicalized_path
|
||||||
|
@ -353,7 +358,8 @@ where
|
||||||
|
|
||||||
if let Some(parent_id) = maybe_parent_id {
|
if let Some(parent_id) = maybe_parent_id {
|
||||||
if parent_id == "<repl>" || parent_id == "internal/preload" {
|
if parent_id == "<repl>" || parent_id == "internal/preload" {
|
||||||
if let Ok(cwd) = Env::Fs::current_dir() {
|
let fs = state.borrow::<Arc<dyn NodeFs>>().clone();
|
||||||
|
if let Ok(cwd) = fs.current_dir() {
|
||||||
ensure_read_permission::<Env::P>(state, &cwd)?;
|
ensure_read_permission::<Env::P>(state, &cwd)?;
|
||||||
return Ok(Some(cwd.to_string_lossy().to_string()));
|
return Ok(Some(cwd.to_string_lossy().to_string()));
|
||||||
}
|
}
|
||||||
|
@ -375,14 +381,14 @@ where
|
||||||
return Ok(None);
|
return Ok(None);
|
||||||
}
|
}
|
||||||
|
|
||||||
let resolver = state.borrow::<Rc<dyn NpmResolver>>().clone();
|
let node_resolver = state.borrow::<Rc<NodeResolver>>().clone();
|
||||||
let permissions = state.borrow_mut::<Env::P>();
|
let permissions = state.borrow_mut::<Env::P>();
|
||||||
let pkg = resolution::get_package_scope_config::<Env::Fs>(
|
let pkg = node_resolver
|
||||||
&Url::from_file_path(parent_path.unwrap()).unwrap(),
|
.get_package_scope_config(
|
||||||
&*resolver,
|
&Url::from_file_path(parent_path.unwrap()).unwrap(),
|
||||||
permissions,
|
permissions,
|
||||||
)
|
)
|
||||||
.ok();
|
.ok();
|
||||||
if pkg.is_none() {
|
if pkg.is_none() {
|
||||||
return Ok(None);
|
return Ok(None);
|
||||||
}
|
}
|
||||||
|
@ -408,18 +414,18 @@ where
|
||||||
|
|
||||||
let referrer = deno_core::url::Url::from_file_path(&pkg.path).unwrap();
|
let referrer = deno_core::url::Url::from_file_path(&pkg.path).unwrap();
|
||||||
if let Some(exports) = &pkg.exports {
|
if let Some(exports) = &pkg.exports {
|
||||||
resolution::package_exports_resolve::<Env::Fs>(
|
node_resolver
|
||||||
&pkg.path,
|
.package_exports_resolve(
|
||||||
expansion,
|
&pkg.path,
|
||||||
exports,
|
expansion,
|
||||||
&referrer,
|
exports,
|
||||||
NodeModuleKind::Cjs,
|
&referrer,
|
||||||
resolution::REQUIRE_CONDITIONS,
|
NodeModuleKind::Cjs,
|
||||||
NodeResolutionMode::Execution,
|
resolution::REQUIRE_CONDITIONS,
|
||||||
&*resolver,
|
NodeResolutionMode::Execution,
|
||||||
permissions,
|
permissions,
|
||||||
)
|
)
|
||||||
.map(|r| Some(r.to_string_lossy().to_string()))
|
.map(|r| Some(r.to_string_lossy().to_string()))
|
||||||
} else {
|
} else {
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
|
@ -435,7 +441,8 @@ where
|
||||||
{
|
{
|
||||||
let file_path = PathBuf::from(file_path);
|
let file_path = PathBuf::from(file_path);
|
||||||
ensure_read_permission::<Env::P>(state, &file_path)?;
|
ensure_read_permission::<Env::P>(state, &file_path)?;
|
||||||
Ok(Env::Fs::read_to_string(file_path)?)
|
let fs = state.borrow::<Arc<dyn NodeFs>>().clone();
|
||||||
|
Ok(fs.read_to_string(&file_path)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[op]
|
#[op]
|
||||||
|
@ -462,10 +469,12 @@ fn op_require_resolve_exports<Env>(
|
||||||
where
|
where
|
||||||
Env: NodeEnv + 'static,
|
Env: NodeEnv + 'static,
|
||||||
{
|
{
|
||||||
let resolver = state.borrow::<Rc<dyn NpmResolver>>().clone();
|
let fs = state.borrow::<Arc<dyn NodeFs>>().clone();
|
||||||
|
let npm_resolver = state.borrow::<Arc<dyn NpmResolver>>().clone();
|
||||||
|
let node_resolver = state.borrow::<Rc<NodeResolver>>().clone();
|
||||||
let permissions = state.borrow_mut::<Env::P>();
|
let permissions = state.borrow_mut::<Env::P>();
|
||||||
|
|
||||||
let pkg_path = if resolver
|
let pkg_path = if npm_resolver
|
||||||
.in_npm_package_at_path(&PathBuf::from(&modules_path))
|
.in_npm_package_at_path(&PathBuf::from(&modules_path))
|
||||||
&& !uses_local_node_modules_dir
|
&& !uses_local_node_modules_dir
|
||||||
{
|
{
|
||||||
|
@ -473,32 +482,31 @@ where
|
||||||
} else {
|
} else {
|
||||||
let orignal = modules_path.clone();
|
let orignal = modules_path.clone();
|
||||||
let mod_dir = path_resolve(vec![modules_path, name]);
|
let mod_dir = path_resolve(vec![modules_path, name]);
|
||||||
if Env::Fs::is_dir(&mod_dir) {
|
if fs.is_dir(Path::new(&mod_dir)) {
|
||||||
mod_dir
|
mod_dir
|
||||||
} else {
|
} else {
|
||||||
orignal
|
orignal
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let pkg = PackageJson::load::<Env::Fs>(
|
let pkg = node_resolver.load_package_json(
|
||||||
&*resolver,
|
|
||||||
permissions,
|
permissions,
|
||||||
PathBuf::from(&pkg_path).join("package.json"),
|
PathBuf::from(&pkg_path).join("package.json"),
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
if let Some(exports) = &pkg.exports {
|
if let Some(exports) = &pkg.exports {
|
||||||
let referrer = Url::from_file_path(parent_path).unwrap();
|
let referrer = Url::from_file_path(parent_path).unwrap();
|
||||||
resolution::package_exports_resolve::<Env::Fs>(
|
node_resolver
|
||||||
&pkg.path,
|
.package_exports_resolve(
|
||||||
format!(".{expansion}"),
|
&pkg.path,
|
||||||
exports,
|
format!(".{expansion}"),
|
||||||
&referrer,
|
exports,
|
||||||
NodeModuleKind::Cjs,
|
&referrer,
|
||||||
resolution::REQUIRE_CONDITIONS,
|
NodeModuleKind::Cjs,
|
||||||
NodeResolutionMode::Execution,
|
resolution::REQUIRE_CONDITIONS,
|
||||||
&*resolver,
|
NodeResolutionMode::Execution,
|
||||||
permissions,
|
permissions,
|
||||||
)
|
)
|
||||||
.map(|r| Some(r.to_string_lossy().to_string()))
|
.map(|r| Some(r.to_string_lossy().to_string()))
|
||||||
} else {
|
} else {
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
|
@ -516,11 +524,10 @@ where
|
||||||
state,
|
state,
|
||||||
PathBuf::from(&filename).parent().unwrap(),
|
PathBuf::from(&filename).parent().unwrap(),
|
||||||
)?;
|
)?;
|
||||||
let resolver = state.borrow::<Rc<dyn NpmResolver>>().clone();
|
let node_resolver = state.borrow::<Rc<NodeResolver>>().clone();
|
||||||
let permissions = state.borrow_mut::<Env::P>();
|
let permissions = state.borrow_mut::<Env::P>();
|
||||||
resolution::get_closest_package_json::<Env::Fs>(
|
node_resolver.get_closest_package_json(
|
||||||
&Url::from_file_path(filename).unwrap(),
|
&Url::from_file_path(filename).unwrap(),
|
||||||
&*resolver,
|
|
||||||
permissions,
|
permissions,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -533,10 +540,12 @@ fn op_require_read_package_scope<Env>(
|
||||||
where
|
where
|
||||||
Env: NodeEnv + 'static,
|
Env: NodeEnv + 'static,
|
||||||
{
|
{
|
||||||
let resolver = state.borrow::<Rc<dyn NpmResolver>>().clone();
|
let node_resolver = state.borrow::<Rc<NodeResolver>>().clone();
|
||||||
let permissions = state.borrow_mut::<Env::P>();
|
let permissions = state.borrow_mut::<Env::P>();
|
||||||
let package_json_path = PathBuf::from(package_json_path);
|
let package_json_path = PathBuf::from(package_json_path);
|
||||||
PackageJson::load::<Env::Fs>(&*resolver, permissions, package_json_path).ok()
|
node_resolver
|
||||||
|
.load_package_json(permissions, package_json_path)
|
||||||
|
.ok()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[op]
|
#[op]
|
||||||
|
@ -550,29 +559,24 @@ where
|
||||||
{
|
{
|
||||||
let parent_path = PathBuf::from(&parent_filename);
|
let parent_path = PathBuf::from(&parent_filename);
|
||||||
ensure_read_permission::<Env::P>(state, &parent_path)?;
|
ensure_read_permission::<Env::P>(state, &parent_path)?;
|
||||||
let resolver = state.borrow::<Rc<dyn NpmResolver>>().clone();
|
let node_resolver = state.borrow::<Rc<NodeResolver>>().clone();
|
||||||
let permissions = state.borrow_mut::<Env::P>();
|
let permissions = state.borrow_mut::<Env::P>();
|
||||||
let pkg = PackageJson::load::<Env::Fs>(
|
let pkg = node_resolver
|
||||||
&*resolver,
|
.load_package_json(permissions, parent_path.join("package.json"))?;
|
||||||
permissions,
|
|
||||||
parent_path.join("package.json"),
|
|
||||||
)?;
|
|
||||||
|
|
||||||
if pkg.imports.is_some() {
|
if pkg.imports.is_some() {
|
||||||
let referrer =
|
let referrer =
|
||||||
deno_core::url::Url::from_file_path(&parent_filename).unwrap();
|
deno_core::url::Url::from_file_path(&parent_filename).unwrap();
|
||||||
let r = resolution::package_imports_resolve::<Env::Fs>(
|
node_resolver
|
||||||
&request,
|
.package_imports_resolve(
|
||||||
&referrer,
|
&request,
|
||||||
NodeModuleKind::Cjs,
|
&referrer,
|
||||||
resolution::REQUIRE_CONDITIONS,
|
NodeModuleKind::Cjs,
|
||||||
NodeResolutionMode::Execution,
|
resolution::REQUIRE_CONDITIONS,
|
||||||
&*resolver,
|
NodeResolutionMode::Execution,
|
||||||
permissions,
|
permissions,
|
||||||
)
|
)
|
||||||
.map(|r| Some(Url::from_file_path(r).unwrap().to_string()));
|
.map(|r| Some(Url::from_file_path(r).unwrap().to_string()))
|
||||||
state.put(resolver);
|
|
||||||
r
|
|
||||||
} else {
|
} else {
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,16 +62,18 @@ impl PackageJson {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn load<Fs: NodeFs>(
|
pub fn load(
|
||||||
|
fs: &dyn NodeFs,
|
||||||
resolver: &dyn NpmResolver,
|
resolver: &dyn NpmResolver,
|
||||||
permissions: &mut dyn NodePermissions,
|
permissions: &mut dyn NodePermissions,
|
||||||
path: PathBuf,
|
path: PathBuf,
|
||||||
) -> Result<PackageJson, AnyError> {
|
) -> Result<PackageJson, AnyError> {
|
||||||
resolver.ensure_read_permission(permissions, &path)?;
|
resolver.ensure_read_permission(permissions, &path)?;
|
||||||
Self::load_skip_read_permission::<Fs>(path)
|
Self::load_skip_read_permission(fs, path)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn load_skip_read_permission<Fs: NodeFs>(
|
pub fn load_skip_read_permission(
|
||||||
|
fs: &dyn NodeFs,
|
||||||
path: PathBuf,
|
path: PathBuf,
|
||||||
) -> Result<PackageJson, AnyError> {
|
) -> Result<PackageJson, AnyError> {
|
||||||
assert!(path.is_absolute());
|
assert!(path.is_absolute());
|
||||||
|
@ -80,7 +82,7 @@ impl PackageJson {
|
||||||
return Ok(CACHE.with(|cache| cache.borrow()[&path].clone()));
|
return Ok(CACHE.with(|cache| cache.borrow()[&path].clone()));
|
||||||
}
|
}
|
||||||
|
|
||||||
let source = match Fs::read_to_string(&path) {
|
let source = match fs.read_to_string(&path) {
|
||||||
Ok(source) => source,
|
Ok(source) => source,
|
||||||
Err(err) if err.kind() == ErrorKind::NotFound => {
|
Err(err) if err.kind() == ErrorKind::NotFound => {
|
||||||
return Ok(PackageJson::empty(path));
|
return Ok(PackageJson::empty(path));
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,686 +0,0 @@
|
||||||
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
|
|
||||||
|
|
||||||
use std::path::Path;
|
|
||||||
use std::path::PathBuf;
|
|
||||||
|
|
||||||
use deno_core::anyhow::bail;
|
|
||||||
use deno_core::anyhow::Context;
|
|
||||||
use deno_core::error::generic_error;
|
|
||||||
use deno_core::error::AnyError;
|
|
||||||
use deno_core::serde_json::Value;
|
|
||||||
use deno_core::url::Url;
|
|
||||||
use deno_core::ModuleSpecifier;
|
|
||||||
use deno_media_type::MediaType;
|
|
||||||
use deno_semver::npm::NpmPackageNv;
|
|
||||||
use deno_semver::npm::NpmPackageNvReference;
|
|
||||||
use deno_semver::npm::NpmPackageReqReference;
|
|
||||||
|
|
||||||
use crate::errors;
|
|
||||||
use crate::get_closest_package_json;
|
|
||||||
use crate::legacy_main_resolve;
|
|
||||||
use crate::package_exports_resolve;
|
|
||||||
use crate::package_imports_resolve;
|
|
||||||
use crate::package_resolve;
|
|
||||||
use crate::path_to_declaration_path;
|
|
||||||
use crate::AllowAllNodePermissions;
|
|
||||||
use crate::NodeFs;
|
|
||||||
use crate::NodeModuleKind;
|
|
||||||
use crate::NodePermissions;
|
|
||||||
use crate::NodeResolutionMode;
|
|
||||||
use crate::NpmResolver;
|
|
||||||
use crate::PackageJson;
|
|
||||||
use crate::DEFAULT_CONDITIONS;
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub enum NodeResolution {
|
|
||||||
Esm(ModuleSpecifier),
|
|
||||||
CommonJs(ModuleSpecifier),
|
|
||||||
BuiltIn(String),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl NodeResolution {
|
|
||||||
pub fn into_url(self) -> ModuleSpecifier {
|
|
||||||
match self {
|
|
||||||
Self::Esm(u) => u,
|
|
||||||
Self::CommonJs(u) => u,
|
|
||||||
Self::BuiltIn(specifier) => {
|
|
||||||
if specifier.starts_with("node:") {
|
|
||||||
ModuleSpecifier::parse(&specifier).unwrap()
|
|
||||||
} else {
|
|
||||||
ModuleSpecifier::parse(&format!("node:{specifier}")).unwrap()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn into_specifier_and_media_type(
|
|
||||||
resolution: Option<Self>,
|
|
||||||
) -> (ModuleSpecifier, MediaType) {
|
|
||||||
match resolution {
|
|
||||||
Some(NodeResolution::CommonJs(specifier)) => {
|
|
||||||
let media_type = MediaType::from_specifier(&specifier);
|
|
||||||
(
|
|
||||||
specifier,
|
|
||||||
match media_type {
|
|
||||||
MediaType::JavaScript | MediaType::Jsx => MediaType::Cjs,
|
|
||||||
MediaType::TypeScript | MediaType::Tsx => MediaType::Cts,
|
|
||||||
MediaType::Dts => MediaType::Dcts,
|
|
||||||
_ => media_type,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
Some(NodeResolution::Esm(specifier)) => {
|
|
||||||
let media_type = MediaType::from_specifier(&specifier);
|
|
||||||
(
|
|
||||||
specifier,
|
|
||||||
match media_type {
|
|
||||||
MediaType::JavaScript | MediaType::Jsx => MediaType::Mjs,
|
|
||||||
MediaType::TypeScript | MediaType::Tsx => MediaType::Mts,
|
|
||||||
MediaType::Dts => MediaType::Dmts,
|
|
||||||
_ => media_type,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
Some(resolution) => (resolution.into_url(), MediaType::Dts),
|
|
||||||
None => (
|
|
||||||
ModuleSpecifier::parse("internal:///missing_dependency.d.ts").unwrap(),
|
|
||||||
MediaType::Dts,
|
|
||||||
),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct NodeResolver<TRequireNpmResolver: NpmResolver> {
|
|
||||||
npm_resolver: TRequireNpmResolver,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<TRequireNpmResolver: NpmResolver> NodeResolver<TRequireNpmResolver> {
|
|
||||||
pub fn new(require_npm_resolver: TRequireNpmResolver) -> Self {
|
|
||||||
Self {
|
|
||||||
npm_resolver: require_npm_resolver,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn in_npm_package(&self, specifier: &ModuleSpecifier) -> bool {
|
|
||||||
self.npm_resolver.in_npm_package(specifier)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// This function is an implementation of `defaultResolve` in
|
|
||||||
/// `lib/internal/modules/esm/resolve.js` from Node.
|
|
||||||
pub fn resolve<Fs: NodeFs>(
|
|
||||||
&self,
|
|
||||||
specifier: &str,
|
|
||||||
referrer: &ModuleSpecifier,
|
|
||||||
mode: NodeResolutionMode,
|
|
||||||
permissions: &mut dyn NodePermissions,
|
|
||||||
) -> Result<Option<NodeResolution>, AnyError> {
|
|
||||||
// Note: if we are here, then the referrer is an esm module
|
|
||||||
// TODO(bartlomieju): skipped "policy" part as we don't plan to support it
|
|
||||||
|
|
||||||
if crate::is_builtin_node_module(specifier) {
|
|
||||||
return Ok(Some(NodeResolution::BuiltIn(specifier.to_string())));
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Ok(url) = Url::parse(specifier) {
|
|
||||||
if url.scheme() == "data" {
|
|
||||||
return Ok(Some(NodeResolution::Esm(url)));
|
|
||||||
}
|
|
||||||
|
|
||||||
let protocol = url.scheme();
|
|
||||||
|
|
||||||
if protocol == "node" {
|
|
||||||
let split_specifier = url.as_str().split(':');
|
|
||||||
let specifier = split_specifier.skip(1).collect::<String>();
|
|
||||||
|
|
||||||
if crate::is_builtin_node_module(&specifier) {
|
|
||||||
return Ok(Some(NodeResolution::BuiltIn(specifier)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if protocol != "file" && protocol != "data" {
|
|
||||||
return Err(errors::err_unsupported_esm_url_scheme(&url));
|
|
||||||
}
|
|
||||||
|
|
||||||
// todo(dsherret): this seems wrong
|
|
||||||
if referrer.scheme() == "data" {
|
|
||||||
let url = referrer.join(specifier).map_err(AnyError::from)?;
|
|
||||||
return Ok(Some(NodeResolution::Esm(url)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let url = self.module_resolve::<Fs>(
|
|
||||||
specifier,
|
|
||||||
referrer,
|
|
||||||
DEFAULT_CONDITIONS,
|
|
||||||
mode,
|
|
||||||
permissions,
|
|
||||||
)?;
|
|
||||||
let url = match url {
|
|
||||||
Some(url) => url,
|
|
||||||
None => return Ok(None),
|
|
||||||
};
|
|
||||||
let url = match mode {
|
|
||||||
NodeResolutionMode::Execution => url,
|
|
||||||
NodeResolutionMode::Types => {
|
|
||||||
let path = url.to_file_path().unwrap();
|
|
||||||
// todo(16370): the module kind is not correct here. I think we need
|
|
||||||
// typescript to tell us if the referrer is esm or cjs
|
|
||||||
let path =
|
|
||||||
match path_to_declaration_path::<Fs>(path, NodeModuleKind::Esm) {
|
|
||||||
Some(path) => path,
|
|
||||||
None => return Ok(None),
|
|
||||||
};
|
|
||||||
ModuleSpecifier::from_file_path(path).unwrap()
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let resolve_response = self.url_to_node_resolution::<Fs>(url)?;
|
|
||||||
// TODO(bartlomieju): skipped checking errors for commonJS resolution and
|
|
||||||
// "preserveSymlinksMain"/"preserveSymlinks" options.
|
|
||||||
Ok(Some(resolve_response))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn module_resolve<Fs: NodeFs>(
|
|
||||||
&self,
|
|
||||||
specifier: &str,
|
|
||||||
referrer: &ModuleSpecifier,
|
|
||||||
conditions: &[&str],
|
|
||||||
mode: NodeResolutionMode,
|
|
||||||
permissions: &mut dyn NodePermissions,
|
|
||||||
) -> Result<Option<ModuleSpecifier>, AnyError> {
|
|
||||||
// note: if we're here, the referrer is an esm module
|
|
||||||
let url = if should_be_treated_as_relative_or_absolute_path(specifier) {
|
|
||||||
let resolved_specifier = referrer.join(specifier)?;
|
|
||||||
if mode.is_types() {
|
|
||||||
let file_path = to_file_path(&resolved_specifier);
|
|
||||||
// todo(dsherret): the node module kind is not correct and we
|
|
||||||
// should use the value provided by typescript instead
|
|
||||||
let declaration_path =
|
|
||||||
path_to_declaration_path::<Fs>(file_path, NodeModuleKind::Esm);
|
|
||||||
declaration_path.map(|declaration_path| {
|
|
||||||
ModuleSpecifier::from_file_path(declaration_path).unwrap()
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
Some(resolved_specifier)
|
|
||||||
}
|
|
||||||
} else if specifier.starts_with('#') {
|
|
||||||
Some(
|
|
||||||
package_imports_resolve::<Fs>(
|
|
||||||
specifier,
|
|
||||||
referrer,
|
|
||||||
NodeModuleKind::Esm,
|
|
||||||
conditions,
|
|
||||||
mode,
|
|
||||||
&self.npm_resolver,
|
|
||||||
permissions,
|
|
||||||
)
|
|
||||||
.map(|p| ModuleSpecifier::from_file_path(p).unwrap())?,
|
|
||||||
)
|
|
||||||
} else if let Ok(resolved) = Url::parse(specifier) {
|
|
||||||
Some(resolved)
|
|
||||||
} else {
|
|
||||||
package_resolve::<Fs>(
|
|
||||||
specifier,
|
|
||||||
referrer,
|
|
||||||
NodeModuleKind::Esm,
|
|
||||||
conditions,
|
|
||||||
mode,
|
|
||||||
&self.npm_resolver,
|
|
||||||
permissions,
|
|
||||||
)?
|
|
||||||
.map(|p| ModuleSpecifier::from_file_path(p).unwrap())
|
|
||||||
};
|
|
||||||
Ok(match url {
|
|
||||||
Some(url) => Some(finalize_resolution::<Fs>(url, referrer)?),
|
|
||||||
None => None,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn resolve_npm_req_reference<Fs: NodeFs>(
|
|
||||||
&self,
|
|
||||||
reference: &NpmPackageReqReference,
|
|
||||||
mode: NodeResolutionMode,
|
|
||||||
permissions: &mut dyn NodePermissions,
|
|
||||||
) -> Result<Option<NodeResolution>, AnyError> {
|
|
||||||
let reference = self
|
|
||||||
.npm_resolver
|
|
||||||
.resolve_nv_ref_from_pkg_req_ref(reference)?;
|
|
||||||
self.resolve_npm_reference::<Fs>(&reference, mode, permissions)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn resolve_npm_reference<Fs: NodeFs>(
|
|
||||||
&self,
|
|
||||||
reference: &NpmPackageNvReference,
|
|
||||||
mode: NodeResolutionMode,
|
|
||||||
permissions: &mut dyn NodePermissions,
|
|
||||||
) -> Result<Option<NodeResolution>, AnyError> {
|
|
||||||
let package_folder = self
|
|
||||||
.npm_resolver
|
|
||||||
.resolve_package_folder_from_deno_module(&reference.nv)?;
|
|
||||||
let node_module_kind = NodeModuleKind::Esm;
|
|
||||||
let maybe_resolved_path = package_config_resolve::<Fs>(
|
|
||||||
&reference
|
|
||||||
.sub_path
|
|
||||||
.as_ref()
|
|
||||||
.map(|s| format!("./{s}"))
|
|
||||||
.unwrap_or_else(|| ".".to_string()),
|
|
||||||
&package_folder,
|
|
||||||
node_module_kind,
|
|
||||||
DEFAULT_CONDITIONS,
|
|
||||||
mode,
|
|
||||||
&self.npm_resolver,
|
|
||||||
permissions,
|
|
||||||
)
|
|
||||||
.with_context(|| {
|
|
||||||
format!("Error resolving package config for '{reference}'")
|
|
||||||
})?;
|
|
||||||
let resolved_path = match maybe_resolved_path {
|
|
||||||
Some(resolved_path) => resolved_path,
|
|
||||||
None => return Ok(None),
|
|
||||||
};
|
|
||||||
let resolved_path = match mode {
|
|
||||||
NodeResolutionMode::Execution => resolved_path,
|
|
||||||
NodeResolutionMode::Types => {
|
|
||||||
match path_to_declaration_path::<Fs>(resolved_path, node_module_kind) {
|
|
||||||
Some(path) => path,
|
|
||||||
None => return Ok(None),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
let url = ModuleSpecifier::from_file_path(resolved_path).unwrap();
|
|
||||||
let resolve_response = self.url_to_node_resolution::<Fs>(url)?;
|
|
||||||
// TODO(bartlomieju): skipped checking errors for commonJS resolution and
|
|
||||||
// "preserveSymlinksMain"/"preserveSymlinks" options.
|
|
||||||
Ok(Some(resolve_response))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn resolve_binary_commands<Fs: NodeFs>(
|
|
||||||
&self,
|
|
||||||
pkg_nv: &NpmPackageNv,
|
|
||||||
) -> Result<Vec<String>, AnyError> {
|
|
||||||
let package_folder = self
|
|
||||||
.npm_resolver
|
|
||||||
.resolve_package_folder_from_deno_module(pkg_nv)?;
|
|
||||||
let package_json_path = package_folder.join("package.json");
|
|
||||||
let package_json = PackageJson::load::<Fs>(
|
|
||||||
&self.npm_resolver,
|
|
||||||
&mut AllowAllNodePermissions,
|
|
||||||
package_json_path,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
Ok(match package_json.bin {
|
|
||||||
Some(Value::String(_)) => vec![pkg_nv.name.to_string()],
|
|
||||||
Some(Value::Object(o)) => {
|
|
||||||
o.into_iter().map(|(key, _)| key).collect::<Vec<_>>()
|
|
||||||
}
|
|
||||||
_ => Vec::new(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn resolve_binary_export<Fs: NodeFs>(
|
|
||||||
&self,
|
|
||||||
pkg_ref: &NpmPackageReqReference,
|
|
||||||
) -> Result<NodeResolution, AnyError> {
|
|
||||||
let pkg_nv = self
|
|
||||||
.npm_resolver
|
|
||||||
.resolve_pkg_id_from_pkg_req(&pkg_ref.req)?
|
|
||||||
.nv;
|
|
||||||
let bin_name = pkg_ref.sub_path.as_deref();
|
|
||||||
let package_folder = self
|
|
||||||
.npm_resolver
|
|
||||||
.resolve_package_folder_from_deno_module(&pkg_nv)?;
|
|
||||||
let package_json_path = package_folder.join("package.json");
|
|
||||||
let package_json = PackageJson::load::<Fs>(
|
|
||||||
&self.npm_resolver,
|
|
||||||
&mut AllowAllNodePermissions,
|
|
||||||
package_json_path,
|
|
||||||
)?;
|
|
||||||
let bin = match &package_json.bin {
|
|
||||||
Some(bin) => bin,
|
|
||||||
None => bail!(
|
|
||||||
"package '{}' did not have a bin property in its package.json",
|
|
||||||
&pkg_nv.name,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
let bin_entry = resolve_bin_entry_value(&pkg_nv, bin_name, bin)?;
|
|
||||||
let url =
|
|
||||||
ModuleSpecifier::from_file_path(package_folder.join(bin_entry)).unwrap();
|
|
||||||
|
|
||||||
let resolve_response = self.url_to_node_resolution::<Fs>(url)?;
|
|
||||||
// TODO(bartlomieju): skipped checking errors for commonJS resolution and
|
|
||||||
// "preserveSymlinksMain"/"preserveSymlinks" options.
|
|
||||||
Ok(resolve_response)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn url_to_node_resolution<Fs: NodeFs>(
|
|
||||||
&self,
|
|
||||||
url: ModuleSpecifier,
|
|
||||||
) -> Result<NodeResolution, AnyError> {
|
|
||||||
let url_str = url.as_str().to_lowercase();
|
|
||||||
if url_str.starts_with("http") {
|
|
||||||
Ok(NodeResolution::Esm(url))
|
|
||||||
} else if url_str.ends_with(".js") || url_str.ends_with(".d.ts") {
|
|
||||||
let package_config = get_closest_package_json::<Fs>(
|
|
||||||
&url,
|
|
||||||
&self.npm_resolver,
|
|
||||||
&mut AllowAllNodePermissions,
|
|
||||||
)?;
|
|
||||||
if package_config.typ == "module" {
|
|
||||||
Ok(NodeResolution::Esm(url))
|
|
||||||
} else {
|
|
||||||
Ok(NodeResolution::CommonJs(url))
|
|
||||||
}
|
|
||||||
} else if url_str.ends_with(".mjs") || url_str.ends_with(".d.mts") {
|
|
||||||
Ok(NodeResolution::Esm(url))
|
|
||||||
} else if url_str.ends_with(".ts") {
|
|
||||||
Err(generic_error(format!(
|
|
||||||
"TypeScript files are not supported in npm packages: {url}"
|
|
||||||
)))
|
|
||||||
} else {
|
|
||||||
Ok(NodeResolution::CommonJs(url))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn resolve_bin_entry_value<'a>(
|
|
||||||
pkg_nv: &NpmPackageNv,
|
|
||||||
bin_name: Option<&str>,
|
|
||||||
bin: &'a Value,
|
|
||||||
) -> Result<&'a str, AnyError> {
|
|
||||||
let bin_entry = match bin {
|
|
||||||
Value::String(_) => {
|
|
||||||
if bin_name.is_some() && bin_name.unwrap() != pkg_nv.name {
|
|
||||||
None
|
|
||||||
} else {
|
|
||||||
Some(bin)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Value::Object(o) => {
|
|
||||||
if let Some(bin_name) = bin_name {
|
|
||||||
o.get(bin_name)
|
|
||||||
} else if o.len() == 1 || o.len() > 1 && o.values().all(|v| v == o.values().next().unwrap()) {
|
|
||||||
o.values().next()
|
|
||||||
} else {
|
|
||||||
o.get(&pkg_nv.name)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
_ => bail!("package '{}' did not have a bin property with a string or object value in its package.json", pkg_nv),
|
|
||||||
};
|
|
||||||
let bin_entry = match bin_entry {
|
|
||||||
Some(e) => e,
|
|
||||||
None => {
|
|
||||||
let keys = bin
|
|
||||||
.as_object()
|
|
||||||
.map(|o| {
|
|
||||||
o.keys()
|
|
||||||
.map(|k| format!(" * npm:{pkg_nv}/{k}"))
|
|
||||||
.collect::<Vec<_>>()
|
|
||||||
})
|
|
||||||
.unwrap_or_default();
|
|
||||||
bail!(
|
|
||||||
"package '{}' did not have a bin entry for '{}' in its package.json{}",
|
|
||||||
pkg_nv,
|
|
||||||
bin_name.unwrap_or(&pkg_nv.name),
|
|
||||||
if keys.is_empty() {
|
|
||||||
"".to_string()
|
|
||||||
} else {
|
|
||||||
format!("\n\nPossibilities:\n{}", keys.join("\n"))
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
match bin_entry {
|
|
||||||
Value::String(s) => Ok(s),
|
|
||||||
_ => bail!(
|
|
||||||
"package '{}' had a non-string sub property of bin in its package.json",
|
|
||||||
pkg_nv,
|
|
||||||
),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn package_config_resolve<Fs: NodeFs>(
|
|
||||||
package_subpath: &str,
|
|
||||||
package_dir: &Path,
|
|
||||||
referrer_kind: NodeModuleKind,
|
|
||||||
conditions: &[&str],
|
|
||||||
mode: NodeResolutionMode,
|
|
||||||
npm_resolver: &dyn NpmResolver,
|
|
||||||
permissions: &mut dyn NodePermissions,
|
|
||||||
) -> Result<Option<PathBuf>, AnyError> {
|
|
||||||
let package_json_path = package_dir.join("package.json");
|
|
||||||
let referrer = ModuleSpecifier::from_directory_path(package_dir).unwrap();
|
|
||||||
let package_config = PackageJson::load::<Fs>(
|
|
||||||
npm_resolver,
|
|
||||||
permissions,
|
|
||||||
package_json_path.clone(),
|
|
||||||
)?;
|
|
||||||
if let Some(exports) = &package_config.exports {
|
|
||||||
let result = package_exports_resolve::<Fs>(
|
|
||||||
&package_json_path,
|
|
||||||
package_subpath.to_string(),
|
|
||||||
exports,
|
|
||||||
&referrer,
|
|
||||||
referrer_kind,
|
|
||||||
conditions,
|
|
||||||
mode,
|
|
||||||
npm_resolver,
|
|
||||||
permissions,
|
|
||||||
);
|
|
||||||
match result {
|
|
||||||
Ok(found) => return Ok(Some(found)),
|
|
||||||
Err(exports_err) => {
|
|
||||||
if mode.is_types() && package_subpath == "." {
|
|
||||||
if let Ok(Some(path)) =
|
|
||||||
legacy_main_resolve::<Fs>(&package_config, referrer_kind, mode)
|
|
||||||
{
|
|
||||||
return Ok(Some(path));
|
|
||||||
} else {
|
|
||||||
return Ok(None);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return Err(exports_err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if package_subpath == "." {
|
|
||||||
return legacy_main_resolve::<Fs>(&package_config, referrer_kind, mode);
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(Some(package_dir.join(package_subpath)))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn finalize_resolution<Fs: NodeFs>(
|
|
||||||
resolved: ModuleSpecifier,
|
|
||||||
base: &ModuleSpecifier,
|
|
||||||
) -> Result<ModuleSpecifier, AnyError> {
|
|
||||||
let encoded_sep_re = lazy_regex::regex!(r"%2F|%2C");
|
|
||||||
|
|
||||||
if encoded_sep_re.is_match(resolved.path()) {
|
|
||||||
return Err(errors::err_invalid_module_specifier(
|
|
||||||
resolved.path(),
|
|
||||||
"must not include encoded \"/\" or \"\\\\\" characters",
|
|
||||||
Some(to_file_path_string(base)),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
let path = to_file_path(&resolved);
|
|
||||||
|
|
||||||
// TODO(bartlomieju): currently not supported
|
|
||||||
// if (getOptionValue('--experimental-specifier-resolution') === 'node') {
|
|
||||||
// ...
|
|
||||||
// }
|
|
||||||
|
|
||||||
let p_str = path.to_str().unwrap();
|
|
||||||
let p = if p_str.ends_with('/') {
|
|
||||||
p_str[p_str.len() - 1..].to_string()
|
|
||||||
} else {
|
|
||||||
p_str.to_string()
|
|
||||||
};
|
|
||||||
|
|
||||||
let (is_dir, is_file) = if let Ok(stats) = Fs::metadata(p) {
|
|
||||||
(stats.is_dir, stats.is_file)
|
|
||||||
} else {
|
|
||||||
(false, false)
|
|
||||||
};
|
|
||||||
if is_dir {
|
|
||||||
return Err(errors::err_unsupported_dir_import(
|
|
||||||
resolved.as_str(),
|
|
||||||
base.as_str(),
|
|
||||||
));
|
|
||||||
} else if !is_file {
|
|
||||||
return Err(errors::err_module_not_found(
|
|
||||||
resolved.as_str(),
|
|
||||||
base.as_str(),
|
|
||||||
"module",
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(resolved)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn to_file_path(url: &ModuleSpecifier) -> PathBuf {
|
|
||||||
url
|
|
||||||
.to_file_path()
|
|
||||||
.unwrap_or_else(|_| panic!("Provided URL was not file:// URL: {url}"))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn to_file_path_string(url: &ModuleSpecifier) -> String {
|
|
||||||
to_file_path(url).display().to_string()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn should_be_treated_as_relative_or_absolute_path(specifier: &str) -> bool {
|
|
||||||
if specifier.is_empty() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if specifier.starts_with('/') {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
is_relative_specifier(specifier)
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO(ry) We very likely have this utility function elsewhere in Deno.
|
|
||||||
fn is_relative_specifier(specifier: &str) -> bool {
|
|
||||||
let specifier_len = specifier.len();
|
|
||||||
let specifier_chars: Vec<_> = specifier.chars().collect();
|
|
||||||
|
|
||||||
if !specifier_chars.is_empty() && specifier_chars[0] == '.' {
|
|
||||||
if specifier_len == 1 || specifier_chars[1] == '/' {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if specifier_chars[1] == '.'
|
|
||||||
&& (specifier_len == 2 || specifier_chars[2] == '/')
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
false
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use deno_core::serde_json::json;
|
|
||||||
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_resolve_bin_entry_value() {
|
|
||||||
// should resolve the specified value
|
|
||||||
let value = json!({
|
|
||||||
"bin1": "./value1",
|
|
||||||
"bin2": "./value2",
|
|
||||||
"test": "./value3",
|
|
||||||
});
|
|
||||||
assert_eq!(
|
|
||||||
resolve_bin_entry_value(
|
|
||||||
&NpmPackageNv::from_str("test@1.1.1").unwrap(),
|
|
||||||
Some("bin1"),
|
|
||||||
&value
|
|
||||||
)
|
|
||||||
.unwrap(),
|
|
||||||
"./value1"
|
|
||||||
);
|
|
||||||
|
|
||||||
// should resolve the value with the same name when not specified
|
|
||||||
assert_eq!(
|
|
||||||
resolve_bin_entry_value(
|
|
||||||
&NpmPackageNv::from_str("test@1.1.1").unwrap(),
|
|
||||||
None,
|
|
||||||
&value
|
|
||||||
)
|
|
||||||
.unwrap(),
|
|
||||||
"./value3"
|
|
||||||
);
|
|
||||||
|
|
||||||
// should not resolve when specified value does not exist
|
|
||||||
assert_eq!(
|
|
||||||
resolve_bin_entry_value(
|
|
||||||
&NpmPackageNv::from_str("test@1.1.1").unwrap(),
|
|
||||||
Some("other"),
|
|
||||||
&value
|
|
||||||
)
|
|
||||||
.err()
|
|
||||||
.unwrap()
|
|
||||||
.to_string(),
|
|
||||||
concat!(
|
|
||||||
"package 'test@1.1.1' did not have a bin entry for 'other' in its package.json\n",
|
|
||||||
"\n",
|
|
||||||
"Possibilities:\n",
|
|
||||||
" * npm:test@1.1.1/bin1\n",
|
|
||||||
" * npm:test@1.1.1/bin2\n",
|
|
||||||
" * npm:test@1.1.1/test"
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
// should not resolve when default value can't be determined
|
|
||||||
assert_eq!(
|
|
||||||
resolve_bin_entry_value(
|
|
||||||
&NpmPackageNv::from_str("asdf@1.2.3").unwrap(),
|
|
||||||
None,
|
|
||||||
&value
|
|
||||||
)
|
|
||||||
.err()
|
|
||||||
.unwrap()
|
|
||||||
.to_string(),
|
|
||||||
concat!(
|
|
||||||
"package 'asdf@1.2.3' did not have a bin entry for 'asdf' in its package.json\n",
|
|
||||||
"\n",
|
|
||||||
"Possibilities:\n",
|
|
||||||
" * npm:asdf@1.2.3/bin1\n",
|
|
||||||
" * npm:asdf@1.2.3/bin2\n",
|
|
||||||
" * npm:asdf@1.2.3/test"
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
// should resolve since all the values are the same
|
|
||||||
let value = json!({
|
|
||||||
"bin1": "./value",
|
|
||||||
"bin2": "./value",
|
|
||||||
});
|
|
||||||
assert_eq!(
|
|
||||||
resolve_bin_entry_value(
|
|
||||||
&NpmPackageNv::from_str("test@1.2.3").unwrap(),
|
|
||||||
None,
|
|
||||||
&value
|
|
||||||
)
|
|
||||||
.unwrap(),
|
|
||||||
"./value"
|
|
||||||
);
|
|
||||||
|
|
||||||
// should not resolve when specified and is a string
|
|
||||||
let value = json!("./value");
|
|
||||||
assert_eq!(
|
|
||||||
resolve_bin_entry_value(
|
|
||||||
&NpmPackageNv::from_str("test@1.2.3").unwrap(),
|
|
||||||
Some("path"),
|
|
||||||
&value
|
|
||||||
)
|
|
||||||
.err()
|
|
||||||
.unwrap()
|
|
||||||
.to_string(),
|
|
||||||
"package 'test@1.2.3' did not have a bin entry for 'path' in its package.json"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -222,7 +222,6 @@ mod startup_snapshot {
|
||||||
|
|
||||||
impl deno_node::NodeEnv for SnapshotNodeEnv {
|
impl deno_node::NodeEnv for SnapshotNodeEnv {
|
||||||
type P = Permissions;
|
type P = Permissions;
|
||||||
type Fs = deno_node::RealFs;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
deno_core::extension!(runtime,
|
deno_core::extension!(runtime,
|
||||||
|
@ -324,7 +323,7 @@ mod startup_snapshot {
|
||||||
runtime::init_ops_and_esm(),
|
runtime::init_ops_and_esm(),
|
||||||
// FIXME(bartlomieju): these extensions are specified last, because they
|
// FIXME(bartlomieju): these extensions are specified last, because they
|
||||||
// depend on `runtime`, even though it should be other way around
|
// depend on `runtime`, even though it should be other way around
|
||||||
deno_node::deno_node::init_ops_and_esm::<SnapshotNodeEnv>(None),
|
deno_node::deno_node::init_ops_and_esm::<SnapshotNodeEnv>(None, None),
|
||||||
#[cfg(not(feature = "snapshot_from_snapshot"))]
|
#[cfg(not(feature = "snapshot_from_snapshot"))]
|
||||||
runtime_main::init_ops_and_esm(),
|
runtime_main::init_ops_and_esm(),
|
||||||
];
|
];
|
||||||
|
|
|
@ -43,6 +43,7 @@ async fn main() -> Result<(), AnyError> {
|
||||||
should_break_on_first_statement: false,
|
should_break_on_first_statement: false,
|
||||||
should_wait_for_inspector_session: false,
|
should_wait_for_inspector_session: false,
|
||||||
module_loader,
|
module_loader,
|
||||||
|
node_fs: None,
|
||||||
npm_resolver: None,
|
npm_resolver: None,
|
||||||
get_error_class_fn: Some(&get_error_class_name),
|
get_error_class_fn: Some(&get_error_class_name),
|
||||||
cache_storage_dir: None,
|
cache_storage_dir: None,
|
||||||
|
|
|
@ -39,5 +39,4 @@ pub use worker_bootstrap::BootstrapOptions;
|
||||||
pub struct RuntimeNodeEnv;
|
pub struct RuntimeNodeEnv;
|
||||||
impl deno_node::NodeEnv for RuntimeNodeEnv {
|
impl deno_node::NodeEnv for RuntimeNodeEnv {
|
||||||
type P = permissions::PermissionsContainer;
|
type P = permissions::PermissionsContainer;
|
||||||
type Fs = deno_node::RealFs;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,7 +37,6 @@ use deno_core::SourceMapGetter;
|
||||||
use deno_fs::StdFs;
|
use deno_fs::StdFs;
|
||||||
use deno_io::Stdio;
|
use deno_io::Stdio;
|
||||||
use deno_kv::sqlite::SqliteDbHandler;
|
use deno_kv::sqlite::SqliteDbHandler;
|
||||||
use deno_node::NpmResolver;
|
|
||||||
use deno_tls::rustls::RootCertStore;
|
use deno_tls::rustls::RootCertStore;
|
||||||
use deno_web::create_entangled_message_port;
|
use deno_web::create_entangled_message_port;
|
||||||
use deno_web::BlobStore;
|
use deno_web::BlobStore;
|
||||||
|
@ -333,7 +332,8 @@ pub struct WebWorkerOptions {
|
||||||
pub root_cert_store: Option<RootCertStore>,
|
pub root_cert_store: Option<RootCertStore>,
|
||||||
pub seed: Option<u64>,
|
pub seed: Option<u64>,
|
||||||
pub module_loader: Rc<dyn ModuleLoader>,
|
pub module_loader: Rc<dyn ModuleLoader>,
|
||||||
pub npm_resolver: Option<Rc<dyn NpmResolver>>,
|
pub node_fs: Option<Arc<dyn deno_node::NodeFs>>,
|
||||||
|
pub npm_resolver: Option<Arc<dyn deno_node::NpmResolver>>,
|
||||||
pub create_web_worker_cb: Arc<ops::worker_host::CreateWebWorkerCb>,
|
pub create_web_worker_cb: Arc<ops::worker_host::CreateWebWorkerCb>,
|
||||||
pub preload_module_cb: Arc<ops::worker_host::WorkerEventCb>,
|
pub preload_module_cb: Arc<ops::worker_host::WorkerEventCb>,
|
||||||
pub pre_execute_module_cb: Arc<ops::worker_host::WorkerEventCb>,
|
pub pre_execute_module_cb: Arc<ops::worker_host::WorkerEventCb>,
|
||||||
|
@ -444,6 +444,7 @@ impl WebWorker {
|
||||||
deno_fs::deno_fs::init_ops::<_, PermissionsContainer>(unstable, StdFs),
|
deno_fs::deno_fs::init_ops::<_, PermissionsContainer>(unstable, StdFs),
|
||||||
deno_node::deno_node::init_ops::<crate::RuntimeNodeEnv>(
|
deno_node::deno_node::init_ops::<crate::RuntimeNodeEnv>(
|
||||||
options.npm_resolver,
|
options.npm_resolver,
|
||||||
|
options.node_fs,
|
||||||
),
|
),
|
||||||
// Runtime ops that are always initialized for WebWorkers
|
// Runtime ops that are always initialized for WebWorkers
|
||||||
ops::web_worker::deno_web_worker::init_ops(),
|
ops::web_worker::deno_web_worker::init_ops(),
|
||||||
|
|
|
@ -33,7 +33,6 @@ use deno_core::SourceMapGetter;
|
||||||
use deno_fs::StdFs;
|
use deno_fs::StdFs;
|
||||||
use deno_io::Stdio;
|
use deno_io::Stdio;
|
||||||
use deno_kv::sqlite::SqliteDbHandler;
|
use deno_kv::sqlite::SqliteDbHandler;
|
||||||
use deno_node::NpmResolver;
|
|
||||||
use deno_tls::rustls::RootCertStore;
|
use deno_tls::rustls::RootCertStore;
|
||||||
use deno_web::BlobStore;
|
use deno_web::BlobStore;
|
||||||
use log::debug;
|
use log::debug;
|
||||||
|
@ -94,7 +93,8 @@ pub struct WorkerOptions {
|
||||||
/// If not provided runtime will error if code being
|
/// If not provided runtime will error if code being
|
||||||
/// executed tries to load modules.
|
/// executed tries to load modules.
|
||||||
pub module_loader: Rc<dyn ModuleLoader>,
|
pub module_loader: Rc<dyn ModuleLoader>,
|
||||||
pub npm_resolver: Option<Rc<dyn NpmResolver>>,
|
pub node_fs: Option<Arc<dyn deno_node::NodeFs>>,
|
||||||
|
pub npm_resolver: Option<Arc<dyn deno_node::NpmResolver>>,
|
||||||
// Callbacks invoked when creating new instance of WebWorker
|
// Callbacks invoked when creating new instance of WebWorker
|
||||||
pub create_web_worker_cb: Arc<ops::worker_host::CreateWebWorkerCb>,
|
pub create_web_worker_cb: Arc<ops::worker_host::CreateWebWorkerCb>,
|
||||||
pub web_worker_preload_module_cb: Arc<ops::worker_host::WorkerEventCb>,
|
pub web_worker_preload_module_cb: Arc<ops::worker_host::WorkerEventCb>,
|
||||||
|
@ -164,6 +164,7 @@ impl Default for WorkerOptions {
|
||||||
broadcast_channel: Default::default(),
|
broadcast_channel: Default::default(),
|
||||||
source_map_getter: Default::default(),
|
source_map_getter: Default::default(),
|
||||||
root_cert_store: Default::default(),
|
root_cert_store: Default::default(),
|
||||||
|
node_fs: Default::default(),
|
||||||
npm_resolver: Default::default(),
|
npm_resolver: Default::default(),
|
||||||
blob_store: Default::default(),
|
blob_store: Default::default(),
|
||||||
extensions: Default::default(),
|
extensions: Default::default(),
|
||||||
|
@ -268,6 +269,7 @@ impl MainWorker {
|
||||||
deno_fs::deno_fs::init_ops::<_, PermissionsContainer>(unstable, StdFs),
|
deno_fs::deno_fs::init_ops::<_, PermissionsContainer>(unstable, StdFs),
|
||||||
deno_node::deno_node::init_ops::<crate::RuntimeNodeEnv>(
|
deno_node::deno_node::init_ops::<crate::RuntimeNodeEnv>(
|
||||||
options.npm_resolver,
|
options.npm_resolver,
|
||||||
|
options.node_fs,
|
||||||
),
|
),
|
||||||
// Ops from this crate
|
// Ops from this crate
|
||||||
ops::runtime::deno_runtime::init_ops(main_module.clone()),
|
ops::runtime::deno_runtime::init_ops(main_module.clone()),
|
||||||
|
|
Loading…
Add table
Reference in a new issue