perf(javascript): analyze member chains without recursive copying (#932)

* fix(javascript): traverse deep semantic member chains iteratively

* fix(javascript): preserve deep initializer and pattern analysis
This commit is contained in:
morluto
2026-10-07 19:09:25 +08:00
committed by GitHub
parent e6ba9c3af3
commit dcde958450
7 changed files with 287 additions and 116 deletions
@@ -520,19 +520,23 @@ export const storageKind = (
};
/** Produce a dotted callee name from member syntax. */
export const calleeName = (node: t.Node): string => calleeNameAt(node);
const calleeNameAt = (node: t.Node): string => {
if (t.isIdentifier(node)) return node.name;
if (t.isImport(node)) return "import";
if (t.isMemberExpression(node) || t.isOptionalMemberExpression(node)) {
const object = t.isNode(node.object) ? calleeNameAt(node.object) : "";
// A dynamic key commits no name: `target[method]()` must not be reported as
// `target.method`, which would fabricate a runtime call shape.
const property = memberPropertyName(node);
return object === "" ? property : `${object}.${property}`;
export const calleeName = (node: t.Node): string => {
const segments: string[] = [];
while (t.isMemberExpression(node) || t.isOptionalMemberExpression(node)) {
// Dynamic keys retain their syntax identity instead of inventing a name.
segments.push(memberPropertyName(node));
if (!t.isNode(node.object)) break;
node = node.object;
}
return "";
const base = t.isIdentifier(node)
? node.name
: t.isImport(node)
? "import"
: "";
segments.push(base);
segments.reverse();
const first = segments.findIndex((segment) => segment !== "");
return first === -1 ? "" : segments.slice(first).join(".");
};
/** Read a member property only when its syntax commits an exact name. */