diff --git a/fixtures/enhanced_resolve/test/fixtures/export-query/add.js b/fixtures/enhanced_resolve/test/fixtures/export-query/add.js new file mode 100644 index 00000000..6e31ef4b --- /dev/null +++ b/fixtures/enhanced_resolve/test/fixtures/export-query/add.js @@ -0,0 +1 @@ +export const add = (a, b) => a + b diff --git a/fixtures/enhanced_resolve/test/fixtures/export-query/equal.js b/fixtures/enhanced_resolve/test/fixtures/export-query/equal.js new file mode 100644 index 00000000..7c99f462 --- /dev/null +++ b/fixtures/enhanced_resolve/test/fixtures/export-query/equal.js @@ -0,0 +1 @@ +export const equal = (a, b) => a === b diff --git a/fixtures/enhanced_resolve/test/fixtures/export-query/minus.js b/fixtures/enhanced_resolve/test/fixtures/export-query/minus.js new file mode 100644 index 00000000..40e6a30f --- /dev/null +++ b/fixtures/enhanced_resolve/test/fixtures/export-query/minus.js @@ -0,0 +1 @@ +export const minus = (a, b) => a - b diff --git a/fixtures/enhanced_resolve/test/fixtures/export-query/package.json b/fixtures/enhanced_resolve/test/fixtures/export-query/package.json new file mode 100644 index 00000000..2c08de3f --- /dev/null +++ b/fixtures/enhanced_resolve/test/fixtures/export-query/package.json @@ -0,0 +1,8 @@ +{ + "name": "export-query", + "exports": { + "./add": "./add.js?query1?query2", + "./minus": "./minus.js?query?extra", + "./equal": "./equal.js?query" + } +} diff --git a/src/lib.rs b/src/lib.rs index 7728fc3a..f61cc2f7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -936,6 +936,29 @@ impl ResolverGeneric { if let Some(path) = self.load_as_file_or_directory(cached_path, "", ctx)? { return Ok(Some(path)); } + + let mut path_str = cached_path.path().to_str(); + + // 3. If the RESOLVED_PATH contains `?``, it could be a path with query + // so try to resolve it as a file or directory without the query, + // but also `?` is a valid character in a path, so we should try from right to left. + while let Some(s) = path_str { + if let Some((before, _)) = s.rsplit_once('?') { + if (self.load_as_file_or_directory( + &self.cache.value(Path::new(before)), + "", + ctx, + )?) + .is_some() + { + return Ok(Some(cached_path.clone())); + } + path_str = Some(before); + } else { + break; + } + } + // 3. THROW "not found" Err(ResolveError::NotFound(specifier.to_string())) } diff --git a/src/tests/exports_field.rs b/src/tests/exports_field.rs index 8f3cb4d8..78e770c4 100644 --- a/src/tests/exports_field.rs +++ b/src/tests/exports_field.rs @@ -12,6 +12,7 @@ fn test_simple() { let f2 = super::fixture().join("exports-field2"); let f4 = super::fixture().join("exports-field-error"); let f5 = super::fixture().join("imports-exports-wildcard"); + let f6 = super::fixture().join("export-query"); let resolver = Resolver::new(ResolveOptions { extensions: vec![".js".into()], @@ -43,6 +44,10 @@ fn test_simple() { ("should resolve with wildcard pattern #7", f5.clone(), "m/middle-3/nested/f", f5.join("node_modules/m/src/middle-3/nested/f/nested/f.js")), ("should resolve with wildcard pattern #8", f5.clone(), "m/middle-4/f/nested", f5.join("node_modules/m/src/middle-4/f/f.js")), ("should resolve with wildcard pattern #9", f5.clone(), "m/middle-5/f$/$", f5.join("node_modules/m/src/middle-5/f$/$.js")), + ("should resolve with query string #10", f6.clone(), "export-query/add", f6.join("add.js?query1?query2")), + // Sadly we can not use real `minus.js?query` and `equal.js?query` file due to Windows: invalid path + ("should resolve with query string #10", f6.clone(), "export-query/minus", f6.join("minus.js?query?extra")), + ("should resolve with query string #10", f6.clone(), "export-query/equal", f6.join("equal.js?query")), ]; // Not needed or snapshot: