@@ -37,6 +37,7 @@ const {
37
37
ObjectPrototypeHasOwnProperty,
38
38
ObjectSetPrototypeOf,
39
39
ReflectSet,
40
+ RegExpPrototypeTest,
40
41
SafeMap,
41
42
String,
42
43
StringPrototypeIndexOf,
@@ -125,7 +126,7 @@ function enrichCJSError(err) {
125
126
after a comment block and/or after a variable definition.
126
127
*/
127
128
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 ) ) ) {
129
130
// Emit the warning synchronously because we are in the middle of handling
130
131
// a SyntaxError that will throw and likely terminate the process before an
131
132
// asynchronous warning would be emitted.
@@ -352,10 +353,11 @@ const realpathCache = new Map();
352
353
// absolute realpath.
353
354
function tryFile ( requestPath , isMain ) {
354
355
const rc = stat ( requestPath ) ;
356
+ if ( rc !== 0 ) return ;
355
357
if ( preserveSymlinks && ! isMain ) {
356
- return rc === 0 && path . resolve ( requestPath ) ;
358
+ return path . resolve ( requestPath ) ;
357
359
}
358
- return rc === 0 && toRealPath ( requestPath ) ;
360
+ return toRealPath ( requestPath ) ;
359
361
}
360
362
361
363
function toRealPath ( requestPath ) {
@@ -392,52 +394,7 @@ function findLongestRegisteredExtension(filename) {
392
394
return '.js' ;
393
395
}
394
396
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 ) {
441
398
const { data : pkg , path : basePath } = readPackageScope ( parentPath ) || { } ;
442
399
if ( ! pkg || pkg . exports === undefined ) return false ;
443
400
if ( typeof pkg . name !== 'string' ) return false ;
@@ -451,20 +408,11 @@ function trySelf(parentPath, isMain, request) {
451
408
return false ;
452
409
}
453
410
454
- const exts = ObjectKeys ( Module . _extensions ) ;
455
411
const fromExports = applyExports ( basePath , expansion ) ;
456
- // Use exports
457
412
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 ) ;
467
414
}
415
+ assert ( fromExports !== false ) ;
468
416
}
469
417
470
418
function isConditionalDotExportSugar ( exports , basePath ) {
@@ -496,7 +444,7 @@ function applyExports(basePath, expansion) {
496
444
497
445
let pkgExports = readPackageExports ( basePath ) ;
498
446
if ( pkgExports === undefined || pkgExports === null )
499
- return path . resolve ( basePath , mappingKey ) ;
447
+ return false ;
500
448
501
449
if ( isConditionalDotExportSugar ( pkgExports , basePath ) )
502
450
pkgExports = { '.' : pkgExports } ;
@@ -520,8 +468,24 @@ function applyExports(basePath, expansion) {
520
468
if ( dirMatch !== '' ) {
521
469
const mapping = pkgExports [ dirMatch ] ;
522
470
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 ;
525
489
}
526
490
}
527
491
@@ -532,20 +496,20 @@ function applyExports(basePath, expansion) {
532
496
// 1. name/.*
533
497
// 2. @scope/name/.*
534
498
const EXPORTS_PATTERN = / ^ ( (?: @ [ ^ / \\ % ] + \/ ) ? [ ^ . / \\ % ] [ ^ / \\ % ] * ) ( \/ .* ) ? $ / ;
535
- function resolveExports ( nmPath , request , absoluteRequest ) {
499
+ function resolveExports ( nmPath , request ) {
536
500
// 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 ;
546
505
}
547
506
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 ;
549
513
}
550
514
551
515
function isArrayIndex ( p ) {
@@ -636,6 +600,7 @@ function resolveExportsTarget(baseUrl, target, subpath, mappingKey) {
636
600
StringPrototypeSlice ( baseUrl . pathname , 0 , - 1 ) , mappingKey , subpath , target ) ;
637
601
}
638
602
603
+ const trailingSlashRegex = / (?: ^ | \/ ) \. ? \. $ / ;
639
604
Module . _findPath = function ( request , paths , isMain ) {
640
605
const absoluteRequest = path . isAbsolute ( request ) ;
641
606
if ( absoluteRequest ) {
@@ -654,15 +619,26 @@ Module._findPath = function(request, paths, isMain) {
654
619
let trailingSlash = request . length > 0 &&
655
620
request . charCodeAt ( request . length - 1 ) === CHAR_FORWARD_SLASH ;
656
621
if ( ! trailingSlash ) {
657
- trailingSlash = / (?: ^ | \/ ) \. ? \. $ / . test ( request ) ;
622
+ trailingSlash = RegExpPrototypeTest ( trailingSlashRegex , request ) ;
658
623
}
659
624
660
625
// For each path
661
626
for ( let i = 0 ; i < paths . length ; i ++ ) {
662
627
// Don't search further if path doesn't exist
663
628
const curPath = paths [ i ] ;
664
629
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 ) ;
666
642
let filename ;
667
643
668
644
const rc = stat ( basePath ) ;
@@ -1005,7 +981,7 @@ Module._resolveFilename = function(request, parent, isMain, options) {
1005
981
}
1006
982
1007
983
if ( parent && parent . filename ) {
1008
- const filename = trySelf ( parent . filename , isMain , request ) ;
984
+ const filename = trySelf ( parent . filename , request ) ;
1009
985
if ( filename ) {
1010
986
const cacheKey = request + '\x00' +
1011
987
( paths . length === 1 ? paths [ 0 ] : paths . join ( '\x00' ) ) ;
0 commit comments