@@ -37,6 +37,7 @@ const {
3737 ObjectPrototypeHasOwnProperty,
3838 ObjectSetPrototypeOf,
3939 ReflectSet,
40+ RegExpPrototypeTest,
4041 SafeMap,
4142 String,
4243 StringPrototypeIndexOf,
@@ -125,7 +126,7 @@ function enrichCJSError(err) {
125126 after a comment block and/or after a variable definition.
126127 */
127128 if ( err . message . startsWith ( 'Unexpected token \'export\'' ) ||
128- ( / ^ \s * i m p o r t (? = [ { ' " * ] ) \s * (? ! [ ( ] ) / ) . test ( lineWithErr ) ) {
129+ ( RegExpPrototypeTest ( / ^ \s * i m p o r t (? = [ { ' " * ] ) \s * (? ! [ ( ] ) / , lineWithErr ) ) ) {
129130 // Emit the warning synchronously because we are in the middle of handling
130131 // a SyntaxError that will throw and likely terminate the process before an
131132 // asynchronous warning would be emitted.
@@ -352,10 +353,11 @@ const realpathCache = new Map();
352353// absolute realpath.
353354function tryFile ( requestPath , isMain ) {
354355 const rc = stat ( requestPath ) ;
356+ if ( rc !== 0 ) return ;
355357 if ( preserveSymlinks && ! isMain ) {
356- return rc === 0 && path . resolve ( requestPath ) ;
358+ return path . resolve ( requestPath ) ;
357359 }
358- return rc === 0 && toRealPath ( requestPath ) ;
360+ return toRealPath ( requestPath ) ;
359361}
360362
361363function toRealPath ( requestPath ) {
@@ -392,52 +394,7 @@ function findLongestRegisteredExtension(filename) {
392394 return '.js' ;
393395}
394396
395- function resolveBasePath ( basePath , exts , isMain , trailingSlash , request ) {
396- let filename ;
397-
398- const rc = stat ( basePath ) ;
399- if ( ! trailingSlash ) {
400- if ( rc === 0 ) { // File.
401- if ( ! isMain ) {
402- if ( preserveSymlinks ) {
403- filename = path . resolve ( basePath ) ;
404- } else {
405- filename = toRealPath ( basePath ) ;
406- }
407- } else if ( preserveSymlinksMain ) {
408- // For the main module, we use the preserveSymlinksMain flag instead
409- // mainly for backward compatibility, as the preserveSymlinks flag
410- // historically has not applied to the main module. Most likely this
411- // was intended to keep .bin/ binaries working, as following those
412- // symlinks is usually required for the imports in the corresponding
413- // files to resolve; that said, in some use cases following symlinks
414- // causes bigger problems which is why the preserveSymlinksMain option
415- // is needed.
416- filename = path . resolve ( basePath ) ;
417- } else {
418- filename = toRealPath ( basePath ) ;
419- }
420- }
421-
422- if ( ! filename ) {
423- // Try it with each of the extensions
424- if ( exts === undefined )
425- exts = ObjectKeys ( Module . _extensions ) ;
426- filename = tryExtensions ( basePath , exts , isMain ) ;
427- }
428- }
429-
430- if ( ! filename && rc === 1 ) { // Directory.
431- // try it with each of the extensions at "index"
432- if ( exts === undefined )
433- exts = ObjectKeys ( Module . _extensions ) ;
434- filename = tryPackage ( basePath , exts , isMain , request ) ;
435- }
436-
437- return filename ;
438- }
439-
440- function trySelf ( parentPath , isMain , request ) {
397+ function trySelf ( parentPath , request ) {
441398 const { data : pkg , path : basePath } = readPackageScope ( parentPath ) || { } ;
442399 if ( ! pkg || pkg . exports === undefined ) return false ;
443400 if ( typeof pkg . name !== 'string' ) return false ;
@@ -451,20 +408,11 @@ function trySelf(parentPath, isMain, request) {
451408 return false ;
452409 }
453410
454- const exts = ObjectKeys ( Module . _extensions ) ;
455411 const fromExports = applyExports ( basePath , expansion ) ;
456- // Use exports
457412 if ( fromExports ) {
458- let trailingSlash = request . length > 0 &&
459- request . charCodeAt ( request . length - 1 ) === CHAR_FORWARD_SLASH ;
460- if ( ! trailingSlash ) {
461- trailingSlash = / (?: ^ | \/ ) \. ? \. $ / . test ( request ) ;
462- }
463- return resolveBasePath ( fromExports , exts , isMain , trailingSlash , request ) ;
464- } else {
465- // Use main field
466- return tryPackage ( basePath , exts , isMain , request ) ;
413+ return tryFile ( fromExports , false ) ;
467414 }
415+ assert ( fromExports !== false ) ;
468416}
469417
470418function isConditionalDotExportSugar ( exports , basePath ) {
@@ -496,7 +444,7 @@ function applyExports(basePath, expansion) {
496444
497445 let pkgExports = readPackageExports ( basePath ) ;
498446 if ( pkgExports === undefined || pkgExports === null )
499- return path . resolve ( basePath , mappingKey ) ;
447+ return false ;
500448
501449 if ( isConditionalDotExportSugar ( pkgExports , basePath ) )
502450 pkgExports = { '.' : pkgExports } ;
@@ -520,8 +468,24 @@ function applyExports(basePath, expansion) {
520468 if ( dirMatch !== '' ) {
521469 const mapping = pkgExports [ dirMatch ] ;
522470 const subpath = StringPrototypeSlice ( mappingKey , dirMatch . length ) ;
523- return resolveExportsTarget ( pathToFileURL ( basePath + '/' ) , mapping ,
524- subpath , mappingKey ) ;
471+ const resolved = resolveExportsTarget ( pathToFileURL ( basePath + '/' ) ,
472+ mapping , subpath , mappingKey ) ;
473+ // Extension searching for folder exports only
474+ const rc = stat ( resolved ) ;
475+ if ( rc === 0 ) return resolved ;
476+ if ( ! ( RegExpPrototypeTest ( trailingSlashRegex , resolved ) ) ) {
477+ const exts = ObjectKeys ( Module . _extensions ) ;
478+ const filename = tryExtensions ( resolved , exts , false ) ;
479+ if ( filename ) return filename ;
480+ }
481+ if ( rc === 1 ) {
482+ const exts = ObjectKeys ( Module . _extensions ) ;
483+ const filename = tryPackage ( resolved , exts , false ,
484+ basePath + expansion ) ;
485+ if ( filename ) return filename ;
486+ }
487+ // Undefined means not found
488+ return ;
525489 }
526490 }
527491
@@ -532,20 +496,20 @@ function applyExports(basePath, expansion) {
532496// 1. name/.*
533497// 2. @scope/name/.*
534498const EXPORTS_PATTERN = / ^ ( (?: @ [ ^ / \\ % ] + \/ ) ? [ ^ . / \\ % ] [ ^ / \\ % ] * ) ( \/ .* ) ? $ / ;
535- function resolveExports ( nmPath , request , absoluteRequest ) {
499+ function resolveExports ( nmPath , request ) {
536500 // The implementation's behavior is meant to mirror resolution in ESM.
537- if ( ! absoluteRequest ) {
538- const [ , name , expansion = '' ] =
539- StringPrototypeMatch ( request , EXPORTS_PATTERN ) || [ ] ;
540- if ( ! name ) {
541- return path . resolve ( nmPath , request ) ;
542- }
543-
544- const basePath = path . resolve ( nmPath , name ) ;
545- return applyExports ( basePath , expansion ) ;
501+ const [ , name , expansion = '' ] =
502+ StringPrototypeMatch ( request , EXPORTS_PATTERN ) || [ ] ;
503+ if ( ! name ) {
504+ return false ;
546505 }
547506
548- return path . resolve ( nmPath , request ) ;
507+ const basePath = path . resolve ( nmPath , name ) ;
508+ const fromExports = applyExports ( basePath , expansion ) ;
509+ if ( fromExports ) {
510+ return tryFile ( fromExports , false ) ;
511+ }
512+ return fromExports ;
549513}
550514
551515function isArrayIndex ( p ) {
@@ -636,6 +600,7 @@ function resolveExportsTarget(baseUrl, target, subpath, mappingKey) {
636600 StringPrototypeSlice ( baseUrl . pathname , 0 , - 1 ) , mappingKey , subpath , target ) ;
637601}
638602
603+ const trailingSlashRegex = / (?: ^ | \/ ) \. ? \. $ / ;
639604Module . _findPath = function ( request , paths , isMain ) {
640605 const absoluteRequest = path . isAbsolute ( request ) ;
641606 if ( absoluteRequest ) {
@@ -654,15 +619,26 @@ Module._findPath = function(request, paths, isMain) {
654619 let trailingSlash = request . length > 0 &&
655620 request . charCodeAt ( request . length - 1 ) === CHAR_FORWARD_SLASH ;
656621 if ( ! trailingSlash ) {
657- trailingSlash = / (?: ^ | \/ ) \. ? \. $ / . test ( request ) ;
622+ trailingSlash = RegExpPrototypeTest ( trailingSlashRegex , request ) ;
658623 }
659624
660625 // For each path
661626 for ( let i = 0 ; i < paths . length ; i ++ ) {
662627 // Don't search further if path doesn't exist
663628 const curPath = paths [ i ] ;
664629 if ( curPath && stat ( curPath ) < 1 ) continue ;
665- const basePath = resolveExports ( curPath , request , absoluteRequest ) ;
630+
631+ if ( ! absoluteRequest ) {
632+ const exportsResolved = resolveExports ( curPath , request ) ;
633+ // Undefined means not found, false means no exports
634+ if ( exportsResolved === undefined )
635+ break ;
636+ if ( exportsResolved ) {
637+ return exportsResolved ;
638+ }
639+ }
640+
641+ const basePath = path . resolve ( curPath , request ) ;
666642 let filename ;
667643
668644 const rc = stat ( basePath ) ;
@@ -1005,7 +981,7 @@ Module._resolveFilename = function(request, parent, isMain, options) {
1005981 }
1006982
1007983 if ( parent && parent . filename ) {
1008- const filename = trySelf ( parent . filename , isMain , request ) ;
984+ const filename = trySelf ( parent . filename , request ) ;
1009985 if ( filename ) {
1010986 const cacheKey = request + '\x00' +
1011987 ( paths . length === 1 ? paths [ 0 ] : paths . join ( '\x00' ) ) ;
0 commit comments