Files

82 lines
2.7 KiB
JavaScript

const { clone } = require("../shared");
const { runPatternPass } = require("./shared-pattern-pass");
const { getTopLevelIifeInfo, traverse, t } = require("./pattern-utils");
function dingxiangArrayPass(ast) {
let changed = false;
traverse(ast, {
Program(programPath) {
const info = getTopLevelIifeInfo(programPath);
if (!info) {
return;
}
const actualArgs = info.argPaths.map((argPath) => argPath.node);
const formalParams = info.calleePath.node.params;
const paramElementMap = Object.create(null);
formalParams.forEach((paramNode, index) => {
if (!t.isIdentifier(paramNode)) {
return;
}
const actualNode = actualArgs[index];
if (t.isArrayExpression(actualNode)) {
paramElementMap[paramNode.name] = actualNode.elements.map((element) => (element ? clone(element) : t.identifier("undefined")));
}
});
if (Object.keys(paramElementMap).length === 0) {
return;
}
info.statementPath.traverse({
UnaryExpression(path) {
const callPath = path.get("argument");
if (
!callPath.isCallExpression() ||
!callPath.get("callee").isFunctionExpression() ||
callPath.node.arguments.length !== 2 ||
!callPath.get("arguments").every((argPath) => argPath.isArrayExpression())
) {
return;
}
callPath.get("callee.params").forEach((paramPath) => {
if (!paramPath.isIdentifier()) {
return;
}
const elements = paramElementMap[paramPath.node.name];
if (!elements) {
return;
}
const binding = paramPath.scope.getBinding(paramPath.node.name);
if (!binding || !binding.constant) {
return;
}
binding.referencePaths.forEach((refPath) => {
const parent = refPath.parentPath;
if (!parent.isMemberExpression({ object: refPath.node }) || !parent.get("property").isNumericLiteral()) {
return;
}
const index = parent.node.property.value;
if (!Number.isInteger(index) || index < 0 || index >= elements.length) {
return;
}
parent.replaceWith(clone(elements[index]));
changed = true;
});
});
path.replaceWithMultiple(callPath.get("callee.body").node.body.map((node) => clone(node)));
changed = true;
}
});
}
});
return { ast, changed };
}
runPatternPass(dingxiangArrayPass);