Skip to content

Commit 76e43dd

Browse files
committed
module: support pattern trailers for imports field
PR-URL: nodejs#40041 Reviewed-By: James M Snell <[email protected]> Reviewed-By: Geoffrey Booth <[email protected]>
1 parent b5cb423 commit 76e43dd

File tree

3 files changed

+27
-14
lines changed

3 files changed

+27
-14
lines changed

lib/internal/modules/esm/resolve.js

Lines changed: 24 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ const {
2222
StringPrototypeSlice,
2323
StringPrototypeSplit,
2424
StringPrototypeStartsWith,
25-
StringPrototypeSubstr,
2625
} = primordials;
2726
const internalFS = require('internal/fs/utils');
2827
const { NativeModule } = require('internal/bootstrap/loaders');
@@ -559,38 +558,49 @@ function packageImportsResolve(name, base, conditions) {
559558
packageJSONUrl = pathToFileURL(packageConfig.pjsonPath);
560559
const imports = packageConfig.imports;
561560
if (imports) {
562-
if (ObjectPrototypeHasOwnProperty(imports, name)) {
561+
if (ObjectPrototypeHasOwnProperty(imports, name) &&
562+
!StringPrototypeIncludes(name, '*') &&
563+
!StringPrototypeEndsWith(name, '/')) {
563564
const resolved = resolvePackageTarget(
564565
packageJSONUrl, imports[name], '', name, base, false, true, conditions
565566
);
566567
if (resolved !== null)
567568
return { resolved, exact: true };
568569
} else {
569570
let bestMatch = '';
571+
let bestMatchSubpath;
570572
const keys = ObjectGetOwnPropertyNames(imports);
571573
for (let i = 0; i < keys.length; i++) {
572574
const key = keys[i];
573-
if (key[key.length - 1] === '*' &&
575+
const patternIndex = StringPrototypeIndexOf(key, '*');
576+
if (patternIndex !== -1 &&
574577
StringPrototypeStartsWith(name,
575-
StringPrototypeSlice(key, 0, -1)) &&
576-
name.length >= key.length &&
577-
key.length > bestMatch.length) {
578-
bestMatch = key;
578+
StringPrototypeSlice(key, 0,
579+
patternIndex))) {
580+
const patternTrailer = StringPrototypeSlice(key, patternIndex + 1);
581+
if (name.length >= key.length &&
582+
StringPrototypeEndsWith(name, patternTrailer) &&
583+
patternKeyCompare(bestMatch, key) === 1 &&
584+
StringPrototypeLastIndexOf(key, '*') === patternIndex) {
585+
bestMatch = key;
586+
bestMatchSubpath = StringPrototypeSlice(
587+
name, patternIndex, name.length - patternTrailer.length);
588+
}
579589
} else if (key[key.length - 1] === '/' &&
580590
StringPrototypeStartsWith(name, key) &&
581-
key.length > bestMatch.length) {
591+
patternKeyCompare(bestMatch, key) === 1) {
582592
bestMatch = key;
593+
bestMatchSubpath = StringPrototypeSlice(name, key.length);
583594
}
584595
}
585596

586597
if (bestMatch) {
587598
const target = imports[bestMatch];
588-
const pattern = bestMatch[bestMatch.length - 1] === '*';
589-
const subpath = StringPrototypeSubstr(name, bestMatch.length -
590-
(pattern ? 1 : 0));
591-
const resolved = resolvePackageTarget(
592-
packageJSONUrl, target, subpath, bestMatch, base, pattern, true,
593-
conditions);
599+
const pattern = StringPrototypeIncludes(bestMatch, '*');
600+
const resolved = resolvePackageTarget(packageJSONUrl, target,
601+
bestMatchSubpath, bestMatch,
602+
base, pattern, true,
603+
conditions);
594604
if (resolved !== null)
595605
return { resolved, exact: pattern };
596606
}

test/es-module/test-esm-imports.mjs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ const { requireImport, importImport } = importer;
2020
['#external', { default: 'asdf' }],
2121
// External subpath imports
2222
['#external/subpath/asdf.js', { default: 'asdf' }],
23+
// Trailing pattern imports
24+
['#subpath/asdf.asdf', { default: 'test' }],
2325
]);
2426

2527
for (const [validSpecifier, expected] of internalImports) {

test/fixtures/es-modules/pkgimports/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
"require": "./requirebranch.js"
77
},
88
"#subpath/*": "./sub/*",
9+
"#subpath/*.asdf": "./test.js",
910
"#external": "pkgexports/valid-cjs",
1011
"#external/subpath/*": "pkgexports/sub/*",
1112
"#external/invalidsubpath/": "pkgexports/sub",

0 commit comments

Comments
 (0)