Skip to content

Commit

Permalink
Add support for the @jsxruntime pragma (#59500)
Browse files Browse the repository at this point in the history
  • Loading branch information
weswigham authored Aug 1, 2024
1 parent 41b993b commit 8daac14
Show file tree
Hide file tree
Showing 11 changed files with 1,155 additions and 1 deletion.
8 changes: 7 additions & 1 deletion src/compiler/utilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9164,10 +9164,16 @@ export function getJSXTransformEnabled(options: CompilerOptions): boolean {
export function getJSXImplicitImportBase(compilerOptions: CompilerOptions, file?: SourceFile): string | undefined {
const jsxImportSourcePragmas = file?.pragmas.get("jsximportsource");
const jsxImportSourcePragma = isArray(jsxImportSourcePragmas) ? jsxImportSourcePragmas[jsxImportSourcePragmas.length - 1] : jsxImportSourcePragmas;
const jsxRuntimePragmas = file?.pragmas.get("jsxruntime");
const jsxRuntimePragma = isArray(jsxRuntimePragmas) ? jsxRuntimePragmas[jsxRuntimePragmas.length - 1] : jsxRuntimePragmas;
if (jsxRuntimePragma?.arguments.factory === "classic") {
return undefined;
}
return compilerOptions.jsx === JsxEmit.ReactJSX ||
compilerOptions.jsx === JsxEmit.ReactJSXDev ||
compilerOptions.jsxImportSource ||
jsxImportSourcePragma ?
jsxImportSourcePragma ||
jsxRuntimePragma?.arguments.factory === "automatic" ?
jsxImportSourcePragma?.arguments.factory || compilerOptions.jsxImportSource || "react" :
undefined;
}
Expand Down
92 changes: 92 additions & 0 deletions tests/baselines/reference/jsxRuntimePragma(jsx=react).js
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
//// [tests/cases/compiler/jsxRuntimePragma.ts] ////

//// [one.tsx]
/// <reference path="/.lib/react16.d.ts" />
/* @jsxRuntime classic */
import * as React from "react";
export const HelloWorld = () => <h1>Hello world</h1>;
export const frag = <><div></div></>;
export const selfClosing = <img src="./image.png" />;
//// [two.tsx]
/// <reference path="/.lib/react16.d.ts" />
/* @jsxRuntime automatic */
export const HelloWorld = () => <h1>Hello world</h1>;
export const frag = <><div></div></>;
export const selfClosing = <img src="./image.png" />;
//// [three.tsx]
/// <reference path="/.lib/react16.d.ts" />
/* @jsxRuntime classic */
/* @jsxRuntime automatic */
export const HelloWorld = () => <h1>Hello world</h1>;
export const frag = <><div></div></>;
export const selfClosing = <img src="./image.png" />;
//// [four.tsx]
/// <reference path="/.lib/react16.d.ts" />
/* @jsxRuntime automatic */
/* @jsxRuntime classic */
import * as React from "react";
export const HelloWorld = () => <h1>Hello world</h1>;
export const frag = <><div></div></>;
export const selfClosing = <img src="./image.png" />;
//// [index.ts]
export * as one from "./one.js";
export * as two from "./two.js";
export * as three from "./three.js";
export * as four from "./four.js";

//// [one.js]
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.selfClosing = exports.frag = exports.HelloWorld = void 0;
/// <reference path="react16.d.ts" />
/* @jsxRuntime classic */
var React = require("react");
var HelloWorld = function () { return React.createElement("h1", null, "Hello world"); };
exports.HelloWorld = HelloWorld;
exports.frag = React.createElement(React.Fragment, null,
React.createElement("div", null));
exports.selfClosing = React.createElement("img", { src: "./image.png" });
//// [two.js]
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.selfClosing = exports.frag = exports.HelloWorld = void 0;
var jsx_runtime_1 = require("react/jsx-runtime");
/// <reference path="react16.d.ts" />
/* @jsxRuntime automatic */
var HelloWorld = function () { return (0, jsx_runtime_1.jsx)("h1", { children: "Hello world" }); };
exports.HelloWorld = HelloWorld;
exports.frag = (0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: (0, jsx_runtime_1.jsx)("div", {}) });
exports.selfClosing = (0, jsx_runtime_1.jsx)("img", { src: "./image.png" });
//// [three.js]
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.selfClosing = exports.frag = exports.HelloWorld = void 0;
var jsx_runtime_1 = require("react/jsx-runtime");
/// <reference path="react16.d.ts" />
/* @jsxRuntime classic */
/* @jsxRuntime automatic */
var HelloWorld = function () { return (0, jsx_runtime_1.jsx)("h1", { children: "Hello world" }); };
exports.HelloWorld = HelloWorld;
exports.frag = (0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: (0, jsx_runtime_1.jsx)("div", {}) });
exports.selfClosing = (0, jsx_runtime_1.jsx)("img", { src: "./image.png" });
//// [four.js]
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.selfClosing = exports.frag = exports.HelloWorld = void 0;
/// <reference path="react16.d.ts" />
/* @jsxRuntime automatic */
/* @jsxRuntime classic */
var React = require("react");
var HelloWorld = function () { return React.createElement("h1", null, "Hello world"); };
exports.HelloWorld = HelloWorld;
exports.frag = React.createElement(React.Fragment, null,
React.createElement("div", null));
exports.selfClosing = React.createElement("img", { src: "./image.png" });
//// [index.js]
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.four = exports.three = exports.two = exports.one = void 0;
exports.one = require("./one.js");
exports.two = require("./two.js");
exports.three = require("./three.js");
exports.four = require("./four.js");
95 changes: 95 additions & 0 deletions tests/baselines/reference/jsxRuntimePragma(jsx=react).symbols
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
//// [tests/cases/compiler/jsxRuntimePragma.ts] ////

