Commit Graph
6750 Commits
Author SHA1 Message Date
Malte Ubl 2d518aa680 Merge remote-tracking branch 'origin/ni-2-node-island-report' into HEAD 2026-10-23 08:06:55 -07:00
Malte UblandClaude Opus 5.5 f32d0cd184 Make the packaging island fixture a webpack bundle
Main now compiles minified npm packages (#1989), so ni-minified no
longer refuses and the island report lost its packaging class. The
fixture is now ni-bundled, whose build-transform markers still refuse it
as shipped.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 08:06:38 -07:00
Malte UblandClaude Opus 5.5 a705a3fd09 Reject other classes' capsules inline in class-table brand probes
A class table (property bags, normalization, computed reads) tests the
receiver's capsule key against every compiled class in turn. A capsule
boxed by another class has another key pointer, and each such probe called
scr_dyn_typed_ref_is_key to compare the names. The probe now rejects it
inline when the key length or its last eight bytes differ, and calls the
out-of-line comparison only for a likely match, so capsules boxed with an
equal key elsewhere still match.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 08:04:00 -07:00
Malte UblandClaude Opus 5.5 7b8a07e0f2 Search proven-ASCII strings backwards by byte in lastIndexOf
lastIndexOf built the receiver's UTF-16 index map and converted positions
both ways even when the receiver is proven ASCII, where byte offsets are
UTF-16 indexes (indexOf already has this fast path). A short id such as
"bk_00042".lastIndexOf("_") cost about 200 instructions; the Hono
fixture's list endpoint does it 80 times per request.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 08:04:00 -07:00
Malte UblandClaude Opus 5.5 056dda3633 Read Web Headers pairs without copying them, and cache their sorted list
Headers kept its name/value pairs in a string array and read every element
through scr_arr_get_ref (index checks, retain, release). forEach and the
iterators re-sorted and rescanned the whole list for every step, and every
Response or Headers built from another Headers object re-validated and
re-normalized each copied pair. The Hono fixture spends 12-15% of a request
there.

- Pair loops read borrowed elements of the dense array (sf_pair_at).
- The sort-and-combine list is cached on the Headers object and dropped by
  every mutation, so live iteration keeps Node's semantics.
- get() of a single value returns the stored string.
- Copying a Headers object whose pairs are canonical (built by the
  constructor or a Response) into an empty list copies the pairs; wire
  response headers keep the per-pair path because they may repeat names.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 08:03:59 -07:00
Chris Tate e771de1cfb Check cycle bindings only where early code can reach the reading function (#1882) 2026-10-23 10:02:29 -05:00
Chris Tateandejc3 52792d8c52 Find weak collection entries through hashed indexes
WeakMap and WeakSet kept each collection's entries in one list and found
a key by walking it, and every collection's entries for a key in 1,024
shared buckets. Filling a collection and reading it back took quadratic
time: 40,000 keys took 6.7 s against Node's 0.2 s, and 200,000 keys did
not finish.

Each thread now indexes its entries twice, in open-addressing tables with
linear probing and backward-shift deletion: by collection, key and kind,
for get, set, has and delete, and by key pointer, for a key's disposal,
which ends the key's entries in every collection. A collection's entries
and a key's entries are doubly linked, so an entry leaves both in
constant time. The tables grow at half load and are freed when their last
entry goes, so an exiting worker leaves none. 200,000 keys now take
0.24 s (Node 0.30 s).

Closes #1702

Co-authored-by: ejc3 <1694850+ejc3@users.noreply.github.com>
2026-10-23 09:54:58 -05:00
Malte Ubl 433cbaf3ac Merge remote-tracking branch 'origin/main' into HEAD 2026-10-23 07:54:16 -07:00
Chris Tate a23ce3043c Keep loop-carried locals written from int32 element reads int32
The int32 array proof assumes its candidates' elements are int32 and
asks the integer range analysis whether every stored value is one. A
local assigned in a loop from an element read of a candidate array
(`const t = next[at]!; next[at] = at; at = t`) never closed under the
int32 bound, because the loop-carried closure had no case for element
reads, so arrays that store such cursors kept double slots and every
index converted from a double. Element reads now take the slot range in
that closure, as field reads and calls already did.

The index-cursors runtime workload walks an array of indices with such a
cursor.
2026-10-23 09:53:05 -05:00
Malte UblandClaude Opus 5.5 7c33b55435 Keep fixed layouts for JavaScript classes next to freezes and unrelated accessors
Two rules sent every JavaScript class family to field-creation tracking:

- Any Object.freeze, Object.seal or Object.preventExtensions of a value
  other than a fresh literal. These never create or remove a property, and
  a class instance keeps its integrity state beside its fields: a typed
  call sets the CLASS_ATTRIBUTES word that TypeScript classes use with the
  same fixed layouts, and through an untyped value the runtime refuses the
  operation on every class instance (SC2020). Only Reflect.deleteProperty
  stays a removal of any name.
- Any getter or setter. An accessor only matters when it shares a name
  with a field of the instances that see it, or when a subclass accessor
  can intercept a base constructor's field assignment. Other accessors
  live on the prototype beside the fields.

In zod 3, ParseStatus and ParseInputLazyPath now keep fixed layouts (2 of
the 39 tracked classes; the ZodType family stays tracked because its
constructor creates own properties before _def). z.array(Order).parse
over 500 orders: 270.7M -> 235.8M instructions per round (-12.9%).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 07:39:29 -07:00
Chris Tate dddcb339aa Revert "Cache untyped property access in programs that declare classes" (#1996) 2026-10-23 09:35:24 -05:00
Malte UblandClaude Opus 5.5 0e10a01386 Keep record key order through typed iterators and generator resumes
Records read out of a typed Map through an `IterableIterator<T>` method
(`all() { return this.rows.values(); }`) or out of a `Generator<T>` came
back through checked conversions, so the key-order witness treated their
type as built at run time and a self copy (`{ ...current, ...patch }`)
fell back to the declared order.

- A record yield channel keeps its type beside the defaulted `any` return
  channel, like number, boolean and string already do: for-of and spread
  read the yielded record unchecked.
- `m.values()`/`keys()`/`entries()` on a typed Map or Set flowing into an
  iterator-typed slot walks the collection with typed reads. It keeps the
  native iterator's protocol: lazy, live, and parked instead of closed by
  an early loop exit.
- The witness counts a generator resume as building only its
  IteratorResult record, not the value it carries.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 07:31:40 -07:00
Chris Tate 116d163e2c Take the elements before converting foreign elements
Math.max, Math.min and Math.hypot over a spread, and the default sort,
convert foreign elements with user code. As in Node, the elements are
taken first, each foreign value retained, so a conversion that changes
the array changes neither the count nor the values the operation sees,
and no slot read before the conversion is released under it. join and
the numeric element read hold the value they convert, and join reads the
length once and stops at a throw.

toSorted of an array with foreign elements now builds a copy of the
full length and reads its holes as undefined, as for other arrays.
2026-10-23 09:30:37 -05:00
Chris Tate c7c8f5d45e Run lone array callbacks as loops with their bodies inlined 2026-10-23 09:25:07 -05:00
Malte Ubl 55d19f3d7b Merge remote-tracking branch 'origin/ni/i10-js-island-requires' into HEAD 2026-10-23 07:25:05 -07:00
Malte Ubl f661d65147 Merge remote-tracking branch 'origin/ni/i9-recorded-deferral' into HEAD 2026-10-23 07:24:47 -07:00
Malte Ubl 58389fed57 Merge remote-tracking branch 'origin/ni/i8-exit' into HEAD 2026-10-23 07:24:31 -07:00
Chris Tate 0f8dd276d9 Reach a class's methods from its class expression's inner name in static initializers
A named class expression's own name (const C = class Impl { static x =
Impl.m(); }) names the class inside its body as the binding it is stored
in names it outside. The reachability walk followed only stored binding
names, so a static initializer calling a method through the inner name
did not reach that method, and its early reads of the other cycle
member's bindings lost their TDZ checks: the program read the binding
before its declaration ran (a crash), where Node throws ReferenceError.
The inner name now maps to its class expression.
2026-10-23 09:24:28 -05:00
Malte Ubl dcbdaa9475 Merge remote-tracking branch 'origin/ni/i7-routing' into HEAD 2026-10-23 07:24:17 -07:00
Malte Ubl 586ec48c22 Merge remote-tracking branch 'origin/ni/i6-subclasses' into HEAD 2026-10-23 07:23:57 -07:00
Malte Ubl b2bd9dabce Merge remote-tracking branch 'origin/ni/i5-shared-modules' into HEAD 2026-10-23 07:23:36 -07:00
Malte Ubl 545013908a Merge remote-tracking branch 'origin/ni/i4-deferred' into HEAD 2026-10-23 07:23:14 -07:00
Malte Ubl 7cbddb7dd2 Merge remote-tracking branch 'origin/ni/i3-exports' into HEAD 2026-10-23 07:22:53 -07:00
Malte Ubl 448b1108da Merge remote-tracking branch 'origin/ni/i2-handles' into HEAD 2026-10-23 07:22:32 -07:00
Malte Ubl 4abfd98cb8 Merge remote-tracking branch 'origin/ni/i1-stack-bound' into HEAD 2026-10-23 07:22:11 -07:00
Malte Ubl 7c64604980 Merge remote-tracking branch 'origin/ni/islands-base' into HEAD 2026-10-23 07:21:49 -07:00
Malte Ubl 1d139d7005 Merge remote-tracking branch 'origin/ni-2-node-island-report' into HEAD 2026-10-23 07:21:44 -07:00
Malte UblandClaude Opus 5.5 249773437a Update the strict-user-js coverage snapshot for main's startup section
Main now reports fenced sites in module top-level code under "runs at
startup"; the use of 'legacy' on line 22 is one of them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 07:21:37 -07:00
Chris Tate 313eb1177c Merge main and fix CI 2026-10-23 09:14:31 -05:00
Chris Tate 885a829959 Compile minified npm packages such as marked (#1989) 2026-10-23 09:07:41 -05:00
Chris Tate a10c183b13 Revert "Cache untyped property access in programs that declare classes (#1995)" 2026-10-23 09:05:55 -05:00
Chris Tate 17c069667e Settle a var declared by a for-in or for-of loop only inside the loop body
A for-in or for-of loop stores its var binding only when it iterates. The
early-read analysis counted the loop as an unconditional store for every
later statement, so after a loop that ran zero times a closure read the
binding as initialized (typeof answered "string" where Node answers
"undefined"). The loop now settles the reads in its body; later reads
settle at the next unconditional store.
2026-10-23 09:03:59 -05:00
Chris Tate da2173d54b Cache untyped property access in programs that declare classes (#1995) 2026-10-23 08:47:07 -05:00
Malte Ubl 6d920c2dde Merge remote-tracking branch 'origin/ni/i10-js-island-requires' into HEAD 2026-10-23 06:45:34 -07:00
Malte Ubl 3cf2bd9b19 Merge remote-tracking branch 'origin/ni/i9-recorded-deferral' into HEAD 2026-10-23 06:45:10 -07:00
Malte Ubl 283f689087 Merge remote-tracking branch 'origin/ni/i8-exit' into HEAD 2026-10-23 06:44:46 -07:00
Malte Ubl 183289ddc0 Merge remote-tracking branch 'origin/ni/i7-routing' into HEAD 2026-10-23 06:44:20 -07:00
Malte Ubl d62752f11b Merge remote-tracking branch 'origin/ni/i6-subclasses' into HEAD 2026-10-23 06:43:46 -07:00
Chris Tate 4b60ac0de9 Copy class-view property bags entry by entry (#1976) 2026-10-23 08:43:19 -05:00
Malte Ubl e4a660c15a Merge remote-tracking branch 'origin/ni/i5-shared-modules' into HEAD 2026-10-23 06:43:11 -07:00
Malte UblandClaude Opus 5.5 ec5f77f508 Give the libnode smoke dispatcher the sharedPush entry the bridge requires
ABI 7 takes sharedPush from the bootstrap's dispatcher as well.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 06:43:02 -07:00
Chris Tate fa22b991cc Return ASCII header values as their own ByteString (#1978) 2026-10-23 08:42:17 -05:00
Malte Ubl 6bd7ecd789 Merge remote-tracking branch 'origin/ni/i4-deferred' into HEAD 2026-10-23 06:42:12 -07:00
Malte Ubl 4d5edcca20 Merge remote-tracking branch 'origin/ni/i3-exports' into HEAD 2026-10-23 06:41:42 -07:00
Chris Tate 8eedab9fde Cache untyped property access in programs that declare classes
A program that declares a class reads and writes untyped properties
through helpers that first select the receiver's property bag. The bag
helpers return jsvals, so the helpers read the bag through js.toDyn;
keyed helpers test each class's key table between the key's coercion and
the read; and a program with subclasses normalizes the receiver
(value = %dyn.class.normalize(value)) at the start of each helper. The
inline-cache recognizer accepted none of these forms, so every property
site in such a program called its helper. It now looks through dyn/jsval
conversions of the receiver, accepts capsule branches before a keyed
helper's final read, and accepts a rebinding of the receiver to a bag of
itself. Plain objects and arrays then read and write through the site's
cache, as they do in programs without classes.

bench/dynamic-properties (new) exercises these sites.
2026-10-23 08:41:40 -05:00
Malte Ubl 9df17b1c85 Merge remote-tracking branch 'origin/ni/i2-handles' into HEAD 2026-10-23 06:41:13 -07:00
Malte UblandClaude Opus 5.5 f42fc643de Give the libnode smoke dispatcher the load entry the bridge requires
ABI 5 takes a load function from the bootstrap's dispatcher; without it
the smoke program's start fails with an incomplete dispatcher.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 06:40:57 -07:00
Malte Ubl d3b1e33906 Merge remote-tracking branch 'origin/ni/i10-js-island-requires' into HEAD
# Conflicts:
#	packages/runtime-pack-common/runtime-pack-matrix.mjs
2026-10-23 06:39:28 -07:00
Malte Ubl df314d09e0 Merge remote-tracking branch 'origin/ni/i9-recorded-deferral' into HEAD 2026-10-23 06:38:57 -07:00
Malte Ubl 902bd3025b Merge remote-tracking branch 'origin/main' into HEAD 2026-10-23 06:38:51 -07:00