Mark transpiled JSX elements as pure (#11126)

* Mark transpiled JSX elements as pure

* Avoid duble annotation

* Add "pure" option to the React preset

* Fix generator indentation

* Update tests

* Add tests for the "pure" option

* Update windows fixtures
This commit is contained in:
Nicolò Ribaudo
2020-03-19 15:43:54 +01:00
committed by GitHub
parent fa7ec81771
commit f3912ac08f
246 changed files with 613 additions and 314 deletions

View File

@@ -4,6 +4,8 @@ import { declare } from "@babel/helper-plugin-utils";
import { types as t } from "@babel/core";
export default declare((api, options) => {
const PURE_ANNOTATION = options.pure;
const visitor = helper(api, {
pre(state) {
const tagName = state.tagName;
@@ -20,6 +22,9 @@ export default declare((api, options) => {
state.createElementCallee = pass.get(
"@babel/plugin-react-jsx/createElementIdentifier",
)();
state.pure =
PURE_ANNOTATION ?? !pass.get("@babel/plugin-react-jsx/pragmaSet");
} else {
state.jsxCallee = pass.get("@babel/plugin-react-jsx/jsxIdentifier")();
state.jsxStaticCallee = pass.get(
@@ -28,6 +33,10 @@ export default declare((api, options) => {
state.createElementCallee = pass.get(
"@babel/plugin-react-jsx/createElementIdentifier",
)();
state.pure =
PURE_ANNOTATION ??
!pass.get("@babel/plugin-react-jsx/importSourceSet");
}
},

View File

@@ -3,12 +3,18 @@ import jsx from "@babel/plugin-syntax-jsx";
import helper from "@babel/helper-builder-react-jsx";
import { types as t } from "@babel/core";
const DEFAULT = {
pragma: "React.createElement",
pragmaFrag: "React.Fragment",
};
export default declare((api, options) => {
const THROW_IF_NAMESPACE =
options.throwIfNamespace === undefined ? true : !!options.throwIfNamespace;
const PRAGMA_DEFAULT = options.pragma || "React.createElement";
const PRAGMA_FRAG_DEFAULT = options.pragmaFrag || "React.Fragment";
const PRAGMA_DEFAULT = options.pragma || DEFAULT.pragma;
const PRAGMA_FRAG_DEFAULT = options.pragmaFrag || DEFAULT.pragmaFrag;
const PURE_ANNOTATION = options.pure;
const JSX_ANNOTATION_REGEX = /\*?\s*@jsx\s+([^\s]+)/;
const JSX_FRAG_ANNOTATION_REGEX = /\*?\s*@jsxFrag\s+([^\s]+)/;
@@ -35,6 +41,7 @@ export default declare((api, options) => {
post(state, pass) {
state.callee = pass.get("jsxIdentifier")();
state.pure = PURE_ANNOTATION ?? !pass.get("pragmaSet");
},
throwIfNamespace: THROW_IF_NAMESPACE,
@@ -46,20 +53,16 @@ export default declare((api, options) => {
let pragma = PRAGMA_DEFAULT;
let pragmaFrag = PRAGMA_FRAG_DEFAULT;
let pragmaSet = !!options.pragma;
let pragmaFragSet = !!options.pragmaFrag;
if (file.ast.comments) {
for (const comment of (file.ast.comments: Array<Object>)) {
const jsxMatches = JSX_ANNOTATION_REGEX.exec(comment.value);
if (jsxMatches) {
pragma = jsxMatches[1];
pragmaSet = true;
}
const jsxFragMatches = JSX_FRAG_ANNOTATION_REGEX.exec(comment.value);
if (jsxFragMatches) {
pragmaFrag = jsxFragMatches[1];
pragmaFragSet = true;
}
}
}
@@ -67,8 +70,8 @@ export default declare((api, options) => {
state.set("jsxIdentifier", createIdentifierParser(pragma));
state.set("jsxFragIdentifier", createIdentifierParser(pragmaFrag));
state.set("usedFragment", false);
state.set("pragmaSet", pragmaSet);
state.set("pragmaFragSet", pragmaFragSet);
state.set("pragmaSet", pragma !== DEFAULT.pragma);
state.set("pragmaFragSet", pragmaFrag !== DEFAULT.pragmaFrag);
},
exit(path, state) {
if (