Files
scriptc/tests/harness/code-quality.test.ts
T
Chris Tate 9abf35f6a2 Build the large compiler tables on first use
The native compiler ran four large module initializers at every startup:
the builtin call signatures (LIB_FN_SIGS), the Node 24 fetch
compatibility profile, and the builtin module function and ambient
surface tables. Together their init functions are about 1.3 MB of code,
and --version and warm cache-hit builds paged them in and built the
tables without reading them.

Each table is now built by a function on its first call and kept in a
module variable:

- libFnSignatures() replaces LIB_FN_SIGS
- node24FetchCompatProfile() and staticFetchMembers() replace
  NODE24_FETCH_COMPAT_PROFILE and the STATIC_* member sets
- builtinModuleFns() and ambientSurfaceFns() replace BUILTIN_MODULE_FNS
  and AMBIENT_SURFACE_FNS

The @scriptc/compiler entry point keeps LIB_FN_SIGS and
NODE24_FETCH_COMPAT_PROFILE as deprecated constants built from the new
functions when the entry module loads. The native compiler does not load
that module.

The surface manifest's coverage notes read the fetch target through the
profile function, so building the manifest module no longer builds the
profile. The table contents are unchanged.
2026-10-25 05:23:35 -05:00

171 lines
7.5 KiB
TypeScript

