import { expect, it, vi } from "vitest"; import { analyzeJavaScriptSemantics, indexJavaScriptBindingsSteps, } from "./javascriptSemanticAnalysis.js"; import { SemanticDependencyProofs } from "./javascriptSemanticDependencies.js"; import { SEMANTIC_EXPRESSION_DEPTH_LIMIT } from "./javascriptSemanticResourceLimits.js"; import type { JavaScriptSemanticValue } from "./javascriptSemanticValueTypes.js"; import { clearSemanticValueCaches, evaluateSemanticBinding, evaluateSemanticProvenance, } from "./javascriptSemanticValues.js"; import { parseJavaScriptSource } from "./javascriptSourceParser.js"; const property = ( value: JavaScriptSemanticValue, name: string, ): JavaScriptSemanticValue => { if (value.status !== "object") throw new Error(`Expected object at ${name}, got ${value.status}`); const result = value.properties.find((entry) => entry.name === name)?.value; if (result === undefined) throw new Error(`Missing ${name}`); return result; }; it("reuses dependency-aware read snapshots across a reconvergent value chain", () => { const measure = (depth: number) => { const source = `let a0=1;${Array.from( { length: depth }, (_, index) => `let a${index + 1}=a${index}+a${index};`, ).join( "", )}const saved=a${depth};${Array.from({ length: depth + 1 }, (_, index) => `a${index}=0;`).join("")}`; const parsed = parseJavaScriptSource(source, "saved-chain.js"); if (parsed === null) throw new Error("Expected parsed source"); const steps = indexJavaScriptBindingsSteps(parsed.program); let step = steps.next(); while (step.done !== true) step = steps.next(); const state = step.value; const saved = [...state.bindingsById.values()].find( ({ name }) => name === "saved", ); if (saved === undefined) throw new Error("Missing saved binding"); const binding = vi.spyOn(SemanticDependencyProofs.prototype, "binding"); try { expect(evaluateSemanticBinding(saved, state)).toEqual({ status: "literal", value: 2 ** depth, }); return binding.mock.calls.length; } finally { binding.mockRestore(); } }; const small = measure(8); const large = measure(12); expect(small).toBeGreaterThan(0); expect(large).toBeLessThan(3 * small); }); it("preserves the remaining depth budget when reusing a read snapshot", () => { const depth = 12; const nesting = SEMANTIC_EXPRESSION_DEPTH_LIMIT - depth; const source = `let a0=1;${Array.from({ length: depth }, (_, index) => `let a${index + 1}=a${index}+a${index};`).join("")} const root={shallow:a${depth},deep:${"[".repeat(nesting)}a${depth}${"]".repeat(nesting)},after:a${depth}}; ${Array.from({ length: depth + 1 }, (_, index) => `a${index}=0;`).join("")}`; const parsed = parseJavaScriptSource(source, "snapshot-depth.js"); if (parsed === null) throw new Error("Expected parsed source"); const steps = indexJavaScriptBindingsSteps(parsed.program); let step = steps.next(); while (step.done !== true) step = steps.next(); const state = step.value; const root = [...state.bindingsById.values()].find( ({ name }) => name === "root", ); if (root === undefined) throw new Error("Missing root binding"); const result = evaluateSemanticBinding(root, state); for (const key of ["shallow", "after"]) expect(property(result, key)).toEqual({ status: "literal", value: 2 ** depth, }); let leaf = property(result, "deep"); while (leaf.status === "array") { const item = leaf.items[0]; if (item === undefined) throw new Error("Missing nested item"); leaf = item.value; } expect(leaf).toMatchObject({ status: "unknown", resourceLimit: "expression-depth", }); }); it("bounds reconvergent read work when the expression depth budget is exhausted", () => { const depth = SEMANTIC_EXPRESSION_DEPTH_LIMIT; const source = `let a0=1;${Array.from({ length: depth }, (_, index) => `let a${index + 1}=a${index}+a${index};`).join("")} const saved=a${depth};${Array.from({ length: depth + 1 }, (_, index) => `a${index}=0;`).join("")}`; const parsed = parseJavaScriptSource(source, "snapshot-limit.js"); if (parsed === null) throw new Error("Expected parsed source"); const steps = indexJavaScriptBindingsSteps(parsed.program); let step = steps.next(); while (step.done !== true) step = steps.next(); const state = step.value; const saved = [...state.bindingsById.values()].find( ({ name }) => name === "saved", ); if (saved === undefined) throw new Error("Missing saved binding"); const original = SemanticDependencyProofs.prototype.binding; let visits = 0; const binding = vi .spyOn(SemanticDependencyProofs.prototype, "binding") .mockImplementation(function (this: SemanticDependencyProofs, name) { if (++visits > 16 * depth) throw new Error("Unbounded snapshot dependency evaluation"); return original.call(this, name); }); try { expect(evaluateSemanticBinding(saved, state)).toMatchObject({ status: "unknown", resourceLimit: "expression-depth", }); } finally { binding.mockRestore(); } }); it.each([false, true])( "isolates captured parameter values from the assigned binding cache (prewarmed: %s)", (prewarmed) => { const parsed = parseJavaScriptSource( `export function read(x) { const earlier = x; x = 2; const later = x; return { earlier, later }; }`, "captured-parameter.js", ); if (parsed === null) throw new Error("Expected parsed source"); const steps = indexJavaScriptBindingsSteps(parsed.program); let step = steps.next(); while (step.done !== true) step = steps.next(); const state = step.value; const bindings = new Map( [...state.bindingsById.values()].map((binding) => [ binding.name, binding, ]), ); const assigned = bindings.get("x"); const earlier = bindings.get("earlier"); const later = bindings.get("later"); if (assigned === undefined || earlier === undefined || later === undefined) throw new Error("Missing capture bindings"); if (prewarmed) expect(evaluateSemanticBinding(assigned, state)).toEqual({ status: "literal", value: 2, }); expect(evaluateSemanticBinding(earlier, state).status).toBe("unknown"); expect(evaluateSemanticBinding(later, state)).toEqual({ status: "literal", value: 2, }); expect(evaluateSemanticBinding(assigned, state)).toEqual({ status: "literal", value: 2, }); }, ); it.each([ [false, false], [true, false], [false, true], [true, true], ])( "recomputes a shared cyclic value under a different active ancestor (prewarmed: %s, rebound: %s)", (prewarmed, rebound) => { const parsed = parseJavaScriptSource( ` ${rebound ? "let" : "const"} a = { shared: common, own: "a" }; ${rebound ? "let" : "const"} b = { shared: common, own: "b" }; const common = { a, b }; const result = { first: a, second: b }; ${rebound ? "a=0; b=0;" : ""} `, "cycles.js", ); if (parsed === null) throw new Error("Expected parsed source"); const steps = indexJavaScriptBindingsSteps(parsed.program); let step = steps.next(); while (step.done !== true) step = steps.next(); const state = step.value; const binding = [...state.bindingsById.values()].find( (entry) => entry.name === "result", ); if (binding === undefined) throw new Error("Missing result binding"); if (prewarmed) for (const entry of state.bindingsById.values()) if (entry.name === "a" || entry.name === "b") evaluateSemanticBinding(entry, state); const value = evaluateSemanticBinding(binding, state); const firstCommon = property(property(value, "first"), "shared"); const secondCommon = property(property(value, "second"), "shared"); expect(property(firstCommon, "a").status).toBe("cycle"); expect(property(property(firstCommon, "b"), "own")).toEqual({ status: "literal", value: "b", }); expect(property(secondCommon, "b").status).toBe("cycle"); expect(property(property(secondCommon, "a"), "own")).toEqual({ status: "literal", value: "a", }); }, ); it.each([ ["const", ""], ["let", "target={value:2};"], ])( "invalidates retained %s alias values at the producing mutation boundary", (kind, later) => { const parsed = parseJavaScriptSource( `${kind} target = { value: 1 }; const alias = target; const root = { alias }; ${later}`, "mutation.js", ); if (parsed === null) throw new Error("Expected parsed source"); const steps = indexJavaScriptBindingsSteps(parsed.program); let step = steps.next(); while (step.done !== true) step = steps.next(); const state = step.value; const target = [...state.bindingsById.values()].find( ({ name }) => name === "target", ); const root = [...state.bindingsById.values()].find( ({ name }) => name === "root", ); if (target === undefined || root === undefined) throw new Error("Missing binding"); expect( property( property(evaluateSemanticBinding(root, state), "alias"), "value", ), ).toEqual({ status: "literal", value: 1 }); target.memberWrites.push({ path: ["value"], node: undefined }); clearSemanticValueCaches(state); expect( property(property(evaluateSemanticBinding(root, state), "alias"), "value") .status, ).toBe("unknown"); }, ); const balancedOr = (names: string[]): string => { if (names.length === 1) return names[0]!; const middle = Math.floor(names.length / 2); return `(${balancedOr(names.slice(0, middle))} || ${balancedOr(names.slice(middle))})`; }; it("shares dependency proofs across a shallow wide reconvergent graph", () => { const measure = (width: number) => { const imports = Array.from({ length: width }, (_, index) => `l${index}`); const aliases = Array.from({ length: width }, (_, index) => `a${index}`); const source = `${imports.map((name) => `import * as ${name} from "fs";`).join("\n")} const shared = ${balancedOr(imports)}; function consumer() { ${aliases.map((name) => `const ${name} = shared;`).join("\n")} const root = ${balancedOr(aliases)}; }`; const parsed = parseJavaScriptSource(source, "wide.js"); if (parsed === null) throw new Error("Expected parsed source"); const steps = indexJavaScriptBindingsSteps(parsed.program); let step = steps.next(); while (step.done !== true) step = steps.next(); const state = step.value; const rootBinding = [...state.bindingsById.values()].find( ({ name }) => name === "root", ); if (rootBinding === undefined) throw new Error("Missing root binding"); // One root query simultaneously retains every alias memo in this family. // Separate per-binding provenance queries have baseline repeated traversal; // they must not be confused with this cache's retained closure expansion. // Count representation construction and union work, not elapsed time/heap. // Binding-ID additions also discriminate the superseded flattened Sets. let bindingMemberships = 0; let proofBranches = 0; let unionCalls = 0; const add = Set.prototype.add; const freeze = Object.freeze; const union = SemanticDependencyProofs.prototype.union; const addSpy = vi.spyOn(Set.prototype, "add").mockImplementation(function ( this: Set, value: unknown, ) { if (typeof value === "string" && value.includes("binding:")) bindingMemberships++; return add.call(this, value); }); const freezeSpy = vi.spyOn(Object, "freeze").mockImplementation((value) => { if ( typeof value === "object" && value !== null && Object.hasOwn(value, "zero") && Object.hasOwn(value, "one") && Object.keys(value).length === 2 ) proofBranches++; return freeze(value); }); const unionSpy = vi .spyOn(SemanticDependencyProofs.prototype, "union") .mockImplementation(function ( this: SemanticDependencyProofs, first, second, ) { unionCalls++; return union.call(this, first, second); }); try { expect(evaluateSemanticBinding(rootBinding, state).status).toBe( "ambiguous", ); expect(evaluateSemanticProvenance(rootBinding, state).origins).toEqual([ { specifier: "fs", importedPath: [] }, ]); } finally { unionSpy.mockRestore(); freezeSpy.mockRestore(); addSpy.mockRestore(); } const result = analyzeJavaScriptSemantics(source); expect(result.coverage).toEqual({ status: "complete", omittedCount: 0 }); for (const name of [...imports, ...aliases, "shared", "root"]) expect( result.bindings.filter((entry) => entry.name === name), ).toHaveLength(1); const root = result.bindings.find((entry) => entry.name === "root"); expect(root?.value.status).toBe("ambiguous"); expect(root?.provenance.origins).toEqual([ { specifier: "fs", importedPath: [] }, ]); return { storage: bindingMemberships + proofBranches, work: bindingMemberships + unionCalls, }; }; // Balanced depths remain small; doubling both independent widths must not // quadruple proof construction/work while all meaningful aliases survive. const small = measure(32); const large = measure(64); expect(small.storage).toBeGreaterThan(0); expect(small.work).toBeGreaterThan(0); expect(large.storage).toBeLessThan(small.storage * 3); expect(large.work).toBeLessThan(small.work * 3); }); it("uses immutable exact identity proofs and shares unchanged union branches", () => { const proofs = new SemanticDependencyProofs(["a", "b", "c", "d", "e"]); const a = proofs.binding("a"); const b = proofs.binding("b"); const c = proofs.binding("c"); const ab = proofs.union(a, b); const abc = proofs.union(ab, c); expect(proofs.union(abc, ab)).toBe(abc); expect(proofs.binding("a")).toBe(a); expect(Object.isFrozen(abc)).toBe(true); expect(["a", "b", "c", "d", "e"].map((id) => proofs.has(abc, id))).toEqual([ true, true, true, false, false, ]); expect(proofs.has(undefined, "a")).toBe(false); expect(proofs.intersects(abc, new Map([["d", 0]]))).toBe(false); expect(proofs.intersects(abc, new Map([["c", 0]]))).toBe(true); const single = new SemanticDependencyProofs(["only"]); expect(single.has(single.binding("only"), "only")).toBe(true); expect(single.has(undefined, "only")).toBe(false); expect(() => proofs.binding("unindexed")).toThrow( "Unindexed semantic dependency", ); });