diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts
index 07996e0bcdd41..9e61193a1f962 100644
--- a/src/compiler/checker.ts
+++ b/src/compiler/checker.ts
@@ -1091,6 +1091,16 @@ namespace ts {
}
}
function errorOrSuggestion(isError: boolean, location: Node, message: DiagnosticMessage | DiagnosticMessageChain, arg0?: string | number, arg1?: string | number, arg2?: string | number, arg3?: string | number): void {
+ // Pseudo-synthesized input node
+ if (location.pos < 0 || location.end < 0) {
+ if (!isError) {
+ return; // Drop suggestions (we have no span to suggest on)
+ }
+ // Issue errors globally
+ const file = getSourceFileOfNode(location);
+ addErrorOrSuggestion(isError, "message" in message ? createFileDiagnostic(file, 0, 0, message, arg0, arg1, arg2, arg3) : createDiagnosticForFileFromMessageChain(file, message)); // eslint-disable-line no-in-operator
+ return;
+ }
addErrorOrSuggestion(isError, "message" in message ? createDiagnosticForNode(location, message, arg0, arg1, arg2, arg3) : createDiagnosticForNodeFromMessageChain(location, message)); // eslint-disable-line no-in-operator
}
diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts
index 2dc1fb0475d34..295671b70449b 100644
--- a/src/compiler/utilities.ts
+++ b/src/compiler/utilities.ts
@@ -989,6 +989,18 @@ namespace ts {
};
}
+ export function createDiagnosticForFileFromMessageChain(sourceFile: SourceFile, messageChain: DiagnosticMessageChain, relatedInformation?: DiagnosticRelatedInformation[]): DiagnosticWithLocation {
+ return {
+ file: sourceFile,
+ start: 0,
+ length: 0,
+ code: messageChain.code,
+ category: messageChain.category,
+ messageText: messageChain.next ? messageChain : messageChain.messageText,
+ relatedInformation
+ };
+ }
+
export function createDiagnosticForRange(sourceFile: SourceFile, range: TextRange, message: DiagnosticMessage): DiagnosticWithLocation {
return {
file: sourceFile,
diff --git a/src/testRunner/unittests/tsc/incremental.ts b/src/testRunner/unittests/tsc/incremental.ts
index fd42ccddf1843..36ea38edd0155 100644
--- a/src/testRunner/unittests/tsc/incremental.ts
+++ b/src/testRunner/unittests/tsc/incremental.ts
@@ -235,5 +235,42 @@ const a: string = 10;`, "utf-8"),
}
}
});
+
+ const jsxLibraryContent = `
+export {};
+declare global {
+ namespace JSX {
+ interface Element {}
+ interface IntrinsicElements {
+ div: {
+ propA?: boolean;
+ };
+ }
+ }
+}`;
+
+ verifyTsc({
+ scenario: "react-jsx-emit-mode",
+ subScenario: "with no backing types found doesn't crash",
+ fs: () => loadProjectFromFiles({
+ "/src/project/node_modules/react/jsx-runtime.js": "export {}", // js needs to be present so there's a resolution result
+ "/src/project/node_modules/@types/react/index.d.ts": jsxLibraryContent, // doesn't contain a jsx-runtime definition
+ "/src/project/src/index.tsx": `export const App = () =>
;`,
+ "/src/project/tsconfig.json": JSON.stringify({ compilerOptions: { module: "commonjs", jsx: "react-jsx", incremental: true, jsxImportSource: "react" } })
+ }),
+ commandLineArgs: ["--p", "src/project"]
+ });
+
+ verifyTsc({
+ scenario: "react-jsx-emit-mode",
+ subScenario: "with no backing types found doesn't crash under --strict",
+ fs: () => loadProjectFromFiles({
+ "/src/project/node_modules/react/jsx-runtime.js": "export {}", // js needs to be present so there's a resolution result
+ "/src/project/node_modules/@types/react/index.d.ts": jsxLibraryContent, // doesn't contain a jsx-runtime definition
+ "/src/project/src/index.tsx": `export const App = () => ;`,
+ "/src/project/tsconfig.json": JSON.stringify({ compilerOptions: { module: "commonjs", jsx: "react-jsx", incremental: true, jsxImportSource: "react" } })
+ }),
+ commandLineArgs: ["--p", "src/project", "--strict"]
+ });
});
}
diff --git a/tests/baselines/reference/tsc/react-jsx-emit-mode/initial-build/with-no-backing-types-found-doesn't-crash-under---strict.js b/tests/baselines/reference/tsc/react-jsx-emit-mode/initial-build/with-no-backing-types-found-doesn't-crash-under---strict.js
new file mode 100644
index 0000000000000..b0b8497aaf4eb
--- /dev/null
+++ b/tests/baselines/reference/tsc/react-jsx-emit-mode/initial-build/with-no-backing-types-found-doesn't-crash-under---strict.js
@@ -0,0 +1,115 @@
+Input::
+//// [/lib/lib.d.ts]
+///
+interface Boolean {}
+interface Function {}
+interface CallableFunction {}
+interface NewableFunction {}
+interface IArguments {}
+interface Number { toExponential: any; }
+interface Object {}
+interface RegExp {}
+interface String { charAt: any; }
+interface Array { length: number; [n: number]: T; }
+interface ReadonlyArray {}
+declare const console: { log(msg: any): void; };
+
+//// [/src/project/node_modules/@types/react/index.d.ts]
+
+export {};
+declare global {
+ namespace JSX {
+ interface Element {}
+ interface IntrinsicElements {
+ div: {
+ propA?: boolean;
+ };
+ }
+ }
+}
+
+//// [/src/project/node_modules/react/jsx-runtime.js]
+
+
+//// [/src/project/src/index.tsx]
+export const App = () => ;
+
+//// [/src/project/tsconfig.json]
+{"compilerOptions":{"module":"commonjs","jsx":"react-jsx","incremental":true,"jsxImportSource":"react"}}
+
+
+
+Output::
+/lib/tsc --p src/project --strict
+[96msrc/project/src/index.tsx[0m:[93m1[0m:[93m26[0m - [91merror[0m[90m TS7016: [0mCould not find a declaration file for module 'react/jsx-runtime'. '/src/project/node_modules/react/jsx-runtime.js' implicitly has an 'any' type.
+
+[7m1[0m export const App = () => ;
+[7m [0m [91m ~~~~~~~~~~~~~~~~~~~~~~~~[0m
+
+
+Found 1 error.
+
+exitCode:: ExitStatus.DiagnosticsPresent_OutputsGenerated
+
+
+//// [/src/project/src/index.js]
+"use strict";
+exports.__esModule = true;
+exports.App = void 0;
+var jsx_runtime_1 = require("react/jsx-runtime");
+var App = function () { return jsx_runtime_1.jsx("div", { propA: true }, void 0); };
+exports.App = App;
+
+
+//// [/src/project/tsconfig.tsbuildinfo]
+{
+ "program": {
+ "fileInfos": {
+ "../../lib/lib.d.ts": {
+ "version": "3858781397-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ndeclare const console: { log(msg: any): void; };",
+ "signature": "3858781397-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ndeclare const console: { log(msg: any): void; };",
+ "affectsGlobalScope": true
+ },
+ "./src/index.tsx": {
+ "version": "-14760199789-export const App = () => ;",
+ "signature": "-8716173275-/// \r\nexport declare const App: () => JSX.Element;\r\n",
+ "affectsGlobalScope": false
+ },
+ "./node_modules/@types/react/index.d.ts": {
+ "version": "-16587767667-\nexport {};\ndeclare global {\n namespace JSX {\n interface Element {}\n interface IntrinsicElements {\n div: {\n propA?: boolean;\n };\n }\n }\n}",
+ "signature": "-16587767667-\nexport {};\ndeclare global {\n namespace JSX {\n interface Element {}\n interface IntrinsicElements {\n div: {\n propA?: boolean;\n };\n }\n }\n}",
+ "affectsGlobalScope": true
+ }
+ },
+ "options": {
+ "module": 1,
+ "jsx": 4,
+ "incremental": true,
+ "jsxImportSource": "react",
+ "project": "./",
+ "strict": true,
+ "configFilePath": "./tsconfig.json"
+ },
+ "referencedMap": {},
+ "exportedModulesMap": {},
+ "semanticDiagnosticsPerFile": [
+ "../../lib/lib.d.ts",
+ "./node_modules/@types/react/index.d.ts",
+ [
+ "./src/index.tsx",
+ [
+ {
+ "file": "./src/index.tsx",
+ "start": 25,
+ "length": 24,
+ "code": 7016,
+ "category": 1,
+ "messageText": "Could not find a declaration file for module 'react/jsx-runtime'. '/src/project/node_modules/react/jsx-runtime.js' implicitly has an 'any' type."
+ }
+ ]
+ ]
+ ]
+ },
+ "version": "FakeTSVersion"
+}
+
diff --git a/tests/baselines/reference/tsc/react-jsx-emit-mode/initial-build/with-no-backing-types-found-doesn't-crash.js b/tests/baselines/reference/tsc/react-jsx-emit-mode/initial-build/with-no-backing-types-found-doesn't-crash.js
new file mode 100644
index 0000000000000..da35f20174d3c
--- /dev/null
+++ b/tests/baselines/reference/tsc/react-jsx-emit-mode/initial-build/with-no-backing-types-found-doesn't-crash.js
@@ -0,0 +1,94 @@
+Input::
+//// [/lib/lib.d.ts]
+///
+interface Boolean {}
+interface Function {}
+interface CallableFunction {}
+interface NewableFunction {}
+interface IArguments {}
+interface Number { toExponential: any; }
+interface Object {}
+interface RegExp {}
+interface String { charAt: any; }
+interface Array { length: number; [n: number]: T; }
+interface ReadonlyArray {}
+declare const console: { log(msg: any): void; };
+
+//// [/src/project/node_modules/@types/react/index.d.ts]
+
+export {};
+declare global {
+ namespace JSX {
+ interface Element {}
+ interface IntrinsicElements {
+ div: {
+ propA?: boolean;
+ };
+ }
+ }
+}
+
+//// [/src/project/node_modules/react/jsx-runtime.js]
+
+
+//// [/src/project/src/index.tsx]
+export const App = () => ;
+
+//// [/src/project/tsconfig.json]
+{"compilerOptions":{"module":"commonjs","jsx":"react-jsx","incremental":true,"jsxImportSource":"react"}}
+
+
+
+Output::
+/lib/tsc --p src/project
+exitCode:: ExitStatus.Success
+
+
+//// [/src/project/src/index.js]
+"use strict";
+exports.__esModule = true;
+exports.App = void 0;
+var jsx_runtime_1 = require("react/jsx-runtime");
+var App = function () { return jsx_runtime_1.jsx("div", { propA: true }, void 0); };
+exports.App = App;
+
+
+//// [/src/project/tsconfig.tsbuildinfo]
+{
+ "program": {
+ "fileInfos": {
+ "../../lib/lib.d.ts": {
+ "version": "3858781397-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ndeclare const console: { log(msg: any): void; };",
+ "signature": "3858781397-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ndeclare const console: { log(msg: any): void; };",
+ "affectsGlobalScope": true
+ },
+ "./src/index.tsx": {
+ "version": "-14760199789-export const App = () => ;",
+ "signature": "-8716173275-/// \r\nexport declare const App: () => JSX.Element;\r\n",
+ "affectsGlobalScope": false
+ },
+ "./node_modules/@types/react/index.d.ts": {
+ "version": "-16587767667-\nexport {};\ndeclare global {\n namespace JSX {\n interface Element {}\n interface IntrinsicElements {\n div: {\n propA?: boolean;\n };\n }\n }\n}",
+ "signature": "-16587767667-\nexport {};\ndeclare global {\n namespace JSX {\n interface Element {}\n interface IntrinsicElements {\n div: {\n propA?: boolean;\n };\n }\n }\n}",
+ "affectsGlobalScope": true
+ }
+ },
+ "options": {
+ "module": 1,
+ "jsx": 4,
+ "incremental": true,
+ "jsxImportSource": "react",
+ "project": "./",
+ "configFilePath": "./tsconfig.json"
+ },
+ "referencedMap": {},
+ "exportedModulesMap": {},
+ "semanticDiagnosticsPerFile": [
+ "../../lib/lib.d.ts",
+ "./node_modules/@types/react/index.d.ts",
+ "./src/index.tsx"
+ ]
+ },
+ "version": "FakeTSVersion"
+}
+