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