Fix prioritization of `paths` specifiers over node_modules package specifiers (#60238)

This commit is contained in:
Andrew Branch 2024-10-23 13:22:23 -07:00 коммит произвёл GitHub
Родитель db8eacd7e2
Коммит 2ac4cb78d6
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: B5690EEEBB952194
2 изменённых файлов: 62 добавлений и 38 удалений

Просмотреть файл

@ -508,46 +508,44 @@ function computeModuleSpecifiers(
}
}
if (!specifier) {
const local = getLocalModuleSpecifier(
modulePath.path,
info,
compilerOptions,
host,
options.overrideImportMode || importingSourceFile.impliedNodeFormat,
preferences,
/*pathsOnly*/ modulePath.isRedirect,
);
if (!local || forAutoImport && isExcludedByRegex(local, preferences.excludeRegexes)) {
continue;
}
if (modulePath.isRedirect) {
redirectPathsSpecifiers = append(redirectPathsSpecifiers, local);
}
else if (pathIsBareSpecifier(local)) {
if (pathContainsNodeModules(local)) {
// We could be in this branch due to inappropriate use of `baseUrl`, not intentional `paths`
// usage. It's impossible to reason about where to prioritize baseUrl-generated module
// specifiers, but if they contain `/node_modules/`, they're going to trigger a portability
// error, so *at least* don't prioritize those.
relativeSpecifiers = append(relativeSpecifiers, local);
}
else {
pathsSpecifiers = append(pathsSpecifiers, local);
}
}
else if (forAutoImport || !importedFileIsInNodeModules || modulePath.isInNodeModules) {
// Why this extra conditional, not just an `else`? If some path to the file contained
// 'node_modules', but we can't create a non-relative specifier (e.g. "@foo/bar/path/to/file"),
// that means we had to go through a *sibling's* node_modules, not one we can access directly.
// If some path to the file was in node_modules but another was not, this likely indicates that
// we have a monorepo structure with symlinks. In this case, the non-node_modules path is
// probably the realpath, e.g. "../bar/path/to/file", but a relative path to another package
// in a monorepo is probably not portable. So, the module specifier we actually go with will be
// the relative path through node_modules, so that the declaration emitter can produce a
// portability error. (See declarationEmitReexportedSymlinkReference3)
const local = getLocalModuleSpecifier(
modulePath.path,
info,
compilerOptions,
host,
options.overrideImportMode || importingSourceFile.impliedNodeFormat,
preferences,
/*pathsOnly*/ modulePath.isRedirect || !!specifier,
);
if (!local || forAutoImport && isExcludedByRegex(local, preferences.excludeRegexes)) {
continue;
}
if (modulePath.isRedirect) {
redirectPathsSpecifiers = append(redirectPathsSpecifiers, local);
}
else if (pathIsBareSpecifier(local)) {
if (pathContainsNodeModules(local)) {
// We could be in this branch due to inappropriate use of `baseUrl`, not intentional `paths`
// usage. It's impossible to reason about where to prioritize baseUrl-generated module
// specifiers, but if they contain `/node_modules/`, they're going to trigger a portability
// error, so *at least* don't prioritize those.
relativeSpecifiers = append(relativeSpecifiers, local);
}
else {
pathsSpecifiers = append(pathsSpecifiers, local);
}
}
else if (forAutoImport || !importedFileIsInNodeModules || modulePath.isInNodeModules) {
// Why this extra conditional, not just an `else`? If some path to the file contained
// 'node_modules', but we can't create a non-relative specifier (e.g. "@foo/bar/path/to/file"),
// that means we had to go through a *sibling's* node_modules, not one we can access directly.
// If some path to the file was in node_modules but another was not, this likely indicates that
// we have a monorepo structure with symlinks. In this case, the non-node_modules path is
// probably the realpath, e.g. "../bar/path/to/file", but a relative path to another package
// in a monorepo is probably not portable. So, the module specifier we actually go with will be
// the relative path through node_modules, so that the declaration emitter can produce a
// portability error. (See declarationEmitReexportedSymlinkReference3)
relativeSpecifiers = append(relativeSpecifiers, local);
}
}

Просмотреть файл

@ -0,0 +1,26 @@
/// <reference path="fourslash.ts" />
// @Filename: tsconfig.json
//// {
//// "compilerOptions": {
//// "module": "amd",
//// "moduleResolution": "node",
//// "rootDir": "ts",
//// "baseUrl": ".",
//// "paths": {
//// "*": ["node_modules/@woltlab/wcf/ts/*"]
//// }
//// },
//// "include": [
//// "ts",
//// "node_modules/@woltlab/wcf/ts",
//// ]
//// }
// @Filename: node_modules/@woltlab/wcf/ts/WoltLabSuite/Core/Component/Dialog.ts
//// export class Dialog {}
// @Filename: ts/main.ts
//// Dialog/**/
verify.importFixModuleSpecifiers("", ["WoltLabSuite/Core/Component/Dialog"]);