@@ -1035,41 +1035,63 @@ function getExportsForCircularRequire(module) {
10351035 return module . exports ;
10361036}
10371037
1038+
10381039/**
1039- * Resolve a module request for CommonJS, invoking hooks from module.registerHooks()
1040- * if necessary .
1040+ * Wraps result of Module._resolveFilename to include additional fields for hooks.
1041+ * See resolveForCJSWithHooks .
10411042 * @param {string } specifier
10421043 * @param {Module|undefined } parent
10431044 * @param {boolean } isMain
1044- * @param {boolean } shouldSkipModuleHooks
1045+ * @param {ResolveFilenameOptions } options
10451046 * @returns {{url?: string, format?: string, parentURL?: string, filename: string} }
10461047 */
1047- function resolveForCJSWithHooks ( specifier , parent , isMain , shouldSkipModuleHooks ) {
1048- let defaultResolvedURL ;
1049- let defaultResolvedFilename ;
1050- let format ;
1051-
1052- function defaultResolveImpl ( specifier , parent , isMain , options ) {
1053- // For backwards compatibility, when encountering requests starting with node:,
1054- // throw ERR_UNKNOWN_BUILTIN_MODULE on failure or return the normalized ID on success
1055- // without going into Module._resolveFilename.
1056- let normalized ;
1057- if ( StringPrototypeStartsWith ( specifier , 'node:' ) ) {
1058- normalized = BuiltinModule . normalizeRequirableId ( specifier ) ;
1059- if ( ! normalized ) {
1060- throw new ERR_UNKNOWN_BUILTIN_MODULE ( specifier ) ;
1061- }
1062- defaultResolvedURL = specifier ;
1063- format = 'builtin' ;
1064- return normalized ;
1048+ function wrapResolveFilename ( specifier , parent , isMain , options ) {
1049+ const filename = Module . _resolveFilename ( specifier , parent , isMain , options ) . toString ( ) ;
1050+ return { __proto__ : null , url : undefined , format : undefined , filename } ;
1051+ }
1052+
1053+ /**
1054+ * See resolveForCJSWithHooks.
1055+ * @param {string } specifier
1056+ * @param {Module|undefined } parent
1057+ * @param {boolean } isMain
1058+ * @param {ResolveFilenameOptions } options
1059+ * @returns {{url?: string, format?: string, parentURL?: string, filename: string} }
1060+ */
1061+ function defaultResolveImplForCJSLoading ( specifier , parent , isMain , options ) {
1062+ // For backwards compatibility, when encountering requests starting with node:,
1063+ // throw ERR_UNKNOWN_BUILTIN_MODULE on failure or return the normalized ID on success
1064+ // without going into Module._resolveFilename.
1065+ let normalized ;
1066+ if ( StringPrototypeStartsWith ( specifier , 'node:' ) ) {
1067+ normalized = BuiltinModule . normalizeRequirableId ( specifier ) ;
1068+ if ( ! normalized ) {
1069+ throw new ERR_UNKNOWN_BUILTIN_MODULE ( specifier ) ;
10651070 }
1066- return Module . _resolveFilename ( specifier , parent , isMain , options ) . toString ( ) ;
1071+ return { __proto__ : null , url : specifier , format : 'builtin' , filename : normalized } ;
10671072 }
1073+ return wrapResolveFilename ( specifier , parent , isMain , options ) ;
1074+ }
10681075
1076+ /**
1077+ * Resolve a module request for CommonJS, invoking hooks from module.registerHooks()
1078+ * if necessary.
1079+ * @param {string } specifier
1080+ * @param {Module|undefined } parent
1081+ * @param {boolean } isMain
1082+ * @param {object } internalResolveOptions
1083+ * @param {boolean } internalResolveOptions.shouldSkipModuleHooks Whether to skip module hooks.
1084+ * @param {ResolveFilenameOptions } internalResolveOptions.requireResolveOptions Options from require.resolve().
1085+ * Only used when it comes from require.resolve().
1086+ * @returns {{url?: string, format?: string, parentURL?: string, filename: string} }
1087+ */
1088+ function resolveForCJSWithHooks ( specifier , parent , isMain , internalResolveOptions ) {
1089+ const { requireResolveOptions, shouldSkipModuleHooks } = internalResolveOptions ;
1090+ const defaultResolveImpl = requireResolveOptions ?
1091+ wrapResolveFilename : defaultResolveImplForCJSLoading ;
10691092 // Fast path: no hooks, just return simple results.
10701093 if ( ! resolveHooks . length || shouldSkipModuleHooks ) {
1071- const filename = defaultResolveImpl ( specifier , parent , isMain ) ;
1072- return { __proto__ : null , url : defaultResolvedURL , filename, format } ;
1094+ return defaultResolveImpl ( specifier , parent , isMain , requireResolveOptions ) ;
10731095 }
10741096
10751097 // Slow path: has hooks, do the URL conversions and invoke hooks with contexts.
@@ -1098,27 +1120,25 @@ function resolveForCJSWithHooks(specifier, parent, isMain, shouldSkipModuleHooks
10981120 } else {
10991121 conditionSet = getCjsConditions ( ) ;
11001122 }
1101- defaultResolvedFilename = defaultResolveImpl ( specifier , parent , isMain , {
1123+
1124+ const result = defaultResolveImpl ( specifier , parent , isMain , {
11021125 __proto__ : null ,
1126+ paths : requireResolveOptions ?. paths ,
11031127 conditions : conditionSet ,
11041128 } ) ;
1129+ // If the default resolver does not return a URL, convert it for the public API.
1130+ result . url ??= convertCJSFilenameToURL ( result . filename ) ;
11051131
1106- defaultResolvedURL = convertCJSFilenameToURL ( defaultResolvedFilename ) ;
1107- return { __proto__ : null , url : defaultResolvedURL } ;
1132+ // Remove filename because it's not part of the public API.
1133+ // TODO(joyeecheung): maybe expose it in the public API to avoid re-conversion for users too.
1134+ return { __proto__ : null , url : result . url , format : result . format } ;
11081135 }
11091136
11101137 const resolveResult = resolveWithHooks ( specifier , parentURL , /* importAttributes */ undefined ,
11111138 getCjsConditionsArray ( ) , defaultResolve ) ;
1112- const { url } = resolveResult ;
1113- format = resolveResult . format ;
1114-
1115- let filename ;
1116- if ( url === defaultResolvedURL ) { // Not overridden, skip the re-conversion.
1117- filename = defaultResolvedFilename ;
1118- } else {
1119- filename = convertURLToCJSFilename ( url ) ;
1120- }
1121-
1139+ const { url, format } = resolveResult ;
1140+ // Convert the URL from the hook chain back to a filename for internal use.
1141+ const filename = convertURLToCJSFilename ( url ) ;
11221142 const result = { __proto__ : null , url, format, filename, parentURL } ;
11231143 debug ( 'resolveForCJSWithHooks' , specifier , parent ?. id , isMain , shouldSkipModuleHooks , '->' , result ) ;
11241144 return result ;
@@ -1213,10 +1233,10 @@ function loadBuiltinWithHooks(id, url, format) {
12131233 * @param {string } request Specifier of module to load via `require`
12141234 * @param {Module } parent Absolute path of the module importing the child
12151235 * @param {boolean } isMain Whether the module is the main entry point
1216- * @param {object|undefined } options Additional options for loading the module
1236+ * @param {object|undefined } internalResolveOptions Additional options for loading the module
12171237 * @returns {object }
12181238 */
1219- Module . _load = function ( request , parent , isMain , options = kEmptyObject ) {
1239+ Module . _load = function ( request , parent , isMain , internalResolveOptions = kEmptyObject ) {
12201240 let relResolveCacheIdentifier ;
12211241 if ( parent ) {
12221242 debug ( 'Module._load REQUEST %s parent: %s' , request , parent . id ) ;
@@ -1239,7 +1259,7 @@ Module._load = function(request, parent, isMain, options = kEmptyObject) {
12391259 }
12401260 }
12411261
1242- const resolveResult = resolveForCJSWithHooks ( request , parent , isMain , options . shouldSkipModuleHooks ) ;
1262+ const resolveResult = resolveForCJSWithHooks ( request , parent , isMain , internalResolveOptions ) ;
12431263 let { format } = resolveResult ;
12441264 const { url, filename } = resolveResult ;
12451265
0 commit comments