Last active
August 27, 2021 03:18
-
-
Save strothj/c863b603e00c1a8cfe1b0d426b9d8327 to your computer and use it in GitHub Desktop.
Yarn v3 patch: [email protected]
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"resolutions": { | |
"typescript": "patch:[email protected]#./.yarn/patches/typescript.diff" | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/lib/tsc.js b/lib/tsc.js | |
index d425ad1b5..4c61f37c2 100644 | |
semver exclusivity 4.4.2 | |
--- a/lib/tsc.js | |
+++ b/lib/tsc.js | |
@@ -4758,6 +4758,9 @@ var ts; | |
: new Buffer(input, encoding); | |
} | |
function isFileSystemCaseSensitive() { | |
+ if (process.versions.pnp) { | |
+ return true; | |
+ } | |
if (platform === "win32" || platform === "win64") { | |
return false; | |
} | |
@@ -33390,21 +33393,52 @@ var ts; | |
} | |
} | |
ts.getEffectiveTypeRoots = getEffectiveTypeRoots; | |
- function getDefaultTypeRoots(currentDirectory, host) { | |
+ function getNodeModulesTypeRoots(currentDirectory, host) { | |
if (!host.directoryExists) { | |
return [ts.combinePaths(currentDirectory, nodeModulesAtTypes)]; | |
} | |
- var typeRoots; | |
+ var typeRoots = []; | |
ts.forEachAncestorDirectory(ts.normalizePath(currentDirectory), function (directory) { | |
var atTypes = ts.combinePaths(directory, nodeModulesAtTypes); | |
if (host.directoryExists(atTypes)) { | |
- (typeRoots || (typeRoots = [])).push(atTypes); | |
+ typeRoots.push(atTypes); | |
} | |
return undefined; | |
}); | |
return typeRoots; | |
} | |
var nodeModulesAtTypes = ts.combinePaths("node_modules", "@types"); | |
+ function getPnpTypeRoots(currentDirectory) { | |
+ var pnpapi = getPnpApi(currentDirectory); | |
+ if (!pnpapi) { | |
+ return []; | |
+ } | |
+ currentDirectory = ts.sys.resolvePath(currentDirectory); | |
+ var currentPackage = pnpapi.findPackageLocator(currentDirectory + "/"); | |
+ if (!currentPackage) { | |
+ return []; | |
+ } | |
+ var packageDependencies = pnpapi.getPackageInformation(currentPackage).packageDependencies; | |
+ var typeRoots = []; | |
+ for (var _i = 0, _a = Array.from(packageDependencies.entries()); _i < _a.length; _i++) { | |
+ var _b = _a[_i], name = _b[0], referencish = _b[1]; | |
+ if (name.startsWith(typesPackagePrefix) && referencish !== null) { | |
+ var dependencyLocator = pnpapi.getLocator(name, referencish); | |
+ var packageLocation = pnpapi.getPackageInformation(dependencyLocator).packageLocation; | |
+ typeRoots.push(ts.getDirectoryPath(packageLocation)); | |
+ } | |
+ } | |
+ return typeRoots; | |
+ } | |
+ ts.getPnpTypeRoots = getPnpTypeRoots; | |
+ var typesPackagePrefix = "@types/"; | |
+ function getDefaultTypeRoots(currentDirectory, host) { | |
+ var nmTypes = getNodeModulesTypeRoots(currentDirectory, host); | |
+ var pnpTypes = getPnpTypeRoots(currentDirectory); | |
+ if (nmTypes.length > 0 || pnpTypes.length > 0) { | |
+ return __spreadArray(__spreadArray([], nmTypes, true), pnpTypes, true); | |
+ } | |
+ } | |
function resolveTypeReferenceDirective(typeReferenceDirectiveName, containingFile, options, host, redirectedReference, cache) { | |
var traceEnabled = isTraceEnabled(options, host); | |
if (redirectedReference) { | |
@@ -33511,7 +33545,9 @@ var ts; | |
} | |
var result_4; | |
if (!ts.isExternalModuleNameRelative(typeReferenceDirectiveName)) { | |
- var searchResult = loadModuleFromNearestNodeModulesDirectory(Extensions.DtsOnly, typeReferenceDirectiveName, initialLocationForSecondaryLookup, moduleResolutionState, undefined, undefined); | |
+ var searchResult = getPnpApi(initialLocationForSecondaryLookup) | |
+ ? tryLoadModuleUsingPnpResolution(Extensions.DtsOnly, typeReferenceDirectiveName, initialLocationForSecondaryLookup, moduleResolutionState) | |
+ : loadModuleFromNearestNodeModulesDirectory(Extensions.DtsOnly, typeReferenceDirectiveName, initialLocationForSecondaryLookup, moduleResolutionState, undefined, undefined); | |
result_4 = searchResult && searchResult.value; | |
} | |
else { | |
@@ -33954,9 +33990,12 @@ var ts; | |
if (traceEnabled) { | |
trace(host, ts.Diagnostics.Loading_module_0_from_node_modules_folder_target_file_type_1, moduleName, Extensions[extensions]); | |
} | |
- var resolved_1 = loadModuleFromNearestNodeModulesDirectory(extensions, moduleName, containingDirectory, state, cache, redirectedReference); | |
- if (!resolved_1) | |
+ var resolved_1 = getPnpApi(containingDirectory) | |
+ ? tryLoadModuleUsingPnpResolution(extensions, moduleName, containingDirectory, state) | |
+ : loadModuleFromNearestNodeModulesDirectory(extensions, moduleName, containingDirectory, state, cache, redirectedReference); | |
+ if (!resolved_1) { | |
return undefined; | |
+ } | |
var resolvedValue = resolved_1.value; | |
if (!compilerOptions.preserveSymlinks && resolvedValue && !resolvedValue.originalPath) { | |
var path = realPath(resolvedValue.path, host, traceEnabled); | |
@@ -34267,6 +34306,14 @@ var ts; | |
} | |
function loadModuleFromSpecificNodeModulesDirectory(extensions, moduleName, nodeModulesDirectory, nodeModulesDirectoryExists, state) { | |
var candidate = ts.normalizePath(ts.combinePaths(nodeModulesDirectory, moduleName)); | |
+ return loadModuleFromSpecificNodeModulesDirectoryImpl(extensions, moduleName, nodeModulesDirectory, nodeModulesDirectoryExists, state, candidate, undefined, undefined); | |
+ } | |
+ function loadModuleFromPnpResolution(extensions, packageDirectory, rest, state) { | |
+ var candidate = ts.normalizePath(ts.combinePaths(packageDirectory, rest)); | |
+ return loadModuleFromSpecificNodeModulesDirectoryImpl(extensions, undefined, undefined, true, state, candidate, rest, packageDirectory); | |
+ } | |
+ function loadModuleFromSpecificNodeModulesDirectoryImpl(extensions, moduleName, nodeModulesDirectory, nodeModulesDirectoryExists, state, candidate, rest, packageDirectory) { | |
+ var _a; | |
var packageInfo = getPackageJsonInfo(candidate, !nodeModulesDirectoryExists, state); | |
if (packageInfo) { | |
var fromFile = loadModuleFromFile(extensions, candidate, !nodeModulesDirectoryExists, state); | |
@@ -34281,9 +34328,12 @@ var ts; | |
loadNodeModuleFromDirectoryWorker(extensions, candidate, onlyRecordFailures, state, packageInfo && packageInfo.packageJsonContent, packageInfo && packageInfo.versionPaths); | |
return withPackageId(packageInfo, pathAndExtension); | |
}; | |
- var _a = parsePackageName(moduleName), packageName = _a.packageName, rest = _a.rest; | |
+ var packageName; | |
+ if (rest === undefined) | |
+ (_a = parsePackageName(moduleName), packageName = _a.packageName, rest = _a.rest); | |
if (rest !== "") { | |
- var packageDirectory = ts.combinePaths(nodeModulesDirectory, packageName); | |
+ if (packageDirectory === undefined) | |
+ packageDirectory = ts.combinePaths(nodeModulesDirectory, packageName); | |
packageInfo = getPackageJsonInfo(packageDirectory, !nodeModulesDirectoryExists, state); | |
if (packageInfo && packageInfo.versionPaths) { | |
if (state.traceEnabled) { | |
@@ -34421,6 +34471,47 @@ var ts; | |
function toSearchResult(value) { | |
return value !== undefined ? { value: value } : undefined; | |
} | |
+ function getPnpApi(path) { | |
+ var findPnpApi = require("module").findPnpApi; | |
+ if (findPnpApi === undefined) { | |
+ return undefined; | |
+ } | |
+ return findPnpApi(path + "/"); | |
+ } | |
+ function loadPnpPackageResolution(packageName, containingDirectory) { | |
+ try { | |
+ var resolution = getPnpApi(containingDirectory).resolveToUnqualified(packageName, containingDirectory + "/", { considerBuiltins: false }); | |
+ return ts.normalizeSlashes(resolution); | |
+ } | |
+ catch (_a) { | |
+ } | |
+ } | |
+ function loadPnpTypePackageResolution(packageName, containingDirectory) { | |
+ return loadPnpPackageResolution(getTypesPackageName(packageName), containingDirectory); | |
+ } | |
+ function tryLoadModuleUsingPnpResolution(extensions, moduleName, containingDirectory, state) { | |
+ var _a = parsePackageName(moduleName), packageName = _a.packageName, rest = _a.rest; | |
+ var packageResolution = loadPnpPackageResolution(packageName, containingDirectory); | |
+ var packageFullResolution = packageResolution | |
+ ? loadModuleFromPnpResolution(extensions, packageResolution, rest, state) | |
+ : undefined; | |
+ var resolved; | |
+ if (packageFullResolution) { | |
+ resolved = packageFullResolution; | |
+ } | |
+ else if (extensions === Extensions.TypeScript || extensions === Extensions.DtsOnly) { | |
+ var typePackageResolution = loadPnpTypePackageResolution(packageName, containingDirectory); | |
+ var typePackageFullResolution = typePackageResolution | |
+ ? loadModuleFromPnpResolution(Extensions.DtsOnly, typePackageResolution, rest, state) | |
+ : undefined; | |
+ if (typePackageFullResolution) { | |
+ resolved = typePackageFullResolution; | |
+ } | |
+ } | |
+ if (resolved) { | |
+ return toSearchResult(resolved); | |
+ } | |
+ } | |
})(ts || (ts = {})); | |
var ts; | |
(function (ts) { | |
@@ -91002,6 +91093,7 @@ var ts; | |
ConfigFileProgramReloadLevel[ConfigFileProgramReloadLevel["None"] = 0] = "None"; | |
ConfigFileProgramReloadLevel[ConfigFileProgramReloadLevel["Partial"] = 1] = "Partial"; | |
ConfigFileProgramReloadLevel[ConfigFileProgramReloadLevel["Full"] = 2] = "Full"; | |
+ ConfigFileProgramReloadLevel[ConfigFileProgramReloadLevel["Resolutions"] = 3] = "Resolutions"; | |
})(ConfigFileProgramReloadLevel = ts.ConfigFileProgramReloadLevel || (ts.ConfigFileProgramReloadLevel = {})); | |
function updateSharedExtendedConfigFileWatcher(projectPath, options, extendedConfigFilesMap, createExtendedConfigFileWatch, toPath) { | |
var _a; | |
@@ -96668,6 +96760,25 @@ var ts; | |
return undefined; | |
} | |
var parts = getNodeModulePathParts(path); | |
+ var packageName; | |
+ if (!parts && typeof process.versions.pnp !== "undefined") { | |
+ var pnpApi = require("pnpapi"); | |
+ var locator = pnpApi.findPackageLocator(path); | |
+ if (locator !== null) { | |
+ var sourceLocator = pnpApi.findPackageLocator(sourceDirectory + "/"); | |
+ if (locator === sourceLocator) { | |
+ return undefined; | |
+ } | |
+ var information = pnpApi.getPackageInformation(locator); | |
+ packageName = locator.name; | |
+ parts = { | |
+ topLevelNodeModulesIndex: undefined, | |
+ topLevelPackageNameIndex: undefined, | |
+ packageRootIndex: information.packageLocation.length - 1, | |
+ fileNameIndex: path.lastIndexOf("/"), | |
+ }; | |
+ } | |
+ } | |
if (!parts) { | |
return undefined; | |
} | |
@@ -96695,14 +96806,18 @@ var ts; | |
if (isRedirect && !isPackageRootPath) { | |
return undefined; | |
} | |
- var globalTypingsCacheLocation = host.getGlobalTypingsCacheLocation && host.getGlobalTypingsCacheLocation(); | |
- var pathToTopLevelNodeModules = getCanonicalFileName(moduleSpecifier.substring(0, parts.topLevelNodeModulesIndex)); | |
- if (!(ts.startsWith(sourceDirectory, pathToTopLevelNodeModules) || globalTypingsCacheLocation && ts.startsWith(getCanonicalFileName(globalTypingsCacheLocation), pathToTopLevelNodeModules))) { | |
- return undefined; | |
+ if (typeof process.versions.pnp === "undefined") { | |
+ var globalTypingsCacheLocation = host.getGlobalTypingsCacheLocation && host.getGlobalTypingsCacheLocation(); | |
+ var pathToTopLevelNodeModules = getCanonicalFileName(moduleSpecifier.substring(0, parts.topLevelNodeModulesIndex)); | |
+ if (!(ts.startsWith(sourceDirectory, pathToTopLevelNodeModules) || globalTypingsCacheLocation && ts.startsWith(getCanonicalFileName(globalTypingsCacheLocation), pathToTopLevelNodeModules))) { | |
+ return undefined; | |
+ } | |
} | |
- var nodeModulesDirectoryName = moduleSpecifier.substring(parts.topLevelPackageNameIndex + 1); | |
- var packageName = ts.getPackageNameFromTypesPackageName(nodeModulesDirectoryName); | |
- return ts.getEmitModuleResolutionKind(options) !== ts.ModuleResolutionKind.NodeJs && packageName === nodeModulesDirectoryName ? undefined : packageName; | |
+ var nodeModulesDirectoryName = typeof packageName !== "undefined" | |
+ ? packageName + moduleSpecifier.substring(parts.packageRootIndex) | |
+ : moduleSpecifier.substring(parts.topLevelPackageNameIndex + 1); | |
+ var packageNameFromPath = ts.getPackageNameFromTypesPackageName(nodeModulesDirectoryName); | |
+ return ts.getEmitModuleResolutionKind(options) !== ts.ModuleResolutionKind.NodeJs && packageNameFromPath === nodeModulesDirectoryName ? undefined : packageNameFromPath; | |
function tryDirectoryWithPackageJson(packageRootIndex) { | |
var packageRootPath = path.substring(0, packageRootIndex); | |
var packageJsonPath = ts.combinePaths(packageRootPath, "package.json"); | |
@@ -97430,6 +97545,10 @@ var ts; | |
if (configFileName) { | |
configFileWatcher = watchFile(configFileName, scheduleProgramReload, ts.PollingInterval.High, watchOptions, ts.WatchType.ConfigFile); | |
} | |
+ var pnpFileWatcher; | |
+ if (typeof process.versions.pnp !== "undefined") { | |
+ pnpFileWatcher = watchFile(require.resolve("pnpapi"), scheduleResolutionReload, ts.PollingInterval.High, watchOptions, ts.WatchType.ConfigFile); | |
+ } | |
var compilerHost = ts.createCompilerHostFromProgramHost(host, function () { return compilerOptions; }, directoryStructureHost); | |
ts.setGetSourceFileAsHashVersioned(compilerHost, host); | |
var getNewSourceFile = compilerHost.getSourceFile; | |
@@ -97501,6 +97620,10 @@ var ts; | |
configFileWatcher.close(); | |
configFileWatcher = undefined; | |
} | |
+ if (pnpFileWatcher) { | |
+ pnpFileWatcher.close(); | |
+ pnpFileWatcher = undefined; | |
+ } | |
extendedConfigCache === null || extendedConfigCache === void 0 ? void 0 : extendedConfigCache.clear(); | |
extendedConfigCache = undefined; | |
if (sharedExtendedConfigFileWatchers) { | |
@@ -97533,7 +97656,8 @@ var ts; | |
function getCurrentProgram() { | |
return builderProgram && builderProgram.getProgramOrUndefined(); | |
} | |
- function synchronizeProgram() { | |
+ function synchronizeProgram(forceAllFilesAsInvalidated) { | |
+ if (forceAllFilesAsInvalidated === void 0) { forceAllFilesAsInvalidated = false; } | |
writeLog("Synchronizing program"); | |
clearInvalidateResolutionsOfFailedLookupLocations(); | |
var program = getCurrentBuilderProgram(); | |
@@ -97543,7 +97667,7 @@ var ts; | |
resolutionCache.clear(); | |
} | |
} | |
- var hasInvalidatedResolution = resolutionCache.createHasInvalidatedResolution(userProvidedResolution || changesAffectResolution); | |
+ var hasInvalidatedResolution = resolutionCache.createHasInvalidatedResolution(userProvidedResolution || forceAllFilesAsInvalidated); | |
if (ts.isProgramUptoDate(getCurrentProgram(), rootFileNames, compilerOptions, getSourceVersion, fileExists, hasInvalidatedResolution, hasChangedAutomaticTypeDirectiveNames, getParsedCommandLine, projectReferences)) { | |
if (hasChangedConfigFileParsingErrors) { | |
builderProgram = createProgram(undefined, undefined, compilerHost, builderProgram, configFileParsingDiagnostics, projectReferences); | |
@@ -97727,6 +97851,12 @@ var ts; | |
reloadLevel = ts.ConfigFileProgramReloadLevel.Full; | |
scheduleProgramUpdate(); | |
} | |
+ function scheduleResolutionReload() { | |
+ writeLog("Clearing resolutions"); | |
+ resolutionCache.clear(); | |
+ reloadLevel = ts.ConfigFileProgramReloadLevel.Resolutions; | |
+ scheduleProgramUpdate(); | |
+ } | |
function updateProgramWithWatchStatus() { | |
timerToUpdateProgram = undefined; | |
reportWatchDiagnostic(ts.Diagnostics.File_change_detected_Starting_incremental_compilation); | |
@@ -97742,6 +97872,10 @@ var ts; | |
ts.perfLogger.logStartUpdateProgram("FullConfigReload"); | |
reloadConfigFile(); | |
break; | |
+ case ts.ConfigFileProgramReloadLevel.Resolutions: | |
+ ts.perfLogger.logStartUpdateProgram("SynchronizeProgramWithResolutions"); | |
+ synchronizeProgram(true); | |
+ break; | |
default: | |
ts.perfLogger.logStartUpdateProgram("SynchronizeProgram"); | |
synchronizeProgram(); | |
diff --git a/lib/tsserver.js b/lib/tsserver.js | |
index 6e4ee30b7..a774c21dd 100644 | |
semver exclusivity 4.4.2 | |
--- a/lib/tsserver.js | |
+++ b/lib/tsserver.js | |
@@ -7458,6 +7458,11 @@ var ts; | |
: new Buffer(input, encoding); | |
} | |
function isFileSystemCaseSensitive() { | |
+ // The PnP runtime is always case-sensitive | |
+ // @ts-ignore | |
+ if (process.versions.pnp) { | |
+ return true; | |
+ } | |
// win32\win64 are case insensitive platforms | |
if (platform === "win32" || platform === "win64") { | |
return false; | |
@@ -40967,24 +40972,56 @@ var ts; | |
ts.getEffectiveTypeRoots = getEffectiveTypeRoots; | |
/** | |
* Returns the path to every node_modules/@types directory from some ancestor directory. | |
- * Returns undefined if there are none. | |
*/ | |
- function getDefaultTypeRoots(currentDirectory, host) { | |
+ function getNodeModulesTypeRoots(currentDirectory, host) { | |
if (!host.directoryExists) { | |
return [ts.combinePaths(currentDirectory, nodeModulesAtTypes)]; | |
// And if it doesn't exist, tough. | |
} | |
- var typeRoots; | |
+ var typeRoots = []; | |
ts.forEachAncestorDirectory(ts.normalizePath(currentDirectory), function (directory) { | |
var atTypes = ts.combinePaths(directory, nodeModulesAtTypes); | |
if (host.directoryExists(atTypes)) { | |
- (typeRoots || (typeRoots = [])).push(atTypes); | |
+ typeRoots.push(atTypes); | |
} | |
return undefined; | |
}); | |
return typeRoots; | |
} | |
var nodeModulesAtTypes = ts.combinePaths("node_modules", "@types"); | |
+ function getPnpTypeRoots(currentDirectory) { | |
+ var pnpapi = getPnpApi(currentDirectory); | |
+ if (!pnpapi) { | |
+ return []; | |
+ } | |
+ // Some TS consumers pass relative paths that aren't normalized | |
+ currentDirectory = ts.sys.resolvePath(currentDirectory); | |
+ var currentPackage = pnpapi.findPackageLocator(currentDirectory + "/"); | |
+ if (!currentPackage) { | |
+ return []; | |
+ } | |
+ var packageDependencies = pnpapi.getPackageInformation(currentPackage).packageDependencies; | |
+ var typeRoots = []; | |
+ for (var _i = 0, _a = Array.from(packageDependencies.entries()); _i < _a.length; _i++) { | |
+ var _b = _a[_i], name = _b[0], referencish = _b[1]; | |
+ // eslint-disable-next-line no-null/no-null | |
+ if (name.startsWith(typesPackagePrefix) && referencish !== null) { | |
+ var dependencyLocator = pnpapi.getLocator(name, referencish); | |
+ var packageLocation = pnpapi.getPackageInformation(dependencyLocator).packageLocation; | |
+ typeRoots.push(ts.getDirectoryPath(packageLocation)); | |
+ } | |
+ } | |
+ return typeRoots; | |
+ } | |
+ ts.getPnpTypeRoots = getPnpTypeRoots; | |
+ var typesPackagePrefix = "@types/"; | |
+ function getDefaultTypeRoots(currentDirectory, host) { | |
+ var nmTypes = getNodeModulesTypeRoots(currentDirectory, host); | |
+ var pnpTypes = getPnpTypeRoots(currentDirectory); | |
+ if (nmTypes.length > 0 || pnpTypes.length > 0) { | |
+ return __spreadArray(__spreadArray([], nmTypes, true), pnpTypes, true); | |
+ } | |
+ } | |
/** | |
* @param {string | undefined} containingFile - file that contains type reference directive, can be undefined if containing file is unknown. | |
* This is possible in case if resolution is performed for directives specified via 'types' parameter. In this case initial path for secondary lookups | |
@@ -41098,7 +41135,9 @@ var ts; | |
} | |
var result_4; | |
if (!ts.isExternalModuleNameRelative(typeReferenceDirectiveName)) { | |
- var searchResult = loadModuleFromNearestNodeModulesDirectory(Extensions.DtsOnly, typeReferenceDirectiveName, initialLocationForSecondaryLookup, moduleResolutionState, /*cache*/ undefined, /*redirectedReference*/ undefined); | |
+ var searchResult = getPnpApi(initialLocationForSecondaryLookup) | |
+ ? tryLoadModuleUsingPnpResolution(Extensions.DtsOnly, typeReferenceDirectiveName, initialLocationForSecondaryLookup, moduleResolutionState) | |
+ : loadModuleFromNearestNodeModulesDirectory(Extensions.DtsOnly, typeReferenceDirectiveName, initialLocationForSecondaryLookup, moduleResolutionState, /*cache*/ undefined, /*redirectedReference*/ undefined); | |
result_4 = searchResult && searchResult.value; | |
} | |
else { | |
@@ -41653,9 +41692,12 @@ var ts; | |
if (traceEnabled) { | |
trace(host, ts.Diagnostics.Loading_module_0_from_node_modules_folder_target_file_type_1, moduleName, Extensions[extensions]); | |
} | |
- var resolved_1 = loadModuleFromNearestNodeModulesDirectory(extensions, moduleName, containingDirectory, state, cache, redirectedReference); | |
- if (!resolved_1) | |
+ var resolved_1 = getPnpApi(containingDirectory) | |
+ ? tryLoadModuleUsingPnpResolution(extensions, moduleName, containingDirectory, state) | |
+ : loadModuleFromNearestNodeModulesDirectory(extensions, moduleName, containingDirectory, state, cache, redirectedReference); | |
+ if (!resolved_1) { | |
return undefined; | |
+ } | |
var resolvedValue = resolved_1.value; | |
if (!compilerOptions.preserveSymlinks && resolvedValue && !resolvedValue.originalPath) { | |
var path = realPath(resolvedValue.path, host, traceEnabled); | |
@@ -42000,6 +42042,14 @@ var ts; | |
} | |
function loadModuleFromSpecificNodeModulesDirectory(extensions, moduleName, nodeModulesDirectory, nodeModulesDirectoryExists, state) { | |
var candidate = ts.normalizePath(ts.combinePaths(nodeModulesDirectory, moduleName)); | |
+ return loadModuleFromSpecificNodeModulesDirectoryImpl(extensions, moduleName, nodeModulesDirectory, nodeModulesDirectoryExists, state, candidate, undefined, undefined); | |
+ } | |
+ function loadModuleFromPnpResolution(extensions, packageDirectory, rest, state) { | |
+ var candidate = ts.normalizePath(ts.combinePaths(packageDirectory, rest)); | |
+ return loadModuleFromSpecificNodeModulesDirectoryImpl(extensions, undefined, undefined, true, state, candidate, rest, packageDirectory); | |
+ } | |
+ function loadModuleFromSpecificNodeModulesDirectoryImpl(extensions, moduleName, nodeModulesDirectory, nodeModulesDirectoryExists, state, candidate, rest, packageDirectory) { | |
+ var _a; | |
// First look for a nested package.json, as in `node_modules/foo/bar/package.json`. | |
var packageInfo = getPackageJsonInfo(candidate, !nodeModulesDirectoryExists, state); | |
if (packageInfo) { | |
@@ -42015,9 +42065,12 @@ var ts; | |
loadNodeModuleFromDirectoryWorker(extensions, candidate, onlyRecordFailures, state, packageInfo && packageInfo.packageJsonContent, packageInfo && packageInfo.versionPaths); | |
return withPackageId(packageInfo, pathAndExtension); | |
}; | |
- var _a = parsePackageName(moduleName), packageName = _a.packageName, rest = _a.rest; | |
+ var packageName; | |
+ if (rest === undefined) | |
+ (_a = parsePackageName(moduleName), packageName = _a.packageName, rest = _a.rest); | |
if (rest !== "") { // If "rest" is empty, we just did this search above. | |
- var packageDirectory = ts.combinePaths(nodeModulesDirectory, packageName); | |
+ if (packageDirectory === undefined) | |
+ packageDirectory = ts.combinePaths(nodeModulesDirectory, packageName); | |
// Don't use a "types" or "main" from here because we're not loading the root, but a subdirectory -- just here for the packageId and path mappings. | |
packageInfo = getPackageJsonInfo(packageDirectory, !nodeModulesDirectoryExists, state); | |
if (packageInfo && packageInfo.versionPaths) { | |
@@ -42176,6 +42229,58 @@ var ts; | |
function toSearchResult(value) { | |
return value !== undefined ? { value: value } : undefined; | |
} | |
+ /** | |
+ * We only allow PnP to be used as a resolution strategy if TypeScript | |
+ * itself is executed under a PnP runtime (and we only allow it to access | |
+ * the current PnP runtime, not any on the disk). This ensures that we | |
+ * don't execute potentially malicious code that didn't already have a | |
+ * chance to be executed (if we're running within the runtime, it means | |
+ * that the runtime has already been executed). | |
+ * @internal | |
+ */ | |
+ function getPnpApi(path) { | |
+ var findPnpApi = require("module").findPnpApi; | |
+ if (findPnpApi === undefined) { | |
+ return undefined; | |
+ } | |
+ return findPnpApi(path + "/"); | |
+ } | |
+ function loadPnpPackageResolution(packageName, containingDirectory) { | |
+ try { | |
+ var resolution = getPnpApi(containingDirectory).resolveToUnqualified(packageName, containingDirectory + "/", { considerBuiltins: false }); | |
+ return ts.normalizeSlashes(resolution); | |
+ } | |
+ catch (_a) { | |
+ // Nothing to do | |
+ } | |
+ } | |
+ function loadPnpTypePackageResolution(packageName, containingDirectory) { | |
+ return loadPnpPackageResolution(getTypesPackageName(packageName), containingDirectory); | |
+ } | |
+ /* @internal */ | |
+ function tryLoadModuleUsingPnpResolution(extensions, moduleName, containingDirectory, state) { | |
+ var _a = parsePackageName(moduleName), packageName = _a.packageName, rest = _a.rest; | |
+ var packageResolution = loadPnpPackageResolution(packageName, containingDirectory); | |
+ var packageFullResolution = packageResolution | |
+ ? loadModuleFromPnpResolution(extensions, packageResolution, rest, state) | |
+ : undefined; | |
+ var resolved; | |
+ if (packageFullResolution) { | |
+ resolved = packageFullResolution; | |
+ } | |
+ else if (extensions === Extensions.TypeScript || extensions === Extensions.DtsOnly) { | |
+ var typePackageResolution = loadPnpTypePackageResolution(packageName, containingDirectory); | |
+ var typePackageFullResolution = typePackageResolution | |
+ ? loadModuleFromPnpResolution(Extensions.DtsOnly, typePackageResolution, rest, state) | |
+ : undefined; | |
+ if (typePackageFullResolution) { | |
+ resolved = typePackageFullResolution; | |
+ } | |
+ } | |
+ if (resolved) { | |
+ return toSearchResult(resolved); | |
+ } | |
+ } | |
})(ts || (ts = {})); | |
/* @internal */ | |
var ts; | |
@@ -110519,6 +110624,8 @@ var ts; | |
ConfigFileProgramReloadLevel[ConfigFileProgramReloadLevel["Partial"] = 1] = "Partial"; | |
/** Reload completely by re-reading contents of config file from disk and updating program */ | |
ConfigFileProgramReloadLevel[ConfigFileProgramReloadLevel["Full"] = 2] = "Full"; | |
+ /** Reload the resolutions */ | |
+ ConfigFileProgramReloadLevel[ConfigFileProgramReloadLevel["Resolutions"] = 3] = "Resolutions"; | |
})(ConfigFileProgramReloadLevel = ts.ConfigFileProgramReloadLevel || (ts.ConfigFileProgramReloadLevel = {})); | |
/** | |
* Updates the map of shared extended config file watches with a new set of extended config files from a base config file of the project | |
@@ -117089,6 +117196,29 @@ var ts; | |
return undefined; | |
} | |
var parts = getNodeModulePathParts(path); | |
+ var packageName; | |
+ if (!parts && typeof process.versions.pnp !== "undefined") { | |
+ var pnpApi = require("pnpapi"); | |
+ var locator = pnpApi.findPackageLocator(path); | |
+ // eslint-disable-next-line no-null/no-null | |
+ if (locator !== null) { | |
+ var sourceLocator = pnpApi.findPackageLocator(sourceDirectory + "/"); | |
+ // Don't use the package name when the imported file is inside | |
+ // the source directory (prefer a relative path instead) | |
+ if (locator === sourceLocator) { | |
+ return undefined; | |
+ } | |
+ var information = pnpApi.getPackageInformation(locator); | |
+ packageName = locator.name; | |
+ parts = { | |
+ topLevelNodeModulesIndex: undefined, | |
+ topLevelPackageNameIndex: undefined, | |
+ // The last character from packageLocation is the trailing "/", we want to point to it | |
+ packageRootIndex: information.packageLocation.length - 1, | |
+ fileNameIndex: path.lastIndexOf("/"), | |
+ }; | |
+ } | |
+ } | |
if (!parts) { | |
return undefined; | |
} | |
@@ -117119,18 +117249,24 @@ var ts; | |
if (isRedirect && !isPackageRootPath) { | |
return undefined; | |
} | |
- var globalTypingsCacheLocation = host.getGlobalTypingsCacheLocation && host.getGlobalTypingsCacheLocation(); | |
- // Get a path that's relative to node_modules or the importing file's path | |
- // if node_modules folder is in this folder or any of its parent folders, no need to keep it. | |
- var pathToTopLevelNodeModules = getCanonicalFileName(moduleSpecifier.substring(0, parts.topLevelNodeModulesIndex)); | |
- if (!(ts.startsWith(sourceDirectory, pathToTopLevelNodeModules) || globalTypingsCacheLocation && ts.startsWith(getCanonicalFileName(globalTypingsCacheLocation), pathToTopLevelNodeModules))) { | |
- return undefined; | |
+ // If PnP is enabled the node_modules entries we'll get will always be relevant even if they | |
+ // are located in a weird path apparently outside of the source directory | |
+ if (typeof process.versions.pnp === "undefined") { | |
+ var globalTypingsCacheLocation = host.getGlobalTypingsCacheLocation && host.getGlobalTypingsCacheLocation(); | |
+ // Get a path that's relative to node_modules or the importing file's path | |
+ // if node_modules folder is in this folder or any of its parent folders, no need to keep it. | |
+ var pathToTopLevelNodeModules = getCanonicalFileName(moduleSpecifier.substring(0, parts.topLevelNodeModulesIndex)); | |
+ if (!(ts.startsWith(sourceDirectory, pathToTopLevelNodeModules) || globalTypingsCacheLocation && ts.startsWith(getCanonicalFileName(globalTypingsCacheLocation), pathToTopLevelNodeModules))) { | |
+ return undefined; | |
+ } | |
} | |
// If the module was found in @types, get the actual Node package name | |
- var nodeModulesDirectoryName = moduleSpecifier.substring(parts.topLevelPackageNameIndex + 1); | |
- var packageName = ts.getPackageNameFromTypesPackageName(nodeModulesDirectoryName); | |
+ var nodeModulesDirectoryName = typeof packageName !== "undefined" | |
+ ? packageName + moduleSpecifier.substring(parts.packageRootIndex) | |
+ : moduleSpecifier.substring(parts.topLevelPackageNameIndex + 1); | |
+ var packageNameFromPath = ts.getPackageNameFromTypesPackageName(nodeModulesDirectoryName); | |
// For classic resolution, only allow importing from node_modules/@types, not other node_modules | |
- return ts.getEmitModuleResolutionKind(options) !== ts.ModuleResolutionKind.NodeJs && packageName === nodeModulesDirectoryName ? undefined : packageName; | |
+ return ts.getEmitModuleResolutionKind(options) !== ts.ModuleResolutionKind.NodeJs && packageNameFromPath === nodeModulesDirectoryName ? undefined : packageNameFromPath; | |
function tryDirectoryWithPackageJson(packageRootIndex) { | |
var packageRootPath = path.substring(0, packageRootIndex); | |
var packageJsonPath = ts.combinePaths(packageRootPath, "package.json"); | |
@@ -117924,6 +118060,10 @@ var ts; | |
if (configFileName) { | |
configFileWatcher = watchFile(configFileName, scheduleProgramReload, ts.PollingInterval.High, watchOptions, ts.WatchType.ConfigFile); | |
} | |
+ var pnpFileWatcher; | |
+ if (typeof process.versions.pnp !== "undefined") { | |
+ pnpFileWatcher = watchFile(require.resolve("pnpapi"), scheduleResolutionReload, ts.PollingInterval.High, watchOptions, ts.WatchType.ConfigFile); | |
+ } | |
var compilerHost = ts.createCompilerHostFromProgramHost(host, function () { return compilerOptions; }, directoryStructureHost); | |
ts.setGetSourceFileAsHashVersioned(compilerHost, host); | |
// Members for CompilerHost | |
@@ -118002,6 +118142,10 @@ var ts; | |
configFileWatcher.close(); | |
configFileWatcher = undefined; | |
} | |
+ if (pnpFileWatcher) { | |
+ pnpFileWatcher.close(); | |
+ pnpFileWatcher = undefined; | |
+ } | |
extendedConfigCache === null || extendedConfigCache === void 0 ? void 0 : extendedConfigCache.clear(); | |
extendedConfigCache = undefined; | |
if (sharedExtendedConfigFileWatchers) { | |
@@ -118034,7 +118178,8 @@ var ts; | |
function getCurrentProgram() { | |
return builderProgram && builderProgram.getProgramOrUndefined(); | |
} | |
- function synchronizeProgram() { | |
+ function synchronizeProgram(forceAllFilesAsInvalidated) { | |
+ if (forceAllFilesAsInvalidated === void 0) { forceAllFilesAsInvalidated = false; } | |
writeLog("Synchronizing program"); | |
clearInvalidateResolutionsOfFailedLookupLocations(); | |
var program = getCurrentBuilderProgram(); | |
@@ -118045,7 +118190,7 @@ var ts; | |
} | |
} | |
// All resolutions are invalid if user provided resolutions | |
- var hasInvalidatedResolution = resolutionCache.createHasInvalidatedResolution(userProvidedResolution || changesAffectResolution); | |
+ var hasInvalidatedResolution = resolutionCache.createHasInvalidatedResolution(userProvidedResolution || forceAllFilesAsInvalidated); | |
if (ts.isProgramUptoDate(getCurrentProgram(), rootFileNames, compilerOptions, getSourceVersion, fileExists, hasInvalidatedResolution, hasChangedAutomaticTypeDirectiveNames, getParsedCommandLine, projectReferences)) { | |
if (hasChangedConfigFileParsingErrors) { | |
builderProgram = createProgram(/*rootNames*/ undefined, /*options*/ undefined, compilerHost, builderProgram, configFileParsingDiagnostics, projectReferences); | |
@@ -118252,6 +118397,12 @@ var ts; | |
reloadLevel = ts.ConfigFileProgramReloadLevel.Full; | |
scheduleProgramUpdate(); | |
} | |
+ function scheduleResolutionReload() { | |
+ writeLog("Clearing resolutions"); | |
+ resolutionCache.clear(); | |
+ reloadLevel = ts.ConfigFileProgramReloadLevel.Resolutions; | |
+ scheduleProgramUpdate(); | |
+ } | |
function updateProgramWithWatchStatus() { | |
timerToUpdateProgram = undefined; | |
reportWatchDiagnostic(ts.Diagnostics.File_change_detected_Starting_incremental_compilation); | |
@@ -118267,6 +118418,10 @@ var ts; | |
ts.perfLogger.logStartUpdateProgram("FullConfigReload"); | |
reloadConfigFile(); | |
break; | |
+ case ts.ConfigFileProgramReloadLevel.Resolutions: | |
+ ts.perfLogger.logStartUpdateProgram("SynchronizeProgramWithResolutions"); | |
+ synchronizeProgram(/*forceAllFilesAsInvalidated*/ true); | |
+ break; | |
default: | |
ts.perfLogger.logStartUpdateProgram("SynchronizeProgram"); | |
synchronizeProgram(); | |
@@ -123684,11 +123839,27 @@ var ts; | |
return hasImportablePath; | |
} | |
ts.isImportableFile = isImportableFile; | |
+ /** | |
+ * We only allow PnP to be used as a resolution strategy if TypeScript | |
+ * itself is executed under a PnP runtime (and we only allow it to access | |
+ * the current PnP runtime, not any on the disk). This ensures that we | |
+ * don't execute potentially malicious code that didn't already have a | |
+ * chance to be executed (if we're running within the runtime, it means | |
+ * that the runtime has already been executed). | |
+ * @internal | |
+ */ | |
+ function getPnpApi(path) { | |
+ var findPnpApi = require("module").findPnpApi; | |
+ if (findPnpApi === undefined) { | |
+ return undefined; | |
+ } | |
+ return findPnpApi(path + "/"); | |
+ } | |
/** | |
* Don't include something from a `node_modules` that isn't actually reachable by a global import. | |
* A relative import to node_modules is usually a bad idea. | |
*/ | |
- function isImportablePath(fromPath, toPath, getCanonicalFileName, globalCachePath) { | |
+ function isImportablePathNode(fromPath, toPath, getCanonicalFileName, globalCachePath) { | |
// If it's in a `node_modules` but is not reachable from here via a global import, don't bother. | |
var toNodeModules = ts.forEachAncestorDirectory(toPath, function (ancestor) { return ts.getBaseFileName(ancestor) === "node_modules" ? ancestor : undefined; }); | |
var toNodeModulesParent = toNodeModules && ts.getDirectoryPath(getCanonicalFileName(toNodeModules)); | |
@@ -123696,6 +123867,26 @@ var ts; | |
|| ts.startsWith(getCanonicalFileName(fromPath), toNodeModulesParent) | |
|| (!!globalCachePath && ts.startsWith(getCanonicalFileName(globalCachePath), toNodeModulesParent)); | |
} | |
+ function isImportablePathPnp(fromPath, toPath) { | |
+ var pnpApi = getPnpApi(fromPath); | |
+ var fromLocator = pnpApi.findPackageLocator(fromPath); | |
+ var toLocator = pnpApi.findPackageLocator(toPath); | |
+ // eslint-disable-next-line no-null/no-null | |
+ if (toLocator === null) { | |
+ return false; | |
+ } | |
+ var fromInfo = pnpApi.getPackageInformation(fromLocator); | |
+ var toReference = fromInfo.packageDependencies.get(toLocator.name); | |
+ return toReference === toLocator.reference; | |
+ } | |
+ function isImportablePath(fromPath, toPath, getCanonicalFileName, globalCachePath) { | |
+ if (getPnpApi(fromPath)) { | |
+ return isImportablePathPnp(fromPath, toPath); | |
+ } | |
+ else { | |
+ return isImportablePathNode(fromPath, toPath, getCanonicalFileName, globalCachePath); | |
+ } | |
+ } | |
function forEachExternalModuleToImportFrom(program, host, useAutoImportProvider, cb) { | |
var _a, _b; | |
forEachExternalModule(program.getTypeChecker(), program.getSourceFiles(), function (module, file) { return cb(module, file, program, /*isFromPackageJson*/ false); }); | |
@@ -125506,6 +125697,7 @@ var ts; | |
* This includes all files that are found in node_modules/moduleName/ with acceptable file extensions | |
*/ | |
function getCompletionEntriesForNonRelativeModules(fragment, scriptPath, compilerOptions, host, typeChecker) { | |
+ var _a, _b; | |
var baseUrl = compilerOptions.baseUrl, paths = compilerOptions.paths; | |
var result = []; | |
var extensionOptions = getExtensionOptions(compilerOptions); | |
@@ -125518,8 +125710,8 @@ var ts; | |
} | |
} | |
var fragmentDirectory = getFragmentDirectory(fragment); | |
- for (var _i = 0, _a = getAmbientModuleCompletions(fragment, fragmentDirectory, typeChecker); _i < _a.length; _i++) { | |
- var ambientName = _a[_i]; | |
+ for (var _i = 0, _c = getAmbientModuleCompletions(fragment, fragmentDirectory, typeChecker); _i < _c.length; _i++) { | |
+ var ambientName = _c[_i]; | |
result.push(nameAndKind(ambientName, "external module name" /* externalModuleName */, /*extension*/ undefined)); | |
} | |
getCompletionEntriesFromTypings(host, compilerOptions, scriptPath, fragmentDirectory, extensionOptions, result); | |
@@ -125534,18 +125726,36 @@ var ts; | |
result.push(nameAndKind(moduleName, "external module name" /* externalModuleName */, /*extension*/ undefined)); | |
} | |
}; | |
- for (var _b = 0, _c = enumerateNodeModulesVisibleToScript(host, scriptPath); _b < _c.length; _b++) { | |
- var moduleName = _c[_b]; | |
+ for (var _d = 0, _e = enumerateNodeModulesVisibleToScript(host, scriptPath); _d < _e.length; _d++) { | |
+ var moduleName = _e[_d]; | |
_loop_3(moduleName); | |
} | |
} | |
if (!foundGlobal) { | |
- ts.forEachAncestorDirectory(scriptPath, function (ancestor) { | |
- var nodeModules = ts.combinePaths(ancestor, "node_modules"); | |
- if (ts.tryDirectoryExists(host, nodeModules)) { | |
- getCompletionEntriesForDirectoryFragment(fragment, nodeModules, extensionOptions, host, /*exclude*/ undefined, result); | |
+ var pnpapi = (_b = (_a = require("module")).findPnpApi) === null || _b === void 0 ? void 0 : _b.call(_a, scriptPath); | |
+ if (pnpapi) { | |
+ try { | |
+ // Splits a require request into its components, or return null if the request is a file path | |
+ var pathRegExp = /^(?![a-zA-Z]:[\\/]|\\\\|\.{0,2}(?:\/|$))((?:@[^/]+\/)?[^/]+)\/*(.*|)$/; | |
+ var dependencyNameMatch = fragment.match(pathRegExp); | |
+ if (dependencyNameMatch) { | |
+ var dependencyName = dependencyNameMatch[1], subPath = dependencyNameMatch[2]; | |
+ var unqualified = pnpapi.resolveToUnqualified(dependencyName, scriptPath, { considerBuiltins: false }); | |
+ if (unqualified) { | |
+ getCompletionEntriesForDirectoryFragment(subPath, ts.normalizePath(unqualified), extensionOptions, host, /*exclude*/ undefined, result); | |
+ } | |
+ } | |
} | |
- }); | |
+ catch (_f) { } | |
+ } | |
+ else { | |
+ ts.forEachAncestorDirectory(scriptPath, function (ancestor) { | |
+ var nodeModules = ts.combinePaths(ancestor, "node_modules"); | |
+ if (ts.tryDirectoryExists(host, nodeModules)) { | |
+ getCompletionEntriesForDirectoryFragment(fragment, nodeModules, extensionOptions, host, /*exclude*/ undefined, result); | |
+ } | |
+ }); | |
+ } | |
} | |
} | |
return result; | |
@@ -125646,6 +125856,7 @@ var ts; | |
return addReplacementSpans(toComplete, range.pos + prefix.length, names); | |
} | |
function getCompletionEntriesFromTypings(host, options, scriptPath, fragmentDirectory, extensionOptions, result) { | |
+ var _a, _b; | |
if (result === void 0) { result = []; } | |
// Check for typings specified in compiler options | |
var seen = new ts.Map(); | |
@@ -125654,11 +125865,19 @@ var ts; | |
var root = typeRoots_1[_i]; | |
getCompletionEntriesFromDirectories(root); | |
} | |
- // Also get all @types typings installed in visible node_modules directories | |
- for (var _a = 0, _b = ts.findPackageJsons(scriptPath, host); _a < _b.length; _a++) { | |
- var packageJson = _b[_a]; | |
- var typesDir = ts.combinePaths(ts.getDirectoryPath(packageJson), "node_modules/@types"); | |
- getCompletionEntriesFromDirectories(typesDir); | |
+ if ((_b = (_a = require("module")).findPnpApi) === null || _b === void 0 ? void 0 : _b.call(_a, scriptPath)) { | |
+ for (var _c = 0, _d = ts.getPnpTypeRoots(scriptPath); _c < _d.length; _c++) { | |
+ var root = _d[_c]; | |
+ getCompletionEntriesFromDirectories(root); | |
+ } | |
+ } | |
+ else { | |
+ // Also get all @types typings installed in visible node_modules directories | |
+ for (var _e = 0, _f = ts.findPackageJsons(scriptPath, host); _e < _f.length; _e++) { | |
+ var packageJson = _f[_e]; | |
+ var typesDir = ts.combinePaths(ts.getDirectoryPath(packageJson), "node_modules/@types"); | |
+ getCompletionEntriesFromDirectories(typesDir); | |
+ } | |
} | |
return result; | |
function getCompletionEntriesFromDirectories(directory) { | |
@@ -153851,9 +154070,9 @@ var ts; | |
if (isTopLevelDeclarationStatement(statement) && | |
!isExported(sourceFile, statement, useEs6Exports) && | |
forEachTopLevelDeclaration(statement, function (d) { return needExport.has(ts.Debug.checkDefined(d.symbol)); })) { | |
- var exports = addExport(statement, useEs6Exports); | |
- if (exports) | |
- return exports; | |
+ var exports_1 = addExport(statement, useEs6Exports); | |
+ if (exports_1) | |
+ return exports_1; | |
} | |
return statement; | |
}); | |
@@ -162652,6 +162871,37 @@ var ts; | |
return this.projectReferences; | |
}; | |
ConfiguredProject.prototype.updateReferences = function (refs) { | |
+ // @ts-ignore | |
+ if (process.versions.pnp) { | |
+ // With Plug'n'Play, dependencies that list peer dependencies | |
+ // are "virtualized": they are resolved to a unique (virtual) | |
+ // path that the underlying filesystem layer then resolve back | |
+ // to the original location. | |
+ // | |
+ // When a workspace depends on another workspace with peer | |
+ // dependencies, this other workspace will thus be resolved to | |
+ // a unique path that won't match what the initial project has | |
+ // listed in its `references` field, and TS thus won't leverage | |
+ // the reference at all. | |
+ // | |
+ // To avoid that, we compute here the virtualized paths for the | |
+ // user-provided references in our references by directly querying | |
+ // the PnP API. This way users don't have to know the virtual paths, | |
+ // but we still support them just fine even through references. | |
+ var pnpApi_1 = require("pnpapi"); | |
+ var basePath_1 = this.getCurrentDirectory(); | |
+ var getPnpPath_1 = function (path) { | |
+ try { | |
+ var targetLocator = pnpApi_1.findPackageLocator(path + "/"); | |
+ return pnpApi_1.resolveToUnqualified(targetLocator.name, basePath_1 + "/"); | |
+ } | |
+ catch (_a) { | |
+ // something went wrong with the resolution, try not to fail | |
+ return path; | |
+ } | |
+ }; | |
+ refs = refs === null || refs === void 0 ? void 0 : refs.map(function (r) { return (__assign(__assign({}, r), { path: getPnpPath_1(r.path) })); }); | |
+ } | |
this.projectReferences = refs; | |
this.potentialProjectReferences = undefined; | |
}; | |
@@ -163268,6 +163518,7 @@ var ts; | |
watchDirectory: ts.returnNoopFileWatcher, | |
} : | |
ts.getWatchFactory(this.host, watchLogLevel, log, getDetailWatchInfo); | |
+ this.pnpWatcher = this.watchPnpFile(); | |
} | |
ProjectService.prototype.toPath = function (fileName) { | |
return ts.toPath(fileName, this.currentDirectory, this.toCanonicalFileName); | |
@@ -165120,7 +165371,7 @@ var ts; | |
}; | |
ProjectService.prototype.setHostConfiguration = function (args) { | |
var _this = this; | |
- var _a; | |
+ var _a, _b; | |
if (args.file) { | |
var info = this.getScriptInfoForNormalizedPath(server.toNormalizedPath(args.file)); | |
if (info) { | |
@@ -165138,7 +165389,7 @@ var ts; | |
this.logger.info("Format host information updated"); | |
} | |
if (args.preferences) { | |
- var _b = this.hostConfiguration.preferences, lazyConfiguredProjectsFromExternalProject = _b.lazyConfiguredProjectsFromExternalProject, includePackageJsonAutoImports = _b.includePackageJsonAutoImports; | |
+ var _c = this.hostConfiguration.preferences, lazyConfiguredProjectsFromExternalProject = _c.lazyConfiguredProjectsFromExternalProject, includePackageJsonAutoImports = _c.includePackageJsonAutoImports; | |
this.hostConfiguration.preferences = __assign(__assign({}, this.hostConfiguration.preferences), args.preferences); | |
if (lazyConfiguredProjectsFromExternalProject && !this.hostConfiguration.preferences.lazyConfiguredProjectsFromExternalProject) { | |
// Load configured projects for external projects that are pending reload | |
@@ -165164,6 +165415,8 @@ var ts; | |
if (args.watchOptions) { | |
this.hostConfiguration.watchOptions = (_a = convertWatchOptions(args.watchOptions)) === null || _a === void 0 ? void 0 : _a.watchOptions; | |
this.logger.info("Host watch options changed to " + JSON.stringify(this.hostConfiguration.watchOptions) + ", it will be take effect for next watches."); | |
+ (_b = this.pnpWatcher) === null || _b === void 0 ? void 0 : _b.close(); | |
+ this.watchPnpFile(); | |
} | |
} | |
}; | |
@@ -166158,6 +166411,25 @@ var ts; | |
}); | |
}; | |
/*@internal*/ | |
+ ProjectService.prototype.watchPnpFile = function () { | |
+ var _this = this; | |
+ if (typeof process.versions.pnp === "undefined") { | |
+ return; | |
+ } | |
+ var pnpFileName = require.resolve("pnpapi"); | |
+ return this.watchFactory.watchFile(pnpFileName, function () { | |
+ _this.forEachProject(function (project) { | |
+ for (var _i = 0, _a = project.getScriptInfos(); _i < _a.length; _i++) { | |
+ var info = _a[_i]; | |
+ project.resolutionCache.invalidateResolutionOfFile(info.path); | |
+ } | |
+ project.markAsDirty(); | |
+ updateProjectIfDirty(project); | |
+ }); | |
+ _this.delayEnsureProjectForOpenFiles(); | |
+ }, ts.PollingInterval.Low, this.hostConfiguration.watchOptions, ts.WatchType.ConfigFile); | |
+ }; | |
+ /*@internal*/ | |
ProjectService.prototype.watchPackageJsonFile = function (path) { | |
var _this = this; | |
var watchers = this.packageJsonFilesMap || (this.packageJsonFilesMap = new ts.Map()); | |
@@ -171029,6 +171301,9 @@ var ts; | |
} | |
try { | |
var args = [ts.combinePaths(__dirname, "watchGuard.js"), path]; | |
+ if (typeof process.versions.pnp !== "undefined") { | |
+ args.unshift('-r', require.resolve('pnpapi')); | |
+ } | |
if (logger.hasLevel(server.LogLevel.verbose)) { | |
logger.info("Starting " + process.execPath + " with args:" + server.stringifyIndented(args)); | |
} | |
@@ -171289,6 +171564,9 @@ var ts; | |
break; | |
} | |
} | |
+ if (typeof process.versions.pnp !== "undefined") { | |
+ execArgv.unshift('-r', require.resolve('pnpapi')); | |
+ } | |
this.installer = childProcess.fork(ts.combinePaths(__dirname, "typingsInstaller.js"), args, { execArgv: execArgv }); | |
this.installer.on("message", function (m) { return _this.handleMessage(m); }); | |
// We have to schedule this event to the next tick | |
diff --git a/lib/tsserverlibrary.d.ts b/lib/tsserverlibrary.d.ts | |
index 581d70b71..93b185e08 100644 | |
semver exclusivity 4.4.2 | |
--- a/lib/tsserverlibrary.d.ts | |
+++ b/lib/tsserverlibrary.d.ts | |
@@ -4759,6 +4759,7 @@ declare namespace ts { | |
} | |
declare namespace ts { | |
export function getEffectiveTypeRoots(options: CompilerOptions, host: GetEffectiveTypeRootsHost): string[] | undefined; | |
+ export function getPnpTypeRoots(currentDirectory: string): string[]; | |
/** | |
* @param {string | undefined} containingFile - file that contains type reference directive, can be undefined if containing file is unknown. | |
* This is possible in case if resolution is performed for directives specified via 'types' parameter. In this case initial path for secondary lookups | |
diff --git a/lib/tsserverlibrary.js b/lib/tsserverlibrary.js | |
index 5fa1cd290..0c97c83ad 100644 | |
semver exclusivity 4.4.2 | |
--- a/lib/tsserverlibrary.js | |
+++ b/lib/tsserverlibrary.js | |
@@ -7652,6 +7652,11 @@ var ts; | |
: new Buffer(input, encoding); | |
} | |
function isFileSystemCaseSensitive() { | |
+ // The PnP runtime is always case-sensitive | |
+ // @ts-ignore | |
+ if (process.versions.pnp) { | |
+ return true; | |
+ } | |
// win32\win64 are case insensitive platforms | |
if (platform === "win32" || platform === "win64") { | |
return false; | |
@@ -41161,24 +41166,56 @@ var ts; | |
ts.getEffectiveTypeRoots = getEffectiveTypeRoots; | |
/** | |
* Returns the path to every node_modules/@types directory from some ancestor directory. | |
- * Returns undefined if there are none. | |
*/ | |
- function getDefaultTypeRoots(currentDirectory, host) { | |
+ function getNodeModulesTypeRoots(currentDirectory, host) { | |
if (!host.directoryExists) { | |
return [ts.combinePaths(currentDirectory, nodeModulesAtTypes)]; | |
// And if it doesn't exist, tough. | |
} | |
- var typeRoots; | |
+ var typeRoots = []; | |
ts.forEachAncestorDirectory(ts.normalizePath(currentDirectory), function (directory) { | |
var atTypes = ts.combinePaths(directory, nodeModulesAtTypes); | |
if (host.directoryExists(atTypes)) { | |
- (typeRoots || (typeRoots = [])).push(atTypes); | |
+ typeRoots.push(atTypes); | |
} | |
return undefined; | |
}); | |
return typeRoots; | |
} | |
var nodeModulesAtTypes = ts.combinePaths("node_modules", "@types"); | |
+ function getPnpTypeRoots(currentDirectory) { | |
+ var pnpapi = getPnpApi(currentDirectory); | |
+ if (!pnpapi) { | |
+ return []; | |
+ } | |
+ // Some TS consumers pass relative paths that aren't normalized | |
+ currentDirectory = ts.sys.resolvePath(currentDirectory); | |
+ var currentPackage = pnpapi.findPackageLocator(currentDirectory + "/"); | |
+ if (!currentPackage) { | |
+ return []; | |
+ } | |
+ var packageDependencies = pnpapi.getPackageInformation(currentPackage).packageDependencies; | |
+ var typeRoots = []; | |
+ for (var _i = 0, _a = Array.from(packageDependencies.entries()); _i < _a.length; _i++) { | |
+ var _b = _a[_i], name = _b[0], referencish = _b[1]; | |
+ // eslint-disable-next-line no-null/no-null | |
+ if (name.startsWith(typesPackagePrefix) && referencish !== null) { | |
+ var dependencyLocator = pnpapi.getLocator(name, referencish); | |
+ var packageLocation = pnpapi.getPackageInformation(dependencyLocator).packageLocation; | |
+ typeRoots.push(ts.getDirectoryPath(packageLocation)); | |
+ } | |
+ } | |
+ return typeRoots; | |
+ } | |
+ ts.getPnpTypeRoots = getPnpTypeRoots; | |
+ var typesPackagePrefix = "@types/"; | |
+ function getDefaultTypeRoots(currentDirectory, host) { | |
+ var nmTypes = getNodeModulesTypeRoots(currentDirectory, host); | |
+ var pnpTypes = getPnpTypeRoots(currentDirectory); | |
+ if (nmTypes.length > 0 || pnpTypes.length > 0) { | |
+ return __spreadArray(__spreadArray([], nmTypes, true), pnpTypes, true); | |
+ } | |
+ } | |
/** | |
* @param {string | undefined} containingFile - file that contains type reference directive, can be undefined if containing file is unknown. | |
* This is possible in case if resolution is performed for directives specified via 'types' parameter. In this case initial path for secondary lookups | |
@@ -41292,7 +41329,9 @@ var ts; | |
} | |
var result_4; | |
if (!ts.isExternalModuleNameRelative(typeReferenceDirectiveName)) { | |
- var searchResult = loadModuleFromNearestNodeModulesDirectory(Extensions.DtsOnly, typeReferenceDirectiveName, initialLocationForSecondaryLookup, moduleResolutionState, /*cache*/ undefined, /*redirectedReference*/ undefined); | |
+ var searchResult = getPnpApi(initialLocationForSecondaryLookup) | |
+ ? tryLoadModuleUsingPnpResolution(Extensions.DtsOnly, typeReferenceDirectiveName, initialLocationForSecondaryLookup, moduleResolutionState) | |
+ : loadModuleFromNearestNodeModulesDirectory(Extensions.DtsOnly, typeReferenceDirectiveName, initialLocationForSecondaryLookup, moduleResolutionState, /*cache*/ undefined, /*redirectedReference*/ undefined); | |
result_4 = searchResult && searchResult.value; | |
} | |
else { | |
@@ -41847,9 +41886,12 @@ var ts; | |
if (traceEnabled) { | |
trace(host, ts.Diagnostics.Loading_module_0_from_node_modules_folder_target_file_type_1, moduleName, Extensions[extensions]); | |
} | |
- var resolved_1 = loadModuleFromNearestNodeModulesDirectory(extensions, moduleName, containingDirectory, state, cache, redirectedReference); | |
- if (!resolved_1) | |
+ var resolved_1 = getPnpApi(containingDirectory) | |
+ ? tryLoadModuleUsingPnpResolution(extensions, moduleName, containingDirectory, state) | |
+ : loadModuleFromNearestNodeModulesDirectory(extensions, moduleName, containingDirectory, state, cache, redirectedReference); | |
+ if (!resolved_1) { | |
return undefined; | |
+ } | |
var resolvedValue = resolved_1.value; | |
if (!compilerOptions.preserveSymlinks && resolvedValue && !resolvedValue.originalPath) { | |
var path = realPath(resolvedValue.path, host, traceEnabled); | |
@@ -42194,6 +42236,14 @@ var ts; | |
} | |
function loadModuleFromSpecificNodeModulesDirectory(extensions, moduleName, nodeModulesDirectory, nodeModulesDirectoryExists, state) { | |
var candidate = ts.normalizePath(ts.combinePaths(nodeModulesDirectory, moduleName)); | |
+ return loadModuleFromSpecificNodeModulesDirectoryImpl(extensions, moduleName, nodeModulesDirectory, nodeModulesDirectoryExists, state, candidate, undefined, undefined); | |
+ } | |
+ function loadModuleFromPnpResolution(extensions, packageDirectory, rest, state) { | |
+ var candidate = ts.normalizePath(ts.combinePaths(packageDirectory, rest)); | |
+ return loadModuleFromSpecificNodeModulesDirectoryImpl(extensions, undefined, undefined, true, state, candidate, rest, packageDirectory); | |
+ } | |
+ function loadModuleFromSpecificNodeModulesDirectoryImpl(extensions, moduleName, nodeModulesDirectory, nodeModulesDirectoryExists, state, candidate, rest, packageDirectory) { | |
+ var _a; | |
// First look for a nested package.json, as in `node_modules/foo/bar/package.json`. | |
var packageInfo = getPackageJsonInfo(candidate, !nodeModulesDirectoryExists, state); | |
if (packageInfo) { | |
@@ -42209,9 +42259,12 @@ var ts; | |
loadNodeModuleFromDirectoryWorker(extensions, candidate, onlyRecordFailures, state, packageInfo && packageInfo.packageJsonContent, packageInfo && packageInfo.versionPaths); | |
return withPackageId(packageInfo, pathAndExtension); | |
}; | |
- var _a = parsePackageName(moduleName), packageName = _a.packageName, rest = _a.rest; | |
+ var packageName; | |
+ if (rest === undefined) | |
+ (_a = parsePackageName(moduleName), packageName = _a.packageName, rest = _a.rest); | |
if (rest !== "") { // If "rest" is empty, we just did this search above. | |
- var packageDirectory = ts.combinePaths(nodeModulesDirectory, packageName); | |
+ if (packageDirectory === undefined) | |
+ packageDirectory = ts.combinePaths(nodeModulesDirectory, packageName); | |
// Don't use a "types" or "main" from here because we're not loading the root, but a subdirectory -- just here for the packageId and path mappings. | |
packageInfo = getPackageJsonInfo(packageDirectory, !nodeModulesDirectoryExists, state); | |
if (packageInfo && packageInfo.versionPaths) { | |
@@ -42370,6 +42423,58 @@ var ts; | |
function toSearchResult(value) { | |
return value !== undefined ? { value: value } : undefined; | |
} | |
+ /** | |
+ * We only allow PnP to be used as a resolution strategy if TypeScript | |
+ * itself is executed under a PnP runtime (and we only allow it to access | |
+ * the current PnP runtime, not any on the disk). This ensures that we | |
+ * don't execute potentially malicious code that didn't already have a | |
+ * chance to be executed (if we're running within the runtime, it means | |
+ * that the runtime has already been executed). | |
+ * @internal | |
+ */ | |
+ function getPnpApi(path) { | |
+ var findPnpApi = require("module").findPnpApi; | |
+ if (findPnpApi === undefined) { | |
+ return undefined; | |
+ } | |
+ return findPnpApi(path + "/"); | |
+ } | |
+ function loadPnpPackageResolution(packageName, containingDirectory) { | |
+ try { | |
+ var resolution = getPnpApi(containingDirectory).resolveToUnqualified(packageName, containingDirectory + "/", { considerBuiltins: false }); | |
+ return ts.normalizeSlashes(resolution); | |
+ } | |
+ catch (_a) { | |
+ // Nothing to do | |
+ } | |
+ } | |
+ function loadPnpTypePackageResolution(packageName, containingDirectory) { | |
+ return loadPnpPackageResolution(getTypesPackageName(packageName), containingDirectory); | |
+ } | |
+ /* @internal */ | |
+ function tryLoadModuleUsingPnpResolution(extensions, moduleName, containingDirectory, state) { | |
+ var _a = parsePackageName(moduleName), packageName = _a.packageName, rest = _a.rest; | |
+ var packageResolution = loadPnpPackageResolution(packageName, containingDirectory); | |
+ var packageFullResolution = packageResolution | |
+ ? loadModuleFromPnpResolution(extensions, packageResolution, rest, state) | |
+ : undefined; | |
+ var resolved; | |
+ if (packageFullResolution) { | |
+ resolved = packageFullResolution; | |
+ } | |
+ else if (extensions === Extensions.TypeScript || extensions === Extensions.DtsOnly) { | |
+ var typePackageResolution = loadPnpTypePackageResolution(packageName, containingDirectory); | |
+ var typePackageFullResolution = typePackageResolution | |
+ ? loadModuleFromPnpResolution(Extensions.DtsOnly, typePackageResolution, rest, state) | |
+ : undefined; | |
+ if (typePackageFullResolution) { | |
+ resolved = typePackageFullResolution; | |
+ } | |
+ } | |
+ if (resolved) { | |
+ return toSearchResult(resolved); | |
+ } | |
+ } | |
})(ts || (ts = {})); | |
/* @internal */ | |
var ts; | |
@@ -110713,6 +110818,8 @@ var ts; | |
ConfigFileProgramReloadLevel[ConfigFileProgramReloadLevel["Partial"] = 1] = "Partial"; | |
/** Reload completely by re-reading contents of config file from disk and updating program */ | |
ConfigFileProgramReloadLevel[ConfigFileProgramReloadLevel["Full"] = 2] = "Full"; | |
+ /** Reload the resolutions */ | |
+ ConfigFileProgramReloadLevel[ConfigFileProgramReloadLevel["Resolutions"] = 3] = "Resolutions"; | |
})(ConfigFileProgramReloadLevel = ts.ConfigFileProgramReloadLevel || (ts.ConfigFileProgramReloadLevel = {})); | |
/** | |
* Updates the map of shared extended config file watches with a new set of extended config files from a base config file of the project | |
@@ -117283,6 +117390,29 @@ var ts; | |
return undefined; | |
} | |
var parts = getNodeModulePathParts(path); | |
+ var packageName; | |
+ if (!parts && typeof process.versions.pnp !== "undefined") { | |
+ var pnpApi = require("pnpapi"); | |
+ var locator = pnpApi.findPackageLocator(path); | |
+ // eslint-disable-next-line no-null/no-null | |
+ if (locator !== null) { | |
+ var sourceLocator = pnpApi.findPackageLocator(sourceDirectory + "/"); | |
+ // Don't use the package name when the imported file is inside | |
+ // the source directory (prefer a relative path instead) | |
+ if (locator === sourceLocator) { | |
+ return undefined; | |
+ } | |
+ var information = pnpApi.getPackageInformation(locator); | |
+ packageName = locator.name; | |
+ parts = { | |
+ topLevelNodeModulesIndex: undefined, | |
+ topLevelPackageNameIndex: undefined, | |
+ // The last character from packageLocation is the trailing "/", we want to point to it | |
+ packageRootIndex: information.packageLocation.length - 1, | |
+ fileNameIndex: path.lastIndexOf("/"), | |
+ }; | |
+ } | |
+ } | |
if (!parts) { | |
return undefined; | |
} | |
@@ -117313,18 +117443,24 @@ var ts; | |
if (isRedirect && !isPackageRootPath) { | |
return undefined; | |
} | |
- var globalTypingsCacheLocation = host.getGlobalTypingsCacheLocation && host.getGlobalTypingsCacheLocation(); | |
- // Get a path that's relative to node_modules or the importing file's path | |
- // if node_modules folder is in this folder or any of its parent folders, no need to keep it. | |
- var pathToTopLevelNodeModules = getCanonicalFileName(moduleSpecifier.substring(0, parts.topLevelNodeModulesIndex)); | |
- if (!(ts.startsWith(sourceDirectory, pathToTopLevelNodeModules) || globalTypingsCacheLocation && ts.startsWith(getCanonicalFileName(globalTypingsCacheLocation), pathToTopLevelNodeModules))) { | |
- return undefined; | |
+ // If PnP is enabled the node_modules entries we'll get will always be relevant even if they | |
+ // are located in a weird path apparently outside of the source directory | |
+ if (typeof process.versions.pnp === "undefined") { | |
+ var globalTypingsCacheLocation = host.getGlobalTypingsCacheLocation && host.getGlobalTypingsCacheLocation(); | |
+ // Get a path that's relative to node_modules or the importing file's path | |
+ // if node_modules folder is in this folder or any of its parent folders, no need to keep it. | |
+ var pathToTopLevelNodeModules = getCanonicalFileName(moduleSpecifier.substring(0, parts.topLevelNodeModulesIndex)); | |
+ if (!(ts.startsWith(sourceDirectory, pathToTopLevelNodeModules) || globalTypingsCacheLocation && ts.startsWith(getCanonicalFileName(globalTypingsCacheLocation), pathToTopLevelNodeModules))) { | |
+ return undefined; | |
+ } | |
} | |
// If the module was found in @types, get the actual Node package name | |
- var nodeModulesDirectoryName = moduleSpecifier.substring(parts.topLevelPackageNameIndex + 1); | |
- var packageName = ts.getPackageNameFromTypesPackageName(nodeModulesDirectoryName); | |
+ var nodeModulesDirectoryName = typeof packageName !== "undefined" | |
+ ? packageName + moduleSpecifier.substring(parts.packageRootIndex) | |
+ : moduleSpecifier.substring(parts.topLevelPackageNameIndex + 1); | |
+ var packageNameFromPath = ts.getPackageNameFromTypesPackageName(nodeModulesDirectoryName); | |
// For classic resolution, only allow importing from node_modules/@types, not other node_modules | |
- return ts.getEmitModuleResolutionKind(options) !== ts.ModuleResolutionKind.NodeJs && packageName === nodeModulesDirectoryName ? undefined : packageName; | |
+ return ts.getEmitModuleResolutionKind(options) !== ts.ModuleResolutionKind.NodeJs && packageNameFromPath === nodeModulesDirectoryName ? undefined : packageNameFromPath; | |
function tryDirectoryWithPackageJson(packageRootIndex) { | |
var packageRootPath = path.substring(0, packageRootIndex); | |
var packageJsonPath = ts.combinePaths(packageRootPath, "package.json"); | |
@@ -118118,6 +118254,10 @@ var ts; | |
if (configFileName) { | |
configFileWatcher = watchFile(configFileName, scheduleProgramReload, ts.PollingInterval.High, watchOptions, ts.WatchType.ConfigFile); | |
} | |
+ var pnpFileWatcher; | |
+ if (typeof process.versions.pnp !== "undefined") { | |
+ pnpFileWatcher = watchFile(require.resolve("pnpapi"), scheduleResolutionReload, ts.PollingInterval.High, watchOptions, ts.WatchType.ConfigFile); | |
+ } | |
var compilerHost = ts.createCompilerHostFromProgramHost(host, function () { return compilerOptions; }, directoryStructureHost); | |
ts.setGetSourceFileAsHashVersioned(compilerHost, host); | |
// Members for CompilerHost | |
@@ -118196,6 +118336,10 @@ var ts; | |
configFileWatcher.close(); | |
configFileWatcher = undefined; | |
} | |
+ if (pnpFileWatcher) { | |
+ pnpFileWatcher.close(); | |
+ pnpFileWatcher = undefined; | |
+ } | |
extendedConfigCache === null || extendedConfigCache === void 0 ? void 0 : extendedConfigCache.clear(); | |
extendedConfigCache = undefined; | |
if (sharedExtendedConfigFileWatchers) { | |
@@ -118228,7 +118372,8 @@ var ts; | |
function getCurrentProgram() { | |
return builderProgram && builderProgram.getProgramOrUndefined(); | |
} | |
- function synchronizeProgram() { | |
+ function synchronizeProgram(forceAllFilesAsInvalidated) { | |
+ if (forceAllFilesAsInvalidated === void 0) { forceAllFilesAsInvalidated = false; } | |
writeLog("Synchronizing program"); | |
clearInvalidateResolutionsOfFailedLookupLocations(); | |
var program = getCurrentBuilderProgram(); | |
@@ -118239,7 +118384,7 @@ var ts; | |
} | |
} | |
// All resolutions are invalid if user provided resolutions | |
- var hasInvalidatedResolution = resolutionCache.createHasInvalidatedResolution(userProvidedResolution || changesAffectResolution); | |
+ var hasInvalidatedResolution = resolutionCache.createHasInvalidatedResolution(userProvidedResolution || forceAllFilesAsInvalidated); | |
if (ts.isProgramUptoDate(getCurrentProgram(), rootFileNames, compilerOptions, getSourceVersion, fileExists, hasInvalidatedResolution, hasChangedAutomaticTypeDirectiveNames, getParsedCommandLine, projectReferences)) { | |
if (hasChangedConfigFileParsingErrors) { | |
builderProgram = createProgram(/*rootNames*/ undefined, /*options*/ undefined, compilerHost, builderProgram, configFileParsingDiagnostics, projectReferences); | |
@@ -118446,6 +118591,12 @@ var ts; | |
reloadLevel = ts.ConfigFileProgramReloadLevel.Full; | |
scheduleProgramUpdate(); | |
} | |
+ function scheduleResolutionReload() { | |
+ writeLog("Clearing resolutions"); | |
+ resolutionCache.clear(); | |
+ reloadLevel = ts.ConfigFileProgramReloadLevel.Resolutions; | |
+ scheduleProgramUpdate(); | |
+ } | |
function updateProgramWithWatchStatus() { | |
timerToUpdateProgram = undefined; | |
reportWatchDiagnostic(ts.Diagnostics.File_change_detected_Starting_incremental_compilation); | |
@@ -118461,6 +118612,10 @@ var ts; | |
ts.perfLogger.logStartUpdateProgram("FullConfigReload"); | |
reloadConfigFile(); | |
break; | |
+ case ts.ConfigFileProgramReloadLevel.Resolutions: | |
+ ts.perfLogger.logStartUpdateProgram("SynchronizeProgramWithResolutions"); | |
+ synchronizeProgram(/*forceAllFilesAsInvalidated*/ true); | |
+ break; | |
default: | |
ts.perfLogger.logStartUpdateProgram("SynchronizeProgram"); | |
synchronizeProgram(); | |
@@ -124266,11 +124421,27 @@ var ts; | |
return hasImportablePath; | |
} | |
ts.isImportableFile = isImportableFile; | |
+ /** | |
+ * We only allow PnP to be used as a resolution strategy if TypeScript | |
+ * itself is executed under a PnP runtime (and we only allow it to access | |
+ * the current PnP runtime, not any on the disk). This ensures that we | |
+ * don't execute potentially malicious code that didn't already have a | |
+ * chance to be executed (if we're running within the runtime, it means | |
+ * that the runtime has already been executed). | |
+ * @internal | |
+ */ | |
+ function getPnpApi(path) { | |
+ var findPnpApi = require("module").findPnpApi; | |
+ if (findPnpApi === undefined) { | |
+ return undefined; | |
+ } | |
+ return findPnpApi(path + "/"); | |
+ } | |
/** | |
* Don't include something from a `node_modules` that isn't actually reachable by a global import. | |
* A relative import to node_modules is usually a bad idea. | |
*/ | |
- function isImportablePath(fromPath, toPath, getCanonicalFileName, globalCachePath) { | |
+ function isImportablePathNode(fromPath, toPath, getCanonicalFileName, globalCachePath) { | |
// If it's in a `node_modules` but is not reachable from here via a global import, don't bother. | |
var toNodeModules = ts.forEachAncestorDirectory(toPath, function (ancestor) { return ts.getBaseFileName(ancestor) === "node_modules" ? ancestor : undefined; }); | |
var toNodeModulesParent = toNodeModules && ts.getDirectoryPath(getCanonicalFileName(toNodeModules)); | |
@@ -124278,6 +124449,26 @@ var ts; | |
|| ts.startsWith(getCanonicalFileName(fromPath), toNodeModulesParent) | |
|| (!!globalCachePath && ts.startsWith(getCanonicalFileName(globalCachePath), toNodeModulesParent)); | |
} | |
+ function isImportablePathPnp(fromPath, toPath) { | |
+ var pnpApi = getPnpApi(fromPath); | |
+ var fromLocator = pnpApi.findPackageLocator(fromPath); | |
+ var toLocator = pnpApi.findPackageLocator(toPath); | |
+ // eslint-disable-next-line no-null/no-null | |
+ if (toLocator === null) { | |
+ return false; | |
+ } | |
+ var fromInfo = pnpApi.getPackageInformation(fromLocator); | |
+ var toReference = fromInfo.packageDependencies.get(toLocator.name); | |
+ return toReference === toLocator.reference; | |
+ } | |
+ function isImportablePath(fromPath, toPath, getCanonicalFileName, globalCachePath) { | |
+ if (getPnpApi(fromPath)) { | |
+ return isImportablePathPnp(fromPath, toPath); | |
+ } | |
+ else { | |
+ return isImportablePathNode(fromPath, toPath, getCanonicalFileName, globalCachePath); | |
+ } | |
+ } | |
function forEachExternalModuleToImportFrom(program, host, useAutoImportProvider, cb) { | |
var _a, _b; | |
forEachExternalModule(program.getTypeChecker(), program.getSourceFiles(), function (module, file) { return cb(module, file, program, /*isFromPackageJson*/ false); }); | |
@@ -126088,6 +126279,7 @@ var ts; | |
* This includes all files that are found in node_modules/moduleName/ with acceptable file extensions | |
*/ | |
function getCompletionEntriesForNonRelativeModules(fragment, scriptPath, compilerOptions, host, typeChecker) { | |
+ var _a, _b; | |
var baseUrl = compilerOptions.baseUrl, paths = compilerOptions.paths; | |
var result = []; | |
var extensionOptions = getExtensionOptions(compilerOptions); | |
@@ -126100,8 +126292,8 @@ var ts; | |
} | |
} | |
var fragmentDirectory = getFragmentDirectory(fragment); | |
- for (var _i = 0, _a = getAmbientModuleCompletions(fragment, fragmentDirectory, typeChecker); _i < _a.length; _i++) { | |
- var ambientName = _a[_i]; | |
+ for (var _i = 0, _c = getAmbientModuleCompletions(fragment, fragmentDirectory, typeChecker); _i < _c.length; _i++) { | |
+ var ambientName = _c[_i]; | |
result.push(nameAndKind(ambientName, "external module name" /* externalModuleName */, /*extension*/ undefined)); | |
} | |
getCompletionEntriesFromTypings(host, compilerOptions, scriptPath, fragmentDirectory, extensionOptions, result); | |
@@ -126116,18 +126308,36 @@ var ts; | |
result.push(nameAndKind(moduleName, "external module name" /* externalModuleName */, /*extension*/ undefined)); | |
} | |
}; | |
- for (var _b = 0, _c = enumerateNodeModulesVisibleToScript(host, scriptPath); _b < _c.length; _b++) { | |
- var moduleName = _c[_b]; | |
+ for (var _d = 0, _e = enumerateNodeModulesVisibleToScript(host, scriptPath); _d < _e.length; _d++) { | |
+ var moduleName = _e[_d]; | |
_loop_3(moduleName); | |
} | |
} | |
if (!foundGlobal) { | |
- ts.forEachAncestorDirectory(scriptPath, function (ancestor) { | |
- var nodeModules = ts.combinePaths(ancestor, "node_modules"); | |
- if (ts.tryDirectoryExists(host, nodeModules)) { | |
- getCompletionEntriesForDirectoryFragment(fragment, nodeModules, extensionOptions, host, /*exclude*/ undefined, result); | |
+ var pnpapi = (_b = (_a = require("module")).findPnpApi) === null || _b === void 0 ? void 0 : _b.call(_a, scriptPath); | |
+ if (pnpapi) { | |
+ try { | |
+ // Splits a require request into its components, or return null if the request is a file path | |
+ var pathRegExp = /^(?![a-zA-Z]:[\\/]|\\\\|\.{0,2}(?:\/|$))((?:@[^/]+\/)?[^/]+)\/*(.*|)$/; | |
+ var dependencyNameMatch = fragment.match(pathRegExp); | |
+ if (dependencyNameMatch) { | |
+ var dependencyName = dependencyNameMatch[1], subPath = dependencyNameMatch[2]; | |
+ var unqualified = pnpapi.resolveToUnqualified(dependencyName, scriptPath, { considerBuiltins: false }); | |
+ if (unqualified) { | |
+ getCompletionEntriesForDirectoryFragment(subPath, ts.normalizePath(unqualified), extensionOptions, host, /*exclude*/ undefined, result); | |
+ } | |
+ } | |
} | |
- }); | |
+ catch (_f) { } | |
+ } | |
+ else { | |
+ ts.forEachAncestorDirectory(scriptPath, function (ancestor) { | |
+ var nodeModules = ts.combinePaths(ancestor, "node_modules"); | |
+ if (ts.tryDirectoryExists(host, nodeModules)) { | |
+ getCompletionEntriesForDirectoryFragment(fragment, nodeModules, extensionOptions, host, /*exclude*/ undefined, result); | |
+ } | |
+ }); | |
+ } | |
} | |
} | |
return result; | |
@@ -126228,6 +126438,7 @@ var ts; | |
return addReplacementSpans(toComplete, range.pos + prefix.length, names); | |
} | |
function getCompletionEntriesFromTypings(host, options, scriptPath, fragmentDirectory, extensionOptions, result) { | |
+ var _a, _b; | |
if (result === void 0) { result = []; } | |
// Check for typings specified in compiler options | |
var seen = new ts.Map(); | |
@@ -126236,11 +126447,19 @@ var ts; | |
var root = typeRoots_1[_i]; | |
getCompletionEntriesFromDirectories(root); | |
} | |
- // Also get all @types typings installed in visible node_modules directories | |
- for (var _a = 0, _b = ts.findPackageJsons(scriptPath, host); _a < _b.length; _a++) { | |
- var packageJson = _b[_a]; | |
- var typesDir = ts.combinePaths(ts.getDirectoryPath(packageJson), "node_modules/@types"); | |
- getCompletionEntriesFromDirectories(typesDir); | |
+ if ((_b = (_a = require("module")).findPnpApi) === null || _b === void 0 ? void 0 : _b.call(_a, scriptPath)) { | |
+ for (var _c = 0, _d = ts.getPnpTypeRoots(scriptPath); _c < _d.length; _c++) { | |
+ var root = _d[_c]; | |
+ getCompletionEntriesFromDirectories(root); | |
+ } | |
+ } | |
+ else { | |
+ // Also get all @types typings installed in visible node_modules directories | |
+ for (var _e = 0, _f = ts.findPackageJsons(scriptPath, host); _e < _f.length; _e++) { | |
+ var packageJson = _f[_e]; | |
+ var typesDir = ts.combinePaths(ts.getDirectoryPath(packageJson), "node_modules/@types"); | |
+ getCompletionEntriesFromDirectories(typesDir); | |
+ } | |
} | |
return result; | |
function getCompletionEntriesFromDirectories(directory) { | |
@@ -154433,9 +154652,9 @@ var ts; | |
if (isTopLevelDeclarationStatement(statement) && | |
!isExported(sourceFile, statement, useEs6Exports) && | |
forEachTopLevelDeclaration(statement, function (d) { return needExport.has(ts.Debug.checkDefined(d.symbol)); })) { | |
- var exports = addExport(statement, useEs6Exports); | |
- if (exports) | |
- return exports; | |
+ var exports_1 = addExport(statement, useEs6Exports); | |
+ if (exports_1) | |
+ return exports_1; | |
} | |
return statement; | |
}); | |
@@ -162846,6 +163065,37 @@ var ts; | |
return this.projectReferences; | |
}; | |
ConfiguredProject.prototype.updateReferences = function (refs) { | |
+ // @ts-ignore | |
+ if (process.versions.pnp) { | |
+ // With Plug'n'Play, dependencies that list peer dependencies | |
+ // are "virtualized": they are resolved to a unique (virtual) | |
+ // path that the underlying filesystem layer then resolve back | |
+ // to the original location. | |
+ // | |
+ // When a workspace depends on another workspace with peer | |
+ // dependencies, this other workspace will thus be resolved to | |
+ // a unique path that won't match what the initial project has | |
+ // listed in its `references` field, and TS thus won't leverage | |
+ // the reference at all. | |
+ // | |
+ // To avoid that, we compute here the virtualized paths for the | |
+ // user-provided references in our references by directly querying | |
+ // the PnP API. This way users don't have to know the virtual paths, | |
+ // but we still support them just fine even through references. | |
+ var pnpApi_1 = require("pnpapi"); | |
+ var basePath_1 = this.getCurrentDirectory(); | |
+ var getPnpPath_1 = function (path) { | |
+ try { | |
+ var targetLocator = pnpApi_1.findPackageLocator(path + "/"); | |
+ return pnpApi_1.resolveToUnqualified(targetLocator.name, basePath_1 + "/"); | |
+ } | |
+ catch (_a) { | |
+ // something went wrong with the resolution, try not to fail | |
+ return path; | |
+ } | |
+ }; | |
+ refs = refs === null || refs === void 0 ? void 0 : refs.map(function (r) { return (__assign(__assign({}, r), { path: getPnpPath_1(r.path) })); }); | |
+ } | |
this.projectReferences = refs; | |
this.potentialProjectReferences = undefined; | |
}; | |
@@ -163462,6 +163712,7 @@ var ts; | |
watchDirectory: ts.returnNoopFileWatcher, | |
} : | |
ts.getWatchFactory(this.host, watchLogLevel, log, getDetailWatchInfo); | |
+ this.pnpWatcher = this.watchPnpFile(); | |
} | |
ProjectService.prototype.toPath = function (fileName) { | |
return ts.toPath(fileName, this.currentDirectory, this.toCanonicalFileName); | |
@@ -165314,7 +165565,7 @@ var ts; | |
}; | |
ProjectService.prototype.setHostConfiguration = function (args) { | |
var _this = this; | |
- var _a; | |
+ var _a, _b; | |
if (args.file) { | |
var info = this.getScriptInfoForNormalizedPath(server.toNormalizedPath(args.file)); | |
if (info) { | |
@@ -165332,7 +165583,7 @@ var ts; | |
this.logger.info("Format host information updated"); | |
} | |
if (args.preferences) { | |
- var _b = this.hostConfiguration.preferences, lazyConfiguredProjectsFromExternalProject = _b.lazyConfiguredProjectsFromExternalProject, includePackageJsonAutoImports = _b.includePackageJsonAutoImports; | |
+ var _c = this.hostConfiguration.preferences, lazyConfiguredProjectsFromExternalProject = _c.lazyConfiguredProjectsFromExternalProject, includePackageJsonAutoImports = _c.includePackageJsonAutoImports; | |
this.hostConfiguration.preferences = __assign(__assign({}, this.hostConfiguration.preferences), args.preferences); | |
if (lazyConfiguredProjectsFromExternalProject && !this.hostConfiguration.preferences.lazyConfiguredProjectsFromExternalProject) { | |
// Load configured projects for external projects that are pending reload | |
@@ -165358,6 +165609,8 @@ var ts; | |
if (args.watchOptions) { | |
this.hostConfiguration.watchOptions = (_a = convertWatchOptions(args.watchOptions)) === null || _a === void 0 ? void 0 : _a.watchOptions; | |
this.logger.info("Host watch options changed to " + JSON.stringify(this.hostConfiguration.watchOptions) + ", it will be take effect for next watches."); | |
+ (_b = this.pnpWatcher) === null || _b === void 0 ? void 0 : _b.close(); | |
+ this.watchPnpFile(); | |
} | |
} | |
}; | |
@@ -166352,6 +166605,25 @@ var ts; | |
}); | |
}; | |
/*@internal*/ | |
+ ProjectService.prototype.watchPnpFile = function () { | |
+ var _this = this; | |
+ if (typeof process.versions.pnp === "undefined") { | |
+ return; | |
+ } | |
+ var pnpFileName = require.resolve("pnpapi"); | |
+ return this.watchFactory.watchFile(pnpFileName, function () { | |
+ _this.forEachProject(function (project) { | |
+ for (var _i = 0, _a = project.getScriptInfos(); _i < _a.length; _i++) { | |
+ var info = _a[_i]; | |
+ project.resolutionCache.invalidateResolutionOfFile(info.path); | |
+ } | |
+ project.markAsDirty(); | |
+ updateProjectIfDirty(project); | |
+ }); | |
+ _this.delayEnsureProjectForOpenFiles(); | |
+ }, ts.PollingInterval.Low, this.hostConfiguration.watchOptions, ts.WatchType.ConfigFile); | |
+ }; | |
+ /*@internal*/ | |
ProjectService.prototype.watchPackageJsonFile = function (path) { | |
var _this = this; | |
var watchers = this.packageJsonFilesMap || (this.packageJsonFilesMap = new ts.Map()); | |
diff --git a/lib/typescript.d.ts b/lib/typescript.d.ts | |
index 4902d45ad..f512e9e8c 100644 | |
semver exclusivity 4.4.2 | |
--- a/lib/typescript.d.ts | |
+++ b/lib/typescript.d.ts | |
@@ -4759,6 +4759,7 @@ declare namespace ts { | |
} | |
declare namespace ts { | |
export function getEffectiveTypeRoots(options: CompilerOptions, host: GetEffectiveTypeRootsHost): string[] | undefined; | |
+ export function getPnpTypeRoots(currentDirectory: string): string[]; | |
/** | |
* @param {string | undefined} containingFile - file that contains type reference directive, can be undefined if containing file is unknown. | |
* This is possible in case if resolution is performed for directives specified via 'types' parameter. In this case initial path for secondary lookups | |
diff --git a/lib/typescript.js b/lib/typescript.js | |
index 44462973f..07a9ef8fa 100644 | |
semver exclusivity 4.4.2 | |
--- a/lib/typescript.js | |
+++ b/lib/typescript.js | |
@@ -7652,6 +7652,11 @@ var ts; | |
: new Buffer(input, encoding); | |
} | |
function isFileSystemCaseSensitive() { | |
+ // The PnP runtime is always case-sensitive | |
+ // @ts-ignore | |
+ if (process.versions.pnp) { | |
+ return true; | |
+ } | |
// win32\win64 are case insensitive platforms | |
if (platform === "win32" || platform === "win64") { | |
return false; | |
@@ -41161,24 +41166,56 @@ var ts; | |
ts.getEffectiveTypeRoots = getEffectiveTypeRoots; | |
/** | |
* Returns the path to every node_modules/@types directory from some ancestor directory. | |
- * Returns undefined if there are none. | |
*/ | |
- function getDefaultTypeRoots(currentDirectory, host) { | |
+ function getNodeModulesTypeRoots(currentDirectory, host) { | |
if (!host.directoryExists) { | |
return [ts.combinePaths(currentDirectory, nodeModulesAtTypes)]; | |
// And if it doesn't exist, tough. | |
} | |
- var typeRoots; | |
+ var typeRoots = []; | |
ts.forEachAncestorDirectory(ts.normalizePath(currentDirectory), function (directory) { | |
var atTypes = ts.combinePaths(directory, nodeModulesAtTypes); | |
if (host.directoryExists(atTypes)) { | |
- (typeRoots || (typeRoots = [])).push(atTypes); | |
+ typeRoots.push(atTypes); | |
} | |
return undefined; | |
}); | |
return typeRoots; | |
} | |
var nodeModulesAtTypes = ts.combinePaths("node_modules", "@types"); | |
+ function getPnpTypeRoots(currentDirectory) { | |
+ var pnpapi = getPnpApi(currentDirectory); | |
+ if (!pnpapi) { | |
+ return []; | |
+ } | |
+ // Some TS consumers pass relative paths that aren't normalized | |
+ currentDirectory = ts.sys.resolvePath(currentDirectory); | |
+ var currentPackage = pnpapi.findPackageLocator(currentDirectory + "/"); | |
+ if (!currentPackage) { | |
+ return []; | |
+ } | |
+ var packageDependencies = pnpapi.getPackageInformation(currentPackage).packageDependencies; | |
+ var typeRoots = []; | |
+ for (var _i = 0, _a = Array.from(packageDependencies.entries()); _i < _a.length; _i++) { | |
+ var _b = _a[_i], name = _b[0], referencish = _b[1]; | |
+ // eslint-disable-next-line no-null/no-null | |
+ if (name.startsWith(typesPackagePrefix) && referencish !== null) { | |
+ var dependencyLocator = pnpapi.getLocator(name, referencish); | |
+ var packageLocation = pnpapi.getPackageInformation(dependencyLocator).packageLocation; | |
+ typeRoots.push(ts.getDirectoryPath(packageLocation)); | |
+ } | |
+ } | |
+ return typeRoots; | |
+ } | |
+ ts.getPnpTypeRoots = getPnpTypeRoots; | |
+ var typesPackagePrefix = "@types/"; | |
+ function getDefaultTypeRoots(currentDirectory, host) { | |
+ var nmTypes = getNodeModulesTypeRoots(currentDirectory, host); | |
+ var pnpTypes = getPnpTypeRoots(currentDirectory); | |
+ if (nmTypes.length > 0 || pnpTypes.length > 0) { | |
+ return __spreadArray(__spreadArray([], nmTypes, true), pnpTypes, true); | |
+ } | |
+ } | |
/** | |
* @param {string | undefined} containingFile - file that contains type reference directive, can be undefined if containing file is unknown. | |
* This is possible in case if resolution is performed for directives specified via 'types' parameter. In this case initial path for secondary lookups | |
@@ -41292,7 +41329,9 @@ var ts; | |
} | |
var result_4; | |
if (!ts.isExternalModuleNameRelative(typeReferenceDirectiveName)) { | |
- var searchResult = loadModuleFromNearestNodeModulesDirectory(Extensions.DtsOnly, typeReferenceDirectiveName, initialLocationForSecondaryLookup, moduleResolutionState, /*cache*/ undefined, /*redirectedReference*/ undefined); | |
+ var searchResult = getPnpApi(initialLocationForSecondaryLookup) | |
+ ? tryLoadModuleUsingPnpResolution(Extensions.DtsOnly, typeReferenceDirectiveName, initialLocationForSecondaryLookup, moduleResolutionState) | |
+ : loadModuleFromNearestNodeModulesDirectory(Extensions.DtsOnly, typeReferenceDirectiveName, initialLocationForSecondaryLookup, moduleResolutionState, /*cache*/ undefined, /*redirectedReference*/ undefined); | |
result_4 = searchResult && searchResult.value; | |
} | |
else { | |
@@ -41847,9 +41886,12 @@ var ts; | |
if (traceEnabled) { | |
trace(host, ts.Diagnostics.Loading_module_0_from_node_modules_folder_target_file_type_1, moduleName, Extensions[extensions]); | |
} | |
- var resolved_1 = loadModuleFromNearestNodeModulesDirectory(extensions, moduleName, containingDirectory, state, cache, redirectedReference); | |
- if (!resolved_1) | |
+ var resolved_1 = getPnpApi(containingDirectory) | |
+ ? tryLoadModuleUsingPnpResolution(extensions, moduleName, containingDirectory, state) | |
+ : loadModuleFromNearestNodeModulesDirectory(extensions, moduleName, containingDirectory, state, cache, redirectedReference); | |
+ if (!resolved_1) { | |
return undefined; | |
+ } | |
var resolvedValue = resolved_1.value; | |
if (!compilerOptions.preserveSymlinks && resolvedValue && !resolvedValue.originalPath) { | |
var path = realPath(resolvedValue.path, host, traceEnabled); | |
@@ -42194,6 +42236,14 @@ var ts; | |
} | |
function loadModuleFromSpecificNodeModulesDirectory(extensions, moduleName, nodeModulesDirectory, nodeModulesDirectoryExists, state) { | |
var candidate = ts.normalizePath(ts.combinePaths(nodeModulesDirectory, moduleName)); | |
+ return loadModuleFromSpecificNodeModulesDirectoryImpl(extensions, moduleName, nodeModulesDirectory, nodeModulesDirectoryExists, state, candidate, undefined, undefined); | |
+ } | |
+ function loadModuleFromPnpResolution(extensions, packageDirectory, rest, state) { | |
+ var candidate = ts.normalizePath(ts.combinePaths(packageDirectory, rest)); | |
+ return loadModuleFromSpecificNodeModulesDirectoryImpl(extensions, undefined, undefined, true, state, candidate, rest, packageDirectory); | |
+ } | |
+ function loadModuleFromSpecificNodeModulesDirectoryImpl(extensions, moduleName, nodeModulesDirectory, nodeModulesDirectoryExists, state, candidate, rest, packageDirectory) { | |
+ var _a; | |
// First look for a nested package.json, as in `node_modules/foo/bar/package.json`. | |
var packageInfo = getPackageJsonInfo(candidate, !nodeModulesDirectoryExists, state); | |
if (packageInfo) { | |
@@ -42209,9 +42259,12 @@ var ts; | |
loadNodeModuleFromDirectoryWorker(extensions, candidate, onlyRecordFailures, state, packageInfo && packageInfo.packageJsonContent, packageInfo && packageInfo.versionPaths); | |
return withPackageId(packageInfo, pathAndExtension); | |
}; | |
- var _a = parsePackageName(moduleName), packageName = _a.packageName, rest = _a.rest; | |
+ var packageName; | |
+ if (rest === undefined) | |
+ (_a = parsePackageName(moduleName), packageName = _a.packageName, rest = _a.rest); | |
if (rest !== "") { // If "rest" is empty, we just did this search above. | |
- var packageDirectory = ts.combinePaths(nodeModulesDirectory, packageName); | |
+ if (packageDirectory === undefined) | |
+ packageDirectory = ts.combinePaths(nodeModulesDirectory, packageName); | |
// Don't use a "types" or "main" from here because we're not loading the root, but a subdirectory -- just here for the packageId and path mappings. | |
packageInfo = getPackageJsonInfo(packageDirectory, !nodeModulesDirectoryExists, state); | |
if (packageInfo && packageInfo.versionPaths) { | |
@@ -42370,6 +42423,58 @@ var ts; | |
function toSearchResult(value) { | |
return value !== undefined ? { value: value } : undefined; | |
} | |
+ /** | |
+ * We only allow PnP to be used as a resolution strategy if TypeScript | |
+ * itself is executed under a PnP runtime (and we only allow it to access | |
+ * the current PnP runtime, not any on the disk). This ensures that we | |
+ * don't execute potentially malicious code that didn't already have a | |
+ * chance to be executed (if we're running within the runtime, it means | |
+ * that the runtime has already been executed). | |
+ * @internal | |
+ */ | |
+ function getPnpApi(path) { | |
+ var findPnpApi = require("module").findPnpApi; | |
+ if (findPnpApi === undefined) { | |
+ return undefined; | |
+ } | |
+ return findPnpApi(path + "/"); | |
+ } | |
+ function loadPnpPackageResolution(packageName, containingDirectory) { | |
+ try { | |
+ var resolution = getPnpApi(containingDirectory).resolveToUnqualified(packageName, containingDirectory + "/", { considerBuiltins: false }); | |
+ return ts.normalizeSlashes(resolution); | |
+ } | |
+ catch (_a) { | |
+ // Nothing to do | |
+ } | |
+ } | |
+ function loadPnpTypePackageResolution(packageName, containingDirectory) { | |
+ return loadPnpPackageResolution(getTypesPackageName(packageName), containingDirectory); | |
+ } | |
+ /* @internal */ | |
+ function tryLoadModuleUsingPnpResolution(extensions, moduleName, containingDirectory, state) { | |
+ var _a = parsePackageName(moduleName), packageName = _a.packageName, rest = _a.rest; | |
+ var packageResolution = loadPnpPackageResolution(packageName, containingDirectory); | |
+ var packageFullResolution = packageResolution | |
+ ? loadModuleFromPnpResolution(extensions, packageResolution, rest, state) | |
+ : undefined; | |
+ var resolved; | |
+ if (packageFullResolution) { | |
+ resolved = packageFullResolution; | |
+ } | |
+ else if (extensions === Extensions.TypeScript || extensions === Extensions.DtsOnly) { | |
+ var typePackageResolution = loadPnpTypePackageResolution(packageName, containingDirectory); | |
+ var typePackageFullResolution = typePackageResolution | |
+ ? loadModuleFromPnpResolution(Extensions.DtsOnly, typePackageResolution, rest, state) | |
+ : undefined; | |
+ if (typePackageFullResolution) { | |
+ resolved = typePackageFullResolution; | |
+ } | |
+ } | |
+ if (resolved) { | |
+ return toSearchResult(resolved); | |
+ } | |
+ } | |
})(ts || (ts = {})); | |
/* @internal */ | |
var ts; | |
@@ -110713,6 +110818,8 @@ var ts; | |
ConfigFileProgramReloadLevel[ConfigFileProgramReloadLevel["Partial"] = 1] = "Partial"; | |
/** Reload completely by re-reading contents of config file from disk and updating program */ | |
ConfigFileProgramReloadLevel[ConfigFileProgramReloadLevel["Full"] = 2] = "Full"; | |
+ /** Reload the resolutions */ | |
+ ConfigFileProgramReloadLevel[ConfigFileProgramReloadLevel["Resolutions"] = 3] = "Resolutions"; | |
})(ConfigFileProgramReloadLevel = ts.ConfigFileProgramReloadLevel || (ts.ConfigFileProgramReloadLevel = {})); | |
/** | |
* Updates the map of shared extended config file watches with a new set of extended config files from a base config file of the project | |
@@ -117283,6 +117390,29 @@ var ts; | |
return undefined; | |
} | |
var parts = getNodeModulePathParts(path); | |
+ var packageName; | |
+ if (!parts && typeof process.versions.pnp !== "undefined") { | |
+ var pnpApi = require("pnpapi"); | |
+ var locator = pnpApi.findPackageLocator(path); | |
+ // eslint-disable-next-line no-null/no-null | |
+ if (locator !== null) { | |
+ var sourceLocator = pnpApi.findPackageLocator(sourceDirectory + "/"); | |
+ // Don't use the package name when the imported file is inside | |
+ // the source directory (prefer a relative path instead) | |
+ if (locator === sourceLocator) { | |
+ return undefined; | |
+ } | |
+ var information = pnpApi.getPackageInformation(locator); | |
+ packageName = locator.name; | |
+ parts = { | |
+ topLevelNodeModulesIndex: undefined, | |
+ topLevelPackageNameIndex: undefined, | |
+ // The last character from packageLocation is the trailing "/", we want to point to it | |
+ packageRootIndex: information.packageLocation.length - 1, | |
+ fileNameIndex: path.lastIndexOf("/"), | |
+ }; | |
+ } | |
+ } | |
if (!parts) { | |
return undefined; | |
} | |
@@ -117313,18 +117443,24 @@ var ts; | |
if (isRedirect && !isPackageRootPath) { | |
return undefined; | |
} | |
- var globalTypingsCacheLocation = host.getGlobalTypingsCacheLocation && host.getGlobalTypingsCacheLocation(); | |
- // Get a path that's relative to node_modules or the importing file's path | |
- // if node_modules folder is in this folder or any of its parent folders, no need to keep it. | |
- var pathToTopLevelNodeModules = getCanonicalFileName(moduleSpecifier.substring(0, parts.topLevelNodeModulesIndex)); | |
- if (!(ts.startsWith(sourceDirectory, pathToTopLevelNodeModules) || globalTypingsCacheLocation && ts.startsWith(getCanonicalFileName(globalTypingsCacheLocation), pathToTopLevelNodeModules))) { | |
- return undefined; | |
+ // If PnP is enabled the node_modules entries we'll get will always be relevant even if they | |
+ // are located in a weird path apparently outside of the source directory | |
+ if (typeof process.versions.pnp === "undefined") { | |
+ var globalTypingsCacheLocation = host.getGlobalTypingsCacheLocation && host.getGlobalTypingsCacheLocation(); | |
+ // Get a path that's relative to node_modules or the importing file's path | |
+ // if node_modules folder is in this folder or any of its parent folders, no need to keep it. | |
+ var pathToTopLevelNodeModules = getCanonicalFileName(moduleSpecifier.substring(0, parts.topLevelNodeModulesIndex)); | |
+ if (!(ts.startsWith(sourceDirectory, pathToTopLevelNodeModules) || globalTypingsCacheLocation && ts.startsWith(getCanonicalFileName(globalTypingsCacheLocation), pathToTopLevelNodeModules))) { | |
+ return undefined; | |
+ } | |
} | |
// If the module was found in @types, get the actual Node package name | |
- var nodeModulesDirectoryName = moduleSpecifier.substring(parts.topLevelPackageNameIndex + 1); | |
- var packageName = ts.getPackageNameFromTypesPackageName(nodeModulesDirectoryName); | |
+ var nodeModulesDirectoryName = typeof packageName !== "undefined" | |
+ ? packageName + moduleSpecifier.substring(parts.packageRootIndex) | |
+ : moduleSpecifier.substring(parts.topLevelPackageNameIndex + 1); | |
+ var packageNameFromPath = ts.getPackageNameFromTypesPackageName(nodeModulesDirectoryName); | |
// For classic resolution, only allow importing from node_modules/@types, not other node_modules | |
- return ts.getEmitModuleResolutionKind(options) !== ts.ModuleResolutionKind.NodeJs && packageName === nodeModulesDirectoryName ? undefined : packageName; | |
+ return ts.getEmitModuleResolutionKind(options) !== ts.ModuleResolutionKind.NodeJs && packageNameFromPath === nodeModulesDirectoryName ? undefined : packageNameFromPath; | |
function tryDirectoryWithPackageJson(packageRootIndex) { | |
var packageRootPath = path.substring(0, packageRootIndex); | |
var packageJsonPath = ts.combinePaths(packageRootPath, "package.json"); | |
@@ -118118,6 +118254,10 @@ var ts; | |
if (configFileName) { | |
configFileWatcher = watchFile(configFileName, scheduleProgramReload, ts.PollingInterval.High, watchOptions, ts.WatchType.ConfigFile); | |
} | |
+ var pnpFileWatcher; | |
+ if (typeof process.versions.pnp !== "undefined") { | |
+ pnpFileWatcher = watchFile(require.resolve("pnpapi"), scheduleResolutionReload, ts.PollingInterval.High, watchOptions, ts.WatchType.ConfigFile); | |
+ } | |
var compilerHost = ts.createCompilerHostFromProgramHost(host, function () { return compilerOptions; }, directoryStructureHost); | |
ts.setGetSourceFileAsHashVersioned(compilerHost, host); | |
// Members for CompilerHost | |
@@ -118196,6 +118336,10 @@ var ts; | |
configFileWatcher.close(); | |
configFileWatcher = undefined; | |
} | |
+ if (pnpFileWatcher) { | |
+ pnpFileWatcher.close(); | |
+ pnpFileWatcher = undefined; | |
+ } | |
extendedConfigCache === null || extendedConfigCache === void 0 ? void 0 : extendedConfigCache.clear(); | |
extendedConfigCache = undefined; | |
if (sharedExtendedConfigFileWatchers) { | |
@@ -118228,7 +118372,8 @@ var ts; | |
function getCurrentProgram() { | |
return builderProgram && builderProgram.getProgramOrUndefined(); | |
} | |
- function synchronizeProgram() { | |
+ function synchronizeProgram(forceAllFilesAsInvalidated) { | |
+ if (forceAllFilesAsInvalidated === void 0) { forceAllFilesAsInvalidated = false; } | |
writeLog("Synchronizing program"); | |
clearInvalidateResolutionsOfFailedLookupLocations(); | |
var program = getCurrentBuilderProgram(); | |
@@ -118239,7 +118384,7 @@ var ts; | |
} | |
} | |
// All resolutions are invalid if user provided resolutions | |
- var hasInvalidatedResolution = resolutionCache.createHasInvalidatedResolution(userProvidedResolution || changesAffectResolution); | |
+ var hasInvalidatedResolution = resolutionCache.createHasInvalidatedResolution(userProvidedResolution || forceAllFilesAsInvalidated); | |
if (ts.isProgramUptoDate(getCurrentProgram(), rootFileNames, compilerOptions, getSourceVersion, fileExists, hasInvalidatedResolution, hasChangedAutomaticTypeDirectiveNames, getParsedCommandLine, projectReferences)) { | |
if (hasChangedConfigFileParsingErrors) { | |
builderProgram = createProgram(/*rootNames*/ undefined, /*options*/ undefined, compilerHost, builderProgram, configFileParsingDiagnostics, projectReferences); | |
@@ -118446,6 +118591,12 @@ var ts; | |
reloadLevel = ts.ConfigFileProgramReloadLevel.Full; | |
scheduleProgramUpdate(); | |
} | |
+ function scheduleResolutionReload() { | |
+ writeLog("Clearing resolutions"); | |
+ resolutionCache.clear(); | |
+ reloadLevel = ts.ConfigFileProgramReloadLevel.Resolutions; | |
+ scheduleProgramUpdate(); | |
+ } | |
function updateProgramWithWatchStatus() { | |
timerToUpdateProgram = undefined; | |
reportWatchDiagnostic(ts.Diagnostics.File_change_detected_Starting_incremental_compilation); | |
@@ -118461,6 +118612,10 @@ var ts; | |
ts.perfLogger.logStartUpdateProgram("FullConfigReload"); | |
reloadConfigFile(); | |
break; | |
+ case ts.ConfigFileProgramReloadLevel.Resolutions: | |
+ ts.perfLogger.logStartUpdateProgram("SynchronizeProgramWithResolutions"); | |
+ synchronizeProgram(/*forceAllFilesAsInvalidated*/ true); | |
+ break; | |
default: | |
ts.perfLogger.logStartUpdateProgram("SynchronizeProgram"); | |
synchronizeProgram(); | |
@@ -124266,11 +124421,27 @@ var ts; | |
return hasImportablePath; | |
} | |
ts.isImportableFile = isImportableFile; | |
+ /** | |
+ * We only allow PnP to be used as a resolution strategy if TypeScript | |
+ * itself is executed under a PnP runtime (and we only allow it to access | |
+ * the current PnP runtime, not any on the disk). This ensures that we | |
+ * don't execute potentially malicious code that didn't already have a | |
+ * chance to be executed (if we're running within the runtime, it means | |
+ * that the runtime has already been executed). | |
+ * @internal | |
+ */ | |
+ function getPnpApi(path) { | |
+ var findPnpApi = require("module").findPnpApi; | |
+ if (findPnpApi === undefined) { | |
+ return undefined; | |
+ } | |
+ return findPnpApi(path + "/"); | |
+ } | |
/** | |
* Don't include something from a `node_modules` that isn't actually reachable by a global import. | |
* A relative import to node_modules is usually a bad idea. | |
*/ | |
- function isImportablePath(fromPath, toPath, getCanonicalFileName, globalCachePath) { | |
+ function isImportablePathNode(fromPath, toPath, getCanonicalFileName, globalCachePath) { | |
// If it's in a `node_modules` but is not reachable from here via a global import, don't bother. | |
var toNodeModules = ts.forEachAncestorDirectory(toPath, function (ancestor) { return ts.getBaseFileName(ancestor) === "node_modules" ? ancestor : undefined; }); | |
var toNodeModulesParent = toNodeModules && ts.getDirectoryPath(getCanonicalFileName(toNodeModules)); | |
@@ -124278,6 +124449,26 @@ var ts; | |
|| ts.startsWith(getCanonicalFileName(fromPath), toNodeModulesParent) | |
|| (!!globalCachePath && ts.startsWith(getCanonicalFileName(globalCachePath), toNodeModulesParent)); | |
} | |
+ function isImportablePathPnp(fromPath, toPath) { | |
+ var pnpApi = getPnpApi(fromPath); | |
+ var fromLocator = pnpApi.findPackageLocator(fromPath); | |
+ var toLocator = pnpApi.findPackageLocator(toPath); | |
+ // eslint-disable-next-line no-null/no-null | |
+ if (toLocator === null) { | |
+ return false; | |
+ } | |
+ var fromInfo = pnpApi.getPackageInformation(fromLocator); | |
+ var toReference = fromInfo.packageDependencies.get(toLocator.name); | |
+ return toReference === toLocator.reference; | |
+ } | |
+ function isImportablePath(fromPath, toPath, getCanonicalFileName, globalCachePath) { | |
+ if (getPnpApi(fromPath)) { | |
+ return isImportablePathPnp(fromPath, toPath); | |
+ } | |
+ else { | |
+ return isImportablePathNode(fromPath, toPath, getCanonicalFileName, globalCachePath); | |
+ } | |
+ } | |
function forEachExternalModuleToImportFrom(program, host, useAutoImportProvider, cb) { | |
var _a, _b; | |
forEachExternalModule(program.getTypeChecker(), program.getSourceFiles(), function (module, file) { return cb(module, file, program, /*isFromPackageJson*/ false); }); | |
@@ -126088,6 +126279,7 @@ var ts; | |
* This includes all files that are found in node_modules/moduleName/ with acceptable file extensions | |
*/ | |
function getCompletionEntriesForNonRelativeModules(fragment, scriptPath, compilerOptions, host, typeChecker) { | |
+ var _a, _b; | |
var baseUrl = compilerOptions.baseUrl, paths = compilerOptions.paths; | |
var result = []; | |
var extensionOptions = getExtensionOptions(compilerOptions); | |
@@ -126100,8 +126292,8 @@ var ts; | |
} | |
} | |
var fragmentDirectory = getFragmentDirectory(fragment); | |
- for (var _i = 0, _a = getAmbientModuleCompletions(fragment, fragmentDirectory, typeChecker); _i < _a.length; _i++) { | |
- var ambientName = _a[_i]; | |
+ for (var _i = 0, _c = getAmbientModuleCompletions(fragment, fragmentDirectory, typeChecker); _i < _c.length; _i++) { | |
+ var ambientName = _c[_i]; | |
result.push(nameAndKind(ambientName, "external module name" /* externalModuleName */, /*extension*/ undefined)); | |
} | |
getCompletionEntriesFromTypings(host, compilerOptions, scriptPath, fragmentDirectory, extensionOptions, result); | |
@@ -126116,18 +126308,36 @@ var ts; | |
result.push(nameAndKind(moduleName, "external module name" /* externalModuleName */, /*extension*/ undefined)); | |
} | |
}; | |
- for (var _b = 0, _c = enumerateNodeModulesVisibleToScript(host, scriptPath); _b < _c.length; _b++) { | |
- var moduleName = _c[_b]; | |
+ for (var _d = 0, _e = enumerateNodeModulesVisibleToScript(host, scriptPath); _d < _e.length; _d++) { | |
+ var moduleName = _e[_d]; | |
_loop_3(moduleName); | |
} | |
} | |
if (!foundGlobal) { | |
- ts.forEachAncestorDirectory(scriptPath, function (ancestor) { | |
- var nodeModules = ts.combinePaths(ancestor, "node_modules"); | |
- if (ts.tryDirectoryExists(host, nodeModules)) { | |
- getCompletionEntriesForDirectoryFragment(fragment, nodeModules, extensionOptions, host, /*exclude*/ undefined, result); | |
+ var pnpapi = (_b = (_a = require("module")).findPnpApi) === null || _b === void 0 ? void 0 : _b.call(_a, scriptPath); | |
+ if (pnpapi) { | |
+ try { | |
+ // Splits a require request into its components, or return null if the request is a file path | |
+ var pathRegExp = /^(?![a-zA-Z]:[\\/]|\\\\|\.{0,2}(?:\/|$))((?:@[^/]+\/)?[^/]+)\/*(.*|)$/; | |
+ var dependencyNameMatch = fragment.match(pathRegExp); | |
+ if (dependencyNameMatch) { | |
+ var dependencyName = dependencyNameMatch[1], subPath = dependencyNameMatch[2]; | |
+ var unqualified = pnpapi.resolveToUnqualified(dependencyName, scriptPath, { considerBuiltins: false }); | |
+ if (unqualified) { | |
+ getCompletionEntriesForDirectoryFragment(subPath, ts.normalizePath(unqualified), extensionOptions, host, /*exclude*/ undefined, result); | |
+ } | |
+ } | |
} | |
- }); | |
+ catch (_f) { } | |
+ } | |
+ else { | |
+ ts.forEachAncestorDirectory(scriptPath, function (ancestor) { | |
+ var nodeModules = ts.combinePaths(ancestor, "node_modules"); | |
+ if (ts.tryDirectoryExists(host, nodeModules)) { | |
+ getCompletionEntriesForDirectoryFragment(fragment, nodeModules, extensionOptions, host, /*exclude*/ undefined, result); | |
+ } | |
+ }); | |
+ } | |
} | |
} | |
return result; | |
@@ -126228,6 +126438,7 @@ var ts; | |
return addReplacementSpans(toComplete, range.pos + prefix.length, names); | |
} | |
function getCompletionEntriesFromTypings(host, options, scriptPath, fragmentDirectory, extensionOptions, result) { | |
+ var _a, _b; | |
if (result === void 0) { result = []; } | |
// Check for typings specified in compiler options | |
var seen = new ts.Map(); | |
@@ -126236,11 +126447,19 @@ var ts; | |
var root = typeRoots_1[_i]; | |
getCompletionEntriesFromDirectories(root); | |
} | |
- // Also get all @types typings installed in visible node_modules directories | |
- for (var _a = 0, _b = ts.findPackageJsons(scriptPath, host); _a < _b.length; _a++) { | |
- var packageJson = _b[_a]; | |
- var typesDir = ts.combinePaths(ts.getDirectoryPath(packageJson), "node_modules/@types"); | |
- getCompletionEntriesFromDirectories(typesDir); | |
+ if ((_b = (_a = require("module")).findPnpApi) === null || _b === void 0 ? void 0 : _b.call(_a, scriptPath)) { | |
+ for (var _c = 0, _d = ts.getPnpTypeRoots(scriptPath); _c < _d.length; _c++) { | |
+ var root = _d[_c]; | |
+ getCompletionEntriesFromDirectories(root); | |
+ } | |
+ } | |
+ else { | |
+ // Also get all @types typings installed in visible node_modules directories | |
+ for (var _e = 0, _f = ts.findPackageJsons(scriptPath, host); _e < _f.length; _e++) { | |
+ var packageJson = _f[_e]; | |
+ var typesDir = ts.combinePaths(ts.getDirectoryPath(packageJson), "node_modules/@types"); | |
+ getCompletionEntriesFromDirectories(typesDir); | |
+ } | |
} | |
return result; | |
function getCompletionEntriesFromDirectories(directory) { | |
@@ -154433,9 +154652,9 @@ var ts; | |
if (isTopLevelDeclarationStatement(statement) && | |
!isExported(sourceFile, statement, useEs6Exports) && | |
forEachTopLevelDeclaration(statement, function (d) { return needExport.has(ts.Debug.checkDefined(d.symbol)); })) { | |
- var exports = addExport(statement, useEs6Exports); | |
- if (exports) | |
- return exports; | |
+ var exports_1 = addExport(statement, useEs6Exports); | |
+ if (exports_1) | |
+ return exports_1; | |
} | |
return statement; | |
}); | |
diff --git a/lib/typescriptServices.d.ts b/lib/typescriptServices.d.ts | |
index c4e5e624c..1ff41ed4d 100644 | |
semver exclusivity 4.4.2 | |
--- a/lib/typescriptServices.d.ts | |
+++ b/lib/typescriptServices.d.ts | |
@@ -4759,6 +4759,7 @@ declare namespace ts { | |
} | |
declare namespace ts { | |
export function getEffectiveTypeRoots(options: CompilerOptions, host: GetEffectiveTypeRootsHost): string[] | undefined; | |
+ export function getPnpTypeRoots(currentDirectory: string): string[]; | |
/** | |
* @param {string | undefined} containingFile - file that contains type reference directive, can be undefined if containing file is unknown. | |
* This is possible in case if resolution is performed for directives specified via 'types' parameter. In this case initial path for secondary lookups | |
diff --git a/lib/typescriptServices.js b/lib/typescriptServices.js | |
index 20a6fc52e..7c5460b03 100644 | |
semver exclusivity 4.4.2 | |
--- a/lib/typescriptServices.js | |
+++ b/lib/typescriptServices.js | |
@@ -7652,6 +7652,11 @@ var ts; | |
: new Buffer(input, encoding); | |
} | |
function isFileSystemCaseSensitive() { | |
+ // The PnP runtime is always case-sensitive | |
+ // @ts-ignore | |
+ if (process.versions.pnp) { | |
+ return true; | |
+ } | |
// win32\win64 are case insensitive platforms | |
if (platform === "win32" || platform === "win64") { | |
return false; | |
@@ -41161,24 +41166,56 @@ var ts; | |
ts.getEffectiveTypeRoots = getEffectiveTypeRoots; | |
/** | |
* Returns the path to every node_modules/@types directory from some ancestor directory. | |
- * Returns undefined if there are none. | |
*/ | |
- function getDefaultTypeRoots(currentDirectory, host) { | |
+ function getNodeModulesTypeRoots(currentDirectory, host) { | |
if (!host.directoryExists) { | |
return [ts.combinePaths(currentDirectory, nodeModulesAtTypes)]; | |
// And if it doesn't exist, tough. | |
} | |
- var typeRoots; | |
+ var typeRoots = []; | |
ts.forEachAncestorDirectory(ts.normalizePath(currentDirectory), function (directory) { | |
var atTypes = ts.combinePaths(directory, nodeModulesAtTypes); | |
if (host.directoryExists(atTypes)) { | |
- (typeRoots || (typeRoots = [])).push(atTypes); | |
+ typeRoots.push(atTypes); | |
} | |
return undefined; | |
}); | |
return typeRoots; | |
} | |
var nodeModulesAtTypes = ts.combinePaths("node_modules", "@types"); | |
+ function getPnpTypeRoots(currentDirectory) { | |
+ var pnpapi = getPnpApi(currentDirectory); | |
+ if (!pnpapi) { | |
+ return []; | |
+ } | |
+ // Some TS consumers pass relative paths that aren't normalized | |
+ currentDirectory = ts.sys.resolvePath(currentDirectory); | |
+ var currentPackage = pnpapi.findPackageLocator(currentDirectory + "/"); | |
+ if (!currentPackage) { | |
+ return []; | |
+ } | |
+ var packageDependencies = pnpapi.getPackageInformation(currentPackage).packageDependencies; | |
+ var typeRoots = []; | |
+ for (var _i = 0, _a = Array.from(packageDependencies.entries()); _i < _a.length; _i++) { | |
+ var _b = _a[_i], name = _b[0], referencish = _b[1]; | |
+ // eslint-disable-next-line no-null/no-null | |
+ if (name.startsWith(typesPackagePrefix) && referencish !== null) { | |
+ var dependencyLocator = pnpapi.getLocator(name, referencish); | |
+ var packageLocation = pnpapi.getPackageInformation(dependencyLocator).packageLocation; | |
+ typeRoots.push(ts.getDirectoryPath(packageLocation)); | |
+ } | |
+ } | |
+ return typeRoots; | |
+ } | |
+ ts.getPnpTypeRoots = getPnpTypeRoots; | |
+ var typesPackagePrefix = "@types/"; | |
+ function getDefaultTypeRoots(currentDirectory, host) { | |
+ var nmTypes = getNodeModulesTypeRoots(currentDirectory, host); | |
+ var pnpTypes = getPnpTypeRoots(currentDirectory); | |
+ if (nmTypes.length > 0 || pnpTypes.length > 0) { | |
+ return __spreadArray(__spreadArray([], nmTypes, true), pnpTypes, true); | |
+ } | |
+ } | |
/** | |
* @param {string | undefined} containingFile - file that contains type reference directive, can be undefined if containing file is unknown. | |
* This is possible in case if resolution is performed for directives specified via 'types' parameter. In this case initial path for secondary lookups | |
@@ -41292,7 +41329,9 @@ var ts; | |
} | |
var result_4; | |
if (!ts.isExternalModuleNameRelative(typeReferenceDirectiveName)) { | |
- var searchResult = loadModuleFromNearestNodeModulesDirectory(Extensions.DtsOnly, typeReferenceDirectiveName, initialLocationForSecondaryLookup, moduleResolutionState, /*cache*/ undefined, /*redirectedReference*/ undefined); | |
+ var searchResult = getPnpApi(initialLocationForSecondaryLookup) | |
+ ? tryLoadModuleUsingPnpResolution(Extensions.DtsOnly, typeReferenceDirectiveName, initialLocationForSecondaryLookup, moduleResolutionState) | |
+ : loadModuleFromNearestNodeModulesDirectory(Extensions.DtsOnly, typeReferenceDirectiveName, initialLocationForSecondaryLookup, moduleResolutionState, /*cache*/ undefined, /*redirectedReference*/ undefined); | |
result_4 = searchResult && searchResult.value; | |
} | |
else { | |
@@ -41847,9 +41886,12 @@ var ts; | |
if (traceEnabled) { | |
trace(host, ts.Diagnostics.Loading_module_0_from_node_modules_folder_target_file_type_1, moduleName, Extensions[extensions]); | |
} | |
- var resolved_1 = loadModuleFromNearestNodeModulesDirectory(extensions, moduleName, containingDirectory, state, cache, redirectedReference); | |
- if (!resolved_1) | |
+ var resolved_1 = getPnpApi(containingDirectory) | |
+ ? tryLoadModuleUsingPnpResolution(extensions, moduleName, containingDirectory, state) | |
+ : loadModuleFromNearestNodeModulesDirectory(extensions, moduleName, containingDirectory, state, cache, redirectedReference); | |
+ if (!resolved_1) { | |
return undefined; | |
+ } | |
var resolvedValue = resolved_1.value; | |
if (!compilerOptions.preserveSymlinks && resolvedValue && !resolvedValue.originalPath) { | |
var path = realPath(resolvedValue.path, host, traceEnabled); | |
@@ -42194,6 +42236,14 @@ var ts; | |
} | |
function loadModuleFromSpecificNodeModulesDirectory(extensions, moduleName, nodeModulesDirectory, nodeModulesDirectoryExists, state) { | |
var candidate = ts.normalizePath(ts.combinePaths(nodeModulesDirectory, moduleName)); | |
+ return loadModuleFromSpecificNodeModulesDirectoryImpl(extensions, moduleName, nodeModulesDirectory, nodeModulesDirectoryExists, state, candidate, undefined, undefined); | |
+ } | |
+ function loadModuleFromPnpResolution(extensions, packageDirectory, rest, state) { | |
+ var candidate = ts.normalizePath(ts.combinePaths(packageDirectory, rest)); | |
+ return loadModuleFromSpecificNodeModulesDirectoryImpl(extensions, undefined, undefined, true, state, candidate, rest, packageDirectory); | |
+ } | |
+ function loadModuleFromSpecificNodeModulesDirectoryImpl(extensions, moduleName, nodeModulesDirectory, nodeModulesDirectoryExists, state, candidate, rest, packageDirectory) { | |
+ var _a; | |
// First look for a nested package.json, as in `node_modules/foo/bar/package.json`. | |
var packageInfo = getPackageJsonInfo(candidate, !nodeModulesDirectoryExists, state); | |
if (packageInfo) { | |
@@ -42209,9 +42259,12 @@ var ts; | |
loadNodeModuleFromDirectoryWorker(extensions, candidate, onlyRecordFailures, state, packageInfo && packageInfo.packageJsonContent, packageInfo && packageInfo.versionPaths); | |
return withPackageId(packageInfo, pathAndExtension); | |
}; | |
- var _a = parsePackageName(moduleName), packageName = _a.packageName, rest = _a.rest; | |
+ var packageName; | |
+ if (rest === undefined) | |
+ (_a = parsePackageName(moduleName), packageName = _a.packageName, rest = _a.rest); | |
if (rest !== "") { // If "rest" is empty, we just did this search above. | |
- var packageDirectory = ts.combinePaths(nodeModulesDirectory, packageName); | |
+ if (packageDirectory === undefined) | |
+ packageDirectory = ts.combinePaths(nodeModulesDirectory, packageName); | |
// Don't use a "types" or "main" from here because we're not loading the root, but a subdirectory -- just here for the packageId and path mappings. | |
packageInfo = getPackageJsonInfo(packageDirectory, !nodeModulesDirectoryExists, state); | |
if (packageInfo && packageInfo.versionPaths) { | |
@@ -42370,6 +42423,58 @@ var ts; | |
function toSearchResult(value) { | |
return value !== undefined ? { value: value } : undefined; | |
} | |
+ /** | |
+ * We only allow PnP to be used as a resolution strategy if TypeScript | |
+ * itself is executed under a PnP runtime (and we only allow it to access | |
+ * the current PnP runtime, not any on the disk). This ensures that we | |
+ * don't execute potentially malicious code that didn't already have a | |
+ * chance to be executed (if we're running within the runtime, it means | |
+ * that the runtime has already been executed). | |
+ * @internal | |
+ */ | |
+ function getPnpApi(path) { | |
+ var findPnpApi = require("module").findPnpApi; | |
+ if (findPnpApi === undefined) { | |
+ return undefined; | |
+ } | |
+ return findPnpApi(path + "/"); | |
+ } | |
+ function loadPnpPackageResolution(packageName, containingDirectory) { | |
+ try { | |
+ var resolution = getPnpApi(containingDirectory).resolveToUnqualified(packageName, containingDirectory + "/", { considerBuiltins: false }); | |
+ return ts.normalizeSlashes(resolution); | |
+ } | |
+ catch (_a) { | |
+ // Nothing to do | |
+ } | |
+ } | |
+ function loadPnpTypePackageResolution(packageName, containingDirectory) { | |
+ return loadPnpPackageResolution(getTypesPackageName(packageName), containingDirectory); | |
+ } | |
+ /* @internal */ | |
+ function tryLoadModuleUsingPnpResolution(extensions, moduleName, containingDirectory, state) { | |
+ var _a = parsePackageName(moduleName), packageName = _a.packageName, rest = _a.rest; | |
+ var packageResolution = loadPnpPackageResolution(packageName, containingDirectory); | |
+ var packageFullResolution = packageResolution | |
+ ? loadModuleFromPnpResolution(extensions, packageResolution, rest, state) | |
+ : undefined; | |
+ var resolved; | |
+ if (packageFullResolution) { | |
+ resolved = packageFullResolution; | |
+ } | |
+ else if (extensions === Extensions.TypeScript || extensions === Extensions.DtsOnly) { | |
+ var typePackageResolution = loadPnpTypePackageResolution(packageName, containingDirectory); | |
+ var typePackageFullResolution = typePackageResolution | |
+ ? loadModuleFromPnpResolution(Extensions.DtsOnly, typePackageResolution, rest, state) | |
+ : undefined; | |
+ if (typePackageFullResolution) { | |
+ resolved = typePackageFullResolution; | |
+ } | |
+ } | |
+ if (resolved) { | |
+ return toSearchResult(resolved); | |
+ } | |
+ } | |
})(ts || (ts = {})); | |
/* @internal */ | |
var ts; | |
@@ -110713,6 +110818,8 @@ var ts; | |
ConfigFileProgramReloadLevel[ConfigFileProgramReloadLevel["Partial"] = 1] = "Partial"; | |
/** Reload completely by re-reading contents of config file from disk and updating program */ | |
ConfigFileProgramReloadLevel[ConfigFileProgramReloadLevel["Full"] = 2] = "Full"; | |
+ /** Reload the resolutions */ | |
+ ConfigFileProgramReloadLevel[ConfigFileProgramReloadLevel["Resolutions"] = 3] = "Resolutions"; | |
})(ConfigFileProgramReloadLevel = ts.ConfigFileProgramReloadLevel || (ts.ConfigFileProgramReloadLevel = {})); | |
/** | |
* Updates the map of shared extended config file watches with a new set of extended config files from a base config file of the project | |
@@ -117283,6 +117390,29 @@ var ts; | |
return undefined; | |
} | |
var parts = getNodeModulePathParts(path); | |
+ var packageName; | |
+ if (!parts && typeof process.versions.pnp !== "undefined") { | |
+ var pnpApi = require("pnpapi"); | |
+ var locator = pnpApi.findPackageLocator(path); | |
+ // eslint-disable-next-line no-null/no-null | |
+ if (locator !== null) { | |
+ var sourceLocator = pnpApi.findPackageLocator(sourceDirectory + "/"); | |
+ // Don't use the package name when the imported file is inside | |
+ // the source directory (prefer a relative path instead) | |
+ if (locator === sourceLocator) { | |
+ return undefined; | |
+ } | |
+ var information = pnpApi.getPackageInformation(locator); | |
+ packageName = locator.name; | |
+ parts = { | |
+ topLevelNodeModulesIndex: undefined, | |
+ topLevelPackageNameIndex: undefined, | |
+ // The last character from packageLocation is the trailing "/", we want to point to it | |
+ packageRootIndex: information.packageLocation.length - 1, | |
+ fileNameIndex: path.lastIndexOf("/"), | |
+ }; | |
+ } | |
+ } | |
if (!parts) { | |
return undefined; | |
} | |
@@ -117313,18 +117443,24 @@ var ts; | |
if (isRedirect && !isPackageRootPath) { | |
return undefined; | |
} | |
- var globalTypingsCacheLocation = host.getGlobalTypingsCacheLocation && host.getGlobalTypingsCacheLocation(); | |
- // Get a path that's relative to node_modules or the importing file's path | |
- // if node_modules folder is in this folder or any of its parent folders, no need to keep it. | |
- var pathToTopLevelNodeModules = getCanonicalFileName(moduleSpecifier.substring(0, parts.topLevelNodeModulesIndex)); | |
- if (!(ts.startsWith(sourceDirectory, pathToTopLevelNodeModules) || globalTypingsCacheLocation && ts.startsWith(getCanonicalFileName(globalTypingsCacheLocation), pathToTopLevelNodeModules))) { | |
- return undefined; | |
+ // If PnP is enabled the node_modules entries we'll get will always be relevant even if they | |
+ // are located in a weird path apparently outside of the source directory | |
+ if (typeof process.versions.pnp === "undefined") { | |
+ var globalTypingsCacheLocation = host.getGlobalTypingsCacheLocation && host.getGlobalTypingsCacheLocation(); | |
+ // Get a path that's relative to node_modules or the importing file's path | |
+ // if node_modules folder is in this folder or any of its parent folders, no need to keep it. | |
+ var pathToTopLevelNodeModules = getCanonicalFileName(moduleSpecifier.substring(0, parts.topLevelNodeModulesIndex)); | |
+ if (!(ts.startsWith(sourceDirectory, pathToTopLevelNodeModules) || globalTypingsCacheLocation && ts.startsWith(getCanonicalFileName(globalTypingsCacheLocation), pathToTopLevelNodeModules))) { | |
+ return undefined; | |
+ } | |
} | |
// If the module was found in @types, get the actual Node package name | |
- var nodeModulesDirectoryName = moduleSpecifier.substring(parts.topLevelPackageNameIndex + 1); | |
- var packageName = ts.getPackageNameFromTypesPackageName(nodeModulesDirectoryName); | |
+ var nodeModulesDirectoryName = typeof packageName !== "undefined" | |
+ ? packageName + moduleSpecifier.substring(parts.packageRootIndex) | |
+ : moduleSpecifier.substring(parts.topLevelPackageNameIndex + 1); | |
+ var packageNameFromPath = ts.getPackageNameFromTypesPackageName(nodeModulesDirectoryName); | |
// For classic resolution, only allow importing from node_modules/@types, not other node_modules | |
- return ts.getEmitModuleResolutionKind(options) !== ts.ModuleResolutionKind.NodeJs && packageName === nodeModulesDirectoryName ? undefined : packageName; | |
+ return ts.getEmitModuleResolutionKind(options) !== ts.ModuleResolutionKind.NodeJs && packageNameFromPath === nodeModulesDirectoryName ? undefined : packageNameFromPath; | |
function tryDirectoryWithPackageJson(packageRootIndex) { | |
var packageRootPath = path.substring(0, packageRootIndex); | |
var packageJsonPath = ts.combinePaths(packageRootPath, "package.json"); | |
@@ -118118,6 +118254,10 @@ var ts; | |
if (configFileName) { | |
configFileWatcher = watchFile(configFileName, scheduleProgramReload, ts.PollingInterval.High, watchOptions, ts.WatchType.ConfigFile); | |
} | |
+ var pnpFileWatcher; | |
+ if (typeof process.versions.pnp !== "undefined") { | |
+ pnpFileWatcher = watchFile(require.resolve("pnpapi"), scheduleResolutionReload, ts.PollingInterval.High, watchOptions, ts.WatchType.ConfigFile); | |
+ } | |
var compilerHost = ts.createCompilerHostFromProgramHost(host, function () { return compilerOptions; }, directoryStructureHost); | |
ts.setGetSourceFileAsHashVersioned(compilerHost, host); | |
// Members for CompilerHost | |
@@ -118196,6 +118336,10 @@ var ts; | |
configFileWatcher.close(); | |
configFileWatcher = undefined; | |
} | |
+ if (pnpFileWatcher) { | |
+ pnpFileWatcher.close(); | |
+ pnpFileWatcher = undefined; | |
+ } | |
extendedConfigCache === null || extendedConfigCache === void 0 ? void 0 : extendedConfigCache.clear(); | |
extendedConfigCache = undefined; | |
if (sharedExtendedConfigFileWatchers) { | |
@@ -118228,7 +118372,8 @@ var ts; | |
function getCurrentProgram() { | |
return builderProgram && builderProgram.getProgramOrUndefined(); | |
} | |
- function synchronizeProgram() { | |
+ function synchronizeProgram(forceAllFilesAsInvalidated) { | |
+ if (forceAllFilesAsInvalidated === void 0) { forceAllFilesAsInvalidated = false; } | |
writeLog("Synchronizing program"); | |
clearInvalidateResolutionsOfFailedLookupLocations(); | |
var program = getCurrentBuilderProgram(); | |
@@ -118239,7 +118384,7 @@ var ts; | |
} | |
} | |
// All resolutions are invalid if user provided resolutions | |
- var hasInvalidatedResolution = resolutionCache.createHasInvalidatedResolution(userProvidedResolution || changesAffectResolution); | |
+ var hasInvalidatedResolution = resolutionCache.createHasInvalidatedResolution(userProvidedResolution || forceAllFilesAsInvalidated); | |
if (ts.isProgramUptoDate(getCurrentProgram(), rootFileNames, compilerOptions, getSourceVersion, fileExists, hasInvalidatedResolution, hasChangedAutomaticTypeDirectiveNames, getParsedCommandLine, projectReferences)) { | |
if (hasChangedConfigFileParsingErrors) { | |
builderProgram = createProgram(/*rootNames*/ undefined, /*options*/ undefined, compilerHost, builderProgram, configFileParsingDiagnostics, projectReferences); | |
@@ -118446,6 +118591,12 @@ var ts; | |
reloadLevel = ts.ConfigFileProgramReloadLevel.Full; | |
scheduleProgramUpdate(); | |
} | |
+ function scheduleResolutionReload() { | |
+ writeLog("Clearing resolutions"); | |
+ resolutionCache.clear(); | |
+ reloadLevel = ts.ConfigFileProgramReloadLevel.Resolutions; | |
+ scheduleProgramUpdate(); | |
+ } | |
function updateProgramWithWatchStatus() { | |
timerToUpdateProgram = undefined; | |
reportWatchDiagnostic(ts.Diagnostics.File_change_detected_Starting_incremental_compilation); | |
@@ -118461,6 +118612,10 @@ var ts; | |
ts.perfLogger.logStartUpdateProgram("FullConfigReload"); | |
reloadConfigFile(); | |
break; | |
+ case ts.ConfigFileProgramReloadLevel.Resolutions: | |
+ ts.perfLogger.logStartUpdateProgram("SynchronizeProgramWithResolutions"); | |
+ synchronizeProgram(/*forceAllFilesAsInvalidated*/ true); | |
+ break; | |
default: | |
ts.perfLogger.logStartUpdateProgram("SynchronizeProgram"); | |
synchronizeProgram(); | |
@@ -124266,11 +124421,27 @@ var ts; | |
return hasImportablePath; | |
} | |
ts.isImportableFile = isImportableFile; | |
+ /** | |
+ * We only allow PnP to be used as a resolution strategy if TypeScript | |
+ * itself is executed under a PnP runtime (and we only allow it to access | |
+ * the current PnP runtime, not any on the disk). This ensures that we | |
+ * don't execute potentially malicious code that didn't already have a | |
+ * chance to be executed (if we're running within the runtime, it means | |
+ * that the runtime has already been executed). | |
+ * @internal | |
+ */ | |
+ function getPnpApi(path) { | |
+ var findPnpApi = require("module").findPnpApi; | |
+ if (findPnpApi === undefined) { | |
+ return undefined; | |
+ } | |
+ return findPnpApi(path + "/"); | |
+ } | |
/** | |
* Don't include something from a `node_modules` that isn't actually reachable by a global import. | |
* A relative import to node_modules is usually a bad idea. | |
*/ | |
- function isImportablePath(fromPath, toPath, getCanonicalFileName, globalCachePath) { | |
+ function isImportablePathNode(fromPath, toPath, getCanonicalFileName, globalCachePath) { | |
// If it's in a `node_modules` but is not reachable from here via a global import, don't bother. | |
var toNodeModules = ts.forEachAncestorDirectory(toPath, function (ancestor) { return ts.getBaseFileName(ancestor) === "node_modules" ? ancestor : undefined; }); | |
var toNodeModulesParent = toNodeModules && ts.getDirectoryPath(getCanonicalFileName(toNodeModules)); | |
@@ -124278,6 +124449,26 @@ var ts; | |
|| ts.startsWith(getCanonicalFileName(fromPath), toNodeModulesParent) | |
|| (!!globalCachePath && ts.startsWith(getCanonicalFileName(globalCachePath), toNodeModulesParent)); | |
} | |
+ function isImportablePathPnp(fromPath, toPath) { | |
+ var pnpApi = getPnpApi(fromPath); | |
+ var fromLocator = pnpApi.findPackageLocator(fromPath); | |
+ var toLocator = pnpApi.findPackageLocator(toPath); | |
+ // eslint-disable-next-line no-null/no-null | |
+ if (toLocator === null) { | |
+ return false; | |
+ } | |
+ var fromInfo = pnpApi.getPackageInformation(fromLocator); | |
+ var toReference = fromInfo.packageDependencies.get(toLocator.name); | |
+ return toReference === toLocator.reference; | |
+ } | |
+ function isImportablePath(fromPath, toPath, getCanonicalFileName, globalCachePath) { | |
+ if (getPnpApi(fromPath)) { | |
+ return isImportablePathPnp(fromPath, toPath); | |
+ } | |
+ else { | |
+ return isImportablePathNode(fromPath, toPath, getCanonicalFileName, globalCachePath); | |
+ } | |
+ } | |
function forEachExternalModuleToImportFrom(program, host, useAutoImportProvider, cb) { | |
var _a, _b; | |
forEachExternalModule(program.getTypeChecker(), program.getSourceFiles(), function (module, file) { return cb(module, file, program, /*isFromPackageJson*/ false); }); | |
@@ -126088,6 +126279,7 @@ var ts; | |
* This includes all files that are found in node_modules/moduleName/ with acceptable file extensions | |
*/ | |
function getCompletionEntriesForNonRelativeModules(fragment, scriptPath, compilerOptions, host, typeChecker) { | |
+ var _a, _b; | |
var baseUrl = compilerOptions.baseUrl, paths = compilerOptions.paths; | |
var result = []; | |
var extensionOptions = getExtensionOptions(compilerOptions); | |
@@ -126100,8 +126292,8 @@ var ts; | |
} | |
} | |
var fragmentDirectory = getFragmentDirectory(fragment); | |
- for (var _i = 0, _a = getAmbientModuleCompletions(fragment, fragmentDirectory, typeChecker); _i < _a.length; _i++) { | |
- var ambientName = _a[_i]; | |
+ for (var _i = 0, _c = getAmbientModuleCompletions(fragment, fragmentDirectory, typeChecker); _i < _c.length; _i++) { | |
+ var ambientName = _c[_i]; | |
result.push(nameAndKind(ambientName, "external module name" /* externalModuleName */, /*extension*/ undefined)); | |
} | |
getCompletionEntriesFromTypings(host, compilerOptions, scriptPath, fragmentDirectory, extensionOptions, result); | |
@@ -126116,18 +126308,36 @@ var ts; | |
result.push(nameAndKind(moduleName, "external module name" /* externalModuleName */, /*extension*/ undefined)); | |
} | |
}; | |
- for (var _b = 0, _c = enumerateNodeModulesVisibleToScript(host, scriptPath); _b < _c.length; _b++) { | |
- var moduleName = _c[_b]; | |
+ for (var _d = 0, _e = enumerateNodeModulesVisibleToScript(host, scriptPath); _d < _e.length; _d++) { | |
+ var moduleName = _e[_d]; | |
_loop_3(moduleName); | |
} | |
} | |
if (!foundGlobal) { | |
- ts.forEachAncestorDirectory(scriptPath, function (ancestor) { | |
- var nodeModules = ts.combinePaths(ancestor, "node_modules"); | |
- if (ts.tryDirectoryExists(host, nodeModules)) { | |
- getCompletionEntriesForDirectoryFragment(fragment, nodeModules, extensionOptions, host, /*exclude*/ undefined, result); | |
+ var pnpapi = (_b = (_a = require("module")).findPnpApi) === null || _b === void 0 ? void 0 : _b.call(_a, scriptPath); | |
+ if (pnpapi) { | |
+ try { | |
+ // Splits a require request into its components, or return null if the request is a file path | |
+ var pathRegExp = /^(?![a-zA-Z]:[\\/]|\\\\|\.{0,2}(?:\/|$))((?:@[^/]+\/)?[^/]+)\/*(.*|)$/; | |
+ var dependencyNameMatch = fragment.match(pathRegExp); | |
+ if (dependencyNameMatch) { | |
+ var dependencyName = dependencyNameMatch[1], subPath = dependencyNameMatch[2]; | |
+ var unqualified = pnpapi.resolveToUnqualified(dependencyName, scriptPath, { considerBuiltins: false }); | |
+ if (unqualified) { | |
+ getCompletionEntriesForDirectoryFragment(subPath, ts.normalizePath(unqualified), extensionOptions, host, /*exclude*/ undefined, result); | |
+ } | |
+ } | |
} | |
- }); | |
+ catch (_f) { } | |
+ } | |
+ else { | |
+ ts.forEachAncestorDirectory(scriptPath, function (ancestor) { | |
+ var nodeModules = ts.combinePaths(ancestor, "node_modules"); | |
+ if (ts.tryDirectoryExists(host, nodeModules)) { | |
+ getCompletionEntriesForDirectoryFragment(fragment, nodeModules, extensionOptions, host, /*exclude*/ undefined, result); | |
+ } | |
+ }); | |
+ } | |
} | |
} | |
return result; | |
@@ -126228,6 +126438,7 @@ var ts; | |
return addReplacementSpans(toComplete, range.pos + prefix.length, names); | |
} | |
function getCompletionEntriesFromTypings(host, options, scriptPath, fragmentDirectory, extensionOptions, result) { | |
+ var _a, _b; | |
if (result === void 0) { result = []; } | |
// Check for typings specified in compiler options | |
var seen = new ts.Map(); | |
@@ -126236,11 +126447,19 @@ var ts; | |
var root = typeRoots_1[_i]; | |
getCompletionEntriesFromDirectories(root); | |
} | |
- // Also get all @types typings installed in visible node_modules directories | |
- for (var _a = 0, _b = ts.findPackageJsons(scriptPath, host); _a < _b.length; _a++) { | |
- var packageJson = _b[_a]; | |
- var typesDir = ts.combinePaths(ts.getDirectoryPath(packageJson), "node_modules/@types"); | |
- getCompletionEntriesFromDirectories(typesDir); | |
+ if ((_b = (_a = require("module")).findPnpApi) === null || _b === void 0 ? void 0 : _b.call(_a, scriptPath)) { | |
+ for (var _c = 0, _d = ts.getPnpTypeRoots(scriptPath); _c < _d.length; _c++) { | |
+ var root = _d[_c]; | |
+ getCompletionEntriesFromDirectories(root); | |
+ } | |
+ } | |
+ else { | |
+ // Also get all @types typings installed in visible node_modules directories | |
+ for (var _e = 0, _f = ts.findPackageJsons(scriptPath, host); _e < _f.length; _e++) { | |
+ var packageJson = _f[_e]; | |
+ var typesDir = ts.combinePaths(ts.getDirectoryPath(packageJson), "node_modules/@types"); | |
+ getCompletionEntriesFromDirectories(typesDir); | |
+ } | |
} | |
return result; | |
function getCompletionEntriesFromDirectories(directory) { | |
@@ -154433,9 +154652,9 @@ var ts; | |
if (isTopLevelDeclarationStatement(statement) && | |
!isExported(sourceFile, statement, useEs6Exports) && | |
forEachTopLevelDeclaration(statement, function (d) { return needExport.has(ts.Debug.checkDefined(d.symbol)); })) { | |
- var exports = addExport(statement, useEs6Exports); | |
- if (exports) | |
- return exports; | |
+ var exports_1 = addExport(statement, useEs6Exports); | |
+ if (exports_1) | |
+ return exports_1; | |
} | |
return statement; | |
}); | |
diff --git a/lib/typingsInstaller.js b/lib/typingsInstaller.js | |
index a0e7177a1..05fe8eb42 100644 | |
semver exclusivity 4.4.2 | |
--- a/lib/typingsInstaller.js | |
+++ b/lib/typingsInstaller.js | |
@@ -7447,6 +7447,11 @@ var ts; | |
: new Buffer(input, encoding); | |
} | |
function isFileSystemCaseSensitive() { | |
+ // The PnP runtime is always case-sensitive | |
+ // @ts-ignore | |
+ if (process.versions.pnp) { | |
+ return true; | |
+ } | |
// win32\win64 are case insensitive platforms | |
if (platform === "win32" || platform === "win64") { | |
return false; | |
@@ -40956,24 +40961,56 @@ var ts; | |
ts.getEffectiveTypeRoots = getEffectiveTypeRoots; | |
/** | |
* Returns the path to every node_modules/@types directory from some ancestor directory. | |
- * Returns undefined if there are none. | |
*/ | |
- function getDefaultTypeRoots(currentDirectory, host) { | |
+ function getNodeModulesTypeRoots(currentDirectory, host) { | |
if (!host.directoryExists) { | |
return [ts.combinePaths(currentDirectory, nodeModulesAtTypes)]; | |
// And if it doesn't exist, tough. | |
} | |
- var typeRoots; | |
+ var typeRoots = []; | |
ts.forEachAncestorDirectory(ts.normalizePath(currentDirectory), function (directory) { | |
var atTypes = ts.combinePaths(directory, nodeModulesAtTypes); | |
if (host.directoryExists(atTypes)) { | |
- (typeRoots || (typeRoots = [])).push(atTypes); | |
+ typeRoots.push(atTypes); | |
} | |
return undefined; | |
}); | |
return typeRoots; | |
} | |
var nodeModulesAtTypes = ts.combinePaths("node_modules", "@types"); | |
+ function getPnpTypeRoots(currentDirectory) { | |
+ var pnpapi = getPnpApi(currentDirectory); | |
+ if (!pnpapi) { | |
+ return []; | |
+ } | |
+ // Some TS consumers pass relative paths that aren't normalized | |
+ currentDirectory = ts.sys.resolvePath(currentDirectory); | |
+ var currentPackage = pnpapi.findPackageLocator(currentDirectory + "/"); | |
+ if (!currentPackage) { | |
+ return []; | |
+ } | |
+ var packageDependencies = pnpapi.getPackageInformation(currentPackage).packageDependencies; | |
+ var typeRoots = []; | |
+ for (var _i = 0, _a = Array.from(packageDependencies.entries()); _i < _a.length; _i++) { | |
+ var _b = _a[_i], name = _b[0], referencish = _b[1]; | |
+ // eslint-disable-next-line no-null/no-null | |
+ if (name.startsWith(typesPackagePrefix) && referencish !== null) { | |
+ var dependencyLocator = pnpapi.getLocator(name, referencish); | |
+ var packageLocation = pnpapi.getPackageInformation(dependencyLocator).packageLocation; | |
+ typeRoots.push(ts.getDirectoryPath(packageLocation)); | |
+ } | |
+ } | |
+ return typeRoots; | |
+ } | |
+ ts.getPnpTypeRoots = getPnpTypeRoots; | |
+ var typesPackagePrefix = "@types/"; | |
+ function getDefaultTypeRoots(currentDirectory, host) { | |
+ var nmTypes = getNodeModulesTypeRoots(currentDirectory, host); | |
+ var pnpTypes = getPnpTypeRoots(currentDirectory); | |
+ if (nmTypes.length > 0 || pnpTypes.length > 0) { | |
+ return __spreadArray(__spreadArray([], nmTypes, true), pnpTypes, true); | |
+ } | |
+ } | |
/** | |
* @param {string | undefined} containingFile - file that contains type reference directive, can be undefined if containing file is unknown. | |
* This is possible in case if resolution is performed for directives specified via 'types' parameter. In this case initial path for secondary lookups | |
@@ -41087,7 +41124,9 @@ var ts; | |
} | |
var result_4; | |
if (!ts.isExternalModuleNameRelative(typeReferenceDirectiveName)) { | |
- var searchResult = loadModuleFromNearestNodeModulesDirectory(Extensions.DtsOnly, typeReferenceDirectiveName, initialLocationForSecondaryLookup, moduleResolutionState, /*cache*/ undefined, /*redirectedReference*/ undefined); | |
+ var searchResult = getPnpApi(initialLocationForSecondaryLookup) | |
+ ? tryLoadModuleUsingPnpResolution(Extensions.DtsOnly, typeReferenceDirectiveName, initialLocationForSecondaryLookup, moduleResolutionState) | |
+ : loadModuleFromNearestNodeModulesDirectory(Extensions.DtsOnly, typeReferenceDirectiveName, initialLocationForSecondaryLookup, moduleResolutionState, /*cache*/ undefined, /*redirectedReference*/ undefined); | |
result_4 = searchResult && searchResult.value; | |
} | |
else { | |
@@ -41642,9 +41681,12 @@ var ts; | |
if (traceEnabled) { | |
trace(host, ts.Diagnostics.Loading_module_0_from_node_modules_folder_target_file_type_1, moduleName, Extensions[extensions]); | |
} | |
- var resolved_1 = loadModuleFromNearestNodeModulesDirectory(extensions, moduleName, containingDirectory, state, cache, redirectedReference); | |
- if (!resolved_1) | |
+ var resolved_1 = getPnpApi(containingDirectory) | |
+ ? tryLoadModuleUsingPnpResolution(extensions, moduleName, containingDirectory, state) | |
+ : loadModuleFromNearestNodeModulesDirectory(extensions, moduleName, containingDirectory, state, cache, redirectedReference); | |
+ if (!resolved_1) { | |
return undefined; | |
+ } | |
var resolvedValue = resolved_1.value; | |
if (!compilerOptions.preserveSymlinks && resolvedValue && !resolvedValue.originalPath) { | |
var path = realPath(resolvedValue.path, host, traceEnabled); | |
@@ -41989,6 +42031,14 @@ var ts; | |
} | |
function loadModuleFromSpecificNodeModulesDirectory(extensions, moduleName, nodeModulesDirectory, nodeModulesDirectoryExists, state) { | |
var candidate = ts.normalizePath(ts.combinePaths(nodeModulesDirectory, moduleName)); | |
+ return loadModuleFromSpecificNodeModulesDirectoryImpl(extensions, moduleName, nodeModulesDirectory, nodeModulesDirectoryExists, state, candidate, undefined, undefined); | |
+ } | |
+ function loadModuleFromPnpResolution(extensions, packageDirectory, rest, state) { | |
+ var candidate = ts.normalizePath(ts.combinePaths(packageDirectory, rest)); | |
+ return loadModuleFromSpecificNodeModulesDirectoryImpl(extensions, undefined, undefined, true, state, candidate, rest, packageDirectory); | |
+ } | |
+ function loadModuleFromSpecificNodeModulesDirectoryImpl(extensions, moduleName, nodeModulesDirectory, nodeModulesDirectoryExists, state, candidate, rest, packageDirectory) { | |
+ var _a; | |
// First look for a nested package.json, as in `node_modules/foo/bar/package.json`. | |
var packageInfo = getPackageJsonInfo(candidate, !nodeModulesDirectoryExists, state); | |
if (packageInfo) { | |
@@ -42004,9 +42054,12 @@ var ts; | |
loadNodeModuleFromDirectoryWorker(extensions, candidate, onlyRecordFailures, state, packageInfo && packageInfo.packageJsonContent, packageInfo && packageInfo.versionPaths); | |
return withPackageId(packageInfo, pathAndExtension); | |
}; | |
- var _a = parsePackageName(moduleName), packageName = _a.packageName, rest = _a.rest; | |
+ var packageName; | |
+ if (rest === undefined) | |
+ (_a = parsePackageName(moduleName), packageName = _a.packageName, rest = _a.rest); | |
if (rest !== "") { // If "rest" is empty, we just did this search above. | |
- var packageDirectory = ts.combinePaths(nodeModulesDirectory, packageName); | |
+ if (packageDirectory === undefined) | |
+ packageDirectory = ts.combinePaths(nodeModulesDirectory, packageName); | |
// Don't use a "types" or "main" from here because we're not loading the root, but a subdirectory -- just here for the packageId and path mappings. | |
packageInfo = getPackageJsonInfo(packageDirectory, !nodeModulesDirectoryExists, state); | |
if (packageInfo && packageInfo.versionPaths) { | |
@@ -42165,6 +42218,58 @@ var ts; | |
function toSearchResult(value) { | |
return value !== undefined ? { value: value } : undefined; | |
} | |
+ /** | |
+ * We only allow PnP to be used as a resolution strategy if TypeScript | |
+ * itself is executed under a PnP runtime (and we only allow it to access | |
+ * the current PnP runtime, not any on the disk). This ensures that we | |
+ * don't execute potentially malicious code that didn't already have a | |
+ * chance to be executed (if we're running within the runtime, it means | |
+ * that the runtime has already been executed). | |
+ * @internal | |
+ */ | |
+ function getPnpApi(path) { | |
+ var findPnpApi = require("module").findPnpApi; | |
+ if (findPnpApi === undefined) { | |
+ return undefined; | |
+ } | |
+ return findPnpApi(path + "/"); | |
+ } | |
+ function loadPnpPackageResolution(packageName, containingDirectory) { | |
+ try { | |
+ var resolution = getPnpApi(containingDirectory).resolveToUnqualified(packageName, containingDirectory + "/", { considerBuiltins: false }); | |
+ return ts.normalizeSlashes(resolution); | |
+ } | |
+ catch (_a) { | |
+ // Nothing to do | |
+ } | |
+ } | |
+ function loadPnpTypePackageResolution(packageName, containingDirectory) { | |
+ return loadPnpPackageResolution(getTypesPackageName(packageName), containingDirectory); | |
+ } | |
+ /* @internal */ | |
+ function tryLoadModuleUsingPnpResolution(extensions, moduleName, containingDirectory, state) { | |
+ var _a = parsePackageName(moduleName), packageName = _a.packageName, rest = _a.rest; | |
+ var packageResolution = loadPnpPackageResolution(packageName, containingDirectory); | |
+ var packageFullResolution = packageResolution | |
+ ? loadModuleFromPnpResolution(extensions, packageResolution, rest, state) | |
+ : undefined; | |
+ var resolved; | |
+ if (packageFullResolution) { | |
+ resolved = packageFullResolution; | |
+ } | |
+ else if (extensions === Extensions.TypeScript || extensions === Extensions.DtsOnly) { | |
+ var typePackageResolution = loadPnpTypePackageResolution(packageName, containingDirectory); | |
+ var typePackageFullResolution = typePackageResolution | |
+ ? loadModuleFromPnpResolution(Extensions.DtsOnly, typePackageResolution, rest, state) | |
+ : undefined; | |
+ if (typePackageFullResolution) { | |
+ resolved = typePackageFullResolution; | |
+ } | |
+ } | |
+ if (resolved) { | |
+ return toSearchResult(resolved); | |
+ } | |
+ } | |
})(ts || (ts = {})); | |
/* @internal */ | |
var ts; | |
@@ -110508,6 +110613,8 @@ var ts; | |
ConfigFileProgramReloadLevel[ConfigFileProgramReloadLevel["Partial"] = 1] = "Partial"; | |
/** Reload completely by re-reading contents of config file from disk and updating program */ | |
ConfigFileProgramReloadLevel[ConfigFileProgramReloadLevel["Full"] = 2] = "Full"; | |
+ /** Reload the resolutions */ | |
+ ConfigFileProgramReloadLevel[ConfigFileProgramReloadLevel["Resolutions"] = 3] = "Resolutions"; | |
})(ConfigFileProgramReloadLevel = ts.ConfigFileProgramReloadLevel || (ts.ConfigFileProgramReloadLevel = {})); | |
/** | |
* Updates the map of shared extended config file watches with a new set of extended config files from a base config file of the project | |
@@ -117078,6 +117185,29 @@ var ts; | |
return undefined; | |
} | |
var parts = getNodeModulePathParts(path); | |
+ var packageName; | |
+ if (!parts && typeof process.versions.pnp !== "undefined") { | |
+ var pnpApi = require("pnpapi"); | |
+ var locator = pnpApi.findPackageLocator(path); | |
+ // eslint-disable-next-line no-null/no-null | |
+ if (locator !== null) { | |
+ var sourceLocator = pnpApi.findPackageLocator(sourceDirectory + "/"); | |
+ // Don't use the package name when the imported file is inside | |
+ // the source directory (prefer a relative path instead) | |
+ if (locator === sourceLocator) { | |
+ return undefined; | |
+ } | |
+ var information = pnpApi.getPackageInformation(locator); | |
+ packageName = locator.name; | |
+ parts = { | |
+ topLevelNodeModulesIndex: undefined, | |
+ topLevelPackageNameIndex: undefined, | |
+ // The last character from packageLocation is the trailing "/", we want to point to it | |
+ packageRootIndex: information.packageLocation.length - 1, | |
+ fileNameIndex: path.lastIndexOf("/"), | |
+ }; | |
+ } | |
+ } | |
if (!parts) { | |
return undefined; | |
} | |
@@ -117108,18 +117238,24 @@ var ts; | |
if (isRedirect && !isPackageRootPath) { | |
return undefined; | |
} | |
- var globalTypingsCacheLocation = host.getGlobalTypingsCacheLocation && host.getGlobalTypingsCacheLocation(); | |
- // Get a path that's relative to node_modules or the importing file's path | |
- // if node_modules folder is in this folder or any of its parent folders, no need to keep it. | |
- var pathToTopLevelNodeModules = getCanonicalFileName(moduleSpecifier.substring(0, parts.topLevelNodeModulesIndex)); | |
- if (!(ts.startsWith(sourceDirectory, pathToTopLevelNodeModules) || globalTypingsCacheLocation && ts.startsWith(getCanonicalFileName(globalTypingsCacheLocation), pathToTopLevelNodeModules))) { | |
- return undefined; | |
+ // If PnP is enabled the node_modules entries we'll get will always be relevant even if they | |
+ // are located in a weird path apparently outside of the source directory | |
+ if (typeof process.versions.pnp === "undefined") { | |
+ var globalTypingsCacheLocation = host.getGlobalTypingsCacheLocation && host.getGlobalTypingsCacheLocation(); | |
+ // Get a path that's relative to node_modules or the importing file's path | |
+ // if node_modules folder is in this folder or any of its parent folders, no need to keep it. | |
+ var pathToTopLevelNodeModules = getCanonicalFileName(moduleSpecifier.substring(0, parts.topLevelNodeModulesIndex)); | |
+ if (!(ts.startsWith(sourceDirectory, pathToTopLevelNodeModules) || globalTypingsCacheLocation && ts.startsWith(getCanonicalFileName(globalTypingsCacheLocation), pathToTopLevelNodeModules))) { | |
+ return undefined; | |
+ } | |
} | |
// If the module was found in @types, get the actual Node package name | |
- var nodeModulesDirectoryName = moduleSpecifier.substring(parts.topLevelPackageNameIndex + 1); | |
- var packageName = ts.getPackageNameFromTypesPackageName(nodeModulesDirectoryName); | |
+ var nodeModulesDirectoryName = typeof packageName !== "undefined" | |
+ ? packageName + moduleSpecifier.substring(parts.packageRootIndex) | |
+ : moduleSpecifier.substring(parts.topLevelPackageNameIndex + 1); | |
+ var packageNameFromPath = ts.getPackageNameFromTypesPackageName(nodeModulesDirectoryName); | |
// For classic resolution, only allow importing from node_modules/@types, not other node_modules | |
- return ts.getEmitModuleResolutionKind(options) !== ts.ModuleResolutionKind.NodeJs && packageName === nodeModulesDirectoryName ? undefined : packageName; | |
+ return ts.getEmitModuleResolutionKind(options) !== ts.ModuleResolutionKind.NodeJs && packageNameFromPath === nodeModulesDirectoryName ? undefined : packageNameFromPath; | |
function tryDirectoryWithPackageJson(packageRootIndex) { | |
var packageRootPath = path.substring(0, packageRootIndex); | |
var packageJsonPath = ts.combinePaths(packageRootPath, "package.json"); | |
@@ -117913,6 +118049,10 @@ var ts; | |
if (configFileName) { | |
configFileWatcher = watchFile(configFileName, scheduleProgramReload, ts.PollingInterval.High, watchOptions, ts.WatchType.ConfigFile); | |
} | |
+ var pnpFileWatcher; | |
+ if (typeof process.versions.pnp !== "undefined") { | |
+ pnpFileWatcher = watchFile(require.resolve("pnpapi"), scheduleResolutionReload, ts.PollingInterval.High, watchOptions, ts.WatchType.ConfigFile); | |
+ } | |
var compilerHost = ts.createCompilerHostFromProgramHost(host, function () { return compilerOptions; }, directoryStructureHost); | |
ts.setGetSourceFileAsHashVersioned(compilerHost, host); | |
// Members for CompilerHost | |
@@ -117991,6 +118131,10 @@ var ts; | |
configFileWatcher.close(); | |
configFileWatcher = undefined; | |
} | |
+ if (pnpFileWatcher) { | |
+ pnpFileWatcher.close(); | |
+ pnpFileWatcher = undefined; | |
+ } | |
extendedConfigCache === null || extendedConfigCache === void 0 ? void 0 : extendedConfigCache.clear(); | |
extendedConfigCache = undefined; | |
if (sharedExtendedConfigFileWatchers) { | |
@@ -118023,7 +118167,8 @@ var ts; | |
function getCurrentProgram() { | |
return builderProgram && builderProgram.getProgramOrUndefined(); | |
} | |
- function synchronizeProgram() { | |
+ function synchronizeProgram(forceAllFilesAsInvalidated) { | |
+ if (forceAllFilesAsInvalidated === void 0) { forceAllFilesAsInvalidated = false; } | |
writeLog("Synchronizing program"); | |
clearInvalidateResolutionsOfFailedLookupLocations(); | |
var program = getCurrentBuilderProgram(); | |
@@ -118034,7 +118179,7 @@ var ts; | |
} | |
} | |
// All resolutions are invalid if user provided resolutions | |
- var hasInvalidatedResolution = resolutionCache.createHasInvalidatedResolution(userProvidedResolution || changesAffectResolution); | |
+ var hasInvalidatedResolution = resolutionCache.createHasInvalidatedResolution(userProvidedResolution || forceAllFilesAsInvalidated); | |
if (ts.isProgramUptoDate(getCurrentProgram(), rootFileNames, compilerOptions, getSourceVersion, fileExists, hasInvalidatedResolution, hasChangedAutomaticTypeDirectiveNames, getParsedCommandLine, projectReferences)) { | |
if (hasChangedConfigFileParsingErrors) { | |
builderProgram = createProgram(/*rootNames*/ undefined, /*options*/ undefined, compilerHost, builderProgram, configFileParsingDiagnostics, projectReferences); | |
@@ -118241,6 +118386,12 @@ var ts; | |
reloadLevel = ts.ConfigFileProgramReloadLevel.Full; | |
scheduleProgramUpdate(); | |
} | |
+ function scheduleResolutionReload() { | |
+ writeLog("Clearing resolutions"); | |
+ resolutionCache.clear(); | |
+ reloadLevel = ts.ConfigFileProgramReloadLevel.Resolutions; | |
+ scheduleProgramUpdate(); | |
+ } | |
function updateProgramWithWatchStatus() { | |
timerToUpdateProgram = undefined; | |
reportWatchDiagnostic(ts.Diagnostics.File_change_detected_Starting_incremental_compilation); | |
@@ -118256,6 +118407,10 @@ var ts; | |
ts.perfLogger.logStartUpdateProgram("FullConfigReload"); | |
reloadConfigFile(); | |
break; | |
+ case ts.ConfigFileProgramReloadLevel.Resolutions: | |
+ ts.perfLogger.logStartUpdateProgram("SynchronizeProgramWithResolutions"); | |
+ synchronizeProgram(/*forceAllFilesAsInvalidated*/ true); | |
+ break; | |
default: | |
ts.perfLogger.logStartUpdateProgram("SynchronizeProgram"); | |
synchronizeProgram(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment