@@ -101,6 +101,7 @@ const kIsCachedByESMLoader = Symbol('kIsCachedByESMLoader');
101101const kRequiredModuleSymbol = Symbol ( 'kRequiredModuleSymbol' ) ;
102102const kIsExecuting = Symbol ( 'kIsExecuting' ) ;
103103
104+ const kURL = Symbol ( 'kURL' ) ;
104105const kFormat = Symbol ( 'kFormat' ) ;
105106
106107// Set first due to cycle with ESM loader functions.
@@ -111,6 +112,9 @@ module.exports = {
111112 kModuleCircularVisited,
112113 initializeCJS,
113114 Module,
115+ findLongestRegisteredExtension,
116+ resolveForCJSWithHooks,
117+ loadSourceForCJSWithHooks : loadSource ,
114118 wrapSafe,
115119 wrapModuleLoad,
116120 kIsMainSymbol,
@@ -155,6 +159,13 @@ const {
155159 stripBOM,
156160 toRealPath,
157161} = require ( 'internal/modules/helpers' ) ;
162+ const {
163+ convertCJSFilenameToURL,
164+ convertURLToCJSFilename,
165+ loadWithHooks,
166+ registerHooks,
167+ resolveWithHooks,
168+ } = require ( 'internal/modules/sync_hooks' ) ;
158169const { stripTypeScriptModuleTypes } = require ( 'internal/modules/typescript' ) ;
159170const packageJsonReader = require ( 'internal/modules/package_json_reader' ) ;
160171const { getOptionValue, getEmbedderOptions } = require ( 'internal/options' ) ;
@@ -584,7 +595,7 @@ function trySelfParentPath(parent) {
584595 * @param {string } parentPath The path of the parent module
585596 * @param {string } request The module request to resolve
586597 */
587- function trySelf ( parentPath , request ) {
598+ function trySelf ( parentPath , request , conditions ) {
588599 if ( ! parentPath ) { return false ; }
589600
590601 const pkg = packageJsonReader . getNearestParentPackageJSON ( parentPath ) ;
@@ -605,7 +616,7 @@ function trySelf(parentPath, request) {
605616 const { packageExportsResolve } = require ( 'internal/modules/esm/resolve' ) ;
606617 return finalizeEsmResolution ( packageExportsResolve (
607618 pathToFileURL ( pkg . path ) , expansion , pkg . data ,
608- pathToFileURL ( parentPath ) , getCjsConditions ( ) ) , parentPath , pkg . path ) ;
619+ pathToFileURL ( parentPath ) , conditions ) , parentPath , pkg . path ) ;
609620 } catch ( e ) {
610621 if ( e . code === 'ERR_MODULE_NOT_FOUND' ) {
611622 throw createEsmNotFoundErr ( request , pkg . path ) ;
@@ -626,7 +637,7 @@ const EXPORTS_PATTERN = /^((?:@[^/\\%]+\/)?[^./\\%][^/\\%]*)(\/.*)?$/;
626637 * @param {string } nmPath The path to the module.
627638 * @param {string } request The request for the module.
628639 */
629- function resolveExports ( nmPath , request ) {
640+ function resolveExports ( nmPath , request , conditions ) {
630641 // The implementation's behavior is meant to mirror resolution in ESM.
631642 const { 1 : name , 2 : expansion = '' } =
632643 RegExpPrototypeExec ( EXPORTS_PATTERN , request ) || kEmptyObject ;
@@ -638,7 +649,7 @@ function resolveExports(nmPath, request) {
638649 const { packageExportsResolve } = require ( 'internal/modules/esm/resolve' ) ;
639650 return finalizeEsmResolution ( packageExportsResolve (
640651 pathToFileURL ( pkgPath + '/package.json' ) , '.' + expansion , pkg , null ,
641- getCjsConditions ( ) ) , null , pkgPath ) ;
652+ conditions ) , null , pkgPath ) ;
642653 } catch ( e ) {
643654 if ( e . code === 'ERR_MODULE_NOT_FOUND' ) {
644655 throw createEsmNotFoundErr ( request , pkgPath + '/package.json' ) ;
@@ -680,7 +691,7 @@ function getDefaultExtensions() {
680691 * @param {boolean } isMain Whether the request is the main app entry point
681692 * @returns {string | false }
682693 */
683- Module . _findPath = function ( request , paths , isMain ) {
694+ Module . _findPath = function ( request , paths , isMain , conditions = getCjsConditions ( ) ) {
684695 const absoluteRequest = path . isAbsolute ( request ) ;
685696 if ( absoluteRequest ) {
686697 paths = [ '' ] ;
@@ -738,7 +749,7 @@ Module._findPath = function(request, paths, isMain) {
738749 }
739750
740751 if ( ! absoluteRequest ) {
741- const exportsResolved = resolveExports ( curPath , request ) ;
752+ const exportsResolved = resolveExports ( curPath , request , conditions ) ;
742753 if ( exportsResolved ) {
743754 return exportsResolved ;
744755 }
@@ -1019,6 +1030,50 @@ function getExportsForCircularRequire(module) {
10191030 return module . exports ;
10201031}
10211032
1033+ /**
1034+ * Resolve a module request for CommonJS
1035+ * @param {string } specifier
1036+ * @param {Module|undefined } parent
1037+ * @param {boolean } isMain
1038+ * @returns {{url: string, format?: string, parentURL?: string, filename: string} }
1039+ */
1040+ function resolveForCJSWithHooks ( specifier , parent , isMain ) {
1041+ let parentURL ;
1042+ if ( parent ) {
1043+ if ( ! parent [ kURL ] && parent . filename ) {
1044+ parent [ kURL ] = convertCJSFilenameToURL ( parent . filename ) ;
1045+ }
1046+ parentURL = parent [ kURL ] ;
1047+ }
1048+
1049+ let defaultResolvedURL ;
1050+ let defaultResolvedFilename ;
1051+ function defaultResolve ( specifier , context ) {
1052+ // TODO(joyeecheung): parent and isMain should be part of context, then we
1053+ // no longer need to use a different defaultResolve for every resolution.
1054+ defaultResolvedFilename = Module . _resolveFilename ( specifier , parent , isMain , {
1055+ __proto__ : null ,
1056+ conditions : context . conditions ,
1057+ } ) . toString ( ) ;
1058+ defaultResolvedURL = convertCJSFilenameToURL ( defaultResolvedFilename ) ;
1059+ return { url : defaultResolvedURL } ;
1060+ }
1061+
1062+ const {
1063+ url, format,
1064+ } = resolveWithHooks ( specifier , parentURL , /* importAttributes */ undefined ,
1065+ getCjsConditions ( ) , defaultResolve ) ;
1066+
1067+ let filename ;
1068+ if ( url === defaultResolvedURL ) { // Not overridden, skip the re-conversion.
1069+ filename = defaultResolvedFilename ;
1070+ } else {
1071+ filename = convertURLToCJSFilename ( url ) ;
1072+ }
1073+
1074+ return { __proto__ : null , url, format, filename, parentURL } ;
1075+ }
1076+
10221077/**
10231078 * Load a module from cache if it exists, otherwise create a new module instance.
10241079 * 1. If a module already exists in the cache: return its exports object.
@@ -1065,7 +1120,8 @@ Module._load = function(request, parent, isMain) {
10651120 return module . exports ;
10661121 }
10671122
1068- const filename = Module . _resolveFilename ( request , parent , isMain ) ;
1123+ const { url, format, filename } = resolveForCJSWithHooks ( request , parent , isMain ) ;
1124+
10691125 const cachedModule = Module . _cache [ filename ] ;
10701126 if ( cachedModule !== undefined ) {
10711127 updateChildren ( parent , cachedModule , true ) ;
@@ -1110,6 +1166,10 @@ Module._load = function(request, parent, isMain) {
11101166 reportModuleToWatchMode ( filename ) ;
11111167 Module . _cache [ filename ] = module ;
11121168 module [ kIsCachedByESMLoader ] = false ;
1169+ // If there are resolve hooks, carry the context information into the
1170+ // load hooks for the module keyed by the (potentially customized) filename.
1171+ module [ kURL ] = url ;
1172+ module [ kFormat ] = format ;
11131173 }
11141174
11151175 if ( parent !== undefined ) {
@@ -1157,6 +1217,7 @@ Module._resolveFilename = function(request, parent, isMain, options) {
11571217 if ( BuiltinModule . normalizeRequirableId ( request ) ) {
11581218 return request ;
11591219 }
1220+ const conditions = ( options ?. conditions ) || getCjsConditions ( ) ;
11601221
11611222 let paths ;
11621223
@@ -1202,7 +1263,7 @@ Module._resolveFilename = function(request, parent, isMain, options) {
12021263 try {
12031264 const { packageImportsResolve } = require ( 'internal/modules/esm/resolve' ) ;
12041265 return finalizeEsmResolution (
1205- packageImportsResolve ( request , pathToFileURL ( parentPath ) , getCjsConditions ( ) ) ,
1266+ packageImportsResolve ( request , pathToFileURL ( parentPath ) , conditions ) ,
12061267 parentPath ,
12071268 pkg . path ,
12081269 ) ;
@@ -1217,7 +1278,7 @@ Module._resolveFilename = function(request, parent, isMain, options) {
12171278
12181279 // Try module self resolution first
12191280 const parentPath = trySelfParentPath ( parent ) ;
1220- const selfResolved = trySelf ( parentPath , request ) ;
1281+ const selfResolved = trySelf ( parentPath , request , conditions ) ;
12211282 if ( selfResolved ) {
12221283 const cacheKey = request + '\x00' +
12231284 ( paths . length === 1 ? paths [ 0 ] : ArrayPrototypeJoin ( paths , '\x00' ) ) ;
@@ -1226,7 +1287,7 @@ Module._resolveFilename = function(request, parent, isMain, options) {
12261287 }
12271288
12281289 // Look up the filename first, since that's the cache key.
1229- const filename = Module . _findPath ( request , paths , isMain ) ;
1290+ const filename = Module . _findPath ( request , paths , isMain , conditions ) ;
12301291 if ( filename ) { return filename ; }
12311292 const requireStack = [ ] ;
12321293 for ( let cursor = parent ;
@@ -1293,8 +1354,8 @@ Module.prototype.load = function(filename) {
12931354 debug ( 'load %j for module %j' , filename , this . id ) ;
12941355
12951356 assert ( ! this . loaded ) ;
1296- this . filename = filename ;
1297- this . paths = Module . _nodeModulePaths ( path . dirname ( filename ) ) ;
1357+ this . filename ?? = filename ;
1358+ this . paths ?? = Module . _nodeModulePaths ( path . dirname ( filename ) ) ;
12981359
12991360 const extension = findLongestRegisteredExtension ( filename ) ;
13001361
@@ -1563,20 +1624,36 @@ Module.prototype._compile = function(content, filename, format) {
15631624 * @returns {{source: string, format?: string} }
15641625 */
15651626function loadSource ( mod , filename , formatFromNode ) {
1566- if ( formatFromNode ! == undefined ) {
1627+ if ( mod [ kFormat ] = == undefined ) {
15671628 mod [ kFormat ] = formatFromNode ;
15681629 }
1569- const format = mod [ kFormat ] ;
1630+ // If the module was loaded before, just return.
1631+ if ( mod [ kModuleSource ] !== undefined ) {
1632+ return { source : mod [ kModuleSource ] , format : mod [ kFormat ] } ;
1633+ }
15701634
1571- let source = mod [ kModuleSource ] ;
1572- if ( source !== undefined ) {
1573- mod [ kModuleSource ] = undefined ;
1574- } else {
1575- // TODO(joyeecheung): we can read a buffer instead to speed up
1576- // compilation.
1577- source = fs . readFileSync ( filename , 'utf8' ) ;
1635+ if ( mod [ kURL ] === undefined ) {
1636+ mod [ kURL ] = convertCJSFilenameToURL ( filename ) ;
15781637 }
1579- return { source, format } ;
1638+ const url = mod [ kURL ] ;
1639+
1640+ const originalFormat = mod [ kFormat ] ;
1641+
1642+ function defaultLoad ( url , context ) {
1643+ // If the url is the same as the original one, save the conversion.
1644+ const newFilename = ( url === mod [ kURL ] ) ? filename : convertURLToCJSFilename ( url ) ;
1645+ const source = fs . readFileSync ( newFilename , 'utf8' ) ;
1646+ return { source, format : originalFormat } ;
1647+ }
1648+
1649+ const loadResult = loadWithHooks ( url , originalFormat , undefined , getCjsConditions ( ) , defaultLoad ) ;
1650+
1651+ // Reset the module properties with load hook results.
1652+ if ( loadResult . format !== undefined ) {
1653+ mod [ kFormat ] = loadResult . format ;
1654+ }
1655+ mod [ kModuleSource ] = loadResult . source ;
1656+ return { source : mod [ kModuleSource ] , format : mod [ kFormat ] } ;
15801657}
15811658
15821659/**
@@ -1594,7 +1671,6 @@ function loadMTS(mod, filename) {
15941671 * @param {Module } module CJS module instance
15951672 * @param {string } filename The file path of the module
15961673 */
1597-
15981674function loadCTS ( module , filename ) {
15991675 const loadResult = loadSource ( module , filename , 'commonjs-typescript' ) ;
16001676 module . _compile ( loadResult . source , filename , loadResult . format ) ;
@@ -1862,3 +1938,4 @@ ObjectDefineProperty(Module.prototype, 'constructor', {
18621938
18631939// Backwards compatibility
18641940Module . Module = Module ;
1941+ Module . registerHooks = registerHooks ;
0 commit comments