Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 68fd2ac

Browse filesBrowse files
dygabotargos
authored andcommitted
loader: fix package resolution for edge case
this commit solves a regression introduced with PR-40980. if a resolve call results in a script with .mjs extension the is automatically set to . This avoids the case where an additional in the same directory as the .mjs file would declare the to commonjs PR-URL: #41218 Refs: #40980 Refs: yargs/yargs#2068 Reviewed-By: Guy Bedford <guybedford@gmail.com> Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com>
1 parent fac0871 commit 68fd2ac
Copy full SHA for 68fd2ac

File tree

Expand file treeCollapse file tree

5 files changed

+233
-169
lines changed
Open diff view settings
Filter options
Expand file treeCollapse file tree

5 files changed

+233
-169
lines changed
Open diff view settings
Collapse file

‎lib/internal/modules/cjs/loader.js‎

Copy file name to clipboardExpand all lines: lib/internal/modules/cjs/loader.js
+2-2Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -457,7 +457,7 @@ function trySelf(parentPath, request) {
457457
try {
458458
return finalizeEsmResolution(packageExportsResolve(
459459
pathToFileURL(pkgPath + '/package.json'), expansion, pkg,
460-
pathToFileURL(parentPath), cjsConditions).resolved, parentPath, pkgPath);
460+
pathToFileURL(parentPath), cjsConditions), parentPath, pkgPath);
461461
} catch (e) {
462462
if (e.code === 'ERR_MODULE_NOT_FOUND')
463463
throw createEsmNotFoundErr(request, pkgPath + '/package.json');
@@ -481,7 +481,7 @@ function resolveExports(nmPath, request) {
481481
try {
482482
return finalizeEsmResolution(packageExportsResolve(
483483
pathToFileURL(pkgPath + '/package.json'), '.' + expansion, pkg, null,
484-
cjsConditions).resolved, null, pkgPath);
484+
cjsConditions), null, pkgPath);
485485
} catch (e) {
486486
if (e.code === 'ERR_MODULE_NOT_FOUND')
487487
throw createEsmNotFoundErr(request, pkgPath + '/package.json');
Collapse file

‎lib/internal/modules/esm/get_format.js‎

Copy file name to clipboardExpand all lines: lib/internal/modules/esm/get_format.js
+42-24Lines changed: 42 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ const legacyExtensionFormatMap = {
3232
'.node': 'commonjs'
3333
};
3434

35+
let experimentalSpecifierResolutionWarned = false;
36+
3537
if (experimentalWasmModules)
3638
extensionFormatMap['.wasm'] = legacyExtensionFormatMap['.wasm'] = 'wasm';
3739

@@ -53,41 +55,57 @@ const protocolHandlers = ObjectAssign(ObjectCreate(null), {
5355

5456
return format;
5557
},
56-
'file:'(parsed, url) {
57-
const ext = extname(parsed.pathname);
58-
let format;
59-
60-
if (ext === '.js') {
61-
format = getPackageType(parsed.href) === 'module' ? 'module' : 'commonjs';
62-
} else {
63-
format = extensionFormatMap[ext];
64-
}
65-
if (!format) {
66-
if (experimentalSpecifierResolution === 'node') {
67-
process.emitWarning(
68-
'The Node.js specifier resolution in ESM is experimental.',
69-
'ExperimentalWarning');
70-
format = legacyExtensionFormatMap[ext];
71-
} else {
72-
throw new ERR_UNKNOWN_FILE_EXTENSION(ext, fileURLToPath(url));
73-
}
74-
}
75-
76-
return format || null;
77-
},
58+
'file:': getFileProtocolModuleFormat,
7859
'node:'() { return 'builtin'; },
7960
});
8061

