@@ -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,
@@ -122,7 +123,10 @@ function enrichCJSError(err) {
122
123
after a comment block and/or after a variable definition.
123
124
*/
124
125
if ( err . message . startsWith ( 'Unexpected token \'export\'' ) ||
125
- ( / ^ \s * i m p o r t (? = [ { ' " * ] ) \s * (? ! [ ( ] ) / ) . test ( lineWithErr ) ) {
126
+ ( RegExpPrototypeTest ( / ^ \s * i m p o r t (? = [ { ' " * ] ) \s * (? ! [ ( ] ) / , lineWithErr ) ) ) {
127
+ // Emit the warning synchronously because we are in the middle of handling
128
+ // a SyntaxError that will throw and likely terminate the process before an
129
+ // asynchronous warning would be emitted.
126
130
process . emitWarning (
127
131
'To load an ES module, set "type": "module" in the package.json or use ' +
128
132
'the .mjs extension.' ,
@@ -349,10 +353,11 @@ const realpathCache = new Map();
349
353
// absolute realpath.
350
354
function tryFile ( requestPath , isMain ) {
351
355
const rc = stat ( requestPath ) ;
356
+ if ( rc !== 0 ) return ;
352
357
if ( preserveSymlinks && ! isMain ) {
353
- return rc === 0 && path . resolve ( requestPath ) ;
358
+ return path . resolve ( requestPath ) ;
354
359
}
355
- return rc === 0 && toRealPath ( requestPath ) ;
360
+ return toRealPath ( requestPath ) ;
356
361
}
357
362
358
363
function toRealPath ( requestPath ) {
@@ -389,52 +394,7 @@ function findLongestRegisteredExtension(filename) {
389
394
return '.js' ;
390
395
}
391
396
392
- function resolveBasePath ( basePath , exts , isMain , trailingSlash , request ) {
393
- let filename ;
394
-
395
- const rc = stat ( basePath ) ;
396
- if ( ! trailingSlash ) {
397
- if ( rc === 0 ) { // File.
398
- if ( ! isMain ) {
399
- if ( preserveSymlinks ) {
400
- filename = path . resolve ( basePath ) ;
401
- } else {
402
- filename = toRealPath ( basePath ) ;
403
- }
404
- } else if ( preserveSymlinksMain ) {
405
- // For the main module, we use the preserveSymlinksMain flag instead
406
- // mainly for backward compatibility, as the preserveSymlinks flag
407
- // historically has not applied to the main module. Most likely this
408
- // was intended to keep .bin/ binaries working, as following those
409
- // symlinks is usually required for the imports in the corresponding
410
- // files to resolve; that said, in some use cases following symlinks
411
- // causes bigger problems which is why the preserveSymlinksMain option
412
- // is needed.
413
- filename = path . resolve ( basePath ) ;
414
- } else {
415
- filename = toRealPath ( basePath ) ;
416
- }
417
- }
418
-
419
- if ( ! filename ) {
420
- // Try it with each of the extensions
421
- if ( exts === undefined )
422
- exts = ObjectKeys ( Module . _extensions ) ;
423
- filename = tryExtensions ( basePath , exts , isMain ) ;
424
- }
425
- }
426
-
427
- if ( ! filename && rc === 1 ) { // Directory.
428
- // try it with each of the extensions at "index"
429
- if ( exts === undefined )
430
- exts = ObjectKeys ( Module . _extensions ) ;
431
- filename = tryPackage ( basePath , exts , isMain , request ) ;
432
- }
433
-
434
- return filename ;
435
- }
436
-
437
- function trySelf ( parentPath , isMain , request ) {
397
+ function trySelf ( parentPath , request ) {
438
398
if ( ! experimentalModules ) return false ;
439
399
const { data : pkg , path : basePath } = readPackageScope ( parentPath ) || { } ;
440
400
if ( ! pkg || pkg . exports === undefined ) return false ;
@@ -449,20 +409,11 @@ function trySelf(parentPath, isMain, request) {
449
409
return false ;
450
410
}
451
411
452
- const exts = ObjectKeys ( Module . _extensions ) ;
453
412
const fromExports = applyExports ( basePath , expansion ) ;
454
- // Use exports
455
413
if ( fromExports ) {
456
- let trailingSlash = request . length > 0 &&
457
- request . charCodeAt ( request . length - 1 ) === CHAR_FORWARD_SLASH ;
458
- if ( ! trailingSlash ) {
459
- trailingSlash = / (?: ^ | \/ ) \. ? \. $ / . test ( request ) ;
460
- }
461
- return resolveBasePath ( fromExports , exts , isMain , trailingSlash , request ) ;
462
- } else {
463
- // Use main field
464
- return tryPackage ( basePath , exts , isMain , request ) ;
414
+ return tryFile ( fromExports , false ) ;
465
415
}
416
+ assert ( fromExports !== false ) ;
466
417
}
467
418
468
419
function isConditionalDotExportSugar ( exports , basePath ) {
@@ -494,7 +445,7 @@ function applyExports(basePath, expansion) {
494
445
495
446
let pkgExports = readPackageExports ( basePath ) ;
496
447
if ( pkgExports === undefined || pkgExports === null || ! experimentalModules )
497
- return path . resolve ( basePath , mappingKey ) ;
448
+ return false ;
498
449
499
450
if ( isConditionalDotExportSugar ( pkgExports , basePath ) )
500
451
pkgExports = { '.' : pkgExports } ;
@@ -518,8 +469,24 @@ function applyExports(basePath, expansion) {
518
469
if ( dirMatch !== '' ) {
519
470
const mapping = pkgExports [ dirMatch ] ;
520
471
const subpath = StringPrototypeSlice ( mappingKey , dirMatch . length ) ;
521
- return resolveExportsTarget ( pathToFileURL ( basePath + '/' ) , mapping ,
522
- subpath , mappingKey ) ;
472
+ const resolved = resolveExportsTarget ( pathToFileURL ( basePath + '/' ) ,
473
+ mapping , subpath , mappingKey ) ;
474
+ // Extension searching for folder exports only
475
+ const rc = stat ( resolved ) ;
476
+ if ( rc === 0 ) return resolved ;
477
+ if ( ! ( RegExpPrototypeTest ( trailingSlashRegex , resolved ) ) ) {
478
+ const exts = ObjectKeys ( Module . _extensions ) ;
479
+ const filename = tryExtensions ( resolved , exts , false ) ;
480
+ if ( filename ) return filename ;
481
+ }
482
+ if ( rc === 1 ) {
483
+ const exts = ObjectKeys ( Module . _extensions ) ;
484
+ const filename = tryPackage ( resolved , exts , false ,
485
+ basePath + expansion ) ;
486
+ if ( filename ) return filename ;
487
+ }
488
+ // Undefined means not found
489
+ return ;
523
490
}
524
491
}
525
492
@@ -530,20 +497,20 @@ function applyExports(basePath, expansion) {
530
497
// 1. name/.*
531
498
// 2. @scope/name/.*
532
499
const EXPORTS_PATTERN = / ^ ( (?: @ [ ^ / \\ % ] + \/ ) ? [ ^ . / \\ % ] [ ^ / \\ % ] * ) ( \/ .* ) ? $ / ;
533
- function resolveExports ( nmPath , request , absoluteRequest ) {
500
+ function resolveExports ( nmPath , request ) {
534
501
// The implementation's behavior is meant to mirror resolution in ESM.
535
- if ( ! absoluteRequest ) {
536
- const [ , name , expansion = '' ] =
537
- StringPrototypeMatch ( request , EXPORTS_PATTERN ) || [ ] ;
538
- if ( ! name ) {
539
- return path . resolve ( nmPath , request ) ;
540
- }
541
-
542
- const basePath = path . resolve ( nmPath , name ) ;
543
- return applyExports ( basePath , expansion ) ;
502
+ const [ , name , expansion = '' ] =
503
+ StringPrototypeMatch ( request , EXPORTS_PATTERN ) || [ ] ;
504
+ if ( ! name ) {
505
+ return false ;
544
506
}
545
507
546
- return path . resolve ( nmPath , request ) ;
508
+ const basePath = path . resolve ( nmPath , name ) ;
509
+ const fromExports = applyExports ( basePath , expansion ) ;
510
+ if ( fromExports ) {
511
+ return tryFile ( fromExports , false ) ;
512
+ }
513
+ return fromExports ;
547
514
}
548
515
549
516
function isArrayIndex ( p ) {
@@ -635,6 +602,7 @@ function resolveExportsTarget(baseUrl, target, subpath, mappingKey) {
635
602
StringPrototypeSlice ( baseUrl . pathname , 0 , - 1 ) , mappingKey , subpath , target ) ;
636
603
}
637
604
605
+ const trailingSlashRegex = / (?: ^ | \/ ) \. ? \. $ / ;
638
606
Module . _findPath = function ( request , paths , isMain ) {
639
607
const absoluteRequest = path . isAbsolute ( request ) ;
640
608
if ( absoluteRequest ) {
@@ -653,15 +621,26 @@ Module._findPath = function(request, paths, isMain) {
653
621
let trailingSlash = request . length > 0 &&
654
622
request . charCodeAt ( request . length - 1 ) === CHAR_FORWARD_SLASH ;
655
623
if ( ! trailingSlash ) {
656
- trailingSlash = / (?: ^ | \/ ) \. ? \. $ / . test ( request ) ;
624
+ trailingSlash = RegExpPrototypeTest ( trailingSlashRegex , request ) ;
657
625
}
658
626
659
627
// For each path
660
628
for ( let i = 0 ; i < paths . length ; i ++ ) {
661
629
// Don't search further if path doesn't exist
662
630
const curPath = paths [ i ] ;
663
631
if ( curPath && stat ( curPath ) < 1 ) continue ;
664
- const basePath = resolveExports ( curPath , request , absoluteRequest ) ;
632
+
633
+ if ( ! absoluteRequest ) {
634
+ const exportsResolved = resolveExports ( curPath , request ) ;
635
+ // Undefined means not found, false means no exports
636
+ if ( exportsResolved === undefined )
637
+ break ;
638
+ if ( exportsResolved ) {
639
+ return exportsResolved ;
640
+ }
641
+ }
642
+
643
+ const basePath = path . resolve ( curPath , request ) ;
665
644
let filename ;
666
645
667
646
const rc = stat ( basePath ) ;
@@ -953,7 +932,7 @@ Module._resolveFilename = function(request, parent, isMain, options) {
953
932
}
954
933
955
934
if ( parent && parent . filename ) {
956
- const filename = trySelf ( parent . filename , isMain , request ) ;
935
+ const filename = trySelf ( parent . filename , request ) ;
957
936
if ( filename ) {
958
937
emitExperimentalWarning ( 'Package name self resolution' ) ;
959
938
const cacheKey = request + '\x00' +
0 commit comments