=== one.tsx ===
/// <reference path="react16.d.ts" />
/* @jsxRuntime classic */
import * as React from "react";
>React : Symbol(React, Decl(one.tsx, 2, 6))

export const HelloWorld = () => <h1>Hello world</h1>;
>HelloWorld : Symbol(HelloWorld, Decl(one.tsx, 3, 12))
>h1 : Symbol(JSX.IntrinsicElements.h1, Decl(react16.d.ts, 2556, 106))
>h1 : Symbol(JSX.IntrinsicElements.h1, Decl(react16.d.ts, 2556, 106))

export const frag = <><div></div></>;
>frag : Symbol(frag, Decl(one.tsx, 4, 12))
>div : Symbol(JSX.IntrinsicElements.div, Decl(react16.d.ts, 2546, 114))
>div : Symbol(JSX.IntrinsicElements.div, Decl(react16.d.ts, 2546, 114))

export const selfClosing = <img src="./image.png" />;
>selfClosing : Symbol(selfClosing, Decl(one.tsx, 5, 12))
>img : Symbol(JSX.IntrinsicElements.img, Decl(react16.d.ts, 2569, 114))
>src : Symbol(src, Decl(one.tsx, 5, 31))

=== two.tsx ===
/// <reference path="react16.d.ts" />
/* @jsxRuntime automatic */
export const HelloWorld = () => <h1>Hello world</h1>;
>HelloWorld : Symbol(HelloWorld, Decl(two.tsx, 2, 12))
>h1 : Symbol(JSX.IntrinsicElements.h1, Decl(react16.d.ts, 2556, 106))
>h1 : Symbol(JSX.IntrinsicElements.h1, Decl(react16.d.ts, 2556, 106))

export const frag = <><div></div></>;
>frag : Symbol(frag, Decl(two.tsx, 3, 12))
>div : Symbol(JSX.IntrinsicElements.div, Decl(react16.d.ts, 2546, 114))
>div : Symbol(JSX.IntrinsicElements.div, Decl(react16.d.ts, 2546, 114))

export const selfClosing = <img src="./image.png" />;
>selfClosing : Symbol(selfClosing, Decl(two.tsx, 4, 12))
>img : Symbol(JSX.IntrinsicElements.img, Decl(react16.d.ts, 2569, 114))
>src : Symbol(src, Decl(two.tsx, 4, 31))

