feat(resolver): implement descriptionFiles option (#565)

This commit is contained in:
Boshen 2023-07-18 14:11:43 +08:00 committed by GitHub
parent 0c17f4f783
commit e5de977279
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 56 additions and 27 deletions

View file

@ -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 |

View file

@ -188,25 +188,27 @@ impl<Fs: FileSystem> ResolverGeneric<Fs> {
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)

View file

@ -18,27 +18,32 @@ pub struct ResolveOptions {
/// Default `[]`
pub alias_fields: Vec<String>,
/// 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<String>)>,
/// Default `["package.json"]`
pub description_files: Vec<String>,
/// 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<String>)>,
/// A list of extensions which should be tried for.
///
/// Default `[".js", ".json", ".node"]`
pub extensions: Vec<String>,
/// A list of main files in directories
/// A list of main files in directories.
///
/// Default `["index"]`
pub main_files: Vec<String>,
/// 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<String>,
@ -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()],

View file

@ -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())));
}

View file

@ -1,3 +1,4 @@
mod description_file;
mod enhanced_resolve;
mod memory_fs;