import { spawnSync } from "node:child_process";
import { copyFileSync, mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs";
import { tmpdir } from "node:os";
import { dirname, join } from "node:path";
import { fileURLToPath } from "node:url";
import { afterEach, expect, test } from "vitest";
const root = fileURLToPath(new URL("../..", import.meta.url));
const temporary: string[] = [];
afterEach(() => {
for (const path of temporary.splice(0)) rmSync(path, { recursive: true, force: true });
});
function workspace(): string {
const path = mkdtempSync(join(tmpdir(), "scriptc-code-quality-"));
temporary.push(path);
for (const config of [".oxlintrc.jsonc", ".oxfmtrc.jsonc"]) {
copyFileSync(join(root, config), join(path, config));
}
return path;
}
function source(work: string, name: string, text: string): void {
const path = join(work, name);
mkdirSync(dirname(path), { recursive: true });
writeFileSync(path, text);
}
function run(tool: "oxlint" | "oxfmt", work: string, args: string[]) {
const result = spawnSync(
process.execPath,
[join(root, "node_modules", tool, "bin", tool), ...args],
{
cwd: work,
encoding: "utf8",
timeout: 30_000,
},
);
expect(result.error).toBeUndefined();
expect(result.signal).toBeNull();
return result;
}
test("compiler import fences reject cross-layer and cross-parser imports", () => {
const work = workspace();
const cases = [
["packages/compiler/src/backend/probe.ts", "../frontend/program.js"],
["packages/compiler/src/backend/native/driver.ts", "../native-toolchain.js"],
["packages/compiler/src/backend/native/contracts.ts", "../../frontend/program.js"],
["packages/compiler/src/backend/native/tool-identity.ts", "typescript5"],
["packages/compiler/src/frontend/probe.ts", "../backend/llvm/emitter.js"],
["packages/compiler/src/frontend/lowering/probe.ts", "../../ir/validate.js"],
["packages/compiler/src/frontend/cjs-lexer.ts", "../ir/validate.js"],
["packages/compiler/src/ir/probe.ts", "typescript5"],
["packages/compiler/src/frontend/ts7/probe.ts", "typescript5/lib/typescript.js"],
["packages/compiler/src/frontend/npm.ts", "../backend/llvm/emitter.js"],
["packages/compiler/src/frontend/lowering/call-arguments.ts", "./lower-calls.js"],
["packages/compiler/src/frontend/lowering/call-signatures.ts", "../../ir/validate.js"],
["packages/compiler/src/frontend/lowering/generic-functions.ts", "../../backend/targets.js"],
["packages/compiler/src/frontend/lowering/native-ffi.ts", "typescript5"],
["packages/compiler/src/frontend/lowering/containers/array-callbacks.ts", "./array-methods.js"],
[
"packages/compiler/src/frontend/lowering/containers/callback-arguments.ts",
"../../../ir/validate.js",
],
[
"packages/compiler/src/frontend/lowering/containers/indexed-objects.ts",
"../../../backend/targets.js",
],
["packages/compiler/src/frontend/lowering/containers/for-of.ts", "typescript5"],
["packages/compiler/src/frontend/lowering/builtins/filesystem.ts", "./module-calls.js"],
["packages/compiler/src/frontend/lowering/builtins/arguments.ts", "../../../ir/validate.js"],
["packages/compiler/src/frontend/lowering/builtins/crypto.ts", "../../../backend/targets.js"],
["packages/compiler/src/frontend/lowering/builtins/module-bindings.ts", "typescript5"],
] as const;
for (const [name, specifier] of cases)
source(work, name, `export { value } from "${specifier}";\n`);
const result = run("oxlint", work, ["--format=json", "packages"]);
expect(result.status).toBe(1);
const report = JSON.parse(result.stdout) as { diagnostics: { code: string; filename: string }[] };
expect(report.diagnostics).toHaveLength(cases.length);
expect(report.diagnostics.every((d) => d.code === "eslint(no-restricted-imports)")).toBe(true);
expect(report.diagnostics.map((d) => d.filename.replaceAll("\\", "/")).sort()).toEqual(
cases.map(([name]) => name).sort(),
);
});
test("IR imports and the explicit parser islands remain usable", () => {
const work = workspace();
source(work, "packages/compiler/src/backend/probe.ts", 'export { value } from "../ir/ir.js";\n');
source(work, "packages/compiler/src/frontend/probe.ts", 'export { value } from "../ir/ir.js";\n');
source(
work,
"packages/compiler/src/frontend/lowering/probe.ts",
'export { libFnSignatures } from "../../ir/builtin-signatures.js";\nexport { STR_INTRINSIC_SIGS } from "../../ir/intrinsic-signatures.js";\n',
);
source(
work,
"packages/compiler/src/frontend/lowering/call-arguments.ts",
'export { funcTypeFromParamShapes } from "./call-signatures.js";\n',
);
source(
work,
"packages/compiler/src/frontend/lowering/containers/array-construction.ts",
'export { lowerArrayCallback } from "./callback-arguments.js";\n',
);
source(
work,
"packages/compiler/src/frontend/lowering/builtins/crypto.ts",
'export { lowerBuiltinByteInput } from "./arguments.js";\n',
);
for (const name of [
"frontend/npm.ts",
"frontend/cjs-lexer.ts",
"frontend/comptime-node.ts",
"frontend/ts7/world-check.ts",
"frontend/ts7/source-parser.test.ts",
"frontend/npm-static-rewrite.ts",
"frontend/npm-static-bundled-cjs.ts",
"library/semantic-source.ts",
])
source(work, `packages/compiler/src/${name}`, 'export { value } from "typescript5";\n');
const result = run("oxlint", work, ["--deny-warnings", "packages"]);
expect(result.status, result.stdout + result.stderr).toBe(0);
});
test("fixture and generated exclusions protect invalid input while normal code is checked", () => {
const work = workspace();
const excluded = [
"tests/corpus/bad.ts",
"tests/diagnostics/bad.ts",
"tests/fixtures/bad.ts",
"packages/compiler/test/fixtures/bad.ts",
"packages/compiler/src/frontend/ts7/probe.generated.ts",
"packages/runtime/vendor/bad.js",
"packages/compiler/dist/bad.js",
"docs/src/probe.ts",
];
const invalid = "export const = deliberately invalid\n";
for (const name of excluded) source(work, name, invalid);
source(work, "scripts/probe.mjs", "const unused = 1;\n");
const lint = run("oxlint", work, ["--format=json", "."]);
expect(lint.status).toBe(1);
const diagnostics = JSON.parse(lint.stdout).diagnostics as { code: string; filename: string }[];
expect(
diagnostics.map((d) => ({ ...d, filename: d.filename.replaceAll("\\", "/") })),
).toMatchObject([{ code: "eslint(no-unused-vars)", filename: "scripts/probe.mjs" }]);
const format = run("oxfmt", work, ["--write", "**/*.{ts,js,mjs}"]);
expect(format.status, format.stdout + format.stderr).toBe(0);
for (const name of excluded) expect(readFileSync(join(work, name), "utf8")).toBe(invalid);
});
test("formatting keeps source payloads and import order and reaches a stable result", () => {
const work = workspace();
const name = "tests/harness/probe.ts";
const payload = "function bad( {\n";
source(
work,
name,
'import "./z.js";\nimport "./a.js";\nexport const code=String.raw`' + payload + "`;\n",
);
expect(run("oxfmt", work, ["--check", name]).status).toBe(1);
const formatted = run("oxfmt", work, ["--write", name]);
expect(formatted.status, formatted.stdout + formatted.stderr).toBe(0);
const result = readFileSync(join(work, name), "utf8");
expect(result).toContain("String.raw`" + payload + "`");
expect(result.indexOf('import "./z.js"')).toBeLessThan(result.indexOf('import "./a.js"'));
expect(run("oxfmt", work, ["--check", name]).status).toBe(0);
});