=== three.tsx ===
/// <reference path="react16.d.ts" />
/* @jsxRuntime classic */
/* @jsxRuntime automatic */
export const HelloWorld = () => <h1>Hello world</h1>;
>HelloWorld : Symbol(HelloWorld, Decl(three.tsx, 3, 12))
>h1 : Symbol(JSX.IntrinsicElements.h1, Decl(react16.d.ts, 2556, 106))
>h1 : Symbol(JSX.IntrinsicElements.h1, Decl(react16.d.ts, 2556, 106))

export const frag = <><div></div></>;
>frag : Symbol(frag, Decl(three.tsx, 4, 12))
>div : Symbol(JSX.IntrinsicElements.div, Decl(react16.d.ts, 2546, 114))
>div : Symbol(JSX.IntrinsicElements.div, Decl(react16.d.ts, 2546, 114))

export const selfClosing = <img src="./image.png" />;
>selfClosing : Symbol(selfClosing, Decl(three.tsx, 5, 12))
>img : Symbol(JSX.IntrinsicElements.img, Decl(react16.d.ts, 2569, 114))
>src : Symbol(src, Decl(three.tsx, 5, 31))

=== four.tsx ===
/// <reference path="react16.d.ts" />
/* @jsxRuntime automatic */
/* @jsxRuntime classic */
import * as React from "react";
>React : Symbol(React, Decl(four.tsx, 3, 6))

export const HelloWorld = () => <h1>Hello world</h1>;
>HelloWorld : Symbol(HelloWorld, Decl(four.tsx, 4, 12))
>h1 : Symbol(JSX.IntrinsicElements.h1, Decl(react16.d.ts, 2556, 106))
>h1 : Symbol(JSX.IntrinsicElements.h1, Decl(react16.d.ts, 2556, 106))

export const frag = <><div></div></>;
>frag : Symbol(frag, Decl(four.tsx, 5, 12))
>div : Symbol(JSX.IntrinsicElements.div, Decl(react16.d.ts, 2546, 114))
>div : Symbol(JSX.IntrinsicElements.div, Decl(react16.d.ts, 2546, 114))

export const selfClosing = <img src="./image.png" />;
>selfClosing : Symbol(selfClosing, Decl(four.tsx, 6, 12))
>img : Symbol(JSX.IntrinsicElements.img, Decl(react16.d.ts, 2569, 114))
>src : Symbol(src, Decl(four.tsx, 6, 31))

=== index.ts ===
export * as one from "./one.js";
>one : Symbol(one, Decl(index.ts, 0, 6))

export * as two from "./two.js";
>two : Symbol(two, Decl(index.ts, 1, 6))

export * as three from "./three.js";
>three : Symbol(three, Decl(index.ts, 2, 6))

export * as four from "./four.js";
>four : Symbol(four, Decl(index.ts, 3, 6))

183 changes: 183 additions & 0 deletions tests/baselines/reference/jsxRuntimePragma(jsx=react).types
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
//// [tests/cases/compiler/jsxRuntimePragma.ts] ////

=== Performance Stats ===
Assignability cache: 2,500
Type Count: 5,000
Instantiation count: 50,000
Symbol count: 50,000

=== one.tsx ===
/// <reference path="react16.d.ts" />
/* @jsxRuntime classic */
import * as React from "react";
>React : typeof React
> : ^^^^^^^^^^^^

export const HelloWorld = () => <h1>Hello world</h1>;
>HelloWorld : () => JSX.Element
> : ^^^^^^^^^^^^^^^^^
>() => <h1>Hello world</h1> : () => JSX.Element
> : ^^^^^^^^^^^^^^^^^
><h1>Hello world</h1> : JSX.Element
> : ^^^^^^^^^^^
>h1 : any
> : ^^^
>h1 : any
> : ^^^

export const frag = <><div></div></>;
>frag : JSX.Element
> : ^^^^^^^^^^^
><><div></div></> : JSX.Element
> : ^^^^^^^^^^^
><div></div> : JSX.Element
> : ^^^^^^^^^^^
>div : any
> : ^^^
>div : any
> : ^^^

export const selfClosing = <img src="./image.png" />;
>selfClosing : JSX.Element
> : ^^^^^^^^^^^
><img src="./image.png" /> : JSX.Element
> : ^^^^^^^^^^^
>img : any
> : ^^^
>src : string
> : ^^^^^^

