Commit Graph
101 Commits
Author SHA1 Message Date
Chris Tate fdf5010b28 Prepare v0.0.20 release
- Stamp all publishable packages at v0.0.20.

- Publish release notes for the contract-sidecar improvements.

- Refresh the compiler surface manifest for the release.
2026-07-30 16:26:39 -05:00
Chris Tate 1bd7e4af2e Prepare v0.0.19 release
- Stamp all published packages and the compiler surface manifest at 0.0.19.
- Promote the completed integer-slot fixes into the marked release notes.
2026-07-30 13:36:35 -05:00
Chris Tate 7f68aa1676 Prepare v0.0.18 release
- Stamp all publishable packages and the surface manifest at 0.0.18.
- Promote the curated Unreleased notes and release markers to v0.0.18.
2026-07-30 09:29:36 -05:00
Chris Tate f47ee03dc6 Support array copying and Uint8Array iteration
- Add static Array and Uint8Array copying, sorting, and join surfaces.
- Lower Uint8Array spread, destructuring, and iterator methods across C and LLVM.
- Pin Node 24 semantics with differential coverage and runtime size gating.
2026-07-29 18:03:00 -05:00
Chris Tate a992b644fb fix: align Array.toSorted ordering semantics 2026-07-29 15:30:48 -05:00
Chris Tate 9b0ad004f8 Fix top-level await rejection checkpoints 2026-07-29 01:32:26 -05:00
Chris Tate 05752fde96 Fix top-level await dependency rejection handling 2026-07-29 00:35:35 -05:00
Chris Tate 786f10dbf2 Fix top-level await cycle semantics 2026-07-28 23:27:25 -05:00
Chris Tate 2d9070cd54 fix top-level await rejection handling 2026-07-28 22:01:32 -05:00
Chris Tate ad56e7716a Merge branch 'main' into ctate/top-level-await 2026-07-28 20:57:35 -05:00
Chris Tate 177d025452 Harden sandbox gate across host platforms
- Retain representative Darwin kqueue coverage in the default gate.
- Schedule native runtime tests by host and make Linux clang invocations portable.
- Resolve canonical OCI manifest digests for direct and indexed images.
2026-07-28 17:48:17 -05:00
Chris Tate a504ccb850 Cut full sandbox validation to four minutes
- Shard portable coverage across 16 sandboxes while retaining focused Darwin contracts.

- Run invariant suites once and keep differential and sanitizer-sensitive coverage in both lanes.

