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 GitHub
parent 273ec9fbf2
commit 9e0855f160
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

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,11 +1030,9 @@ 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 target = package_exports.get(package_subpath).unwrap();
let resolved = self.resolve_package_target( let resolved = self.resolve_package_target(
package_json_path, package_json_path,
target, target,
@ -1062,14 +1058,19 @@ impl<
), ),
}; };
} }
}
let mut best_match = ""; let mut best_match = "";
let mut best_match_subpath = None; let mut best_match_data = None;
for key in package_exports.keys() { for (key, target) in package_exports {
let pattern_index = key.find('*'); let Some(pattern_index) = key.find('*') else {
if let Some(pattern_index) = pattern_index { continue;
};
let key_sub = &key[0..pattern_index]; let key_sub = &key[0..pattern_index];
if package_subpath.starts_with(key_sub) { if !package_subpath.starts_with(key_sub) {
continue;
}
// When this reaches EOL, this can throw at the top of the whole function: // When this reaches EOL, this can throw at the top of the whole function:
// //
// if (StringPrototypeEndsWith(packageSubpath, '/')) // if (StringPrototypeEndsWith(packageSubpath, '/'))
@ -1087,22 +1088,19 @@ impl<
&& key.rfind('*') == Some(pattern_index) && key.rfind('*') == Some(pattern_index)
{ {
best_match = key; best_match = key;
best_match_subpath = Some( best_match_data = Some((
package_subpath[pattern_index target,
..(package_subpath.len() - pattern_trailer.len())] &package_subpath
.to_string(), [pattern_index..(package_subpath.len() - pattern_trailer.len())],
); ));
}
}
} }
} }
if !best_match.is_empty() { if let Some((target, subpath)) = best_match_data {
let target = package_exports.get(best_match).unwrap();
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
) )
); );