0
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2025-02-08 07:16:56 -05:00

refactor(node_resolver): remove some allocations and lookups (#27799)

This commit is contained in:
David Sherret 2025-01-23 21:20:45 -05:00 committed by Bartek Iwańczuk
parent a63f614ba1
commit 5333339deb
No known key found for this signature in database
GPG key ID: 0C6BCDDC3B3AD750

View file

@ -971,7 +971,7 @@ impl<
} }
return Err(last_error.unwrap()); return Err(last_error.unwrap());
} else if let Some(target_obj) = target.as_object() { } else if let Some(target_obj) = target.as_object() {
for key in target_obj.keys() { for (key, condition_target) in target_obj {
// TODO(bartlomieju): verify that keys are not numeric // TODO(bartlomieju): verify that keys are not numeric
// return Err(errors::err_invalid_package_config( // return Err(errors::err_invalid_package_config(
// to_file_path_string(package_json_url), // to_file_path_string(package_json_url),
@ -983,8 +983,6 @@ impl<
|| conditions.contains(&key.as_str()) || conditions.contains(&key.as_str())
|| resolution_kind.is_types() && key.as_str() == "types" || resolution_kind.is_types() && key.as_str() == "types"
{ {
let condition_target = target_obj.get(key).unwrap();
let resolved = self.resolve_package_target( let resolved = self.resolve_package_target(
package_json_path, package_json_path,
condition_target, condition_target,
@ -1032,77 +1030,77 @@ impl<
conditions: &[&str], conditions: &[&str],
resolution_kind: NodeResolutionKind, resolution_kind: NodeResolutionKind,
) -> Result<Url, PackageExportsResolveError> { ) -> Result<Url, PackageExportsResolveError> {
if package_exports.contains_key(package_subpath) if let Some(target) = package_exports.get(package_subpath) {
&& package_subpath.find('*').is_none() if package_subpath.find('*').is_none() && !package_subpath.ends_with('/')
&& !package_subpath.ends_with('/') {
{ let resolved = self.resolve_package_target(
let target = package_exports.get(package_subpath).unwrap(); package_json_path,
let resolved = self.resolve_package_target( target,
package_json_path, "",
target, package_subpath,
"", maybe_referrer,
package_subpath, resolution_mode,
maybe_referrer, false,
resolution_mode, false,
false, conditions,
false, resolution_kind,
conditions, )?;
resolution_kind, return match resolved {
)?; Some(resolved) => Ok(resolved),
return match resolved { None => Err(
Some(resolved) => Ok(resolved), PackagePathNotExportedError {
None => Err( pkg_json_path: package_json_path.to_path_buf(),
PackagePathNotExportedError { subpath: package_subpath.to_string(),
pkg_json_path: package_json_path.to_path_buf(), maybe_referrer: maybe_referrer.map(ToOwned::to_owned),
subpath: package_subpath.to_string(), resolution_kind,
maybe_referrer: maybe_referrer.map(ToOwned::to_owned), }
resolution_kind, .into(),
} ),
.into(), };
),
};
}
let mut best_match = "";
let mut best_match_subpath = None;
for key in package_exports.keys() {
let pattern_index = key.find('*');
if let Some(pattern_index) = pattern_index {
let key_sub = &key[0..pattern_index];
if package_subpath.starts_with(key_sub) {
// When this reaches EOL, this can throw at the top of the whole function:
//
// if (StringPrototypeEndsWith(packageSubpath, '/'))
// throwInvalidSubpath(packageSubpath)
//
// To match "imports" and the spec.
if package_subpath.ends_with('/') {
// TODO(bartlomieju):
// emitTrailingSlashPatternDeprecation();
}
let pattern_trailer = &key[pattern_index + 1..];
if package_subpath.len() >= key.len()
&& package_subpath.ends_with(&pattern_trailer)
&& pattern_key_compare(best_match, key) == 1
&& key.rfind('*') == Some(pattern_index)
{
best_match = key;
best_match_subpath = Some(
package_subpath[pattern_index
..(package_subpath.len() - pattern_trailer.len())]
.to_string(),
);
}
}
} }
} }
if !best_match.is_empty() { let mut best_match = "";
let target = package_exports.get(best_match).unwrap(); let mut best_match_data = None;
for (key, target) in package_exports {
let Some(pattern_index) = key.find('*') else {
continue;
};
let key_sub = &key[0..pattern_index];
if !package_subpath.starts_with(key_sub) {
continue;
}
// When this reaches EOL, this can throw at the top of the whole function:
//
// if (StringPrototypeEndsWith(packageSubpath, '/'))
// throwInvalidSubpath(packageSubpath)
//
// To match "imports" and the spec.
if package_subpath.ends_with('/') {
// TODO(bartlomieju):
// emitTrailingSlashPatternDeprecation();
}
let pattern_trailer = &key[pattern_index + 1..];
if package_subpath.len() >= key.len()
&& package_subpath.ends_with(&pattern_trailer)
&& pattern_key_compare(best_match, key) == 1
&& key.rfind('*') == Some(pattern_index)
{
best_match = key;
best_match_data = Some((
target,
&package_subpath
[pattern_index..(package_subpath.len() - pattern_trailer.len())],
));
}
}
if let Some((target, subpath)) = best_match_data {
let maybe_resolved = self.resolve_package_target( let maybe_resolved = self.resolve_package_target(
package_json_path, package_json_path,
target, target,
&best_match_subpath.unwrap(), subpath,
best_match, best_match,
maybe_referrer, maybe_referrer,
resolution_mode, resolution_mode,
@ -1152,7 +1150,7 @@ impl<
self.pkg_json_resolver.get_closest_package_json(referrer)? self.pkg_json_resolver.get_closest_package_json(referrer)?
{ {
// ResolveSelf // ResolveSelf
if package_config.name.as_ref() == Some(&package_name) { if package_config.name.as_deref() == Some(package_name) {
if let Some(exports) = &package_config.exports { if let Some(exports) = &package_config.exports {
return self return self
.package_exports_resolve( .package_exports_resolve(
@ -1170,7 +1168,7 @@ impl<
} }
self.resolve_package_subpath_for_package( self.resolve_package_subpath_for_package(
&package_name, package_name,
&package_subpath, &package_subpath,
referrer, referrer,
resolution_mode, resolution_mode,
@ -1760,10 +1758,10 @@ fn throw_invalid_subpath(
} }
} }
pub fn parse_npm_pkg_name( pub fn parse_npm_pkg_name<'a>(
specifier: &str, specifier: &'a str,
referrer: &Url, referrer: &Url,
) -> Result<(String, String, bool), InvalidModuleSpecifierError> { ) -> Result<(&'a str, Cow<'static, str>, bool), InvalidModuleSpecifierError> {
let mut separator_index = specifier.find('/'); let mut separator_index = specifier.find('/');
let mut valid_package_name = true; let mut valid_package_name = true;
let mut is_scoped = false; let mut is_scoped = false;
@ -1780,10 +1778,11 @@ pub fn parse_npm_pkg_name(
} }
} }
let package_name = if let Some(index) = separator_index { let (package_name, subpath) = if let Some(index) = separator_index {
specifier[0..index].to_string() let (package_name, subpath) = specifier.split_at(index);
(package_name, Cow::Owned(format!(".{}", subpath)))
} else { } else {
specifier.to_string() (specifier, Cow::Borrowed("."))
}; };
// Package name cannot have leading . and cannot have percent-encoding or separators. // Package name cannot have leading . and cannot have percent-encoding or separators.
@ -1802,13 +1801,7 @@ pub fn parse_npm_pkg_name(
}); });
} }
let package_subpath = if let Some(index) = separator_index { Ok((package_name, subpath, is_scoped))
format!(".{}", specifier.chars().skip(index).collect::<String>())
} else {
".".to_string()
};
Ok((package_name, package_subpath, is_scoped))
} }
/// Resolves a specifier that is pointing into a node_modules folder. /// Resolves a specifier that is pointing into a node_modules folder.
@ -2055,18 +2048,18 @@ mod tests {
assert_eq!( assert_eq!(
parse_npm_pkg_name("fetch-blob", &dummy_referrer).unwrap(), parse_npm_pkg_name("fetch-blob", &dummy_referrer).unwrap(),
("fetch-blob".to_string(), ".".to_string(), false) ("fetch-blob", Cow::Borrowed("."), false)
); );
assert_eq!( assert_eq!(
parse_npm_pkg_name("@vue/plugin-vue", &dummy_referrer).unwrap(), parse_npm_pkg_name("@vue/plugin-vue", &dummy_referrer).unwrap(),
("@vue/plugin-vue".to_string(), ".".to_string(), true) ("@vue/plugin-vue", Cow::Borrowed("."), true)
); );
assert_eq!( assert_eq!(
parse_npm_pkg_name("@astrojs/prism/dist/highlighter", &dummy_referrer) parse_npm_pkg_name("@astrojs/prism/dist/highlighter", &dummy_referrer)
.unwrap(), .unwrap(),
( (
"@astrojs/prism".to_string(), "@astrojs/prism",
"./dist/highlighter".to_string(), Cow::Owned("./dist/highlighter".to_string()),
true true
) )
); );