@nodesecure/js-x-ray
Version:
JavaScript AST XRay analysis
87 lines • 3.12 kB
JavaScript
// Import Internal Dependencies
import { getCallExpressionIdentifier } from "../../estree/index.js";
import { VirtualVariableIdentifier } from "../../VirtualVariableIdentifier.js";
export class InlinedRequire {
static assertNode(node) {
if (node.type === "CallExpression" &&
getCallExpressionIdentifier(node)?.match(/^require..*$/i)) {
return true;
}
return false;
}
static split(expectedCallExpr) {
if (!InlinedRequire.assertNode(expectedCallExpr)) {
return null;
}
const requireCall = InlinedRequire.#findRequireCall(expectedCallExpr);
if (!requireCall) {
return null;
}
const virtualIdentifier = VirtualVariableIdentifier.generate("require", expectedCallExpr.loc);
return {
virtualIdentifier,
virtualDeclaration: {
type: "VariableDeclaration",
kind: "const",
declarations: [
{
type: "VariableDeclarator",
id: {
type: "Identifier",
name: virtualIdentifier
},
init: requireCall
}
]
},
rebuildExpression: InlinedRequire.#rebuildWithVirtualIdentifier(expectedCallExpr, requireCall, virtualIdentifier)
};
}
static #findRequireCall(node) {
const object = node.type === "MemberExpression"
? node.object
: node.callee;
if (object.type === "CallExpression" &&
object.callee.type === "Identifier" &&
object.callee.name === "require") {
return object;
}
if (object.type === "MemberExpression" ||
object.type === "CallExpression") {
return InlinedRequire.#findRequireCall(object);
}
return null;
}
static #rebuildWithVirtualIdentifier(node, requireCall, virtualIdentifier) {
if (node === requireCall) {
return null;
}
const virtualId = {
type: "Identifier",
name: virtualIdentifier
};
return InlinedRequire.#cloneAndReplace(node, requireCall, virtualId);
}
static #cloneAndReplace(node, target, replacement) {
if (node === target) {
return replacement;
}
if (node.type === "CallExpression") {
const callee = InlinedRequire.#cloneAndReplace(node.callee, target, replacement);
const args = node.arguments.map((arg) => InlinedRequire.#cloneAndReplace(arg, target, replacement));
return {
...node,
callee,
arguments: args
};
}
if (node.type === "MemberExpression") {
return {
...node,
object: InlinedRequire.#cloneAndReplace(node.object, target, replacement)
};
}
return node;
}
}
//# sourceMappingURL=InlinedRequire.js.map