- Harden sandbox transport, exit-status parsing, and Linux runtime test portability.
2026-07-28 14:58:34 -05:00
Chris Tate e88ddc1678 Support top-level await
- Lower asynchronous ESM initialization with Node-compatible dependency ordering and caching.
- Finish top-level promises consistently across the C and LLVM runtimes.
- Add differential coverage for imports, rejection, and unsettled evaluation.
2026-07-28 11:19:04 -05:00
Chris Tate 820b8f2edf Merge pull request #14 from vercel-labs/ctate/v0.0.17
Prepare v0.0.17 release
2026-07-26 21:14:11 -05:00
Chris Tate e6de55819f Prepare v0.0.17 release
- Stamp the runtime, compiler, and CLI packages at 0.0.17.
- Regenerate the surface manifest for the synchronized version.
- Add release notes for the Windows CLI build and run fixes.
2026-07-26 20:32:46 -05:00
Chris Tate bc2cd2b7d1 Support Number.toFixed statically
- Lower Number.prototype.toFixed through the compiler IR and native backends.
- Match JavaScript rounding, range errors, and numeric edge cases in the runtime.
- Add differential coverage and update surface metadata and diagnostics.
2026-07-26 18:43:53 -05:00
Chris Tate aacfc4cbf0 Prepare v0.0.16 release
- Synchronize package versions and regenerate the compiler surface manifest.
- Publish release notes for prompt output flushing and Linux host clang builds.
2026-07-26 10:22:45 -05:00
Chris Tate 481dd9c974 fix: flush console output promptly
- Submit console, process, readline, and island writes before returning.
- Add live-pipe and SIGKILL parity coverage against Node 24.
2026-07-26 01:30:42 -05:00
Chris Tate 3817e74e74 chore: release v0.0.15
- Bump all published packages to 0.0.15 and refresh the surface manifest.
- Promote the outbound native FFI notes into the marked release block.
- Verify the workspace build plus plain and sanitized full test lanes.
2026-07-25 12:48:14 -05:00
Chris Tate ee1f8697b8 Release 0.0.14 2026-07-24 23:30:35 -05:00
Chris Tate a7538fd87d URL-string and URL-object arguments to the http and https clients
- `http.get("http://host/path")` and its https spelling now compile. The declarations only described the options-record form, so the first thing a from-scratch client writes was a type error — the shape worked under --dynamic, where the engine does not consult our declarations, which is how it read as a hello-world failure.
- A URL object is accepted the same way, as its href through the same parse. An unparsable input is the WHATWG "Invalid URL" TypeError and a scheme that is not the calling module's is ERR_INVALID_PROTOCOL, both catchable, matching Node rather than silently upgrading the dial.
- `request` and `get` take one signature with a union first parameter instead of Node's two overloads: `tls ? https.request : http.request` unions two function types, and resolving a call on that union collapses each side to a single signature, so an overload set misresolves in either declaration order. The lowering dispatches on the argument's own type.
- Both rows run on the LLVM backend, and the tls CA-store entries joined it too — the omission there was stale, so 2557-tls-ca-store moved off the C lane with identical output.
- Corpus 2644 and 2645 cover both schemes against loopback servers, so neither needs the network.
2026-07-24 23:24:53 -05:00
Chris Tate 46643230d8 Resolve hostnames at the client dial
- http, https, TLS and HTTP/2 clients now resolve the hostname before connecting. A client that dialed by name got ENOTFOUND regardless of the name — only literal addresses worked, which is most of what a from-scratch client writes.
- Only the dial takes the address. The original name stays on the request, which is what the Host header carries and what SNI and certificate verification see, so a resolved dial does not weaken the TLS check.
- node:net's own connect surface stays resolver-less: Node's async lookup semantics there are a separate piece of work, so `net.connect(port, hostname)` still refuses to resolve.
2026-07-24 23:24:41 -05:00
Chris Tate 91245d659f Release 0.0.13 2026-07-24 21:20:01 -05:00
Chris Tate 44d05d8e74 Route the compiler's dyn world onto the engine's own operations
- Island values held in `unknown` arm the routed operation set (SCR_DYN_JSVAL): keyed reads and writes, calls and method dispatch, Object statics, and `??` all run in the engine, so a wrapped value answers exactly what Node answers instead of meeting a fence.
- Scalars normalize at the wrap, composites stay engine values by reference, and the round trip preserves identity — a value that crosses into the checked-dynamic tree and back is the same engine value.
- deepStrictEqual over a mixed engine-vs-native pair fails with the reason stated rather than guessing at an answer.
- Corpus 2582–2585 and an npm routed-row fixture pin the behavior; the dyncheck expectations move with it.
- The retired "DOM" nickname is swept out of the sources and corpus in the same pass (29 comment sites) — the world is the checked-dynamic tree, its values are dyn values.
2026-07-24 19:53:10 -05:00
Chris Tate 27e7537cec Crypto introspection, the TLS CA store, and the http2/rejection tail
- The crypto introspection statics (getFips and the cipher/hash/curve name lists) bake at the call site, and the crypto constant table joins http2's under a generalized per-module baked-constants lowering.
- The CA-store introspection surface lands in its own unit (scr_tls_ca.c) behind its own link gate, so a getCACertificates-only binary never pulls mbedTLS: getCACertificates, rootCertificates, setDefaultCACertificates.
- http2.createSecureServer grows the eager request handler and the runtime options record, riding the same server-options walk as tls.createServer; string-typed 'data' listeners decode.
- process once/off for 'unhandledRejection' plus the sibling 'rejectionHandled' registry, removal by closure identity per the warning-registry stance.
- Merge resolution unions this lane with main's fs ladders, createRequire erasure, and dyn secure-context work; the runtime's retired "DOM" nickname is spelled "dyn" throughout.
2026-07-24 19:49:54 -05:00
Chris Tate 2c0f01ad93 HTTP Agent and dynamic-handle compatibility
- Add Agent connection accounting and HTTP/socket compatibility surfaces
- Support dynamic Buffer at and slice access
- Pin behavior with differential corpus coverage
2026-07-24 18:52:19 -05:00
Chris Tate 6ce1a44c80 Release 0.0.12 2026-07-24 18:23:39 -05:00
Chris Tate e947502af6 The long tail of engine-held values: iteration, promises crossing, and the driver through its plugin pipeline
- for-of, destructuring, and spread over engine-held dyn values ride the engine's own iterator protocol with V8's exact non-iterable spellings; for-of over dyn lowers generally
- Static promises cross into the engine as thenables; Promise.all over mixed and non-literal entries runs the engine's own combinator; engine-array fulfillments exit by reference
- The re-minted silent-wrong-answer path is closed: island-literal members whose values poison fence at the read with the captured diagnostic
- The checked-dynamic tree replaces the old nickname across comments and internal docs
2026-07-24 17:17:00 -05:00
Chris Tate e96d1264c1 Release 0.0.11 2026-07-24 12:47:01 -05:00
Chris Tate 07c9a4128c node:stream/consumers compiles statically; createRequire erases to static requires
- text, json, and buffer settle real promises over the readable machinery with Node's settle timing and rejection set; arrayBuffer and blob fence with their representation reasons
- createRequire over this file's URL is compile-time plumbing: builtin specs become namespace imports, relative JSON bakes as validated documents, npm packages ride the require-condition graph, unresolvable names throw Node's catchable MODULE_NOT_FOUND
- module.builtinModules bakes as the compat target's exact list

