@@ -110,6 +110,8 @@ import {
110110 versionMajorMinor ,
111111 VersionRange ,
112112} from "./_namespaces/ts.js" ;
113+ import { getPnpTypeRoots } from "./pnp.js" ;
114+ import { getPnpApi } from "./pnpapi.js" ;
113115
114116/** @internal */
115117export function trace ( host : ModuleResolutionHost , message : DiagnosticMessage , ...args : any [ ] ) : void {
@@ -495,7 +497,7 @@ export function getEffectiveTypeRoots(options: CompilerOptions, host: GetEffecti
495497 * Returns the path to every node_modules/@types directory from some ancestor directory.
496498 * Returns undefined if there are none.
497499 */
498- function getDefaultTypeRoots ( currentDirectory : string ) : string [ ] | undefined {
500+ function getNodeModulesTypeRoots ( currentDirectory : string ) {
499501 let typeRoots : string [ ] | undefined ;
500502 forEachAncestorDirectory ( normalizePath ( currentDirectory ) , directory => {
501503 const atTypes = combinePaths ( directory , nodeModulesAtTypes ) ;
@@ -510,6 +512,18 @@ function arePathsEqual(path1: string, path2: string, host: ModuleResolutionHost)
510512 return comparePaths ( path1 , path2 , ! useCaseSensitiveFileNames ) === Comparison . EqualTo ;
511513}
512514
515+ function getDefaultTypeRoots ( currentDirectory : string ) : string [ ] | undefined {
516+ const nmTypes = getNodeModulesTypeRoots ( currentDirectory ) ;
517+ const pnpTypes = getPnpTypeRoots ( currentDirectory ) ;
518+
519+ if ( nmTypes ?. length ) {
520+ return [ ...nmTypes , ...pnpTypes ] ;
521+ }
522+ else if ( pnpTypes . length ) {
523+ return pnpTypes ;
524+ }
525+ }
526+
513527function getOriginalAndResolvedFileName ( fileName : string , host : ModuleResolutionHost , traceEnabled : boolean ) {
514528 const resolvedFileName = realPath ( fileName , host , traceEnabled ) ;
515529 const pathsAreEqual = arePathsEqual ( fileName , resolvedFileName , host ) ;
@@ -790,6 +804,18 @@ export function resolvePackageNameToPackageJson(
790804) : PackageJsonInfo | undefined {
791805 const moduleResolutionState = getTemporaryModuleResolutionState ( cache ?. getPackageJsonInfoCache ( ) , host , options ) ;
792806
807+ const pnpapi = getPnpApi ( containingDirectory ) ;
808+ if ( pnpapi ) {
809+ try {
810+ const resolution = pnpapi . resolveToUnqualified ( packageName , `${ containingDirectory } /` , { considerBuiltins : false } ) ;
811+ const candidate = normalizeSlashes ( resolution ) . replace ( / \/ $ / , "" ) ;
812+ return getPackageJsonInfo ( candidate , /*onlyRecordFailures*/ false , moduleResolutionState ) ;
813+ }
814+ catch {
815+ return ;
816+ }
817+ }
818+
793819 return forEachAncestorDirectoryStoppingAtGlobalCache ( host , containingDirectory , ancestorDirectory => {
794820 if ( getBaseFileName ( ancestorDirectory ) !== "node_modules" ) {
795821 const nodeModulesFolder = combinePaths ( ancestorDirectory , "node_modules" ) ;
@@ -3013,6 +3039,15 @@ function loadModuleFromNearestNodeModulesDirectoryWorker(extensions: Extensions,
30133039 }
30143040
30153041 function lookup ( extensions : Extensions ) {
3042+ const issuer = normalizeSlashes ( directory ) ;
3043+ if ( getPnpApi ( issuer ) ) {
3044+ const resolutionFromCache = tryFindNonRelativeModuleNameInCache ( cache , moduleName , mode , issuer , redirectedReference , state ) ;
3045+ if ( resolutionFromCache ) {
3046+ return resolutionFromCache ;
3047+ }
3048+ return toSearchResult ( loadModuleFromImmediateNodeModulesDirectoryPnP ( extensions , moduleName , issuer , state , typesScopeOnly , cache , redirectedReference ) ) ;
3049+ }
3050+
30163051 return forEachAncestorDirectoryStoppingAtGlobalCache (
30173052 state . host ,
30183053 normalizeSlashes ( directory ) ,
@@ -3075,11 +3110,34 @@ function loadModuleFromImmediateNodeModulesDirectory(extensions: Extensions, mod
30753110 }
30763111}
30773112
3113+ function loadModuleFromImmediateNodeModulesDirectoryPnP ( extensions : Extensions , moduleName : string , directory : string , state : ModuleResolutionState , typesScopeOnly : boolean , cache : ModuleResolutionCache | undefined , redirectedReference : ResolvedProjectReference | undefined ) : Resolved | undefined {
3114+ const issuer = normalizeSlashes ( directory ) ;
3115+
3116+ if ( ! typesScopeOnly ) {
3117+ const packageResult = tryLoadModuleUsingPnpResolution ( extensions , moduleName , issuer , state , cache , redirectedReference ) ;
3118+ if ( packageResult ) {
3119+ return packageResult ;
3120+ }
3121+ }
3122+
3123+ if ( extensions & Extensions . Declaration ) {
3124+ return tryLoadModuleUsingPnpResolution ( Extensions . Declaration , `@types/${ mangleScopedPackageNameWithTrace ( moduleName , state ) } ` , issuer , state , cache , redirectedReference ) ;
3125+ }
3126+ }
3127+
30783128function loadModuleFromSpecificNodeModulesDirectory ( extensions : Extensions , moduleName : string , nodeModulesDirectory : string , nodeModulesDirectoryExists : boolean , state : ModuleResolutionState , cache : ModuleResolutionCache | undefined , redirectedReference : ResolvedProjectReference | undefined ) : Resolved | undefined {
30793129 const candidate = normalizePath ( combinePaths ( nodeModulesDirectory , moduleName ) ) ;
30803130 const { packageName, rest } = parsePackageName ( moduleName ) ;
30813131 const packageDirectory = combinePaths ( nodeModulesDirectory , packageName ) ;
3132+ return loadModuleFromSpecificNodeModulesDirectoryImpl ( extensions , nodeModulesDirectoryExists , state , cache , redirectedReference , candidate , rest , packageDirectory ) ;
3133+ }
3134+
3135+ function loadModuleFromPnpResolution ( extensions : Extensions , packageDirectory : string , rest : string , state : ModuleResolutionState , cache : ModuleResolutionCache | undefined , redirectedReference : ResolvedProjectReference | undefined ) : Resolved | undefined {
3136+ const candidate = normalizePath ( combinePaths ( packageDirectory , rest ) ) ;
3137+ return loadModuleFromSpecificNodeModulesDirectoryImpl ( extensions , /*nodeModulesDirectoryExists*/ true , state , cache , redirectedReference , candidate , rest , packageDirectory ) ;
3138+ }
30823139
3140+ function loadModuleFromSpecificNodeModulesDirectoryImpl ( extensions : Extensions , nodeModulesDirectoryExists : boolean , state : ModuleResolutionState , cache : ModuleResolutionCache | undefined , redirectedReference : ResolvedProjectReference | undefined , candidate : string , rest : string , packageDirectory : string ) : Resolved | undefined {
30833141 let rootPackageInfo : PackageJsonInfo | undefined ;
30843142 // First look for a nested package.json, as in `node_modules/foo/bar/package.json`.
30853143 let packageInfo = getPackageJsonInfo ( candidate , ! nodeModulesDirectoryExists , state ) ;
@@ -3415,3 +3473,22 @@ function useCaseSensitiveFileNames(state: ModuleResolutionState) {
34153473 typeof state . host . useCaseSensitiveFileNames === "boolean" ? state . host . useCaseSensitiveFileNames :
34163474 state . host . useCaseSensitiveFileNames ( ) ;
34173475}
3476+
3477+ function loadPnpPackageResolution ( packageName : string , containingDirectory : string ) {
3478+ try {
3479+ const resolution = getPnpApi ( containingDirectory ) . resolveToUnqualified ( packageName , `${ containingDirectory } /` , { considerBuiltins : false } ) ;
3480+ return normalizeSlashes ( resolution ) . replace ( / \/ $ / , "" ) ;
3481+ }
3482+ catch {
3483+ // Nothing to do
3484+ }
3485+ }
3486+
3487+ function tryLoadModuleUsingPnpResolution ( extensions : Extensions , moduleName : string , containingDirectory : string , state : ModuleResolutionState , cache : ModuleResolutionCache | undefined , redirectedReference : ResolvedProjectReference | undefined ) {
3488+ const { packageName, rest } = parsePackageName ( moduleName ) ;
3489+
3490+ const packageResolution = loadPnpPackageResolution ( packageName , containingDirectory ) ;
3491+ return packageResolution
3492+ ? loadModuleFromPnpResolution ( extensions , packageResolution , rest , state , cache , redirectedReference )
3493+ : undefined ;
3494+ }
0 commit comments