mirror of
https://github.com/denoland/deno.git
synced 2024-11-28 16:20:57 -05:00
refactor(npm): add CliNodeResolver (#18742)
This commit is contained in:
parent
7762566a6a
commit
772e4c033f
16 changed files with 474 additions and 442 deletions
|
@ -17,11 +17,9 @@ use crate::file_fetcher::get_source_from_bytes;
|
|||
use crate::file_fetcher::map_content_type;
|
||||
use crate::file_fetcher::SUPPORTED_SCHEMES;
|
||||
use crate::lsp::logging::lsp_warn;
|
||||
use crate::node;
|
||||
use crate::node::node_resolve_npm_reference;
|
||||
use crate::node::CliNodeResolver;
|
||||
use crate::node::NodeResolution;
|
||||
use crate::npm::CliNpmRegistryApi;
|
||||
use crate::npm::NpmPackageResolver;
|
||||
use crate::npm::NpmResolution;
|
||||
use crate::npm::PackageJsonDepsInstaller;
|
||||
use crate::resolver::CliGraphResolver;
|
||||
|
@ -1057,7 +1055,7 @@ impl Documents {
|
|||
&self,
|
||||
specifiers: Vec<String>,
|
||||
referrer_doc: &AssetOrDocument,
|
||||
maybe_npm_resolver: Option<&Arc<NpmPackageResolver>>,
|
||||
maybe_node_resolver: Option<&Arc<CliNodeResolver>>,
|
||||
) -> Vec<Option<(ModuleSpecifier, MediaType)>> {
|
||||
let referrer = referrer_doc.specifier();
|
||||
let dependencies = match referrer_doc {
|
||||
|
@ -1066,19 +1064,19 @@ impl Documents {
|
|||
};
|
||||
let mut results = Vec::new();
|
||||
for specifier in specifiers {
|
||||
if let Some(npm_resolver) = maybe_npm_resolver {
|
||||
if npm_resolver.in_npm_package(referrer) {
|
||||
if let Some(node_resolver) = maybe_node_resolver {
|
||||
if node_resolver.in_npm_package(referrer) {
|
||||
// we're in an npm package, so use node resolution
|
||||
results.push(Some(NodeResolution::into_specifier_and_media_type(
|
||||
node::node_resolve(
|
||||
&specifier,
|
||||
referrer,
|
||||
NodeResolutionMode::Types,
|
||||
&npm_resolver.as_require_npm_resolver(),
|
||||
&mut PermissionsContainer::allow_all(),
|
||||
)
|
||||
.ok()
|
||||
.flatten(),
|
||||
node_resolver
|
||||
.resolve(
|
||||
&specifier,
|
||||
referrer,
|
||||
NodeResolutionMode::Types,
|
||||
&mut PermissionsContainer::allow_all(),
|
||||
)
|
||||
.ok()
|
||||
.flatten(),
|
||||
)));
|
||||
continue;
|
||||
}
|
||||
|
@ -1106,9 +1104,9 @@ impl Documents {
|
|||
dependencies.as_ref().and_then(|d| d.deps.get(&specifier))
|
||||
{
|
||||
if let Some(specifier) = dep.maybe_type.maybe_specifier() {
|
||||
results.push(self.resolve_dependency(specifier, maybe_npm_resolver));
|
||||
results.push(self.resolve_dependency(specifier, maybe_node_resolver));
|
||||
} else if let Some(specifier) = dep.maybe_code.maybe_specifier() {
|
||||
results.push(self.resolve_dependency(specifier, maybe_npm_resolver));
|
||||
results.push(self.resolve_dependency(specifier, maybe_node_resolver));
|
||||
} else {
|
||||
results.push(None);
|
||||
}
|
||||
|
@ -1116,11 +1114,12 @@ impl Documents {
|
|||
.resolve_imports_dependency(&specifier)
|
||||
.and_then(|r| r.maybe_specifier())
|
||||
{
|
||||
results.push(self.resolve_dependency(specifier, maybe_npm_resolver));
|
||||
results.push(self.resolve_dependency(specifier, maybe_node_resolver));
|
||||
} else if let Ok(npm_req_ref) =
|
||||
NpmPackageReqReference::from_str(&specifier)
|
||||
{
|
||||
results.push(node_resolve_npm_req_ref(npm_req_ref, maybe_npm_resolver));
|
||||
results
|
||||
.push(node_resolve_npm_req_ref(npm_req_ref, maybe_node_resolver));
|
||||
} else {
|
||||
results.push(None);
|
||||
}
|
||||
|
@ -1418,10 +1417,10 @@ impl Documents {
|
|||
fn resolve_dependency(
|
||||
&self,
|
||||
specifier: &ModuleSpecifier,
|
||||
maybe_npm_resolver: Option<&Arc<NpmPackageResolver>>,
|
||||
maybe_node_resolver: Option<&Arc<CliNodeResolver>>,
|
||||
) -> Option<(ModuleSpecifier, MediaType)> {
|
||||
if let Ok(npm_ref) = NpmPackageReqReference::from_specifier(specifier) {
|
||||
return node_resolve_npm_req_ref(npm_ref, maybe_npm_resolver);
|
||||
return node_resolve_npm_req_ref(npm_ref, maybe_node_resolver);
|
||||
}
|
||||
let doc = self.get(specifier)?;
|
||||
let maybe_module = doc.maybe_esm_module().and_then(|r| r.as_ref().ok());
|
||||
|
@ -1430,7 +1429,7 @@ impl Documents {
|
|||
if let Some(specifier) =
|
||||
maybe_types_dependency.and_then(|d| d.maybe_specifier())
|
||||
{
|
||||
self.resolve_dependency(specifier, maybe_npm_resolver)
|
||||
self.resolve_dependency(specifier, maybe_node_resolver)
|
||||
} else {
|
||||
let media_type = doc.media_type();
|
||||
Some((specifier.clone(), media_type))
|
||||
|
@ -1453,23 +1452,18 @@ impl Documents {
|
|||
|
||||
fn node_resolve_npm_req_ref(
|
||||
npm_req_ref: NpmPackageReqReference,
|
||||
maybe_npm_resolver: Option<&Arc<NpmPackageResolver>>,
|
||||
maybe_node_resolver: Option<&Arc<CliNodeResolver>>,
|
||||
) -> Option<(ModuleSpecifier, MediaType)> {
|
||||
maybe_npm_resolver.map(|npm_resolver| {
|
||||
maybe_node_resolver.map(|node_resolver| {
|
||||
NodeResolution::into_specifier_and_media_type(
|
||||
npm_resolver
|
||||
.pkg_req_ref_to_nv_ref(npm_req_ref)
|
||||
node_resolver
|
||||
.resolve_npm_req_reference(
|
||||
&npm_req_ref,
|
||||
NodeResolutionMode::Types,
|
||||
&mut PermissionsContainer::allow_all(),
|
||||
)
|
||||
.ok()
|
||||
.and_then(|pkg_id_ref| {
|
||||
node_resolve_npm_reference(
|
||||
&pkg_id_ref,
|
||||
NodeResolutionMode::Types,
|
||||
npm_resolver,
|
||||
&mut PermissionsContainer::allow_all(),
|
||||
)
|
||||
.ok()
|
||||
.flatten()
|
||||
}),
|
||||
.flatten(),
|
||||
)
|
||||
})
|
||||
}
|
||||
|
|
|
@ -78,6 +78,7 @@ use crate::file_fetcher::FileFetcher;
|
|||
use crate::graph_util;
|
||||
use crate::http_util::HttpClient;
|
||||
use crate::lsp::urls::LspUrlKind;
|
||||
use crate::node::CliNodeResolver;
|
||||
use crate::npm::create_npm_fs_resolver;
|
||||
use crate::npm::CliNpmRegistryApi;
|
||||
use crate::npm::NpmCache;
|
||||
|
@ -101,6 +102,7 @@ pub struct StateSnapshot {
|
|||
pub cache_metadata: cache::CacheMetadata,
|
||||
pub documents: Documents,
|
||||
pub maybe_import_map: Option<Arc<ImportMap>>,
|
||||
pub maybe_node_resolver: Option<Arc<CliNodeResolver>>,
|
||||
pub maybe_npm_resolver: Option<Arc<NpmPackageResolver>>,
|
||||
}
|
||||
|
||||
|
@ -695,30 +697,32 @@ impl Inner {
|
|||
}
|
||||
|
||||
pub fn snapshot(&self) -> Arc<StateSnapshot> {
|
||||
// create a new snapshotted npm resolution and resolver
|
||||
let npm_resolution = Arc::new(NpmResolution::new(
|
||||
self.npm_api.clone(),
|
||||
self.npm_resolution.snapshot(),
|
||||
None,
|
||||
));
|
||||
let npm_resolver = Arc::new(NpmPackageResolver::new(
|
||||
npm_resolution.clone(),
|
||||
create_npm_fs_resolver(
|
||||
self.npm_cache.clone(),
|
||||
&ProgressBar::new(ProgressBarStyle::TextOnly),
|
||||
self.npm_api.base_url().clone(),
|
||||
npm_resolution.clone(),
|
||||
None,
|
||||
),
|
||||
None,
|
||||
));
|
||||
let node_resolver =
|
||||
Arc::new(CliNodeResolver::new(npm_resolution, npm_resolver.clone()));
|
||||
Arc::new(StateSnapshot {
|
||||
assets: self.assets.snapshot(),
|
||||
cache_metadata: self.cache_metadata.clone(),
|
||||
documents: self.documents.clone(),
|
||||
maybe_import_map: self.maybe_import_map.clone(),
|
||||
maybe_npm_resolver: Some({
|
||||
// create a new snapshotted npm resolution and resolver
|
||||
let resolution = Arc::new(NpmResolution::new(
|
||||
self.npm_api.clone(),
|
||||
self.npm_resolution.snapshot(),
|
||||
None,
|
||||
));
|
||||
Arc::new(NpmPackageResolver::new(
|
||||
resolution.clone(),
|
||||
create_npm_fs_resolver(
|
||||
self.npm_cache.clone(),
|
||||
&ProgressBar::new(ProgressBarStyle::TextOnly),
|
||||
self.npm_api.base_url().clone(),
|
||||
resolution,
|
||||
None,
|
||||
),
|
||||
None,
|
||||
))
|
||||
}),
|
||||
maybe_node_resolver: Some(node_resolver),
|
||||
maybe_npm_resolver: Some(npm_resolver),
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -2763,7 +2763,7 @@ fn op_resolve(
|
|||
let resolved = state.state_snapshot.documents.resolve(
|
||||
args.specifiers,
|
||||
&referrer_doc,
|
||||
state.state_snapshot.maybe_npm_resolver.as_ref(),
|
||||
state.state_snapshot.maybe_node_resolver.as_ref(),
|
||||
);
|
||||
Ok(
|
||||
resolved
|
||||
|
|
|
@ -11,10 +11,9 @@ use crate::graph_util::graph_valid_with_cli_options;
|
|||
use crate::graph_util::ModuleGraphBuilder;
|
||||
use crate::graph_util::ModuleGraphContainer;
|
||||
use crate::node;
|
||||
use crate::node::CliNodeResolver;
|
||||
use crate::node::NodeCodeTranslator;
|
||||
use crate::node::NodeResolution;
|
||||
use crate::npm::NpmPackageResolver;
|
||||
use crate::npm::NpmResolution;
|
||||
use crate::proc_state::CjsResolutionStore;
|
||||
use crate::proc_state::FileWatcherReporter;
|
||||
use crate::proc_state::ProcState;
|
||||
|
@ -243,8 +242,7 @@ pub struct CliModuleLoader {
|
|||
graph_container: Arc<ModuleGraphContainer>,
|
||||
module_load_preparer: Arc<ModuleLoadPreparer>,
|
||||
node_code_translator: Arc<NodeCodeTranslator>,
|
||||
npm_resolution: Arc<NpmResolution>,
|
||||
npm_resolver: Arc<NpmPackageResolver>,
|
||||
node_resolver: Arc<CliNodeResolver>,
|
||||
parsed_source_cache: Arc<ParsedSourceCache>,
|
||||
resolver: Arc<CliGraphResolver>,
|
||||
}
|
||||
|
@ -265,8 +263,7 @@ impl CliModuleLoader {
|
|||
graph_container: ps.graph_container.clone(),
|
||||
module_load_preparer: ps.module_load_preparer.clone(),
|
||||
node_code_translator: ps.node_code_translator.clone(),
|
||||
npm_resolution: ps.npm_resolution.clone(),
|
||||
npm_resolver: ps.npm_resolver.clone(),
|
||||
node_resolver: ps.node_resolver.clone(),
|
||||
parsed_source_cache: ps.parsed_source_cache.clone(),
|
||||
resolver: ps.resolver.clone(),
|
||||
})
|
||||
|
@ -287,8 +284,7 @@ impl CliModuleLoader {
|
|||
graph_container: ps.graph_container.clone(),
|
||||
module_load_preparer: ps.module_load_preparer.clone(),
|
||||
node_code_translator: ps.node_code_translator.clone(),
|
||||
npm_resolution: ps.npm_resolution.clone(),
|
||||
npm_resolver: ps.npm_resolver.clone(),
|
||||
node_resolver: ps.node_resolver.clone(),
|
||||
parsed_source_cache: ps.parsed_source_cache.clone(),
|
||||
resolver: ps.resolver.clone(),
|
||||
})
|
||||
|
@ -370,7 +366,7 @@ impl CliModuleLoader {
|
|||
maybe_referrer: Option<&ModuleSpecifier>,
|
||||
is_dynamic: bool,
|
||||
) -> Result<ModuleSource, AnyError> {
|
||||
let code_source = if self.npm_resolver.in_npm_package(specifier) {
|
||||
let code_source = if self.node_resolver.in_npm_package(specifier) {
|
||||
let file_path = specifier.to_file_path().unwrap();
|
||||
let code = std::fs::read_to_string(&file_path).with_context(|| {
|
||||
let mut msg = "Unable to load ".to_string();
|
||||
|
@ -466,14 +462,13 @@ impl ModuleLoader for CliModuleLoader {
|
|||
let referrer_result = deno_core::resolve_url_or_path(referrer, &cwd);
|
||||
|
||||
if let Ok(referrer) = referrer_result.as_ref() {
|
||||
if self.npm_resolver.in_npm_package(referrer) {
|
||||
if self.node_resolver.in_npm_package(referrer) {
|
||||
// we're in an npm package, so use node resolution
|
||||
return self
|
||||
.handle_node_resolve_result(node::node_resolve(
|
||||
.handle_node_resolve_result(self.node_resolver.resolve(
|
||||
specifier,
|
||||
referrer,
|
||||
NodeResolutionMode::Execution,
|
||||
&self.npm_resolver.as_require_npm_resolver(),
|
||||
&mut permissions,
|
||||
))
|
||||
.with_context(|| {
|
||||
|
@ -495,12 +490,13 @@ impl ModuleLoader for CliModuleLoader {
|
|||
|
||||
return match graph.get(specifier) {
|
||||
Some(Module::Npm(module)) => self
|
||||
.handle_node_resolve_result(node::node_resolve_npm_reference(
|
||||
&module.nv_reference,
|
||||
NodeResolutionMode::Execution,
|
||||
&self.npm_resolver,
|
||||
&mut permissions,
|
||||
))
|
||||
.handle_node_resolve_result(
|
||||
self.node_resolver.resolve_npm_reference(
|
||||
&module.nv_reference,
|
||||
NodeResolutionMode::Execution,
|
||||
&mut permissions,
|
||||
),
|
||||
)
|
||||
.with_context(|| {
|
||||
format!("Could not resolve '{}'.", module.nv_reference)
|
||||
}),
|
||||
|
@ -555,15 +551,14 @@ impl ModuleLoader for CliModuleLoader {
|
|||
if let Ok(reference) =
|
||||
NpmPackageReqReference::from_specifier(&specifier)
|
||||
{
|
||||
let reference =
|
||||
self.npm_resolution.pkg_req_ref_to_nv_ref(reference)?;
|
||||
return self
|
||||
.handle_node_resolve_result(node::node_resolve_npm_reference(
|
||||
&reference,
|
||||
deno_runtime::deno_node::NodeResolutionMode::Execution,
|
||||
&self.npm_resolver,
|
||||
&mut permissions,
|
||||
))
|
||||
.handle_node_resolve_result(
|
||||
self.node_resolver.resolve_npm_req_reference(
|
||||
&reference,
|
||||
deno_runtime::deno_node::NodeResolutionMode::Execution,
|
||||
&mut permissions,
|
||||
),
|
||||
)
|
||||
.with_context(|| format!("Could not resolve '{reference}'."));
|
||||
}
|
||||
}
|
||||
|
@ -595,7 +590,7 @@ impl ModuleLoader for CliModuleLoader {
|
|||
_maybe_referrer: Option<String>,
|
||||
is_dynamic: bool,
|
||||
) -> Pin<Box<dyn Future<Output = Result<(), AnyError>>>> {
|
||||
if self.npm_resolver.in_npm_package(specifier) {
|
||||
if self.node_resolver.in_npm_package(specifier) {
|
||||
// nothing to prepare
|
||||
return Box::pin(deno_core::futures::future::ready(Ok(())));
|
||||
}
|
||||
|
|
553
cli/node/mod.rs
553
cli/node/mod.rs
|
@ -31,8 +31,11 @@ use deno_runtime::deno_node::DEFAULT_CONDITIONS;
|
|||
use deno_runtime::permissions::PermissionsContainer;
|
||||
use deno_semver::npm::NpmPackageNv;
|
||||
use deno_semver::npm::NpmPackageNvReference;
|
||||
use deno_semver::npm::NpmPackageReqReference;
|
||||
|
||||
use crate::npm::NpmPackageResolver;
|
||||
use crate::npm::NpmResolution;
|
||||
use crate::npm::RequireNpmPackageResolver;
|
||||
use crate::util::fs::canonicalize_path_maybe_not_exists;
|
||||
|
||||
mod analyze;
|
||||
|
@ -109,127 +112,305 @@ pub fn resolve_builtin_node_module(module_name: &str) -> Result<Url, AnyError> {
|
|||
)))
|
||||
}
|
||||
|
||||
/// This function is an implementation of `defaultResolve` in
|
||||
/// `lib/internal/modules/esm/resolve.js` from Node.
|
||||
pub fn node_resolve(
|
||||
specifier: &str,
|
||||
referrer: &ModuleSpecifier,
|
||||
mode: NodeResolutionMode,
|
||||
npm_resolver: &dyn RequireNpmResolver,
|
||||
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 deno_node::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 deno_node::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 = module_resolve(
|
||||
specifier,
|
||||
referrer,
|
||||
DEFAULT_CONDITIONS,
|
||||
mode,
|
||||
npm_resolver,
|
||||
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::<RealFs>(path, NodeModuleKind::Esm) {
|
||||
Some(path) => path,
|
||||
None => return Ok(None),
|
||||
};
|
||||
ModuleSpecifier::from_file_path(path).unwrap()
|
||||
}
|
||||
};
|
||||
|
||||
let resolve_response = url_to_node_resolution(url, npm_resolver)?;
|
||||
// TODO(bartlomieju): skipped checking errors for commonJS resolution and
|
||||
// "preserveSymlinksMain"/"preserveSymlinks" options.
|
||||
Ok(Some(resolve_response))
|
||||
#[derive(Debug)]
|
||||
pub struct CliNodeResolver {
|
||||
npm_resolution: Arc<NpmResolution>,
|
||||
npm_resolver: Arc<NpmPackageResolver>,
|
||||
require_npm_resolver: RequireNpmPackageResolver,
|
||||
}
|
||||
|
||||
pub fn node_resolve_npm_reference(
|
||||
reference: &NpmPackageNvReference,
|
||||
mode: NodeResolutionMode,
|
||||
npm_resolver: &Arc<NpmPackageResolver>,
|
||||
permissions: &mut dyn NodePermissions,
|
||||
) -> Result<Option<NodeResolution>, AnyError> {
|
||||
let package_folder =
|
||||
npm_resolver.resolve_package_folder_from_deno_module(&reference.nv)?;
|
||||
let node_module_kind = NodeModuleKind::Esm;
|
||||
let maybe_resolved_path = package_config_resolve(
|
||||
&reference
|
||||
.sub_path
|
||||
.as_ref()
|
||||
.map(|s| format!("./{s}"))
|
||||
.unwrap_or_else(|| ".".to_string()),
|
||||
&package_folder,
|
||||
node_module_kind,
|
||||
DEFAULT_CONDITIONS,
|
||||
mode,
|
||||
&npm_resolver.as_require_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::<RealFs>(resolved_path, node_module_kind)
|
||||
{
|
||||
Some(path) => path,
|
||||
None => return Ok(None),
|
||||
impl CliNodeResolver {
|
||||
pub fn new(
|
||||
npm_resolution: Arc<NpmResolution>,
|
||||
npm_package_resolver: Arc<NpmPackageResolver>,
|
||||
) -> Self {
|
||||
Self {
|
||||
npm_resolution,
|
||||
require_npm_resolver: npm_package_resolver.as_require_npm_resolver(),
|
||||
npm_resolver: npm_package_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(
|
||||
&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 deno_node::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 deno_node::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 = ModuleSpecifier::from_file_path(resolved_path).unwrap();
|
||||
let resolve_response =
|
||||
url_to_node_resolution(url, &npm_resolver.as_require_npm_resolver())?;
|
||||
// TODO(bartlomieju): skipped checking errors for commonJS resolution and
|
||||
// "preserveSymlinksMain"/"preserveSymlinks" options.
|
||||
Ok(Some(resolve_response))
|
||||
|
||||
let url = self.module_resolve(
|
||||
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::<RealFs>(path, NodeModuleKind::Esm) {
|
||||
Some(path) => path,
|
||||
None => return Ok(None),
|
||||
};
|
||||
ModuleSpecifier::from_file_path(path).unwrap()
|
||||
}
|
||||
};
|
||||
|
||||
let resolve_response = self.url_to_node_resolution(url)?;
|
||||
// TODO(bartlomieju): skipped checking errors for commonJS resolution and
|
||||
// "preserveSymlinksMain"/"preserveSymlinks" options.
|
||||
Ok(Some(resolve_response))
|
||||
}
|
||||
|
||||
fn module_resolve(
|
||||
&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::<RealFs>(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::<RealFs>(
|
||||
specifier,
|
||||
referrer,
|
||||
NodeModuleKind::Esm,
|
||||
conditions,
|
||||
mode,
|
||||
&self.require_npm_resolver,
|
||||
permissions,
|
||||
)
|
||||
.map(|p| ModuleSpecifier::from_file_path(p).unwrap())?,
|
||||
)
|
||||
} else if let Ok(resolved) = Url::parse(specifier) {
|
||||
Some(resolved)
|
||||
} else {
|
||||
package_resolve::<RealFs>(
|
||||
specifier,
|
||||
referrer,
|
||||
NodeModuleKind::Esm,
|
||||
conditions,
|
||||
mode,
|
||||
&self.require_npm_resolver,
|
||||
permissions,
|
||||
)?
|
||||
.map(|p| ModuleSpecifier::from_file_path(p).unwrap())
|
||||
};
|
||||
Ok(match url {
|
||||
Some(url) => Some(finalize_resolution(url, referrer)?),
|
||||
None => None,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn resolve_npm_req_reference(
|
||||
&self,
|
||||
reference: &NpmPackageReqReference,
|
||||
mode: NodeResolutionMode,
|
||||
permissions: &mut dyn NodePermissions,
|
||||
) -> Result<Option<NodeResolution>, AnyError> {
|
||||
let reference = self.npm_resolution.pkg_req_ref_to_nv_ref(reference)?;
|
||||
self.resolve_npm_reference(&reference, mode, permissions)
|
||||
}
|
||||
|
||||
pub fn resolve_npm_reference(
|
||||
&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(
|
||||
&reference
|
||||
.sub_path
|
||||
.as_ref()
|
||||
.map(|s| format!("./{s}"))
|
||||
.unwrap_or_else(|| ".".to_string()),
|
||||
&package_folder,
|
||||
node_module_kind,
|
||||
DEFAULT_CONDITIONS,
|
||||
mode,
|
||||
&self.require_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::<RealFs>(
|
||||
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(url)?;
|
||||
// TODO(bartlomieju): skipped checking errors for commonJS resolution and
|
||||
// "preserveSymlinksMain"/"preserveSymlinks" options.
|
||||
Ok(Some(resolve_response))
|
||||
}
|
||||
|
||||
pub fn resolve_binary_commands(
|
||||
&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::<RealFs>(
|
||||
&self.require_npm_resolver,
|
||||
&mut PermissionsContainer::allow_all(),
|
||||
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(
|
||||
&self,
|
||||
pkg_ref: &NpmPackageReqReference,
|
||||
) -> Result<NodeResolution, AnyError> {
|
||||
let pkg_nv = self
|
||||
.npm_resolution
|
||||
.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::<RealFs>(
|
||||
&self.require_npm_resolver,
|
||||
&mut PermissionsContainer::allow_all(),
|
||||
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(url)?;
|
||||
// TODO(bartlomieju): skipped checking errors for commonJS resolution and
|
||||
// "preserveSymlinksMain"/"preserveSymlinks" options.
|
||||
Ok(resolve_response)
|
||||
}
|
||||
|
||||
pub fn url_to_node_resolution(
|
||||
&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::<RealFs>(
|
||||
&url,
|
||||
&self.require_npm_resolver,
|
||||
&mut PermissionsContainer::allow_all(),
|
||||
)?;
|
||||
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))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Resolves a specifier that is pointing into a node_modules folder.
|
||||
|
@ -251,59 +432,6 @@ pub fn resolve_specifier_into_node_modules(
|
|||
.unwrap_or_else(|| specifier.clone())
|
||||
}
|
||||
|
||||
pub fn node_resolve_binary_commands(
|
||||
pkg_nv: &NpmPackageNv,
|
||||
npm_resolver: &Arc<NpmPackageResolver>,
|
||||
) -> Result<Vec<String>, AnyError> {
|
||||
let package_folder =
|
||||
npm_resolver.resolve_package_folder_from_deno_module(pkg_nv)?;
|
||||
let package_json_path = package_folder.join("package.json");
|
||||
let package_json = PackageJson::load::<RealFs>(
|
||||
&npm_resolver.as_require_npm_resolver(),
|
||||
&mut PermissionsContainer::allow_all(),
|
||||
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 node_resolve_binary_export(
|
||||
pkg_nv: &NpmPackageNv,
|
||||
bin_name: Option<&str>,
|
||||
npm_resolver: &Arc<NpmPackageResolver>,
|
||||
) -> Result<NodeResolution, AnyError> {
|
||||
let package_folder =
|
||||
npm_resolver.resolve_package_folder_from_deno_module(pkg_nv)?;
|
||||
let package_json_path = package_folder.join("package.json");
|
||||
let package_json = PackageJson::load::<RealFs>(
|
||||
&npm_resolver.as_require_npm_resolver(),
|
||||
&mut PermissionsContainer::allow_all(),
|
||||
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 =
|
||||
url_to_node_resolution(url, &npm_resolver.as_require_npm_resolver())?;
|
||||
// TODO(bartlomieju): skipped checking errors for commonJS resolution and
|
||||
// "preserveSymlinksMain"/"preserveSymlinks" options.
|
||||
Ok(resolve_response)
|
||||
}
|
||||
|
||||
fn resolve_bin_entry_value<'a>(
|
||||
pkg_nv: &NpmPackageNv,
|
||||
bin_name: Option<&str>,
|
||||
|
@ -411,35 +539,6 @@ fn package_config_resolve(
|
|||
Ok(Some(package_dir.join(package_subpath)))
|
||||
}
|
||||
|
||||
pub fn url_to_node_resolution(
|
||||
url: ModuleSpecifier,
|
||||
npm_resolver: &dyn RequireNpmResolver,
|
||||
) -> 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::<RealFs>(
|
||||
&url,
|
||||
npm_resolver,
|
||||
&mut PermissionsContainer::allow_all(),
|
||||
)?;
|
||||
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 finalize_resolution(
|
||||
resolved: ModuleSpecifier,
|
||||
base: &ModuleSpecifier,
|
||||
|
@ -489,62 +588,6 @@ fn finalize_resolution(
|
|||
Ok(resolved)
|
||||
}
|
||||
|
||||
fn module_resolve(
|
||||
specifier: &str,
|
||||
referrer: &ModuleSpecifier,
|
||||
conditions: &[&str],
|
||||
mode: NodeResolutionMode,
|
||||
npm_resolver: &dyn RequireNpmResolver,
|
||||
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::<RealFs>(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::<RealFs>(
|
||||
specifier,
|
||||
referrer,
|
||||
NodeModuleKind::Esm,
|
||||
conditions,
|
||||
mode,
|
||||
npm_resolver,
|
||||
permissions,
|
||||
)
|
||||
.map(|p| ModuleSpecifier::from_file_path(p).unwrap())?,
|
||||
)
|
||||
} else if let Ok(resolved) = Url::parse(specifier) {
|
||||
Some(resolved)
|
||||
} else {
|
||||
package_resolve::<RealFs>(
|
||||
specifier,
|
||||
referrer,
|
||||
NodeModuleKind::Esm,
|
||||
conditions,
|
||||
mode,
|
||||
npm_resolver,
|
||||
permissions,
|
||||
)?
|
||||
.map(|p| ModuleSpecifier::from_file_path(p).unwrap())
|
||||
};
|
||||
Ok(match url {
|
||||
Some(url) => Some(finalize_resolution(url, referrer)?),
|
||||
None => None,
|
||||
})
|
||||
}
|
||||
|
||||
fn to_file_path(url: &ModuleSpecifier) -> PathBuf {
|
||||
url
|
||||
.to_file_path()
|
||||
|
|
|
@ -15,3 +15,4 @@ pub use resolution::NpmResolution;
|
|||
pub use resolvers::create_npm_fs_resolver;
|
||||
pub use resolvers::NpmPackageResolver;
|
||||
pub use resolvers::NpmProcessState;
|
||||
pub use resolvers::RequireNpmPackageResolver;
|
||||
|
|
|
@ -156,12 +156,12 @@ impl NpmResolution {
|
|||
|
||||
pub fn pkg_req_ref_to_nv_ref(
|
||||
&self,
|
||||
req_ref: NpmPackageReqReference,
|
||||
req_ref: &NpmPackageReqReference,
|
||||
) -> Result<NpmPackageNvReference, PackageReqNotFoundError> {
|
||||
let node_id = self.resolve_pkg_id_from_pkg_req(&req_ref.req)?;
|
||||
Ok(NpmPackageNvReference {
|
||||
nv: node_id.nv,
|
||||
sub_path: req_ref.sub_path,
|
||||
sub_path: req_ref.sub_path.clone(),
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -23,9 +23,7 @@ use deno_runtime::deno_node::NodeResolutionMode;
|
|||
use deno_runtime::deno_node::PathClean;
|
||||
use deno_runtime::deno_node::RequireNpmResolver;
|
||||
use deno_semver::npm::NpmPackageNv;
|
||||
use deno_semver::npm::NpmPackageNvReference;
|
||||
use deno_semver::npm::NpmPackageReq;
|
||||
use deno_semver::npm::NpmPackageReqReference;
|
||||
use global::GlobalNpmPackageResolver;
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
|
@ -87,13 +85,6 @@ impl NpmPackageResolver {
|
|||
self.resolution.resolve_pkg_id_from_pkg_req(req)
|
||||
}
|
||||
|
||||
pub fn pkg_req_ref_to_nv_ref(
|
||||
&self,
|
||||
req_ref: NpmPackageReqReference,
|
||||
) -> Result<NpmPackageNvReference, PackageReqNotFoundError> {
|
||||
self.resolution.pkg_req_ref_to_nv_ref(req_ref)
|
||||
}
|
||||
|
||||
/// Resolves an npm package folder path from a Deno module.
|
||||
pub fn resolve_package_folder_from_deno_module(
|
||||
&self,
|
||||
|
@ -245,6 +236,7 @@ impl NpmPackageResolver {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct RequireNpmPackageResolver(Arc<NpmPackageResolver>);
|
||||
|
||||
impl RequireNpmResolver for RequireNpmPackageResolver {
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
|
||||
|
||||
use crate::proc_state::ProcState;
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::npm::NpmPackageResolver;
|
||||
use deno_core::error::AnyError;
|
||||
use deno_core::op;
|
||||
use deno_core::Extension;
|
||||
|
@ -9,17 +11,17 @@ use deno_core::OpState;
|
|||
pub mod bench;
|
||||
pub mod testing;
|
||||
|
||||
pub fn cli_exts(ps: ProcState) -> Vec<Extension> {
|
||||
vec![deno_cli::init_ops(ps)]
|
||||
pub fn cli_exts(npm_resolver: Arc<NpmPackageResolver>) -> Vec<Extension> {
|
||||
vec![deno_cli::init_ops(npm_resolver)]
|
||||
}
|
||||
|
||||
deno_core::extension!(deno_cli,
|
||||
ops = [op_npm_process_state],
|
||||
options = {
|
||||
ps: ProcState,
|
||||
npm_resolver: Arc<NpmPackageResolver>,
|
||||
},
|
||||
state = |state, options| {
|
||||
state.put(options.ps);
|
||||
state.put(options.npm_resolver);
|
||||
},
|
||||
customizer = |ext: &mut deno_core::ExtensionBuilder| {
|
||||
ext.force_op_registration();
|
||||
|
@ -28,6 +30,6 @@ deno_core::extension!(deno_cli,
|
|||
|
||||
#[op]
|
||||
fn op_npm_process_state(state: &mut OpState) -> Result<String, AnyError> {
|
||||
let proc_state = state.borrow_mut::<ProcState>();
|
||||
Ok(proc_state.npm_resolver.get_npm_process_state())
|
||||
let npm_resolver = state.borrow_mut::<Arc<NpmPackageResolver>>();
|
||||
Ok(npm_resolver.get_npm_process_state())
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@ use crate::graph_util::ModuleGraphBuilder;
|
|||
use crate::graph_util::ModuleGraphContainer;
|
||||
use crate::http_util::HttpClient;
|
||||
use crate::module_loader::ModuleLoadPreparer;
|
||||
use crate::node::CliNodeResolver;
|
||||
use crate::node::NodeCodeTranslator;
|
||||
use crate::npm::create_npm_fs_resolver;
|
||||
use crate::npm::CliNpmRegistryApi;
|
||||
|
@ -75,6 +76,7 @@ pub struct Inner {
|
|||
pub module_graph_builder: Arc<ModuleGraphBuilder>,
|
||||
pub module_load_preparer: Arc<ModuleLoadPreparer>,
|
||||
pub node_code_translator: Arc<NodeCodeTranslator>,
|
||||
pub node_resolver: Arc<CliNodeResolver>,
|
||||
pub npm_api: Arc<CliNpmRegistryApi>,
|
||||
pub npm_cache: Arc<NpmCache>,
|
||||
pub npm_resolver: Arc<NpmPackageResolver>,
|
||||
|
@ -145,6 +147,7 @@ impl ProcState {
|
|||
module_graph_builder: self.module_graph_builder.clone(),
|
||||
module_load_preparer: self.module_load_preparer.clone(),
|
||||
node_code_translator: self.node_code_translator.clone(),
|
||||
node_resolver: self.node_resolver.clone(),
|
||||
npm_api: self.npm_api.clone(),
|
||||
npm_cache: self.npm_cache.clone(),
|
||||
npm_resolver: self.npm_resolver.clone(),
|
||||
|
@ -306,10 +309,15 @@ impl ProcState {
|
|||
file_fetcher.clone(),
|
||||
npm_resolver.clone(),
|
||||
));
|
||||
let node_resolver = Arc::new(CliNodeResolver::new(
|
||||
npm_resolution.clone(),
|
||||
npm_resolver.clone(),
|
||||
));
|
||||
let type_checker = Arc::new(TypeChecker::new(
|
||||
dir.clone(),
|
||||
caches.clone(),
|
||||
cli_options.clone(),
|
||||
node_resolver.clone(),
|
||||
npm_resolver.clone(),
|
||||
));
|
||||
let module_graph_builder = Arc::new(ModuleGraphBuilder::new(
|
||||
|
@ -357,6 +365,7 @@ impl ProcState {
|
|||
maybe_file_watcher_reporter,
|
||||
module_graph_builder,
|
||||
node_code_translator,
|
||||
node_resolver,
|
||||
npm_api,
|
||||
npm_cache,
|
||||
npm_resolver,
|
||||
|
|
|
@ -265,7 +265,7 @@ fn create_web_worker_callback(
|
|||
user_agent: version::get_user_agent().to_string(),
|
||||
inspect: ps.options.is_inspecting(),
|
||||
},
|
||||
extensions: ops::cli_exts(ps.clone()),
|
||||
extensions: ops::cli_exts(ps.npm_resolver.clone()),
|
||||
startup_snapshot: Some(crate::js::deno_isolate_init()),
|
||||
unsafely_ignore_certificate_errors: ps
|
||||
.options
|
||||
|
@ -354,7 +354,7 @@ pub async fn run(
|
|||
user_agent: version::get_user_agent().to_string(),
|
||||
inspect: ps.options.is_inspecting(),
|
||||
},
|
||||
extensions: ops::cli_exts(ps.clone()),
|
||||
extensions: ops::cli_exts(ps.npm_resolver.clone()),
|
||||
startup_snapshot: Some(crate::js::deno_isolate_init()),
|
||||
unsafely_ignore_certificate_errors: metadata
|
||||
.unsafely_ignore_certificate_errors,
|
||||
|
|
|
@ -21,6 +21,7 @@ use crate::cache::Caches;
|
|||
use crate::cache::DenoDir;
|
||||
use crate::cache::FastInsecureHasher;
|
||||
use crate::cache::TypeCheckCache;
|
||||
use crate::node::CliNodeResolver;
|
||||
use crate::npm::NpmPackageResolver;
|
||||
use crate::tsc;
|
||||
use crate::version;
|
||||
|
@ -41,6 +42,7 @@ pub struct TypeChecker {
|
|||
deno_dir: DenoDir,
|
||||
caches: Arc<Caches>,
|
||||
cli_options: Arc<CliOptions>,
|
||||
node_resolver: Arc<CliNodeResolver>,
|
||||
npm_resolver: Arc<NpmPackageResolver>,
|
||||
}
|
||||
|
||||
|
@ -49,12 +51,14 @@ impl TypeChecker {
|
|||
deno_dir: DenoDir,
|
||||
caches: Arc<Caches>,
|
||||
cli_options: Arc<CliOptions>,
|
||||
node_resolver: Arc<CliNodeResolver>,
|
||||
npm_resolver: Arc<NpmPackageResolver>,
|
||||
) -> Self {
|
||||
Self {
|
||||
deno_dir,
|
||||
caches,
|
||||
cli_options,
|
||||
node_resolver,
|
||||
npm_resolver,
|
||||
}
|
||||
}
|
||||
|
@ -133,7 +137,7 @@ impl TypeChecker {
|
|||
debug,
|
||||
graph: graph.clone(),
|
||||
hash_data,
|
||||
maybe_npm_resolver: Some(self.npm_resolver.clone()),
|
||||
maybe_node_resolver: Some(self.node_resolver.clone()),
|
||||
maybe_tsbuildinfo,
|
||||
root_names,
|
||||
check_mode: type_check_mode,
|
||||
|
@ -144,7 +148,7 @@ impl TypeChecker {
|
|||
if let Some(file_name) = &d.file_name {
|
||||
if !file_name.starts_with("http") {
|
||||
if ModuleSpecifier::parse(file_name)
|
||||
.map(|specifier| !self.npm_resolver.in_npm_package(&specifier))
|
||||
.map(|specifier| !self.node_resolver.in_npm_package(&specifier))
|
||||
.unwrap_or(true)
|
||||
{
|
||||
Some(d.clone())
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
|
||||
|
||||
use crate::args::CliOptions;
|
||||
use crate::args::Flags;
|
||||
use crate::args::TaskFlags;
|
||||
use crate::colors;
|
||||
use crate::node::CliNodeResolver;
|
||||
use crate::npm::NpmPackageResolver;
|
||||
use crate::proc_state::ProcState;
|
||||
use crate::util::fs::canonicalize_path;
|
||||
use deno_core::anyhow::bail;
|
||||
|
@ -50,7 +53,7 @@ pub async fn execute_script(
|
|||
Some(path) => canonicalize_path(&PathBuf::from(path))?,
|
||||
None => config_file_path.parent().unwrap().to_owned(),
|
||||
};
|
||||
let script = get_script_with_args(script, &ps);
|
||||
let script = get_script_with_args(script, &ps.options);
|
||||
output_task(task_name, &script);
|
||||
let seq_list = deno_task_shell::parser::parse(&script)
|
||||
.with_context(|| format!("Error parsing script '{task_name}'."))?;
|
||||
|
@ -92,11 +95,12 @@ pub async fn execute_script(
|
|||
.unwrap()
|
||||
.to_owned(),
|
||||
};
|
||||
let script = get_script_with_args(script, &ps);
|
||||
let script = get_script_with_args(script, &ps.options);
|
||||
output_task(task_name, &script);
|
||||
let seq_list = deno_task_shell::parser::parse(&script)
|
||||
.with_context(|| format!("Error parsing script '{task_name}'."))?;
|
||||
let npx_commands = resolve_npm_commands(&ps)?;
|
||||
let npx_commands =
|
||||
resolve_npm_commands(&ps.npm_resolver, &ps.node_resolver)?;
|
||||
let env_vars = collect_env_vars();
|
||||
let exit_code =
|
||||
deno_task_shell::execute(seq_list, env_vars, &cwd, npx_commands).await;
|
||||
|
@ -108,9 +112,8 @@ pub async fn execute_script(
|
|||
}
|
||||
}
|
||||
|
||||
fn get_script_with_args(script: &str, ps: &ProcState) -> String {
|
||||
let additional_args = ps
|
||||
.options
|
||||
fn get_script_with_args(script: &str, options: &CliOptions) -> String {
|
||||
let additional_args = options
|
||||
.argv()
|
||||
.iter()
|
||||
// surround all the additional arguments in double quotes
|
||||
|
@ -231,13 +234,13 @@ impl ShellCommand for NpmPackageBinCommand {
|
|||
}
|
||||
|
||||
fn resolve_npm_commands(
|
||||
ps: &ProcState,
|
||||
npm_resolver: &NpmPackageResolver,
|
||||
node_resolver: &CliNodeResolver,
|
||||
) -> Result<HashMap<String, Rc<dyn ShellCommand>>, AnyError> {
|
||||
let mut result = HashMap::new();
|
||||
let snapshot = ps.npm_resolver.snapshot();
|
||||
let snapshot = npm_resolver.snapshot();
|
||||
for id in snapshot.top_level_packages() {
|
||||
let bin_commands =
|
||||
crate::node::node_resolve_binary_commands(&id.nv, &ps.npm_resolver)?;
|
||||
let bin_commands = node_resolver.resolve_binary_commands(&id.nv)?;
|
||||
for bin_command in bin_commands {
|
||||
result.insert(
|
||||
bin_command.to_string(),
|
||||
|
|
15
cli/tools/vendor/mod.rs
vendored
15
cli/tools/vendor/mod.rs
vendored
|
@ -15,6 +15,7 @@ use crate::args::CliOptions;
|
|||
use crate::args::Flags;
|
||||
use crate::args::FmtOptionsConfig;
|
||||
use crate::args::VendorFlags;
|
||||
use crate::graph_util::ModuleGraphBuilder;
|
||||
use crate::proc_state::ProcState;
|
||||
use crate::tools::fmt::format_json;
|
||||
use crate::util::fs::canonicalize_path;
|
||||
|
@ -43,7 +44,12 @@ pub async fn vendor(
|
|||
validate_output_dir(&output_dir, &vendor_flags)?;
|
||||
validate_options(&mut cli_options, &output_dir)?;
|
||||
let ps = ProcState::from_cli_options(Arc::new(cli_options)).await?;
|
||||
let graph = create_graph(&ps, &vendor_flags).await?;
|
||||
let graph = create_graph(
|
||||
&ps.module_graph_builder,
|
||||
&vendor_flags,
|
||||
ps.options.initial_cwd(),
|
||||
)
|
||||
.await?;
|
||||
let vendored_count = build::build(
|
||||
graph,
|
||||
&ps.parsed_source_cache,
|
||||
|
@ -261,16 +267,17 @@ fn is_dir_empty(dir_path: &Path) -> Result<bool, AnyError> {
|
|||
}
|
||||
|
||||
async fn create_graph(
|
||||
ps: &ProcState,
|
||||
module_graph_builder: &ModuleGraphBuilder,
|
||||
flags: &VendorFlags,
|
||||
initial_cwd: &Path,
|
||||
) -> Result<deno_graph::ModuleGraph, AnyError> {
|
||||
let entry_points = flags
|
||||
.specifiers
|
||||
.iter()
|
||||
.map(|p| resolve_url_or_path(p, ps.options.initial_cwd()))
|
||||
.map(|p| resolve_url_or_path(p, initial_cwd))
|
||||
.collect::<Result<Vec<_>, _>>()?;
|
||||
|
||||
ps.module_graph_builder.create_graph(entry_points).await
|
||||
module_graph_builder.create_graph(entry_points).await
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
|
|
@ -4,9 +4,8 @@ use crate::args::TsConfig;
|
|||
use crate::args::TypeCheckMode;
|
||||
use crate::cache::FastInsecureHasher;
|
||||
use crate::node;
|
||||
use crate::node::node_resolve_npm_reference;
|
||||
use crate::node::CliNodeResolver;
|
||||
use crate::node::NodeResolution;
|
||||
use crate::npm::NpmPackageResolver;
|
||||
use crate::util::checksum;
|
||||
use crate::util::path::mapped_specifier_for_tsc;
|
||||
|
||||
|
@ -36,7 +35,6 @@ use deno_graph::ModuleGraph;
|
|||
use deno_graph::ResolutionResolved;
|
||||
use deno_runtime::deno_node::NodeResolutionMode;
|
||||
use deno_runtime::permissions::PermissionsContainer;
|
||||
use deno_semver::npm::NpmPackageNvReference;
|
||||
use deno_semver::npm::NpmPackageReqReference;
|
||||
use lsp_types::Url;
|
||||
use once_cell::sync::Lazy;
|
||||
|
@ -307,7 +305,7 @@ pub struct Request {
|
|||
pub debug: bool,
|
||||
pub graph: Arc<ModuleGraph>,
|
||||
pub hash_data: u64,
|
||||
pub maybe_npm_resolver: Option<Arc<NpmPackageResolver>>,
|
||||
pub maybe_node_resolver: Option<Arc<CliNodeResolver>>,
|
||||
pub maybe_tsbuildinfo: Option<String>,
|
||||
/// A vector of strings that represent the root/entry point modules for the
|
||||
/// program.
|
||||
|
@ -331,7 +329,7 @@ struct State {
|
|||
graph: Arc<ModuleGraph>,
|
||||
maybe_tsbuildinfo: Option<String>,
|
||||
maybe_response: Option<RespondArgs>,
|
||||
maybe_npm_resolver: Option<Arc<NpmPackageResolver>>,
|
||||
maybe_node_resolver: Option<Arc<CliNodeResolver>>,
|
||||
remapped_specifiers: HashMap<String, ModuleSpecifier>,
|
||||
root_map: HashMap<String, ModuleSpecifier>,
|
||||
current_dir: PathBuf,
|
||||
|
@ -341,7 +339,7 @@ impl State {
|
|||
pub fn new(
|
||||
graph: Arc<ModuleGraph>,
|
||||
hash_data: u64,
|
||||
maybe_npm_resolver: Option<Arc<NpmPackageResolver>>,
|
||||
maybe_node_resolver: Option<Arc<CliNodeResolver>>,
|
||||
maybe_tsbuildinfo: Option<String>,
|
||||
root_map: HashMap<String, ModuleSpecifier>,
|
||||
remapped_specifiers: HashMap<String, ModuleSpecifier>,
|
||||
|
@ -350,7 +348,7 @@ impl State {
|
|||
State {
|
||||
hash_data,
|
||||
graph,
|
||||
maybe_npm_resolver,
|
||||
maybe_node_resolver,
|
||||
maybe_tsbuildinfo,
|
||||
maybe_response: None,
|
||||
remapped_specifiers,
|
||||
|
@ -483,7 +481,7 @@ fn op_load(state: &mut OpState, args: Value) -> Result<Value, AnyError> {
|
|||
}
|
||||
}
|
||||
} else if state
|
||||
.maybe_npm_resolver
|
||||
.maybe_node_resolver
|
||||
.as_ref()
|
||||
.map(|resolver| resolver.in_npm_package(specifier))
|
||||
.unwrap_or(false)
|
||||
|
@ -636,24 +634,26 @@ fn resolve_graph_specifier_types(
|
|||
Ok(Some((module.specifier.clone(), module.media_type)))
|
||||
}
|
||||
Some(Module::Npm(module)) => {
|
||||
if let Some(npm_resolver) = &state.maybe_npm_resolver {
|
||||
resolve_npm_package_reference_types(&module.nv_reference, npm_resolver)
|
||||
.map(Some)
|
||||
if let Some(node_resolver) = &state.maybe_node_resolver {
|
||||
let maybe_resolution = node_resolver.resolve_npm_reference(
|
||||
&module.nv_reference,
|
||||
NodeResolutionMode::Types,
|
||||
&mut PermissionsContainer::allow_all(),
|
||||
)?;
|
||||
Ok(Some(NodeResolution::into_specifier_and_media_type(
|
||||
maybe_resolution,
|
||||
)))
|
||||
} else {
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
Some(Module::External(module)) => {
|
||||
// we currently only use "External" for when the module is in an npm package
|
||||
Ok(state.maybe_npm_resolver.as_ref().map(|npm_resolver| {
|
||||
Ok(state.maybe_node_resolver.as_ref().map(|node_resolver| {
|
||||
let specifier =
|
||||
node::resolve_specifier_into_node_modules(&module.specifier);
|
||||
NodeResolution::into_specifier_and_media_type(
|
||||
node::url_to_node_resolution(
|
||||
specifier,
|
||||
&npm_resolver.as_require_npm_resolver(),
|
||||
)
|
||||
.ok(),
|
||||
node_resolver.url_to_node_resolution(specifier).ok(),
|
||||
)
|
||||
}))
|
||||
}
|
||||
|
@ -666,60 +666,47 @@ fn resolve_non_graph_specifier_types(
|
|||
referrer: &ModuleSpecifier,
|
||||
state: &State,
|
||||
) -> Result<Option<(ModuleSpecifier, MediaType)>, AnyError> {
|
||||
let npm_resolver = match state.maybe_npm_resolver.as_ref() {
|
||||
Some(npm_resolver) => npm_resolver,
|
||||
let node_resolver = match state.maybe_node_resolver.as_ref() {
|
||||
Some(node_resolver) => node_resolver,
|
||||
None => return Ok(None), // we only support non-graph types for npm packages
|
||||
};
|
||||
if npm_resolver.in_npm_package(referrer) {
|
||||
if node_resolver.in_npm_package(referrer) {
|
||||
// we're in an npm package, so use node resolution
|
||||
Ok(Some(NodeResolution::into_specifier_and_media_type(
|
||||
node::node_resolve(
|
||||
specifier,
|
||||
referrer,
|
||||
NodeResolutionMode::Types,
|
||||
&npm_resolver.as_require_npm_resolver(),
|
||||
&mut PermissionsContainer::allow_all(),
|
||||
)
|
||||
.ok()
|
||||
.flatten(),
|
||||
node_resolver
|
||||
.resolve(
|
||||
specifier,
|
||||
referrer,
|
||||
NodeResolutionMode::Types,
|
||||
&mut PermissionsContainer::allow_all(),
|
||||
)
|
||||
.ok()
|
||||
.flatten(),
|
||||
)))
|
||||
} else if let Ok(npm_ref) = NpmPackageReqReference::from_str(specifier) {
|
||||
// todo(dsherret): add support for injecting this in the graph so
|
||||
// we don't need this special code here.
|
||||
// This could occur when resolving npm:@types/node when it is
|
||||
// injected and not part of the graph
|
||||
let node_id = npm_resolver.resolve_pkg_id_from_pkg_req(&npm_ref.req)?;
|
||||
let npm_id_ref = NpmPackageNvReference {
|
||||
nv: node_id.nv,
|
||||
sub_path: npm_ref.sub_path,
|
||||
};
|
||||
resolve_npm_package_reference_types(&npm_id_ref, npm_resolver).map(Some)
|
||||
let maybe_resolution = node_resolver.resolve_npm_req_reference(
|
||||
&npm_ref,
|
||||
NodeResolutionMode::Types,
|
||||
&mut PermissionsContainer::allow_all(),
|
||||
)?;
|
||||
Ok(Some(NodeResolution::into_specifier_and_media_type(
|
||||
maybe_resolution,
|
||||
)))
|
||||
} else {
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn resolve_npm_package_reference_types(
|
||||
npm_ref: &NpmPackageNvReference,
|
||||
npm_resolver: &Arc<NpmPackageResolver>,
|
||||
) -> Result<(ModuleSpecifier, MediaType), AnyError> {
|
||||
let maybe_resolution = node_resolve_npm_reference(
|
||||
npm_ref,
|
||||
NodeResolutionMode::Types,
|
||||
npm_resolver,
|
||||
&mut PermissionsContainer::allow_all(),
|
||||
)?;
|
||||
Ok(NodeResolution::into_specifier_and_media_type(
|
||||
maybe_resolution,
|
||||
))
|
||||
}
|
||||
|
||||
#[op]
|
||||
fn op_is_node_file(state: &mut OpState, path: &str) -> bool {
|
||||
let state = state.borrow::<State>();
|
||||
match ModuleSpecifier::parse(path) {
|
||||
Ok(specifier) => state
|
||||
.maybe_npm_resolver
|
||||
.maybe_node_resolver
|
||||
.as_ref()
|
||||
.map(|r| r.in_npm_package(&specifier))
|
||||
.unwrap_or(false),
|
||||
|
@ -783,7 +770,7 @@ pub fn exec(request: Request) -> Result<Response, AnyError> {
|
|||
state.put(State::new(
|
||||
options.request.graph,
|
||||
options.request.hash_data,
|
||||
options.request.maybe_npm_resolver,
|
||||
options.request.maybe_node_resolver,
|
||||
options.request.maybe_tsbuildinfo,
|
||||
options.root_map,
|
||||
options.remapped_specifiers,
|
||||
|
@ -955,7 +942,7 @@ mod tests {
|
|||
debug: false,
|
||||
graph: Arc::new(graph),
|
||||
hash_data,
|
||||
maybe_npm_resolver: None,
|
||||
maybe_node_resolver: None,
|
||||
maybe_tsbuildinfo: None,
|
||||
root_names: vec![(specifier.clone(), MediaType::TypeScript)],
|
||||
check_mode: TypeCheckMode::All,
|
||||
|
|
|
@ -258,23 +258,14 @@ pub async fn create_custom_worker(
|
|||
ps.npm_resolver
|
||||
.add_package_reqs(vec![package_ref.req.clone()])
|
||||
.await?;
|
||||
let pkg_nv = ps
|
||||
.npm_resolution
|
||||
.resolve_pkg_id_from_pkg_req(&package_ref.req)?
|
||||
.nv;
|
||||
let node_resolution = node::node_resolve_binary_export(
|
||||
&pkg_nv,
|
||||
package_ref.sub_path.as_deref(),
|
||||
&ps.npm_resolver,
|
||||
)?;
|
||||
let node_resolution =
|
||||
ps.node_resolver.resolve_binary_export(&package_ref)?;
|
||||
let is_main_cjs =
|
||||
matches!(node_resolution, node::NodeResolution::CommonJs(_));
|
||||
(node_resolution.into_url(), is_main_cjs)
|
||||
} else if ps.options.is_npm_main() {
|
||||
let node_resolution = node::url_to_node_resolution(
|
||||
main_module,
|
||||
&ps.npm_resolver.as_require_npm_resolver(),
|
||||
)?;
|
||||
let node_resolution =
|
||||
ps.node_resolver.url_to_node_resolution(main_module)?;
|
||||
let is_main_cjs =
|
||||
matches!(node_resolution, node::NodeResolution::CommonJs(_));
|
||||
(node_resolution.into_url(), is_main_cjs)
|
||||
|
@ -311,7 +302,7 @@ pub async fn create_custom_worker(
|
|||
.join(checksum::gen(&[key.as_bytes()]))
|
||||
});
|
||||
|
||||
let mut extensions = ops::cli_exts(ps.clone());
|
||||
let mut extensions = ops::cli_exts(ps.npm_resolver.clone());
|
||||
extensions.append(&mut custom_extensions);
|
||||
|
||||
let options = WorkerOptions {
|
||||
|
@ -429,7 +420,7 @@ fn create_web_worker_callback(
|
|||
let pre_execute_module_cb =
|
||||
create_web_worker_pre_execute_module_callback(ps.clone());
|
||||
|
||||
let extensions = ops::cli_exts(ps.clone());
|
||||
let extensions = ops::cli_exts(ps.npm_resolver.clone());
|
||||
|
||||
let maybe_storage_key = ps.options.resolve_storage_key(&args.main_module);
|
||||
let cache_storage_dir = maybe_storage_key.map(|key| {
|
||||
|
|
Loading…
Reference in a new issue