@@ -1034,43 +1034,63 @@ function getExportsForCircularRequire(module) {
10341034 return module . exports ;
10351035}
10361036
1037+
10371038/**
1038- * Resolve a module request for CommonJS, invoking hooks from module.registerHooks()
1039- * if necessary .
1039+ * Wraps result of Module._resolveFilename to include additional fields for hooks.
1040+ * See resolveForCJSWithHooks .
10401041 * @param {string } specifier
10411042 * @param {Module|undefined } parent
10421043 * @param {boolean } isMain
1043- * @param {boolean } shouldSkipModuleHooks
1044- * @param {object } [resolveOptions] Options from require.resolve().
1045- * @param {string[] } [resolveOptions.paths] Paths to search for modules in.
1044+ * @param {ResolveFilenameOptions } options
10461045 * @returns {{url?: string, format?: string, parentURL?: string, filename: string} }
10471046 */
1048- function resolveForCJSWithHooks ( specifier , parent , isMain , shouldSkipModuleHooks , resolveOptions ) {
1049- let defaultResolvedURL ;
1050- let defaultResolvedFilename ;
1051- let format ;
1052-
1053- function defaultResolveImpl ( specifier , parent , isMain , options ) {
1054- // For backwards compatibility, when encountering requests starting with node:,
1055- // throw ERR_UNKNOWN_BUILTIN_MODULE on failure or return the normalized ID on success
1056- // without going into Module._resolveFilename.
1057- let normalized ;
1058- if ( StringPrototypeStartsWith ( specifier , 'node:' ) ) {
1059- normalized = BuiltinModule . normalizeRequirableId ( specifier ) ;
1060- if ( ! normalized ) {
1061- throw new ERR_UNKNOWN_BUILTIN_MODULE ( specifier ) ;
1062- }
1063- defaultResolvedURL = specifier ;
1064- format = 'builtin' ;
1065- return normalized ;
1047+ function wrapResolveFilename ( specifier , parent , isMain , options ) {
1048+ const filename = Module . _resolveFilename ( specifier , parent , isMain , options ) . toString ( ) ;
1049+ return { __proto__ : null , url : undefined , format : undefined , filename } ;
1050+ }
1051+
1052+ /**
1053+ * See resolveForCJSWithHooks.
1054+ * @param {string } specifier
1055+ * @param {Module|undefined } parent
1056+ * @param {boolean } isMain
1057+ * @param {ResolveFilenameOptions } options
1058+ * @returns {{url?: string, format?: string, parentURL?: string, filename: string} }
1059+ */
1060+ function defaultResolveImplForCJSLoading ( specifier , parent , isMain , options ) {
1061+ // For backwards compatibility, when encountering requests starting with node:,
1062+ // throw ERR_UNKNOWN_BUILTIN_MODULE on failure or return the normalized ID on success
1063+ // without going into Module._resolveFilename.
1064+ let normalized ;
1065+ if ( StringPrototypeStartsWith ( specifier , 'node:' ) ) {
1066+ normalized = BuiltinModule . normalizeRequirableId ( specifier ) ;
1067+ if ( ! normalized ) {
1068+ throw new ERR_UNKNOWN_BUILTIN_MODULE ( specifier ) ;
10661069 }
1067- return Module . _resolveFilename ( specifier , parent , isMain , options ) . toString ( ) ;
1070+ return { __proto__ : null , url : specifier , format : 'builtin' , filename : normalized } ;
10681071 }
1072+ return wrapResolveFilename ( specifier , parent , isMain , options ) ;
1073+ }
10691074
1075+ /**
1076+ * Resolve a module request for CommonJS, invoking hooks from module.registerHooks()
1077+ * if necessary.
1078+ * @param {string } specifier
1079+ * @param {Module|undefined } parent
1080+ * @param {boolean } isMain
1081+ * @param {object } internalResolveOptions
1082+ * @param {boolean } internalResolveOptions.shouldSkipModuleHooks Whether to skip module hooks.
1083+ * @param {ResolveFilenameOptions } internalResolveOptions.requireResolveOptions Options from require.resolve().
1084+ * Only used when it comes from require.resolve().
1085+ * @returns {{url?: string, format?: string, parentURL?: string, filename: string} }
1086+ */
1087+ function resolveForCJSWithHooks ( specifier , parent , isMain , internalResolveOptions ) {
1088+ const { requireResolveOptions, shouldSkipModuleHooks } = internalResolveOptions ;
1089+ const defaultResolveImpl = requireResolveOptions ?
1090+ wrapResolveFilename : defaultResolveImplForCJSLoading ;
10701091 // Fast path: no hooks, just return simple results.
10711092 if ( ! resolveHooks . length || shouldSkipModuleHooks ) {
1072- const filename = defaultResolveImpl ( specifier , parent , isMain , resolveOptions ) ;
1073- return { __proto__ : null , url : defaultResolvedURL , filename, format } ;
1093+ return defaultResolveImpl ( specifier , parent , isMain , requireResolveOptions ) ;
10741094 }
10751095
10761096 // Slow path: has hooks, do the URL conversions and invoke hooks with contexts.
@@ -1099,28 +1119,25 @@ function resolveForCJSWithHooks(specifier, parent, isMain, shouldSkipModuleHooks
10991119 } else {
11001120 conditionSet = getCjsConditions ( ) ;
11011121 }
1102- defaultResolvedFilename = defaultResolveImpl ( specifier , parent , isMain , {
1122+
1123+ const result = defaultResolveImpl ( specifier , parent , isMain , {
11031124 __proto__ : null ,
1104- paths : resolveOptions ?. paths ,
1125+ paths : requireResolveOptions ?. paths ,
11051126 conditions : conditionSet ,
11061127 } ) ;
1128+ // If the default resolver does not return a URL, convert it for the public API.
1129+ result . url ??= convertCJSFilenameToURL ( result . filename ) ;
11071130
1108- defaultResolvedURL = convertCJSFilenameToURL ( defaultResolvedFilename ) ;
1109- return { __proto__ : null , url : defaultResolvedURL } ;
1131+ // Remove filename because it's not part of the public API.
1132+ // TODO(joyeecheung): maybe expose it in the public API to avoid re-conversion for users too.
1133+ return { __proto__ : null , url : result . url , format : result . format } ;
11101134 }
11111135
11121136 const resolveResult = resolveWithHooks ( specifier , parentURL , /* importAttributes */ undefined ,
11131137 getCjsConditionsArray ( ) , defaultResolve ) ;
1114- const { url } = resolveResult ;
1115- format = resolveResult . format ;
1116-
1117- let filename ;
1118- if ( url === defaultResolvedURL ) { // Not overridden, skip the re-conversion.
1119- filename = defaultResolvedFilename ;
1120- } else {
1121- filename = convertURLToCJSFilename ( url ) ;
1122- }
1123-
1138+ const { url, format } = resolveResult ;
1139+ // Convert the URL from the hook chain back to a filename for internal use.
1140+ const filename = convertURLToCJSFilename ( url ) ;
11241141 const result = { __proto__ : null , url, format, filename, parentURL } ;
11251142 debug ( 'resolveForCJSWithHooks' , specifier , parent ?. id , isMain , shouldSkipModuleHooks , '->' , result ) ;
11261143 return result ;
@@ -1215,10 +1232,10 @@ function loadBuiltinWithHooks(id, url, format) {
12151232 * @param {string } request Specifier of module to load via `require`
12161233 * @param {Module } parent Absolute path of the module importing the child
12171234 * @param {boolean } isMain Whether the module is the main entry point
1218- * @param {object|undefined } options Additional options for loading the module
1235+ * @param {object|undefined } internalResolveOptions Additional options for loading the module
12191236 * @returns {object }
12201237 */
1221- Module . _load = function ( request , parent , isMain , options = kEmptyObject ) {
1238+ Module . _load = function ( request , parent , isMain , internalResolveOptions = kEmptyObject ) {
12221239 let relResolveCacheIdentifier ;
12231240 if ( parent ) {
12241241 debug ( 'Module._load REQUEST %s parent: %s' , request , parent . id ) ;
@@ -1241,7 +1258,7 @@ Module._load = function(request, parent, isMain, options = kEmptyObject) {
12411258 }
12421259 }
12431260
1244- const resolveResult = resolveForCJSWithHooks ( request , parent , isMain , options . shouldSkipModuleHooks ) ;
1261+ const resolveResult = resolveForCJSWithHooks ( request , parent , isMain , internalResolveOptions ) ;
12451262 let { format } = resolveResult ;
12461263 const { url, filename } = resolveResult ;
12471264
0 commit comments