summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Sherret <dsherret@users.noreply.github.com>2024-07-23 20:22:24 -0400
committerGitHub <noreply@github.com>2024-07-24 00:22:24 +0000
commit52ababc4bf948904092cff54c2ab8b91f6b9b443 (patch)
tree77dc2fe4a9eb79ce893e1593822df4de1f564260
parent445e05a39d005eab6f7d2f1f67a7ae2d7c85b1b3 (diff)
fix(node): better detection for when to surface node resolution errors (#24653)
-rw-r--r--cli/module_loader.rs17
-rw-r--r--cli/npm/byonm.rs7
-rw-r--r--cli/npm/managed/mod.rs4
-rw-r--r--cli/npm/managed/resolvers/global.rs11
-rw-r--r--cli/npm/managed/resolvers/local.rs10
-rw-r--r--cli/resolver.rs351
-rw-r--r--cli/standalone/mod.rs25
-rw-r--r--cli/tsc/mod.rs38
-rw-r--r--cli/worker.rs7
-rw-r--r--ext/node/errors.rs210
-rw-r--r--ext/node/lib.rs1
-rw-r--r--ext/node/resolution.rs387
-rw-r--r--tests/integration/npm_tests.rs37
-rw-r--r--tests/specs/node/byonm_phantom_dep_res_failure/__test__.jsonc13
-rw-r--r--tests/specs/node/byonm_phantom_dep_res_failure/bad_import.out2
-rw-r--r--tests/specs/node/byonm_phantom_dep_res_failure/bad_import.ts3
-rw-r--r--tests/specs/node/byonm_phantom_dep_res_failure/deno.json3
-rw-r--r--tests/specs/node/byonm_phantom_dep_res_failure/good_import.out1
-rw-r--r--tests/specs/node/byonm_phantom_dep_res_failure/good_import.ts3
-rw-r--r--tests/specs/node/byonm_phantom_dep_res_failure/node_modules/package/main.js1
-rw-r--r--tests/specs/node/byonm_phantom_dep_res_failure/node_modules/package/package.json4
-rw-r--r--tests/specs/node/byonm_phantom_dep_res_failure/package.json2
-rw-r--r--tests/specs/npm/esm_import_cjs_default/__test__.jsonc4
-rw-r--r--tests/specs/npm/esm_import_cjs_default/main.out (renamed from tests/testdata/npm/esm_import_cjs_default/main.out)7
-rw-r--r--tests/specs/npm/esm_import_cjs_default/main.ts (renamed from tests/testdata/npm/esm_import_cjs_default/main.ts)0
-rw-r--r--tests/specs/npm/no_types_cjs/__test__.jsonc4
-rw-r--r--tests/specs/npm/no_types_cjs/main.out3
-rw-r--r--tests/specs/npm/no_types_cjs/main.ts (renamed from tests/testdata/npm/no_types_cjs/main.ts)0
-rw-r--r--tests/specs/npm/no_types_in_conditional_exports/__test__.jsonc4
-rw-r--r--tests/specs/npm/no_types_in_conditional_exports/main.out (renamed from tests/testdata/npm/no_types_in_conditional_exports/main.out)0
-rw-r--r--tests/specs/npm/no_types_in_conditional_exports/main.ts (renamed from tests/testdata/npm/no_types_in_conditional_exports/main.ts)0
-rw-r--r--tests/specs/npm/types_general/__test__.jsonc5
-rw-r--r--tests/specs/npm/types_general/main.out (renamed from tests/testdata/npm/types/main.out)27
-rw-r--r--tests/specs/npm/types_general/main.ts (renamed from tests/testdata/npm/types/main.ts)0
-rwxr-xr-xtools/lint.js2
35 files changed, 676 insertions, 517 deletions
diff --git a/cli/module_loader.rs b/cli/module_loader.rs
index 4254375e5..2e047d36d 100644
--- a/cli/module_loader.rs
+++ b/cli/module_loader.rs
@@ -446,15 +446,14 @@ impl<TGraphContainer: ModuleGraphContainer>
specifier: &str,
referrer: &ModuleSpecifier,
) -> Result<ModuleSpecifier, AnyError> {
- if let Some(result) = self.shared.node_resolver.resolve_if_in_npm_package(
- specifier,
- referrer,
- NodeResolutionMode::Execution,
- ) {
- return match result? {
- Some(res) => Ok(res.into_url()),
- None => Err(generic_error("not found")),
- };
+ if self.shared.node_resolver.in_npm_package(referrer) {
+ return Ok(
+ self
+ .shared
+ .node_resolver
+ .resolve(specifier, referrer, NodeResolutionMode::Execution)?
+ .into_url(),
+ );
}
let graph = self.graph_container.graph();
diff --git a/cli/npm/byonm.rs b/cli/npm/byonm.rs
index f776b79c1..d10bb6b2a 100644
--- a/cli/npm/byonm.rs
+++ b/cli/npm/byonm.rs
@@ -12,7 +12,8 @@ use deno_core::serde_json;
use deno_package_json::PackageJsonDepValue;
use deno_runtime::deno_fs::FileSystem;
use deno_runtime::deno_node::errors::PackageFolderResolveError;
-use deno_runtime::deno_node::errors::PackageFolderResolveErrorKind;
+use deno_runtime::deno_node::errors::PackageFolderResolveIoError;
+use deno_runtime::deno_node::errors::PackageNotFoundError;
use deno_runtime::deno_node::load_pkg_json;
use deno_runtime::deno_node::NodePermissions;
use deno_runtime::deno_node::NpmResolver;
@@ -198,7 +199,7 @@ impl NpmResolver for ByonmCliNpmResolver {
}
Err(
- PackageFolderResolveErrorKind::NotFoundPackage {
+ PackageNotFoundError {
package_name: name.to_string(),
referrer: referrer.clone(),
referrer_extra: None,
@@ -209,7 +210,7 @@ impl NpmResolver for ByonmCliNpmResolver {
let path = inner(&*self.fs, name, referrer)?;
self.fs.realpath_sync(&path).map_err(|err| {
- PackageFolderResolveErrorKind::Io {
+ PackageFolderResolveIoError {
package_name: name.to_string(),
referrer: referrer.clone(),
source: err.into_io_error(),
diff --git a/cli/npm/managed/mod.rs b/cli/npm/managed/mod.rs
index a18ad4d7f..602733cab 100644
--- a/cli/npm/managed/mod.rs
+++ b/cli/npm/managed/mod.rs
@@ -21,7 +21,7 @@ use deno_npm::NpmResolutionPackage;
use deno_npm::NpmSystemInfo;
use deno_runtime::deno_fs::FileSystem;
use deno_runtime::deno_node::errors::PackageFolderResolveError;
-use deno_runtime::deno_node::errors::PackageFolderResolveErrorKind;
+use deno_runtime::deno_node::errors::PackageFolderResolveIoError;
use deno_runtime::deno_node::NodePermissions;
use deno_runtime::deno_node::NpmResolver;
use deno_semver::package::PackageNv;
@@ -549,7 +549,7 @@ impl NpmResolver for ManagedCliNpmResolver {
.resolve_package_folder_from_package(name, referrer)?;
let path =
canonicalize_path_maybe_not_exists_with_fs(&path, self.fs.as_ref())
- .map_err(|err| PackageFolderResolveErrorKind::Io {
+ .map_err(|err| PackageFolderResolveIoError {
package_name: name.to_string(),
referrer: referrer.clone(),
source: err,
diff --git a/cli/npm/managed/resolvers/global.rs b/cli/npm/managed/resolvers/global.rs
index d16fe7cd0..e7a57fc23 100644
--- a/cli/npm/managed/resolvers/global.rs
+++ b/cli/npm/managed/resolvers/global.rs
@@ -15,7 +15,8 @@ use deno_npm::NpmPackageId;
use deno_npm::NpmSystemInfo;
use deno_runtime::deno_fs::FileSystem;
use deno_runtime::deno_node::errors::PackageFolderResolveError;
-use deno_runtime::deno_node::errors::PackageFolderResolveErrorKind;
+use deno_runtime::deno_node::errors::PackageNotFoundError;
+use deno_runtime::deno_node::errors::ReferrerNotFoundError;
use deno_runtime::deno_node::NodePermissions;
use super::super::cache::NpmCache;
@@ -84,7 +85,7 @@ impl NpmPackageFsResolver for GlobalNpmPackageResolver {
.resolve_package_folder_id_from_specifier(referrer)
else {
return Err(
- PackageFolderResolveErrorKind::NotFoundReferrer {
+ ReferrerNotFoundError {
referrer: referrer.clone(),
referrer_extra: None,
}
@@ -98,7 +99,7 @@ impl NpmPackageFsResolver for GlobalNpmPackageResolver {
Ok(pkg) => match self.maybe_package_folder(&pkg.id) {
Some(folder) => Ok(folder),
None => Err(
- PackageFolderResolveErrorKind::NotFoundPackage {
+ PackageNotFoundError {
package_name: name.to_string(),
referrer: referrer.clone(),
referrer_extra: Some(format!(
@@ -112,7 +113,7 @@ impl NpmPackageFsResolver for GlobalNpmPackageResolver {
},
Err(err) => match *err {
PackageNotFoundFromReferrerError::Referrer(cache_folder_id) => Err(
- PackageFolderResolveErrorKind::NotFoundReferrer {
+ ReferrerNotFoundError {
referrer: referrer.clone(),
referrer_extra: Some(cache_folder_id.to_string()),
}
@@ -122,7 +123,7 @@ impl NpmPackageFsResolver for GlobalNpmPackageResolver {
name,
referrer: cache_folder_id_referrer,
} => Err(
- PackageFolderResolveErrorKind::NotFoundPackage {
+ PackageNotFoundError {
package_name: name,
referrer: referrer.clone(),
referrer_extra: Some(cache_folder_id_referrer.to_string()),
diff --git a/cli/npm/managed/resolvers/local.rs b/cli/npm/managed/resolvers/local.rs
index 90a17b157..cda78548b 100644
--- a/cli/npm/managed/resolvers/local.rs
+++ b/cli/npm/managed/resolvers/local.rs
@@ -33,7 +33,9 @@ use deno_npm::NpmResolutionPackage;
use deno_npm::NpmSystemInfo;
use deno_runtime::deno_fs;
use deno_runtime::deno_node::errors::PackageFolderResolveError;
-use deno_runtime::deno_node::errors::PackageFolderResolveErrorKind;
+use deno_runtime::deno_node::errors::PackageFolderResolveIoError;
+use deno_runtime::deno_node::errors::PackageNotFoundError;
+use deno_runtime::deno_node::errors::ReferrerNotFoundError;
use deno_runtime::deno_node::NodePermissions;
use deno_semver::package::PackageNv;
use serde::Deserialize;
@@ -185,14 +187,14 @@ impl NpmPackageFsResolver for LocalNpmPackageResolver {
) -> Result<PathBuf, PackageFolderResolveError> {
let maybe_local_path = self
.resolve_folder_for_specifier(referrer)
- .map_err(|err| PackageFolderResolveErrorKind::Io {
+ .map_err(|err| PackageFolderResolveIoError {
package_name: name.to_string(),
referrer: referrer.clone(),
source: err,
})?;
let Some(local_path) = maybe_local_path else {
return Err(
- PackageFolderResolveErrorKind::NotFoundReferrer {
+ ReferrerNotFoundError {
referrer: referrer.clone(),
referrer_extra: None,
}
@@ -220,7 +222,7 @@ impl NpmPackageFsResolver for LocalNpmPackageResolver {
}
Err(
- PackageFolderResolveErrorKind::NotFoundPackage {
+ PackageNotFoundError {
package_name: name.to_string(),
referrer: referrer.clone(),
referrer_extra: None,
diff --git a/cli/resolver.rs b/cli/resolver.rs
index c332878a2..c1bb8a0a5 100644
--- a/cli/resolver.rs
+++ b/cli/resolver.rs
@@ -25,15 +25,17 @@ use deno_runtime::deno_fs;
use deno_runtime::deno_fs::FileSystem;
use deno_runtime::deno_node::errors::ClosestPkgJsonError;
use deno_runtime::deno_node::errors::NodeResolveError;
-use deno_runtime::deno_node::errors::ResolvePkgSubpathFromDenoModuleError;
+use deno_runtime::deno_node::errors::NodeResolveErrorKind;
+use deno_runtime::deno_node::errors::PackageFolderResolveErrorKind;
+use deno_runtime::deno_node::errors::PackageFolderResolveIoError;
+use deno_runtime::deno_node::errors::PackageNotFoundError;
+use deno_runtime::deno_node::errors::PackageResolveErrorKind;
use deno_runtime::deno_node::errors::UrlToNodeResolutionError;
use deno_runtime::deno_node::is_builtin_node_module;
-use deno_runtime::deno_node::parse_npm_pkg_name;
use deno_runtime::deno_node::NodeModuleKind;
use deno_runtime::deno_node::NodeResolution;
use deno_runtime::deno_node::NodeResolutionMode;
use deno_runtime::deno_node::NodeResolver;
-use deno_runtime::deno_node::NpmResolver as DenoNodeNpmResolver;
use deno_runtime::deno_node::PackageJson;
use deno_runtime::fs_util::specifier_to_file_path;
use deno_semver::npm::NpmPackageReqReference;
@@ -47,7 +49,6 @@ use crate::args::JsxImportSourceConfig;
use crate::args::DENO_DISABLE_PEDANTIC_NODE_WARNINGS;
use crate::colors;
use crate::node::CliNodeCodeTranslator;
-use crate::npm::ByonmCliNpmResolver;
use crate::npm::CliNpmResolver;
use crate::npm::InnerCliNpmResolverRef;
use crate::util::sync::AtomicFlag;
@@ -102,17 +103,77 @@ impl CliNodeResolver {
self.node_resolver.get_closest_package_json(referrer)
}
- pub fn resolve_if_in_npm_package(
+ pub fn resolve_if_for_npm_pkg(
&self,
specifier: &str,
referrer: &ModuleSpecifier,
mode: NodeResolutionMode,
- ) -> Option<Result<Option<NodeResolution>, NodeResolveError>> {
- if self.in_npm_package(referrer) {
- // we're in an npm package, so use node resolution
- Some(self.resolve(specifier, referrer, mode))
- } else {
- None
+ ) -> Result<Option<NodeResolution>, AnyError> {
+ let resolution_result = self.resolve(specifier, referrer, mode);
+ match resolution_result {
+ Ok(res) => Ok(Some(res)),
+ Err(err) => {
+ let err = err.into_kind();
+ match err {
+ NodeResolveErrorKind::RelativeJoin(_)
+ | NodeResolveErrorKind::PackageImportsResolve(_)
+ | NodeResolveErrorKind::UnsupportedEsmUrlScheme(_)
+ | NodeResolveErrorKind::DataUrlReferrer(_)
+ | NodeResolveErrorKind::TypesNotFound(_)
+ | NodeResolveErrorKind::FinalizeResolution(_)
+ | NodeResolveErrorKind::UrlToNodeResolution(_) => Err(err.into()),
+ NodeResolveErrorKind::PackageResolve(err) => {
+ let err = err.into_kind();
+ match err {
+ PackageResolveErrorKind::ClosestPkgJson(_)
+ | PackageResolveErrorKind::InvalidModuleSpecifier(_)
+ | PackageResolveErrorKind::ExportsResolve(_)
+ | PackageResolveErrorKind::SubpathResolve(_) => Err(err.into()),
+ PackageResolveErrorKind::PackageFolderResolve(err) => {
+ match err.as_kind() {
+ PackageFolderResolveErrorKind::Io(
+ PackageFolderResolveIoError { package_name, .. },
+ )
+ | PackageFolderResolveErrorKind::PackageNotFound(
+ PackageNotFoundError { package_name, .. },
+ ) => {
+ if self.in_npm_package(referrer) {
+ return Err(err.into());
+ }
+ if let Some(byonm_npm_resolver) =
+ self.npm_resolver.as_byonm()
+ {
+ if byonm_npm_resolver
+ .find_ancestor_package_json_with_dep(
+ package_name,
+ referrer,
+ )
+ .is_some()
+ {
+ return Err(anyhow!(
+ concat!(
+ "Could not resolve \"{}\", but found it in a package.json. ",
+ "Deno expects the node_modules/ directory to be up to date. ",
+ "Did you forget to run `npm install`?"
+ ),
+ specifier
+ ));
+ }
+ }
+ Ok(None)
+ }
+ PackageFolderResolveErrorKind::ReferrerNotFound(_) => {
+ if self.in_npm_package(referrer) {
+ return Err(err.into());
+ }
+ Ok(None)
+ }
+ }
+ }
+ }
+ }
+ }
+ }
}
}
@@ -121,18 +182,18 @@ impl CliNodeResolver {
specifier: &str,
referrer: &ModuleSpecifier,
mode: NodeResolutionMode,
- ) -> Result<Option<NodeResolution>, NodeResolveError> {
+ ) -> Result<NodeResolution, NodeResolveError> {
let referrer_kind = if self.cjs_resolutions.contains(referrer) {
NodeModuleKind::Cjs
} else {
NodeModuleKind::Esm
};
- let maybe_res =
+ let res =
self
.node_resolver
.resolve(specifier, referrer, referrer_kind, mode)?;
- Ok(self.handle_node_resolution(maybe_res))
+ Ok(self.handle_node_resolution(res))
}
pub fn resolve_req_reference(
@@ -159,16 +220,15 @@ impl CliNodeResolver {
let package_folder = self
.npm_resolver
.resolve_pkg_folder_from_deno_module_req(req, referrer)?;
- let maybe_resolution = self
- .maybe_resolve_package_sub_path_from_deno_module(
- &package_folder,
- sub_path,
- Some(referrer),
- mode,
- )?;
- match maybe_resolution {
- Some(resolution) => Ok(resolution),
- None => {
+ let resolution_result = self.resolve_package_sub_path_from_deno_module(
+ &package_folder,
+ sub_path,
+ Some(referrer),
+ mode,
+ );
+ match resolution_result {
+ Ok(resolution) => Ok(resolution),
+ Err(err) => {
if self.npm_resolver.as_byonm().is_some() {
let package_json_path = package_folder.join("package.json");
if !self.fs.exists_sync(&package_json_path) {
@@ -178,12 +238,7 @@ impl CliNodeResolver {
));
}
}
- Err(anyhow!(
- "Failed resolving '{}{}' in '{}'.",
- req,
- sub_path.map(|s| format!("/{}", s)).unwrap_or_default(),
- package_folder.display()
- ))
+ Err(err)
}
}
}
@@ -195,32 +250,7 @@ impl CliNodeResolver {
maybe_referrer: Option<&ModuleSpecifier>,
mode: NodeResolutionMode,
) -> Result<NodeResolution, AnyError> {
- self
- .maybe_resolve_package_sub_path_from_deno_module(
- package_folder,
- sub_path,
- maybe_referrer,
- mode,
- )?
- .ok_or_else(|| {
- anyhow!(
- "Failed resolving '{}' in '{}'.",
- sub_path
- .map(|s| format!("/{}", s))
- .unwrap_or_else(|| ".".to_string()),
- package_folder.display(),
- )
- })
- }
-
- pub fn maybe_resolve_package_sub_path_from_deno_module(
- &self,
- package_folder: &Path,
- sub_path: Option<&str>,
- maybe_referrer: Option<&ModuleSpecifier>,
- mode: NodeResolutionMode,
- ) -> Result<Option<NodeResolution>, ResolvePkgSubpathFromDenoModuleError> {
- let maybe_res = self
+ let res = self
.node_resolver
.resolve_package_subpath_from_deno_module(
package_folder,
@@ -228,7 +258,7 @@ impl CliNodeResolver {
maybe_referrer,
mode,
)?;
- Ok(self.handle_node_resolution(maybe_res))
+ Ok(self.handle_node_resolution(res))
}
pub fn handle_if_in_node_modules(
@@ -267,13 +297,13 @@ impl CliNodeResolver {
fn handle_node_resolution(
&self,
- maybe_resolution: Option<NodeResolution>,
- ) -> Option<NodeResolution> {
- if let Some(NodeResolution::CommonJs(specifier)) = &maybe_resolution {
+ resolution: NodeResolution,
+ ) -> NodeResolution {
+ if let NodeResolution::CommonJs(specifier) = &resolution {
// remember that this was a common js resolution
self.cjs_resolutions.insert(specifier.clone());
}
- maybe_resolution
+ resolution
}
}
@@ -458,39 +488,6 @@ impl CliGraphResolver {
bare_node_builtins_enabled: self.bare_node_builtins_enabled,
}
}
-
- // todo(dsherret): update this and the surrounding code to handle the structured errors from NodeResolver
- fn check_surface_byonm_node_error(
- &self,
- specifier: &str,
- referrer: &ModuleSpecifier,
- original_err: AnyError,
- resolver: &ByonmCliNpmResolver,
- ) -> Result<(), AnyError> {
- if let Ok((pkg_name, _, _)) = parse_npm_pkg_name(specifier, referrer) {
- match resolver.resolve_package_folder_from_package(&pkg_name, referrer) {
- Ok(_) => {
- return Err(original_err);
- }
- Err(_) => {
- if resolver
- .find_ancestor_package_json_with_dep(&pkg_name, referrer)
- .is_some()
- {
- return Err(anyhow!(
- concat!(
- "Could not resolve \"{}\", but found it in a package.json. ",
- "Deno expects the node_modules/ directory to be up to date. ",
- "Did you forget to run `npm install`?"
- ),
- specifier
- ));
- }
- }
- }
- }
- Ok(())
- }
}
impl Resolver for CliGraphResolver {
@@ -523,6 +520,18 @@ impl Resolver for CliGraphResolver {
}
let referrer = &referrer_range.specifier;
+
+ // Use node resolution if we're in an npm package
+ if let Some(node_resolver) = self.node_resolver.as_ref() {
+ if referrer.scheme() == "file" && node_resolver.in_npm_package(referrer) {
+ return node_resolver
+ .resolve(specifier, referrer, to_node_mode(mode))
+ .map(|res| res.into_url())
+ .map_err(|e| ResolveError::Other(e.into()));
+ }
+ }
+
+ // Attempt to resolve with the workspace resolver
let result: Result<_, ResolveError> = self
.workspace_resolver
.resolve(specifier, referrer)
@@ -535,7 +544,19 @@ impl Resolver for CliGraphResolver {
let result = match result {
Ok(resolution) => match resolution {
MappedResolution::Normal(specifier)
- | MappedResolution::ImportMap(specifier) => Ok(specifier),
+ | MappedResolution::ImportMap(specifier) => {
+ // do sloppy imports resolution if enabled
+ if let Some(sloppy_imports_resolver) = &self.sloppy_imports_resolver {
+ Ok(sloppy_imports_resolve(
+ sloppy_imports_resolver,
+ specifier,
+ referrer_range,
+ mode,
+ ))
+ } else {
+ Ok(specifier)
+ }
+ }
MappedResolution::WorkspaceNpmPackage {
target_pkg_json: pkg_json,
sub_path,
@@ -552,8 +573,6 @@ impl Resolver for CliGraphResolver {
)
.map_err(ResolveError::Other)
.map(|res| res.into_url()),
- // todo(dsherret): for byonm it should do resolution solely based on
- // the referrer and not the package.json
MappedResolution::PackageJson {
dep_result,
alias,
@@ -604,127 +623,75 @@ impl Resolver for CliGraphResolver {
Err(err) => Err(err),
};
- // check if it's an npm specifier that resolves to a workspace member
- if let Some(node_resolver) = &self.node_resolver {
+ // When the user is vendoring, don't allow them to import directly from the vendor/ directory
+ // as it might cause them confusion or duplicate dependencies. Additionally, this folder has
+ // special treatment in the language server so it will definitely cause issues/confusion there
+ // if they do this.
+ if let Some(vendor_specifier) = &self.maybe_vendor_specifier {
if let Ok(specifier) = &result {
- if let Ok(req_ref) = NpmPackageReqReference::from_specifier(specifier) {
+ if specifier.as_str().starts_with(vendor_specifier.as_str()) {
+ return Err(ResolveError::Other(anyhow!("Importing from the vendor directory is not permitted. Use a remote specifier instead or disable vendoring.")));
+ }
+ }
+ }
+
+ let Some(node_resolver) = &self.node_resolver else {
+ return result;
+ };
+
+ let is_byonm = self
+ .npm_resolver
+ .as_ref()
+ .is_some_and(|r| r.as_byonm().is_some());
+ match result {
+ Ok(specifier) => {
+ if let Ok(npm_req_ref) =
+ NpmPackageReqReference::from_specifier(&specifier)
+ {
+ // check if the npm specifier resolves to a workspace member
if let Some(pkg_folder) = self
.workspace_resolver
- .resolve_workspace_pkg_json_folder_for_npm_specifier(req_ref.req())
+ .resolve_workspace_pkg_json_folder_for_npm_specifier(
+ npm_req_ref.req(),
+ )
{
return Ok(
node_resolver
.resolve_package_sub_path_from_deno_module(
pkg_folder,
- req_ref.sub_path(),
+ npm_req_ref.sub_path(),
Some(referrer),
to_node_mode(mode),
)?
.into_url(),
);
}
- }
- }
- }
-
- // do sloppy imports resolution if enabled
- let result =
- if let Some(sloppy_imports_resolver) = &self.sloppy_imports_resolver {
- result.map(|specifier| {
- sloppy_imports_resolve(
- sloppy_imports_resolver,
- specifier,
- referrer_range,
- mode,
- )
- })
- } else {
- result
- };
-
- // When the user is vendoring, don't allow them to import directly from the vendor/ directory
- // as it might cause them confusion or duplicate dependencies. Additionally, this folder has
- // special treatment in the language server so it will definitely cause issues/confusion there
- // if they do this.
- if let Some(vendor_specifier) = &self.maybe_vendor_specifier {
- if let Ok(specifier) = &result {
- if specifier.as_str().starts_with(vendor_specifier.as_str()) {
- return Err(ResolveError::Other(anyhow!("Importing from the vendor directory is not permitted. Use a remote specifier instead or disable vendoring.")));
- }
- }
- }
- if let Some(resolver) =
- self.npm_resolver.as_ref().and_then(|r| r.as_byonm())
- {
- match &result {
- Ok(specifier) => {
- if let Ok(npm_req_ref) =
- NpmPackageReqReference::from_specifier(specifier)
- {
- let node_resolver = self.node_resolver.as_ref().unwrap();
+ // do npm resolution for byonm
+ if is_byonm {
return node_resolver
.resolve_req_reference(&npm_req_ref, referrer, to_node_mode(mode))
.map(|res| res.into_url())
.map_err(|err| err.into());
}
}
- Err(_) => {
- if referrer.scheme() == "file" {
- if let Some(node_resolver) = &self.node_resolver {
- let node_result =
- node_resolver.resolve(specifier, referrer, to_node_mode(mode));
- match node_result {
- Ok(Some(res)) => {
- return Ok(res.into_url());
- }
- Ok(None) => {
- self
- .check_surface_byonm_node_error(
- specifier,
- referrer,
- anyhow!("Cannot find \"{}\"", specifier),
- resolver,
- )
- .map_err(ResolveError::Other)?;
- }
- Err(err) => {
- self
- .check_surface_byonm_node_error(
- specifier,
- referrer,
- err.into(),
- resolver,
- )
- .map_err(ResolveError::Other)?;
- }
- }
- }
+
+ Ok(node_resolver.handle_if_in_node_modules(specifier)?)
+ }
+ Err(err) => {
+ // If byonm, check if the bare specifier resolves to an npm package
+ if is_byonm && referrer.scheme() == "file" {
+ let maybe_resolution = node_resolver
+ .resolve_if_for_npm_pkg(specifier, referrer, to_node_mode(mode))
+ .map_err(ResolveError::Other)?;
+ if let Some(res) = maybe_resolution {
+ return Ok(res.into_url());
}
}
- }
- }
- if referrer.scheme() == "file" {
- if let Some(node_resolver) = &self.node_resolver {
- let node_result = node_resolver.resolve_if_in_npm_package(
- specifier,
- referrer,
- to_node_mode(mode),
- );
- if let Some(Ok(Some(res))) = node_result {
- return Ok(res.into_url());
- }
+ Err(err)
}
}
-
- let specifier = result?;
- match &self.node_resolver {
- Some(node_resolver) => node_resolver
- .handle_if_in_node_modules(specifier)
- .map_err(|e| e.into()),
- None => Ok(specifier),
- }
}
}
diff --git a/cli/standalone/mod.rs b/cli/standalone/mod.rs
index 74586c1be..561c99c98 100644
--- a/cli/standalone/mod.rs
+++ b/cli/standalone/mod.rs
@@ -151,15 +151,14 @@ impl ModuleLoader for EmbeddedModuleLoader {
})?
};
- if let Some(result) = self.shared.node_resolver.resolve_if_in_npm_package(
- specifier,
- &referrer,
- NodeResolutionMode::Execution,
- ) {
- return match result? {
- Some(res) => Ok(res.into_url()),
- None => Err(generic_error("not found")),
- };
+ if self.shared.node_resolver.in_npm_package(&referrer) {
+ return Ok(
+ self
+ .shared
+ .node_resolver
+ .resolve(specifier, &referrer, NodeResolutionMode::Execution)?
+ .into_url(),
+ );
}
let mapped_resolution =
@@ -250,14 +249,12 @@ impl ModuleLoader for EmbeddedModuleLoader {
Err(err)
if err.is_unmapped_bare_specifier() && referrer.scheme() == "file" =>
{
- // todo(dsherret): return a better error from node resolution so that
- // we can more easily tell whether to surface it or not
- let node_result = self.shared.node_resolver.resolve(
+ let maybe_res = self.shared.node_resolver.resolve_if_for_npm_pkg(
specifier,
&referrer,
NodeResolutionMode::Execution,
- );
- if let Ok(Some(res)) = node_result {
+ )?;
+ if let Some(res) = maybe_res {
return Ok(res.into_url());
}
Err(err.into())
diff --git a/cli/tsc/mod.rs b/cli/tsc/mod.rs
index f6440266e..424b5c3d3 100644
--- a/cli/tsc/mod.rs
+++ b/cli/tsc/mod.rs
@@ -30,6 +30,8 @@ use deno_graph::GraphKind;
use deno_graph::Module;
use deno_graph::ModuleGraph;
use deno_graph::ResolutionResolved;
+use deno_runtime::deno_node::errors::NodeJsErrorCode;
+use deno_runtime::deno_node::errors::NodeJsErrorCoded;
use deno_runtime::deno_node::NodeModuleKind;
use deno_runtime::deno_node::NodeResolution;
use deno_runtime::deno_node::NodeResolutionMode;
@@ -756,13 +758,21 @@ fn resolve_graph_specifier_types(
.as_managed()
.unwrap() // should never be byonm because it won't create Module::Npm
.resolve_pkg_folder_from_deno_module(module.nv_reference.nv())?;
- let maybe_resolution =
+ let res_result =
npm.node_resolver.resolve_package_subpath_from_deno_module(
&package_folder,
module.nv_reference.sub_path(),
Some(referrer),
NodeResolutionMode::Types,
- )?;
+ );
+ let maybe_resolution = match res_result {
+ Ok(res) => Some(res),
+ Err(err) => match err.code() {
+ NodeJsErrorCode::ERR_TYPES_NOT_FOUND
+ | NodeJsErrorCode::ERR_MODULE_NOT_FOUND => None,
+ _ => return Err(err.into()),
+ },
+ };
Ok(Some(NodeResolution::into_specifier_and_media_type(
maybe_resolution,
)))
@@ -805,8 +815,7 @@ fn resolve_non_graph_specifier_types(
referrer_kind,
NodeResolutionMode::Types,
)
- .ok()
- .flatten(),
+ .ok(),
)))
} else if let Ok(npm_req_ref) = NpmPackageReqReference::from_str(specifier) {
debug_assert_eq!(referrer_kind, NodeModuleKind::Esm);
@@ -817,13 +826,20 @@ fn resolve_non_graph_specifier_types(
let package_folder = npm
.npm_resolver
.resolve_pkg_folder_from_deno_module_req(npm_req_ref.req(), referrer)?;
- let maybe_resolution = node_resolver
- .resolve_package_subpath_from_deno_module(
- &package_folder,
- npm_req_ref.sub_path(),
- Some(referrer),
- NodeResolutionMode::Types,
- )?;
+ let res_result = node_resolver.resolve_package_subpath_from_deno_module(
+ &package_folder,
+ npm_req_ref.sub_path(),
+ Some(referrer),
+ NodeResolutionMode::Types,
+ );
+ let maybe_resolution = match res_result {
+ Ok(res) => Some(res),
+ Err(err) => match err.code() {
+ NodeJsErrorCode::ERR_TYPES_NOT_FOUND
+ | NodeJsErrorCode::ERR_MODULE_NOT_FOUND => None,
+ _ => return Err(err.into()),
+ },
+ };
Ok(Some(NodeResolution::into_specifier_and_media_type(
maybe_resolution,
)))
diff --git a/cli/worker.rs b/cli/worker.rs
index a639dae41..0d7e61c50 100644
--- a/cli/worker.rs
+++ b/cli/worker.rs
@@ -687,7 +687,7 @@ impl CliMainWorkerFactory {
return Ok(None);
}
- let Some(resolution) = self
+ let resolution = self
.shared
.node_resolver
.resolve_package_subpath_from_deno_module(
@@ -695,10 +695,7 @@ impl CliMainWorkerFactory {
sub_path,
/* referrer */ None,
NodeResolutionMode::Execution,
- )?
- else {
- return Ok(None);
- };
+ )?;
match &resolution {
NodeResolution::BuiltIn(_) => Ok(None),
NodeResolution::CommonJs(specifier) | NodeResolution::Esm(specifier) => {
diff --git a/ext/node/errors.rs b/ext/node/errors.rs
index 11bb011f8..64625d32f 100644
--- a/ext/node/errors.rs
+++ b/ext/node/errors.rs
@@ -49,6 +49,8 @@ pub enum NodeJsErrorCode {
ERR_UNKNOWN_FILE_EXTENSION,
ERR_UNSUPPORTED_DIR_IMPORT,
ERR_UNSUPPORTED_ESM_URL_SCHEME,
+ /// Deno specific since Node doesn't support TypeScript.
+ ERR_TYPES_NOT_FOUND,
}
impl std::fmt::Display for NodeJsErrorCode {
@@ -70,6 +72,7 @@ impl NodeJsErrorCode {
ERR_UNKNOWN_FILE_EXTENSION => "ERR_UNKNOWN_FILE_EXTENSION",
ERR_UNSUPPORTED_DIR_IMPORT => "ERR_UNSUPPORTED_DIR_IMPORT",
ERR_UNSUPPORTED_ESM_URL_SCHEME => "ERR_UNSUPPORTED_ESM_URL_SCHEME",
+ ERR_TYPES_NOT_FOUND => "ERR_TYPES_NOT_FOUND",
}
}
}
@@ -122,65 +125,98 @@ impl NodeJsErrorCoded for InvalidModuleSpecifierError {
}
}
+kinded_err!(LegacyResolveError, LegacyResolveErrorKind);
+
#[derive(Debug, Error)]
-pub enum LegacyMainResolveError {
+pub enum LegacyResolveErrorKind {
+ #[error(transparent)]
+ TypesNotFound(#[from] TypesNotFoundError),
#[error(transparent)]
- PathToDeclarationUrl(PathToDeclarationUrlError),
+ ModuleNotFound(#[from] ModuleNotFoundError),
}
-impl NodeJsErrorCoded for LegacyMainResolveError {
+impl NodeJsErrorCoded for LegacyResolveError {
fn code(&self) -> NodeJsErrorCode {
- match self {
- Self::PathToDeclarationUrl(e) => e.code(),
+ match self.as_kind() {
+ LegacyResolveErrorKind::TypesNotFound(e) => e.code(),
+ LegacyResolveErrorKind::ModuleNotFound(e) => e.code(),
}
}
}
kinded_err!(PackageFolderResolveError, PackageFolderResolveErrorKind);
+#[derive(Debug, Error)]
+#[error(
+ "Could not find package '{}' from referrer '{}'{}.",
+ package_name,
+ referrer,
+ referrer_extra.as_ref().map(|r| format!(" ({})", r)).unwrap_or_default()
+)]
+pub struct PackageNotFoundError {
+ pub package_name: String,
+ pub referrer: ModuleSpecifier,
+ /// Extra information about the referrer.
+ pub referrer_extra: Option<String>,
+}
+
+impl NodeJsErrorCoded for PackageNotFoundError {
+ fn code(&self) -> NodeJsErrorCode {
+ NodeJsErrorCode::ERR_MODULE_NOT_FOUND
+ }
+}
+
+#[derive(Debug, Error)]
+#[error(
+ "Could not find referrer npm package '{}'{}.",
+ referrer,
+ referrer_extra.as_ref().map(|r| format!(" ({})", r)).unwrap_or_default()
+)]
+pub struct ReferrerNotFoundError {
+ pub referrer: ModuleSpecifier,
+ /// Extra information about the referrer.
+ pub referrer_extra: Option<String>,
+}
+
+impl NodeJsErrorCoded for ReferrerNotFoundError {
+ fn code(&self) -> NodeJsErrorCode {
+ NodeJsErrorCode::ERR_MODULE_NOT_FOUND
+ }
+}
+
+#[derive(Debug, Error)]
+#[error("Failed resolving '{package_name}' from referrer '{referrer}'.")]
+pub struct PackageFolderResolveIoError {
+ pub package_name: String,
+ pub referrer: ModuleSpecifier,
+ #[source]
+ pub source: std::io::Error,
+}
+
+impl NodeJsErrorCoded for PackageFolderResolveIoError {
+ fn code(&self) -> NodeJsErrorCode {
+ NodeJsErrorCode::ERR_MODULE_NOT_FOUND
+ }
+}
+
impl NodeJsErrorCoded for PackageFolderResolveError {
fn code(&self) -> NodeJsErrorCode {
match self.as_kind() {
- PackageFolderResolveErrorKind::NotFoundPackage { .. }
- | PackageFolderResolveErrorKind::NotFoundReferrer { .. }
- | PackageFolderResolveErrorKind::Io { .. } => {
- NodeJsErrorCode::ERR_MODULE_NOT_FOUND
- }
+ PackageFolderResolveErrorKind::PackageNotFound(e) => e.code(),
+ PackageFolderResolveErrorKind::ReferrerNotFound(e) => e.code(),
+ PackageFolderResolveErrorKind::Io(e) => e.code(),
}
}
}
#[derive(Debug, Error)]
pub enum PackageFolderResolveErrorKind {
- #[error(
- "Could not find package '{}' from referrer '{}'{}.",
- package_name,
- referrer,
- referrer_extra.as_ref().map(|r| format!(" ({})", r)).unwrap_or_default()
- )]
- NotFoundPackage {
- package_name: String,
- referrer: ModuleSpecifier,
- /// Extra information about the referrer.
- referrer_extra: Option<String>,
- },
- #[error(
- "Could not find referrer npm package '{}'{}.",
- referrer,
- referrer_extra.as_ref().map(|r| format!(" ({})", r)).unwrap_or_default()
- )]
- NotFoundReferrer {
- referrer: ModuleSpecifier,
- /// Extra information about the referrer.
- referrer_extra: Option<String>,
- },
- #[error("Failed resolving '{package_name}' from referrer '{referrer}'.")]
- Io {
- package_name: String,
- referrer: ModuleSpecifier,
- #[source]
- source: std::io::Error,
- },
+ #[error(transparent)]
+ PackageNotFound(#[from] PackageNotFoundError),
+ #[error(transparent)]
+ ReferrerNotFound(#[from] ReferrerNotFoundError),
+ #[error(transparent)]
+ Io(#[from] PackageFolderResolveIoError),
}
kinded_err!(PackageSubpathResolveError, PackageSubpathResolveErrorKind);
@@ -189,10 +225,8 @@ impl NodeJsErrorCoded for PackageSubpathResolveError {
fn code(&self) -> NodeJsErrorCode {
match self.as_kind() {
PackageSubpathResolveErrorKind::PkgJsonLoad(e) => e.code(),
- PackageSubpathResolveErrorKind::PackageFolderResolve(e) => e.code(),
PackageSubpathResolveErrorKind::Exports(e) => e.code(),
- PackageSubpathResolveErrorKind::LegacyMain(e) => e.code(),
- PackageSubpathResolveErrorKind::LegacyExact(e) => e.code(),
+ PackageSubpathResolveErrorKind::LegacyResolve(e) => e.code(),
}
}
}
@@ -202,13 +236,9 @@ pub enum PackageSubpathResolveErrorKind {
#[error(transparent)]
PkgJsonLoad(#[from] PackageJsonLoadError),
#[error(transparent)]
- PackageFolderResolve(#[from] PackageFolderResolveError),
- #[error(transparent)]
Exports(PackageExportsResolveError),
#[error(transparent)]
- LegacyMain(LegacyMainResolveError),
- #[error(transparent)]
- LegacyExact(PathToDeclarationUrlError),
+ LegacyResolve(LegacyResolveError),
}
#[derive(Debug, Error)]
@@ -254,7 +284,7 @@ impl NodeJsErrorCoded for PackageTargetResolveError {
PackageTargetResolveErrorKind::InvalidPackageTarget(e) => e.code(),
PackageTargetResolveErrorKind::InvalidModuleSpecifier(e) => e.code(),
PackageTargetResolveErrorKind::PackageResolve(e) => e.code(),
- PackageTargetResolveErrorKind::PathToDeclarationUrl(e) => e.code(),
+ PackageTargetResolveErrorKind::TypesNotFound(e) => e.code(),
}
}
}
@@ -270,7 +300,7 @@ pub enum PackageTargetResolveErrorKind {
#[error(transparent)]
PackageResolve(#[from] PackageResolveError),
#[error(transparent)]
- PathToDeclarationUrl(#[from] PathToDeclarationUrlError),
+ TypesNotFound(#[from] TypesNotFoundError),
}
kinded_err!(PackageExportsResolveError, PackageExportsResolveErrorKind);
@@ -293,16 +323,23 @@ pub enum PackageExportsResolveErrorKind {
}
#[derive(Debug, Error)]
-pub enum PathToDeclarationUrlError {
- #[error(transparent)]
- SubPath(#[from] PackageSubpathResolveError),
+#[error(
+ "[{}] Could not find types for '{}'{}",
+ self.code(),
+ self.0.code_specifier,
+ self.0.maybe_referrer.as_ref().map(|r| format!(" imported from '{}'", r)).unwrap_or_default(),
+ )]
+pub struct TypesNotFoundError(pub Box<TypesNotFoundErrorData>);
+
+#[derive(Debug)]
+pub struct TypesNotFoundErrorData {
+ pub code_specifier: ModuleSpecifier,
+ pub maybe_referrer: Option<ModuleSpecifier>,
}
-impl NodeJsErrorCoded for PathToDeclarationUrlError {
+impl NodeJsErrorCoded for TypesNotFoundError {
fn code(&self) -> NodeJsErrorCode {
- match self {
- PathToDeclarationUrlError::SubPath(e) => e.code(),
- }
+ NodeJsErrorCode::ERR_TYPES_NOT_FOUND
}
}
@@ -441,6 +478,7 @@ impl NodeJsErrorCoded for PackageResolveError {
match self.as_kind() {
PackageResolveErrorKind::ClosestPkgJson(e) => e.code(),
PackageResolveErrorKind::InvalidModuleSpecifier(e) => e.code(),
+ PackageResolveErrorKind::PackageFolderResolve(e) => e.code(),
PackageResolveErrorKind::ExportsResolve(e) => e.code(),
PackageResolveErrorKind::SubpathResolve(e) => e.code(),
}
@@ -454,37 +492,49 @@ pub enum PackageResolveErrorKind {
#[error(transparent)]
InvalidModuleSpecifier(#[from] InvalidModuleSpecifierError),
#[error(transparent)]
+ PackageFolderResolve(#[from] PackageFolderResolveError),
+ #[error(transparent)]
ExportsResolve(#[from] PackageExportsResolveError),
#[error(transparent)]
SubpathResolve(#[from] PackageSubpathResolveError),
}
#[derive(Debug, Error)]
-pub enum NodeResolveError {
- #[error("Failed joining '{path}' from '{base}'.")]
- RelativeJoinError {
- path: String,
- base: ModuleSpecifier,
- #[source]
- source: url::ParseError,
- },
+#[error("Failed joining '{path}' from '{base}'.")]
+pub struct NodeResolveRelativeJoinError {
+ pub path: String,
+ pub base: ModuleSpecifier,
+ #[source]
+ pub source: url::ParseError,
+}
+
+#[derive(Debug, Error)]
+#[error("Failed resolving specifier from data url referrer.")]
+pub struct DataUrlReferrerError {
+ #[source]
+ pub source: url::ParseError,
+}
+
+kinded_err!(NodeResolveError, NodeResolveErrorKind);
+
+#[derive(Debug, Error)]
+pub enum NodeResolveErrorKind {
+ #[error(transparent)]
+ RelativeJoin(#[from] NodeResolveRelativeJoinError),
#[error(transparent)]
PackageImportsResolve(#[from] PackageImportsResolveError),
#[error(transparent)]
UnsupportedEsmUrlScheme(#[from] UnsupportedEsmUrlSchemeError),
- #[error("Failed resolving specifier from data url referrer.")]
- DataUrlReferrerFailed {
- #[source]
- source: url::ParseError,
- },
+ #[error(transparent)]
+ DataUrlReferrer(#[from] DataUrlReferrerError),
#[error(transparent)]
PackageResolve(#[from] PackageResolveError),
#[error(transparent)]
- PathToDeclarationUrl(#[from] PathToDeclarationUrlError),
- #[error(transparent)]
- UrlToNodeResolution(#[from] UrlToNodeResolutionError),
+ TypesNotFound(#[from] TypesNotFoundError),
#[error(transparent)]
FinalizeResolution(#[from] FinalizeResolutionError),
+ #[error(transparent)]
+ UrlToNodeResolution(#[from] UrlToNodeResolutionError),
}
kinded_err!(FinalizeResolutionError, FinalizeResolutionErrorKind);
@@ -499,6 +549,16 @@ pub enum FinalizeResolutionErrorKind {
UnsupportedDirImport(#[from] UnsupportedDirImportError),
}
+impl NodeJsErrorCoded for FinalizeResolutionError {
+ fn code(&self) -> NodeJsErrorCode {
+ match self.as_kind() {
+ FinalizeResolutionErrorKind::InvalidModuleSpecifierError(e) => e.code(),
+ FinalizeResolutionErrorKind::ModuleNotFound(e) => e.code(),
+ FinalizeResolutionErrorKind::UnsupportedDirImport(e) => e.code(),
+ }
+ }
+}
+
#[derive(Debug, Error)]
#[error(
"[{}] Cannot find {} '{}'{}",
@@ -513,9 +573,9 @@ pub struct ModuleNotFoundError {
pub typ: &'static str,
}
-impl ModuleNotFoundError {
- pub fn code(&self) -> &'static str {
- "ERR_MODULE_NOT_FOUND"
+impl NodeJsErrorCoded for ModuleNotFoundError {
+ fn code(&self) -> NodeJsErrorCode {
+ NodeJsErrorCode::ERR_MODULE_NOT_FOUND
}
}
diff --git a/ext/node/lib.rs b/ext/node/lib.rs
index 6f7185148..21af5a094 100644
--- a/ext/node/lib.rs
+++ b/ext/node/lib.rs
@@ -46,7 +46,6 @@ pub use path::PathClean;
pub use polyfill::is_builtin_node_module;
pub use polyfill::SUPPORTED_BUILTIN_NODE_MODULES;
pub use polyfill::SUPPORTED_BUILTIN_NODE_MODULES_WITH_PREFIX;
-pub use resolution::parse_npm_pkg_name;
pub use resolution::NodeModuleKind;
pub use resolution::NodeResolution;
pub use resolution::NodeResolutionMode;
diff --git a/ext/node/resolution.rs b/ext/node/resolution.rs
index 476b4f59c..6417835a2 100644
--- a/ext/node/resolution.rs
+++ b/ext/node/resolution.rs
@@ -18,14 +18,16 @@ use deno_package_json::PackageJsonRc;
use crate::errors;
use crate::errors::CanonicalizingPkgJsonDirError;
use crate::errors::ClosestPkgJsonError;
+use crate::errors::DataUrlReferrerError;
use crate::errors::FinalizeResolutionError;
use crate::errors::InvalidModuleSpecifierError;
use crate::errors::InvalidPackageTargetError;
-use crate::errors::LegacyMainResolveError;
+use crate::errors::LegacyResolveError;
use crate::errors::ModuleNotFoundError;
use crate::errors::NodeJsErrorCode;
use crate::errors::NodeJsErrorCoded;
use crate::errors::NodeResolveError;
+use crate::errors::NodeResolveRelativeJoinError;
use crate::errors::PackageExportsResolveError;
use crate::errors::PackageImportNotDefinedError;
use crate::errors::PackageImportsResolveError;
@@ -38,11 +40,12 @@ use crate::errors::PackageSubpathResolveErrorKind;
use crate::errors::PackageTargetNotFoundError;
use crate::errors::PackageTargetResolveError;
use crate::errors::PackageTargetResolveErrorKind;
-use crate::errors::PathToDeclarationUrlError;
use crate::errors::ResolveBinaryCommandsError;
use crate::errors::ResolvePkgJsonBinExportError;
use crate::errors::ResolvePkgSubpathFromDenoModuleError;
use crate::errors::TypeScriptNotSupportedInNpmError;
+use crate::errors::TypesNotFoundError;
+use crate::errors::TypesNotFoundErrorData;
use crate::errors::UnsupportedDirImportError;
use crate::errors::UnsupportedEsmUrlSchemeError;
use crate::errors::UrlToNodeResolutionError;
@@ -55,6 +58,7 @@ use crate::PathClean;
pub static DEFAULT_CONDITIONS: &[&str] = &["deno", "node", "import"];
pub static REQUIRE_CONDITIONS: &[&str] = &["require", "node"];
+static TYPES_ONLY_CONDITIONS: &[&str] = &["types"];
pub type NodeModuleKind = deno_package_json::NodeModuleKind;
@@ -177,23 +181,23 @@ impl NodeResolver {
referrer: &ModuleSpecifier,
referrer_kind: NodeModuleKind,
mode: NodeResolutionMode,
- ) -> Result<Option<NodeResolution>, NodeResolveError> {
+ ) -> Result<NodeResolution, NodeResolveError> {
// Note: if we are here, then the referrer is an esm module
// TODO(bartlomieju): skipped "policy" part as we don't plan to support it
if crate::is_builtin_node_module(specifier) {
- return Ok(Some(NodeResolution::BuiltIn(specifier.to_string())));
+ return Ok(NodeResolution::BuiltIn(specifier.to_string()));
}
if let Ok(url) = Url::parse(specifier) {
if url.scheme() == "data" {
- return Ok(Some(NodeResolution::Esm(url)));
+ return Ok(NodeResolution::Esm(url));
}
if let Some(module_name) =
get_module_name_from_builtin_node_module_specifier(&url)
{
- return Ok(Some(NodeResolution::BuiltIn(module_name.to_string())));
+ return Ok(NodeResolution::BuiltIn(module_name.to_string()));
}
let protocol = url.scheme();
@@ -209,14 +213,14 @@ impl NodeResolver {
// todo(dsherret): this seems wrong
if referrer.scheme() == "data" {
- let url = referrer.join(specifier).map_err(|source| {
- NodeResolveError::DataUrlReferrerFailed { source }
- })?;
- return Ok(Some(NodeResolution::Esm(url)));
+ let url = referrer
+ .join(specifier)
+ .map_err(|source| DataUrlReferrerError { source })?;
+ return Ok(NodeResolution::Esm(url));
}
}
- let maybe_url = self.module_resolve(
+ let url = self.module_resolve(
specifier,
referrer,
referrer_kind,
@@ -226,15 +230,19 @@ impl NodeResolver {
},
mode,
)?;
- let url = match maybe_url {
- Some(url) => url,
- None => return Ok(None),
+
+ let url = if mode.is_types() {
+ let file_path = to_file_path(&url);
+ self.path_to_declaration_url(&file_path, Some(referrer), referrer_kind)?
+ } else {
+ url
};
+ let url = self.finalize_resolution(url, Some(referrer))?;
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))
+ Ok(resolve_response)
}
fn module_resolve(
@@ -244,12 +252,10 @@ impl NodeResolver {
referrer_kind: NodeModuleKind,
conditions: &[&str],
mode: NodeResolutionMode,
- ) -> Result<Option<ModuleSpecifier>, NodeResolveError> {
- // note: if we're here, the referrer is an esm module
- let maybe_url = if should_be_treated_as_relative_or_absolute_path(specifier)
- {
- Some(referrer.join(specifier).map_err(|err| {
- NodeResolveError::RelativeJoinError {
+ ) -> Result<ModuleSpecifier, NodeResolveError> {
+ if should_be_treated_as_relative_or_absolute_path(specifier) {
+ Ok(referrer.join(specifier).map_err(|err| {
+ NodeResolveRelativeJoinError {
path: specifier.to_string(),
base: referrer.clone(),
source: err,
@@ -260,7 +266,7 @@ impl NodeResolver {
.get_closest_package_json(referrer)
.map_err(PackageImportsResolveErrorKind::ClosestPkgJson)
.map_err(|err| PackageImportsResolveError(Box::new(err)))?;
- Some(self.package_imports_resolve(
+ Ok(self.package_imports_resolve(
specifier,
Some(referrer),
referrer_kind,
@@ -269,32 +275,16 @@ impl NodeResolver {
mode,
)?)
} else if let Ok(resolved) = Url::parse(specifier) {
- Some(resolved)
+ Ok(resolved)
} else {
- self.package_resolve(
+ Ok(self.package_resolve(
specifier,
referrer,
referrer_kind,
conditions,
mode,
- )?
- };
-
- let Some(url) = maybe_url else {
- return Ok(None);
- };
-
- let maybe_url = if mode.is_types() {
- let file_path = to_file_path(&url);
- self.path_to_declaration_url(&file_path, Some(referrer), referrer_kind)?
- } else {
- Some(url)
- };
-
- Ok(match maybe_url {
- Some(url) => Some(self.finalize_resolution(url, Some(referrer))?),
- None => None,
- })
+ )?)
+ }
}
fn finalize_resolution(
@@ -369,12 +359,12 @@ impl NodeResolver {
package_subpath: Option<&str>,
maybe_referrer: Option<&ModuleSpecifier>,
mode: NodeResolutionMode,
- ) -> Result<Option<NodeResolution>, ResolvePkgSubpathFromDenoModuleError> {
+ ) -> Result<NodeResolution, ResolvePkgSubpathFromDenoModuleError> {
let node_module_kind = NodeModuleKind::Esm;
let package_subpath = package_subpath
.map(|s| format!("./{s}"))
.unwrap_or_else(|| ".".to_string());
- let maybe_resolved_url = self.resolve_package_dir_subpath(
+ let resolved_url = self.resolve_package_dir_subpath(
package_dir,
&package_subpath,
maybe_referrer,
@@ -382,14 +372,10 @@ impl NodeResolver {
DEFAULT_CONDITIONS,
mode,
)?;
- let resolved_url = match maybe_resolved_url {
- Some(resolved_url) => resolved_url,
- None => return Ok(None),
- };
let resolve_response = self.url_to_node_resolution(resolved_url)?;
// TODO(bartlomieju): skipped checking errors for commonJS resolution and
// "preserveSymlinksMain"/"preserveSymlinks" options.
- Ok(Some(resolve_response))
+ Ok(resolve_response)
}
pub fn resolve_binary_commands(
@@ -475,7 +461,7 @@ impl NodeResolver {
path: &Path,
maybe_referrer: Option<&ModuleSpecifier>,
referrer_kind: NodeModuleKind,
- ) -> Result<Option<ModuleSpecifier>, PathToDeclarationUrlError> {
+ ) -> Result<ModuleSpecifier, TypesNotFoundError> {
fn probe_extensions(
fs: &dyn deno_fs::FileSystem,
path: &Path,
@@ -525,15 +511,15 @@ impl NodeResolver {
|| lowercase_path.ends_with(".d.cts")
|| lowercase_path.ends_with(".d.mts")
{
- return Ok(Some(to_file_specifier(path)));
+ return Ok(to_file_specifier(path));
}
if let Some(path) =
probe_extensions(&*self.fs, path, &lowercase_path, referrer_kind)
{
- return Ok(Some(to_file_specifier(&path)));
+ return Ok(to_file_specifier(&path));
}
if self.fs.is_dir_sync(path) {
- let maybe_resolution = self.resolve_package_dir_subpath(
+ let resolution_result = self.resolve_package_dir_subpath(
path,
/* sub path */ ".",
maybe_referrer,
@@ -543,9 +529,9 @@ impl NodeResolver {
NodeModuleKind::Cjs => REQUIRE_CONDITIONS,
},
NodeResolutionMode::Types,
- )?;
- if let Some(resolution) = maybe_resolution {
- return Ok(Some(resolution));
+ );
+ if let Ok(resolution) = resolution_result {
+ return Ok(resolution);
}
let index_path = path.join("index.js");
if let Some(path) = probe_extensions(
@@ -554,14 +540,17 @@ impl NodeResolver {
&index_path.to_string_lossy().to_lowercase(),
referrer_kind,
) {
- return Ok(Some(to_file_specifier(&path)));
+ return Ok(to_file_specifier(&path));
}
}
// allow resolving .css files for types resolution
if lowercase_path.ends_with(".css") {
- return Ok(Some(to_file_specifier(path)));
+ return Ok(to_file_specifier(path));
}
- Ok(None)
+ Err(TypesNotFoundError(Box::new(TypesNotFoundErrorData {
+ code_specifier: to_file_specifier(path),
+ maybe_referrer: maybe_referrer.cloned(),
+ })))
}
#[allow(clippy::too_many_arguments)]
@@ -719,22 +708,32 @@ impl NodeResolver {
conditions,
mode,
) {
- Ok(Some(url)) => Ok(url),
- Ok(None) => Err(
- PackageTargetResolveErrorKind::NotFound(
- PackageTargetNotFoundError {
- pkg_json_path: package_json_path.to_path_buf(),
- target: export_target.to_string(),
- maybe_referrer: maybe_referrer.map(ToOwned::to_owned),
- referrer_kind,
- mode,
- },
- )
- .into(),
- ),
- Err(err) => {
- Err(PackageTargetResolveErrorKind::PackageResolve(err).into())
- }
+ Ok(url) => Ok(url),
+ Err(err) => match err.code() {
+ NodeJsErrorCode::ERR_INVALID_MODULE_SPECIFIER
+ | NodeJsErrorCode::ERR_INVALID_PACKAGE_CONFIG
+ | NodeJsErrorCode::ERR_INVALID_PACKAGE_TARGET
+ | NodeJsErrorCode::ERR_PACKAGE_IMPORT_NOT_DEFINED
+ | NodeJsErrorCode::ERR_PACKAGE_PATH_NOT_EXPORTED
+ | NodeJsErrorCode::ERR_UNKNOWN_FILE_EXTENSION
+ | NodeJsErrorCode::ERR_UNSUPPORTED_DIR_IMPORT
+ | NodeJsErrorCode::ERR_UNSUPPORTED_ESM_URL_SCHEME
+ | NodeJsErrorCode::ERR_TYPES_NOT_FOUND => {
+ Err(PackageTargetResolveErrorKind::PackageResolve(err).into())
+ }
+ NodeJsErrorCode::ERR_MODULE_NOT_FOUND => Err(
+ PackageTargetResolveErrorKind::NotFound(
+ PackageTargetNotFoundError {
+ pkg_json_path: package_json_path.to_path_buf(),
+ target: export_target.to_string(),
+ maybe_referrer: maybe_referrer.map(ToOwned::to_owned),
+ referrer_kind,
+ mode,
+ },
+ )
+ .into(),
+ ),
+ },
};
return match result {
@@ -832,6 +831,62 @@ impl NodeResolver {
conditions: &[&str],
mode: NodeResolutionMode,
) -> Result<Option<ModuleSpecifier>, PackageTargetResolveError> {
+ let result = self.resolve_package_target_inner(
+ package_json_path,
+ target,
+ subpath,
+ package_subpath,
+ maybe_referrer,
+ referrer_kind,
+ pattern,
+ internal,
+ conditions,
+ mode,
+ );
+ match result {
+ Ok(maybe_resolved) => Ok(maybe_resolved),
+ Err(err) => {
+ if mode.is_types()
+ && err.code() == NodeJsErrorCode::ERR_TYPES_NOT_FOUND
+ && conditions != TYPES_ONLY_CONDITIONS
+ {
+ // try resolving with just "types" conditions for when someone misconfigures
+ // and puts the "types" condition in the wrong place
+ if let Ok(Some(resolved)) = self.resolve_package_target_inner(
+ package_json_path,
+ target,
+ subpath,
+ package_subpath,
+ maybe_referrer,
+ referrer_kind,
+ pattern,
+ internal,
+ TYPES_ONLY_CONDITIONS,
+ mode,
+ ) {
+ return Ok(Some(resolved));
+ }
+ }
+
+ Err(err)
+ }
+ }
+ }
+
+ #[allow(clippy::too_many_arguments)]
+ fn resolve_package_target_inner(
+ &self,
+ package_json_path: &Path,
+ target: &Value,
+ subpath: &str,
+ package_subpath: &str,
+ maybe_referrer: Option<&ModuleSpecifier>,
+ referrer_kind: NodeModuleKind,
+ pattern: bool,
+ internal: bool,
+ conditions: &[&str],
+ mode: NodeResolutionMode,
+ ) -> Result<Option<ModuleSpecifier>, PackageTargetResolveError> {
if let Some(target) = target.as_str() {
let url = self.resolve_package_target_string(
target,
@@ -847,11 +902,11 @@ impl NodeResolver {
)?;
if mode.is_types() && url.scheme() == "file" {
let path = url.to_file_path().unwrap();
- return Ok(self.path_to_declaration_url(
+ return Ok(Some(self.path_to_declaration_url(
&path,
maybe_referrer,
referrer_kind,
- )?);
+ )?));
} else {
return Ok(Some(url));
}
@@ -1069,41 +1124,37 @@ impl NodeResolver {
referrer_kind: NodeModuleKind,
conditions: &[&str],
mode: NodeResolutionMode,
- ) -> Result<Option<ModuleSpecifier>, PackageResolveError> {
+ ) -> Result<ModuleSpecifier, PackageResolveError> {
let (package_name, package_subpath, _is_scoped) =
parse_npm_pkg_name(specifier, referrer)?;
- let Some(package_config) = self.get_closest_package_json(referrer)? else {
- return Ok(None);
- };
- // ResolveSelf
- if package_config.name.as_ref() == Some(&package_name) {
- if let Some(exports) = &package_config.exports {
- return self
- .package_exports_resolve(
- &package_config.path,
- &package_subpath,
- exports,
- Some(referrer),
- referrer_kind,
- conditions,
- mode,
- )
- .map(Some)
- .map_err(|err| err.into());
+ if let Some(package_config) = self.get_closest_package_json(referrer)? {
+ // ResolveSelf
+ if package_config.name.as_ref() == Some(&package_name) {
+ if let Some(exports) = &package_config.exports {
+ return self
+ .package_exports_resolve(
+ &package_config.path,
+ &package_subpath,
+ exports,
+ Some(referrer),
+ referrer_kind,
+ conditions,
+ mode,
+ )
+ .map_err(|err| err.into());
+ }
}
}
- self
- .resolve_package_subpath_for_package(
- &package_name,
- &package_subpath,
- referrer,
- referrer_kind,
- conditions,
- mode,
- )
- .map_err(|err| err.into())
+ self.resolve_package_subpath_for_package(
+ &package_name,
+ &package_subpath,
+ referrer,
+ referrer_kind,
+ conditions,
+ mode,
+ )
}
#[allow(clippy::too_many_arguments)]
@@ -1115,7 +1166,7 @@ impl NodeResolver {
referrer_kind: NodeModuleKind,
conditions: &[&str],
mode: NodeResolutionMode,
- ) -> Result<Option<ModuleSpecifier>, PackageSubpathResolveError> {
+ ) -> Result<ModuleSpecifier, PackageResolveError> {
let result = self.resolve_package_subpath_for_package_inner(
package_name,
package_subpath,
@@ -1124,10 +1175,10 @@ impl NodeResolver {
conditions,
mode,
);
- if mode.is_types() && !matches!(result, Ok(Some(_))) {
+ if mode.is_types() && !matches!(result, Ok(ModuleSpecifier { .. })) {
// try to resolve with the @types package
let package_name = types_package_name(package_name);
- if let Ok(Some(result)) = self.resolve_package_subpath_for_package_inner(
+ if let Ok(result) = self.resolve_package_subpath_for_package_inner(
&package_name,
package_subpath,
referrer,
@@ -1135,7 +1186,7 @@ impl NodeResolver {
conditions,
mode,
) {
- return Ok(Some(result));
+ return Ok(result);
}
}
result
@@ -1150,7 +1201,7 @@ impl NodeResolver {
referrer_kind: NodeModuleKind,
conditions: &[&str],
mode: NodeResolutionMode,
- ) -> Result<Option<ModuleSpecifier>, PackageSubpathResolveError> {
+ ) -> Result<ModuleSpecifier, PackageResolveError> {
let package_dir_path = self
.npm_resolver
.resolve_package_folder_from_package(package_name, referrer)?;
@@ -1169,14 +1220,16 @@ impl NodeResolver {
// ))
// Package match.
- self.resolve_package_dir_subpath(
- &package_dir_path,
- package_subpath,
- Some(referrer),
- referrer_kind,
- conditions,
- mode,
- )
+ self
+ .resolve_package_dir_subpath(
+ &package_dir_path,
+ package_subpath,
+ Some(referrer),
+ referrer_kind,
+ conditions,
+ mode,
+ )
+ .map_err(|err| err.into())
}
#[allow(clippy::too_many_arguments)]
@@ -1188,7 +1241,7 @@ impl NodeResolver {
referrer_kind: NodeModuleKind,
conditions: &[&str],
mode: NodeResolutionMode,
- ) -> Result<Option<ModuleSpecifier>, PackageSubpathResolveError> {
+ ) -> Result<ModuleSpecifier, PackageSubpathResolveError> {
let package_json_path = package_dir_path.join("package.json");
match self.load_package_json(&package_json_path)? {
Some(pkg_json) => self.resolve_package_subpath(
@@ -1207,7 +1260,9 @@ impl NodeResolver {
referrer_kind,
mode,
)
- .map_err(|err| PackageSubpathResolveErrorKind::LegacyExact(err).into()),
+ .map_err(|err| {
+ PackageSubpathResolveErrorKind::LegacyResolve(err).into()
+ }),
}
}
@@ -1220,7 +1275,7 @@ impl NodeResolver {
referrer_kind: NodeModuleKind,
conditions: &[&str],
mode: NodeResolutionMode,
- ) -> Result<Option<ModuleSpecifier>, PackageSubpathResolveError> {
+ ) -> Result<ModuleSpecifier, PackageSubpathResolveError> {
if let Some(exports) = &package_json.exports {
let result = self.package_exports_resolve(
&package_json.path,
@@ -1232,13 +1287,13 @@ impl NodeResolver {
mode,
);
match result {
- Ok(found) => return Ok(Some(found)),
+ Ok(found) => return Ok(found),
Err(exports_err) => {
if mode.is_types() && package_subpath == "." {
return self
.legacy_main_resolve(package_json, referrer, referrer_kind, mode)
.map_err(|err| {
- PackageSubpathResolveErrorKind::LegacyMain(err).into()
+ PackageSubpathResolveErrorKind::LegacyResolve(err).into()
});
}
return Err(
@@ -1251,7 +1306,9 @@ impl NodeResolver {
if package_subpath == "." {
return self
.legacy_main_resolve(package_json, referrer, referrer_kind, mode)
- .map_err(|err| PackageSubpathResolveErrorKind::LegacyMain(err).into());
+ .map_err(|err| {
+ PackageSubpathResolveErrorKind::LegacyResolve(err).into()
+ });
}
self
@@ -1262,7 +1319,9 @@ impl NodeResolver {
referrer_kind,
mode,
)
- .map_err(|err| PackageSubpathResolveErrorKind::LegacyExact(err).into())
+ .map_err(|err| {
+ PackageSubpathResolveErrorKind::LegacyResolve(err.into()).into()
+ })
}
fn resolve_subpath_exact(
@@ -1272,13 +1331,13 @@ impl NodeResolver {
referrer: Option<&ModuleSpecifier>,
referrer_kind: NodeModuleKind,
mode: NodeResolutionMode,
- ) -> Result<Option<ModuleSpecifier>, PathToDeclarationUrlError> {
+ ) -> Result<ModuleSpecifier, TypesNotFoundError> {
assert_ne!(package_subpath, ".");
let file_path = directory.join(package_subpath);
if mode.is_types() {
Ok(self.path_to_declaration_url(&file_path, referrer, referrer_kind)?)
} else {
- Ok(Some(to_file_specifier(&file_path)))
+ Ok(to_file_specifier(&file_path))
}
}
@@ -1286,20 +1345,22 @@ impl NodeResolver {
&self,
directory: &Path,
package_subpath: &str,
- referrer: Option<&ModuleSpecifier>,
+ maybe_referrer: Option<&ModuleSpecifier>,
referrer_kind: NodeModuleKind,
mode: NodeResolutionMode,
- ) -> Result<Option<ModuleSpecifier>, PathToDeclarationUrlError> {
+ ) -> Result<ModuleSpecifier, LegacyResolveError> {
if package_subpath == "." {
- Ok(self.legacy_index_resolve(directory, referrer_kind, mode))
+ self.legacy_index_resolve(directory, maybe_referrer, referrer_kind, mode)
} else {
- self.resolve_subpath_exact(
- directory,
- package_subpath,
- referrer,
- referrer_kind,
- mode,
- )
+ self
+ .resolve_subpath_exact(
+ directory,
+ package_subpath,
+ maybe_referrer,
+ referrer_kind,
+ mode,
+ )
+ .map_err(|err| err.into())
}
}
@@ -1348,7 +1409,7 @@ impl NodeResolver {
maybe_referrer: Option<&ModuleSpecifier>,
referrer_kind: NodeModuleKind,
mode: NodeResolutionMode,
- ) -> Result<Option<ModuleSpecifier>, LegacyMainResolveError> {
+ ) -> Result<ModuleSpecifier, LegacyResolveError> {
let maybe_main = if mode.is_types() {
match package_json.types.as_ref() {
Some(types) => Some(types.as_str()),
@@ -1357,11 +1418,14 @@ impl NodeResolver {
// a corresponding declaration file
if let Some(main) = package_json.main(referrer_kind) {
let main = package_json.path.parent().unwrap().join(main).clean();
- let maybe_decl_url = self
- .path_to_declaration_url(&main, maybe_referrer, referrer_kind)
- .map_err(LegacyMainResolveError::PathToDeclarationUrl)?;
- if let Some(path) = maybe_decl_url {
- return Ok(Some(path));
+ let decl_url_result = self.path_to_declaration_url(
+ &main,
+ maybe_referrer,
+ referrer_kind,
+ );
+ // don't surface errors, fallback to checking the index now
+ if let Ok(url) = decl_url_result {
+ return Ok(url);
}
}
None
@@ -1374,7 +1438,7 @@ impl NodeResolver {
if let Some(main) = maybe_main {
let guess = package_json.path.parent().unwrap().join(main).clean();
if self.fs.is_file_sync(&guess) {
- return Ok(Some(to_file_specifier(&guess)));
+ return Ok(to_file_specifier(&guess));
}
// todo(dsherret): investigate exactly how node and typescript handles this
@@ -1404,24 +1468,26 @@ impl NodeResolver {
.clean();
if self.fs.is_file_sync(&guess) {
// TODO(bartlomieju): emitLegacyIndexDeprecation()
- return Ok(Some(to_file_specifier(&guess)));
+ return Ok(to_file_specifier(&guess));
}
}
}
- Ok(self.legacy_index_resolve(
+ self.legacy_index_resolve(
package_json.path.parent().unwrap(),
+ maybe_referrer,
referrer_kind,
mode,
- ))
+ )
}
fn legacy_index_resolve(
&self,
directory: &Path,
+ maybe_referrer: Option<&ModuleSpecifier>,
referrer_kind: NodeModuleKind,
mode: NodeResolutionMode,
- ) -> Option<ModuleSpecifier> {
+ ) -> Result<ModuleSpecifier, LegacyResolveError> {
let index_file_names = if mode.is_types() {
// todo(dsherret): investigate exactly how typescript does this
match referrer_kind {
@@ -1435,11 +1501,28 @@ impl NodeResolver {
let guess = directory.join(index_file_name).clean();
if self.fs.is_file_sync(&guess) {
// TODO(bartlomieju): emitLegacyIndexDeprecation()
- return Some(to_file_specifier(&guess));
+ return Ok(to_file_specifier(&guess));
}
}
- None
+ if mode.is_types() {
+ Err(
+ TypesNotFoundError(Box::new(TypesNotFoundErrorData {
+ code_specifier: to_file_specifier(&directory.join("index.js")),
+ maybe_referrer: maybe_referrer.cloned(),
+ }))
+ .into(),
+ )
+ } else {
+ Err(
+ ModuleNotFoundError {
+ specifier: to_file_specifier(&directory.join("index.js")),
+ typ: "module",
+ maybe_referrer: maybe_referrer.cloned(),
+ }
+ .into(),
+ )
+ }
}
}
@@ -1557,7 +1640,7 @@ fn should_be_treated_as_relative_or_absolute_path(specifier: &str) -> bool {
// TODO(ry) We very likely have this utility function elsewhere in Deno.
fn is_relative_specifier(specifier: &str) -> bool {
let specifier_len = specifier.len();
- let specifier_chars: Vec<_> = specifier.chars().collect();
+ let specifier_chars: Vec<_> = specifier.chars().take(3).collect();
if !specifier_chars.is_empty() && specifier_chars[0] == '.' {
if specifier_len == 1 || specifier_chars[1] == '/' {
diff --git a/tests/integration/npm_tests.rs b/tests/integration/npm_tests.rs
index dba519087..e721633a6 100644
--- a/tests/integration/npm_tests.rs
+++ b/tests/integration/npm_tests.rs
@@ -15,13 +15,6 @@ use util::TestContextBuilder;
// NOTE: See how to make test npm packages at ./testdata/npm/README.md
-itest!(esm_import_cjs_default {
- args: "run --allow-read --allow-env --quiet --check=all npm/esm_import_cjs_default/main.ts",
- output: "npm/esm_import_cjs_default/main.out",
- envs: env_vars_for_npm_tests(),
- http_server: true,
-});
-
itest!(cjs_with_deps {
args: "run --allow-read --allow-env npm/cjs_with_deps/main.js",
output: "npm/cjs_with_deps/main.out",
@@ -324,14 +317,6 @@ itest!(check_local {
exit_code: 1,
});
-itest!(types_general {
- args: "check --quiet npm/types/main.ts",
- output: "npm/types/main.out",
- envs: env_vars_for_npm_tests(),
- http_server: true,
- exit_code: 1,
-});
-
itest!(types_ambient_module {
args: "check --quiet npm/types_ambient_module/main.ts",
output: "npm/types_ambient_module/main.out",
@@ -341,27 +326,11 @@ itest!(types_ambient_module {
});
itest!(types_ambient_module_import_map {
- args: "check --quiet --import-map=npm/types_ambient_module/import_map.json npm/types_ambient_module/main_import_map.ts",
- output: "npm/types_ambient_module/main_import_map.out",
- envs: env_vars_for_npm_tests(),
- http_server: true,
- exit_code: 1,
- });
-
-itest!(no_types_cjs {
- args: "check --quiet npm/no_types_cjs/main.ts",
- output_str: Some(""),
- exit_code: 0,
- envs: env_vars_for_npm_tests(),
- http_server: true,
-});
-
-itest!(no_types_in_conditional_exports {
- args: "run --check npm/no_types_in_conditional_exports/main.ts",
- output: "npm/no_types_in_conditional_exports/main.out",
- exit_code: 0,
+ args: "check --quiet --import-map=npm/types_ambient_module/import_map.json npm/types_ambient_module/main_import_map.ts",
+ output: "npm/types_ambient_module/main_import_map.out",
envs: env_vars_for_npm_tests(),
http_server: true,
+ exit_code: 1,
});
itest!(types_entry_value_not_exists {
diff --git a/tests/specs/node/byonm_phantom_dep_res_failure/__test__.jsonc b/tests/specs/node/byonm_phantom_dep_res_failure/__test__.jsonc
new file mode 100644
index 000000000..35e0a7686
--- /dev/null
+++ b/tests/specs/node/byonm_phantom_dep_res_failure/__test__.jsonc
@@ -0,0 +1,13 @@
+{
+ "tests": {
+ "bad_import": {
+ "args": "run bad_import.ts",
+ "output": "bad_import.out",
+ "exitCode": 1
+ },
+ "good_import": {
+ "args": "run good_import.ts",
+ "output": "good_import.out"
+ }
+ }
+}
diff --git a/tests/specs/node/byonm_phantom_dep_res_failure/bad_import.out b/tests/specs/node/byonm_phantom_dep_res_failure/bad_import.out
new file mode 100644
index 000000000..a524720e3
--- /dev/null
+++ b/tests/specs/node/byonm_phantom_dep_res_failure/bad_import.out
@@ -0,0 +1,2 @@
+error: [ERR_MODULE_NOT_FOUND] Cannot find module 'file:///[WILDLINE]/node_modules/package/index.js' imported from 'file:///[WILDLINE]/bad_import.ts'
+ at file:///[WILDLINE]/bad_import.ts:1:16
diff --git a/tests/specs/node/byonm_phantom_dep_res_failure/bad_import.ts b/tests/specs/node/byonm_phantom_dep_res_failure/bad_import.ts
new file mode 100644
index 000000000..e20fe1fcf
--- /dev/null
+++ b/tests/specs/node/byonm_phantom_dep_res_failure/bad_import.ts
@@ -0,0 +1,3 @@
+import hi from "package";
+
+hi();
diff --git a/tests/specs/node/byonm_phantom_dep_res_failure/deno.json b/tests/specs/node/byonm_phantom_dep_res_failure/deno.json
new file mode 100644
index 000000000..6134d86d1
--- /dev/null
+++ b/tests/specs/node/byonm_phantom_dep_res_failure/deno.json
@@ -0,0 +1,3 @@
+{
+ "unstable": ["byonm"]
+}
diff --git a/tests/specs/node/byonm_phantom_dep_res_failure/good_import.out b/tests/specs/node/byonm_phantom_dep_res_failure/good_import.out
new file mode 100644
index 000000000..45b983be3
--- /dev/null
+++ b/tests/specs/node/byonm_phantom_dep_res_failure/good_import.out
@@ -0,0 +1 @@
+hi
diff --git a/tests/specs/node/byonm_phantom_dep_res_failure/good_import.ts b/tests/specs/node/byonm_phantom_dep_res_failure/good_import.ts
new file mode 100644
index 000000000..2b17d3e33
--- /dev/null
+++ b/tests/specs/node/byonm_phantom_dep_res_failure/good_import.ts
@@ -0,0 +1,3 @@
+import hi from "package/main.js";
+
+hi();
diff --git a/tests/specs/node/byonm_phantom_dep_res_failure/node_modules/package/main.js b/tests/specs/node/byonm_phantom_dep_res_failure/node_modules/package/main.js
new file mode 100644
index 000000000..bc76b8e9e
--- /dev/null
+++ b/tests/specs/node/byonm_phantom_dep_res_failure/node_modules/package/main.js
@@ -0,0 +1 @@
+module.exports = () => console.log('hi'); \ No newline at end of file
diff --git a/tests/specs/node/byonm_phantom_dep_res_failure/node_modules/package/package.json b/tests/specs/node/byonm_phantom_dep_res_failure/node_modules/package/package.json
new file mode 100644
index 000000000..5723987e9
--- /dev/null
+++ b/tests/specs/node/byonm_phantom_dep_res_failure/node_modules/package/package.json
@@ -0,0 +1,4 @@
+{
+ "name": "package",
+ "version": "1.0.0"
+} \ No newline at end of file
diff --git a/tests/specs/node/byonm_phantom_dep_res_failure/package.json b/tests/specs/node/byonm_phantom_dep_res_failure/package.json
new file mode 100644
index 000000000..2c63c0851
--- /dev/null
+++ b/tests/specs/node/byonm_phantom_dep_res_failure/package.json
@@ -0,0 +1,2 @@
+{
+}
diff --git a/tests/specs/npm/esm_import_cjs_default/__test__.jsonc b/tests/specs/npm/esm_import_cjs_default/__test__.jsonc
new file mode 100644
index 000000000..b2a25914f
--- /dev/null
+++ b/tests/specs/npm/esm_import_cjs_default/__test__.jsonc
@@ -0,0 +1,4 @@
+{
+ "args": "run --allow-read --allow-env --check=all main.ts",
+ "output": "main.out"
+}
diff --git a/tests/testdata/npm/esm_import_cjs_default/main.out b/tests/specs/npm/esm_import_cjs_default/main.out
index 0f6a61e34..ec7962e5a 100644
--- a/tests/testdata/npm/esm_import_cjs_default/main.out
+++ b/tests/specs/npm/esm_import_cjs_default/main.out
@@ -1,3 +1,10 @@
+[UNORDERED_START]
+Download http://localhost:4260/@denotest/esm-import-cjs-default
+Download http://localhost:4260/@denotest/cjs-default-export
+Download http://localhost:4260/@denotest/cjs-default-export/1.0.0.tgz
+Download http://localhost:4260/@denotest/esm-import-cjs-default/1.0.0.tgz
+[UNORDERED_END]
+Check file:///[WILDLINE]/main.ts
Node esm importing node cjs
===========================
{
diff --git a/tests/testdata/npm/esm_import_cjs_default/main.ts b/tests/specs/npm/esm_import_cjs_default/main.ts
index f9c3280e5..f9c3280e5 100644
--- a/tests/testdata/npm/esm_import_cjs_default/main.ts
+++ b/tests/specs/npm/esm_import_cjs_default/main.ts
diff --git a/tests/specs/npm/no_types_cjs/__test__.jsonc b/tests/specs/npm/no_types_cjs/__test__.jsonc
new file mode 100644
index 000000000..de0339cfb
--- /dev/null
+++ b/tests/specs/npm/no_types_cjs/__test__.jsonc
@@ -0,0 +1,4 @@
+{
+ "args": "check main.ts",
+ "output": "main.out"
+}
diff --git a/tests/specs/npm/no_types_cjs/main.out b/tests/specs/npm/no_types_cjs/main.out
new file mode 100644
index 000000000..4747a9a32
--- /dev/null
+++ b/tests/specs/npm/no_types_cjs/main.out
@@ -0,0 +1,3 @@
+Download http://localhost:4260/@denotest/no-types-cjs
+Download http://localhost:4260/@denotest/no-types-cjs/1.0.0.tgz
+Check file:///[WILDLINE]/no_types_cjs/main.ts
diff --git a/tests/testdata/npm/no_types_cjs/main.ts b/tests/specs/npm/no_types_cjs/main.ts
index 32458e839..32458e839 100644
--- a/tests/testdata/npm/no_types_cjs/main.ts
+++ b/tests/specs/npm/no_types_cjs/main.ts
diff --git a/tests/specs/npm/no_types_in_conditional_exports/__test__.jsonc b/tests/specs/npm/no_types_in_conditional_exports/__test__.jsonc
new file mode 100644
index 000000000..8955fcda2
--- /dev/null
+++ b/tests/specs/npm/no_types_in_conditional_exports/__test__.jsonc
@@ -0,0 +1,4 @@
+{
+ "args": "run --check main.ts",
+ "output": "main.out"
+}
diff --git a/tests/testdata/npm/no_types_in_conditional_exports/main.out b/tests/specs/npm/no_types_in_conditional_exports/main.out
index 46c583234..46c583234 100644
--- a/tests/testdata/npm/no_types_in_conditional_exports/main.out
+++ b/tests/specs/npm/no_types_in_conditional_exports/main.out
diff --git a/tests/testdata/npm/no_types_in_conditional_exports/main.ts b/tests/specs/npm/no_types_in_conditional_exports/main.ts
index 7ec2f18fd..7ec2f18fd 100644
--- a/tests/testdata/npm/no_types_in_conditional_exports/main.ts
+++ b/tests/specs/npm/no_types_in_conditional_exports/main.ts
diff --git a/tests/specs/npm/types_general/__test__.jsonc b/tests/specs/npm/types_general/__test__.jsonc
new file mode 100644
index 000000000..a991c6eed
--- /dev/null
+++ b/tests/specs/npm/types_general/__test__.jsonc
@@ -0,0 +1,5 @@
+{
+ "args": "check main.ts",
+ "output": "main.out",
+ "exitCode": 1
+}
diff --git a/tests/testdata/npm/types/main.out b/tests/specs/npm/types_general/main.out
index de1f2c145..ffba4f84d 100644
--- a/tests/testdata/npm/types/main.out
+++ b/tests/specs/npm/types_general/main.out
@@ -1,7 +1,16 @@
+[UNORDERED_START]
+Download http://localhost:4260/@denotest/types
+Download http://localhost:4260/@denotest/types_imported
+Download http://localhost:4260/@denotest/types-exports-subpaths
+Download http://localhost:4260/@denotest/types_imported/1.0.0.tgz
+Download http://localhost:4260/@denotest/types-exports-subpaths/1.0.0.tgz
+Download http://localhost:4260/@denotest/types/1.0.0.tgz
+[UNORDERED_END]
+Check file:///[WILDLINE]/main.ts
error: TS2322 [ERROR]: Type 'number' is not assignable to type 'string'.
bar: 1,
~~~
- at [WILDCARD]/npm/types/main.ts:[WILDCARD]
+ at [WILDCARD]/main.ts:[WILDCARD]
The expected type comes from property 'bar' which is declared here on type 'Foobar'
bar: string;
@@ -11,7 +20,7 @@ error: TS2322 [ERROR]: Type 'number' is not assignable to type 'string'.
TS2322 [ERROR]: Type 'number' is not assignable to type 'string'.
prop: 1,
~~~~
- at [WILDCARD]/npm/types/main.ts:[WILDCARD]
+ at [WILDCARD]/main.ts:[WILDCARD]
The expected type comes from property 'prop' which is declared here on type 'SomeInterface'
prop: string;
@@ -21,7 +30,7 @@ TS2322 [ERROR]: Type 'number' is not assignable to type 'string'.
TS2322 [ERROR]: Type 'string' is not assignable to type 'number'.
prop2: "asdf",
~~~~~
- at [WILDCARD]/npm/types/main.ts:[WILDCARD]
+ at [WILDCARD]/main.ts:[WILDCARD]
The expected type comes from property 'prop2' which is declared here on type 'SomeInterface'
prop2: number;
@@ -31,7 +40,7 @@ TS2322 [ERROR]: Type 'string' is not assignable to type 'number'.
TS2322 [ERROR]: Type 'number' is not assignable to type 'string'.
fizz: 1,
~~~~
- at [WILDCARD]/npm/types/main.ts:[WILDCARD]
+ at [WILDCARD]/main.ts:[WILDCARD]
The expected type comes from property 'fizz' which is declared here on type 'Fizzbuzz'
fizz: string;
@@ -41,7 +50,7 @@ TS2322 [ERROR]: Type 'number' is not assignable to type 'string'.
TS2322 [ERROR]: Type 'number' is not assignable to type 'string'.
buzz: 2,
~~~~
- at [WILDCARD]/npm/types/main.ts:[WILDCARD]
+ at [WILDCARD]/main.ts:[WILDCARD]
The expected type comes from property 'buzz' which is declared here on type 'Fizzbuzz'
buzz: string;
@@ -51,21 +60,21 @@ TS2322 [ERROR]: Type 'number' is not assignable to type 'string'.
TS2322 [ERROR]: Type '5' is not assignable to type '"test1"'.
const valueA: "test1" = getClient();
~~~~~~
- at [WILDCARD]/npm/types/main.ts:[WILDCARD]
+ at [WILDCARD]/main.ts:[WILDCARD]
TS2322 [ERROR]: Type '"import"' is not assignable to type '"test2"'.
const valueB: "test2" = entryImport();
~~~~~~
- at [WILDCARD]/types/main.ts:[WILDCARD]
+ at [WILDCARD]/main.ts:[WILDCARD]
TS2322 [ERROR]: Type '12' is not assignable to type '"test3"'.
const valueC: "test3" = entryA();
~~~~~~
- at [WILDCARD]/types/main.ts:[WILDCARD]
+ at [WILDCARD]/main.ts:[WILDCARD]
TS2322 [ERROR]: Type '"types"' is not assignable to type '"test4"'.
const valueD: "test4" = entryTypes();
~~~~~~
- at file:///[WILDCARD]/types/main.ts:[WILDCARD]
+ at file:///[WILDCARD]/main.ts:[WILDCARD]
Found 9 errors.
diff --git a/tests/testdata/npm/types/main.ts b/tests/specs/npm/types_general/main.ts
index ae420f6d6..ae420f6d6 100644
--- a/tests/testdata/npm/types/main.ts
+++ b/tests/specs/npm/types_general/main.ts
diff --git a/tools/lint.js b/tools/lint.js
index aeab48c1a..dad963160 100755
--- a/tools/lint.js
+++ b/tools/lint.js
@@ -218,7 +218,7 @@ async function ensureNoNewITests() {
"lsp_tests.rs": 0,
"node_compat_tests.rs": 4,
"node_unit_tests.rs": 2,
- "npm_tests.rs": 97,
+ "npm_tests.rs": 93,
"pm_tests.rs": 0,
"publish_tests.rs": 0,
"repl_tests.rs": 0,