# Conflicts:
#	packages/compiler/src/frontend/lowering/lower-modules.ts
#	packages/compiler/src/frontend/lowering/lowerer.ts
2026-07-24 12:13:08 -05:00
Chris Tate aac4f9390b Buffer views alias for real; stream ticks interleave with process.nextTick in Node's order
- Buffer slice and subarray become true aliasing views over the retained owner — mutating through a view was silently computing wrong bytes
- Each stream tick posts a one-to-one marker on the user tick queue, so stream emissions interleave with process.nextTick in enqueue order, Node's order by construction; the station remains for teardown
- Stream emitters model the pre-created event-key shape governing eventNames order; push honors defaultEncoding with Node's unknown-encoding errors

# Conflicts:
#	packages/compiler/test/ts7/baselines/order-parity.json
2026-07-24 12:11:31 -05:00
Chris Tate 034195f588 Profile-declared integer boundary slots prove or refuse at compile time
- An interval-and-wholeness inference over the lowered IR proves integrality and range for every value reaching a declared i64/u64 slot, with loop-header widening precise enough that the bounded counter loop proves its exact range
- Refusals carry the slot path, the failed obligation with evidence, and the author's concrete fix as SC4021, SC4022, and SC4023
- Declared slots are both obligation and assumption: call sites check arguments, callee bodies assume their classes; integer returns emit exact machine-integer wrappers and inbound params trap through the structured host-contract family
- Math.trunc and Math.ceil compile statically

