mirror of
https://github.com/vercel-labs/scriptc.git
synced 2026-10-02 08:35:07 +08:00
Keep self-hosting test workers responsive during compilation
- Run runtime-pack and native-toolchain compiler passes in child processes. - Preserve static coverage and native behavior assertions without relying on an unsupported RPC timeout setting.
This commit is contained in:
@@ -22,8 +22,6 @@ jobs:
|
||||
# calling onTaskUpdate") with every test green — the same contention
|
||||
# artifact the harness README documents for local parallel suites.
|
||||
SCRIPTC_TEST_WORKERS: "4"
|
||||
# Native self-hosting analysis can block worker RPC during lowering.
|
||||
VITEST_RPC_TIMEOUT: "180000"
|
||||
# san = ASan + RC audit over the same suite; anything but "1" is plain.
|
||||
SCRIPTC_SAN: ${{ matrix.flavor == 'san' && '1' || '' }}
|
||||
# Within-file partition for the large case-driven harnesses
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
import { execFile } from "node:child_process";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import { promisify } from "node:util";
|
||||
import type { AnalyzeOptions, CompileOptions, CompileExecutableResult, CoverageInput } from "@scriptc/compiler";
|
||||
|
||||
const execFileAsync = promisify(execFile);
|
||||
const root = fileURLToPath(new URL("../../", import.meta.url));
|
||||
const api = new URL("../../packages/compiler/src/index.ts", import.meta.url).href;
|
||||
|
||||
// Large synchronous frontend passes must leave Vitest's worker RPC responsive.
|
||||
// Execute the source API in a child and return only JSON-compatible results.
|
||||
async function compilerProcess(operation: "analyze" | "compile", entry: string, options: object): Promise<unknown> {
|
||||
const { stdout, stderr } = await execFileAsync(process.execPath, [
|
||||
"--max-old-space-size=8192", "--import", "tsx", "--input-type=module", "--eval",
|
||||
`import { analyze, compile } from ${JSON.stringify(api)};
|
||||
const options = JSON.parse(process.argv[3]);
|
||||
const result = process.argv[1] === 'analyze'
|
||||
? analyze(process.argv[2], options).coverage
|
||||
: await compile(process.argv[2], options);
|
||||
console.log(JSON.stringify(result, (key, value) => key === 'sourceTexts' ? undefined : value));`,
|
||||
operation, entry, JSON.stringify(options),
|
||||
], { cwd: root, timeout: 300_000, maxBuffer: 16 * 1024 * 1024 });
|
||||
if (stderr !== "") throw new Error(stderr);
|
||||
return JSON.parse(stdout);
|
||||
}
|
||||
|
||||
export async function analyzeInChild(entry: string, options: AnalyzeOptions): Promise<CoverageInput> {
|
||||
return await compilerProcess("analyze", entry, options) as CoverageInput;
|
||||
}
|
||||
|
||||
type ExecutableResult =
|
||||
| Extract<CompileExecutableResult, { ok: true }>
|
||||
| Omit<Extract<CompileExecutableResult, { ok: false }>, "sourceTexts">;
|
||||
|
||||
export async function compileInChild(entry: string, options: CompileOptions): Promise<ExecutableResult> {
|
||||
return await compilerProcess("compile", entry, options) as ExecutableResult;
|
||||
}
|
||||
@@ -4,7 +4,7 @@ import { existsSync, mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync
|
||||
import { tmpdir } from "node:os";
|
||||
import { join } from "node:path";
|
||||
import { expect, test } from "vitest";
|
||||
import { analyze, compile } from "@scriptc/compiler";
|
||||
import { analyzeInChild, compileInChild } from "./self-hosting-compiler-process.js";
|
||||
import { nativeCodegenTarget } from "../../packages/compiler/src/backend/targets.js";
|
||||
import type { NativeLinkFeatures } from "../../packages/compiler/src/backend/native-link-info.js";
|
||||
import type { RuntimePackManifest } from "../../packages/compiler/src/backend/runtime-pack-core.js";
|
||||
@@ -20,8 +20,8 @@ const features: NativeLinkFeatures = {
|
||||
http2: false, dgram: false, watch: false, foreignFfi: false, nodeTest: false, tls: false, tlsCa: false,
|
||||
};
|
||||
|
||||
test("native toolchain configuration, staging and helper validation are static", () => {
|
||||
const { coverage } = analyze(entry, { dynamic: false });
|
||||
test("native toolchain configuration, staging and helper validation are static", async () => {
|
||||
const coverage = await analyzeInChild(entry, { dynamic: false });
|
||||
expect(coverage.preflightFailed).toBe(false);
|
||||
expect(coverage.stats.statementsFailed).toBe(0);
|
||||
expect(coverage.stats.statementsIsland).toBe(0);
|
||||
@@ -33,7 +33,7 @@ for (const backend of ["llvm"] as const) {
|
||||
const directory = mkdtempSync(join(process.platform === "win32" ? tmpdir() : "/tmp", "scriptc-native-integrity-"));
|
||||
const target = nativeCodegenTarget()!;
|
||||
try {
|
||||
const built = await compile(entry, {
|
||||
const built = await compileInChild(entry, {
|
||||
outDir: directory, outPath: join(directory, "toolchain" + target.outputSuffixes.exe),
|
||||
backend, optimization: "dev", dynamic: false, sanitize: process.env["SCRIPTC_SAN"] === "1",
|
||||
});
|
||||
|
||||
@@ -3,7 +3,7 @@ import { mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
||||
import { tmpdir } from "node:os";
|
||||
import { join } from "node:path";
|
||||
import { expect, test } from "vitest";
|
||||
import { analyze, compile } from "@scriptc/compiler";
|
||||
import { analyzeInChild, compileInChild } from "./self-hosting-compiler-process.js";
|
||||
import { NATIVE_TARGETS, nativeCodegenTarget } from "../../packages/compiler/src/backend/targets.js";
|
||||
import type { NativeLinkFeatures } from "../../packages/compiler/src/backend/native-link-info.js";
|
||||
import type { RuntimePackManifest } from "../../packages/compiler/src/backend/runtime-pack-core.js";
|
||||
@@ -18,8 +18,8 @@ const base: NativeLinkFeatures = {
|
||||
http2: false, dgram: false, watch: false, foreignFfi: false, nodeTest: false, tls: false, tlsCa: false,
|
||||
};
|
||||
|
||||
test("runtime manifest validation and selection are entirely static", () => {
|
||||
const { coverage } = analyze(entry, { dynamic: false });
|
||||
test("runtime manifest validation and selection are entirely static", async () => {
|
||||
const coverage = await analyzeInChild(entry, { dynamic: false });
|
||||
expect(coverage.preflightFailed).toBe(false);
|
||||
expect(coverage.stats.statementsTotal).toBeGreaterThan(50);
|
||||
expect(coverage.stats.statementsFailed).toBe(0);
|
||||
@@ -31,7 +31,7 @@ for (const backend of ["llvm"] as const) {
|
||||
test(`native runtime manifest selection matches Node (${backend})`, async () => {
|
||||
const directory = mkdtempSync(join(process.platform === "win32" ? tmpdir() : "/tmp", "scriptc-pack-selection-"));
|
||||
try {
|
||||
const built = await compile(entry, {
|
||||
const built = await compileInChild(entry, {
|
||||
outDir: directory, outPath: join(directory, "selection" + (process.platform === "win32" ? ".exe" : "")),
|
||||
backend, dynamic: false, optimization: "dev", sanitize: process.env["SCRIPTC_SAN"] === "1",
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user