81-
function defaultGetFormat(url, context) {
62+
function getLegacyExtensionFormat(ext) {
63+
if (
64+
experimentalSpecifierResolution === 'node' &&
65+
!experimentalSpecifierResolutionWarned
66+
) {
67+
process.emitWarning(
68+
'The Node.js specifier resolution in ESM is experimental.',
69+
'ExperimentalWarning');
70+
experimentalSpecifierResolutionWarned = true;
71+
}
72+
return legacyExtensionFormatMap[ext];
73+
}
74+
75+
function getFileProtocolModuleFormat(url, ignoreErrors) {
76+
const ext = extname(url.pathname);
77+
if (ext === '.js') {
78+
return getPackageType(url) === 'module' ? 'module' : 'commonjs';
79+
}
80+
81+
const format = extensionFormatMap[ext];
82+
if (format) return format;
83+
if (experimentalSpecifierResolution !== 'node') {
84+
// Explicit undefined return indicates load hook should rerun format check
85+
if (ignoreErrors)
86+
return undefined;
87+
throw new ERR_UNKNOWN_FILE_EXTENSION(ext, fileURLToPath(url));
88+
}
89+
return getLegacyExtensionFormat(ext) ?? null;
90+
}
91+
92+
function defaultGetFormatWithoutErrors(url, context) {
8293
const parsed = new URL(url);
94+
if (!ObjectPrototypeHasOwnProperty(protocolHandlers, parsed.protocol))
95+
return null;
96+
return protocolHandlers[parsed.protocol](parsed, true);
97+
}
8398

99+
function defaultGetFormat(url, context) {
100+
const parsed = new URL(url);
84101
return ObjectPrototypeHasOwnProperty(protocolHandlers, parsed.protocol) ?
85-
protocolHandlers[parsed.protocol](parsed, url) :
102+
protocolHandlers[parsed.protocol](parsed, false) :
86103
null;
87104
}
88105

89106
module.exports = {
90107
defaultGetFormat,
108+
defaultGetFormatWithoutErrors,
91109
extensionFormatMap,
92110
legacyExtensionFormatMap,
93111
};
Collapse file

‎lib/internal/modules/esm/load.js‎

Copy file name to clipboardExpand all lines: lib/internal/modules/esm/load.js
+1-2Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
const { defaultGetFormat } = require('internal/modules/esm/get_format');
44
const { defaultGetSource } = require('internal/modules/esm/get_source');
5-
const { translators } = require('internal/modules/esm/translators');
65
const { validateAssertions } = require('internal/modules/esm/assert');
76

87
/**
@@ -18,7 +17,7 @@ async function defaultLoad(url, context) {
1817
} = context;
1918
const { importAssertions } = context;
2019

21-
if (!format || !translators.has(format)) {
20+
if (format == null) {
2221
format = defaultGetFormat(url);
2322
}
2423

Collapse file

‎lib/internal/modules/esm/resolve.js‎

Copy file name to clipboardExpand all lines: lib/internal/modules/esm/resolve.js
+40-59Lines changed: 40 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ function emitTrailingSlashPatternDeprecation(match, pjsonUrl, base) {
107107
* @returns {void}
108108
*/
109109
function emitLegacyIndexDeprecation(url, packageJSONUrl, base, main) {
110-
const format = defaultGetFormat(url);
110+
const format = defaultGetFormatWithoutErrors(url);
111111
if (format !== 'module')
112112
return;
113113
const path = fileURLToPath(url);
@@ -464,22 +464,6 @@ const patternRegEx = /\*/g;
464464
function resolvePackageTargetString(
465465
target, subpath, match, packageJSONUrl, base, pattern, internal, conditions) {
466466

467-
const composeResult = (resolved) => {
468-
let format;
469-
try {
470-
format = getPackageType(resolved);
471-
} catch (err) {
472-
if (err.code === 'ERR_INVALID_FILE_URL_PATH') {
473-
const invalidModuleErr = new ERR_INVALID_MODULE_SPECIFIER(
474-
resolved, 'must not include encoded "/" or "\\" characters', base);
475-
invalidModuleErr.cause = err;
476-
throw invalidModuleErr;
477-
}
478-
throw err;
479-
}
480-
return { resolved, ...(format !== 'none') && { format } };
481-
};
482-
483467
if (subpath !== '' && !pattern && target[target.length - 1] !== '/')
484468
throwInvalidPackageTarget(match, target, packageJSONUrl, internal, base);
485469

@@ -512,7 +496,7 @@ function resolvePackageTargetString(
512496
if (!StringPrototypeStartsWith(resolvedPath, packagePath))
513497
throwInvalidPackageTarget(match, target, packageJSONUrl, internal, base);
514498

515-
if (subpath === '') return composeResult(resolved);
499+
if (subpath === '') return resolved;
516500

517501
if (RegExpPrototypeTest(invalidSegmentRegEx, subpath)) {
518502
const request = pattern ?
@@ -521,12 +505,16 @@ function resolvePackageTargetString(
521505
}
522506

523507
if (pattern) {
524-
return composeResult(new URL(RegExpPrototypeSymbolReplace(patternRegEx,
525-
resolved.href,
526-
() => subpath)));
508+
return new URL(
509+
RegExpPrototypeSymbolReplace(
510+
patternRegEx,
511+
resolved.href,
512+
() => subpath
513+
)
514+
);
527515
}
528516

529-
return composeResult(new URL(subpath, resolved));
517+
return new URL(subpath, resolved);
530518
}
531519

532520
/**
@@ -753,7 +741,7 @@ function packageImportsResolve(name, base, conditions) {
753741
packageJSONUrl, imports[name], '', name, base, false, true, conditions
754742
);
755743
if (resolveResult != null) {
756-
return resolveResult.resolved;
744+
return resolveResult;
757745
}
758746
} else {
759747
let bestMatch = '';
@@ -785,7 +773,7 @@ function packageImportsResolve(name, base, conditions) {
785773
bestMatch, base, true,
786774
true, conditions);
787775
if (resolveResult != null) {
788-
return resolveResult.resolved;
776+
return resolveResult;
789777
}
790778
}
791779
}
@@ -849,7 +837,7 @@ function parsePackageName(specifier, base) {
849837
*/
850838
function packageResolve(specifier, base, conditions) {
851839
if (NativeModule.canBeRequiredByUsers(specifier))
852-
return { resolved: new URL('node:' + specifier) };
840+
return new URL('node:' + specifier);
853841

854842
const { packageName, packageSubpath, isScoped } =
855843
parsePackageName(specifier, base);
@@ -888,19 +876,14 @@ function packageResolve(specifier, base, conditions) {
888876
packageJSONUrl, packageSubpath, packageConfig, base, conditions);
889877
}
890878
if (packageSubpath === '.') {
891-
return {
892-
resolved: legacyMainResolve(
893-
packageJSONUrl,
894-
packageConfig,
895-
base),
896-
...(packageConfig.type !== 'none') && { format: packageConfig.type }
897-
};
879+
return legacyMainResolve(
880+
packageJSONUrl,
881+
packageConfig,
882+
base
883+
);
898884
}
899885

900-
return {
901-
resolved: new URL(packageSubpath, packageJSONUrl),
902-
...(packageConfig.type !== 'none') && { format: packageConfig.type }
903-
};
886+
return new URL(packageSubpath, packageJSONUrl);
904887
// Cross-platform root check.
905888
} while (packageJSONPath.length !== lastPath.length);
906889

@@ -944,7 +927,6 @@ function moduleResolve(specifier, base, conditions, preserveSymlinks) {
944927
// Order swapped from spec for minor perf gain.
945928
// Ok since relative URLs cannot parse as URLs.
946929
let resolved;
947-
let format;
948930
if (shouldBeTreatedAsRelativeOrAbsolutePath(specifier)) {
949931
resolved = new URL(specifier, base);
950932
} else if (specifier[0] === '#') {
@@ -953,19 +935,13 @@ function moduleResolve(specifier, base, conditions, preserveSymlinks) {
953935
try {
954936
resolved = new URL(specifier);
955937
} catch {
956-
({ resolved, format } = packageResolve(specifier, base, conditions));
938+
resolved = packageResolve(specifier, base, conditions);
957939
}
958940
}
959941
if (resolved.protocol !== 'file:') {
960-
return {
961-
url: resolved
962-
};
942+
return resolved;
963943
}
964-
965-
return {
966-
url: finalizeResolution(resolved, base, preserveSymlinks),
967-
...(format != null) && { format }
968-
};
944+
return finalizeResolution(resolved, base, preserveSymlinks);
969945
}
970946

971947
/**
@@ -1014,6 +990,13 @@ function resolveAsCommonJS(specifier, parentURL) {
1014990
}
1015991
}
1016992

993+
function throwIfUnsupportedURLProtocol(url) {
994+
if (url.protocol !== 'file:' && url.protocol !== 'data:' &&
995+
url.protocol !== 'node:') {
996+
throw new ERR_UNSUPPORTED_ESM_URL_SCHEME(url);
997+
}
998+
}
999+
10171000
function defaultResolve(specifier, context = {}, defaultResolveUnused) {
10181001
let { parentURL, conditions } = context;
10191002
if (parentURL && policy?.manifest) {
@@ -1054,15 +1037,13 @@ function defaultResolve(specifier, context = {}, defaultResolveUnused) {
10541037

10551038
conditions = getConditionsSet(conditions);
10561039
let url;
1057-
let format;
10581040
try {
1059-
({ url, format } =
1060-
moduleResolve(
1061-
specifier,
1062-
parentURL,
1063-
conditions,
1064-
isMain ? preserveSymlinksMain : preserveSymlinks
1065-
));
1041+
url = moduleResolve(
1042+
specifier,
1043+
parentURL,
1044+
conditions,
1045+
isMain ? preserveSymlinksMain : preserveSymlinks
1046+
);
10661047
} catch (error) {
10671048
// Try to give the user a hint of what would have been the
10681049
// resolved CommonJS module
@@ -1086,13 +1067,11 @@ function defaultResolve(specifier, context = {}, defaultResolveUnused) {
10861067
throw error;
10871068
}
10881069

1089-
if (url.protocol !== 'file:' && url.protocol !== 'data:' &&
1090-
url.protocol !== 'node:')
1091-
throw new ERR_UNSUPPORTED_ESM_URL_SCHEME(url);
1070+
throwIfUnsupportedURLProtocol(url);
10921071

10931072
return {
10941073
url: `${url}`,
1095-
...(format != null) && { format }
1074+
format: defaultGetFormatWithoutErrors(url),
10961075
};
10971076
}
10981077

@@ -1107,4 +1086,6 @@ module.exports = {
11071086
};
11081087

11091088
// cycle
1110-
const { defaultGetFormat } = require('internal/modules/esm/get_format');
1089+
const {
1090+
defaultGetFormatWithoutErrors,
1091+
} = require('internal/modules/esm/get_format');

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.