rea/tests/javascriptExportInstrumenta...

84 lines
2.5 KiB
TypeScript

import { createHash } from "node:crypto";
import { describe, expect, it } from "vitest";
import { instrumentJavaScriptExport } from "../src/domain/javascriptExportInstrumentation.js";
const encode = (value: string): Uint8Array => new TextEncoder().encode(value);
const sha256 = (value: Uint8Array): string =>
createHash("sha256").update(value).digest("hex");
describe("JavaScript export instrumentation", () => {
it.each([
[
"plain",
"const hidden = (value) => value.trim();",
"(value) => value.trim()",
],
["minified", "const x=a=>a+1,y=2;", "a=>a+1"],
[
"bundle",
"(()=>{const registry={7:(m)=>m.exports=(x)=>x*2};globalThis.r=registry})()",
"(x)=>x*2",
],
])(
"deterministically exposes one exact %s expression",
(_name, text, selectedText) => {
const source = encode(text);
const original = source.slice();
const start = text.indexOf(selectedText);
const selected = encode(selectedText);
const input = {
artifact_path: "/approved/app.js",
artifact_sha256: sha256(source),
selection: {
byte_start: start,
byte_end: start + selected.byteLength,
selected_sha256: sha256(selected),
export_name: "selected",
},
};
const first = instrumentJavaScriptExport(source, input);
const second = instrumentJavaScriptExport(source, input);
expect(first).toEqual(second);
expect(source).toEqual(original);
expect(first.manifest).toMatchObject({
original_sha256: sha256(source),
instrumented_sha256: sha256(first.bytes),
output_format: "commonjs-factory",
inserted_ranges: [
{ purpose: "factory-prefix" },
{ purpose: "export-binding" },
{ purpose: "factory-suffix" },
],
});
},
);
it("rejects stale artifacts and ambiguous caller-selected bytes", () => {
const source = encode("const hidden = () => 1;");
const input = {
artifact_path: "/approved/app.js",
artifact_sha256: "0".repeat(64),
selection: {
byte_start: 15,
byte_end: 22,
selected_sha256: "1".repeat(64),
export_name: "hidden",
},
};
expect(() => instrumentJavaScriptExport(source, input)).toThrow(
/artifact digest mismatch/u,
);
expect(() =>
instrumentJavaScriptExport(source, {
...input,
artifact_sha256: sha256(source),
}),
).toThrow(/selection digest mismatch/u);
});
});