@@ -58,6 +58,7 @@ const enableSourceMaps = getOptionValue('--enable-source-maps');
58
58
const preserveSymlinks = getOptionValue ( '--preserve-symlinks' ) ;
59
59
const preserveSymlinksMain = getOptionValue ( '--preserve-symlinks-main' ) ;
60
60
const experimentalModules = getOptionValue ( '--experimental-modules' ) ;
61
+ const experimentalSelf = getOptionValue ( '--experimental-resolve-self' ) ;
61
62
const manifest = getOptionValue ( '--experimental-policy' ) ?
62
63
require ( 'internal/process/policy' ) . manifest :
63
64
null ;
@@ -241,6 +242,7 @@ function readPackage(requestPath) {
241
242
try {
242
243
const parsed = JSON . parse ( json ) ;
243
244
const filtered = {
245
+ name : parsed . name ,
244
246
main : parsed . main ,
245
247
exports : parsed . exports ,
246
248
type : parsed . type
@@ -370,6 +372,125 @@ function findLongestRegisteredExtension(filename) {
370
372
return '.js' ;
371
373
}
372
374
375
+ function resolveBasePath ( basePath , exts , isMain , trailingSlash , request ) {
376
+ let filename ;
377
+
378
+ const rc = stat ( basePath ) ;
379
+ if ( ! trailingSlash ) {
380
+ if ( rc === 0 ) { // File.
381
+ if ( ! isMain ) {
382
+ if ( preserveSymlinks ) {
383
+ filename = path . resolve ( basePath ) ;
384
+ } else {
385
+ filename = toRealPath ( basePath ) ;
386
+ }
387
+ } else if ( preserveSymlinksMain ) {
388
+ // For the main module, we use the preserveSymlinksMain flag instead
389
+ // mainly for backward compatibility, as the preserveSymlinks flag
390
+ // historically has not applied to the main module. Most likely this
391
+ // was intended to keep .bin/ binaries working, as following those
392
+ // symlinks is usually required for the imports in the corresponding
393
+ // files to resolve; that said, in some use cases following symlinks
394
+ // causes bigger problems which is why the preserveSymlinksMain option
395
+ // is needed.
396
+ filename = path . resolve ( basePath ) ;
397
+ } else {
398
+ filename = toRealPath ( basePath ) ;
399
+ }
400
+ }
401
+
402
+ if ( ! filename ) {
403
+ // Try it with each of the extensions
404
+ if ( exts === undefined )
405
+ exts = Object . keys ( Module . _extensions ) ;
406
+ filename = tryExtensions ( basePath , exts , isMain ) ;
407
+ }
408
+ }
409
+
410
+ if ( ! filename && rc === 1 ) { // Directory.
411
+ // try it with each of the extensions at "index"
412
+ if ( exts === undefined )
413
+ exts = Object . keys ( Module . _extensions ) ;
414
+ filename = tryPackage ( basePath , exts , isMain , request ) ;
415
+ }
416
+
417
+ return filename ;
418
+ }
419
+
420
+ function trySelf ( paths , exts , isMain , trailingSlash , request ) {
421
+ if ( ! experimentalSelf ) {
422
+ return false ;
423
+ }
424
+
425
+ const { data : pkg , path : basePath } = readPackageScope ( paths [ 0 ] ) ;
426
+ if ( ! pkg ) return false ;
427
+ if ( typeof pkg . name !== 'string' ) return false ;
428
+
429
+ let expansion ;
430
+ if ( request === pkg . name ) {
431
+ expansion = '' ;
432
+ } else if ( StringPrototype . startsWith ( request , `${ pkg . name } /` ) ) {
433
+ expansion = StringPrototype . slice ( request , pkg . name . length ) ;
434
+ } else {
435
+ return false ;
436
+ }
437
+
438
+ if ( exts === undefined )
439
+ exts = Object . keys ( Module . _extensions ) ;
440
+
441
+ if ( expansion ) {
442
+ // Use exports
443
+ const fromExports = applyExports ( basePath , expansion ) ;
444
+ if ( ! fromExports ) return false ;
445
+ return resolveBasePath ( fromExports , exts , isMain , trailingSlash , request ) ;
446
+ } else {
447
+ // Use main field
448
+ return tryPackage ( basePath , exts , isMain , request ) ;
449
+ }
450
+ }
451
+
452
+ function applyExports ( basePath , expansion ) {
453
+ const pkgExports = readPackageExports ( basePath ) ;
454
+ const mappingKey = `.${ expansion } ` ;
455
+
456
+ if ( typeof pkgExports === 'object' && pkgExports !== null ) {
457
+ if ( ObjectPrototype . hasOwnProperty ( pkgExports , mappingKey ) ) {
458
+ const mapping = pkgExports [ mappingKey ] ;
459
+ return resolveExportsTarget ( pathToFileURL ( basePath + '/' ) , mapping , '' ,
460
+ basePath , mappingKey ) ;
461
+ }
462
+
463
+ let dirMatch = '' ;
464
+ for ( const candidateKey of Object . keys ( pkgExports ) ) {
465
+ if ( candidateKey [ candidateKey . length - 1 ] !== '/' ) continue ;
466
+ if ( candidateKey . length > dirMatch . length &&
467
+ StringPrototype . startsWith ( mappingKey , candidateKey ) ) {
468
+ dirMatch = candidateKey ;
469
+ }
470
+ }
471
+
472
+ if ( dirMatch !== '' ) {
473
+ const mapping = pkgExports [ dirMatch ] ;
474
+ const subpath = StringPrototype . slice ( mappingKey , dirMatch . length ) ;
475
+ return resolveExportsTarget ( pathToFileURL ( basePath + '/' ) , mapping ,
476
+ subpath , basePath , mappingKey ) ;
477
+ }
478
+ }
479
+ if ( mappingKey === '.' && typeof pkgExports === 'string' ) {
480
+ return resolveExportsTarget ( pathToFileURL ( basePath + '/' ) , pkgExports ,
481
+ '' , basePath , mappingKey ) ;
482
+ }
483
+ if ( pkgExports != null ) {
484
+ // eslint-disable-next-line no-restricted-syntax
485
+ const e = new Error ( `Package exports for '${ basePath } ' do not define ` +
486
+ `a '${ mappingKey } ' subpath` ) ;
487
+ e . code = 'MODULE_NOT_FOUND' ;
488
+ throw e ;
489
+ }
490
+
491
+ return path . resolve ( basePath , mappingKey ) ;
492
+ }
493
+
373
494
// This only applies to requests of a specific form:
374
495
// 1. name/.*
375
496
// 2. @scope/name/.*
@@ -384,43 +505,7 @@ function resolveExports(nmPath, request, absoluteRequest) {
384
505
}
385
506
386
507
const basePath = path . resolve ( nmPath , name ) ;
387
- const pkgExports = readPackageExports ( basePath ) ;
388
- const mappingKey = `.${ expansion } ` ;
389
-
390
- if ( typeof pkgExports === 'object' && pkgExports !== null ) {
391
- if ( ObjectPrototype . hasOwnProperty ( pkgExports , mappingKey ) ) {
392
- const mapping = pkgExports [ mappingKey ] ;
393
- return resolveExportsTarget ( pathToFileURL ( basePath + '/' ) , mapping , '' ,
394
- basePath , mappingKey ) ;
395
- }
396
-
397
- let dirMatch = '' ;
398
- for ( const candidateKey of Object . keys ( pkgExports ) ) {
399
- if ( candidateKey [ candidateKey . length - 1 ] !== '/' ) continue ;
400
- if ( candidateKey . length > dirMatch . length &&
401
- StringPrototype . startsWith ( mappingKey , candidateKey ) ) {
402
- dirMatch = candidateKey ;
403
- }
404
- }
405
-
406
- if ( dirMatch !== '' ) {
407
- const mapping = pkgExports [ dirMatch ] ;
408
- const subpath = StringPrototype . slice ( mappingKey , dirMatch . length ) ;
409
- return resolveExportsTarget ( pathToFileURL ( basePath + '/' ) , mapping ,
410
- subpath , basePath , mappingKey ) ;
411
- }
412
- }
413
- if ( mappingKey === '.' && typeof pkgExports === 'string' ) {
414
- return resolveExportsTarget ( pathToFileURL ( basePath + '/' ) , pkgExports ,
415
- '' , basePath , mappingKey ) ;
416
- }
417
- if ( pkgExports != null ) {
418
- // eslint-disable-next-line no-restricted-syntax
419
- const e = new Error ( `Package exports for '${ basePath } ' do not define ` +
420
- `a '${ mappingKey } ' subpath` ) ;
421
- e . code = 'MODULE_NOT_FOUND' ;
422
- throw e ;
423
- }
508
+ return applyExports ( basePath , expansion ) ;
424
509
}
425
510
426
511
return path . resolve ( nmPath , request ) ;
@@ -536,6 +621,13 @@ Module._findPath = function(request, paths, isMain) {
536
621
return filename ;
537
622
}
538
623
}
624
+
625
+ const selfFilename = trySelf ( paths , exts , isMain , trailingSlash , request ) ;
626
+ if ( selfFilename ) {
627
+ Module . _pathCache [ cacheKey ] = selfFilename ;
628
+ return selfFilename ;
629
+ }
630
+
539
631
return false ;
540
632
} ;
541
633
0 commit comments