| … | … | @@ -3514,6 +3514,35 @@ injected per layer: |
| 3514 | 3514 | the size (about 120 sites plus l3, L2 and the tools); compile-time growth. |
| 3515 | 3515 | - **Not R4:** network-side awaits that are already continuations (wire, timers); |
| 3516 | 3516 | 4e-4 `replicate()` comes after R4i. |
| 3517 | - **R4a DONE 2026-10-06** (keetd 43440f8 on branch `r4`, on top of R3c's branch copy 4e1b3b5; |
| 3518 | the branch rebases onto main once R3c lands there). |
| 3519 | - **C++20.** nlohmann 3.11.3 switches to its three-way comparison set under C++20 and drops |
| 3520 | `operator==(json, json)`; 50 test comparisons (`std::string == json`) stopped compiling. |
| 3521 | `JSON_HAS_THREE_WAY_COMPARISON=0` keeps the C++17 operators, so every gate compares json |
| 3522 | exactly as before. |
| 3523 | - **`hc/js.h`:** V8's promise steps on rt's queue: PerformPromiseThen, the resolving functions |
| 3524 | (first call wins), the thenable job (adoption), all / allSettled / race, `then` / `catch_`, |
| 3525 | `MaybePromise<T>` (a JS function returning a value OR a promise: only the promise adopts). |
| 3526 | `js::Promise<T>` is the coroutine type of an `async` function: the body runs at the call, |
| 3527 | `co_await` is one reaction job, a throw rejects. |
| 3528 | - **rt:** libjs's unhandled-rejection list (js.cc `on_promise_reject` + `run_microtasks`): FIFO; |
| 3529 | a late handler removes the entry; after every checkpoint each entry left is reported, each |
| 3530 | report followed by its own checkpoint. `hc::setUnhandledRejectionHandler`; none installed = |
| 3531 | Bare's default (prints "Uncaught (in promise)", aborts: exit 134, measured). |
| 3532 | - **`ss::AsyncIterator`:** streamx 2.28.1's `Readable[Symbol.asyncIterator]`, literally. The |
| 3533 | `for await` port pattern is in its header (V8 awaits `next()`, and `return()` on a break). |
| 3534 | - **Measured on Bare 1.28** (microtask ruler beside the code): `await` on a settled promise = 1 |
| 3535 | hop; an async `return promise`, a handler returning a promise, `resolve(promise)` = +2 |
| 3536 | (adoption); reactions run in registration order; a callback's unhandled rejection is |
| 3537 | reported in its checkpoint BEFORE its uncaught throw is delivered; no `rejectionHandled`. |
| 3538 | - **Gates:** `tools/js` (33 scripts; Bare vs rt real AND virtual, identical, deterministic over |
| 3539 | repeated runs); the duplex gate gains 9 iterator / `for await` scripts. ctest 83/83. |
| 3540 | - **Drills:** r4a 16/16 (its one first-run survivor, "catch drops a fulfilled value", was a |
| 3541 | script gap: `catchPassThrough`); r4a-iter 8/9 + 1 equivalent ("the error wins over data only |
| 3542 | when none": measured, after `destroy(err)` `read()` is null at once, and 'error' only comes |
| 3543 | from that destroy). |
| 3544 | - **Next: R4b** (rn/: rocksdb-native's JS layer over librocksdb's async mode, completions |
| 3545 | inline for now, the drain scaffold for unconverted callers). |
| 3517 | 3546 | - **Then 4e-4** (`createProtocolStream` / `replicate`): the first gate that composes the stack |
| 3518 | 3547 | is a COMPOSED trace against JS (secret-stream + protomux + replicator), now meaningful. |
| 3519 | 3548 | |