- The pattern fence lifts: the vendored engine already executes named groups and named backreferences
- Match results project .groups at compile time as the checker's own record shape, with Node's key order, undefined-when-none, and null-read error texts
- Replace and replaceAll resolve $<name> templates with Node's exact edge behaviors; matchAll rows carry groups through for-of, drains, and destructuring
- Destructuring over index-signature records reads through the overflow map generally
- The dynamic-import subgraph judges back edges with the same admission engine as the static graph; its refusals now reach the build instead of being discarded with the discovery pass
- TDZ-shape reads and non-inert top levels refuse naming the binding or statement and its location, not the whole cycle
- Evaluation order stays Node's postorder with back edges as cache hits, pinned by the parity baselines
- New libCalls math.trunc/math.ceil: C trunc()/ceil() are the JS operations, llvm.trunc.f64/llvm.ceil.f64 on the LLVM lane
- Joined STATIC_MATH_FNS (checked before the island table) — they are ask-4's wholeness-discharge operators, so library builds need them compiled
- Surface manifest regenerated: stdlib.math.trunc/ceil move to static
- lowerRegexLiteral drops the (?<name> fence: patterns and \k<name> backreferences run natively in libregexp, and .groups on exec/match/matchAll results desugars into a compile-time record projection over the honest slice — the checker's own Record<string,string> hybrid with overflow entries in group declaration order — whenever the regex is statically known (literals, const bindings, new RegExp("..."), matchAll rows via for-of bindings, stored drains, spread rows, element access)
- Node's exact shapes: a group-less regex answers .groups === undefined, nullable receivers throw Node's TypeError on the unit arms, ES2025 duplicate names project the participating alternative, and destructuring rides — flat, aliased, and the nested { groups: { year } } pattern — via the groups wrap plus a general overflow read for undeclared keys of index-signature shapes
- scr_put_substitution resolves $<name> against lre_get_groupnames with Node's edge answers: nonexistent and nonparticipating names substitute empty, $< stays literal when the pattern has no named groups, an unterminated $<name stays literal
- s.match(re) also claims a nullable string receiver (the Dict<string> member spelling) through the checked narrow; an untraceable .groups read keeps the SC2020 fence with a hint naming the traceable shapes
- Differential corpus 2604-2607 (both backends, SAN), runtime C substitution/backreference cases, refreshed diagnostics snapshots and surface manifest; corpus 1614's deliberate deferred fence moves to a Proxy wrap now that hybrid record reads compile
- Purely additive: the eight new entries (corpus 2604-2610 and the ee-emit-override diagnostics program) join baselines/order-parity.json; no existing baseline moves.
- createRequire(import.meta.url) (or __filename / import.meta.filename) in a const binding is compile-time plumbing that emits nothing; each require call through it resolves per site against the binding's own file, and the inline createRequire(import.meta.url)("spec") spelling erases identically
- The erasure per target: a builtin spec makes the binding a namespace import in const clothing (namespace, destructured, and inline-member spellings all key the existing module tables, with the fallback-typed 'as typeof import(...)' cast idiom stripped); a relative .json document validates at compile time and lowers to json.parse over its baked text (JSON.parse's checked-dynamic unknown stance — exactly Node's value); a bare name nothing installed resolves compiles to Node's catchable MODULE_NOT_FOUND throw (the optional-dependency try/require pattern); an installed npm package embeds under --dynamic through the island's NEW require-condition entry (NpmGraphBuilder.addRequire — a dual package answers its CJS arm, exactly Node's createRequire) and reports the requires-dynamic diagnostic in a static build
- Dynamic specifiers, '#' project imports, relative non-.json targets, --npm-static opt-ins, and non-this-file bases all fence by name; the island-handle rescue skips the plumbing decls so --dynamic builds erase them too
- module.builtinModules bakes as Node v24's exact list (a fresh string[] per read, pinned to the compat target so emitted programs stay host-independent); isBuiltin and syncBuiltinESMExports fence per site with pointed hints, and the createRequire hint, its diagnostics snapshot, the surface manifest, and the npm-static offender wording follow
- Corpus 2606 pins json/builtin/builtinModules/MODULE_NOT_FOUND differentially on both backends and under ASan; the npm create-require fixture case pins cjszoo's module.exports, dual's require-condition CJS arm, and the missing-package rejection against Node
- The Readable defaultEncoding option lowers to a push-side decode default (Buffer.from(chunk, enc)); push(chunk, enc) with any literal encoding decodes per call and overrides the default, utf8 included
- Unknown literal encodings become Node's runtime TypeError — at construction for the encoding/defaultEncoding options (nodeThrowExpr, the ladder pattern), at the call for push
- on/once/off admit Node's ignored extra arguments when they are pure reads (the suite's stray-third-argument shape); effectful extras keep the fence
- readable.pushStrEnc/readable.pushEncoding land in both backends; corpus 2607-stream-push-encodings pins the decode, override, and both throw sites differentially
- Every deferred stream emission posts a raw marker on the user tick queue (scr_next_tick_raw) and each marker dispatches exactly one stream tick, so resume_/emitReadable_/endReadableNT interleave with user nextTicks in enqueue order — in Node they are the same queue
- Cures the setEncoding-with-buffered-bytes shape: a nextTick registered after on('data') now observes the flowed chunks, and stream emissions run before microtasks at each checkpoint instead of after
- The loop station stays as the drain for anything a marker never reached and as the uncaught-throw cleanup of undelivered ticks
- Corpus 2606-stream-ticks-are-nextticks pins the interleavings (buffered decode, split multi-byte char, tick/data/tick ordering, end-after-tick) differentially on both backends
- An unannotated event parameter (checker any) in a JS source binds as the string it always is — event names are compile-time literals program-wide — so CJS emitter subclasses wrapping emit compile like their TS twins; TS sources still spell the annotation.
- Corpus 2610 pins the CJS override with filtering, instance state, and checked-dynamic listeners against Node on both backends.
- Stream constructors reserve their class's known _events names (Readable close/error/data/end/readable, Writable close/error/prefinish/finish/drain, Duplex the union) — empty reserved buckets are invisible to every read but hold the first-registration rank, so eventNames lists them before earlier user events, exactly Node's shape optimization
- Shape mode reproduces Node's removal split: removeListener keeps an emptied name's rank (events[type] = undefined), the named removeAllListeners deletes a populated key (and resets wholesale when the count drains, kShapeMode quirk included), the no-argument wipe resets everything and leaves shape mode
- Corpus 2605-stream-event-names pins the order, rank survival, drain, and wipe behaviors differentially on both backends
- class C extends EventEmitter may re-declare emit(event: string, ...args: unknown[]): boolean when the rest parameter only forwards through super.emit(event, ...args) in the method's own body; the body lowers once per event name as the real hierarchy method emit:<event> (vtable participation, (this, ...tuple) => bool ABI), with event bound to the name and the forward lowered to the runtime emit — or to the nearest override ancestor's specialization, JS's super chain.
- Emit sites dispatch by the whole-program rule: receivers at-or-below an override call the specialization directly (virtually when a deeper override exists); receivers above every override route through an interned helper that instanceOf-tests the topmost override subtrees and falls through to the runtime emit, so plain EventEmitter bindings holding override instances still dispatch like Node.
- super.<member> over an emitter-rooted base now lowers through the emitter spoke with static dispatch (an override at-or-below the lexical class never answers a super call); registering 'newListener'/'removeListener' listeners fences while a comparable class overrides emit (the runtime fires meta events internally, past the override), and every other emitter member keeps the surface fence with the forwarding-shape rule spelled out for emit.
- Corpus 2604-2609 pin both backends against Node: the logging override with upcast dispatch, two-level override chains with literal super.emit, once/off/prepend ordering and handled errors under an override, the unhandled-'error' throw through an override, the filtering override, and an emitter-subclass job queue; the diagnostics snapshot pins the three fences.
- Extract preflight's benign-cycle admission (the cheap per-edge rule plus the declaration-only init window analysis, with Tarjan SCC and cluster-verdict memos) into makeCycleAdmission; preflight's static walk and appendDynamicImportModules now judge back edges identically, so benign cycles behind dynamic import() compile as Node cache hits instead of blanket SC1016.
- appendDynamicImportModules runs once in lowerToIr before any pass constructs: the old per-constructor run minted cycle refusals into the discovery pass, whose diagnostics are discarded by design, so inadmissible import() cycles silently compiled; refusals now land on the emit pass with the same narrowed reason (binding and line, or the offending top-level statement) the static walk mints.
- SC1016 gains a registry hint naming the admitted shape and the fix; diagnostics snapshots, order-parity baselines, and the surface manifest repin with it.
- Corpus 2604 (mutual class cycle across two modules), 2605 (three-module function ring with two back edges and a function-body-only value use), 2606 (import() into an admitted mutual-recursion cycle) — all byte-identical to Node through both backends; diagnostics fixture dyn-import-cycle-tdz pins the dynamic-path TDZ refusal.
- scr_bytes_subarray: a same-elem view retaining the owner (the DataView rule, chain depth 1); subarray() and Buffer's slice() lower there, plain typed arrays' slice() keeps the copy — mutations through views are visible both ways now, byte-exactly with Node
- Buffer.from(x.buffer, byteOffset?, length?) lowers as the dataViewNew view construction (the syntactic .buffer peel); the fallback lib gains the ArrayBuffer overload
- fillElem: TypedArray.prototype.fill on non-u8 receivers, per-element coercion with slice-clamped indices; u8 keeps the Buffer fill family
- Both backends emit the new intrinsics; corpus 2604-bytes-views pins aliasing, offset composition, swap-through-slice, clamping, and fill coercion differentially
- scr_sc_text/json/buffer accumulate every chunk through a native 'data' listener (string chunks as their utf8 bytes, the Blob rule) and settle at the terminal point through the finished watcher — Node's own eos timing, verified byte-exact including resolution landing after 'close'
- Rejections match Node's set: the stream's error, ERR_STREAM_PREMATURE_CLOSE on an early close, json's SyntaxError on malformed text, and the async-iterable TypeError for a stream with no readable side
- lower-stream's stream/consumers arm lowers text/json/buffer over one lowered stream argument (json answers a checked-dynamic promise — the JSON.parse unknown stance); arrayBuffer and blob fence module-qualified with pointed hints, since neither value has a representation
- Both backends emit sc.text/sc.json/sc.buffer; the trio joins the may-throw seeds, the loop-liveness set, and moduleUsesStream's link gate; the SC1010 hint, its snapshots, and the surface manifest gain stream/consumers
- Corpus 2604/2605 pin the consumers differentially on both backends and under ASan + RC audit: split multibyte sequences across chunks, encoded string-chunk streams, settle ordering, empty streams, and all four rejection arms
- A fences array denies manifest-identified surfaces reached by the compiled library graph: SC4008 names the id and surface with the profile's teaching as an attributed note; unreached fences leave emission byte-identical
- Fence evaluation walks the dead-stripped module IR — the same ground as the deterministic attestation, making the full-fences invariant structural
- Teachings generalize to any refusal code or manifest id; unknown or unpoliceable fence selectors refuse loudly rather than sit inert
- Teaching and remediation strings take the ratified byte constraints and the 512-byte cap everywhere
- Profile fences (determinism.fences) resolve at load against this release's surface manifest: exactly one of id/prefix, unknown selectors and unpoliceable static entries refuse SC4001 loudly (ratified strictness), folded constants exempt under a prefix only
- A fenced static surface reached by the compiled library graph refuses SC4008 at the reaching construct, over the same dead-stripped module IR the deterministic attestation reads; unreached fences emit byte-identical code
- The SC4004/SC4005 teaching rider generalizes: one decoration pass attaches profile text to any library refusal by code, manifest id, or fence coverage, rendered as a visibly-attributed note line the renderer prints after the hint
- Teaching/remediation strings now refuse every control byte below 0x20 except newline and cap at 512 UTF-8 bytes; fence remediations feed profileRemediation through covered entry codes
- K14 fence conformance on both emissions, fence-family SC4001 exact-path tests, and the ask-5 §4 pin: the full-fence worked-example profile compiles and attests deterministic: true
- The accepted server-side socket destroys on connection: relying on the peer's destroy to drain the server's connection count races the event loop under slow environments
- fs.exists' async fire compiles out under SCR_LIB and the compile-time scan refuses the surface with the event-loop family
- The regex-free size ceiling re-bases +8KB for the engine-handle arms and validation-ladder strings
- Library, npm-static, provenance, and diagnostics suites key their cache dirs by suite flavor, so concurrent plain and sanitized runs never race ar/ranlib
- The differential oracle publish is atomic: write-tmp then rename, so a concurrent reader can't see a truncated file
- Proven with three consecutive concurrent both-flavor rounds, zero failures
- Evolving-any receivers holding checked-dynamic values take keyed writes with ToPropertyKey-exact key spelling; dyn-keyed reads gain the same key stringification
- Array destructuring over dyn sources packs via the spread walk with V8's exact non-iterable TypeError wordings
- The dyn keyed-write miss error appends the primitive's rendering, matching Node
# Conflicts:
# packages/compiler/src/frontend/lowering/lower-exprs.ts
# packages/compiler/src/ir/validate.ts
- Per-API validators in the checked-dynamic lane run Node's argument checks in Node's order, then the real operation or a rendered fence thrown after validation
- fs.exists is genuinely async including the synchronous-false wart; mkdtempSync and lchmod are real
- Destructured sub-namespace bindings resolve as their module; function-armed unions cross into the checked-dynamic world
- dgram state errors carry their ERR_SOCKET codes
# Conflicts:
# packages/compiler/test/ts7/baselines/order-parity.json
- declare-erased roots make every chain rooted there a catchable ReferenceError at first touch, exactly Node's erasure semantics
- Never-read unmappable bindings emit nothing; nullish-cast bindings answer Node's exact TypeError on member access
- Assertion-supplied generic signatures register like annotations and monomorphize per call
- Stdlib generic members take the lib fence naming the member
# Conflicts:
# packages/compiler/src/frontend/lowering/lower-stmts.ts
# packages/compiler/test/ts7/baselines/order-parity.json
- Object.create(null) is a real null-prototype dictionary: inspect, toString, and deepStrictEqual answer Node's forms; the dynamic tier routes to the engine's own Object.create for live delegation
- Object prototypes fence by name in static builds — an own-copy stance is observably wrong under Node's empty-own-set answers and live proto mutations
- entries() and keys() walk any static array live in for-of heads and iterator-helper chains
- Object.assign(target, ...sources) packs spreads with JS's evaluation order before any copy, with V8's position-dependent error texts
# Conflicts:
# packages/compiler/test/ts7/baselines/order-parity.json
# packages/runtime/src/scr_json.c
- Unions carrying an object/unknown-flavored arm beside dyn-subsumable siblings map to dyn wholesale; typeof and isArray narrowing dispatch natively
- Class instances, Maps, Sets, functions, promises, and regexes stay excluded so typed semantics never degrade; the component fence names the blocking sibling
- A dyn element makes the whole array the DOM value; element reads and writes ride the routed machinery
# Conflicts:
# tests/harness/dyncheck.test.ts
- Keyed reads and writes, dynCall, and method dispatch on engine-held values route through the engine, which runs its own prototypes JS-exact
- One generic host shim carries boxed dyn functions into engine calls over the uniform thunk signature
- Nullish coalescing and optional chains unfence for every dyn value, engine-held or not
- Mixed island-vs-DOM deepStrictEqual comparisons loud-fence instead of minting a fabricated failure
- The formatter driver's support slice runs past its flatMap wall
- SCR_DYN_JSVAL wraps a retained engine cell; scalars normalize to native kinds at the boundary, so only objects, arrays, and functions ever wrap
- typeof, truthiness, strict equality, String(), and Array.isArray/instanceof-Error narrowing route through the engine; every unarmed walker loud-fences by name
- The identity round trip: an engine value crossing into dyn and back is the same engine value, by reference
- The silent-wrong-answer fence box is unreachable from engine members; the LLVM jsMarshal dyn case now mirrors C
- library-mode, library-contract (cache dir plus the tmpdir npm root), and library-asyncfree now carry a plain/san path segment: both flavors run the same ordinary builds, and the nightly's concurrent both-flavor recipe raced ar/ranlib in the shared dirs ("can't open file ... lib.lib.a"); the per-build -san tag stays, it distinguishes explicitly-sanitized builds within one suite
- the same flavor split lands on npm-static's fixed npm-static-workspace dir (the two flavors even build with different sanitize flags there), provenance's shared outDir, and diagnostics' $TMPDIR/scriptc-diag scratch (some entries emit backend artifacts before failing)
- dec-oracle publishes in the differential/llvm/linux/windows lanes are now atomic (write tmp, rename): the content-keyed path is shared across flavors and lanes, and a truncate-and-rewrite could expose a torn oracle to a concurrent reader
- every other suite already keys its build dirs by a content hash that includes the flavor, and the CAS build cache folds the sanitized flags into its key, so those stay as they are
- proof: three consecutive concurrent both-flavor library-mode runs from a wiped cache all pass 45/45 with zero ar/ranlib failures, and a concurrent both-flavor run of all four library suites passes 125/125 in each flavor
- mapType: a union with an 'object'/'unknown'/'{}'-flavored (dyn) arm beside only dyn-subsumable siblings — scalars, units, dynFrom-convertible records/arrays — maps to DYN wholesale; class/Map/Set/func/promise/regex arms keep their typed homes, and the SC2009 classifier now names the sibling that cannot ride the collapse instead of blaming the dyn arm.
- A dyn ELEMENT makes the whole array the DOM value (unknown[], object[], the plugins-slot (string | object)[]): the DOM array literal builds from TS annotations, .length on collapsed-array receivers is a DOM keyed read, element writes ride dyn.keySet (ARR index set/extend with undefined-hole padding), and for-of over dyn gets a pointed operation fence instead of the stale component story.
- Appendix-A repro 4 stops SC2009-fencing: an island plugins array wraps at the collapsed slot (dynFromJsval) and the element read reaches the loud keyed-read ladder until the routing lane arms it (dyncheck pin jsval-collapsed-union-slot).
- Corpus 2584/2585 differential both backends (guard ladder, option tables, unknown[] first-class; SAN clean); json-dyn snapshot repinned where the unknown[] declaration fence retires; conformance movers verified locally: discriminateObjectTypesOnly, unknownPropertiesAreAssignableToObjectUnion, unknownLikeUnionObjectFlagsNotPropagated.
- SEMANTICS 398 documents the collapse rule, the exact subsumable-arm domain, and the width/identity consequences (deep-copy entry, full-width JSON, per-site fences for non-subsumable values).
- 2578 catches the ReferenceError from ambient-rooted optional chains, generic call signatures, method chains, instantiation expressions, trap declarations, and assignment RHS roots
- 2579 pins the uncaught module-level trap: stdout up to the throw, exit 1, dead code past the unwind
- 2580 pins dead unmappable bindings, write-only bindings, and the assertion-shaped generic arrow (called on two instantiations)
- 2581 pins nullish generic bindings: the TypeError messages for null and undefined units, propagation, and nullish-to-nullish writes
- order-parity baselines re-recorded for the four new entries; byte-identical on both backends
- ambientUndefVarRootOf walks calls, `new`, optional chains, assertions, instantiation expressions, and tagged templates, and accepts `declare function` and trap-binding roots: Node erases the declaration, so the root read IS the crash — lowerCall, member reads, assignments, and variable declarations lower the whole statement to the catchable ReferenceError, arguments never evaluate, and the never-initialized binding registers as a trap whose references can never run
- never-read unmappable bindings with value-only initializers and writes emit nothing: Node builds the value and drops it, so `var xs2: typeof Array;` and the write-only `var f2: { <T, U>(x: T, y: U): T }` compile instead of fencing on a type the program never consumes
- null!/as-any bindings whose types keep generic signatures (or intern empty record shapes) register no storage; generic-method calls and member reads through them compile to Node's exact TypeError, nullish-to-nullish flows to nothing, heritage-clause uses decline the family so mixin resolution keeps its fence, and checked-dynamic (`any`) bindings keep their dyn story untouched
- assertion-shaped generic arrows (`< <T>(x: T) => T >((x) => x)`) register like annotated bindings and monomorphize per call; stdlib generic members (Promise.then, Object.defineProperty) take the SC2020 lib fence, and Function.prototype.apply/call/bind on compiled function values name the direct-call spelling
- diagnostics fixtures that used `declare` to conjure unconstructible values now conjure them by cast so each fence family keeps its pin; snapshots re-recorded, the deferred checker-panic diagnostic now flushes at its first reference as designed
- The tls server/secure-context walker validates every present typed option before the pem walk and its fences: the ciphers/passphrase/ecdhCurve string contracts, the engine trio's string-or-null-or-undefined clause, handshakeTimeout/sessionTimeout number contracts with validateInt32's exact range text, ticketKeys' view contract and exactly-48-bytes value ladder (Received renders the byte length, Node's shape), and minVersion/maxVersion's ERR_TLS_INVALID_PROTOCOL_VERSION with %j rendering. Literals carrying a validated key ride whole to the walker (JS sources), and createSecureContext gains the runtime-record form (tls.createSecureContextDyn) — a validated { cert, key } bag builds the real context.
- tls.connect validates checkServerIdentity's function contract with Node's presence semantics (a PRESENT key replaces the builtin verifier even holding undefined — the defaults spread); tls.getCACertificates walks validateString plus the documented name set before its fence.
- stream.finished/stream/promises.finished over a provably-non-stream value throw Node's isNodeStream ERR_INVALID_ARG_TYPE; socket write's two-argument encoding form implements the stream_base typecheck (write(string, 'buffer') is the synchronous "Second argument must be a buffer") with utf8 spellings as the plain write; Readable.toWeb's type option answers Node's one-of ladder.
- Unions with boxable FUNCTION arms now cross into the DOM (canConvertToDyn + both backends' union-to-dyn walkers) — the invalid-input probes iterate [1, null, () => {}, true]; scr_dyn_specific_type renders functions as Node's `function ${name}` (anonymous keeps the trailing space).
- Corpus 2581 (tls) and 2582 (stream, both backends) pin the ladders byte-identically vs Node.
- net.createServer with a provably-non-object argument, connect option bags (literal, computed-key, and runtime-record spellings) walking Node's Socket-constructor order — the objectMode trio's ERR_INVALID_ARG_VALUE, validatePort's ERR_SOCKET_BAD_PORT, host's string and autoSelectFamily's boolean contracts — and the autoSelectFamilyAttemptTimeout range ladder (validated and then inert, the single-dial simplification's sibling); setDefaultAutoSelectFamilyAttemptTimeout validates from 1 and keeps Node's sub-10ms floor.
- listen's and dgram.createSocket's options.signal answer validateAbortSignal's ERR_INVALID_ARG_TYPE for provably-non-AbortSignal values; plausible signals keep the fence (abort-driven close has no lowering yet).
- dgram.Socket.send replicates Node's signature shuffle over DOM arguments: slice type/bounds contracts (ERR_BUFFER_OUT_OF_BOUNDS over Buffers, subarrays, DataViews, and strings), the buffer-list per-element contract with the list as the Received tail, the unconnected port ladder with the specific-type tail and trailing period, the null/undefined-only address gate, and the connected-state ERR_SOCKET_DGRAM_IS_CONNECTED arms — a fully-validated unconnected single-payload send RUNS; callback/list/connected forms meet the post-validation fence. The dgram state errors now carry Node's ERR_SOCKET_* codes, and dgram bind/connect/close callbacks accept checked-dynamic wrappers through the dynCheck boundary.
- Corpus 2579 (net, both backends) and 2580 (dgram) pin the ladders byte-identically vs Node; order-parity baselines re-recorded.
- corpus 2578 (TS) and 2579 (JS, the JSDoc @param {object} repro shape) pin typeof/truthiness/String()/===, scalar normalization, representation-free narrowing, and the identity round trip against Node on both backends
- npm case jsval-into-dyn drives the prettier-plugins shape over a real package surface (the new plugstub fixture package: any-declared exports carrying engine functions)
- dyncheck jsval-* tests pin every loud fence (keyed read/write, member calls, 'in', destructuring, JSON.stringify, structuredClone, Object.keys, deepStrictEqual, inspect) plus the RC-clean catch-and-continue unwind under the SAN lane
- the errors.test.ts SC1101 pin flips to the now Node-exact behavior (the retired "one unbridgeable mix": the wrapped argument compiles and the unbound-this read throws Node's own TypeError); ts7 order-parity baselines record the three new fixtures
- coerceToExpected's expected-dyn/actual-jsval edge, the lib-boundary jsval-into-dyn-slot fence, DOM object-literal members, and index-signature value slots all wrap through the new dynFromJsval IR node — retiring the fence-closure silent-wrong-answer box for jsval members (typeof answered "function" and .length answered 0 there; the box remains only for non-jsval unconvertibles like unboxable-signature functions and func-carrying records)
- both backends emit the wrap (scr_dyn_from_jsval, borrowed operand, +1 out, infallible), and the LLVM jsMarshal gains the missing dyn case (scr_jsval_from_dyn) so dyn→island crossings — the identity unwrap included — stop detouring through the JSON serializer
- the emitted display (sc_ds), keyed-read (sc_dyn_key_get), and iter-N walkers grow JSVAL arms in both backends: engine-routed String(), the loud keyed-read fence with the key named, and the iteration fence instead of a false not-iterable claim
- dynTest/dynHasKey route the representation-free narrowing tests through the engine (typeof object/function, Array.isArray, instanceof Error) and fence 'in' loudly; validator rules pin dynFromJsval to exactly a jsval operand and a dyn result
- scr_dyn_from_jsval scalar-normalizes at wrap time (engine numbers/strings/booleans/null/undefined become native DOM kinds through the strict exits), so JSVAL nodes only ever hold engine objects/arrays/functions; the ops install like the promise-release hook, keeping the always-linked DOM core island-free
- typeof, truthiness, String(), and === route to the engine per use (scr_dyn_jsval_ops), the narrowing helpers (scr_dyn_isl_typeof_is/is_array/is_error) answer the engine's truth, and scr_jsval_from_dyn unwraps the SAME cell back — the identity round trip, nested members embedding by reference
- every un-armed DOM walk throws the loud "on an island value held in 'unknown' is not supported yet" ladder: keyed writes, method dispatch, calls, callback checks, 'in', spread, Object.keys/values/entries/hasOwn/assign/defineProperties, JSON.stringify/%j, structuredClone (options included), util.inspect (engine typeof named), deepStrictEqual (engine-identical answers true honestly), and dc subscription — never a silent wrong answer, never a false "is not a function"/"not iterable" claim
- assert's SameValue and strict_eq compare the ENGINE values (two wraps of one value are equal; a DOM copy is a different object, Node's answer too), and failure reports render wrapped operands as the depth-elided [island value] placeholder (the handle stance)
- The checked-dynamic fs.*Chk lane (JS sources) replicates Node-order argument validation over DOM values: exists/mkdtemp/readFile callback contracts, mkdtemp's prefix slot, assertEncoding on readFile/opendirSync/stream options, watchFile's path/listener pair, createReadStream/createWriteStream's options.fd and path contracts, fs.read's buffer/fd/offset/length/position ladder, and the lchmod family's cb/path/mode ladder with parseFileMode's octal-string and uint32-range arms — each throwing Node's exact ERR_INVALID_ARG_TYPE / ERR_INVALID_ARG_VALUE / ERR_OUT_OF_RANGE texts.
- A validated pass meets the honest tail: the real operation where one exists — fs.exists is REAL now (async answers through the callback, Node's synchronous-false wart for unvalidatable paths kept), mkdtempSync runs through the ladder, lchmodSync/fsPromises.lchmod apply lchmod(2) on macOS and answer Node's not-a-function / ERR_METHOD_NOT_IMPLEMENTED shapes elsewhere — or the compiler-rendered SC2020 fence thrown AFTER validation (scr_throw_lowering_fence), so Node's errors always come first.
- error.propTypeThrow joins argTypeThrow as the property-flavored always-throwing lowered arm; scr_dyn_prop_type_fail / scr_dyn_arg_value_fail / scr_num_received become shared runtime vocabulary for the remaining option-bag ladders.
- Destructured sub-namespace bindings (const { promises } = fs) resolve as the module they are, so fs.promises members reach their lowerings through that spelling.
- Corpus 2578 pins the whole surface byte-identically on both backends; order-parity baselines re-recorded for the new fixture.
- Static builds mint a DOM object flagged prototype-free: own-member walks are already Node's null-proto answers; inspect prefixes [Object: null prototype] (nested/empty/beyond-depth forms), o.toString() throws Node's "is not a function" (dyn.toString carries the source spelling), and deepStrictEqual gains the prototype gate, diff rendering included
- Under --dynamic Object.create routes through the engine's own Object.create for null and engine-held prototypes — live delegation, shadowing writes, and mutation-through-proto all Node-exact
- DOM and static-record prototypes fence with the reason instead of the design doc's own-copy stance: Object.keys/inspect/JSON answer the EMPTY own set in Node and prototype mutations show through live, which no copy answers honestly
- Element writes on plain dyn receivers ride dyn.keySet generally (the result[key] = value memo idiom; unmapped static-any receivers probe their lowered world), unblocking the dictionary's use
- Corpus 2581 (static, byte-for-byte both backends) and 2582 (@dynamic engine route); diagnostics object-create-fences pins the three named fences
- Documented residue: String()/template/join over a null-proto DOM value answer [object Object] where Node throws — the emitted String(unknown) walkers are never-throw by contract
- Runtime-keyed writes on receivers that lower dyn (untyped evolving lets holding object literals, JSON.parse results, unknown slots) emit dyn.keySet — number/bool/dyn keys stringify per ToPropertyKey, values convert into the DOM with closures crossing as the callable kind — and the dyn-keyed read stringifies bool/dyn keys the same way, so an object built up through runtime keys dispatches its stored closures back out.
- Array destructuring over dyn sources packs once through the new scr_dyn_iter_pack (arrays element-by-element, strings by code point, bytes by byte) and binds positions as DOM index reads: holes, past-the-end undefined, defaults firing exactly on undefined, and nested patterns all ride it; non-iterable kinds throw V8's exact destructuring TypeError, spelled statically for identifier and identifier-callee sources, kind-worded otherwise.
- dyn.keySet's strict-mode TypeError now quotes the primitive receiver's rendering ("on number '5'"), V8's wording; rest elements over dyn sources and dyn-source defaults that cannot convert into the DOM keep honest fences.
- Fixtures 2578-2581: the warning-catcher harness shape (runtime-keyed writes of closures plus the Object.keys map arm), DOM keyed-write ops with Node's non-object-receiver TypeErrors, the destructure family with all TypeError wordings, and the island keyed write under --dynamic — byte-identical against Node through both backends, plain and sanitized.
- Head-consumed keys()/entries() over array receivers ride the live index walk (length re-read per pass — the array iterator's contract), yielding the index or the checker's [number, T] pair; plain [i, v] heads bind straight from the reads, identifier/pattern/var heads bind the interned tuple
- Iterator-helper chains accept entries() as the source: the pair seeds the fused per-element walk, so map/filter/flatMap/take/drop and every terminal compose over [index, element] tuples unchanged
- values() keeps its existing receiver unwrap; dyn receivers keep their loud runtime fence (no dyn for-of iteration exists to ride)
- Corpus 2579 pins the for-of head shapes (liveness, holes, object patterns, let/var) and 2580 the chain matrix, byte-for-byte on both backends
- Object.assign(target, ...sources) packs every source into one fresh DOM array before any copying (JS's ArgumentListEvaluation: a throwing spread leaves the target untouched), then copies own enumerable keys left to right and answers the target — identity, like JS
- V8's spread TypeError texts split by position: the single-last spread keeps the optimized apply-path texts (nullish spells the expression), every other position takes the iterator-protocol texts describing the value (scr_dyn_pack_push_spread_iter)
- scr_dyn_assign's copy walk now rides the entries walk, so array/string/bytes sources contribute their index keys exactly as Object.keys lists them (two-arg form included)
- Targets: dyn values, fresh object literals (no alias exists — the DOM build is unobservable), and nullish units (Node's ToObject TypeError, catchably)
- Corpus 2578 pins the support.js shape, identity, ordering, source-kind matrix, and every error text byte-for-byte on both backends
- a socket whose dial hasn't started (the agent's maxSockets queue, the caller-lookup wait) has no fd but is logically connecting: write bytes now buffer and flush at establishment instead of silently dropping, which left the queued exchange (and the program) hanging
- all five differential fixtures (2573-2577) match Node byte-for-byte
- Array patterns over strings split by code points via the string-iterator machinery: positions, holes, defaults, rest, nesting, and for-of heads
- Destructured stdlib-global members bind their builtin identity tokens with Node-agreeing === identity; aliases register the twin
- Surfaced-global members like Math.max fence eagerly by name — a token would quietly degrade them
- Object patterns over strings bind length; wrapper-method extraction names the detached method
# Conflicts:
# packages/compiler/test/ts7/baselines/order-parity.json