@@ -34,6 +34,7 @@ const {
34
34
ObjectKeys,
35
35
ObjectPrototypeHasOwnProperty,
36
36
ReflectSet,
37
+ RegExpPrototypeTest,
37
38
SafeMap,
38
39
String,
39
40
StringPrototypeIndexOf,
@@ -121,7 +122,7 @@ function enrichCJSError(err) {
121
122
after a comment block and/or after a variable definition.
122
123
*/
123
124
if ( err . message . startsWith ( 'Unexpected token \'export\'' ) ||
124
- ( / ^ \s * i m p o r t (? = [ { ' " * ] ) \s * (? ! [ ( ] ) / ) . test ( lineWithErr ) ) {
125
+ ( RegExpPrototypeTest ( / ^ \s * i m p o r t (? = [ { ' " * ] ) \s * (? ! [ ( ] ) / , lineWithErr ) ) ) {
125
126
process . emitWarning (
126
127
'To load an ES module, set "type": "module" in the package.json or use ' +
127
128
'the .mjs extension.' ,
@@ -348,10 +349,11 @@ const realpathCache = new Map();
348
349
// absolute realpath.
349
350
function tryFile ( requestPath , isMain ) {
350
351
const rc = stat ( requestPath ) ;
352
+ if ( rc !== 0 ) return ;
351
353
if ( preserveSymlinks && ! isMain ) {
352
- return rc === 0 && path . resolve ( requestPath ) ;
354
+ return path . resolve ( requestPath ) ;
353
355
}
354
- return rc === 0 && toRealPath ( requestPath ) ;
356
+ return toRealPath ( requestPath ) ;
355
357
}
356
358
357
359
function toRealPath ( requestPath ) {
@@ -388,52 +390,7 @@ function findLongestRegisteredExtension(filename) {
388
390
return '.js' ;
389
391
}
390
392
391
- function resolveBasePath ( basePath , exts , isMain , trailingSlash , request ) {
392
- let filename ;
393
-
394
- const rc = stat ( basePath ) ;
395
- if ( ! trailingSlash ) {
396
- if ( rc === 0 ) { // File.
397
- if ( ! isMain ) {
398
- if ( preserveSymlinks ) {
399
- filename = path . resolve ( basePath ) ;
400
- } else {
401
- filename = toRealPath ( basePath ) ;
402
- }
403
- } else if ( preserveSymlinksMain ) {
404
- // For the main module, we use the preserveSymlinksMain flag instead
405
- // mainly for backward compatibility, as the preserveSymlinks flag
406
- // historically has not applied to the main module. Most likely this
407
- // was intended to keep .bin/ binaries working, as following those
408
- // symlinks is usually required for the imports in the corresponding
409
- // files to resolve; that said, in some use cases following symlinks
410
- // causes bigger problems which is why the preserveSymlinksMain option
411
- // is needed.
412
- filename = path . resolve ( basePath ) ;
413
- } else {
414
- filename = toRealPath ( basePath ) ;
415
- }
416
- }
417
-
418
- if ( ! filename ) {
419
- // Try it with each of the extensions
420
- if ( exts === undefined )
421
- exts = ObjectKeys ( Module . _extensions ) ;
422
- filename = tryExtensions ( basePath , exts , isMain ) ;
423
- }
424
- }
425
-
426
- if ( ! filename && rc === 1 ) { // Directory.
427
- // try it with each of the extensions at "index"
428
- if ( exts === undefined )
429
- exts = ObjectKeys ( Module . _extensions ) ;
430
- filename = tryPackage ( basePath , exts , isMain , request ) ;
431
- }
432
-
433
- return filename ;
434
- }
435
-
436
- function trySelf ( parentPath , isMain , request ) {
393
+ function trySelf ( parentPath , request ) {
437
394
const { data : pkg , path : basePath } = readPackageScope ( parentPath ) || { } ;
438
395
if ( ! pkg || pkg . exports === undefined ) return false ;
439
396
if ( typeof pkg . name !== 'string' ) return false ;
@@ -447,20 +404,11 @@ function trySelf(parentPath, isMain, request) {
447
404
return false ;
448
405
}
449
406
450
- const exts = ObjectKeys ( Module . _extensions ) ;
451
407
const fromExports = applyExports ( basePath , expansion ) ;
452
- // Use exports
453
408
if ( fromExports ) {
454
- let trailingSlash = request . length > 0 &&
455
- request . charCodeAt ( request . length - 1 ) === CHAR_FORWARD_SLASH ;
456
- if ( ! trailingSlash ) {
457
- trailingSlash = / (?: ^ | \/ ) \. ? \. $ / . test ( request ) ;
458
- }
459
- return resolveBasePath ( fromExports , exts , isMain , trailingSlash , request ) ;
460
- } else {
461
- // Use main field
462
- return tryPackage ( basePath , exts , isMain , request ) ;
409
+ return tryFile ( fromExports , false ) ;
463
410
}
411
+ assert ( fromExports !== false ) ;
464
412
}
465
413
466
414
function isConditionalDotExportSugar ( exports , basePath ) {
@@ -492,7 +440,7 @@ function applyExports(basePath, expansion) {
492
440
493
441
let pkgExports = readPackageExports ( basePath ) ;
494
442
if ( pkgExports === undefined || pkgExports === null )
495
- return path . resolve ( basePath , mappingKey ) ;
443
+ return false ;
496
444
497
445
if ( isConditionalDotExportSugar ( pkgExports , basePath ) )
498
446
pkgExports = { '.' : pkgExports } ;
@@ -516,8 +464,24 @@ function applyExports(basePath, expansion) {
516
464
if ( dirMatch !== '' ) {
517
465
const mapping = pkgExports [ dirMatch ] ;
518
466
const subpath = StringPrototypeSlice ( mappingKey , dirMatch . length ) ;
519
- return resolveExportsTarget ( pathToFileURL ( basePath + '/' ) , mapping ,
520
- subpath , mappingKey ) ;
467
+ const resolved = resolveExportsTarget ( pathToFileURL ( basePath + '/' ) ,
468
+ mapping , subpath , mappingKey ) ;
469
+ // Extension searching for folder exports only
470
+ const rc = stat ( resolved ) ;
471
+ if ( rc === 0 ) return resolved ;
472
+ if ( ! ( RegExpPrototypeTest ( trailingSlashRegex , resolved ) ) ) {
473
+ const exts = ObjectKeys ( Module . _extensions ) ;
474
+ const filename = tryExtensions ( resolved , exts , false ) ;
475
+ if ( filename ) return filename ;
476
+ }
477
+ if ( rc === 1 ) {
478
+ const exts = ObjectKeys ( Module . _extensions ) ;
479
+ const filename = tryPackage ( resolved , exts , false ,
480
+ basePath + expansion ) ;
481
+ if ( filename ) return filename ;
482
+ }
483
+ // Undefined means not found
484
+ return ;
521
485
}
522
486
}
523
487
@@ -528,20 +492,20 @@ function applyExports(basePath, expansion) {
528
492
// 1. name/.*
529
493
// 2. @scope/name/.*
530
494
const EXPORTS_PATTERN = / ^ ( (?: @ [ ^ / \\ % ] + \/ ) ? [ ^ . / \\ % ] [ ^ / \\ % ] * ) ( \/ .* ) ? $ / ;
531
- function resolveExports ( nmPath , request , absoluteRequest ) {
495
+ function resolveExports ( nmPath , request ) {
532
496
// The implementation's behavior is meant to mirror resolution in ESM.
533
- if ( ! absoluteRequest ) {
534
- const [ , name , expansion = '' ] =
535
- StringPrototypeMatch ( request , EXPORTS_PATTERN ) || [ ] ;
536
- if ( ! name ) {
537
- return path . resolve ( nmPath , request ) ;
538
- }
539
-
540
- const basePath = path . resolve ( nmPath , name ) ;
541
- return applyExports ( basePath , expansion ) ;
497
+ const [ , name , expansion = '' ] =
498
+ StringPrototypeMatch ( request , EXPORTS_PATTERN ) || [ ] ;
499
+ if ( ! name ) {
500
+ return false ;
542
501
}
543
502
544
- return path . resolve ( nmPath , request ) ;
503
+ const basePath = path . resolve ( nmPath , name ) ;
504
+ const fromExports = applyExports ( basePath , expansion ) ;
505
+ if ( fromExports ) {
506
+ return tryFile ( fromExports , false ) ;
507
+ }
508
+ return fromExports ;
545
509
}
546
510
547
511
function isArrayIndex ( p ) {
@@ -632,6 +596,7 @@ function resolveExportsTarget(baseUrl, target, subpath, mappingKey) {
632
596
StringPrototypeSlice ( baseUrl . pathname , 0 , - 1 ) , mappingKey , subpath , target ) ;
633
597
}
634
598
599
+ const trailingSlashRegex = / (?: ^ | \/ ) \. ? \. $ / ;
635
600
Module . _findPath = function ( request , paths , isMain ) {
636
601
const absoluteRequest = path . isAbsolute ( request ) ;
637
602
if ( absoluteRequest ) {
@@ -650,15 +615,26 @@ Module._findPath = function(request, paths, isMain) {
650
615
let trailingSlash = request . length > 0 &&
651
616
request . charCodeAt ( request . length - 1 ) === CHAR_FORWARD_SLASH ;
652
617
if ( ! trailingSlash ) {
653
- trailingSlash = / (?: ^ | \/ ) \. ? \. $ / . test ( request ) ;
618
+ trailingSlash = RegExpPrototypeTest ( trailingSlashRegex , request ) ;
654
619
}
655
620
656
621
// For each path
657
622
for ( let i = 0 ; i < paths . length ; i ++ ) {
658
623
// Don't search further if path doesn't exist
659
624
const curPath = paths [ i ] ;
660
625
if ( curPath && stat ( curPath ) < 1 ) continue ;
661
- const basePath = resolveExports ( curPath , request , absoluteRequest ) ;
626
+
627
+ if ( ! absoluteRequest ) {
628
+ const exportsResolved = resolveExports ( curPath , request ) ;
629
+ // Undefined means not found, false means no exports
630
+ if ( exportsResolved === undefined )
631
+ break ;
632
+ if ( exportsResolved ) {
633
+ return exportsResolved ;
634
+ }
635
+ }
636
+
637
+ const basePath = path . resolve ( curPath , request ) ;
662
638
let filename ;
663
639
664
640
const rc = stat ( basePath ) ;
@@ -950,7 +926,7 @@ Module._resolveFilename = function(request, parent, isMain, options) {
950
926
}
951
927
952
928
if ( parent && parent . filename ) {
953
- const filename = trySelf ( parent . filename , isMain , request ) ;
929
+ const filename = trySelf ( parent . filename , request ) ;
954
930
if ( filename ) {
955
931
const cacheKey = request + '\x00' +
956
932
( paths . length === 1 ? paths [ 0 ] : paths . join ( '\x00' ) ) ;
0 commit comments