Files
reverse-engineering-anything/src/domain/javascript/javascriptSemanticAmbientWrites.test.ts
T
morluto f91b7f8009 fix(javascript): distinguish resolver discovery from module loading
Preserve load and resolve operations through semantic facts, worker transfer and graph Evidence. Only loads propagate executable ownership. Project ambient member writes and escapes through the shared path- and site-aware mutation owner; retain source literals, bases and uncertainty. Cover ownership and mutation boundaries through CLI and MCP.
2026-10-24 02:35:59 +08:00

131 lines
4.5 KiB
TypeScript

import { expect, it } from "vitest";
import { analyzeJavaScriptStaticSource } from "./javascriptStaticAnalysis.js";
import {
indexJavaScriptBindingsSteps,
indexJavaScriptBindingsWithReceiversSteps,
} from "./javascriptSemanticAnalysis.js";
import { completeSemanticSteps } from "./javascriptSemanticTraversal.js";
import { parseJavaScriptSource } from "./javascriptSourceParser.js";
it("keeps wrapper module aliases distinct from global-object module properties", () => {
const parsed = parseJavaScriptSource(
`
const wrapper = module;
Object.defineProperty(wrapper, "exports", { value: exports });
Object.defineProperty(globalThis.module, "exports", { value: exports });
`,
"app.cjs",
);
if (parsed === null) throw new Error("Expected parsed source");
const state = completeSemanticSteps(
indexJavaScriptBindingsSteps(parsed.program),
);
expect(state.ambientWriteEffects.map(({ path }) => path)).toEqual([
["commonjs-module", "exports"],
["global", "module", "exports"],
]);
});
it.each([
["const copy={...module};consume(copy);", false],
["const copy={...{child:module}};consume(copy);", true],
[
"const original={child:module};const copy={...original};consume(copy);",
true,
],
])(
"exposes copied children without escaping the source container: %s",
(body, moduleEscaped) => {
const parsed = parseJavaScriptSource(`function copy(){${body}}`);
if (parsed === null) throw new Error("Expected copied escape fixture");
const state = completeSemanticSteps(
indexJavaScriptBindingsSteps(parsed.program),
);
expect(
state.ambientEscapeEffects.some(
({ path }) =>
path.length === 2 &&
path[0] === "commonjs-module" &&
path[1] === null,
),
).toBe(moduleEscaped);
},
);
it.each([
{
name: "reconverging projections with different alias-cycle histories",
setup: `var x; const a = { foo: x, bar: globalThis }; x = a.bar;
const y = flag ? x : a.foo; y.URL = replacement;`,
specifier: null,
},
{
name: "growing self-reference projections with an ambient initializer",
setup: `let alias = globalThis; alias = alias.globalThis;
alias.URL = replacement;`,
specifier: null,
},
{
name: "distinct properties selecting both ambient identities",
setup: `const box = { left: globalThis, right: import.meta };
const selected = flag ? box.left : box.right; selected.URL = replacement;`,
specifier: null,
},
{
name: "cyclic containers with a reachable ambient property",
setup: `var alias; const box = { next: alias, target: import.meta };
alias = box; const selected = flag ? alias.target : alias.next.target;
selected.url = "file:///other/entry.mjs";`,
specifier: null,
},
{
name: "cycles containing no ambient identity",
setup: `var box; box = { next: box };
const selected = flag ? box : box.next; selected.URL = replacement;`,
specifier: "./worker.js",
},
{
name: "unrelated writes through widened self-reference projections",
setup: `let alias = globalThis; alias = alias.globalThis;
alias.unrelated = replacement;`,
specifier: "./worker.js",
},
{
name: "an exact empty projection into a shallow copy",
setup: `const copy = { ...globalThis };
const selected = flag ? copy : copy; selected.URL = replacement;`,
specifier: "./worker.js",
},
])("preserves $name", ({ setup, specifier }) => {
const source = `import { Worker } from "node:worker_threads";
${setup}
new Worker(new URL("./worker.js", import.meta.url));`;
const worker = analyzeJavaScriptStaticSource(source).references.find(
(reference) => reference.kind === "worker",
);
expect(worker?.specifier).toBe(specifier);
});
it("retains getter-derived ambient escapes once per invoked read site", () => {
const source = `const box={loader:require,get trigger(){this.loader.resolve=this.loader;return 0}};
box.trigger;
box.trigger;`;
const parsed = parseJavaScriptSource(source);
if (parsed === null) throw new Error("Expected getter fixture");
const index = completeSemanticSteps(
indexJavaScriptBindingsWithReceiversSteps(parsed.program),
);
completeSemanticSteps(index.indexMemberMutationFactsSteps());
const effects = index.bindings.ambientEscapeEffects.filter(
({ path }) =>
JSON.stringify(path) === JSON.stringify(["global", "require", null]),
);
expect(
effects.map(({ node }) =>
node === undefined ? null : source.slice(node.start ?? 0, node.end ?? 0),
),
).toEqual(["box.trigger", "box.trigger"]);
expect(effects[0]?.node).not.toBe(effects[1]?.node);
});