diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index b1cd63ee5b371..d93b37ce1add0 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -2040,8 +2040,22 @@ namespace ts { } function onSingleFileEmit(host: EmitHost, sourceFile: SourceFile) { - const jsFilePath = getOwnEmitOutputFilePath(sourceFile, host, - sourceFile.languageVariant === LanguageVariant.JSX && options.jsx === JsxEmit.Preserve ? ".jsx" : ".js"); + // JavaScript files are always LanguageVariant.JSX, as JSX syntax is allowed in .js files also. + // So for JavaScript files, '.jsx' is only emitted if the input was '.jsx', and JsxEmit.Preserve. + // For TypeScript, the only time to emit with a '.jsx' extension, is on JSX input, and JsxEmit.Preserve + let extension = ".js"; + if (options.jsx === JsxEmit.Preserve) { + if (isSourceFileJavaScript(sourceFile)) { + if (fileExtensionIs(sourceFile.fileName, ".jsx")) { + extension = ".jsx"; + } + } + else if (sourceFile.languageVariant === LanguageVariant.JSX) { + // TypeScript source file preserving JSX syntax + extension = ".jsx"; + } + } + const jsFilePath = getOwnEmitOutputFilePath(sourceFile, host, extension); const emitFileNames: EmitFileNames = { jsFilePath, sourceMapFilePath: getSourceMapFilePath(jsFilePath, options), diff --git a/tests/baselines/reference/jsxPreserveWithJsInput.js b/tests/baselines/reference/jsxPreserveWithJsInput.js new file mode 100644 index 0000000000000..2cc59ffa355df --- /dev/null +++ b/tests/baselines/reference/jsxPreserveWithJsInput.js @@ -0,0 +1,29 @@ +//// [tests/cases/compiler/jsxPreserveWithJsInput.ts] //// + +//// [a.js] + +var elemA = 42; + +//// [b.jsx] +var elemB = {"test"}; + +//// [c.js] +var elemC = {42}; + +//// [d.ts] +var elemD = 42; + +//// [e.tsx] +var elemE = {true}; + + +//// [a.js] +var elemA = 42; +//// [b.jsx] +var elemB = {"test"}; +//// [c.js] +var elemC = {42}; +//// [d.js] +var elemD = 42; +//// [e.jsx] +var elemE = {true}; diff --git a/tests/baselines/reference/jsxPreserveWithJsInput.symbols b/tests/baselines/reference/jsxPreserveWithJsInput.symbols new file mode 100644 index 0000000000000..6ad2f6148757f --- /dev/null +++ b/tests/baselines/reference/jsxPreserveWithJsInput.symbols @@ -0,0 +1,27 @@ +=== tests/cases/compiler/a.js === + +var elemA = 42; +>elemA : Symbol(elemA, Decl(a.js, 1, 3)) + +=== tests/cases/compiler/b.jsx === +var elemB = {"test"}; +>elemB : Symbol(elemB, Decl(b.jsx, 0, 3)) +>b : Symbol(unknown) +>b : Symbol(unknown) + +=== tests/cases/compiler/c.js === +var elemC = {42}; +>elemC : Symbol(elemC, Decl(c.js, 0, 3)) +>c : Symbol(unknown) +>c : Symbol(unknown) + +=== tests/cases/compiler/d.ts === +var elemD = 42; +>elemD : Symbol(elemD, Decl(d.ts, 0, 3)) + +=== tests/cases/compiler/e.tsx === +var elemE = {true}; +>elemE : Symbol(elemE, Decl(e.tsx, 0, 3)) +>e : Symbol(unknown) +>e : Symbol(unknown) + diff --git a/tests/baselines/reference/jsxPreserveWithJsInput.types b/tests/baselines/reference/jsxPreserveWithJsInput.types new file mode 100644 index 0000000000000..7f4ed6daa2b98 --- /dev/null +++ b/tests/baselines/reference/jsxPreserveWithJsInput.types @@ -0,0 +1,35 @@ +=== tests/cases/compiler/a.js === + +var elemA = 42; +>elemA : number +>42 : number + +=== tests/cases/compiler/b.jsx === +var elemB = {"test"}; +>elemB : any +>{"test"} : any +>b : any +>"test" : string +>b : any + +=== tests/cases/compiler/c.js === +var elemC = {42}; +>elemC : any +>{42} : any +>c : any +>42 : number +>c : any + +=== tests/cases/compiler/d.ts === +var elemD = 42; +>elemD : number +>42 : number + +=== tests/cases/compiler/e.tsx === +var elemE = {true}; +>elemE : any +>{true} : any +>e : any +>true : boolean +>e : any + diff --git a/tests/cases/compiler/jsxPreserveWithJsInput.ts b/tests/cases/compiler/jsxPreserveWithJsInput.ts new file mode 100644 index 0000000000000..f229e40a55012 --- /dev/null +++ b/tests/cases/compiler/jsxPreserveWithJsInput.ts @@ -0,0 +1,18 @@ +// @outdir: out +// @jsx: preserve +// @allowjs: true + +// @filename: a.js +var elemA = 42; + +// @filename: b.jsx +var elemB = {"test"}; + +// @filename: c.js +var elemC = {42}; + +// @filename: d.ts +var elemD = 42; + +// @filename: e.tsx +var elemE = {true};