Files
reverse-engineering-anything/src/domain/javascript/javascriptSemanticReturnedReferences.projection.test.ts
T
morlutoandCursor Agent a896e35c47 fix(javascript): preserve semantic effects and graph evidence (#9900)
* fix(javascript): preserve semantic facts across writes and implicit effects

* fix(javascript): preserve bundler identities and helper bindings

* fix(javascript): retain semantic graph evidence and coverage

* test(javascript): include the request link in endpoint traces

Response consumers now also link the originating request to the response, so an endpoint trace reports both that association and the response's json consumer.

* fix(javascript): keep source accessors known after a copied value escapes

An unknown computed getter makes accessor lookup consider every property.
A spread copy already records a value escape, and that escape was treated
as an unknown getter on the source, so the next read escaped the whole
object. Accessor lookup still fails closed for unknown writes and calls.

* fix(javascript): keep Object.defineProperty identified at its own call

The call that escapes Object was treated as a prior replacement of
defineProperty, so a descriptor value never replaced the exported sender
and bundled IPC paths were dropped.

* fix(javascript): keep Vite preload calls that precede reassignment

Helper identity used every write to the binding, so a later assignment
erased a call that had already read the canonical helper. Use the binding
value at the call when that order is known.

* fix(javascript): apply Vite cache mutations before a later reassignment

A later helper write made the whole-binding initializer check ignore an earlier cache mutation. Identity at that mutation uses the same ordered read as the call.

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
2026-11-11 17:33:47 +08:00

226 lines
7.5 KiB
TypeScript

import * as t from "@babel/types";
import { expect, it } from "vitest";
import { indexJavaScriptBindingsSteps } from "./javascriptSemanticAnalysis.js";
import { parseJavaScriptSource } from "./javascriptSourceParser.js";
import { createSemanticReturnedReferences } from "./javascriptSemanticReturnedReferences.js";
import { completeSemanticSteps } from "./javascriptSemanticTraversal.js";
const indexed = (source: string) => {
const parsed = parseJavaScriptSource(
source,
"returned-reference-projection.js",
);
if (parsed === null) throw new Error("Expected valid fixture");
const state = completeSemanticSteps(
indexJavaScriptBindingsSteps(parsed.program),
);
return { parsed, state };
};
const callReads = (program: t.Program, name: string): t.Identifier[] => {
const reads: t.Identifier[] = [];
t.traverseFast(program, (node) => {
if (t.isCallExpression(node) && t.isIdentifier(node.callee, { name }))
reads.push(node.callee);
});
return reads;
};
const callCallees = (program: t.Program, sourceName: string): t.Node[] => {
const callees: t.Node[] = [];
t.traverseFast(program, (node) => {
if (!t.isCallExpression(node)) return;
let root = node.callee;
while (t.isMemberExpression(root)) root = root.object;
if (t.isIdentifier(root, { name: sourceName })) callees.push(node.callee);
});
return callees;
};
const returnedExpression = (program: t.Program, name: string): t.Node => {
let found: t.Node | undefined;
t.traverseFast(program, (node) => {
if (
found === undefined &&
t.isFunctionDeclaration(node) &&
node.id?.name === name
)
t.traverseFast(node.body, (child) => {
if (
found === undefined &&
t.isReturnStatement(child) &&
child.argument !== null
)
found = child.argument;
});
});
if (found === undefined)
throw new Error(`Missing return expression in ${name}`);
return found;
};
const resultIdentifier = (program: t.Program, name: string): t.Identifier => {
let found: t.Identifier | undefined;
t.traverseFast(program, (node) => {
if (
found === undefined &&
((t.isReturnStatement(node) && node.argument !== null) ||
(t.isYieldExpression(node) && node.argument !== null))
)
t.traverseFast(node.argument, (child) => {
if (found === undefined && t.isIdentifier(child, { name }))
found = child;
});
});
if (found === undefined) throw new Error(`Missing result expression ${name}`);
return found;
};
it("keeps returned-reference targets at the source read position", () => {
const { parsed, state } = indexed(`
function beforeTarget() { return beforeResult; }
function afterTarget() { return afterResult; }
function choose() {
let callback = beforeTarget;
callback();
callback = afterTarget;
callback();
}
`);
const [beforeRead, afterRead] = callReads(parsed.program, "callback");
if (beforeRead === undefined || afterRead === undefined)
throw new Error("Missing callback reads");
const returnedReferences = createSemanticReturnedReferences(state);
const before = returnedReferences(beforeRead);
const after = returnedReferences(afterRead);
expect(before.precision).toBe("exact");
expect(before.references.map(({ node }) => node)).toEqual([
returnedExpression(parsed.program, "beforeTarget"),
]);
expect(after.precision).toBe("exact");
expect(after.references.map(({ node }) => node)).toEqual([
returnedExpression(parsed.program, "afterTarget"),
]);
});
it("resolves a finite object and array projection exactly", () => {
const { parsed, state } = indexed(`
function target() { return targetResult; }
const box = { nested: [target] };
const callback = box.nested[0];
callback();
`);
const [read] = callReads(parsed.program, "callback");
if (read === undefined) throw new Error("Missing callback read");
const result = createSemanticReturnedReferences(state)(read);
expect(result.precision).toBe("exact");
expect(result.references.map(({ node }) => node)).toEqual([
returnedExpression(parsed.program, "target"),
]);
});
it("reports conservative widening for a shrinking projection cycle", () => {
const { parsed, state } = indexed(`
function target() { return targetResult; }
let cursor = { target };
while (flag) cursor = { next: cursor, target };
cursor.next.next.target();
`);
const [callee] = callCallees(parsed.program, "cursor");
if (callee === undefined) throw new Error("Missing projected call");
const result = createSemanticReturnedReferences(state)(callee);
expect(result.precision).toBe("widened");
expect(result.references.map(({ node }) => node)).toEqual([
returnedExpression(parsed.program, "target"),
]);
});
it("widens a growing projection while retaining zero-depth and nested targets", () => {
const { parsed, state } = indexed(`
function zeroDepthTarget() { return zeroDepthResult; }
function objectTarget() { return objectResult; }
function arrayTarget() { return arrayResult; }
function* generatorTarget() { yield* generatorResult; }
const shape = {
zero: zeroDepthTarget,
nested: {
object: objectTarget,
array: [arrayTarget],
class: class NestedTarget { method() { return classResult; } },
generator: generatorTarget,
},
};
let cursor = shape;
function walk(flag) {
while (flag) cursor = cursor.next;
return cursor();
}
walk(true);
`);
const [read] = callReads(parsed.program, "cursor");
if (read === undefined) throw new Error("Missing cursor read");
const result = createSemanticReturnedReferences(state)(read);
const expressions = result.references.map(({ node }) => node);
expect(result.precision).toBe("widened");
for (const name of ["zeroDepthTarget", "objectTarget", "arrayTarget"])
expect(expressions).toContain(returnedExpression(parsed.program, name));
expect(expressions).toContain(
resultIdentifier(parsed.program, "classResult"),
);
const generatorResult = resultIdentifier(parsed.program, "generatorResult");
expect(result.references).toContainEqual({
node: generatorResult,
projection: [null],
});
});
it("widens a cycle that rewrites the path head while increasing its depth", () => {
const { parsed, state } = indexed(`
function target() { return targetResult; }
let value = {};
while (flag)
value = {
a: value.x.y,
x: value.a.z,
target,
};
value.a.b();
`);
const [callee] = callCallees(parsed.program, "value");
if (callee === undefined) throw new Error("Missing projected call");
const result = createSemanticReturnedReferences(state)(callee);
expect(result.precision).toBe("widened");
expect(result.references.map(({ node }) => node)).toContain(
returnedExpression(parsed.program, "target"),
);
});
it("retains both finite class-prototype callable selections", () => {
const { parsed, state } = indexed(`
class C { first(){return firstResult} second(){return secondResult} }
const selected=flag?C.prototype.first:C.prototype.second;
selected();
`);
const [read] = callReads(parsed.program, "selected");
if (read === undefined)
throw new Error("Missing selected prototype method call");
const result = createSemanticReturnedReferences(state)(read);
expect(result.precision).toBe("exact");
expect(
result.references
.map(({ node }) => (t.isIdentifier(node) ? node.name : null))
.sort(),
).toEqual(["firstResult", "secondResult"]);
});