Skip to content

Commit b4b29ab

Browse files
committed
Converted legacySafelist to map to avoid using array prototype methods accidently to match with filename
Eg. constructor.js was adding constructor function to aquisition.include which resulted in the mismatch between typing installer's typeAquisition (which was passed as JSON string and parsed back to null) and one in project That meant we kept on queuing the new typing installation request. Fixes microsoft#27435
1 parent 74392a0 commit b4b29ab

File tree

2 files changed

+62
-5
lines changed

2 files changed

+62
-5
lines changed

src/server/editorServices.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -486,7 +486,7 @@ namespace ts.server {
486486

487487
private readonly hostConfiguration: HostConfiguration;
488488
private safelist: SafeList = defaultTypeSafeList;
489-
private legacySafelist: { [key: string]: string } = {};
489+
private readonly legacySafelist = createMap<string>();
490490

491491
private pendingProjectUpdates = createMap<Project>();
492492
/* @internal */
@@ -638,14 +638,14 @@ namespace ts.server {
638638
this.safelist = raw.typesMap;
639639
for (const key in raw.simpleMap) {
640640
if (raw.simpleMap.hasOwnProperty(key)) {
641-
this.legacySafelist[key] = raw.simpleMap[key].toLowerCase();
641+
this.legacySafelist.set(key, raw.simpleMap[key].toLowerCase());
642642
}
643643
}
644644
}
645645
catch (e) {
646646
this.logger.info(`Error loading types map: ${e}`);
647647
this.safelist = defaultTypeSafeList;
648-
this.legacySafelist = {};
648+
this.legacySafelist.clear();
649649
}
650650
}
651651

@@ -2721,13 +2721,13 @@ namespace ts.server {
27212721
if (fileExtensionIs(baseName, "js")) {
27222722
const inferredTypingName = removeFileExtension(baseName);
27232723
const cleanedTypingName = removeMinAndVersionNumbers(inferredTypingName);
2724-
if (this.legacySafelist[cleanedTypingName]) {
2724+
const typeName = this.legacySafelist.get(cleanedTypingName);
2725+
if (typeName !== undefined) {
27252726
this.logger.info(`Excluded '${normalizedNames[i]}' because it matched ${cleanedTypingName} from the legacy safelist`);
27262727
excludedFiles.push(normalizedNames[i]);
27272728
// *exclude* it from the project...
27282729
exclude = true;
27292730
// ... but *include* it in the list of types to acquire
2730-
const typeName = this.legacySafelist[cleanedTypingName];
27312731
// Same best-effort dedupe as above
27322732
if (typeAcqInclude.indexOf(typeName) < 0) {
27332733
typeAcqInclude.push(typeName);

src/testRunner/unittests/tsserverProjectSystem.ts

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1826,6 +1826,63 @@ namespace ts.projectSystem {
18261826
}
18271827
});
18281828

1829+
it("file with name constructor.js doesnt cause issue with typeAcquisition when safe type list", () => {
1830+
const file1 = {
1831+
path: "/a/b/f1.js",
1832+
content: `export let x = 5; import { s } from "s"`
1833+
};
1834+
const constructorFile = {
1835+
path: "/a/b/constructor.js",
1836+
content: "const x = 10;"
1837+
};
1838+
const bliss = {
1839+
path: "/a/b/bliss.js",
1840+
content: "export function is() { return true; }"
1841+
};
1842+
const host = createServerHost([file1, libFile, constructorFile, bliss, customTypesMap]);
1843+
let request: string | undefined;
1844+
const cachePath = "/a/data";
1845+
const typingsInstaller: server.ITypingsInstaller = {
1846+
isKnownTypesPackageName: returnFalse,
1847+
installPackage: notImplemented,
1848+
inspectValue: notImplemented,
1849+
enqueueInstallTypingsRequest: (proj, typeAcquisition, unresolvedImports) => {
1850+
assert.isUndefined(request);
1851+
request = JSON.stringify(server.createInstallTypingsRequest(proj, typeAcquisition, unresolvedImports || server.emptyArray, cachePath));
1852+
},
1853+
attach: noop,
1854+
onProjectClosed: noop,
1855+
globalTypingsCacheLocation: cachePath
1856+
};
1857+
1858+
const projectName = "project";
1859+
const projectService = createProjectService(host, { typingsInstaller });
1860+
projectService.openExternalProject({ projectFileName: projectName, options: {}, rootFiles: toExternalFiles([file1.path, constructorFile.path, bliss.path]) });
1861+
assert.equal(request, JSON.stringify({
1862+
projectName,
1863+
fileNames: [libFile.path, file1.path, constructorFile.path, bliss.path],
1864+
compilerOptions: { allowNonTsExtensions: true, noEmitForJsFiles: true },
1865+
typeAcquisition: { include: ["blissfuljs"], exclude: [], enable: true },
1866+
unresolvedImports: ["s"],
1867+
projectRootPath: "/",
1868+
cachePath,
1869+
kind: "discover"
1870+
}));
1871+
const response = JSON.parse(request!);
1872+
request = undefined;
1873+
projectService.updateTypingsForProject({
1874+
kind: "action::set",
1875+
projectName: response.projectName,
1876+
typeAcquisition: response.typeAcquisition,
1877+
compilerOptions: response.compilerOptions,
1878+
typings: emptyArray,
1879+
unresolvedImports: response.unresolvedImports,
1880+
});
1881+
1882+
host.checkTimeoutQueueLengthAndRun(2);
1883+
assert.isUndefined(request);
1884+
});
1885+
18291886
it("ignores files excluded by the default type list", () => {
18301887
const file1 = {
18311888
path: "/a/b/f1.js",

0 commit comments

Comments
 (0)