fix(javascript): bound member-mutation paths through reassignment loops

Fixes #1401. Refs #1065. Preserve exact member facts and equal-depth write effects while bounding the observed reassignment-loop expansion.

Validated with the JavaScript semantic/application suite, focused alias regressions, full static checks, real compiled CLI and SDK MCP Notion workflows, and all 20 checks on the final PR head.

Co-Authored-By: Marnix Pluim <286664873+marnixpluim@users.noreply.github.com>
Co-Authored-By: N0zoM1z0 <161784452+N0zoM1z0@users.noreply.github.com>
Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
authored and GitHub committed 2026-10-10 12:03:13 +08:00
1 parent 98022a8352
commit 28595276fa
4 files changed
+524 -14

No files matched your search

@@ -9,6 +9,163 @@ const resultValue = (body: string) =>
"result",
).returnSites[0]?.value;
describe("bounded member path propagation", () => {
it("bounds cyclic member paths with no observed container origin", () => {
const branches = Array.from(
{ length: 16 },
(_, index) => `if (flag === ${index}) node = node.m${index};`,
).join(" else ");
const start = performance.now();
const callable = onlyCallable(
analyzeJavaScriptSemantics(
`export function result(seed) { let node=seed; while(node) { ${branches} use(node.state); } return seed.keep; }`,
),
"result",
);
expect(callable.returnSites[0]?.value.status).toBe("unknown");
expect(performance.now() - start).toBeLessThan(2000);
}, 30000);
it("preserves Array prototype effects through an otherwise unknown alias", () => {
expect(
resultValue(
"const values=[1]; const prototype=Array.prototype; prototype[Symbol.iterator]=custom; for(const item of values) { mutate(item); } return values[0];",
)?.status,
).toBe("unknown");
});
it("bounds loops derived from a scalar member while preserving sibling facts", () => {
const branches = Array.from(
{ length: 16 },
(_, index) => `if (flag === ${index}) node = node.m${index};`,
).join(" else ");
const start = performance.now();
expect(
resultValue(
`const source={child:1,keep:{value:3}}; let node=source.child; while(node) { ${branches} use(node.state); } return source.keep.value;`,
),
).toEqual({ status: "literal", value: 3 });
expect(performance.now() - start).toBeLessThan(2000);
}, 30000);
it.each([
["child:external,", "child", "present"],
["", "missing", "unknown-coverage"],
])(
"retains slot presence below an unobserved container: %s",
(property, name, presence) => {
expect(
resultValue(
`const source={${property}keep:3}; const alias=source.${name}; alias.deep.value=2; return source;`,
),
).toMatchObject({
status: "object",
properties: expect.arrayContaining([
{
name,
presence,
value: {
status: "unknown",
reason: "This property may have been mutated.",
},
},
{
name: "keep",
presence: "present",
value: { status: "literal", value: 3 },
},
]),
});
},
);
it.each([
["use(node);", "m0.value", "unknown"],
["node.value = 2;", "m0.value", "unknown"],
["node.value = 2;", "mode", "literal"],
])(
"bounds a loop that reassigns one reference through many members: %s seed.%s",
(effect, read, status) => {
const branches = Array.from(
{ length: 9 },
(_, index) => `if (flag === ${index}) node = node.m${index};`,
).join(" else ");
const start = performance.now();
const value = resultValue(
`const seed = { mode: "initial", m0: { value: 1 } }; let node = seed; while (node) { ${branches} ${effect} } return seed.${read};`,
);
expect(performance.now() - start).toBeLessThan(2000);
expect(value?.status).toBe(status);
},
30000,
);
it.each([
["const alias = flag ? owner.child : owner; alias.value = 2;", "value"],
["const alias = flag ? owner : owner.child; alias.value = 2;", "value"],
["const alias = flag ? owner.child : owner; alias[key] = 2;", "value"],
[
"const alias = flag ? owner.child : owner; alias.child = 2;",
"child.value",
],
[
"let alias = owner; let i = 0; while (i++ < 1) { alias = flag ? alias.child : alias; alias.value = 2; }",
"value",
],
])(
"keeps a write that reaches a child through a longer path: %s",
(body, read) => {
expect(
resultValue(
`const shared = { value: 1, child: { value: 1 } }; const owner = { child: shared }; ${body} return shared.${read};`,
)?.status,
).toBe("unknown");
},
);
it.each([
"mutate(source.left, source.right);",
"const alias = flag ? source.left : source.right; mutate(alias);",
"const copy = flag ? [source.left] : [source.right]; mutate(copy);",
"const alias = flag ? source.left : source.right; alias.value = 2;",
])("keeps members outside the mutated paths: %s", (body) => {
expect(
resultValue(
`const source = { left: { value: 1 }, right: { value: 2 }, keep: { value: 3 } }; ${body} return source.keep.value;`,
),
).toEqual({ status: "literal", value: 3 });
});
});
describe("distinct observable mutation paths", () => {
it.each([
["alias.value = 2;", "left"],
["alias.value = 2;", "right"],
["mutate(alias);", "left"],
["mutate(alias);", "right"],
])(
"propagates both conditional paths to shared bindings: %s %s",
(effect, target) => {
expect(
resultValue(
`const left={value:1}; const right={value:2}; const source={left,right}; const alias=flag?source.left:source.right; ${effect} return ${target}.value;`,
)?.status,
).toBe("unknown");
},
);
it.each(["mutate(alias);", "alias.value = 2;"])(
"preserves sibling facts below a shared prefix: %s",
(effect) => {
expect(
resultValue(
`const shared={left:{value:1},right:{value:2},keep:{value:3}}; const source={nested:shared}; const alias=flag?source.nested.left:source.nested.right; ${effect} return shared.keep.value;`,
),
).toEqual({ status: "literal", value: 3 });
},
);
});
describe("reference lifetimes across calls and shallow copies", () => {
it("bounds dynamic destructuring across shared alias branches", () => {
const declarations = Array.from(