Commit Graph
5920 Commits
Author SHA1 Message Date
Malte UblandClaude 5.5 7cc3a9fe51 Format the effect-gate alias loop
Co-Authored-By: Claude 5.5 <noreply@anthropic.com>
2026-10-27 19:19:33 -07:00
Malte Ubl 81d25a0fc5 Merge branch 'ni/i3-exports' into ni/i4-deferred 2026-10-27 19:16:12 -07:00
Malte Ubl 1428e41841 Merge branch 'ni/i2-handles' into ni/i3-exports 2026-10-27 19:16:06 -07:00
Malte UblandClaude 5.5 7d1a7f3882 Merge origin/ni/i2-handles into the local branch
Co-Authored-By: Claude 5.5 <noreply@anthropic.com>
2026-10-27 19:15:54 -07:00
Malte Ubl 8c4eb85122 Merge branch 'ni/i3-exports' into ni/i4-deferred 2026-10-27 19:14:34 -07:00
Malte Ubl a1742e6377 Merge branch 'ni/i2-handles' into ni/i3-exports 2026-10-27 19:14:25 -07:00
Malte UblandClaude 5.5 1d2ab2e874 Treat aliases of an accessor class as unreadable in the effect gate
Reading a class with a static accessor is refused because the accessor
can run import-time effects, but `const B = A` gave the alias the kind
"value", so a later read through `B` was admitted as pure and the
accessor's effects could move with the deferred module. Propagate the
"accessors" kind through alias chains to a fixed point and cover the
alias in the refusal test.

Co-Authored-By: Claude 5.5 <noreply@anthropic.com>
2026-10-27 19:14:09 -07:00
Malte UblandClaude 5.5 4535c4f90e Merge the hosted-loop base into the handles branch
Co-Authored-By: Claude 5.5 <noreply@anthropic.com>
2026-10-27 19:14:04 -07:00
Malte UblandClaude 5.5 1ab14172c6 Keep a unary island-call argument effectful and link islands beside streams
`+x`, `-x` and `~x` convert their operand with ToNumber, which calls a
user-defined `valueOf`; treating such an argument as inert let the
lowering read the island method after the conversion ran, so the call
reached a method the conversion had replaced. Only a numeric literal
operand is inert now, and the corpus program's `valueOf` replaces the
method it is called through.

A program that uses web streams and Node islands selected one
`scr_async.c` variant by condition count, so the tie between the
one-condition variants left either SCR_NATIVE_REACTIONS or
SCR_NODE_ISLANDS undefined and the hosted-loop symbols unresolved. Add
the combined variant, with a matrix test that pins the selection for
both features together and for each alone.

Co-Authored-By: Claude 5.5 <noreply@anthropic.com>
2026-10-27 19:12:36 -07:00
Malte UblandClaude Opus 5.5 da240b72e0 Merge ni/3-hosted-loop into ni/i2-handles
Brings the island signal listener bookkeeping and migrated timer refresh
fixes into the stack.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-27 19:08:55 -07:00
Malte UblandClaude Opus 5.5 8887f35f74 Fix island signal listener bookkeeping and migrated timer refresh
An island signal registration is now tagged with the raw listener it
installed, so a once registration and an on registration of one function
dispatch through their own listeners instead of both resolving to the plain
function, and the once registration no longer fires indefinitely. The
removal handler forgets the entry whose raw listener is no longer on
process, so a once wrapper that removes itself leaves its runtime
registration behind no longer; duplicate registrations of one function
share a raw listener, and the most recent of those is removed.

refresh() of a timer armed before Node loads re-arms at now + the delay the
timer was created with. Its Node handle was created with the remaining delay
at handoff and a due timer had no handle at all, so the handle is replaced
rather than refreshed.

