@@ -340,10 +340,7 @@ namespace ts {
340
340
}
341
341
342
342
const failedLookupLocations : string [ ] = [ ] ;
343
- const features =
344
- getEmitModuleResolutionKind ( options ) === ModuleResolutionKind . Node12 ? NodeResolutionFeatures . Node12Default :
345
- getEmitModuleResolutionKind ( options ) === ModuleResolutionKind . NodeNext ? NodeResolutionFeatures . NodeNextDefault :
346
- NodeResolutionFeatures . None ;
343
+ const features = getDefaultNodeResolutionFeatures ( options ) ;
347
344
const moduleResolutionState : ModuleResolutionState = { compilerOptions : options , host, traceEnabled, failedLookupLocations, packageJsonInfoCache : cache , features, conditions : [ "node" , "require" , "types" ] } ;
348
345
let resolved = primaryLookup ( ) ;
349
346
let primary = true ;
@@ -433,6 +430,42 @@ namespace ts {
433
430
}
434
431
}
435
432
433
+ function getDefaultNodeResolutionFeatures ( options : CompilerOptions ) {
434
+ return getEmitModuleResolutionKind ( options ) === ModuleResolutionKind . Node12 ? NodeResolutionFeatures . Node12Default :
435
+ getEmitModuleResolutionKind ( options ) === ModuleResolutionKind . NodeNext ? NodeResolutionFeatures . NodeNextDefault :
436
+ NodeResolutionFeatures . None ;
437
+ }
438
+
439
+ /**
440
+ * @internal
441
+ * Does not try `@types/${packageName}` - use a second pass if needed.
442
+ */
443
+ export function resolvePackageNameToPackageJson (
444
+ packageName : string ,
445
+ containingDirectory : string ,
446
+ options : CompilerOptions ,
447
+ host : ModuleResolutionHost ,
448
+ cache : ModuleResolutionCache | undefined ,
449
+ ) : PackageJsonInfo | undefined {
450
+ const moduleResolutionState : ModuleResolutionState = {
451
+ compilerOptions : options ,
452
+ host,
453
+ traceEnabled : isTraceEnabled ( options , host ) ,
454
+ failedLookupLocations : [ ] ,
455
+ packageJsonInfoCache : cache ?. getPackageJsonInfoCache ( ) ,
456
+ conditions : emptyArray ,
457
+ features : NodeResolutionFeatures . None ,
458
+ } ;
459
+
460
+ return forEachAncestorDirectory ( containingDirectory , ancestorDirectory => {
461
+ if ( getBaseFileName ( ancestorDirectory ) !== "node_modules" ) {
462
+ const nodeModulesFolder = combinePaths ( ancestorDirectory , "node_modules" ) ;
463
+ const candidate = combinePaths ( nodeModulesFolder , packageName ) ;
464
+ return getPackageJsonInfo ( candidate , /*onlyRecordFailures*/ false , moduleResolutionState ) ;
465
+ }
466
+ } ) ;
467
+ }
468
+
436
469
/**
437
470
* Given a set of options, returns the set of type directive names
438
471
* that should be included for this program automatically.
@@ -1171,11 +1204,6 @@ namespace ts {
1171
1204
return resolvedModule . resolvedFileName ;
1172
1205
}
1173
1206
1174
- /* @internal */
1175
- export function tryResolveJSModule ( moduleName : string , initialDir : string , host : ModuleResolutionHost ) {
1176
- return tryResolveJSModuleWorker ( moduleName , initialDir , host ) . resolvedModule ;
1177
- }
1178
-
1179
1207
/* @internal */
1180
1208
enum NodeResolutionFeatures {
1181
1209
None = 0 ,
@@ -1536,11 +1564,124 @@ namespace ts {
1536
1564
return withPackageId ( packageInfo , loadNodeModuleFromDirectoryWorker ( extensions , candidate , onlyRecordFailures , state , packageJsonContent , versionPaths ) ) ;
1537
1565
}
1538
1566
1567
+ /* @internal */
1568
+ export function getEntrypointsFromPackageJsonInfo (
1569
+ packageJsonInfo : PackageJsonInfo ,
1570
+ options : CompilerOptions ,
1571
+ host : ModuleResolutionHost ,
1572
+ cache : ModuleResolutionCache | undefined ,
1573
+ resolveJs ?: boolean ,
1574
+ ) : string [ ] | false {
1575
+ if ( ! resolveJs && packageJsonInfo . resolvedEntrypoints !== undefined ) {
1576
+ // Cached value excludes resolutions to JS files - those could be
1577
+ // cached separately, but they're used rarely.
1578
+ return packageJsonInfo . resolvedEntrypoints ;
1579
+ }
1580
+
1581
+ let entrypoints : string [ ] | undefined ;
1582
+ const extensions = resolveJs ? Extensions . JavaScript : Extensions . TypeScript ;
1583
+ const features = getDefaultNodeResolutionFeatures ( options ) ;
1584
+ const requireState : ModuleResolutionState = {
1585
+ compilerOptions : options ,
1586
+ host,
1587
+ traceEnabled : isTraceEnabled ( options , host ) ,
1588
+ failedLookupLocations : [ ] ,
1589
+ packageJsonInfoCache : cache ?. getPackageJsonInfoCache ( ) ,
1590
+ conditions : [ "node" , "require" , "types" ] ,
1591
+ features,
1592
+ } ;
1593
+ const requireResolution = loadNodeModuleFromDirectoryWorker (
1594
+ extensions ,
1595
+ packageJsonInfo . packageDirectory ,
1596
+ /*onlyRecordFailures*/ false ,
1597
+ requireState ,
1598
+ packageJsonInfo . packageJsonContent ,
1599
+ packageJsonInfo . versionPaths ) ;
1600
+ entrypoints = append ( entrypoints , requireResolution ?. path ) ;
1601
+
1602
+ if ( features & NodeResolutionFeatures . Exports && packageJsonInfo . packageJsonContent . exports ) {
1603
+ for ( const conditions of [ [ "node" , "import" , "types" ] , [ "node" , "require" , "types" ] ] ) {
1604
+ const exportState = { ...requireState , failedLookupLocations : [ ] , conditions } ;
1605
+ const exportResolutions = loadEntrypointsFromExportMap (
1606
+ packageJsonInfo ,
1607
+ packageJsonInfo . packageJsonContent . exports ,
1608
+ exportState ,
1609
+ extensions ) ;
1610
+ if ( exportResolutions ) {
1611
+ for ( const resolution of exportResolutions ) {
1612
+ entrypoints = appendIfUnique ( entrypoints , resolution . path ) ;
1613
+ }
1614
+ }
1615
+ }
1616
+ }
1617
+
1618
+ return packageJsonInfo . resolvedEntrypoints = entrypoints || false ;
1619
+ }
1620
+
1621
+ function loadEntrypointsFromExportMap (
1622
+ scope : PackageJsonInfo ,
1623
+ exports : object ,
1624
+ state : ModuleResolutionState ,
1625
+ extensions : Extensions ,
1626
+ ) : PathAndExtension [ ] | undefined {
1627
+ let entrypoints : PathAndExtension [ ] | undefined ;
1628
+ if ( isArray ( exports ) ) {
1629
+ for ( const target of exports ) {
1630
+ loadEntrypointsFromTargetExports ( target ) ;
1631
+ }
1632
+ }
1633
+ // eslint-disable-next-line no-null/no-null
1634
+ else if ( typeof exports === "object" && exports !== null && allKeysStartWithDot ( exports as MapLike < unknown > ) ) {
1635
+ for ( const key in exports ) {
1636
+ loadEntrypointsFromTargetExports ( ( exports as MapLike < unknown > ) [ key ] ) ;
1637
+ }
1638
+ }
1639
+ else {
1640
+ loadEntrypointsFromTargetExports ( exports ) ;
1641
+ }
1642
+ return entrypoints ;
1643
+
1644
+ function loadEntrypointsFromTargetExports ( target : unknown ) : boolean | undefined {
1645
+ if ( typeof target === "string" && startsWith ( target , "./" ) && target . indexOf ( "*" ) === - 1 ) {
1646
+ const partsAfterFirst = getPathComponents ( target ) . slice ( 2 ) ;
1647
+ if ( partsAfterFirst . indexOf ( ".." ) >= 0 || partsAfterFirst . indexOf ( "." ) >= 0 || partsAfterFirst . indexOf ( "node_modules" ) >= 0 ) {
1648
+ return false ;
1649
+ }
1650
+ const resolvedTarget = combinePaths ( scope . packageDirectory , target ) ;
1651
+ const finalPath = getNormalizedAbsolutePath ( resolvedTarget , state . host . getCurrentDirectory ?.( ) ) ;
1652
+ const result = loadJSOrExactTSFileName ( extensions , finalPath , /*recordOnlyFailures*/ false , state ) ;
1653
+ if ( result ) {
1654
+ entrypoints = appendIfUnique ( entrypoints , result , ( a , b ) => a . path === b . path ) ;
1655
+ return true ;
1656
+ }
1657
+ }
1658
+ else if ( Array . isArray ( target ) ) {
1659
+ for ( const t of target ) {
1660
+ const success = loadEntrypointsFromTargetExports ( t ) ;
1661
+ if ( success ) {
1662
+ return true ;
1663
+ }
1664
+ }
1665
+ }
1666
+ // eslint-disable-next-line no-null/no-null
1667
+ else if ( typeof target === "object" && target !== null ) {
1668
+ return forEach ( getOwnKeys ( target as MapLike < unknown > ) , key => {
1669
+ if ( key === "default" || contains ( state . conditions , key ) || isApplicableVersionedTypesKey ( state . conditions , key ) ) {
1670
+ loadEntrypointsFromTargetExports ( ( target as MapLike < unknown > ) [ key ] ) ;
1671
+ return true ;
1672
+ }
1673
+ } ) ;
1674
+ }
1675
+ }
1676
+ }
1677
+
1539
1678
/*@internal */
1540
1679
interface PackageJsonInfo {
1541
1680
packageDirectory : string ;
1542
1681
packageJsonContent : PackageJsonPathFields ;
1543
1682
versionPaths : VersionPaths | undefined ;
1683
+ /** false: resolved to nothing. undefined: not yet resolved */
1684
+ resolvedEntrypoints : string [ ] | false | undefined ;
1544
1685
}
1545
1686
1546
1687
/**
@@ -1606,7 +1747,7 @@ namespace ts {
1606
1747
trace ( host , Diagnostics . Found_package_json_at_0 , packageJsonPath ) ;
1607
1748
}
1608
1749
const versionPaths = readPackageJsonTypesVersionPaths ( packageJsonContent , state ) ;
1609
- const result = { packageDirectory, packageJsonContent, versionPaths } ;
1750
+ const result = { packageDirectory, packageJsonContent, versionPaths, resolvedEntrypoints : undefined } ;
1610
1751
state . packageJsonInfoCache ?. setPackageJsonInfo ( packageJsonPath , result ) ;
1611
1752
return result ;
1612
1753
}
0 commit comments