Commit Graph
3585 Commits
Author SHA1 Message Date
Chris Tate faa5cb601a Route defineProperty replacements of child methods through the child's box, and size the getter-only error to the name
- The scan for properties JavaScript adds to children now also records `Reflect.defineProperty`, `Object.defineProperty` and `Object.defineProperties` on a child, and element writes (`child["kill"] = ...`). A key that is not a literal sends every member through the child's box. A typed call to a method replaced through `Reflect.defineProperty` then calls the replacement instead of the native method.
- The "Cannot set property x of #<ChildProcess> which has only a getter" message is built at its exact length. Before, a name that overflowed the 160-byte buffer passed the untruncated length to the throw, which read past the buffer.
- Corpus 6611 adds a module that replaces kill through Reflect.defineProperty and writes to a getter-only property with a 300-character name; 6610 and 6611 get their cost files.
2026-10-21 00:15:04 -05:00
Chris Tate 00840aaca6 Merge main 2026-10-21 00:08:02 -05:00
Chris Tate 0c27def467 Run child accessors on the child, and find child property writes in every JavaScript file
- A getter or setter that JavaScript defines on a child process now runs with the child as `this`, instead of the hidden object that holds the child's added properties, for reads, writes and member calls. A write to a getter-only accessor throws "Cannot set property x of #<ChildProcess> which has only a getter".
- The scan for properties JavaScript writes onto children now covers every JavaScript file of a program that loads child_process, so a module that patches a child it received counts even when it never names child_process.
- The scan's cache and the program's "writes onto children" flag live on the Lowerer instead of a WeakMap and a WeakSet.
- Corpus 6611 covers a module that adds a replaced method, an accessor pair and a getter-only accessor to a child it did not spawn.
2026-10-20 23:41:21 -05:00
Chris Tate 19c88fedb4 Iterate untyped values with for await, and delegate with yield* in async generators (#1564) 2026-10-20 23:25:24 -05:00
Chris Tate a1c55207fc Merge main 2026-10-20 23:21:29 -05:00
Chris Tate 4dd62802c8 Bound loop counters compared as i + c with a bound (#1463) 2026-10-20 22:56:44 -05:00
Chris Tate 2783b96100 Round a loop bound to an integer before taking the counter's offset off it
- Narrowing `x + c < b` and its other comparison forms subtracted the offset from the bound in floating point. A fractional bound could then round across an integer: `x + 2147483648 > -(2 ** -60)` gave the minimum -2147483647, which leaves out -2147483648. The bound now rounds to an integer first, and the offset comes off in exact integer arithmetic. Integer bounds give the same facts as before.
- A unit test covers that comparison.
2026-10-20 22:54:32 -05:00
Chris Tate 43f1c445e8 Keep counters a for loop bounds in integer shadows (#1491) 2026-10-20 22:31:47 -05:00
Chris Tate 6bf550e11f Treat bindings a for loop's condition or update writes as unbounded
- The bounded-loop analysis collected writes from the loop body only. A binding the condition writes (`i < ((source = values[i]), values).length`) then passed as stable, so a cursor copied from it took the source's entry range, and its integer shadow truncated fractional values. The condition and the update are now scanned too, and a binding either one writes is neither a stable bound nor a copy source.
- Corpus 5686 adds a copy whose source the condition writes with fractional values.
2026-10-20 22:29:56 -05:00
Chris Tate 7ef3011f6c Start small arrays with three inline slots (#1613) 2026-10-20 22:06:12 -05:00
Chris Tate b602cdc76e Start small arrays with three inline slots 2026-10-20 22:01:41 -05:00
Chris Tate e5af4def98 Promisify untyped functions at run time (#1502) 2026-10-20 21:54:51 -05:00
Chris Tate 012fdb3fb0 Merge main 2026-10-20 21:52:19 -05:00
Chris Tate 69ef7da7f8 Run death-triggered full collections at the event loop's idle moments (#1522) 2026-10-20 21:48:02 -05:00
Chris Tate 44c586b1ee Run a waiting death pass at the idle moment even after the heap shrank 2026-10-20 21:44:46 -05:00
Chris Tate 0cb4c3ffea Give the deep fs.cp test a per-process scratch directory (#1612) 2026-10-20 21:32:43 -05:00
Chris Tate a4f9b1f66e Give the deep fs.cp test a per-process scratch directory 2026-10-20 21:30:01 -05:00
Chris Tate 24eb054395 Compile the hot-shots StatsD client over UDP (#1568) 2026-10-20 21:29:48 -05:00
Chris Tate 79f98f4684 Regenerate the compatibility files offline, and after merges (#1609) 2026-10-20 21:25:47 -05:00
Chris Tate b811317f26 Keep String method arguments read before another argument's conversion runs
concat, substr and the other typed String and Number extra methods
convert their arguments after evaluating all of them. When an argument's
conversion can run program code (an object's toString or valueOf), a
variable read of the receiver or another argument is now kept in a local
as well, so a conversion that assigns the variable leaves the
already-evaluated argument unchanged, as in Node.
2026-10-20 21:22:29 -05:00
Chris Tate 100e7738a0 Keep generated-file conflicts until regeneration succeeds, and take the side for the merged pin
regen-generated.mjs resolved each conflicted generated file with
`git checkout <ref> --`, which also staged it, so a failing generator left
the conflict resolved with the branch's stale file. It now writes the
chosen side's file to the working tree only and stages it after both
generators succeed.

It also always took MERGE_HEAD's ledger, so merging a branch with an older
Node pin into one with a newer pin regenerated from a ledger for the older
pin and failed. It now takes the side (index stage 2 or 3) whose ledger is
for the merged pin in node-v24.json, and when neither is, stops and says
to run pnpm node-compat, which fetches the pinned docs.
2026-10-20 21:21:14 -05:00
Chris Tate 7dd9fc3b9f Put each limitations sentence on its own line (#1611) 2026-10-20 21:15:00 -05:00
Chris Tate bde7afa980 Compile undici from a built-in implementation (#1425) 2026-10-20 21:14:37 -05:00
Chris Tate 36a5ff72d2 Put each limitations sentence on its own line 2026-10-20 21:12:48 -05:00
Chris Tate 3abf43affd Use the events module and EventEmitter as untyped constructor values (#1544) 2026-10-20 21:12:06 -05:00
Chris Tate d59d8ff6f2 Merge main and count declaration writes to parameters 2026-10-20 21:05:19 -05:00
Chris Tate eb8a148605 Merge main 2026-10-20 21:01:40 -05:00
Chris Tate 115a763df8 Check that the limitations partials keep one sentence per line (#1571) 2026-10-20 20:59:02 -05:00
Chris Tate adf4912d83 Run the partials check before oxlint in pnpm lint
pnpm appends forwarded arguments to the end of a script, so with the
partials check last, `pnpm lint:fix` and `pnpm lint --format=json` passed
their flags to the check instead of oxlint. The check now runs first; it
prints nothing when the partials are split, so oxlint's output, JSON
included, is unchanged.
2026-10-20 20:56:56 -05:00
Chris Tate 53171c282d Read and write dynamic-tier properties through shapes and inline caches (#1396) 2026-10-20 20:52:12 -05:00
Chris Tate 9c24e64ee2 Regenerate the compatibility files offline, and after merges
pnpm node-compat fetched Node's docs on every run, even though only the
classification changes between pins. pnpm node-compat --local now
reclassifies the committed ledger rows from the current sources and
rewrites the ledger and the public artifact, the same files a fetching
run writes while the pin is unchanged. scripts/regen-generated.mjs uses
it after a merge: for each generated file still in conflict it takes the
merged-in branch's version, regenerates the surface manifest and the
compatibility files from the merged sources, and stages them, so these
files never need a hand merge.
2026-10-20 20:50:04 -05:00
Chris Tate 9a802fe635 Leave the per-chapter status counts out of the compatibility files (#1608) 2026-10-20 20:48:27 -05:00
Chris Tate 06e202a126 Leave the per-chapter status counts out of the compatibility files
The ledger and the public artifact held a block of status counts for
every chapter. Nothing reads them (the docs page uses a chapter's slug
and title), and every classification change rewrote its chapter's block,
so concurrent compatibility changes conflicted there. The rows they were
counted from are unchanged.
2026-10-20 20:46:25 -05:00
Chris Tate 5e2e65a805 Build the Node compatibility backlog from the ledger instead of committing it (#1576) 2026-10-20 20:44:36 -05:00
Chris Tate 70e0af8094 Keep shapes off objects that threads share
A published graph is immortal and shared by pointer across threads, but a
shape names a node of one thread's transition tree, which ends with that
thread. A worker that read a published object through a cache left its
shape in the object; after the worker exited, the main thread's reads
followed it into freed memory. Immortal objects now stay unshaped, and
publishing (postMessage's shared graphs and @scriptc/threads publish)
clears a shape the object already has.
2026-10-20 20:44:14 -05:00
Chris Tate 3ef1b9f7be Merge main 2026-10-20 20:40:58 -05:00
Chris Tate 94aa7065f1 Compile the remaining corpus programs with the native compiler (#1418) 2026-10-20 20:29:41 -05:00
Malte UblandClaude Opus 5.5 da13375a8b Keep properties JavaScript adds to a child process, and await it as a thenable
execa 5 mixes then/catch/finally into a real ChildProcess with
Reflect.defineProperty, replaces kill and adds cancel by assignment, and
awaits the child.

- A new optional runtime unit, scr_dyn_handle_props.c, keeps those
  properties in a side table keyed by the native child. Wrapper ops for
  the child tag look there first for reads, member calls and writes.
  defineProperty and getOwnPropertyDescriptor use it, and await adopts a
  child with a callable then. Class methods read as values call the
  class's own method.
- In JavaScript files, writes onto typed children, reads and calls of
  added names, method values for bind/call/apply, and members no typed
  lowering claims go through the child's checked-dynamic box.
- Only programs whose JavaScript adds properties to children link the
  unit and install the table; everything else compiles as before.
- A setTimeout delay that may be a boolean converts with ToNumber, and
  `if (t.unref)` over a timer handle folds to true (execa's lib/kill.js).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 18:28:00 -07:00
Chris Tate 6e278b8487 Name the spread expression in not-iterable errors for values held as any (#1587) 2026-10-20 20:25:52 -05:00
Chris Tate af502aab45 Revert "Check the optional-record path test's cast at the cast" (#1605) 2026-10-20 20:24:56 -05:00
Chris Tate 97d6ebac6a Revert "Check the optional-record path test's cast at the cast (#1592)" 2026-10-20 20:22:18 -05:00
Chris Tate 5a1882957d Convert Promise and record results and record arguments in function adapters (#1556) 2026-10-20 20:21:38 -05:00
Chris Tate 81bc045524 Spin briefly before a mailbox wait blocks, and signal after the unlock (#1400) 2026-10-20 20:20:14 -05:00
Chris Tate 08c7930958 Support crypto.createECDH and ECDH.convertKey (#1589) 2026-10-20 20:18:22 -05:00
Chris Tate 7ccd9fb3ac Name functions stored in JavaScript object literals as Node (#1591) 2026-10-20 20:17:19 -05:00
Chris Tate f32c309baa Declare function adapter scratch locals in the adapter
A function value whose result is a union of records, assigned to a slot
that returns one record type, lifts each record arm into the slot's
record. The lift declares a scratch local, which went into the function
that requested the adapter, so calling the adapted function failed IR
validation. The adapter body now lowers in its own function context and
the adapter declares those locals.
2026-10-20 20:16:46 -05:00
Chris Tate fae56ff409 Run exec on regular expressions held as any (#1600) 2026-10-20 20:16:04 -05:00
Chris Tate 9eae4af46c Drop the undici shim type test from the TypeScript 5 import allowlist
The test checks the shims with the TypeScript 7 checker and no longer
imports typescript5, so test-ts7 reported its allowlist entry as stale.
2026-10-20 20:08:11 -05:00
Chris Tate a5294f1ec5 Read runtime keys of package enum objects as checked-dynamic values (#1603) 2026-10-20 20:07:13 -05:00
Chris Tate b04166a8f0 Read runtime keys of package enum objects as checked-dynamic values
The enum rewrite turns a package's numeric enum into one object holding
its names and its reverse mapping, so the object's fields have different
types. A reverse read with a runtime key, such as
DiagLogLevel[DiagLogLevel.WARN] in @opentelemetry/api, then failed with
SC1090 ("the declared fields have no one common type").

A keyed read of such a record already answers a checked-dynamic value in
JavaScript files. It now does the same where the checker types the read
'any'. The new npm case tsc-enum-reverse-reads matches Node, as does the
opentelemetry-api case again.
2026-10-20 20:04:06 -05:00