refactor(npm): add CliNodeResolver (#18742)

This commit is contained in:
David Sherret 2023-04-17 15:36:23 -04:00 committed by GitHub
parent 559a61b879
commit d2d62b6312
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
16 changed files with 474 additions and 442 deletions

View file

@ -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(),
)
})
}

View file

@ -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),
})
}

View file

@ -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

View file

@ -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(())));
}

View file

@ -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()

View file

@ -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;

View file

@ -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(),
})
}

View file

@ -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 {

View file

@ -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())
}

View file

@ -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,

View file

@ -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,

View file

@ -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())

View file

@ -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(),

View file

@ -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)]

View file

@ -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,

View file

@ -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| {