# Conflicts:
#	packages/compiler/src/library/profile.ts
2026-07-24 12:07:29 -05:00
Chris Tate 01b47dd78b Promise.all over non-literal 'any[]' arguments runs engine-side; island values bridge into Promise-typed slots with the any[] settle payload
- The loadPlugins shape end-to-end: Promise.all(plugins.map((p) => loadPlugin(p))) — a NON-literal argument the checker spells any[] — lowers to the ENGINE's own Promise.all over the lifted array, and the INFERRED Promise<any[]> return coerces through the island→static promise bridge with the new SCR_ISLP_JSVAL_ARR settle payload: the fulfillment exits Array.isArray-gated BY REFERENCE at the settle, a lying fulfillment rejecting with the boundary TypeError (trust-but-verify at the settle).
- coerceToExpected's jsval branch gains the promise-slot arm generally: island values flowing into Promise<void>/Promise<any>/Promise<any[]>-typed slots bridge instead of fencing (the passing-a-package-promise-into-promise-typed-parameters fence retires for these inners); other inners keep the named fence.
- Corpus 2605 extended with the non-literal all + inferred-return rows, byte-identical to Node under both backends and SAN-clean; dyncheck/errors/island suites green.
2026-07-24 11:51:34 -05:00
Chris Tate c1be329607 Static promises cross into the island as real engine thenables; Promise.all over mixed island/static entries runs the engine's own combinator
- jsvalIn (and the island-literal member path behind it) accepts STATIC promises whose fulfillment is in the reverse bridge's payload domain — void/number/boolean/string/'any', plus the NEW Promise<any[]> payload (SCR_ISLP_JSVAL_ARR: a native array of engine cells re-enters as a fresh engine array over the SAME engine values). scr_jsval_from_promise emits from jsMarshal in both backends; the IR validator admits the arm.
- Promise.all with MIXED entries where some entry is an island value (the withPlugins shape: Promise.all([loadBuiltinPlugins(), loadPlugins(plugins)])) lowers to the ENGINE's own Promise.all — island entries pass through, static promises bridge as thenables, and the combined result stays an island value the static side awaits through the existing island→static bridge. All-static tuples keep the typed fence hint.
- Corpus 2605 (unawaited static promise in an 'any' slot answers typeof "object" and awaits engine-side; the mixed-all + .flat() chain) is byte-identical to Node under both backends; SAN clean. Composite fulfillments (Promise<{...}[]>) stay fenced with the promise type named — the payload-domain residue.
2026-07-24 11:32:57 -05:00
Chris Tate 10696c70f8 Profile-declared i64/u64 integer slots: surface, wiring, wrappers, host-contract trap
- LIB_PARAM_CLASSES/LIB_RETURN_CLASSES grow i64/u64 (the prove-or-refuse pair); u8/u32/i32 stay param-only with the message updated to point at the landed machinery
- sidecar.integer_slots declares contract slots by sidecar path (Msg.count, Point.x, helpers.f.params[0], helpers.f.return); the projection spells each declared slot i64 (the frozen format-1 vocabulary — u64 is the stricter compile-time obligation over the same wire spelling), refuses non-number or unresolvable paths, and emits integer_slots as the resolved-decision attestation in declaration order
- compileLibrary runs the integer-boundary inference over export-map and sidecar-declared slots and refuses SC4021 (representability) / SC4022 (wholeness) / SC4023 (range), each carrying slot path, failed obligation with evidence, and the author's fix; u8/u32/i32 plumbing classes seed parameter shapes for free precision
- Both emitters grow i64/u64 wrappers: inbound params range-check through scr_library_i64_in/u64_in (the SC4012 host-contract trap — silent rounding past 2^53 is a coercion the author never wrote), returns convert exactly under the discharged proof
- Profile-loader suite pins the new surface; the pre-ask-4 pins updated
2026-07-24 11:29:30 -05:00
Chris Tate 6b6445ab90 Retire the "DOM" nickname in comments, internal docs, and message prose: the checked-dynamic tree / dyn values
- The ratified rename rider (world-unification §7 lane 5): "DOM" collided with the browser DOM and, post-lane-1, the structure is no longer a document tree. Comments and doc prose now say "the checked-dynamic tree" for the noun and "dyn" adjectivally; runtime symbol names (scr_dyn_*), the error.domClone libCall, and the real web DOMException family are unchanged.
- The few user-facing strings carrying the nickname move with it (the structuredClone cyclic message, the dc subscriber/publish fences, two emitter ICE texts); diagnostics snapshots regenerated (96 pass). One private compiler constant (DOM_PROTO_METHOD_NAMES -> DYN_PROTO_METHOD_NAMES) rides along.
- Mechanical sweep, 142 files, comments/prose only — no behavior change.
2026-07-24 11:14:58 -05:00
Chris Tate b98d726382 for-of, destructuring, and spread over island values held in 'unknown' drain the engine's own iterator; engine arrays exit into 'any[]' slots
- The iteration pack's JSVAL arm is ARMED (scr_dyn_iter_pack, scr_dyn_arr_push_spread, scr_dyn_pack_push_spread_iter route through the new iter_drain ops row): the ENGINE's iterator protocol drains into a fresh DOM array — engine arrays, generators, Maps, Sets, and Symbol.iterator implementations step exactly as Node runs them, elements wrapping back scalar-normalized.
- for-of over checked-dynamic values LOWERS now (both backends): the source packs once through dyn.iterPack and a hidden index loop binds each element as a dyn value (new dyn.arrLen/dyn.arrAt accessors) — an eager snapshot, the matchAll stance. Pattern heads, pre-declared and var heads, and labeled break/continue all ride the desugar. Non-iterables throw V8's for-of CallPrinter spellings, threaded into the engine-side guard.
- The validated exit gains the jsval-element-array arm (scr_jsval_exit_jsval_arr, both backends): an 'any' value exits into 'any[]'- and 'any[] | undefined'-declared slots Array.isArray-gated, elements BY REFERENCE (identity crosses, the spine is a snapshot) — the withPlugins loadPlugins(plugins) boundary, the driver frontier's first named poison.
- Corpus 2604 and npm case jsval-iterate (package-minted Set/Map/generator/Symbol.iterator) are byte-identical to Node under both backends; dyncheck's jsval-iterate pin flips from the retired island fence to the armed answers; SAN clean over the drain/wrap/exit churn.
2026-07-24 11:04:10 -05:00
Chris Tate 071e5644fd Named capture groups compile end to end
- 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
2026-07-24 10:50:22 -05:00
Chris Tate 65bab3d8cd Named capture groups compile end to end
- 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
2026-07-24 10:41:37 -05:00
Chris Tate 6f2de332db Readable push encodings: defaultEncoding decodes string pushes, explicit literals override, unknown spellings take Node's ERR_UNKNOWN_ENCODING
- 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
2026-07-24 10:30:47 -05:00
Chris Tate 567af934f1 Release 0.0.10 2026-07-24 10:03:40 -05:00
Chris Tate 2785bb09f9 Stream ticks ride the user nextTick queue: FIFO with process.nextTick, Node's order
- 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
2026-07-24 09:47:43 -05:00
Chris Tate 6e9467821f Stream emitters model Node's kShapeMode: pre-created event keys govern eventNames order
- 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
2026-07-24 09:40:01 -05:00
Chris Tate 135aec0383 Buffer slice/subarray become true aliasing views; typed arrays gain element fill and Buffer.from(x.buffer)
- 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
2026-07-24 09:28:37 -05:00
Chris Tate 417ece6724 node:stream/consumers compiles statically: text, json, and buffer settle real promises
- 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
2026-07-24 09:27:44 -05:00
Chris Tate 88ff8eaa60 Library links stay timer-free with the real fs.exists; the regex size arm re-bases
- 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
2026-07-24 08:33:32 -05:00
Chris Tate 8cb44e4345 Record order-parity baselines and the island destructuring fence for the merged train
- Baselines for the renumbered fixtures, purely additive
- iterPack loud-fences engine-held sources instead of claiming not-iterable on values Node iterates
2026-07-24 08:15:35 -05:00
Chris Tate a16ee028ee Keyed writes land on dynamic receivers; array destructuring walks dyn sources
- 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
2026-07-24 08:09:34 -05:00
Chris Tate e4bd46c826 fs, net, dgram, tls, and stream misuse throws Node's validation ladders
- 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
2026-07-24 08:07:01 -05:00
Chris Tate c48a21b9ef Object.create, array entries and keys iterators, and variadic-spread Object.assign
- 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
2026-07-24 08:03:58 -05:00