mirror of
https://github.com/vercel-labs/scriptc.git
synced 2026-11-01 07:33:12 +08:00
Calls into Node now run on one dedicated 64 MB stack with a guard page, reached by a context switch, and the bridge sets V8's stack limit on it (bridge ABI 2). Before, a call from an async fiber (512 KB stacks without a guard page) failed to bootstrap Node, which the dev-mode LLVM differential showed. The runtime's stack guard follows the switch, and the switch carries ASan's fiber annotations. The Node island tests load Node from a libnode pack. Until the NI-13 packs are published, .github/actions/libnode-dev-pack assembles one for the Linux x64 test lanes (plain and sanitized): a pinned, checksum-verified prebuilt libnode of the repository's Node release (24.22.0) and Node's official headers (packages/libnode-common/dev-pack.json), with the bridge built against them by build-pack.mjs. The pack is cached by its inputs and the bridge source, so only a cache miss downloads and builds; the normal build path never does. tests/harness/libnode.ts makes a missing pack a failure in those lanes: island tests skip only off Linux x64 CI without a configured pack. The bridge smoke test (packages/libnode-common/test/bridge-smoke.c) loads the pack the way scr_node_island.c does and makes synchronous, throwing and asynchronous calls through the bridge with the runtime's bootstrap. IR, LLVM and object outputs of programs that call into Node no longer need a pack at build time; only executables record one. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
59 lines
2.2 KiB
JavaScript
59 lines
2.2 KiB
JavaScript
#!/usr/bin/env node
|
|
/* Assembles a development libnode pack from the pinned, checksum-verified
|
|
* inputs in dev-pack.json: a prebuilt libnode of the repository's Node
|
|
* release and Node's official headers, with the bridge built against them
|
|
* by build-pack.mjs. CI's Linux test lanes use it (.github/actions/
|
|
* libnode-dev-pack) until the NI-13 packs are published.
|
|
*
|
|
* node packages/libnode-common/fetch-dev-pack.mjs --out <pack directory> */
|
|
import { execFileSync } from "node:child_process";
|
|
import { createHash } from "node:crypto";
|
|
import { mkdirSync, mkdtempSync, readFileSync, writeFileSync } from "node:fs";
|
|
import { tmpdir } from "node:os";
|
|
import { join, resolve } from "node:path";
|
|
import { fileURLToPath } from "node:url";
|
|
import { parseArgs } from "node:util";
|
|
|
|
const here = fileURLToPath(new URL(".", import.meta.url));
|
|
const { values } = parseArgs({ options: { out: { type: "string" } } });
|
|
if (!values.out) {
|
|
console.error("usage: fetch-dev-pack.mjs --out <pack directory>");
|
|
process.exit(2);
|
|
}
|
|
const platform = `${process.platform}-${process.arch}`;
|
|
const pins = JSON.parse(readFileSync(join(here, "dev-pack.json"), "utf8"))[platform];
|
|
if (pins === undefined) {
|
|
console.error(`dev-pack.json pins no libnode for ${platform}`);
|
|
process.exit(1);
|
|
}
|
|
|
|
const work = mkdtempSync(join(tmpdir(), "scriptc-libnode-dev-"));
|
|
|
|
async function fetchVerified({ url, sha256 }, name) {
|
|
const response = await fetch(url);
|
|
if (!response.ok) throw new Error(`${url}: HTTP ${response.status}`);
|
|
const bytes = Buffer.from(await response.arrayBuffer());
|
|
const actual = createHash("sha256").update(bytes).digest("hex");
|
|
if (actual !== sha256) throw new Error(`${url}: sha256 ${actual}, expected ${sha256}`);
|
|
const path = join(work, name);
|
|
writeFileSync(path, bytes);
|
|
execFileSync("tar", ["-xzf", path, "-C", work]);
|
|
}
|
|
|
|
await fetchVerified(pins.libnode, "libnode.tar.gz");
|
|
await fetchVerified(pins.headers, "headers.tar.gz");
|
|
mkdirSync(resolve(values.out), { recursive: true });
|
|
execFileSync(
|
|
process.execPath,
|
|
[
|
|
join(here, "build-pack.mjs"),
|
|
"--libnode",
|
|
join(work, pins.libnode.file),
|
|
"--headers",
|
|
join(work, pins.headers.dir),
|
|
"--out",
|
|
resolve(values.out),
|
|
],
|
|
{ stdio: "inherit" },
|
|
);
|