diff --git a/src/lib.rs b/src/lib.rs index 27e324e1..4362dd82 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -515,7 +515,7 @@ impl ResolverGeneric { cached_path.package_json(&self.cache.fs, &self.options, ctx)? { // b. If "main" is a falsy value, GOTO 2. - for main_field in &package_json.main_fields { + for main_field in package_json.main_fields(&self.options.main_fields) { // c. let M = X + (json main field) let main_field_path = cached_path.path().normalize_with(main_field); // d. LOAD_AS_FILE(M) @@ -1149,7 +1149,7 @@ impl ResolverGeneric { // 6. Otherwise, if packageSubpath is equal to ".", then if subpath == "." { // 1. If pjson.main is a string, then - for main_field in &package_json.main_fields { + for main_field in package_json.main_fields(&self.options.main_fields) { // 1. Return the URL resolution of main in packageURL. let path = cached_path.path().normalize_with(main_field); let cached_path = self.cache.value(&path); diff --git a/src/package_json.rs b/src/package_json.rs index 357e6982..d4e075b9 100644 --- a/src/package_json.rs +++ b/src/package_json.rs @@ -18,8 +18,7 @@ pub struct PackageJson { /// Realpath to `package.json`. Contains the `package.json` filename. pub realpath: PathBuf, - #[cfg(feature = "package_json_raw_json_api")] - pub(crate) raw_json: std::sync::Arc, + raw_json: std::sync::Arc, /// The "name" field defines your package's name. /// The "name" field can be used in addition to the "exports" field to self-reference a package using its name. @@ -27,14 +26,6 @@ pub struct PackageJson { /// pub name: Option, - /// The "main" field defines the entry point of a package when imported by name via a node_modules lookup. Its value is a path. - /// When a package has an "exports" field, this will take precedence over the "main" field when importing the package by name. - /// - /// Values are dynamically added from [ResolveOptions::main_fields]. - /// - /// - pub main_fields: Vec, - /// The "exports" field allows defining the entry points of a package when imported by name loaded either via a node_modules lookup or a self-reference to its own name. /// /// @@ -64,7 +55,6 @@ impl PackageJson { let mut raw_json: Value = serde_json::from_str(json)?; let mut package_json = Self::default(); - package_json.main_fields.reserve_exact(options.main_fields.len()); package_json.exports.reserve_exact(options.exports_fields.len()); package_json.browser_fields.reserve_exact(options.alias_fields.len()); @@ -92,15 +82,6 @@ impl PackageJson { .transpose()? .map(Box::new); - // Dynamically create `main_fields`. - for main_field_key in &options.main_fields { - // Using `get` + `clone` instead of remove here - // because `main_fields` may contain `browser`, which is also used in `browser_fields. - if let Some(serde_json::Value::String(value)) = json_object.get(main_field_key) { - package_json.main_fields.push(value.clone()); - } - } - // Dynamically create `browser_fields`. let dir = path.parent().unwrap(); for object_path in &options.alias_fields { @@ -138,10 +119,7 @@ impl PackageJson { package_json.path = path; package_json.realpath = realpath; - #[cfg(feature = "package_json_raw_json_api")] - { - package_json.raw_json = std::sync::Arc::new(raw_json); - } + package_json.raw_json = std::sync::Arc::new(raw_json); Ok(package_json) } @@ -189,6 +167,23 @@ impl PackageJson { self.realpath.parent().unwrap() } + /// The "main" field defines the entry point of a package when imported by name via a node_modules lookup. Its value is a path. + /// + /// When a package has an "exports" field, this will take precedence over the "main" field when importing the package by name. + /// + /// Values are dynamically retrieved from [ResolveOptions::main_fields]. + /// + /// + pub(crate) fn main_fields<'a>( + &'a self, + main_fields: &'a [String], + ) -> impl Iterator + '_ { + main_fields + .iter() + .filter_map(|main_field| self.raw_json.get(main_field)) + .filter_map(|value| value.as_str()) + } + /// Resolve the request string for this package.json by looking at the `browser` field. /// /// # Errors diff --git a/src/tests/main_field.rs b/src/tests/main_field.rs index 98f79052..3cadc8ce 100644 --- a/src/tests/main_field.rs +++ b/src/tests/main_field.rs @@ -6,19 +6,19 @@ use crate::{ResolveOptions, Resolver}; fn test() { let f = super::fixture().join("restrictions"); - let resolver = Resolver::new(ResolveOptions { + let resolver1 = Resolver::new(ResolveOptions { main_fields: vec!["style".into()], ..ResolveOptions::default() }); - let resolution = resolver.resolve(&f, "pck2").map(|r| r.full_path()); + let resolution = resolver1.resolve(&f, "pck2").map(|r| r.full_path()); assert_eq!(resolution, Ok(f.join("node_modules/pck2/index.css"))); - let resolver = Resolver::new(ResolveOptions { + let resolver2 = resolver1.clone_with_options(ResolveOptions { main_fields: vec!["module".into(), "main".into()], ..ResolveOptions::default() }); - let resolution = resolver.resolve(&f, "pck2").map(|r| r.full_path()); + let resolution = resolver2.resolve(&f, "pck2").map(|r| r.full_path()); assert_eq!(resolution, Ok(f.join("node_modules/pck2/module.js"))); }