Implement @babel/plugin-transform-react-pure-annotations (#11428)
The new plugin is also enabled in `@babel/preset-react`
This commit is contained in:
@@ -0,0 +1,79 @@
|
||||
import { declare } from "@babel/helper-plugin-utils";
|
||||
import annotateAsPure from "@babel/helper-annotate-as-pure";
|
||||
import { types as t } from "@babel/core";
|
||||
|
||||
// Mapping of React top-level methods that are pure.
|
||||
// This plugin adds a /*#__PURE__#/ annotation to calls to these methods,
|
||||
// so that terser and other minifiers can safely remove them during dead
|
||||
// code elimination.
|
||||
// See https://reactjs.org/docs/react-api.html
|
||||
const PURE_CALLS = new Map([
|
||||
[
|
||||
"react",
|
||||
[
|
||||
"cloneElement",
|
||||
"createElement",
|
||||
"createFactory",
|
||||
"createRef",
|
||||
"forwardRef",
|
||||
"isValidElement",
|
||||
"memo",
|
||||
"lazy",
|
||||
],
|
||||
],
|
||||
["react-dom", ["createPortal"]],
|
||||
]);
|
||||
|
||||
export default declare(api => {
|
||||
api.assertVersion(7);
|
||||
|
||||
return {
|
||||
name: "transform-react-pure-annotations",
|
||||
visitor: {
|
||||
CallExpression(path) {
|
||||
if (isReactCall(path)) {
|
||||
annotateAsPure(path);
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
function isReactCall(path) {
|
||||
// If the callee is not a member expression, then check if it matches
|
||||
// a named import, e.g. `import {forwardRef} from 'react'`.
|
||||
if (!t.isMemberExpression(path.node.callee)) {
|
||||
const callee = path.get("callee");
|
||||
for (const [module, methods] of PURE_CALLS) {
|
||||
for (const method of methods) {
|
||||
if (callee.referencesImport(module, method)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Otherwise, check if the member expression's object matches
|
||||
// a default import (`import React from 'react'`) or namespace
|
||||
// import (`import * as React from 'react'), and check if the
|
||||
// property matches one of the pure methods.
|
||||
for (const [module, methods] of PURE_CALLS) {
|
||||
const object = path.get("callee.object");
|
||||
if (
|
||||
object.referencesImport(module, "default") ||
|
||||
object.referencesImport(module, "*")
|
||||
) {
|
||||
for (const method of methods) {
|
||||
if (t.isIdentifier(path.node.callee.property, { name: method })) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
Reference in New Issue
Block a user