mirror of
https://github.com/vercel-labs/scriptc.git
synced 2026-11-08 08:44:37 +08:00
Node answers a BigIntStats when the stat call is passed `bigint: true`: the
same snapshot, read through a bigint member table. Every number member of
Stats reads as a bigint — the integers, the `*Ms` millisecond members (the
truncated nanosecond quotient, as the binding computes them) and the
BigIntStats-only `*Ns` nanosecond members (sec * 1e9 + nsec, exactly) —
while only the four time members stay Dates. scriptc refused the option
outright.
The representation is static, chosen by the option literal: the lowerer
validates `bigint` against the call's result type (so
`{ bigint: true, throwIfNoEntry: false }` still narrows
`BigIntStats | undefined`), refuses a runtime-valued option and an option
that disagrees with the destination, and keeps every other option key
fenced. fstatSync joins statSync/lstatSync on the same path, with the
descriptor evaluated before the options.
The IR gains a `bigintStats` handle kind beside `stats`: the same RC
family, the same non-traced leaf and non-dynamic handle treatment, so no
shape, tracing or dyn-check behavior moves for any program that never asks
for one. Its member table is a `bigstats.*` lib-call family whose Date
members reuse the existing stat reads.
The runtime support is its own unit, scr_stats_bigint.c: the snapshot
layout moved into scr_stats_private.h so the bigint getters can read the
same fields without scr_lib.c carrying their code. The unit is gated on the
existing `bigint` feature in both the runtime-pack matrix and the
compiler's from-source unit table (the sanitized lane links from that one),
and `-ffunction-sections` keeps a bigint program that never reads a member
from linking any of the getters. No typed program's IR or LLVM changes.
tests/corpus/7018-bigint-stats.ts pins the member table, the Date/bigint
split, ms/ns agreement, arithmetic on a member, lstat over a symlink,
fstatSync over a descriptor, the throwIfNoEntry union, and the plain Stats
answers of the un-optioned and `bigint: false` forms against Node.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
52 lines
2.1 KiB
TypeScript
52 lines
2.1 KiB
TypeScript
import { expect, test } from "vitest";
|
|
import { createRuntimePackMatrix } from "../runtime-pack-matrix.mjs";
|
|
|
|
const matrix = createRuntimePackMatrix({
|
|
target: { object_format: "elf" },
|
|
compileFlags: [],
|
|
systemLibraries: [],
|
|
});
|
|
|
|
/** The runtime pack's variant selection: the matching variant with the
|
|
* most conditions, ties by id. */
|
|
function selected(
|
|
source: string,
|
|
features: Record<string, boolean>,
|
|
): { id: string; defines: string[] } {
|
|
const unit = matrix.runtime_units.find((u: { source: string }) => u.source === source);
|
|
const matches = unit.variants.filter((variant: { when: Record<string, boolean> }) =>
|
|
Object.entries(variant.when).every(([name, expected]) => features[name] === expected),
|
|
);
|
|
matches.sort(
|
|
(a: { when: object; id: string }, b: { when: object; id: string }) =>
|
|
Object.keys(b.when).length - Object.keys(a.when).length || a.id.localeCompare(b.id),
|
|
);
|
|
return matches[0];
|
|
}
|
|
|
|
test("web streams and Node islands select an async build that defines both", () => {
|
|
const variant = selected("scr_async.c", { webStreams: true, nodeIsland: true, workers: false });
|
|
expect(variant.defines).toEqual(
|
|
expect.arrayContaining(["SCR_NATIVE_REACTIONS", "SCR_NODE_ISLANDS"]),
|
|
);
|
|
// Each feature alone still selects its own build, byte for byte.
|
|
expect(
|
|
selected("scr_async.c", { webStreams: true, nodeIsland: false, workers: false }).defines,
|
|
).toEqual(["SCR_NATIVE_REACTIONS"]);
|
|
expect(
|
|
selected("scr_async.c", { webStreams: false, nodeIsland: true, workers: false }).defines,
|
|
).toEqual(["SCR_NODE_ISLANDS"]);
|
|
expect(
|
|
selected("scr_async.c", { webStreams: false, nodeIsland: false, workers: false }).defines,
|
|
).toEqual([]);
|
|
});
|
|
|
|
test("the BigIntStats unit follows its own member-read gate, not bigint", () => {
|
|
const unit = matrix.runtime_units.find(
|
|
(u: { source: string }) => u.source === "scr_stats_bigint.c",
|
|
);
|
|
// Every bigint value turns the bigint feature on; only the member reads
|
|
// name bigstats, so a bigint program keeps this unit out of its binary.
|
|
expect(unit.predicate).toBe("bigstats");
|
|
});
|