Files
reverse-engineering-anything/src/domain/javascript/electronCallPathBlockPrefixes.test.ts
T
morluto 4e663beeb8 fix(javascript): retain guards after labelled breaks (#7841)
* fix(javascript): retain guards after labelled breaks

* fix(javascript): bound labelled exit inspection

* fix(javascript): preserve local break completion

* fix(javascript): avoid exits through unknown control flow

* fix(javascript): retain guards after bounded jump scan
2026-10-29 05:09:45 +08:00

97 lines
3.5 KiB
TypeScript

import * as t from "@babel/types";
import { expect, it } from "vitest";
import { ElectronCallPathBlockPrefixes } from "./electronCallPathBlockPrefixes.js";
import { parseJavaScriptSource } from "./javascriptSourceParser.js";
import { completeSemanticSteps } from "./javascriptSemanticTraversal.js";
it("indexes a real flat block once, retaining contextual guards in source order", () => {
const parsed = parseJavaScriptSource(`{
${"0;".repeat(2048)}
if (uncertain) ordinary();
if (flag) throw 0;
electron.send("tail");
}`);
const block = parsed?.program.body[0];
if (!t.isBlockStatement(block)) throw new Error("Expected parsed block");
const first = block.body[0];
const tail = block.body.at(-1);
if (first === undefined || tail === undefined)
throw new Error("Expected block statements");
let examined = 0;
const prefixes = new ElectronCallPathBlockPrefixes(() => {
examined += 1;
return true;
});
const steps = prefixes.before(block, tail);
expect(steps.next()).toEqual({ done: false, value: undefined });
expect(examined).toBe(2048);
const prefix = completeSemanticSteps(steps);
const completeVisits = examined;
expect(completeVisits).toBeGreaterThan(block.body.length);
expect(prefix).toMatchObject({
before: 2050,
entries: [
{
position: 2048,
fact: {
kind: "branch",
test: { type: "Identifier", name: "uncertain" },
consequentExits: false,
alternateExits: false,
},
},
{
position: 2049,
fact: {
kind: "branch",
test: { type: "Identifier", name: "flag" },
consequentExits: true,
alternateExits: false,
},
},
],
});
for (const statement of block.body) {
const earlier = completeSemanticSteps(prefixes.before(block, statement));
expect(earlier?.entries).toBe(prefix?.entries);
}
expect(examined).toBe(completeVisits);
expect(completeSemanticSteps(prefixes.before(block, first))?.before).toBe(0);
});
it("does not publish an incomplete block index when its work budget ends", () => {
const parsed = parseJavaScriptSource(
`{ 0; 1; if (stop) throw 0; send("tail"); }`,
);
const block = parsed?.program.body[0];
if (!t.isBlockStatement(block)) throw new Error("Expected parsed block");
const tail = block.body.at(-1);
if (tail === undefined) throw new Error("Expected terminal statement");
let remaining = 2;
const prefixes = new ElectronCallPathBlockPrefixes(() => --remaining >= 0);
expect(completeSemanticSteps(prefixes.before(block, tail))).toBeUndefined();
remaining = 100;
expect(completeSemanticSteps(prefixes.before(block, tail))).toMatchObject({
before: 3,
entries: [{ position: 2, fact: { kind: "branch" } }],
});
expect(remaining).toBeGreaterThan(0);
});
it("charges nested exit checks to the same budget and does not cache a partial index", () => {
const parsed = parseJavaScriptSource(
`{ if (x) { { { throw 0; } } } send(); }`,
);
const block = parsed?.program.body[0];
if (!t.isBlockStatement(block)) throw new Error("Expected parsed block");
const tail = block.body.at(-1);
if (tail === undefined) throw new Error("Expected terminal statement");
let remaining = 4;
const prefixes = new ElectronCallPathBlockPrefixes(() => --remaining >= 0);
expect(completeSemanticSteps(prefixes.before(block, tail))).toBeUndefined();
remaining = 100;
expect(completeSemanticSteps(prefixes.before(block, tail))).toMatchObject({
entries: [{ fact: { kind: "branch", consequentExits: true } }],
});
});