From 0b248d5e298db53c6cc9c47a2994bc382e79a0ce Mon Sep 17 00:00:00 2001
From: Sheetal Nandi
Date: Wed, 21 Feb 2018 12:40:36 -0800
Subject: [PATCH 01/22] Trace should write messages to the logger
---
src/server/project.ts | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/src/server/project.ts b/src/server/project.ts
index dc949b4b221..743b4e4bfb7 100644
--- a/src/server/project.ts
+++ b/src/server/project.ts
@@ -238,7 +238,10 @@ namespace ts.server {
this.setInternalCompilerOptionsForEmittingJsFiles();
const host = this.projectService.host;
- if (host.trace) {
+ if (this.projectService.logger.loggingEnabled()) {
+ this.trace = s => this.writeLog(s);
+ }
+ else if (host.trace) {
this.trace = s => host.trace(s);
}
From 403b7d8604087173e82946fff65dc32ea94443bd Mon Sep 17 00:00:00 2001
From: Sheetal Nandi
Date: Thu, 22 Feb 2018 09:17:00 -0800
Subject: [PATCH 02/22] Add tests for module resolution order and reuse
---
.../unittests/tsserverProjectSystem.ts | 343 +++++++++++++++++-
1 file changed, 341 insertions(+), 2 deletions(-)
diff --git a/src/harness/unittests/tsserverProjectSystem.ts b/src/harness/unittests/tsserverProjectSystem.ts
index e09dff2a6d5..02776b4de07 100644
--- a/src/harness/unittests/tsserverProjectSystem.ts
+++ b/src/harness/unittests/tsserverProjectSystem.ts
@@ -145,6 +145,12 @@ namespace ts.projectSystem {
return map;
}
+ function createHostModuleResolutionTrace(host: TestServerHost & ModuleResolutionHost) {
+ const resolutionTrace: string[] = [];
+ host.trace = resolutionTrace.push.bind(resolutionTrace);
+ return resolutionTrace;
+ }
+
export function toExternalFile(fileName: string): protocol.ExternalFile {
return { fileName };
}
@@ -3201,8 +3207,7 @@ namespace ts.projectSystem {
content: "export let x = 1"
};
const host: TestServerHost & ModuleResolutionHost = createServerHost([file1, lib]);
- const resolutionTrace: string[] = [];
- host.trace = resolutionTrace.push.bind(resolutionTrace);
+ const resolutionTrace = createHostModuleResolutionTrace(host);
const projectService = createProjectService(host, { typingsInstaller: new TestTypingsInstaller("/a/cache", /*throttleLimit*/5, host) });
projectService.setCompilerOptionsForInferredProjects({ traceResolution: true, allowJs: true });
@@ -6971,4 +6976,338 @@ namespace ts.projectSystem {
assert.deepEqual(diagnostics, []);
});
});
+
+ describe("tsserverProjectSystem module resolution caching", () => {
+ const projectLocation = "/user/username/projects/myproject";
+ const configFile: FileOrFolder = {
+ path: `${projectLocation}/tsconfig.json`,
+ content: JSON.stringify({ compilerOptions: { traceResolution: true } })
+ };
+
+ function getModules(module1Path: string, module2Path: string) {
+ const module1: FileOrFolder = {
+ path: module1Path,
+ content: `export function module1() {}`
+ };
+ const module2: FileOrFolder = {
+ path: module2Path,
+ content: `export function module2() {}`
+ };
+ return { module1, module2 };
+ }
+
+ function verifyTrace(resolutionTrace: string[], expected: string[]) {
+ assert.deepEqual(resolutionTrace, expected);
+ resolutionTrace.length = 0;
+ }
+
+ function getExpectedFileDoesNotExistResolutionTrace(host: TestServerHost, expectedTrace: string[], foundModule: boolean, module: FileOrFolder, directory: string, file: string, ignoreIfParentMissing?: boolean) {
+ if (!foundModule) {
+ const path = combinePaths(directory, file);
+ if (!ignoreIfParentMissing || host.directoryExists(getDirectoryPath(path))) {
+ if (module.path === path) {
+ foundModule = true;
+ }
+ else {
+ expectedTrace.push(`File '${path}' does not exist.`);
+ }
+ }
+ }
+ return foundModule;
+ }
+
+ function getExpectedMissedLocationResolutionTrace(host: TestServerHost, expectedTrace: string[], dirPath: string, module: FileOrFolder, moduleName: string, useNodeModules: boolean) {
+ let foundModule = false;
+ forEachAncestorDirectory(dirPath, dirPath => {
+ const directory = useNodeModules ? combinePaths(dirPath, nodeModules) : dirPath;
+ if (useNodeModules && !foundModule && !host.directoryExists(directory)) {
+ expectedTrace.push(`Directory '${directory}' does not exist, skipping all lookups in it.`);
+ return undefined;
+ }
+ foundModule = getExpectedFileDoesNotExistResolutionTrace(host, expectedTrace, foundModule, module, directory, `${moduleName}/package.json`, /*ignoreIfParentMissing*/ true);
+ foundModule = getExpectedFileDoesNotExistResolutionTrace(host, expectedTrace, foundModule, module, directory, `${moduleName}.ts`);
+ foundModule = getExpectedFileDoesNotExistResolutionTrace(host, expectedTrace, foundModule, module, directory, `${moduleName}.tsx`);
+ foundModule = getExpectedFileDoesNotExistResolutionTrace(host, expectedTrace, foundModule, module, directory, `${moduleName}.d.ts`);
+ foundModule = getExpectedFileDoesNotExistResolutionTrace(host, expectedTrace, foundModule, module, directory, `${moduleName}/index.ts`, /*ignoreIfParentMissing*/ true);
+ if (useNodeModules && !foundModule) {
+ expectedTrace.push(`Directory '${directory}/@types' does not exist, skipping all lookups in it.`);
+ }
+ return foundModule ? true : undefined;
+ });
+ }
+
+ function getExpectedResolutionTraceHeader(expectedTrace: string[], file: FileOrFolder, moduleName: string) {
+ expectedTrace.push(
+ `======== Resolving module '${moduleName}' from '${file.path}'. ========`,
+ `Module resolution kind is not specified, using 'NodeJs'.`
+ );
+ }
+
+ function getExpectedResolutionTraceFooter(expectedTrace: string[], module: FileOrFolder, moduleName: string, addRealPathTrace: boolean) {
+ expectedTrace.push(`File '${module.path}' exist - use it as a name resolution result.`);
+ if (addRealPathTrace) {
+ expectedTrace.push(`Resolving real path for '${module.path}', result '${module.path}'.`);
+ }
+ expectedTrace.push(`======== Module name '${moduleName}' was successfully resolved to '${module.path}'. ========`);
+ }
+
+ function getExpectedRelativeModuleResolutionTrace(host: TestServerHost, file: FileOrFolder, module: FileOrFolder, moduleName: string, expectedTrace: string[] = []) {
+ getExpectedResolutionTraceHeader(expectedTrace, file, moduleName);
+ expectedTrace.push(`Loading module as file / folder, candidate module location '${removeFileExtension(module.path)}', target file type 'TypeScript'.`);
+ getExpectedMissedLocationResolutionTrace(host, expectedTrace, getDirectoryPath(normalizePath(combinePaths(getDirectoryPath(file.path), moduleName))), module, moduleName.substring(moduleName.lastIndexOf("/") + 1), /*useNodeModules*/ false);
+ getExpectedResolutionTraceFooter(expectedTrace, module, moduleName, /*addRealPathTrace*/ false);
+ return expectedTrace;
+ }
+
+ function getExpectedNonRelativeModuleResolutionTrace(host: TestServerHost, file: FileOrFolder, module: FileOrFolder, moduleName: string, expectedTrace: string[] = []) {
+ getExpectedResolutionTraceHeader(expectedTrace, file, moduleName);
+ expectedTrace.push(`Loading module '${moduleName}' from 'node_modules' folder, target file type 'TypeScript'.`);
+ getExpectedMissedLocationResolutionTrace(host, expectedTrace, getDirectoryPath(file.path), module, moduleName, /*useNodeModules*/ true);
+ getExpectedResolutionTraceFooter(expectedTrace, module, moduleName, /*addRealPathTrace*/ true);
+ return expectedTrace;
+ }
+
+ function getExpectedReusingResolutionFromOldProgram(file: FileOrFolder, moduleName: string) {
+ return `Reusing resolution of module '${moduleName}' to file '${file.path}' from old program.`;
+ }
+
+ function verifyWatchesWithConfigFile(host: TestServerHost, files: FileOrFolder[], openFile: FileOrFolder) {
+ checkWatchedFiles(host, mapDefined(files, f => f === openFile ? undefined : f.path));
+ checkWatchedDirectories(host, [], /*recursive*/ false);
+ const configDirectory = getDirectoryPath(configFile.path);
+ checkWatchedDirectories(host, [configDirectory, `${configDirectory}/${nodeModulesAtTypes}`], /*recursive*/ true);
+ }
+
+ describe("from files in same folder", () => {
+ function getFiles(fileContent: string) {
+ const file1: FileOrFolder = {
+ path: `${projectLocation}/src/file1.ts`,
+ content: fileContent
+ };
+ const file2: FileOrFolder = {
+ path: `${projectLocation}/src/file2.ts`,
+ content: fileContent
+ };
+ return { file1, file2 };
+ }
+
+ it("relative module name", () => {
+ const module1Name = "./module1";
+ const module2Name = "../module2";
+ const fileContent = `import { module1 } from "${module1Name}";import { module2 } from "${module2Name}";`;
+ const { file1, file2 } = getFiles(fileContent);
+ const { module1, module2 } = getModules(`${projectLocation}/src/module1.ts`, `${projectLocation}/module2.ts`);
+ const files = [module1, module2, file1, file2, configFile, libFile];
+ const host = createServerHost(files);
+ const resolutionTrace = createHostModuleResolutionTrace(host);
+ const service = createProjectService(host);
+ service.openClientFile(file1.path);
+ const expectedTrace = getExpectedRelativeModuleResolutionTrace(host, file1, module1, module1Name);
+ getExpectedRelativeModuleResolutionTrace(host, file1, module2, module2Name, expectedTrace);
+ verifyTrace(resolutionTrace, expectedTrace);
+ verifyWatchesWithConfigFile(host, files, file1);
+
+ file1.content += fileContent;
+ file2.content += fileContent;
+ host.reloadFS(files);
+ host.runQueuedTimeoutCallbacks();
+ verifyTrace(resolutionTrace, [
+ getExpectedReusingResolutionFromOldProgram(file1, module1Name),
+ getExpectedReusingResolutionFromOldProgram(file1, module2Name)
+ ]);
+ verifyWatchesWithConfigFile(host, files, file1);
+ });
+
+ it("non relative module name", () => {
+ const module1Name = "module1";
+ const module2Name = "module2";
+ const fileContent = `import { module1 } from "${module1Name}";import { module2 } from "${module2Name}";`;
+ const { file1, file2 } = getFiles(fileContent);
+ const { module1, module2 } = getModules(`${projectLocation}/src/node_modules/module1/index.ts`, `${projectLocation}/node_modules/module2/index.ts`);
+ const files = [module1, module2, file1, file2, configFile, libFile];
+ const host = createServerHost(files);
+ const resolutionTrace = createHostModuleResolutionTrace(host);
+ const service = createProjectService(host);
+ service.openClientFile(file1.path);
+ const expectedTrace = getExpectedNonRelativeModuleResolutionTrace(host, file1, module1, module1Name);
+ getExpectedNonRelativeModuleResolutionTrace(host, file1, module2, module2Name, expectedTrace);
+ verifyTrace(resolutionTrace, expectedTrace);
+ verifyWatchesWithConfigFile(host, files, file1);
+
+ file1.content += fileContent;
+ file2.content += fileContent;
+ host.reloadFS(files);
+ host.runQueuedTimeoutCallbacks();
+ verifyTrace(resolutionTrace, [
+ getExpectedReusingResolutionFromOldProgram(file1, module1Name),
+ getExpectedReusingResolutionFromOldProgram(file1, module2Name)
+ ]);
+ verifyWatchesWithConfigFile(host, files, file1);
+ });
+ });
+
+ describe("from files in different folders", () => {
+ function getFiles(fileContent1: string, fileContent2 = fileContent1, fileContent3 = fileContent1, fileContent4 = fileContent1) {
+ const file1: FileOrFolder = {
+ path: `${projectLocation}/product/src/file1.ts`,
+ content: fileContent1
+ };
+ const file2: FileOrFolder = {
+ path: `${projectLocation}/product/src/feature/file2.ts`,
+ content: fileContent2
+ };
+ const file3: FileOrFolder = {
+ path: `${projectLocation}/product/test/src/file3.ts`,
+ content: fileContent3
+ };
+ const file4: FileOrFolder = {
+ path: `${projectLocation}/product/test/file4.ts`,
+ content: fileContent4
+ };
+ return { file1, file2, file3, file4 };
+ }
+
+ it("relative module name", () => {
+ const module1Name = "./module1";
+ const module2Name = "../module2";
+ const module3Name = "../module1";
+ const module4Name = "../../module2";
+ const module5Name = "../../src/module1";
+ const module6Name = "../src/module1";
+ const fileContent1 = `import { module1 } from "${module1Name}";import { module2 } from "${module2Name}";`;
+ const fileContent2 = `import { module1 } from "${module3Name}";import { module2 } from "${module4Name}";`;
+ const fileContent3 = `import { module1 } from "${module5Name}";import { module2 } from "${module4Name}";`;
+ const fileContent4 = `import { module1 } from "${module6Name}";import { module2 } from "${module2Name}";`;
+ const { file1, file2, file3, file4 } = getFiles(fileContent1, fileContent2, fileContent3, fileContent4);
+ const { module1, module2 } = getModules(`${projectLocation}/product/src/module1.ts`, `${projectLocation}/product/module2.ts`);
+ const files = [module1, module2, file1, file2, file3, file4, configFile, libFile];
+ const host = createServerHost(files);
+ const resolutionTrace = createHostModuleResolutionTrace(host);
+ const service = createProjectService(host);
+ service.openClientFile(file1.path);
+ const expectedTrace = getExpectedRelativeModuleResolutionTrace(host, file1, module1, module1Name);
+ getExpectedRelativeModuleResolutionTrace(host, file1, module2, module2Name, expectedTrace);
+ getExpectedRelativeModuleResolutionTrace(host, file2, module1, module3Name, expectedTrace);
+ getExpectedRelativeModuleResolutionTrace(host, file2, module2, module4Name, expectedTrace);
+ getExpectedRelativeModuleResolutionTrace(host, file4, module1, module6Name, expectedTrace);
+ getExpectedRelativeModuleResolutionTrace(host, file4, module2, module2Name, expectedTrace);
+ getExpectedRelativeModuleResolutionTrace(host, file3, module1, module5Name, expectedTrace);
+ getExpectedRelativeModuleResolutionTrace(host, file3, module2, module4Name, expectedTrace);
+ verifyTrace(resolutionTrace, expectedTrace);
+ verifyWatchesWithConfigFile(host, files, file1);
+
+ file1.content += fileContent1;
+ file2.content += fileContent2;
+ file3.content += fileContent3;
+ file4.content += fileContent4;
+ host.reloadFS(files);
+ host.runQueuedTimeoutCallbacks();
+
+ verifyTrace(resolutionTrace, [
+ getExpectedReusingResolutionFromOldProgram(file1, module1Name),
+ getExpectedReusingResolutionFromOldProgram(file1, module2Name)
+ ]);
+ verifyWatchesWithConfigFile(host, files, file1);
+ });
+
+ it("non relative module name", () => {
+ const module1Name = "module1";
+ const module2Name = "module2";
+ const fileContent = `import { module1 } from "${module1Name}";import { module2 } from "${module2Name}";`;
+ const { file1, file2, file3, file4 } = getFiles(fileContent);
+ const { module1, module2 } = getModules(`${projectLocation}/product/node_modules/module1/index.ts`, `${projectLocation}/node_modules/module2/index.ts`);
+ const files = [module1, module2, file1, file2, file3, file4, configFile, libFile];
+ const host = createServerHost(files);
+ const resolutionTrace = createHostModuleResolutionTrace(host);
+ const service = createProjectService(host);
+ service.openClientFile(file1.path);
+ const expectedTrace = getExpectedNonRelativeModuleResolutionTrace(host, file1, module1, module1Name);
+ getExpectedNonRelativeModuleResolutionTrace(host, file1, module2, module2Name, expectedTrace);
+ getExpectedNonRelativeModuleResolutionTrace(host, file2, module1, module1Name, expectedTrace);
+ getExpectedNonRelativeModuleResolutionTrace(host, file2, module2, module2Name, expectedTrace);
+ getExpectedNonRelativeModuleResolutionTrace(host, file4, module1, module1Name, expectedTrace);
+ getExpectedNonRelativeModuleResolutionTrace(host, file4, module2, module2Name, expectedTrace);
+ getExpectedNonRelativeModuleResolutionTrace(host, file3, module1, module1Name, expectedTrace);
+ getExpectedNonRelativeModuleResolutionTrace(host, file3, module2, module2Name, expectedTrace);
+ verifyTrace(resolutionTrace, expectedTrace);
+ verifyWatchesWithConfigFile(host, files, file1);
+
+ file1.content += fileContent;
+ file2.content += fileContent;
+ file3.content += fileContent;
+ file4.content += fileContent;
+ host.reloadFS(files);
+ host.runQueuedTimeoutCallbacks();
+
+ verifyTrace(resolutionTrace, [
+ getExpectedReusingResolutionFromOldProgram(file1, module1Name),
+ getExpectedReusingResolutionFromOldProgram(file1, module2Name)
+ ]);
+ verifyWatchesWithConfigFile(host, files, file1);
+ });
+
+ it("non relative module name from inferred project", () => {
+ const module1Name = "module1";
+ const module2Name = "module2";
+ const file2Name = "./feature/file2";
+ const file3Name = "../test/src/file3";
+ const file4Name = "../test/file4";
+ const importModuleContent = `import { module1 } from "${module1Name}";import { module2 } from "${module2Name}";`;
+ const { file1, file2, file3, file4 } = getFiles(`import "${file2Name}"; import "${file4Name}"; import "${file3Name}"; ${importModuleContent}`, importModuleContent, importModuleContent, importModuleContent);
+ const { module1, module2 } = getModules(`${projectLocation}/product/node_modules/module1/index.ts`, `${projectLocation}/node_modules/module2/index.ts`);
+ const files = [module1, module2, file1, file2, file3, file4, libFile];
+ const host = createServerHost(files);
+ const resolutionTrace = createHostModuleResolutionTrace(host);
+ const service = createProjectService(host);
+ service.setCompilerOptionsForInferredProjects({ traceResolution: true });
+ service.openClientFile(file1.path);
+ const expectedTrace = getExpectedRelativeModuleResolutionTrace(host, file1, file2, file2Name);
+ getExpectedRelativeModuleResolutionTrace(host, file1, file4, file4Name, expectedTrace);
+ getExpectedRelativeModuleResolutionTrace(host, file1, file3, file3Name, expectedTrace);
+ getExpectedNonRelativeModuleResolutionTrace(host, file1, module1, module1Name, expectedTrace);
+ getExpectedNonRelativeModuleResolutionTrace(host, file1, module2, module2Name, expectedTrace);
+ getExpectedNonRelativeModuleResolutionTrace(host, file2, module1, module1Name, expectedTrace);
+ getExpectedNonRelativeModuleResolutionTrace(host, file2, module2, module2Name, expectedTrace);
+ getExpectedNonRelativeModuleResolutionTrace(host, file4, module1, module1Name, expectedTrace);
+ getExpectedNonRelativeModuleResolutionTrace(host, file4, module2, module2Name, expectedTrace);
+ getExpectedNonRelativeModuleResolutionTrace(host, file3, module1, module1Name, expectedTrace);
+ getExpectedNonRelativeModuleResolutionTrace(host, file3, module2, module2Name, expectedTrace);
+ verifyTrace(resolutionTrace, expectedTrace);
+
+ const currentDirectory = getDirectoryPath(file1.path);
+ const watchedFiles = mapDefined(files, f => f === file1 ? undefined : f.path);
+ forEachAncestorDirectory(currentDirectory, d => {
+ watchedFiles.push(combinePaths(d, "tsconfig.json"), combinePaths(d, "jsconfig.json"));
+ });
+ const watchedRecursiveDirectories = getTypeRootsFromLocation(currentDirectory).concat([
+ currentDirectory, `${projectLocation}/product/${nodeModules}`,
+ `${projectLocation}/${nodeModules}`, `${projectLocation}/product/test/${nodeModules}`,
+ `${projectLocation}/product/test/src/${nodeModules}`
+ ]);
+ checkWatches();
+
+ file1.content += importModuleContent;
+ file2.content += importModuleContent;
+ file3.content += importModuleContent;
+ file4.content += importModuleContent;
+ host.reloadFS(files);
+ host.runQueuedTimeoutCallbacks();
+
+ verifyTrace(resolutionTrace, [
+ getExpectedReusingResolutionFromOldProgram(file1, file2Name),
+ getExpectedReusingResolutionFromOldProgram(file1, file4Name),
+ getExpectedReusingResolutionFromOldProgram(file1, file3Name),
+ getExpectedReusingResolutionFromOldProgram(file1, module1Name),
+ getExpectedReusingResolutionFromOldProgram(file1, module2Name)
+ ]);
+ checkWatches();
+
+ function checkWatches() {
+ checkWatchedFiles(host, watchedFiles);
+ checkWatchedDirectories(host, [], /*recursive*/ false);
+ checkWatchedDirectories(host, watchedRecursiveDirectories, /*recursive*/ true);
+ }
+ });
+ });
+ });
}
From fdb5e95f0a868e2dfdb1a373119f61884fc6c57e Mon Sep 17 00:00:00 2001
From: Sheetal Nandi
Date: Thu, 22 Feb 2018 11:09:23 -0800
Subject: [PATCH 03/22] Use the module cache to resolve non relative module
name as well
---
src/compiler/diagnosticMessages.json | 2 +-
src/compiler/moduleNameResolver.ts | 20 +++++++--
src/compiler/resolutionCache.ts | 17 +++++--
.../unittests/tsserverProjectSystem.ts | 45 ++++++++++++-------
src/server/project.ts | 4 ++
.../reference/cacheResolutions.trace.json | 4 +-
.../cachedModuleResolution1.trace.json | 2 +-
.../cachedModuleResolution2.trace.json | 2 +-
.../cachedModuleResolution3.trace.json | 2 +-
.../cachedModuleResolution4.trace.json | 2 +-
.../cachedModuleResolution5.trace.json | 2 +-
.../cachedModuleResolution6.trace.json | 2 +-
.../cachedModuleResolution7.trace.json | 2 +-
.../cachedModuleResolution8.trace.json | 2 +-
.../cachedModuleResolution9.trace.json | 2 +-
.../typeReferenceDirectives12.trace.json | 2 +-
.../typeReferenceDirectives9.trace.json | 2 +-
17 files changed, 77 insertions(+), 37 deletions(-)
diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json
index f120e81283a..2fc24ca7a84 100644
--- a/src/compiler/diagnosticMessages.json
+++ b/src/compiler/diagnosticMessages.json
@@ -3296,7 +3296,7 @@
"category": "Message",
"code": 6146
},
- "Resolution for module '{0}' was found in cache.": {
+ "Resolution for module '{0}' was found in cache from location '{1}'.": {
"category": "Message",
"code": 6147
},
diff --git a/src/compiler/moduleNameResolver.ts b/src/compiler/moduleNameResolver.ts
index 50181bb98e4..798fd169585 100644
--- a/src/compiler/moduleNameResolver.ts
+++ b/src/compiler/moduleNameResolver.ts
@@ -335,8 +335,20 @@ namespace ts {
}
export function createModuleResolutionCache(currentDirectory: string, getCanonicalFileName: (s: string) => string): ModuleResolutionCache {
- const directoryToModuleNameMap = createMap
;
+>p : any
+ }
+}
+export const tree =
+>tree : predom.JSX.Element
+> : predom.JSX.Element
+>MySFC : (props: { x: number; y: number; children?: predom.JSX.Element[]; }) => predom.JSX.Element
+>x : number
+>1 : 1
+>y : number
+>2 : 2
+> : predom.JSX.Element
+>MyClass : typeof MyClass
+>x : number
+>3 : 3
+>y : number
+>4 : 4
+> : predom.JSX.Element
+>MyClass : typeof MyClass
+>x : number
+>5 : 5
+>y : number
+>6 : 6
+>MySFC : (props: { x: number; y: number; children?: predom.JSX.Element[]; }) => predom.JSX.Element
+
+export default
+> : predom.JSX.Element
+>h : any
+>h : any
+
+=== tests/cases/conformance/jsx/inline/index.tsx ===
+/** @jsx dom */
+import { dom } from "./renderer"
+>dom : () => dom.JSX.Element
+
+import prerendered, {MySFC, MyClass, tree} from "./component";
+>prerendered : predom.JSX.Element
+>MySFC : (props: { x: number; y: number; children?: predom.JSX.Element[]; }) => predom.JSX.Element
+>MyClass : typeof MyClass
+>tree : predom.JSX.Element
+
+let elem = prerendered;
+>elem : predom.JSX.Element
+>prerendered : predom.JSX.Element
+
+elem = ; // Expect assignability error here
+>elem = : dom.JSX.Element
+>elem : predom.JSX.Element
+> : dom.JSX.Element
+>h : any
+>h : any
+
+const DOMSFC = (props: {x: number, y: number, children?: dom.JSX.Element[]}) => {props.x} + {props.y} = {props.x + props.y}{props.children}
;
+>DOMSFC : (props: { x: number; y: number; children?: dom.JSX.Element[]; }) => dom.JSX.Element
+>(props: {x: number, y: number, children?: dom.JSX.Element[]}) => {props.x} + {props.y} = {props.x + props.y}{props.children}
: (props: { x: number; y: number; children?: dom.JSX.Element[]; }) => dom.JSX.Element
+>props : { x: number; y: number; children?: dom.JSX.Element[]; }
+>x : number
+>y : number
+>children : dom.JSX.Element[]
+>dom : any
+>JSX : any
+>Element : dom.JSX.Element
+>{props.x} + {props.y} = {props.x + props.y}{props.children}
: dom.JSX.Element
+>p : any
+>props.x : number
+>props : { x: number; y: number; children?: dom.JSX.Element[]; }
+>x : number
+>props.y : number
+>props : { x: number; y: number; children?: dom.JSX.Element[]; }
+>y : number
+>props.x + props.y : number
+>props.x : number
+>props : { x: number; y: number; children?: dom.JSX.Element[]; }
+>x : number
+>props.y : number
+>props : { x: number; y: number; children?: dom.JSX.Element[]; }
+>y : number
+>props.children : dom.JSX.Element[]
+>props : { x: number; y: number; children?: dom.JSX.Element[]; }
+>children : dom.JSX.Element[]
+>p : any
+
+class DOMClass implements dom.JSX.Element {
+>DOMClass : DOMClass
+>dom.JSX.Element : any
+>dom.JSX : any
+>dom : () => dom.JSX.Element
+>JSX : any
+>Element : dom.JSX.Element
+
+ __domBrand!: void;
+>__domBrand : void
+
+ constructor(public props: {x: number, y: number, children?: dom.JSX.Element[]}) {}
+>props : { x: number; y: number; children?: dom.JSX.Element[]; }
+>x : number
+>y : number
+>children : dom.JSX.Element[]
+>dom : any
+>JSX : any
+>Element : dom.JSX.Element
+
+ render() {
+>render : () => dom.JSX.Element
+
+ return {this.props.x} + {this.props.y} = {this.props.x + this.props.y}{...this.props.children}
;
+>{this.props.x} + {this.props.y} = {this.props.x + this.props.y}{...this.props.children}
: dom.JSX.Element
+>p : any
+>this.props.x : number
+>this.props : { x: number; y: number; children?: dom.JSX.Element[]; }
+>this : this
+>props : { x: number; y: number; children?: dom.JSX.Element[]; }
+>x : number
+>this.props.y : number
+>this.props : { x: number; y: number; children?: dom.JSX.Element[]; }
+>this : this
+>props : { x: number; y: number; children?: dom.JSX.Element[]; }
+>y : number
+>this.props.x + this.props.y : number
+>this.props.x : number
+>this.props : { x: number; y: number; children?: dom.JSX.Element[]; }
+>this : this
+>props : { x: number; y: number; children?: dom.JSX.Element[]; }
+>x : number
+>this.props.y : number
+>this.props : { x: number; y: number; children?: dom.JSX.Element[]; }
+>this : this
+>props : { x: number; y: number; children?: dom.JSX.Element[]; }
+>y : number
+>this.props.children : dom.JSX.Element[]
+>this.props : { x: number; y: number; children?: dom.JSX.Element[]; }
+>this : this
+>props : { x: number; y: number; children?: dom.JSX.Element[]; }
+>children : dom.JSX.Element[]
+>p : any
+ }
+}
+
+// Should work, everything is a DOM element
+const _tree =
+>_tree : dom.JSX.Element
+> : dom.JSX.Element
+>DOMSFC : (props: { x: number; y: number; children?: dom.JSX.Element[]; }) => dom.JSX.Element
+>x : number
+>1 : 1
+>y : number
+>2 : 2
+> : dom.JSX.Element
+>DOMClass : typeof DOMClass
+>x : number
+>3 : 3
+>y : number
+>4 : 4
+> : dom.JSX.Element
+>DOMClass : typeof DOMClass
+>x : number
+>5 : 5
+>y : number
+>6 : 6
+>DOMSFC : (props: { x: number; y: number; children?: dom.JSX.Element[]; }) => dom.JSX.Element
+
+// Should fail, no dom elements
+const _brokenTree =
+>_brokenTree : dom.JSX.Element
+> : dom.JSX.Element
+>MySFC : (props: { x: number; y: number; children?: predom.JSX.Element[]; }) => predom.JSX.Element
+>x : number
+>1 : 1
+>y : number
+>2 : 2
+> : dom.JSX.Element
+>MyClass : typeof MyClass
+>x : number
+>3 : 3
+>y : number
+>4 : 4
+> : dom.JSX.Element
+>MyClass : typeof MyClass
+>x : number
+>5 : 5
+>y : number
+>6 : 6
+>MySFC : (props: { x: number; y: number; children?: predom.JSX.Element[]; }) => predom.JSX.Element
+
+// Should fail, nondom isn't allowed as children of dom
+const _brokenTree2 = {tree}{tree}
+>_brokenTree2 : dom.JSX.Element
+>{tree}{tree} : dom.JSX.Element
+>DOMSFC : (props: { x: number; y: number; children?: dom.JSX.Element[]; }) => dom.JSX.Element
+>x : number
+>1 : 1
+>y : number
+>2 : 2
+>tree : predom.JSX.Element
+>tree : predom.JSX.Element
+>DOMSFC : (props: { x: number; y: number; children?: dom.JSX.Element[]; }) => dom.JSX.Element
+
diff --git a/tests/baselines/reference/inlineJsxFactoryLocalTypeGlobalFallback.errors.txt b/tests/baselines/reference/inlineJsxFactoryLocalTypeGlobalFallback.errors.txt
new file mode 100644
index 00000000000..9d4e4e0a026
--- /dev/null
+++ b/tests/baselines/reference/inlineJsxFactoryLocalTypeGlobalFallback.errors.txt
@@ -0,0 +1,51 @@
+tests/cases/conformance/jsx/inline/index.tsx(5,1): error TS2322: Type 'JSX.Element' is not assignable to type 'predom.JSX.Element'.
+ Property '__predomBrand' is missing in type 'Element'.
+
+
+==== tests/cases/conformance/jsx/inline/renderer.d.ts (0 errors) ====
+ declare global {
+ namespace JSX {
+ interface IntrinsicElements {
+ [e: string]: {};
+ }
+ interface Element {
+ __domBrand: void;
+ children: Element[];
+ props: {};
+ }
+ interface ElementAttributesProperty { props: any; }
+ interface ElementChildrenAttribute { children: any; }
+ }
+ }
+ export function dom(): JSX.Element;
+==== tests/cases/conformance/jsx/inline/renderer2.d.ts (0 errors) ====
+ export namespace predom {
+ namespace JSX {
+ interface IntrinsicElements {
+ [e: string]: {};
+ }
+ interface Element {
+ __predomBrand: void;
+ children: Element[];
+ props: {};
+ }
+ interface ElementAttributesProperty { props: any; }
+ interface ElementChildrenAttribute { children: any; }
+ }
+ }
+ export function predom(): predom.JSX.Element;
+==== tests/cases/conformance/jsx/inline/component.tsx (0 errors) ====
+ /** @jsx predom */
+ import { predom } from "./renderer2"
+ export default
+
+==== tests/cases/conformance/jsx/inline/index.tsx (1 errors) ====
+ /** @jsx dom */
+ import { dom } from "./renderer"
+ import prerendered from "./component";
+ let elem = prerendered;
+ elem = ; // Expect assignability error here
+ ~~~~
+!!! error TS2322: Type 'JSX.Element' is not assignable to type 'predom.JSX.Element'.
+!!! error TS2322: Property '__predomBrand' is missing in type 'Element'.
+
\ No newline at end of file
diff --git a/tests/baselines/reference/inlineJsxFactoryLocalTypeGlobalFallback.js b/tests/baselines/reference/inlineJsxFactoryLocalTypeGlobalFallback.js
new file mode 100644
index 00000000000..4f5123ed67d
--- /dev/null
+++ b/tests/baselines/reference/inlineJsxFactoryLocalTypeGlobalFallback.js
@@ -0,0 +1,61 @@
+//// [tests/cases/conformance/jsx/inline/inlineJsxFactoryLocalTypeGlobalFallback.tsx] ////
+
+//// [renderer.d.ts]
+declare global {
+ namespace JSX {
+ interface IntrinsicElements {
+ [e: string]: {};
+ }
+ interface Element {
+ __domBrand: void;
+ children: Element[];
+ props: {};
+ }
+ interface ElementAttributesProperty { props: any; }
+ interface ElementChildrenAttribute { children: any; }
+ }
+}
+export function dom(): JSX.Element;
+//// [renderer2.d.ts]
+export namespace predom {
+ namespace JSX {
+ interface IntrinsicElements {
+ [e: string]: {};
+ }
+ interface Element {
+ __predomBrand: void;
+ children: Element[];
+ props: {};
+ }
+ interface ElementAttributesProperty { props: any; }
+ interface ElementChildrenAttribute { children: any; }
+ }
+}
+export function predom(): predom.JSX.Element;
+//// [component.tsx]
+/** @jsx predom */
+import { predom } from "./renderer2"
+export default
+
+//// [index.tsx]
+/** @jsx dom */
+import { dom } from "./renderer"
+import prerendered from "./component";
+let elem = prerendered;
+elem = ; // Expect assignability error here
+
+
+//// [component.js]
+"use strict";
+exports.__esModule = true;
+/** @jsx predom */
+var renderer2_1 = require("./renderer2");
+exports["default"] = renderer2_1.predom("h", null);
+//// [index.js]
+"use strict";
+exports.__esModule = true;
+/** @jsx dom */
+var renderer_1 = require("./renderer");
+var component_1 = require("./component");
+var elem = component_1["default"];
+elem = renderer_1.dom("h", null); // Expect assignability error here
diff --git a/tests/baselines/reference/inlineJsxFactoryLocalTypeGlobalFallback.symbols b/tests/baselines/reference/inlineJsxFactoryLocalTypeGlobalFallback.symbols
new file mode 100644
index 00000000000..c4962015871
--- /dev/null
+++ b/tests/baselines/reference/inlineJsxFactoryLocalTypeGlobalFallback.symbols
@@ -0,0 +1,107 @@
+=== tests/cases/conformance/jsx/inline/renderer.d.ts ===
+declare global {
+>global : Symbol(global, Decl(renderer.d.ts, 0, 0))
+
+ namespace JSX {
+>JSX : Symbol(JSX, Decl(renderer.d.ts, 0, 16))
+
+ interface IntrinsicElements {
+>IntrinsicElements : Symbol(IntrinsicElements, Decl(renderer.d.ts, 1, 19))
+
+ [e: string]: {};
+>e : Symbol(e, Decl(renderer.d.ts, 3, 13))
+ }
+ interface Element {
+>Element : Symbol(Element, Decl(renderer.d.ts, 4, 9))
+
+ __domBrand: void;
+>__domBrand : Symbol(Element.__domBrand, Decl(renderer.d.ts, 5, 27))
+
+ children: Element[];
+>children : Symbol(Element.children, Decl(renderer.d.ts, 6, 29))
+>Element : Symbol(Element, Decl(renderer.d.ts, 4, 9))
+
+ props: {};
+>props : Symbol(Element.props, Decl(renderer.d.ts, 7, 32))
+ }
+ interface ElementAttributesProperty { props: any; }
+>ElementAttributesProperty : Symbol(ElementAttributesProperty, Decl(renderer.d.ts, 9, 9))
+>props : Symbol(ElementAttributesProperty.props, Decl(renderer.d.ts, 10, 45))
+
+ interface ElementChildrenAttribute { children: any; }
+>ElementChildrenAttribute : Symbol(ElementChildrenAttribute, Decl(renderer.d.ts, 10, 59))
+>children : Symbol(ElementChildrenAttribute.children, Decl(renderer.d.ts, 11, 44))
+ }
+}
+export function dom(): JSX.Element;
+>dom : Symbol(dom, Decl(renderer.d.ts, 13, 1))
+>JSX : Symbol(JSX, Decl(renderer.d.ts, 0, 16))
+>Element : Symbol(JSX.Element, Decl(renderer.d.ts, 4, 9))
+
+=== tests/cases/conformance/jsx/inline/renderer2.d.ts ===
+export namespace predom {
+>predom : Symbol(predom, Decl(renderer2.d.ts, 0, 0), Decl(renderer2.d.ts, 13, 1))
+
+ namespace JSX {
+>JSX : Symbol(JSX, Decl(renderer2.d.ts, 0, 25))
+
+ interface IntrinsicElements {
+>IntrinsicElements : Symbol(IntrinsicElements, Decl(renderer2.d.ts, 1, 19))
+
+ [e: string]: {};
+>e : Symbol(e, Decl(renderer2.d.ts, 3, 13))
+ }
+ interface Element {
+>Element : Symbol(Element, Decl(renderer2.d.ts, 4, 9))
+
+ __predomBrand: void;
+>__predomBrand : Symbol(Element.__predomBrand, Decl(renderer2.d.ts, 5, 27))
+
+ children: Element[];
+>children : Symbol(Element.children, Decl(renderer2.d.ts, 6, 32))
+>Element : Symbol(Element, Decl(renderer2.d.ts, 4, 9))
+
+ props: {};
+>props : Symbol(Element.props, Decl(renderer2.d.ts, 7, 32))
+ }
+ interface ElementAttributesProperty { props: any; }
+>ElementAttributesProperty : Symbol(ElementAttributesProperty, Decl(renderer2.d.ts, 9, 9))
+>props : Symbol(ElementAttributesProperty.props, Decl(renderer2.d.ts, 10, 45))
+
+ interface ElementChildrenAttribute { children: any; }
+>ElementChildrenAttribute : Symbol(ElementChildrenAttribute, Decl(renderer2.d.ts, 10, 59))
+>children : Symbol(ElementChildrenAttribute.children, Decl(renderer2.d.ts, 11, 44))
+ }
+}
+export function predom(): predom.JSX.Element;
+>predom : Symbol(predom, Decl(renderer2.d.ts, 0, 0), Decl(renderer2.d.ts, 13, 1))
+>predom : Symbol(predom, Decl(renderer2.d.ts, 0, 0), Decl(renderer2.d.ts, 13, 1))
+>JSX : Symbol(predom.JSX, Decl(renderer2.d.ts, 0, 25))
+>Element : Symbol(predom.JSX.Element, Decl(renderer2.d.ts, 4, 9))
+
+=== tests/cases/conformance/jsx/inline/component.tsx ===
+/** @jsx predom */
+import { predom } from "./renderer2"
+>predom : Symbol(predom, Decl(component.tsx, 1, 8))
+
+export default
+>h : Symbol(predom.JSX.IntrinsicElements, Decl(renderer2.d.ts, 1, 19))
+>h : Symbol(predom.JSX.IntrinsicElements, Decl(renderer2.d.ts, 1, 19))
+
+=== tests/cases/conformance/jsx/inline/index.tsx ===
+/** @jsx dom */
+import { dom } from "./renderer"
+>dom : Symbol(dom, Decl(index.tsx, 1, 8))
+
+import prerendered from "./component";
+>prerendered : Symbol(prerendered, Decl(index.tsx, 2, 6))
+
+let elem = prerendered;
+>elem : Symbol(elem, Decl(index.tsx, 3, 3))
+>prerendered : Symbol(prerendered, Decl(index.tsx, 2, 6))
+
+elem = ; // Expect assignability error here
+>elem : Symbol(elem, Decl(index.tsx, 3, 3))
+>h : Symbol(JSX.IntrinsicElements, Decl(renderer.d.ts, 1, 19))
+>h : Symbol(JSX.IntrinsicElements, Decl(renderer.d.ts, 1, 19))
+
diff --git a/tests/baselines/reference/inlineJsxFactoryLocalTypeGlobalFallback.types b/tests/baselines/reference/inlineJsxFactoryLocalTypeGlobalFallback.types
new file mode 100644
index 00000000000..369341f0f7a
--- /dev/null
+++ b/tests/baselines/reference/inlineJsxFactoryLocalTypeGlobalFallback.types
@@ -0,0 +1,110 @@
+=== tests/cases/conformance/jsx/inline/renderer.d.ts ===
+declare global {
+>global : any
+
+ namespace JSX {
+>JSX : any
+
+ interface IntrinsicElements {
+>IntrinsicElements : IntrinsicElements
+
+ [e: string]: {};
+>e : string
+ }
+ interface Element {
+>Element : Element
+
+ __domBrand: void;
+>__domBrand : void
+
+ children: Element[];
+>children : Element[]
+>Element : Element
+
+ props: {};
+>props : {}
+ }
+ interface ElementAttributesProperty { props: any; }
+>ElementAttributesProperty : ElementAttributesProperty
+>props : any
+
+ interface ElementChildrenAttribute { children: any; }
+>ElementChildrenAttribute : ElementChildrenAttribute
+>children : any
+ }
+}
+export function dom(): JSX.Element;
+>dom : () => JSX.Element
+>JSX : any
+>Element : JSX.Element
+
+=== tests/cases/conformance/jsx/inline/renderer2.d.ts ===
+export namespace predom {
+>predom : () => JSX.Element
+
+ namespace JSX {
+>JSX : any
+
+ interface IntrinsicElements {
+>IntrinsicElements : IntrinsicElements
+
+ [e: string]: {};
+>e : string
+ }
+ interface Element {
+>Element : Element
+
+ __predomBrand: void;
+>__predomBrand : void
+
+ children: Element[];
+>children : Element[]
+>Element : Element
+
+ props: {};
+>props : {}
+ }
+ interface ElementAttributesProperty { props: any; }
+>ElementAttributesProperty : ElementAttributesProperty
+>props : any
+
+ interface ElementChildrenAttribute { children: any; }
+>ElementChildrenAttribute : ElementChildrenAttribute
+>children : any
+ }
+}
+export function predom(): predom.JSX.Element;
+>predom : () => predom.JSX.Element
+>predom : any
+>JSX : any
+>Element : predom.JSX.Element
+
+=== tests/cases/conformance/jsx/inline/component.tsx ===
+/** @jsx predom */
+import { predom } from "./renderer2"
+>predom : () => predom.JSX.Element
+
+export default
+> : predom.JSX.Element
+>h : any
+>h : any
+
+=== tests/cases/conformance/jsx/inline/index.tsx ===
+/** @jsx dom */
+import { dom } from "./renderer"
+>dom : () => JSX.Element
+
+import prerendered from "./component";
+>prerendered : predom.JSX.Element
+
+let elem = prerendered;
+>elem : predom.JSX.Element
+>prerendered : predom.JSX.Element
+
+elem = ; // Expect assignability error here
+>elem = : JSX.Element
+>elem : predom.JSX.Element
+> : JSX.Element
+>h : any
+>h : any
+
diff --git a/tests/baselines/reference/tsxElementResolution16.errors.txt b/tests/baselines/reference/tsxElementResolution16.errors.txt
index b68c442c36d..07b2ec54b44 100644
--- a/tests/baselines/reference/tsxElementResolution16.errors.txt
+++ b/tests/baselines/reference/tsxElementResolution16.errors.txt
@@ -1,8 +1,7 @@
-tests/cases/conformance/jsx/file.tsx(8,1): error TS2602: JSX element implicitly has type 'any' because the global type 'JSX.Element' does not exist.
tests/cases/conformance/jsx/file.tsx(8,1): error TS7026: JSX element implicitly has type 'any' because no interface 'JSX.IntrinsicElements' exists.
-==== tests/cases/conformance/jsx/file.tsx (2 errors) ====
+==== tests/cases/conformance/jsx/file.tsx (1 errors) ====
declare module JSX {
}
@@ -12,7 +11,5 @@ tests/cases/conformance/jsx/file.tsx(8,1): error TS7026: JSX element implicitly
var obj1: Obj1;
; // Error (JSX.Element is implicit any)
~~~~~~~~~~~~~~~
-!!! error TS2602: JSX element implicitly has type 'any' because the global type 'JSX.Element' does not exist.
- ~~~~~~~~~~~~~~~
!!! error TS7026: JSX element implicitly has type 'any' because no interface 'JSX.IntrinsicElements' exists.
\ No newline at end of file
diff --git a/tests/cases/conformance/jsx/inline/inlineJsxFactoryDeclarationsLocalTypes.tsx b/tests/cases/conformance/jsx/inline/inlineJsxFactoryDeclarationsLocalTypes.tsx
new file mode 100644
index 00000000000..009abe2e852
--- /dev/null
+++ b/tests/cases/conformance/jsx/inline/inlineJsxFactoryDeclarationsLocalTypes.tsx
@@ -0,0 +1,86 @@
+// @jsx: react
+// @filename: renderer.d.ts
+export namespace dom {
+ namespace JSX {
+ interface IntrinsicElements {
+ [e: string]: {};
+ }
+ interface Element {
+ __domBrand: void;
+ props: {
+ children?: Element[];
+ };
+ }
+ interface ElementClass extends Element {
+ render(): Element;
+ }
+ interface ElementAttributesProperty { props: any; }
+ interface ElementChildrenAttribute { children: any; }
+ }
+}
+export function dom(): dom.JSX.Element;
+// @filename: renderer2.d.ts
+export namespace predom {
+ namespace JSX {
+ interface IntrinsicElements {
+ [e: string]: {};
+ }
+ interface Element {
+ __predomBrand: void;
+ props: {
+ children?: Element[];
+ };
+ }
+ interface ElementClass extends Element {
+ render(): Element;
+ }
+ interface ElementAttributesProperty { props: any; }
+ interface ElementChildrenAttribute { children: any; }
+ }
+}
+export function predom(): predom.JSX.Element;
+// @filename: component.tsx
+/** @jsx predom */
+import { predom } from "./renderer2"
+
+export const MySFC = (props: {x: number, y: number, children?: predom.JSX.Element[]}) => {props.x} + {props.y} = {props.x + props.y}{...this.props.children}
;
+
+export class MyClass implements predom.JSX.Element {
+ __predomBrand!: void;
+ constructor(public props: {x: number, y: number, children?: predom.JSX.Element[]}) {}
+ render() {
+ return
+ {this.props.x} + {this.props.y} = {this.props.x + this.props.y}
+ {...this.props.children}
+
;
+ }
+}
+export const tree =
+
+export default
+
+// @filename: index.tsx
+/** @jsx dom */
+import { dom } from "./renderer"
+import prerendered, {MySFC, MyClass, tree} from "./component";
+let elem = prerendered;
+elem = ; // Expect assignability error here
+
+const DOMSFC = (props: {x: number, y: number, children?: dom.JSX.Element[]}) => {props.x} + {props.y} = {props.x + props.y}{props.children}
;
+
+class DOMClass implements dom.JSX.Element {
+ __domBrand!: void;
+ constructor(public props: {x: number, y: number, children?: dom.JSX.Element[]}) {}
+ render() {
+ return {this.props.x} + {this.props.y} = {this.props.x + this.props.y}{...this.props.children}
;
+ }
+}
+
+// Should work, everything is a DOM element
+const _tree =
+
+// Should fail, no dom elements
+const _brokenTree =
+
+// Should fail, nondom isn't allowed as children of dom
+const _brokenTree2 = {tree}{tree}
diff --git a/tests/cases/conformance/jsx/inline/inlineJsxFactoryLocalTypeGlobalFallback.tsx b/tests/cases/conformance/jsx/inline/inlineJsxFactoryLocalTypeGlobalFallback.tsx
new file mode 100644
index 00000000000..3f4340f518b
--- /dev/null
+++ b/tests/cases/conformance/jsx/inline/inlineJsxFactoryLocalTypeGlobalFallback.tsx
@@ -0,0 +1,44 @@
+// @jsx: react
+// @filename: renderer.d.ts
+declare global {
+ namespace JSX {
+ interface IntrinsicElements {
+ [e: string]: {};
+ }
+ interface Element {
+ __domBrand: void;
+ children: Element[];
+ props: {};
+ }
+ interface ElementAttributesProperty { props: any; }
+ interface ElementChildrenAttribute { children: any; }
+ }
+}
+export function dom(): JSX.Element;
+// @filename: renderer2.d.ts
+export namespace predom {
+ namespace JSX {
+ interface IntrinsicElements {
+ [e: string]: {};
+ }
+ interface Element {
+ __predomBrand: void;
+ children: Element[];
+ props: {};
+ }
+ interface ElementAttributesProperty { props: any; }
+ interface ElementChildrenAttribute { children: any; }
+ }
+}
+export function predom(): predom.JSX.Element;
+// @filename: component.tsx
+/** @jsx predom */
+import { predom } from "./renderer2"
+export default
+
+// @filename: index.tsx
+/** @jsx dom */
+import { dom } from "./renderer"
+import prerendered from "./component";
+let elem = prerendered;
+elem = ; // Expect assignability error here
From b8e0009c9b591d20697bfdb6ed7f2d3715b2bb73 Mon Sep 17 00:00:00 2001
From: Wesley Wigham
Date: Wed, 28 Feb 2018 16:03:05 -0800
Subject: [PATCH 18/22] Set syntheticLiteralTypeOrigin on synthetic
`undefined`-type members (#22216)
* Have getNameOfSymbolAsWritten quote nonidentifier nonnumeric symbols all the time
* Revert checker changes
* Reuse synthetic origin to indicate that derived declaration name may need to be quoted
---
src/compiler/checker.ts | 4 ++++
.../inferredNonidentifierTypesGetQuotes.js | 22 +++++++++++++++++++
...nferredNonidentifierTypesGetQuotes.symbols | 10 +++++++++
.../inferredNonidentifierTypesGetQuotes.types | 18 +++++++++++++++
.../inferredNonidentifierTypesGetQuotes.ts | 4 ++++
5 files changed, 58 insertions(+)
create mode 100644 tests/baselines/reference/inferredNonidentifierTypesGetQuotes.js
create mode 100644 tests/baselines/reference/inferredNonidentifierTypesGetQuotes.symbols
create mode 100644 tests/baselines/reference/inferredNonidentifierTypesGetQuotes.types
create mode 100644 tests/cases/compiler/inferredNonidentifierTypesGetQuotes.ts
diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts
index e7ff00df556..f98031cf44d 100644
--- a/src/compiler/checker.ts
+++ b/src/compiler/checker.ts
@@ -11150,6 +11150,10 @@ namespace ts {
}
const result = createSymbol(SymbolFlags.Property | SymbolFlags.Optional, name);
result.type = undefinedType;
+ const associatedKeyType = getLiteralType(unescapeLeadingUnderscores(name));
+ if (associatedKeyType.flags & TypeFlags.StringLiteral) {
+ result.syntheticLiteralTypeOrigin = associatedKeyType as StringLiteralType;
+ }
undefinedProperties.set(name, result);
return result;
}
diff --git a/tests/baselines/reference/inferredNonidentifierTypesGetQuotes.js b/tests/baselines/reference/inferredNonidentifierTypesGetQuotes.js
new file mode 100644
index 00000000000..e9ce8e56d1f
--- /dev/null
+++ b/tests/baselines/reference/inferredNonidentifierTypesGetQuotes.js
@@ -0,0 +1,22 @@
+//// [inferredNonidentifierTypesGetQuotes.ts]
+var x = [{ "a-b": "string" }, {}];
+
+var y = [{ ["a-b"]: "string" }, {}];
+
+//// [inferredNonidentifierTypesGetQuotes.js]
+var x = [{ "a-b": "string" }, {}];
+var y = [(_a = {}, _a["a-b"] = "string", _a), {}];
+var _a;
+
+
+//// [inferredNonidentifierTypesGetQuotes.d.ts]
+declare var x: ({
+ "a-b": string;
+} | {
+ "a-b"?: undefined;
+})[];
+declare var y: ({
+ ["a-b"]: string;
+} | {
+ "a-b"?: undefined;
+})[];
diff --git a/tests/baselines/reference/inferredNonidentifierTypesGetQuotes.symbols b/tests/baselines/reference/inferredNonidentifierTypesGetQuotes.symbols
new file mode 100644
index 00000000000..f37063dcee5
--- /dev/null
+++ b/tests/baselines/reference/inferredNonidentifierTypesGetQuotes.symbols
@@ -0,0 +1,10 @@
+=== tests/cases/compiler/inferredNonidentifierTypesGetQuotes.ts ===
+var x = [{ "a-b": "string" }, {}];
+>x : Symbol(x, Decl(inferredNonidentifierTypesGetQuotes.ts, 0, 3))
+>"a-b" : Symbol("a-b", Decl(inferredNonidentifierTypesGetQuotes.ts, 0, 10))
+
+var y = [{ ["a-b"]: "string" }, {}];
+>y : Symbol(y, Decl(inferredNonidentifierTypesGetQuotes.ts, 2, 3))
+>["a-b"] : Symbol(["a-b"], Decl(inferredNonidentifierTypesGetQuotes.ts, 2, 10))
+>"a-b" : Symbol(["a-b"], Decl(inferredNonidentifierTypesGetQuotes.ts, 2, 10))
+
diff --git a/tests/baselines/reference/inferredNonidentifierTypesGetQuotes.types b/tests/baselines/reference/inferredNonidentifierTypesGetQuotes.types
new file mode 100644
index 00000000000..361b550952a
--- /dev/null
+++ b/tests/baselines/reference/inferredNonidentifierTypesGetQuotes.types
@@ -0,0 +1,18 @@
+=== tests/cases/compiler/inferredNonidentifierTypesGetQuotes.ts ===
+var x = [{ "a-b": "string" }, {}];
+>x : ({ "a-b": string; } | { "a-b"?: undefined; })[]
+>[{ "a-b": "string" }, {}] : ({ "a-b": string; } | {})[]
+>{ "a-b": "string" } : { "a-b": string; }
+>"a-b" : string
+>"string" : "string"
+>{} : {}
+
+var y = [{ ["a-b"]: "string" }, {}];
+>y : ({ ["a-b"]: string; } | { "a-b"?: undefined; })[]
+>[{ ["a-b"]: "string" }, {}] : ({ ["a-b"]: string; } | {})[]
+>{ ["a-b"]: "string" } : { ["a-b"]: string; }
+>["a-b"] : string
+>"a-b" : "a-b"
+>"string" : "string"
+>{} : {}
+
diff --git a/tests/cases/compiler/inferredNonidentifierTypesGetQuotes.ts b/tests/cases/compiler/inferredNonidentifierTypesGetQuotes.ts
new file mode 100644
index 00000000000..70e3296bef6
--- /dev/null
+++ b/tests/cases/compiler/inferredNonidentifierTypesGetQuotes.ts
@@ -0,0 +1,4 @@
+// @declaration: true
+var x = [{ "a-b": "string" }, {}];
+
+var y = [{ ["a-b"]: "string" }, {}];
\ No newline at end of file
From ec249f7f674d1663a5d031376d75efface967885 Mon Sep 17 00:00:00 2001
From: Wesley Wigham
Date: Wed, 28 Feb 2018 16:56:54 -0800
Subject: [PATCH 19/22] Fix typo in inference (#22243)
---
src/compiler/checker.ts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts
index f98031cf44d..ffbd83456aa 100644
--- a/src/compiler/checker.ts
+++ b/src/compiler/checker.ts
@@ -11634,7 +11634,7 @@ namespace ts {
}
}
else {
- if (!(priority && InferencePriority.NoConstraints && source.flags & (TypeFlags.Intersection | TypeFlags.Instantiable))) {
+ if (!(priority & InferencePriority.NoConstraints && source.flags & (TypeFlags.Intersection | TypeFlags.Instantiable))) {
source = getApparentType(source);
}
if (source.flags & (TypeFlags.Object | TypeFlags.Intersection)) {
From c12fc0d6c3faa413b9feb2f3e9751e5614d8e5fe Mon Sep 17 00:00:00 2001
From: Wesley Wigham
Date: Wed, 28 Feb 2018 17:55:56 -0800
Subject: [PATCH 20/22] Format unique symmbol string output with `unique
symbol` and not `typeof` within checker (#22247)
* Accept baseline update to symbol test
* Set default node flag instead of accepting new error
---
src/compiler/checker.ts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts
index ffbd83456aa..9579ba80d0f 100644
--- a/src/compiler/checker.ts
+++ b/src/compiler/checker.ts
@@ -2756,7 +2756,7 @@ namespace ts {
}
}
- function typeToString(type: Type, enclosingDeclaration?: Node, flags?: TypeFormatFlags, writer: EmitTextWriter = createTextWriter("")): string {
+ function typeToString(type: Type, enclosingDeclaration?: Node, flags: TypeFormatFlags = TypeFormatFlags.AllowUniqueESSymbolType, writer: EmitTextWriter = createTextWriter("")): string {
const typeNode = nodeBuilder.typeToTypeNode(type, enclosingDeclaration, toNodeBuilderFlags(flags) | NodeBuilderFlags.IgnoreErrors, writer);
Debug.assert(typeNode !== undefined, "should always get typenode");
const options = { removeComments: true };
From 75c6c8c78802a5bfd5f52deebc28b722861d4993 Mon Sep 17 00:00:00 2001
From: csigs
Date: Thu, 1 Mar 2018 05:10:18 +0000
Subject: [PATCH 21/22] LEGO: check in for master to temporary branch.
---
.../diagnosticMessages.generated.json.lcl | 27 +++++++++++++++++++
.../diagnosticMessages.generated.json.lcl | 27 +++++++++++++++++++
2 files changed, 54 insertions(+)
diff --git a/src/loc/lcl/csy/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/csy/diagnosticMessages/diagnosticMessages.generated.json.lcl
index 332e2933d2a..d732d0101c3 100644
--- a/src/loc/lcl/csy/diagnosticMessages/diagnosticMessages.generated.json.lcl
+++ b/src/loc/lcl/csy/diagnosticMessages/diagnosticMessages.generated.json.lcl
@@ -912,6 +912,15 @@
+ -
+
+
+
+
+
+
+
+
-
@@ -924,6 +933,15 @@
+ -
+
+
+
+
+
+
+
+
-
@@ -948,6 +966,15 @@
+ -
+
+
+
+
+
+
+
+
-
diff --git a/src/loc/lcl/ita/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/ita/diagnosticMessages/diagnosticMessages.generated.json.lcl
index 9c0ffaf818e..6ab6de8613c 100644
--- a/src/loc/lcl/ita/diagnosticMessages/diagnosticMessages.generated.json.lcl
+++ b/src/loc/lcl/ita/diagnosticMessages/diagnosticMessages.generated.json.lcl
@@ -903,6 +903,15 @@
+ -
+
+
+
+
+
+
+
+
-
@@ -915,6 +924,15 @@
+ -
+
+
+
+
+
+
+
+
-
@@ -939,6 +957,15 @@
+ -
+
+
+
+
+
+
+
+
-
From 3df0b4cd61c1bf244e12ff90bb04326e5129cd85 Mon Sep 17 00:00:00 2001
From: csigs
Date: Thu, 1 Mar 2018 11:10:18 +0000
Subject: [PATCH 22/22] LEGO: check in for master to temporary branch.
---
.../diagnosticMessages.generated.json.lcl | 27 +++++++++++++++++++
1 file changed, 27 insertions(+)
diff --git a/src/loc/lcl/rus/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/rus/diagnosticMessages/diagnosticMessages.generated.json.lcl
index 15c5e26b54f..b8891b5a90b 100644
--- a/src/loc/lcl/rus/diagnosticMessages/diagnosticMessages.generated.json.lcl
+++ b/src/loc/lcl/rus/diagnosticMessages/diagnosticMessages.generated.json.lcl
@@ -902,6 +902,15 @@
+ -
+
+
+
+
+
+
+
+
-
@@ -914,6 +923,15 @@
+ -
+
+
+
+
+
+
+
+
-
@@ -938,6 +956,15 @@
+ -
+
+
+
+
+
+
+
+
-