Commit Graph
1696 Commits
Author SHA1 Message Date
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 8476f68136 Support writev on Transform and PassThrough, and runtime stream option values (#1944) 2026-10-23 07:53:59 -05:00
Chris Tate 1221104388 Merge main and fix CI 2026-10-23 07:50:09 -05:00
Chris Tate a85c7c0a3b Read native handle methods as function values (#1984) 2026-10-23 06:02:41 -05:00
Chris Tate d9544bb71d Release EventTarget's shared method values at exit when only a signal read them
The EventTarget method values are cached for the program, and exit
released them only when an EventTarget, an event or a listener had
registered the unit's teardown. A program that read an AbortSignal's
addEventListener and never added a listener or made a target left the
cached functions live, and RC-audit builds exited with 99. Caching a
method value now registers the teardown too.
2026-10-23 05:57:37 -05:00
Chris Tate 8d17fe4e57 Support crypto.getCipherInfo, AES-CCM and AES key wrap (#1873) 2026-10-23 05:36:21 -05:00
Chris Tate 19e0fe8bcd Merge main and read cipher options through getters and prototypes 2026-10-23 05:33:14 -05:00
Chris Tate 40c3f69b40 Read an AbortSignal's EventTarget methods as EventTarget's own
An AbortSignal answered addEventListener, removeEventListener and
dispatchEvent read as values with functions of its own, which only ran on
AbortSignal handles: calling one on a plain EventTarget threw
ERR_INVALID_THIS. In Node they are EventTarget.prototype's methods,
shared with every target. The signal's property read now answers the
EventTarget method values (scr_event_target_method_value), which run on
any EventTarget receiver, AbortSignal included, so
signal.addEventListener === new EventTarget().addEventListener holds.
The signal's own method table keeps throwIfAborted.
2026-10-23 05:31:21 -05:00
Chris Tate 63fd3cecb7 Build @hono/node-server 2.x into scriptc (#1886) 2026-10-23 05:25:14 -05:00
Chris Tate eb2fa3c829 Fire spawn listeners for a child that exits before its first poll pass
A child spawned from a listener that runs during a poll pass, such as a
'close' listener, can exit before the next pass fires its 'spawn'
listeners. The same pass's waitpid loop then settled it with 'spawn' never
emitted. Settling an exited child now fires its pending 'spawn' listeners
first, before its stream data and 'exit', as Node emits them.
2026-10-23 05:14:51 -05:00
Chris Tate 952e01d2ed Stream request bodies in the Node server adapter 2026-10-23 05:03:12 -05:00
Chris Tate 0222bb1058 Keep fiber stacks across short event-loop sleeps (#1977) 2026-10-23 04:52:57 -05:00
Chris Tate 900bd2cf01 Check generateKeyPair arguments and RSA parameters as Node does (#1973) 2026-10-23 04:39:34 -05:00
Chris Tate 53838b39ec Call methods of bag-tracked class instances without building their views (#1979) 2026-10-23 04:37:54 -05:00
Chris Tate 58d3603549 Accept a callable Proxy as the generateKeyPair callback
generateKeyPair tested its callback, and a function in the options
position, by the checked-dynamic kind, so a Proxy whose target is a
function threw ERR_INVALID_ARG_TYPE. Node checks typeof, which answers
"function" for such a Proxy. Both tests now ask whether the value is
callable.
2026-10-23 04:33:56 -05:00
Chris Tate 8bb9ee8c57 Check generateKeyPair arguments and RSA parameters as Node does 2026-10-23 03:38:18 -05:00
Chris Tate 9e41d505b6 Declare the property-bag helpers in the runtime header
scr_dyn_bag_create_field and scr_dyn_is_class_capsule are declared by
the LLVM backend; their prototypes move from scr_json.c into scr_dyn.h,
which llvm-runtime-abi.test.ts checks the backend's declares against.
2026-10-23 03:30:06 -05:00
Malte UblandClaude Opus 5.5 3cbd1740a8 Call methods of bag-tracked class instances without building their views
Untyped code calling a method on an instance of a compiled JavaScript class
whose own properties live in a property bag materialized the instance's
whole checked view on every call (copying the bag, boxing each field and
attaching the prototype) only to read one member. Hono's Context declares
its methods as arrow-function fields, so every c.header() or c.json() from
middleware rebuilt an 18-property view.

The materializer of such a class gives the view exactly the bag's
string-keyed properties, the declared fields among them with their native
slot values, and the class's prototype. The compiler now emits those parts
as ScrDynTypedBagClassOps (bag, prototype, declared field names, field
getter) and binds them to the class's capsules, and scr_dyn_invoke resolves
a member that is an ordinary data property, own or inherited, from them,
calling it with the capsule as this. Accessors, read-only fields, capsule
prototype links and everything else still build the view.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 01:28:46 -07:00
Malte UblandClaude Opus 5.5 2f903f0255 Read native handle methods as function values
Methods of Web objects held in untyped code (Request, Response, Headers,
ReadableStream, its reader, AbortSignal) answered member calls only by
static name, so a property read such as hono's `raw[key]()` or
`typeof req.json` saw undefined. A handle class now lists the methods its
invoke answers; a read returns one shared function per method that calls
invoke on its `this` and raises Node's ERR_INVALID_THIS TypeError (or a
rejected promise for the async operations) on another receiver. The in
operator sees the methods and the modeled properties.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 01:13:24 -07:00
Chris Tate 88d15a8ea7 Call own accessors over an Error's name and message from typed code (#1957) 2026-10-23 02:48:44 -05:00
Chris Tate 6318d35679 Iterate untyped Headers values (#1969) 2026-10-23 02:42:23 -05:00
Malte UblandClaude Opus 5.5 e269262d73 Iterate untyped Headers values
entries(), keys() and values() on a checked-dynamic Headers value threw 'is not a function'. They now return live native iterators over the sorted header list, re-read on every step with set-cookie values one by one, as Node's Headers iterator does (hono's Context copies response headers this way).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 00:37:51 -07:00
Malte UblandClaude Opus 5.5 1edb2fe92d Keep fiber stacks across short event-loop sleeps
Finished fiber stacks went back to a spare pool that the event loop
unmapped whenever it was about to sleep. A server's loop sleeps between
nearly every pair of requests, so each request that awaited mapped, faulted
in and unmapped a fresh 512 KiB stack: on a Hono server mmap, munmap and the
page faults were about a fifth of its CPU time. Spares now outlive short
sleeps. At most once a second a sleep unmaps the spares that no fiber took
since the previous trim, and a sleep longer than two seconds unmaps them
all, so an idle program still returns the memory.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 00:29:27 -07:00
Chris Tate 94c00200ff Create untyped class instances' property-bag entries without the class tables (#1961) 2026-10-23 02:18:39 -05:00
Chris Tate 2232c716a8 Compile instanceof against constructors held as values (#1909) 2026-10-23 01:56:13 -05:00
Chris Tate 6fba766e58 Merge main 2026-10-23 01:52:29 -05:00
Malte UblandClaude Opus 5.5 756a93a8f2 Exit the untyped class tables early for values that are not class capsules
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 23:50:59 -07:00
Malte UblandClaude Opus 5.5 14a2769f58 Create untyped class instances' property-bag entries without the class tables
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 23:50:58 -07:00
Chris Tate f5cecccf5c Reflect the prototype of function-local classes without prototype members (#1958) 2026-10-23 01:46:06 -05:00
Chris Tate 1d68edc0f6 Give function-local class prototypes their own constructor
The prototype object of a function-local class, created once per evaluation
of the class, now starts with its own non-enumerable `constructor`, the
class value of that evaluation, as every class prototype does. Reflecting
the prototype of a function-local class without prototype members exposed
an object without it: `proto.constructor` answered the base class, and
`Object.hasOwn(proto, "constructor")` and its property descriptor did not
match Node.
2026-10-23 01:39:26 -05:00
Malte UblandClaude Opus 5.5 14ba361985 Call own accessors over an Error's name and message from typed code
zod 4 defines its error message with Object.defineProperty(inst, "message",
{ get, set }). The typed-ref commit of an Error subclass read the accessor
as a data value and threw "expected string". The commit and the slot sync
now leave the slot alone and mark the property absent; typed reads and
writes of name and message call the accessor when the program reflects on
an untyped or Error-shaped target.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 23:34:56 -07:00
Chris Tate b6d6eb60ae Replace a scheduled _construct hook, and keep runtime option values in order
Node's constructNT reads _construct on the construction tick, so an
assignment after the constructor and before that tick replaces a scheduled
construct hook. The assignment was dropped, so the original hook ran. It
now lowers to stream.replaceConstruct, which swaps the hook while its tick
has not run and has no effect after it or on a stream without a hook.

Runtime decodeStrings and defaultEncoding values are read into locals
before the constructor evaluates the other option members, while Node
evaluates the members in order. A runtime value after a member whose value
has effects (a call or an assignment) now refuses instead of reading a
value that member could still change.
2026-10-23 01:34:19 -05:00
Chris Tate 7dfc96728d Merge main 2026-10-23 01:19:49 -05:00
Chris Tate d942c27c2f Merge main 2026-10-23 01:01:03 -05:00
Chris Tate 5c5d0f5a0f Merge main 2026-10-23 00:42:41 -05:00
Chris Tate 6e71385a1a Type user code from npm package declarations at a checked, identity-preserving boundary (#1942) 2026-10-23 00:33:02 -05:00
Chris Tate cba3fa6a05 Keep projected files valid for bare async arrows and unbraced bodies, and adopt tuple elements
- A bare arrow parameter after `async` (`async x => ...`) gets parentheses
  with its projected type, as `x => ...` does. Without them the rewritten
  file failed its check and lost its projection (SC6102).
- A cast that starts an unbraced loop or `if` body gets no `;` guard. Only
  a statement in a statement list can continue the previous line, and in
  a body the `;` became the body, which moved the statement after the
  loop.
- Adoption walks a tuple's elements through the live element capsules of
  the tuple's view, so references package code holds to them see the
  native values.
- scr_runtime.h declares scr_dyn_decl_adopt (in scr_dyn.h), which the
  backend emits, so llvm-runtime-abi.test.ts finds its prototype.
- npm.test.ts gives zod3-adoption and zod3-boundary the long per-case
  timeout of the other zod 3 cases; their sanitized builds compile zod's
  types module too.
2026-10-23 00:25:59 -05:00
Chris Tate 0314d9db3e Dispatch checked-dynamic method calls on method ids 2026-10-22 23:52:25 -05:00
Chris Tate ebefb8d208 Merge main 2026-10-22 23:23:00 -05:00
Chris Tate da289bb593 Support writev on Transform and PassThrough, and runtime stream option values 2026-10-22 23:13:49 -05:00
Chris Tate ac3cb1c98f Merge main 2026-10-22 22:59:19 -05:00
Chris Tate fc31dd5060 Enumerate each record in the key order its object literal wrote 2026-10-22 22:56:12 -05:00
Chris Tate b161d0be13 Authenticate empty AES-CCM messages in decipher
A CCM decipher skipped its one update() when the data was empty, and
final() accepted when an update had run without failing, so it never
compared the tag. setAuthTag() with any tag of the right length, then
update() with empty data, then final(), succeeded: anyone could forge an
empty message, or one with different AAD or a different declared
plaintextLength, without the key.

A decipher's update() now runs the authenticated decryption for empty
data too. As in OpenSSL, the tag covers the nonce, the AAD and the
length, so the right tag still opens an empty message and any other
tag, AAD or length fails in final() with "Unsupported state or unable to
authenticate data". final() succeeds only after a tag comparison has
succeeded. A cipher's empty update() is unchanged.
2026-10-22 22:46:00 -05:00
Chris Tate 97921c2764 Read and write Error.stackTraceLimit through the Error constructor value (#1932) 2026-10-22 22:21:42 -05:00
Chris Tate 143f2e11e9 Keep an own stackTraceLimit on the Error value ahead of the limit 2026-10-22 22:15:57 -05:00
Chris Tate 75cf8f0e52 Run zod 4's core constructor factory in the dynamic tier (#1918) 2026-10-22 22:08:46 -05:00
Chris Tate 6a1e5103f0 Array keys and properties: non-index number keys, Object.keys, console.log (#1769) 2026-10-22 22:00:27 -05:00
Chris Tate 77c0636826 Include star re-exports in namespace objects, and read causes and instanceof Error like Node under a runtime Error parent
- A module namespace converted to an untyped object, and a computed
  namespace read, use the module's resolved exports, which include the
  members of `export *` declarations.
- `super(message, options)` through a runtime Error parent installs the
  cause as Error does: an inherited `cause` counts, the value is read
  through its getter, and the getter's exception propagates.
- `value instanceof Error` on an instance of a class whose heritage is
  evaluated at run time tests that class's prototype chain for
  Error.prototype. A program with such a class checks prototype chains
  for `instanceof Error` on untyped values.
- The cache of names written on the global object is a Lowerer field
  instead of a WeakMap keyed by the Lowerer.
- errors.test.ts: `"prototype" in Map` answers from the builtin
  constructor's keys now, so it leaves the refused reads and joins a
  check of `in` probes against Node's answers.
2026-10-22 22:00:01 -05:00
Malte UblandClaude Opus 5.5 ca2d5bd9c7 Support String.prototype.at on strings held in untyped values
Hono's mergePath reads base?.at(-1) on an untyped parameter. The
checked-dynamic method dispatch answered at() on strings with a
not-supported error. It now returns the UTF-16 code unit at the index,
counting from the end for a negative index, and undefined outside the
string, as String.prototype.at does.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 19:58:24 -07:00
Chris Tate 12166956b8 Spread protocol iterables into Math.min and Math.max
Math.min(...src) and Math.max(...src) over an untyped source now take its
values the way a spread does: arrays, strings, bytes and collections pack,
a native iterator (a Map's keys()) drains, and other iterables (a generator,
an object with a Symbol.iterator method) step their iterator to the end.
Before, only the packing kinds were accepted and every other iterable threw
the spread TypeError.
2026-10-22 21:57:29 -05:00