Files
rea/src/domain/javascript/javascriptSourceParser.test.ts
T
星闌 de9371b85d fix(javascript): preserve effective child-process stdio options (#4336)
* fix(javascript): preserve effective child-process stdio options

* fix(javascript): retain proven callbacks and primitive stdio keys

* fix(javascript): preserve argv shapes and nullish spreads

* fix(javascript): bound callable proofs and retain exposed binding uncertainty

* test(javascript): keep callback acceptance within transport budget

* test(javascript): inspect application coverage for callback proof limits

* fix(javascript): keep spread command argument slots uncertain

* fix(javascript): bound mapped argument content proofs

* fix(javascript): distinguish erased declarations from runtime shadows

* fix(javascript): prove runtime module context before binding isolation

* fix(javascript): share erased declaration and opaque scope proofs

* fix(javascript): keep lowered enum scopes opaque

* fix(javascript): narrow stdio proofs and consolidate regressions

* perf(javascript): reuse lexical references for child shapes

* fix(javascript): retain CommonJS child argument context

* fix(javascript): keep Annex B affected child arguments unknown

* fix(javascript): recognize value import-equals runtime modules

* fix(javascript): retain exact stdio through module and primitive syntax

* fix(javascript): bound inline spread property resolution

* fix(javascript): distinguish copied methods from getters
2026-10-17 15:51:55 +08:00

88 lines
3.7 KiB
TypeScript

import { expect, it } from "vitest";
import * as t from "@babel/types";
import {
parseJavaScriptSource,
parseRecoveredJavaScript,
parserPluginsForPath,
javaScriptRuntimeContext,
} from "./javascriptSourceParser.js";
import { analyzeParsedJavaScriptStaticSource } from "./javascriptStaticAnalysis.js";
it.each([
['import type {T} from "example";', "fixture.cts", "commonjs"],
['import type {T} from "example";', "fixture.mts", "module"],
['import type {T} from "example";', "fixture.ts", "unknown"],
['import cp = require("node:child_process");', "fixture.ts", "module"],
['import type cp = require("node:child_process");', "fixture.ts", "unknown"],
["const value=[]; export = value;", "fixture.ts", "commonjs"],
['export type {T} from "example";', "fixture.ts", "unknown"],
['import {type T} from "example";', "fixture.ts", "unknown"],
['export {type T} from "example";', "fixture.ts", "unknown"],
["export declare const value: unknown;", "fixture.ts", "unknown"],
["export default function f(): void;", "fixture.ts", "unknown"],
["export default interface I {}", "fixture.ts", "unknown"],
["export default function f() {}", "fixture.ts", "module"],
["export default class C {}", "fixture.ts", "module"],
['import {} from "example";', "fixture.js", "module"],
['import {} from "example";', "fixture.cjs", "commonjs"],
["export {};", "fixture.ts", "module"],
["const value = 1;", "fixture.mjs", "module"],
["const value = 1;", "fixture.js", "unknown"],
["const value = 1;", "fixture.cjs", "commonjs"],
["const value = 1;", "fixture.cts", "commonjs"],
["declare const value: unknown;", "fixture.d.cts", "unknown"],
] as const)(
"keeps runtime context consistent across parser entries: %s (%s)",
(source, path, context) => {
const parsed = parseJavaScriptSource(source, path);
if (parsed === null) throw new Error("Expected parsed source");
const recovered = parseRecoveredJavaScript(source, path, {
plugins: parserPluginsForPath(path),
}).file;
expect(javaScriptRuntimeContext(parsed.program)).toBe(context);
expect(javaScriptRuntimeContext(recovered.program)).toBe(context);
expect(javaScriptRuntimeContext(t.cloneNode(parsed.program, true))).toBe(
"unknown",
);
},
);
const analyze = (source: string, path: string) => {
const parsed = parseJavaScriptSource(source, path);
return parsed === null
? null
: {
errors: parsed.errors.length,
facts: analyzeParsedJavaScriptStaticSource(source, parsed),
};
};
it("parses conditional arrow bodies in JavaScript sources with JavaScript grammar", () => {
// Bundlers emit this shape; TypeScript reads `):H=>` as a return type.
const source = `const {ipcMain}=require("electron");
const pick=n===0?H=>({start:H.startY}):H=>({start:H.startX});
ipcMain.handle("layout:ready",()=>pick);`;
for (const path of ["main.js", "main.cjs", "main.mjs", "main.jsx"]) {
const result = analyze(source, path);
expect(result?.errors).toBe(0);
expect(result?.facts.electron.ipc).toContainEqual(
expect.objectContaining({ channel: "layout:ready", operation: "handle" }),
);
}
});
it("keeps JavaScript comparison meaning for angle brackets in JavaScript sources", () => {
const source = `const a=fetch<limit>("/api/compare");`;
expect(analyze(source, "main.js")?.facts.endpoints).toEqual([]);
expect(analyze(source, "main.ts")?.facts.endpoints).toContainEqual(
expect.objectContaining({ value: "/api/compare" }),
);
});
it("keeps TypeScript syntax available for TypeScript and unnamed sources", () => {
const source = "let count: number = 1; export type Id = string;";
expect(parseJavaScriptSource(source, "value.ts")?.errors).toEqual([]);
expect(parseJavaScriptSource(source)?.errors).toEqual([]);
});