fix(browser): distinguish computed call keys from identifiers (#808)

Signed-off-by: Rudy Celekli <47457359+rudycelekli@users.noreply.github.com>
This commit is contained in:
Rudy Mizrahi Celekli
2026-10-06 21:19:44 -05:00
committed by GitHub
parent 21a8bd0ccd
commit 02beb74535
2 changed files with 47 additions and 7 deletions
+42
View File
@@ -369,3 +369,45 @@ describe("web metadata key semantics", () => {
]);
});
});
it("does not infer call names from dynamic computed identifiers", () => {
const result = analyzeCapturedWebBundle(
inspection(`
const fetch = "render";
const require = "render";
const registerTool = "render";
window[fetch]("/render-only");
window[require]("./not-a-module.js");
document.modelContext[registerTool]({ name: "not-a-tool" });
`),
);
expect(result.observations.endpoints).toEqual([]);
expect(result.observations.chunks.edges).toEqual([]);
expect(result.observations.webmcp_declarations).toEqual([]);
});
it("retains direct and literal computed call names", () => {
const result = analyzeCapturedWebBundle(
inspection(`
window.fetch("/direct");
window["fetch"]("/literal");
window[receiver].fetch("/nested-receiver");
window.require("./direct.js");
window["require"]("./literal.js");
document.modelContext["registerTool"]({ name: "literal-tool" });
`),
);
expect(result.observations.endpoints.map(({ value }) => value)).toEqual([
"/direct",
"/literal",
"/nested-receiver",
]);
expect(
result.observations.chunks.edges.map(({ specifier }) => specifier),
).toEqual(["./direct.js", "./literal.js"]);
expect(result.observations.webmcp_declarations).toEqual([
expect.objectContaining({ name: "literal-tool" }),
]);
});
+5 -7
View File
@@ -11,7 +11,11 @@ export const calleeName = (callee: t.Node): string => {
const object = t.isExpression(callee.object)
? calleeName(callee.object)
: "";
const property = propertyName(callee.property);
const property = semanticStaticPropertyName(
callee.property,
callee.computed,
);
if (property === "") return "";
return object === "" ? property : `${object}.${property}`;
}
return "";
@@ -21,12 +25,6 @@ export const stringArgument = (
value: t.Node | null | undefined,
): string | undefined => (t.isStringLiteral(value) ? value.value : undefined);
export const propertyName = (value: t.Node): string => {
if (t.isIdentifier(value)) return value.name;
if (t.isStringLiteral(value)) return value.value;
return "";
};
export const objectValue = (
object: t.ObjectExpression,
name: string,