mirror of
https://github.com/morluto/rea.git
synced 2026-10-29 02:45:58 +00:00
fix(javascript): preserve builtin identity and share alias traversal
Track module writes and escapes at their owner, preserve capture and reassignment ordering, and share CommonJS/default namespace identity without erasing parent-slot changes. Carry write sites into ambient alias resolution and use parsed write targets across consumers. Deduplicate returned-reference work with cycle context; retain unchanged temporal selection identity so provenance memoization stays effective. Reviewed fixes include #2041, #2465, #2830, #2881, and #2948. Remove superseded mutation representations and the ineffective per-markValue dedup layer. Validation: 380 focused JavaScript tests passed under a 384 MiB heap cap, including the previously aborting 30-level/128-call alias regression. Six public CLI/MCP builtin tests passed. Exact pdf.js completed-workflow performance remains unmeasured.
This commit is contained in:
1 parent
0f4c484be5
commit
04672f2b91
34 files changed
+3778
-321
No files matched your search
@@ -210,6 +210,64 @@ describe("JavaScript semantic analysis: read-modify-write", () => {
|
||||
]);
|
||||
});
|
||||
|
||||
it.each([
|
||||
["destructuring assignment", "[source.count] = [2];"],
|
||||
["destructuring assignment with default", "[source.count = 2] = [];"],
|
||||
[
|
||||
"nested destructuring assignment",
|
||||
"({ value: { count: source.count } } = {});",
|
||||
],
|
||||
["rest destructuring assignment", "[...source.items] = [];"],
|
||||
["for-of head", "for (source.count of [4]) {}"],
|
||||
["for-in head", "for (source.count in { key: true }) {}"],
|
||||
["delete", "delete source.count;"],
|
||||
])("records a member target in %s as a write", (_name, statement) => {
|
||||
const ir = analyzeJavaScriptSemantics(`
|
||||
const source = { count: 1, items: [] };
|
||||
${statement}
|
||||
`);
|
||||
expect(ir.objectOperations.map(({ kind }) => kind)).toEqual(["write"]);
|
||||
});
|
||||
|
||||
it.each([
|
||||
["non-null update", "source.count!++;"],
|
||||
["non-null compound assignment", "source.count! += 1;"],
|
||||
["cast compound assignment", "(source.count as number) += 1;"],
|
||||
["parenthesized update", "(source.count)++;"],
|
||||
])(
|
||||
"retains the property read in a wrapped read-modify-write: %s",
|
||||
(_name, statement) => {
|
||||
const ir = analyzeJavaScriptSemantics(`
|
||||
const source = { count: 1 };
|
||||
${statement}
|
||||
`);
|
||||
expect(ir.objectOperations.map(({ kind }) => kind)).toEqual([
|
||||
"read",
|
||||
"write",
|
||||
]);
|
||||
},
|
||||
);
|
||||
|
||||
it.each([
|
||||
["cast plain assignment", "(source.count as number) = 2;"],
|
||||
["non-null delete", "delete source.count!;"],
|
||||
])("keeps a wrapped %s write-only", (_name, statement) => {
|
||||
const ir = analyzeJavaScriptSemantics(`
|
||||
const source = { count: 1 };
|
||||
${statement}
|
||||
`);
|
||||
expect(ir.objectOperations.map(({ kind }) => kind)).toEqual(["write"]);
|
||||
});
|
||||
|
||||
it("keeps a member in a destructuring default value a read", () => {
|
||||
const ir = analyzeJavaScriptSemantics(`
|
||||
const source = { count: 1 };
|
||||
let value;
|
||||
[value = source.count] = [];
|
||||
`);
|
||||
expect(ir.objectOperations.map(({ kind }) => kind)).toEqual(["read"]);
|
||||
});
|
||||
|
||||
it("does not model a compound binding write as a competing replacement", () => {
|
||||
const ir = analyzeJavaScriptSemantics(`
|
||||
let count = 1;
|
||||
@@ -222,6 +280,37 @@ describe("JavaScript semantic analysis: read-modify-write", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("JavaScript semantic analysis: wrapped binding targets", () => {
|
||||
it("records a wrapped identifier update as a read before a write", () => {
|
||||
const ir = analyzeJavaScriptSemantics(`
|
||||
let count = 1;
|
||||
count! += 1;
|
||||
(count as number)++;
|
||||
const copy = count!;
|
||||
`);
|
||||
expect(
|
||||
ir.references
|
||||
.filter(({ name }) => name === "count")
|
||||
.map(({ role }) => role),
|
||||
).toEqual(["read", "write", "read", "write", "read"]);
|
||||
expect(topLevelBinding(ir, "count").value).toMatchObject({
|
||||
status: "unknown",
|
||||
});
|
||||
});
|
||||
|
||||
it("records a wrapped identifier assignment as a write of its value", () => {
|
||||
const ir = analyzeJavaScriptSemantics(`
|
||||
let count = 1;
|
||||
count! = 2;
|
||||
`);
|
||||
expect(
|
||||
ir.references
|
||||
.filter(({ name }) => name === "count")
|
||||
.map(({ role }) => role),
|
||||
).toEqual(["write"]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("JavaScript semantic analysis: dataflow 2", () => {
|
||||
it("retains partial property coverage and empty returns", () => {
|
||||
const partial = analyzeJavaScriptSemantics(`
|
||||
|
||||
Reference in new issue
Block a user