diff --git a/crates/oxc_resolver/README.md b/crates/oxc_resolver/README.md index 393aa9a00..1d705eee3 100644 --- a/crates/oxc_resolver/README.md +++ b/crates/oxc_resolver/README.md @@ -15,7 +15,7 @@ | | cachePredicate | function() { return true }; | A function which decides whether a request should be cached or not. An object is passed to the function with `path` and `request` properties. | | | cacheWithContext | true | If unsafe cache is enabled, includes `request.context` in the cache key | | | conditionNames | [] | A list of exports field condition names | -| | descriptionFiles | ["package.json"] | A list of description files to read from | +| ✅ | descriptionFiles | ["package.json"] | A list of description files to read from | | | enforceExtension | false | Enforce that a extension from extensions must be used | | | exportsFields | ["exports"] | A list of exports fields in description files | | ✅ | extensions | [".js", ".json", ".node"] | A list of extensions which should be tried for files | diff --git a/crates/oxc_resolver/src/lib.rs b/crates/oxc_resolver/src/lib.rs index c0f24aa7f..912c0cb65 100644 --- a/crates/oxc_resolver/src/lib.rs +++ b/crates/oxc_resolver/src/lib.rs @@ -188,25 +188,27 @@ impl ResolverGeneric { fn load_as_directory(&self, path: &Path) -> ResolveState { // 1. If X/package.json is a file, - let package_json_path = path.join("package.json"); - if self.cache.is_file(&package_json_path) { - // a. Parse X/package.json, and look for "main" field. - let package_json = self.cache.read_package_json(&package_json_path)?; - // b. If "main" is a falsy value, GOTO 2. - if let Some(main_field) = &package_json.main { - // c. let M = X + (json main field) - let main_field_path = path.normalize_with(main_field); - // d. LOAD_AS_FILE(M) - if let Some(path) = self.load_as_file(&main_field_path)? { - return Ok(Some(path)); + for description_file in &self.options.description_files { + let package_json_path = path.join(description_file); + if self.cache.is_file(&package_json_path) { + // a. Parse X/package.json, and look for "main" field. + let package_json = self.cache.read_package_json(&package_json_path)?; + // b. If "main" is a falsy value, GOTO 2. + if let Some(main_field) = &package_json.main { + // c. let M = X + (json main field) + let main_field_path = path.normalize_with(main_field); + // d. LOAD_AS_FILE(M) + if let Some(path) = self.load_as_file(&main_field_path)? { + return Ok(Some(path)); + } + // e. LOAD_INDEX(M) + if let Some(path) = self.load_index(&main_field_path)? { + return Ok(Some(path)); + } + // f. LOAD_INDEX(X) DEPRECATED + // g. THROW "not found" + return Err(ResolveError::NotFound(main_field_path.into_boxed_path())); } - // e. LOAD_INDEX(M) - if let Some(path) = self.load_index(&main_field_path)? { - return Ok(Some(path)); - } - // f. LOAD_INDEX(X) DEPRECATED - // g. THROW "not found" - return Err(ResolveError::NotFound(main_field_path.into_boxed_path())); } } // 2. LOAD_INDEX(X) diff --git a/crates/oxc_resolver/src/options.rs b/crates/oxc_resolver/src/options.rs index 13eda913b..874999b06 100644 --- a/crates/oxc_resolver/src/options.rs +++ b/crates/oxc_resolver/src/options.rs @@ -18,27 +18,32 @@ pub struct ResolveOptions { /// Default `[]` pub alias_fields: Vec, - /// An object which maps extension to extension aliases + /// A list of description files to read (there was once a `bower.json`). /// - /// Default `{}` - pub extension_alias: Vec<(String, Vec)>, + /// Default `["package.json"]` + pub description_files: Vec, - /// Enforce that a extension from extensions must be used + /// Enforce that a extension from extensions must be used. /// /// Default `false` pub enforce_extension: bool, - /// A list of extensions which should be tried for + /// An object which maps extension to extension aliases. + /// + /// Default `{}` + pub extension_alias: Vec<(String, Vec)>, + + /// A list of extensions which should be tried for. /// /// Default `[".js", ".json", ".node"]` pub extensions: Vec, - /// A list of main files in directories + /// A list of main files in directories. /// /// Default `["index"]` pub main_files: Vec, - /// A list of directories to resolve modules from, can be absolute path or folder name + /// A list of directories to resolve modules from, can be absolute path or folder name. /// /// Default `["node_modules"]` pub modules: Vec, @@ -49,8 +54,9 @@ impl Default for ResolveOptions { Self { alias: vec![], alias_fields: vec![], - extension_alias: vec![], + description_files: vec!["package.json".into()], enforce_extension: false, + extension_alias: vec![], extensions: vec![".js".into(), ".json".into(), ".node".into()], main_files: vec!["index".into()], modules: vec!["node_modules".into()], diff --git a/crates/oxc_resolver/tests/description_file.rs b/crates/oxc_resolver/tests/description_file.rs new file mode 100644 index 000000000..fc30744e2 --- /dev/null +++ b/crates/oxc_resolver/tests/description_file.rs @@ -0,0 +1,20 @@ +//! FYI webpack does not have any tests for description files + +use std::env; + +use oxc_resolver::{Resolution, ResolveError, ResolveOptions, Resolver}; + +#[test] +fn no_description_file() { + let f = env::current_dir().unwrap().join("tests/enhanced_resolve"); + + let resolver = Resolver::default(); + assert_eq!( + resolver.resolve(&f, ".").map(Resolution::into_path_buf), + Ok(f.join("lib/index.js")) + ); + + let resolver = + Resolver::new(ResolveOptions { description_files: vec![], ..ResolveOptions::default() }); + assert_eq!(resolver.resolve(&f, "."), Err(ResolveError::NotFound(f.into_boxed_path()))); +} diff --git a/crates/oxc_resolver/tests/mod.rs b/crates/oxc_resolver/tests/mod.rs index 8d7d45340..3df6fd24a 100644 --- a/crates/oxc_resolver/tests/mod.rs +++ b/crates/oxc_resolver/tests/mod.rs @@ -1,3 +1,4 @@ +mod description_file; mod enhanced_resolve; mod memory_fs;