@@ -669,11 +669,30 @@ namespace ts.codefix {
669669 }
670670 }
671671
672+ /**
673+ * We only allow PnP to be used as a resolution strategy if TypeScript
674+ * itself is executed under a PnP runtime (and we only allow it to access
675+ * the current PnP runtime, not any on the disk). This ensures that we
676+ * don't execute potentially malicious code that didn't already have a
677+ * chance to be executed (if we're running within the runtime, it means
678+ * that the runtime has already been executed).
679+ * @internal
680+ */
681+ function isPnpAvailable ( ) {
682+ // @ts -ignore
683+ return process . versions . pnp ;
684+ }
685+
686+ function getPnpApi ( ) {
687+ // @ts -ignore
688+ return require ( "pnpapi" ) ;
689+ }
690+
672691 /**
673692 * Don't include something from a `node_modules` that isn't actually reachable by a global import.
674693 * A relative import to node_modules is usually a bad idea.
675694 */
676- function isImportablePath ( fromPath : string , toPath : string , getCanonicalFileName : GetCanonicalFileName , globalCachePath ?: string ) : boolean {
695+ function isImportablePathNode ( fromPath : string , toPath : string , getCanonicalFileName : GetCanonicalFileName , globalCachePath ?: string ) : boolean {
677696 // If it's in a `node_modules` but is not reachable from here via a global import, don't bother.
678697 const toNodeModules = forEachAncestorDirectory ( toPath , ancestor => getBaseFileName ( ancestor ) === "node_modules" ? ancestor : undefined ) ;
679698 const toNodeModulesParent = toNodeModules && getDirectoryPath ( getCanonicalFileName ( toNodeModules ) ) ;
@@ -682,6 +701,30 @@ namespace ts.codefix {
682701 || ( ! ! globalCachePath && startsWith ( getCanonicalFileName ( globalCachePath ) , toNodeModulesParent ) ) ;
683702 }
684703
704+ function isImportablePathPnp ( fromPath : string , toPath : string ) : boolean {
705+ const pnpApi = getPnpApi ( ) ;
706+
707+ const fromLocator = pnpApi . findPackageLocator ( fromPath ) ;
708+ const toLocator = pnpApi . findPackageLocator ( toPath ) ;
709+
710+ if ( toLocator === null ) {
711+ return false ;
712+ }
713+
714+ const fromInfo = pnpApi . getPackageInformation ( fromLocator ) ;
715+ const toReference = fromInfo . packageDependencies . get ( toLocator . name ) ;
716+
717+ return toReference === toLocator . reference ;
718+ }
719+
720+ function isImportablePath ( fromPath : string , toPath : string , getCanonicalFileName : GetCanonicalFileName , globalCachePath ?: string ) : boolean {
721+ if ( isPnpAvailable ( ) ) {
722+ return isImportablePathPnp ( fromPath , toPath ) ;
723+ } else {
724+ return isImportablePathNode ( fromPath , toPath , getCanonicalFileName , globalCachePath ) ;
725+ }
726+ }
727+
685728 export function moduleSymbolToValidIdentifier ( moduleSymbol : Symbol , target : ScriptTarget ) : string {
686729 return moduleSpecifierToValidIdentifier ( removeFileExtension ( stripQuotes ( moduleSymbol . name ) ) , target ) ;
687730 }
0 commit comments