71 lines
2.0 KiB
JavaScript
71 lines
2.0 KiB
JavaScript
import syntaxOptionalChaining from "babel-plugin-syntax-optional-chaining";
|
|
|
|
export default function ({ types: t }) {
|
|
return {
|
|
inherits: syntaxOptionalChaining,
|
|
|
|
visitor: {
|
|
MemberExpression(path) {
|
|
if (!path.node.optional) {
|
|
return;
|
|
}
|
|
|
|
const { scope, node } = path;
|
|
const { object } = node;
|
|
|
|
node.optional = false;
|
|
|
|
const ref = scope.generateUidIdentifierBasedOnNode(object);
|
|
scope.push({ id: ref });
|
|
node.object = ref;
|
|
|
|
let parent = path;
|
|
let expression = path;
|
|
while (parent.listKey === undefined) {
|
|
expression = parent;
|
|
parent = parent.parentPath;
|
|
}
|
|
|
|
const replace = parent.isExpression() ? parent : expression;
|
|
replace.replaceWith(t.conditionalExpression(
|
|
t.binaryExpression("==", t.assignmentExpression("=", ref, object), t.nullLiteral()),
|
|
scope.buildUndefinedNode(),
|
|
replace.node
|
|
));
|
|
},
|
|
|
|
"NewExpression|CallExpression": {
|
|
exit(path) {
|
|
if (!path.node.optional) {
|
|
return;
|
|
}
|
|
|
|
const { scope, node } = path;
|
|
const { callee } = node;
|
|
|
|
node.optional = false;
|
|
|
|
const ref = scope.generateUidIdentifierBasedOnNode(callee);
|
|
scope.push({ id: ref });
|
|
node.callee = ref;
|
|
|
|
if (t.isMemberExpression(callee) && !t.isNewExpression(node)) {
|
|
const context = scope.generateUidIdentifierBasedOnNode(callee.object);
|
|
scope.push({ id: context });
|
|
callee.object = t.assignmentExpression("=", context, callee.object);
|
|
|
|
node.arguments.unshift(context);
|
|
node.callee = t.memberExpression(node.callee, t.identifier("call"));
|
|
}
|
|
|
|
path.replaceWith(t.conditionalExpression(
|
|
t.binaryExpression("==", t.assignmentExpression("=", ref, callee), t.nullLiteral()),
|
|
scope.buildUndefinedNode(),
|
|
node
|
|
));
|
|
},
|
|
},
|
|
},
|
|
};
|
|
}
|