packages/babel-helper-explode-class/src/index.js
import bindifyDecorators from "@babel/helper-bindify-decorators";
import type { NodePath } from "@babel/traverse";
import * as t from "@babel/types";
export default function (classPath) {
classPath.assertClass();
const memoisedExpressions = [];
function maybeMemoise(path) {
if (!path.node || path.isPure()) return;
const uid = classPath.scope.generateDeclaredUidIdentifier();
memoisedExpressions.push(t.assignmentExpression("=", uid, path.node));
path.replaceWith(uid);
}
function memoiseDecorators(paths: Array<NodePath>) {
if (!Array.isArray(paths) || !paths.length) return;
// ensure correct evaluation order of decorators
paths = paths.reverse();
// bind decorators if they're member expressions
bindifyDecorators(paths);
for (const path of paths) {
maybeMemoise(path);
}
}
maybeMemoise(classPath.get("superClass"));
memoiseDecorators(classPath.get("decorators"), true);
const methods: Array<NodePath> = classPath.get("body.body");
for (const methodPath of methods) {
if (methodPath.is("computed")) {
maybeMemoise(methodPath.get("key"));
}
if (methodPath.has("decorators")) {
memoiseDecorators(classPath.get("decorators"));
}
}
if (memoisedExpressions) {
classPath.insertBefore(
memoisedExpressions.map(expr => t.expressionStatement(expr)),
);
}
}