mirror of
https://github.com/danbulant/oxc
synced 2026-05-24 20:32:10 +00:00
feat(resolver): implement enforceExtension (#566)
This commit is contained in:
parent
e5de977279
commit
c32dd32bad
4 changed files with 34 additions and 22 deletions
|
|
@ -16,7 +16,7 @@
|
|||
| | 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 |
|
||||
| | enforceExtension | false | Enforce that a extension from extensions must be used |
|
||||
| ✅ | 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 |
|
||||
| | fallback | [] | Same as `alias`, but only used if default resolving fails |
|
||||
|
|
|
|||
|
|
@ -170,7 +170,7 @@ impl<Fs: FileSystem> ResolverGeneric<Fs> {
|
|||
fn load_index(&self, path: &Path) -> ResolveState {
|
||||
for main_field in &self.options.main_files {
|
||||
let main_path = path.join(main_field);
|
||||
if !self.options.enforce_extension && self.cache.is_file(&main_path) {
|
||||
if self.options.enforce_extension == Some(false) && self.cache.is_file(&main_path) {
|
||||
return Ok(Some(main_path));
|
||||
}
|
||||
// 1. If X/index.js is a file, load X/index.js as JavaScript text. STOP
|
||||
|
|
|
|||
|
|
@ -25,8 +25,12 @@ pub struct ResolveOptions {
|
|||
|
||||
/// Enforce that a extension from extensions must be used.
|
||||
///
|
||||
/// Default `false`
|
||||
pub enforce_extension: bool,
|
||||
/// Default to `true` when [ResolveOptions::extensions] contains an empty string.
|
||||
/// Use `Some(false)` to disable the behavior.
|
||||
/// See <https://github.com/webpack/enhanced-resolve/pull/285>
|
||||
///
|
||||
/// Default None, which is the same as `Some(false)` when the above empty rule is not applied.
|
||||
pub enforce_extension: Option<bool>,
|
||||
|
||||
/// An object which maps extension to extension aliases.
|
||||
///
|
||||
|
|
@ -55,7 +59,7 @@ impl Default for ResolveOptions {
|
|||
alias: vec![],
|
||||
alias_fields: vec![],
|
||||
description_files: vec!["package.json".into()],
|
||||
enforce_extension: false,
|
||||
enforce_extension: None,
|
||||
extension_alias: vec![],
|
||||
extensions: vec![".js".into(), ".json".into(), ".node".into()],
|
||||
main_files: vec!["index".into()],
|
||||
|
|
@ -66,6 +70,15 @@ impl Default for ResolveOptions {
|
|||
|
||||
impl ResolveOptions {
|
||||
pub(crate) fn sanitize(mut self) -> Self {
|
||||
if self.enforce_extension.is_none() {
|
||||
self.enforce_extension = Some(false);
|
||||
// Set `enforceExtension` to `true` when [ResolveOptions::extensions] contains an empty string.
|
||||
// See <https://github.com/webpack/enhanced-resolve/pull/285>
|
||||
if self.extensions.iter().any(String::is_empty) {
|
||||
self.enforce_extension = Some(true);
|
||||
self.extensions.retain(String::is_empty);
|
||||
}
|
||||
}
|
||||
self.extensions = Self::remove_leading_dots(self.extensions);
|
||||
self.extension_alias = self
|
||||
.extension_alias
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
use std::path::PathBuf;
|
||||
|
||||
use oxc_resolver::{ResolveError, ResolveOptions, Resolver};
|
||||
use oxc_resolver::{Resolution, ResolveError, ResolveOptions, Resolver};
|
||||
|
||||
fn fixture() -> PathBuf {
|
||||
super::fixture().join("extensions")
|
||||
|
|
@ -48,32 +48,31 @@ fn extensions() -> Result<(), ResolveError> {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[ignore = "need to match missingDependencies returned from the resolve function"]
|
||||
// should default enforceExtension to true when extensions includes an empty string
|
||||
fn default_enforce_extension() {
|
||||
// should default enforceExtension to true when extensions includes an empty string
|
||||
let fixture = fixture();
|
||||
let f = fixture();
|
||||
|
||||
let options = ResolveOptions {
|
||||
let resolved = Resolver::new(ResolveOptions {
|
||||
extensions: vec![".ts".into(), String::new(), ".js".into()],
|
||||
..ResolveOptions::default()
|
||||
};
|
||||
})
|
||||
.resolve(&f, "./foo");
|
||||
|
||||
let resolver = Resolver::new(options);
|
||||
let _resolved = resolver.resolve(fixture, "./foo");
|
||||
assert_eq!(resolved, Err(ResolveError::NotFound(f.join("foo").into_boxed_path())));
|
||||
// TODO: need to match missingDependencies returned from the resolve function
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore = "need to match missingDependencies returned from the resolve function"]
|
||||
// should respect enforceExtension when extensions includes an empty string
|
||||
fn respect_enforce_extension() {
|
||||
// should respect enforceExtension when extensions includes an empty string
|
||||
let fixture = fixture();
|
||||
let f = fixture();
|
||||
|
||||
let options = ResolveOptions {
|
||||
enforce_extension: false,
|
||||
let resolved = Resolver::new(ResolveOptions {
|
||||
enforce_extension: Some(false),
|
||||
extensions: vec![".ts".into(), String::new(), ".js".into()],
|
||||
..ResolveOptions::default()
|
||||
};
|
||||
|
||||
let resolver = Resolver::new(options);
|
||||
let _resolved = resolver.resolve(fixture, "./foo");
|
||||
})
|
||||
.resolve(&f, "./foo");
|
||||
assert_eq!(resolved.map(Resolution::into_path_buf), Ok(f.join("foo.ts")));
|
||||
// TODO: need to match missingDependencies returned from the resolve function
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue