mirror of
https://github.com/vercel-labs/scriptc.git
synced 2026-10-22 05:59:31 +08:00
- Enforce oxlint and oxfmt for owned JavaScript and TypeScript with independent CI checks. - Preserve compiler import boundaries and protected fixtures while cleaning up lint findings. - Standardize source formatting and validate import, fixture, and embedded-source protections.
136 lines
5.9 KiB
TypeScript
136 lines
5.9 KiB
TypeScript
import { execFile } from "node:child_process";
|
|
import { cpSync, mkdirSync, mkdtempSync, rmSync, symlinkSync, writeFileSync } from "node:fs";
|
|
import { tmpdir } from "node:os";
|
|
import { dirname, join } from "node:path";
|
|
import { promisify } from "node:util";
|
|
import { expect, test } from "vitest";
|
|
import { analyze, compile } from "@scriptc/compiler";
|
|
|
|
const execFileAsync = promisify(execFile);
|
|
const corpus = join(import.meta.dirname, "../corpus");
|
|
const sanitize = process.env["SCRIPTC_SAN"] === "1";
|
|
|
|
test.each([
|
|
["package", "3064-installed-entry-imports", "main.ts"],
|
|
["@scope/package", "3064-installed-entry-imports", "main.ts"],
|
|
["outer/node_modules/package", "3064-installed-entry-imports", "main.ts"],
|
|
["package", "3065-installed-entry-js", "main.js"],
|
|
["@scope/package", "3065-installed-entry-js", "main.js"],
|
|
])("explicit entry in node_modules/%s: %s", async (name, fixture, entryName) => {
|
|
const dir = mkdtempSync(join(tmpdir(), "scriptc-installed-entry-"));
|
|
try {
|
|
const original = join(corpus, fixture);
|
|
const installed = join(dir, "node_modules", name);
|
|
cpSync(original, installed, { recursive: true });
|
|
const entry = join(installed, entryName);
|
|
// Node refuses native TS stripping inside node_modules. Its oracle
|
|
// runs the identical source tree at the original corpus location.
|
|
const oracle = await execFileAsync(process.execPath, [join(original, entryName)]);
|
|
for (const backend of ["llvm"] as const) {
|
|
const outDir = join(dir, backend);
|
|
const built = await compile(entry, {
|
|
outDir,
|
|
outPath: join(outDir, "program"),
|
|
backend,
|
|
sanitize,
|
|
});
|
|
expect(built.ok, !built.ok ? JSON.stringify(built.diagnostics) : "").toBe(true);
|
|
if (!built.ok) continue;
|
|
const native = await execFileAsync(built.binaryPath);
|
|
expect(native.stdout).toBe(oracle.stdout);
|
|
expect(native.stderr).toBe(oracle.stderr);
|
|
}
|
|
for (const dynamic of [false, true]) {
|
|
const { coverage } = analyze(entry, { dynamic });
|
|
expect(coverage.preflightFailed).toBe(false);
|
|
expect(coverage.diagnostics).toEqual([]);
|
|
expect(coverage.stats.statementsFailed).toBe(0);
|
|
expect(coverage.stats.statementsIsland).toBe(0);
|
|
}
|
|
} finally {
|
|
rmSync(dir, { recursive: true, force: true });
|
|
}
|
|
});
|
|
|
|
test.each([
|
|
["dependency", "package/node_modules/dependency", "dependency"],
|
|
["package-extra", "package-extra", "package-extra"],
|
|
["relative dependency", "package/node_modules/dependency", "./node_modules/dependency/index.js"],
|
|
])("installed entry keeps %s on the npm boundary", (label, dependencyPath, specifier) => {
|
|
const dir = mkdtempSync(join(tmpdir(), "scriptc-installed-entry-dependency-"));
|
|
try {
|
|
const entry = join(dir, "node_modules/package/main.ts");
|
|
const dependency = join(dir, "node_modules", dependencyPath);
|
|
mkdirSync(dirname(entry), { recursive: true });
|
|
mkdirSync(dependency, { recursive: true });
|
|
writeFileSync(join(dirname(entry), "package.json"), '{"type":"module"}\n');
|
|
writeFileSync(
|
|
join(dependency, "package.json"),
|
|
JSON.stringify({ type: "module", main: "index.js", types: "index.d.ts" }),
|
|
);
|
|
writeFileSync(join(dependency, "index.d.ts"), "export declare const value: number;\n");
|
|
writeFileSync(join(dependency, "index.js"), "export const value = 42;\n");
|
|
writeFileSync(
|
|
entry,
|
|
`import { value } from ${JSON.stringify(specifier)}; ` + "console.log(`value ${value}`);\n",
|
|
);
|
|
const withoutIsland = analyze(entry).coverage;
|
|
expect(withoutIsland.preflightFailed, label).toBe(false);
|
|
expect(new Set(withoutIsland.diagnostics.map((d) => d.code)), label).toEqual(
|
|
new Set(["SC2013"]),
|
|
);
|
|
const withIsland = analyze(entry, { dynamic: true }).coverage;
|
|
expect(withIsland.diagnostics, label).toEqual([]);
|
|
expect(withIsland.stats.statementsIsland, label).toBeGreaterThan(0);
|
|
} finally {
|
|
rmSync(dir, { recursive: true, force: true });
|
|
}
|
|
});
|
|
|
|
test("installed entry ownership follows a linked package's source graph", async () => {
|
|
const dir = mkdtempSync(join(tmpdir(), "scriptc-installed-entry-link-"));
|
|
try {
|
|
const original = join(corpus, "3065-installed-entry-js");
|
|
const source = join(dir, "source");
|
|
cpSync(original, source, { recursive: true });
|
|
mkdirSync(join(dir, "node_modules"));
|
|
symlinkSync(
|
|
source,
|
|
join(dir, "node_modules/package"),
|
|
process.platform === "win32" ? "junction" : "dir",
|
|
);
|
|
const entry = join(dir, "node_modules/package/main.js");
|
|
const outDir = join(dir, "out");
|
|
const built = await compile(entry, { outDir, outPath: join(outDir, "program"), sanitize });
|
|
expect(built.ok, !built.ok ? JSON.stringify(built.diagnostics) : "").toBe(true);
|
|
if (!built.ok) return;
|
|
const [native, node] = await Promise.all([
|
|
execFileAsync(built.binaryPath),
|
|
execFileAsync(process.execPath, [entry]),
|
|
]);
|
|
expect(native.stdout).toBe(node.stdout);
|
|
expect(native.stderr).toBe(node.stderr);
|
|
} finally {
|
|
rmSync(dir, { recursive: true, force: true });
|
|
}
|
|
});
|
|
|
|
test("explicit installed JavaScript entry keeps diagnostics in its own modules", () => {
|
|
const dir = mkdtempSync(join(tmpdir(), "scriptc-installed-entry-errors-"));
|
|
try {
|
|
const entry = join(dir, "node_modules/package/main.js");
|
|
mkdirSync(dirname(entry), { recursive: true });
|
|
writeFileSync(join(dirname(entry), "package.json"), '{"type":"module"}\n');
|
|
writeFileSync(entry, 'import { value } from "./value.js"; console.log(value);\n');
|
|
writeFileSync(join(dirname(entry), "value.js"), "export const value = missingName;\n");
|
|
const { coverage } = analyze(entry);
|
|
expect(coverage.preflightFailed).toBe(true);
|
|
expect(coverage.diagnostics.map((d) => d.code)).toEqual(["SC0001"]);
|
|
expect(coverage.diagnostics[0]?.loc.file.replaceAll("\\", "/")).toBe(
|
|
join(dirname(entry), "value.js").replaceAll("\\", "/"),
|
|
);
|
|
} finally {
|
|
rmSync(dir, { recursive: true, force: true });
|
|
}
|
|
});
|