The signal program registers one function once and on; a new timer program
refreshes a timer most of whose delay passed before Node loaded.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-27 19:04:26 -07:00
Chris Tate ca4a162e35 Merge main 2026-10-27 20:40:14 -05:00
Chris Tate a4a844f446 Revert "Keep frozen checked records frozen, and give sloppy-mode this the global object" (#2444) 2026-10-27 20:08:07 -05:00
Chris Tate 6d94457760 Relower units that add Node island module loads and name the island set a setting 2026-10-27 19:55:16 -05:00
Chris Tate b16c739d34 Classify zero-cost gate differences instead of failing every runtime change (#2271) 2026-10-27 19:27:25 -05:00
Chris Tate 919b79b62a Revert "Keep frozen checked records frozen, and give sloppy-mode this the global object" 2026-10-27 19:20:37 -05:00
Chris Tate 7d670f0e2a Merge main 2026-10-27 18:53:59 -05:00
Chris Tate d2595a4a70 Merge main 2026-10-27 18:49:24 -05:00
Chris Tate dfb7afcdd7 Load Node.js in-process on first use: libnode bridge and runtime loader (#1685) 2026-10-27 18:48:02 -05:00
Chris Tate e941d5d659 Run JavaScript WritableStream, TransformStream and pipes natively (#2437) 2026-10-27 18:43:35 -05:00
Chris Tate ccd87f44fc Keep the scr_map and three-library tests inside their timeouts (#2441) 2026-10-27 18:35:52 -05:00
Chris Tate ea8c1e6a34 Keep frozen checked records frozen, and give sloppy-mode this the global object (#2436) 2026-10-27 18:33:05 -05:00
Chris Tate 78e31bc73a Compile dev executables of more than 64 KiB in partitions (#2440) 2026-10-27 18:16:13 -05:00
Chris Tate e6a26e8e40 Keep the borrowed dispatch path through the inherited-method fallback (#2280) 2026-10-27 18:09:26 -05:00
Chris Tate 14deeba3aa Journal the Node island flag and relower units that add island call sites 2026-10-27 17:56:38 -05:00
Chris Tate 08fbecb7e7 Excuse only reproduced differences as nondeterministic, and read vendor archive symbols
A program is nondeterministic only when every artifact that differs also
differs between two baseline builds; a deterministic difference in another
artifact still fails the gate. The runtime-only check now reads the symbols
of changed vendor archives as well as runtime objects.
2026-10-27 17:55:44 -05:00
Chris Tate 90471a180d Read a proxy's integrity from its target, and give sloppy this the program's global object
Records checked from a proxy in a program that freezes untyped values no
longer fail on the proxy's integrity query: a proxy is frozen exactly when
its target is. A sloppy-mode function called with undefined or null
receives the global object that globalThis reads, so its builtin members
such as console answer before anything else reads the global object. The
new corpus programs are named instead of numbered and record their CI
costs.
2026-10-27 17:54:43 -05:00
Chris Tate 4e98e5e9bd Call web stream methods past own overrides, and await a transformer's thenable start
A method value of a web stream class, such as a saved
WritableStream.prototype.close, called on an instance whose own property of
the same name wraps it, ran the own property again, so the wrapper recursed.
The classes' method values now call the class's method directly
(ScrDynHandleClass.method_invoke); member calls still look at own properties
first.

TransformStream resolved its start promise with a transformer start's
result without adopting a thenable, so both sides started at once and a
rejection was lost. The start promise now resolves as a promise's resolve
function does (scr_dyn_promise_resolve_with): a thenable adopts through its
resolve job, a throwing `then` read rejects, and the stream starts or errors
when it settles, in Node's order.

Lowerer.namesWebStreamClass, a cache made when first needed, is listed in
Lowerer.unjournaled.
2026-10-27 17:53:47 -05:00
Chris Tate 89fbce5ce0 Read virtual calls by their kind when the unwind ABI walks a body (#2439) 2026-10-27 17:50:12 -05:00
Chris Tate fa046b8757 Compile dev executables of more than 64 KiB in partitions
A dev executable was one partition up to 1 MiB of LLVM text, so every edit
compiled the whole program again. Unoptimized partitions are compiled on
their own, with nothing imported across them, so dividing a program does
not change its code's quality, and the helper reuses each partition an edit
does not change from the partition cache.

nativeProgramPartitions now takes whether the program is optimized. Dev
executables are divided from 64 KiB of LLVM text, with at least 32 KiB per
partition: four partitions up to 128 KiB, then at least 8 as before. Release
and speed executables keep their partition and code generation counts.
2026-10-27 17:32:28 -05:00
Chris Tate 6f8c42bab7 Check unit records against one content snapshot per wave instead of per-unit copies (#2438) 2026-10-27 17:30:45 -05:00
Malte UblandClaude Opus 5.5 458fe7d54a Give the three-library release and sanitized cases 1200s timeouts
The test compiles the three npm package twice, dev and release, and both
cases shared one 600s budget through test.each. Release compiles the whole
library into one LLVM module that scriptc-llvm-codegen optimizes and
codegens in a single process on a single core: 426s of the 477s total run
in the native-archive phase alone. Across sandbox lanes release measured
331, 335, 339, 345, 348, 350, 358, 428, 450, 511, 521 and 581s, so whole-
box speed varies about 1.7x and the slowest lanes sat within 20s of the
budget; the sanitized dev case hit 600s twice. There is no regression, the
work is fixed and single-threaded.

Generate the two cases in a loop so each gets its own timeout: 1200_000ms
for release and for dev under SCRIPTC_SAN, and the unchanged 600_000ms else.
Test names are byte-identical to the .each %s expansion, so
skipUnownedTest keeps assigning each case to the same shard.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-27 15:27:08 -07:00
Malte UblandClaude Opus 5.5 54aba6a606 Build the scr_map semantics test at -O0
The scr_map unit test compiles 23 runtime translation units with
ASan/UBSan, and that build is essentially the whole test: 90s of clang
against a 2.1s binary run. scr_hash.c alone takes 29s at -O1 because the
sanitizer instruments its unrolled digest rounds; scr_json.c and
scr_lib.c add 28s more. The test then normally ran within 20s of its
120s timeout, and whenever a lane shared the box it repeatedly timed out
in both the plain and sanitized lanes.

The link set cannot shrink: scr_map.c's dyn ops need scr_dyn_* from
scr_json.c, scr_lib.c supplies the remaining date/math/number/perf
symbols, and scr_lib.c needs scr_hash.c. The test asserts Map semantics
under sanitizers, not codegen, and its cost checks are relative bounds,
so build it at -O0: every assertion and sanitizer check still runs and
the build drops to about 15s. Eight concurrent copies now take 20-22s
each instead of 90s, with the timeout unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-27 15:26:28 -07:00
Chris Tate a0198c80c6 Read virtual calls by their kind when the unwind ABI walks a body
Without the node index, or for a function the index didn't record,
eachNodeOfKinds passes every node of the body, statements too. The
unwind ABI's virtual-call pass cast each node to an expression before
testing its kind, and the native compiler checks that cast: with
SCRIPTC_EMIT_FACTS_VERIFY=1, whose comparison walks every body, it
stopped on the first statement. The kind test now narrows the node.
2026-10-27 17:18:53 -05:00
Chris Tate 039ca078ca Check unit records against one content snapshot per wave instead of per-unit copies
Recording a unit copied the keys and values of every appendable table before the unit and compared them after it. Each appendable table now keeps one snapshot of its entries' content per recorded wave (JournalTable.contents): a unit is checked only on the entries its IR and new entries name, by key or by the helper name its value holds, and the wave's end checks the content and key order of every entry. The name scan keeps only the strings the tables are keyed by (names that start with % and union ids). ShapeRegistry.journalSizes counts its declared-order candidates and attached names as they are added. On tsc-ts the serial mode's overhead over plain lowering falls from 12.7 s to 10.4 s.
2026-10-27 16:54:44 -05:00
Chris Tate 6e5f21c580 Reuse keep-alive connections across fetch() requests (#2379) 2026-10-27 16:45:35 -05:00
Chris Tate 1a86f94239 Merge main 2026-10-27 16:45:14 -05:00
Chris Tate 38bc4ed67b Pad ASCII strings without indexing their UTF-16 units (#2392) 2026-10-27 16:44:40 -05:00
Chris Tate 517451b8be Map large executables' text with 2 MiB pages (#2435) 2026-10-27 16:35:58 -05:00
Chris Tate f945efecee Run JavaScript WritableStream, TransformStream and pipes natively
In JavaScript sources, WritableStream with its default writer and
controller, TransformStream with its controller, pipeTo and pipeThrough,
and TextEncoderStream and TextDecoderStream join the native web stream
classes, following Node 24's webstreams step by step: sinks and
transformers, backpressure and the writers' ready and closed promises,
abort with the controller's signal, the pipe's shared write requests and
its abort signal, and UTF-8 encoding and decoding across chunks settle in
Node's order. The streams take own properties, which a pipe does not use
for its own reads and writes, and the global object answers the classes
by computed name in programs that name them.

A JavaScript class that extends one of these classes keeps the SC1090
refusal, and TextDecoderStream refuses encodings other than UTF-8.

The node24-web-stream lifecycle, errors, queues, transforms, pipes,
pipe-errors, pipe-abort, tee and encoding cases now match Node.
2026-10-27 15:55:31 -05:00
Chris Tate 62d4cecd3a Keep frozen checked records frozen, and give sloppy-mode this the global object 2026-10-27 15:22:08 -05:00
Chris Tate d82d1c4e94 Time emission's serial steps and remove three repeated walks (#2434) 2026-10-27 15:05:18 -05:00
Chris Tate 5dc4a4daa6 Map large executables' text with 2 MiB pages 2026-10-27 15:04:45 -05:00
Chris Tate c5aab2833b Use an exact integer loop limit as the counted loop's endpoint (#2432) 2026-10-27 14:51:49 -05:00
Chris Tate 3c7f47e6aa Lower function values with extra optional parameters into narrower slots (#2433) 2026-10-27 14:31:51 -05:00
Chris Tate b3453591c8 Time emission's serial steps and remove three repeated walks 2026-10-27 14:29:41 -05:00
Chris Tate cc6ee85fd7 Run JavaScript web streams on a native ReadableStream (#2411) 2026-10-27 14:20:02 -05:00
Chris Tate d76521be94 List the held entries a unit record reads, and leave units that register units or add class fields without one (#2431) 2026-10-27 14:15:52 -05:00
Chris Tate fef45262f8 Read a literal loop limit back with its integer's signedness
exactInteger can answer a limit's ToUint32 view, which for a number
literal is a literal of its unsigned bits: -1 has the view 4294967295. The
counted loop took such a literal as its i64 endpoint as written, so a
negative limit became a large positive endpoint and the loop ran when it
should not. An i32 literal endpoint is now read as signed or unsigned, as
the integer says.
2026-10-27 14:06:44 -05:00
Chris Tate a75cff7ab4 Use an exact integer loop limit as the counted loop's endpoint
A counted for loop converts its limit to an i64 endpoint. A limit that is
not a literal went through the double every time: converted to double,
clamped to 2^53, rounded with llvm.floor or llvm.ceil and converted back.
At the default target CPU the rounding is a libm call, which a loop such as
`for (let i = values.length - 1; i > at; i--)` paid on every entry even
when `at` was an int32 local. A limit that is an exact integer (an int32
local, an integer view, or a proven range) is its own floor and ceiling and
within ±2^53, so it is now the endpoint directly; other limits keep the
double path.
2026-10-27 13:49:48 -05:00