=== two.tsx ===
/// <reference path="react16.d.ts" />
/* @jsxRuntime automatic */
export const HelloWorld = () => <h1>Hello world</h1>;
>HelloWorld : () => JSX.Element
> : ^^^^^^^^^^^^^^^^^
>() => <h1>Hello world</h1> : () => JSX.Element
> : ^^^^^^^^^^^^^^^^^
><h1>Hello world</h1> : JSX.Element
> : ^^^^^^^^^^^
>h1 : any
> : ^^^
>h1 : any
> : ^^^

export const frag = <><div></div></>;
>frag : JSX.Element
> : ^^^^^^^^^^^
><><div></div></> : JSX.Element
> : ^^^^^^^^^^^
><div></div> : JSX.Element
> : ^^^^^^^^^^^
>div : any
> : ^^^
>div : any
> : ^^^

export const selfClosing = <img src="./image.png" />;
>selfClosing : JSX.Element
> : ^^^^^^^^^^^
><img src="./image.png" /> : JSX.Element
> : ^^^^^^^^^^^
>img : any
> : ^^^
>src : string
> : ^^^^^^

=== three.tsx ===
/// <reference path="react16.d.ts" />
/* @jsxRuntime classic */
/* @jsxRuntime automatic */
export const HelloWorld = () => <h1>Hello world</h1>;
>HelloWorld : () => JSX.Element
> : ^^^^^^^^^^^^^^^^^
>() => <h1>Hello world</h1> : () => JSX.Element
> : ^^^^^^^^^^^^^^^^^
><h1>Hello world</h1> : JSX.Element
> : ^^^^^^^^^^^
>h1 : any
> : ^^^
>h1 : any
> : ^^^

export const frag = <><div></div></>;
>frag : JSX.Element
> : ^^^^^^^^^^^
><><div></div></> : JSX.Element
> : ^^^^^^^^^^^
><div></div> : JSX.Element
> : ^^^^^^^^^^^
>div : any
> : ^^^
>div : any
> : ^^^

export const selfClosing = <img src="./image.png" />;
>selfClosing : JSX.Element
> : ^^^^^^^^^^^
><img src="./image.png" /> : JSX.Element
> : ^^^^^^^^^^^
>img : any
> : ^^^
>src : string
> : ^^^^^^

=== four.tsx ===
/// <reference path="react16.d.ts" />
/* @jsxRuntime automatic */
/* @jsxRuntime classic */
import * as React from "react";
>React : typeof React
> : ^^^^^^^^^^^^

export const HelloWorld = () => <h1>Hello world</h1>;
>HelloWorld : () => JSX.Element
> : ^^^^^^^^^^^^^^^^^
>() => <h1>Hello world</h1> : () => JSX.Element
> : ^^^^^^^^^^^^^^^^^
><h1>Hello world</h1> : JSX.Element
> : ^^^^^^^^^^^
>h1 : any
> : ^^^
>h1 : any
> : ^^^

export const frag = <><div></div></>;
>frag : JSX.Element
> : ^^^^^^^^^^^
><><div></div></> : JSX.Element
> : ^^^^^^^^^^^
><div></div> : JSX.Element
> : ^^^^^^^^^^^
>div : any
> : ^^^
>div : any
> : ^^^

export const selfClosing = <img src="./image.png" />;
>selfClosing : JSX.Element
> : ^^^^^^^^^^^
><img src="./image.png" /> : JSX.Element
> : ^^^^^^^^^^^
>img : any
> : ^^^
>src : string
> : ^^^^^^

=== index.ts ===
export * as one from "./one.js";
>one : typeof import("one")
> : ^^^^^^^^^^^^^^^^^^^^

export * as two from "./two.js";
>two : typeof import("two")
> : ^^^^^^^^^^^^^^^^^^^^

export * as three from "./three.js";
>three : typeof import("three")
> : ^^^^^^^^^^^^^^^^^^^^^^

export * as four from "./four.js";
>four : typeof import("four")
> : ^^^^^^^^^^^^^^^^^^^^^

Loading

0 comments on commit 8daac14

Please sign in to comment.