@scriptc/runtime 0.0.10 → 0.0.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@scriptc/runtime",
3
- "version": "0.0.10",
3
+ "version": "0.0.12",
4
4
  "description": "scriptc native runtime — C sources, compiled into every scriptc binary",
5
5
  "license": "Apache-2.0",
6
6
  "homepage": "https://scriptc.dev",
package/src/scr_assert.c CHANGED
@@ -396,15 +396,15 @@ void scr_assert_ref_eq_fn(const ScrClosure *a, const ScrClosure *b, bool negated
396
396
  }
397
397
 
398
398
  /* ── strictEqual / deepStrictEqual over CHECKED-DYNAMIC (dyn) operands ──
399
- * The DOM carries the value's kind at runtime, so one entry point serves
399
+ * The checked-dynamic tree carries the value's kind at runtime, so one entry point serves
400
400
  * the whole quartet: SameValue for the strict pair (numbers by Object.is,
401
401
  * strings by bytes, units by kind, arrays/objects/bytes by node identity,
402
402
  * functions by the BOXED CLOSURE — two dyn crossings of one function are
403
- * the same JS function), a structural DOM walk for the deep pair.
403
+ * the same JS function), a structural dyn walk for the deep pair.
404
404
  *
405
405
  * Failure messages reproduce Node's assertion_error.js against the v24
406
406
  * sources: inspectValue is a compact:false / sorted:true / depth-1000
407
- * rendering of the DOM (each entry on its own line, entries sorted by
407
+ * rendering of the checked-dynamic tree (each entry on its own line, entries sorted by
408
408
  * their RENDERED text — Node's `sorted: true` sorts formatted entries),
409
409
  * the simple/stacked scalar forms match the static paths byte-for-byte,
410
410
  * and composite diffs run the real myers line diff with Node's printer
@@ -415,7 +415,7 @@ void scr_assert_ref_eq_fn(const ScrClosure *a, const ScrClosure *b, bool negated
415
415
  * the [Function: name] form, and values rendering past ~4096 lines fall
416
416
  * back to the whole-value +/- form without context collapsing. */
417
417
 
418
- /* JS SameValue over two DOM values (Object.is — the strictEqual and
418
+ /* JS SameValue over two dyn values (Object.is — the strictEqual and
419
419
  * notStrictEqual comparison). Functions compare by boxed closure: the
420
420
  * ScrDyn box is a boundary artifact, the closure IS the JS identity. */
421
421
  static bool scr_assert_dyn_same_value(const ScrDyn *a, const ScrDyn *b) {
@@ -449,19 +449,19 @@ static bool scr_assert_dyn_same_value(const ScrDyn *a, const ScrDyn *b) {
449
449
  }
450
450
  }
451
451
 
452
- /* Node's strict deep equality over two DOM values: kind-wise — Object.is
452
+ /* Node's strict deep equality over two dyn values: kind-wise — Object.is
453
453
  * numbers, byte-equal strings, units by kind, per-element arrays,
454
- * key-set-plus-values objects (DOM keys are unique, so equal lengths and
454
+ * key-set-plus-values objects (dyn keys are unique, so equal lengths and
455
455
  * an a⊆b value walk prove the bijection), brand-aware bytes (the buffer
456
456
  * flavor bit IS the Buffer-vs-Uint8Array prototype Node compares first),
457
457
  * reference identity for functions (boxed closure). Plain recursion:
458
- * JSON-origin DOMs are trees; a keyed-write cycle (h.self = h) has no
458
+ * JSON-origin dyn values are trees; a keyed-write cycle (h.self = h) has no
459
459
  * memo here where Node carries one (documented divergence). */
460
460
  static bool scr_assert_dyn_deep_eq(const ScrDyn *a, const ScrDyn *b) {
461
461
  if (a == b) return true;
462
462
  if (a->kind != b->kind) {
463
463
  /* A MIXED comparison with an island side (wrapped engine object vs
464
- * DOM data): Node walks both structurally — a plain `false` would
464
+ * dyn data): Node walks both structurally — a plain `false` would
465
465
  * mint a fabricated AssertionError for values Node may call equal.
466
466
  * Loud fence (the long-tail lane's structural walk). */
467
467
  if (a->kind == SCR_DYN_JSVAL || b->kind == SCR_DYN_JSVAL) {
@@ -528,7 +528,7 @@ static bool scr_assert_dyn_deep_eq(const ScrDyn *a, const ScrDyn *b) {
528
528
  return false; /* unreachable */
529
529
  }
530
530
 
531
- /* ── inspectValue over the DOM (assertion_error.js's inspect options:
531
+ /* ── inspectValue over the checked-dynamic tree (assertion_error.js's inspect options:
532
532
  * compact:false, sorted:true, depth 1000, maxArrayLength Infinity) ───── */
533
533
 
534
534
  #define SCR_ASSERT_CF_DEPTH 1000
@@ -924,7 +924,7 @@ static bool scr_assert_print_myers(ScrAssertBuf *b, const ScrDiffOp *diff, size_
924
924
 
925
925
  /* ── the dyn entry point ─────────────────────────────────────────────── */
926
926
 
927
- /* Is this DOM kind `typeof == "object" && != null` to assertion_error.js? */
927
+ /* Is this dyn kind `typeof == "object" && != null` to assertion_error.js? */
928
928
  static bool scr_assert_dyn_is_object(const ScrDyn *d) {
929
929
  return d->kind == SCR_DYN_ARR || d->kind == SCR_DYN_OBJ || d->kind == SCR_DYN_BYTES ||
930
930
  d->kind == SCR_DYN_HANDLE || d->kind == SCR_DYN_PROMISE ||
@@ -1095,7 +1095,7 @@ static void scr_assert_dyn_neq_fail(ScrDyn *a, bool deep, ScrStr *msg, bool has_
1095
1095
  }
1096
1096
 
1097
1097
  /* strictEqual / notStrictEqual / deepStrictEqual / notDeepStrictEqual
1098
- * where either operand is a checked-dynamic value (both arrive as DOM
1098
+ * where either operand is a checked-dynamic value (both arrive as dyn
1099
1099
  * values — the frontend boxes a static side). Borrows everything. */
1100
1100
  void scr_assert_eq_dyn(ScrDyn *a, ScrDyn *b, bool negated, bool deep,
1101
1101
  ScrStr *msg, bool has_msg) {
@@ -1113,7 +1113,7 @@ void scr_assert_eq_dyn(ScrDyn *a, ScrDyn *b, bool negated, bool deep,
1113
1113
  }
1114
1114
 
1115
1115
  /* Node's expectsError over an error-INSTANCE expected (assert.throws/
1116
- * rejects second argument): every key of the expected DOM error (the
1116
+ * rejects second argument): every key of the expected dyn error (the
1117
1117
  * %error marker skipped; name/message/code is the encoding's surface)
1118
1118
  * must deep-strict-equal the caught value's — extra ACTUAL keys are fine
1119
1119
  * (Node walks the expected's keys only). A mismatch fails through the
@@ -1441,7 +1441,7 @@ void scr_assert_iferror_bool(bool v) {
1441
1441
  }
1442
1442
 
1443
1443
  /* The checked-dynamic argument (test/common's mustSucceed wrapper): the
1444
- * DOM kind dispatches — units pass quietly, %error-marked objects (the
1444
+ * dyn kind dispatches — units pass quietly, %error-marked objects (the
1445
1445
  * caughtToDyn encoding) throw with the error's message (its name when
1446
1446
  * the message is empty, Node's rule), everything else throws with the
1447
1447
  * value's inspection. */
package/src/scr_async.c CHANGED
@@ -272,7 +272,7 @@ struct ScrFiber {
272
272
 
273
273
  /* ── AsyncLocalStorage (node:async_hooks) ─────────────────────────────
274
274
  * Stores are process-lived ids; the CONTEXT is an immutable refcounted
275
- * snapshot of (store id → DOM value) entries. One ACTIVE SLOT pointer
275
+ * snapshot of (store id → dyn value) entries. One ACTIVE SLOT pointer
276
276
  * (the exc-cell pattern): main owns a static slot, every fiber owns its
277
277
  * own field, scr_switch repoints the active slot — so run()'s window
278
278
  * rides the fiber across awaits, and a spawned fiber INHERITS the
@@ -591,7 +591,8 @@ ScrArr *scr_active_resources(void) {
591
591
  * left queued on the uncaught paths) never run — the teardown releases
592
592
  * them, like Node dropping the queue at exit. */
593
593
  typedef struct ScrNtick {
594
- ScrClosure *cb; /* owned */
594
+ ScrClosure *cb; /* owned; NULL for a raw C-hook entry */
595
+ void (*raw)(void); /* the hook when cb == NULL (stream tick markers) */
595
596
  struct ScrNtick *next;
596
597
  } ScrNtick;
597
598
 
@@ -612,11 +613,25 @@ void scr_next_tick(ScrClosure *cb /*moves*/) {
612
613
  scr_nt_tail = t;
613
614
  }
614
615
 
616
+ /* A RAW C-hook tick: the stream unit enqueues one marker per deferred
617
+ * stream emission so those emissions interleave with user nextTicks in
618
+ * true FIFO order — in Node they ARE nextTicks (resume_, emitReadable_,
619
+ * endReadableNT, ...). The hook dispatches exactly one stream tick;
620
+ * teardown just drops markers (the stream queue owns its entries). */
621
+ void scr_next_tick_raw(void (*fn)(void)) {
622
+ ScrNtick *t = calloc(1, sizeof *t);
623
+ if (!t) scr_oom();
624
+ t->raw = fn;
625
+ if (scr_nt_tail) scr_nt_tail->next = t;
626
+ else scr_nt_head = t;
627
+ scr_nt_tail = t;
628
+ }
629
+
615
630
  void scr_nticks_teardown(void) {
616
631
  while (scr_nt_head != NULL) {
617
632
  ScrNtick *t = scr_nt_head;
618
633
  scr_nt_head = t->next;
619
- scr_closure_release(t->cb);
634
+ if (t->cb) scr_closure_release(t->cb);
620
635
  free(t);
621
636
  }
622
637
  scr_nt_tail = NULL;
@@ -1009,7 +1024,7 @@ ScrStr *scr_promise_payload_str(ScrPromise *p) {
1009
1024
  return scr_str_retain((ScrStr *)p->payload);
1010
1025
  }
1011
1026
  /* Thin views for the gated dyn-async TU (scr_async_dyn.c): the payload
1012
- * KIND, whether a REF payload is a DOM value (the dyn adapters), and the
1027
+ * KIND, whether a REF payload is a dyn value (the dyn adapters), and the
1013
1028
  * settled-await primitive (park/hop + rejection re-throw; true =
1014
1029
  * fulfilled). */
1015
1030
  static bool scr_await_settled(ScrPromise *p); /* defined with the await family */
@@ -1424,12 +1439,12 @@ ScrPromise *scr_tp_set_immediate(void) {
1424
1439
  return p;
1425
1440
  }
1426
1441
 
1427
- /* ── setImmediate as a first-class DOM value ─────────────────────────
1442
+ /* ── setImmediate as a first-class dyn value ─────────────────────────
1428
1443
  * The global passed AS A FUNCTION VALUE into untyped code (the Node-suite
1429
1444
  * traceCallback shape: `channel.traceCallback(setImmediate, 0, ctx, null,
1430
1445
  * cb)`). The minted dyn callable schedules its own immediate that calls
1431
1446
  * args[0] with the remaining arguments (Node's setImmediate(cb, ...args)
1432
- * contract) and answers undefined (the Immediate handle object has no DOM
1447
+ * contract) and answers undefined (the Immediate handle object has no dyn
1433
1448
  * story — clearImmediate over this value is not modeled). A non-function
1434
1449
  * first argument throws Node's ERR_INVALID_ARG_TYPE synchronously. */
1435
1450
 
@@ -1677,9 +1692,14 @@ void scr_loop_run(void) {
1677
1692
  scr_nt_head = t->next;
1678
1693
  if (scr_nt_head == NULL) scr_nt_tail = NULL;
1679
1694
  ScrClosure *cb = t->cb;
1695
+ void (*raw)(void) = t->raw;
1680
1696
  free(t);
1681
- ((void (*)(ScrClosure *))cb->fn)(cb);
1682
- scr_closure_release(cb);
1697
+ if (cb) {
1698
+ ((void (*)(ScrClosure *))cb->fn)(cb);
1699
+ scr_closure_release(cb);
1700
+ } else {
1701
+ raw(); /* one stream tick, FIFO with the user ticks around it */
1702
+ }
1683
1703
  if (scr_exc_pending()) return;
1684
1704
  }
1685
1705
  }
@@ -2030,7 +2050,7 @@ void scr_loop_set_island_rejections(bool (*fn)(bool print)) {
2030
2050
  }
2031
2051
 
2032
2052
  /* ── process.on('unhandledRejection') ─────────────────────────────────
2033
- * DOM listeners called per never-observed rejection instead of the
2053
+ * dyn listeners called per never-observed rejection instead of the
2034
2054
  * default report below. Node fires the event at end-of-turn; the
2035
2055
  * compiled runtime fires at loop exhaustion, where the ledger is
2036
2056
  * decided — the same values, later (SEMANTICS.md; mustCall-style
@@ -1,7 +1,7 @@
1
1
  /* Checked-dynamic ASYNC surfaces (gated — cc.ts links this TU only when
2
2
  * the IR carries the crossing libCalls or dyn dispatch: the scr_dc.c
3
3
  * size-class precedent). Everything here rides scr_async.c's public
4
- * machinery: the DOM-promise reaction helpers (.then/.catch/.finally
4
+ * machinery: the checked-dynamic tree-promise reaction helpers (.then/.catch/.finally
5
5
  * over SCR_DYN_PROMISE, await of a checked-dynamic value, the
6
6
  * `new Promise(setImmediate)` constructor), the AsyncLocalStorage API
7
7
  * over the fiber-carried snapshots (the always-linked core keeps only
@@ -128,7 +128,7 @@ void scr_als_disable(double id) {
128
128
  }
129
129
 
130
130
  /* run(store, fn, ...args) / exit(fn, ...args): enter (or clear), call the
131
- * DOM function with the forwarded arguments, restore — the finally, so a
131
+ * dyn function with the forwarded arguments, restore — the finally, so a
132
132
  * throw still restores before propagating. Result +1 or NULL pending. */
133
133
  static ScrDyn *scr_als_call_in(ScrAlsCtx *prev, ScrDyn *fn, ScrDyn *args) {
134
134
  size_t argc = args->kind == SCR_DYN_ARR ? args->v.arr.len : 0;
@@ -197,8 +197,8 @@ static bool scr_urj_dispatch(ScrPromise *p) {
197
197
 
198
198
  /* `new Promise(setImmediate)` (the Node-suite early-exit shape): the
199
199
  * executor IS setImmediate, so resolve rides the immediate queue — a
200
- * fresh promise an armed immediate fulfills with the undefined DOM value
201
- * (the executor's resolve receives no argument; the DOM payload keeps
200
+ * fresh promise an armed immediate fulfills with the undefined dyn value
201
+ * (the executor's resolve receives no argument; the dyn payload keeps
202
202
  * promise<dyn> awaiters honest and void awaiters ignore it). +1. */
203
203
  static void scr_imm_promise_thunk(ScrClosure *self) {
204
204
  ScrPromise *p = (ScrPromise *)scr_box_get_ref(self->caps[0]);
@@ -216,12 +216,12 @@ ScrPromise *scr_immediate_promise(void) {
216
216
  return p;
217
217
  }
218
218
 
219
- /* ── .then/.catch/.finally over DOM promises (scr_dyn_invoke's promise
219
+ /* ── .then/.catch/.finally over dyn promises (scr_dyn_invoke's promise
220
220
  * arm and the dc tracePromise reactions) ──────────────────────────────
221
221
  * One reaction fiber per registration: it awaits src (the settled-await
222
222
  * microtask hop keeps JS's ordering — reactions never run synchronously
223
- * inside settle), runs the DOM handler, and settles dst. A handler
224
- * returning a DOM promise is ADOPTED (awaited in a loop, like JS's
223
+ * inside settle), runs the checked-dynamic tree handler, and settles dst. A handler
224
+ * returning a dyn promise is ADOPTED (awaited in a loop, like JS's
225
225
  * resolve). Non-callable handlers pass the settlement through (JS's
226
226
  * PromisePrototypeThen over non-function reactions). The fiber's own
227
227
  * promise is dropped unobserved — the entry consumes every exception
@@ -258,7 +258,7 @@ static void scr_dyn_then_entry(ScrFiber *self, void *ap) {
258
258
  scr_promise_fulfill_ref(a->dst, scr_dyn_retain(v), scr_dyn_retain_v, scr_dyn_release_v, NULL);
259
259
  }
260
260
  } else {
261
- /* Adopt DOM-promise results (JS's resolve walk). */
261
+ /* Adopt dyn-promise results (JS's resolve walk). */
262
262
  while (r != NULL && r->kind == SCR_DYN_PROMISE) {
263
263
  ScrDyn *inner = scr_await_dyn(r->v.promise);
264
264
  scr_dyn_release(r);
@@ -301,7 +301,7 @@ ScrDyn *scr_dyn_promise_then(ScrPromise *src, ScrDyn *onf, ScrDyn *onr, ScrDyn *
301
301
  scr_promise_release(waiter); /* the entry never rejects; nobody awaits it */
302
302
  return boxed;
303
303
  }
304
- /* `await v` where v is a CHECKED-DYNAMIC value: a DOM promise adopts
304
+ /* `await v` where v is a CHECKED-DYNAMIC value: a dyn promise adopts
305
305
  * (the boxed promise awaits — rejections re-throw); every other kind is
306
306
  * JS's await-of-a-non-thenable — one microtask hop, the value itself
307
307
  * (+1). Thenable ADOPTION (a plain object carrying a then method) is not
@@ -314,14 +314,14 @@ ScrDyn *scr_await_dyn_value(ScrDyn *v) {
314
314
 
315
315
  /* ── process warnings (emitWarning + the 'warning' event) ─────────────
316
316
  * Gated with the rest of this TU (a deprecation-emitting unit's gate
317
- * must imply the dynAsync link). Listeners are DOM functions; emission
317
+ * must imply the dynAsync link). Listeners are dyn functions; emission
318
318
  * is SYNCHRONOUS at the
319
319
  * call (Node defers a tick through nextTick — the MaxListenersExceeded
320
320
  * precedent, SEMANTICS.md 138) and the default stderr report always
321
321
  * prints (Node's own bootstrap listener; a compiled binary has no
322
- * --no-warnings). The warning VALUE is the DOM error encoding built over
322
+ * --no-warnings). The warning VALUE is the dyn error encoding built over
323
323
  * an ScrError (identity-cached, so a listener comparing two deliveries
324
- * of one warning sees one object); a string `detail` joins the DOM node
324
+ * of one warning sees one object); a string `detail` joins the dyn node
325
325
  * and the report's second line, exactly Node. */
326
326
  static ScrDyn **scr_warn_listeners = NULL;
327
327
  static size_t scr_nwarn = 0, scr_warn_cap = 0;
@@ -366,7 +366,7 @@ void scr_process_off_warning(ScrDyn *fn) {
366
366
  }
367
367
  }
368
368
 
369
- /* Dispatch + the default stderr report over a built warning DOM node.
369
+ /* Dispatch + the default stderr report over a built warning dyn node.
370
370
  * Borrowed. A listener throw propagates (the dc publish stance). */
371
371
  static void scr_warning_dispatch(ScrDyn *w) {
372
372
  for (size_t i = 0; i < scr_nwarn; i++) {
@@ -415,7 +415,7 @@ static void scr_warn_bad_arg(const char *arg, const char *want) {
415
415
  scr_throw_error_msg_code(SCR_ERR_TYPE, buf, (size_t)n, "ERR_INVALID_ARG_TYPE");
416
416
  }
417
417
 
418
- /* process.emitWarning(...) — Node's full argument grammar over DOM
418
+ /* process.emitWarning(...) — Node's full argument grammar over dyn
419
419
  * values: (warning: string | Error), then for string warnings a type
420
420
  * string / ctor function / options object ({type, code, detail}) second
421
421
  * and a code string / ctor function third. Wrong kinds throw Node's
@@ -487,11 +487,11 @@ void scr_process_emit_warning(ScrDyn *args) {
487
487
 
488
488
 
489
489
 
490
- /* A caught-exception snapshot as a DOM value — identity-preserving for
491
- * DOM payloads (a dyn-thrown value is retained, not copied), the
490
+ /* A caught-exception snapshot as a dyn value — identity-preserving for
491
+ * dyn payloads (a dyn-thrown value is retained, not copied), the
492
492
  * identity-cached %error encoding above for Error-family objects,
493
493
  * scalars by value, the type-erased empty object for the rest
494
- * (SEMANTICS.md 67). Shared by the dc trace choreography, the DOM
494
+ * (SEMANTICS.md 67). Shared by the dc trace choreography, the checked-dynamic tree
495
495
  * promise reactions, and the unhandled-rejection dispatch. Borrows the
496
496
  * box; result +1. */
497
497
  ScrDyn *scr_caught_to_dyn(const ScrCaught *c) {
@@ -510,8 +510,8 @@ ScrDyn *scr_caught_to_dyn(const ScrCaught *c) {
510
510
  }
511
511
  }
512
512
 
513
- /* Await a DOM-CROSSING promise (SCR_DYN_PROMISE's boundary contract —
514
- * dyn or void fulfillment): the payload as a DOM value (+1; a void
513
+ /* Await a dyn-CROSSING promise (SCR_DYN_PROMISE's boundary contract —
514
+ * dyn or void fulfillment): the payload as a dyn value (+1; a void
515
515
  * fulfillment answers the undefined value, and the defensive scalar arms
516
516
  * cover payload kinds a direct box could theoretically carry), or NULL
517
517
  * with the rejection re-thrown into the awaiter. */
@@ -528,7 +528,7 @@ ScrDyn *scr_await_dyn(ScrPromise *p) {
528
528
  }
529
529
  case SCR_EXC_REF: {
530
530
  void *v = scr_promise_payload_ref(p);
531
- if (v) return (ScrDyn *)v; /* the DOM contract: a retained dyn */
531
+ if (v) return (ScrDyn *)v; /* the dyn contract: a retained dyn */
532
532
  return scr_dyn_retain(scr_dyn_undefined());
533
533
  }
534
534
  default:
@@ -536,7 +536,7 @@ ScrDyn *scr_await_dyn(ScrPromise *p) {
536
536
  }
537
537
  }
538
538
 
539
- /* The rejection reason as a DOM value — the scr_caught_to_dyn stances
539
+ /* The rejection reason as a dyn value — the scr_caught_to_dyn stances
540
540
  * over a promise's payload slot (identity-preserving for dyn-thrown
541
541
  * values and %Error instances). */
542
542
  ScrDyn *scr_promise_reason_dyn(const ScrPromise *p) {
@@ -573,10 +573,10 @@ ScrDyn *scr_promise_reason_dyn(const ScrPromise *p) {
573
573
  }
574
574
  }
575
575
 
576
- /* ── promises in the DOM (SCR_DYN_PROMISE) ────────────────────────────
576
+ /* ── promises in the checked-dynamic tree (SCR_DYN_PROMISE) ────────────────────────────
577
577
  * Reference boxes over the fiber machinery's ScrPromise (scr_runtime.h's
578
578
  * design note). The boundary contract — a boxed promise settles with a
579
- * DOM payload — is the CALLERS' to keep: the compiler's converters box
579
+ * dyn payload — is the CALLERS' to keep: the compiler's converters box
580
580
  * promise<dyn> directly and every other inner type through the adapting
581
581
  * constructor below. */
582
582
 
@@ -588,7 +588,7 @@ ScrDyn *scr_dyn_new_promise(ScrPromise *p) {
588
588
 
589
589
  /* The typed-inner box: a fresh destination promise parked on `src`
590
590
  * through the Promise.race cb-waiter machinery — `adapt` (emitted,
591
- * per-inner-type) converts the fulfillment payload into a DOM value and
591
+ * per-inner-type) converts the fulfillment payload into a dyn value and
592
592
  * fulfills the destination; rejections copy raw inside the machinery and
593
593
  * count as HANDLED on src (the box is the tracked promise, like a JS
594
594
  * .then chain). Already-settled sources adapt inline. Borrows src; +1. */
package/src/scr_bytes.c CHANGED
@@ -1,6 +1,8 @@
1
1
  /* Typed arrays / Buffer: ONE runtime representation (ScrBytes — see the
2
- * header contract). Element buffers own their storage outright: no views,
3
- * no byteOffset, slice/subarray both copy. Coercions are JS-exact
2
+ * header contract). An ScrBytes either OWNS its storage or is a VIEW into
3
+ * an owner's (backing set, chain depth exactly 1): DataView, subarray(),
4
+ * and Buffer's slice() all alias JS-exactly; only the plain typed arrays'
5
+ * slice() copies. Coercions are JS-exact
4
6
  * (ToUint8/ToUint32 modular truncation, double→float rounding); the
5
7
  * encoding conversions (utf8 with WHATWG replacement, hex, base64) match
6
8
  * Node byte-for-byte — the differential corpus holds them to it. */
@@ -164,7 +166,7 @@ void scr_bytes_set(ScrBytes *b, double i, double v) {
164
166
  }
165
167
  }
166
168
 
167
- /* ── slice / subarray (both COPY) ──────────────────────────────────────── */
169
+ /* ── slice (copy) / subarray (view) ────────────────────────────────────── */
168
170
 
169
171
  /* Relative index: ToIntegerOrInfinity, negatives from the end, clamped. */
170
172
  static size_t scr_bytes_rel_index(double i, size_t len) {
@@ -186,6 +188,41 @@ ScrBytes *scr_bytes_slice(const ScrBytes *b, double start, double end) {
186
188
  return out;
187
189
  }
188
190
 
191
+ /* TypedArray.prototype.fill on non-u8 receivers: per-ELEMENT fill with
192
+ * the element write's JS-exact coercion (ToUint32/ToInt32 wrap, f32
193
+ * rounding), slice-clamped relative indices; answers the receiver +1
194
+ * (chaining). Never throws — Buffer's throwing fill family is separate. */
195
+ ScrBytes *scr_bytes_fill_elem(ScrBytes *b, double v, double start, double end) {
196
+ size_t s = scr_bytes_rel_index(start, b->len);
197
+ size_t e = scr_bytes_rel_index(end, b->len);
198
+ for (size_t i = s; i < e; i++) scr_bytes_set(b, (double)i, v);
199
+ return scr_bytes_retain(b);
200
+ }
201
+
202
+ /* subarray(start, end): a same-elem VIEW over the receiver's storage —
203
+ * TypedArray.prototype.subarray and Buffer's slice()/subarray() all alias
204
+ * in JS (mutations are visible both ways; buffer-swap through a slice is
205
+ * the canonical Node use). Chain depth stays exactly 1: a subarray of a
206
+ * view retains the OWNER, offsets composed here (the DataView rule).
207
+ * Relative indices clamp like slice; never throws. */
208
+ ScrBytes *scr_bytes_subarray(ScrBytes *b, double start, double end) {
209
+ size_t s = scr_bytes_rel_index(start, b->len);
210
+ size_t e = scr_bytes_rel_index(end, b->len);
211
+ size_t count = e > s ? e - s : 0;
212
+ ScrBytes *owner = b->backing ? b->backing : b;
213
+ ScrBytes *v = malloc(sizeof(ScrBytes));
214
+ if (!v) scr_bytes_oom();
215
+ v->rc = 1;
216
+ v->len = count;
217
+ v->elem = b->elem;
218
+ v->data = b->data + s * scr_bytes_elem_size(b->elem);
219
+ v->backing = scr_bytes_retain(owner);
220
+ #ifdef SCR_RC_AUDIT
221
+ scr_live_bytes++;
222
+ #endif
223
+ return v;
224
+ }
225
+
189
226
  void scr_bytes_set_from(ScrBytes *dst, const ScrBytes *src, double offset) {
190
227
  double t = (offset != offset) ? 0 : trunc(offset);
191
228
  if (!(t >= 0) || (double)src->len + t > (double)dst->len) {
@@ -61,7 +61,7 @@ ScrBytes *scr_fs_read_file_bytes(ScrStr *path) {
61
61
  * utf8 answers a string, Node's other real encodings meet the loud
62
62
  * not-supported ladder, unknown names throw ERR_UNKNOWN_ENCODING, and an
63
63
  * options object dispatches on its `encoding` member (Node's form). +1
64
- * DOM value, or NULL with the exception pending. */
64
+ * dyn value, or NULL with the exception pending. */
65
65
  ScrDyn *scr_fs_read_file_sync_dyn(ScrStr *path, const ScrDyn *enc) {
66
66
  if (enc->kind == SCR_DYN_OBJ) {
67
67
  ScrDyn *ev = scr_dyn_obj_get((ScrDyn *)enc, "encoding", 8); /* borrowed */
@@ -166,7 +166,7 @@ bool scr_process_stderr_write_bytes(const ScrBytes *b) {
166
166
 
167
167
  /* ── the checked-dynamic Buffer compare/equals validators ──────────────
168
168
  * Node's argument ladders for buf.equals / buf.compare / Buffer.compare
169
- * over DOM-boxed arguments (the invalid-input probes: string needles,
169
+ * over dyn-boxed arguments (the invalid-input probes: string needles,
170
170
  * '0' offsets, null/object range args). A well-typed dyn still computes
171
171
  * the real answer — validation, not a constant fence. */
172
172
 
@@ -260,7 +260,7 @@ double scr_fs_to_unix_timestamp(const ScrDyn *t) {
260
260
 
261
261
  /* ── the fs argument-validation ladders (checked-dynamic lane) ─────────
262
262
  * Each fs.*Chk libCall replicates its API's Node-order validation over
263
- * DOM values and throws Node's exact typed errors; when every validation
263
+ * dyn values and throws Node's exact typed errors; when every validation
264
264
  * passes, the honest tail runs — the real operation where one exists
265
265
  * (mkdtempSync, lchmodSync on macOS), the compiler-rendered SC2020 fence
266
266
  * otherwise (scr_throw_lowering_fence). All arguments borrowed. */
@@ -282,7 +282,7 @@ static bool scr_fs_cb_chk(const ScrDyn *cb, const char *name) {
282
282
  }
283
283
 
284
284
  /* getValidatedPath: strings and Buffers pass (URL instances never reach
285
- * these ladders — the DOM has no URL kind here, and Node would accept
285
+ * these ladders — the checked-dynamic tree has no URL kind here, and Node would accept
286
286
  * only file: URLs anyway). */
287
287
  static bool scr_fs_path_chk(const ScrDyn *p, const char *name) {
288
288
  if (p->kind == SCR_DYN_STR || p->kind == SCR_DYN_BYTES) return true;
@@ -522,7 +522,7 @@ static void scr_fs_lchmod_apply(const ScrDyn *path, const ScrDyn *mode) {
522
522
  }
523
523
  #endif
524
524
 
525
- /* Answers the DOM undefined (+1) on success — lchmodSync's JS value, so
525
+ /* Answers the dyn undefined (+1) on success — lchmodSync's JS value, so
526
526
  * return-position uses lower; NULL with the exception pending. */
527
527
  ScrDyn *scr_fs_lchmod_sync_chk(const ScrDyn *path, const ScrDyn *mode) {
528
528
  if (!scr_fs_lchmod_defined("fs.lchmodSync")) return NULL;
package/src/scr_dc.c CHANGED
@@ -1,13 +1,13 @@
1
1
  /* node:diagnostics_channel — the in-process pub/sub core (scr_runtime.h
2
2
  * has the API contract). Linked only when the IR carries dc.* libCalls
3
- * (cc.ts; the zlib gating precedent), pure data structure over the DOM
3
+ * (cc.ts; the zlib gating precedent), pure data structure over the checked-dynamic tree
4
4
  * no loop hooks, no platform seams, cross-compiles everywhere.
5
5
  *
6
6
  * - The registry is process-global and append-only (Node's channels are
7
7
  * process-lived too — its WeakRefMap only collects channels nothing
8
8
  * references, which a compiled program cannot observe). Handles are
9
9
  * 1-based indexes so a zeroed f64 can never alias channel 0.
10
- * - Subscribers are DOM FUNCTION values. unsubscribe matches by the
10
+ * - Subscribers are dyn FUNCTION values. unsubscribe matches by the
11
11
  * UNDERLYING closure when both sides are functions (boxing one function
12
12
  * twice yields distinct ScrDyn nodes sharing one ScrClosure, and JS has
13
13
  * ONE function object), falling back to node identity.
@@ -98,7 +98,7 @@ static ScrDcChannel *dc_of(double handle) {
98
98
  }
99
99
 
100
100
  /* Node's ERR_INVALID_ARG_TYPE for a non-function subscriber — the
101
- * "Received ..." tail covers the DOM kinds (determineSpecificType lite;
101
+ * "Received ..." tail covers the dyn kinds (determineSpecificType lite;
102
102
  * scr_dyn_handle.c's full renderer is not linked here). */
103
103
  static void dc_throw_bad_fn_arg(const ScrDyn *cb, const char *arg_name) {
104
104
  const char *received = "an instance of Object";
@@ -341,7 +341,7 @@ ScrDyn *scr_dc_chan_run_stores(double handle, ScrDyn *data, ScrDyn *fn, ScrDyn *
341
341
  /* ── TracingChannel ────────────────────────────────────────────────────
342
342
  * A registry entry of five channel indexes (start/end/asyncStart/asyncEnd/
343
343
  * error), handled as a 1-based f64 like Channel. The trace choreography
344
- * lives here in C over the DOM: publishes stash the pending traced-call /
344
+ * lives here in C over the checked-dynamic tree: publishes stash the pending traced-call /
345
345
  * subscriber exception in a ScrCaught box first (compiled subscriber
346
346
  * bodies run with a CLEAR cell — a pending flag would unwind them at
347
347
  * their first call) and re-raise after, so throws propagate exactly like
@@ -468,8 +468,8 @@ bool scr_dc_tc_unsubscribe(double h, ScrDyn *handlers) {
468
468
  return done;
469
469
  }
470
470
 
471
- /* The pending exception as a DOM value for ctx.error: scr_caught_to_dyn
472
- * (scr_json.c) — identity-preserving for DOM payloads and %Error
471
+ /* The pending exception as a dyn value for ctx.error: scr_caught_to_dyn
472
+ * (scr_json.c) — identity-preserving for dyn payloads and %Error
473
473
  * instances (the identity-cached crossing: the stamped ctx.error compares
474
474
  * reference-equal to the thrown error's other boxings). */
475
475
 
@@ -586,7 +586,7 @@ static void dc_tp_entry(ScrFiber *self, void *ap) {
586
586
  free(a);
587
587
  }
588
588
 
589
- /* The traced result as a promise (+1): a DOM promise unwraps, anything
589
+ /* The traced result as a promise (+1): a dyn promise unwraps, anything
590
590
  * else is PromiseResolve'd (Node converts non-promise returns; a raw
591
591
  * non-promise return on the NO-SUBSCRIBER path wraps too — the lowering
592
592
  * types the result Promise<unknown>, a wrap Node skips, SEMANTICS.md). */
@@ -728,7 +728,7 @@ ScrDyn *scr_dc_tc_trace_callback(double h, ScrDyn *fn, double position, ScrDyn *
728
728
  dc_throw_bad_fn_arg(cb, "callback");
729
729
  return NULL;
730
730
  }
731
- /* Splice the wrapper in (a fresh argument vector; the DOM array is
731
+ /* Splice the wrapper in (a fresh argument vector; the dyn array is
732
732
  * borrowed and Node's splice mutation is unobservable through it — the
733
733
  * caller rebuilt it from the call site's arguments). */
734
734
  ScrClosure *clo = scr_closure_new((void *)dc_tc_wrapped_cb, 3);
package/src/scr_dgram.c CHANGED
@@ -1020,7 +1020,7 @@ void scr_dgram_install(void) {
1020
1020
 
1021
1021
  /* ── the send argument-validation ladder (checked-dynamic lane) ─────────
1022
1022
  * Node's Socket.prototype.send signature shuffle and validation order
1023
- * over DOM arguments, byte-for-byte: the connected/unconnected split
1023
+ * over dyn arguments, byte-for-byte: the connected/unconnected split
1024
1024
  * decides whether (a1, a2) are an offset/length slice or the port/address
1025
1025
  * pair; sliceBuffer validates the buffer's type and bounds
1026
1026
  * (ERR_BUFFER_OUT_OF_BOUNDS); list payloads validate per element with the
@@ -1,10 +1,10 @@
1
1
  /* The checked-dynamic HANDLE support unit — everything the handle
2
2
  * dispatchers (scr_http.c / scr_net.c) and the emitter unit's dyn
3
- * registrations share BEYOND the DOM core: the listener gate over the
3
+ * registrations share BEYOND the dyn core: the listener gate over the
4
4
  * ERR_INVALID_ARG_TYPE throwers (the throwers themselves live in
5
- * scr_json.c beside the DOM core — the always-linked bytes/fs argument
5
+ * scr_json.c beside the dyn core — the always-linked bytes/fs argument
6
6
  * validators call them too), and the runtime-built listener adapter
7
- * closures whose fire thunks box event tuples back into the DOM. Split
7
+ * closures whose fire thunks box event tuples back into the checked-dynamic tree. Split
8
8
  * out of scr_json.c so handle-free binaries keep their exact size
9
9
  * class: cc.ts compiles this unit exactly when a user of it links (the
10
10
  * net or emitter gate — http implies net).
@@ -24,7 +24,7 @@ void scr_dyn_check_listener(const ScrDyn *cb, const char *argname) {
24
24
 
25
25
  /* ── runtime-built listener closures (the handle dispatchers' .on paths) ─
26
26
  * One capture: a box holding the retained dyn FUNCTION value. The fire
27
- * thunks box the event tuple back into the DOM and call through the
27
+ * thunks box the event tuple back into the checked-dynamic tree and call through the
28
28
  * checked-dynamic machinery (scr_dyn_call — per-arg validation lives in
29
29
  * the boxed thunk). A throw from the listener stays pending, exactly like
30
30
  * a compiler-emitted listener body. */
@@ -56,7 +56,7 @@ void scr_dyn_listener_fire_data(ScrClosure *cb, ScrBytes *chunk) {
56
56
 
57
57
  void scr_dyn_listener_fire_err(ScrClosure *cb, ScrStr *msg) {
58
58
  ScrDyn *fn = scr_dyn_listener_peek(cb);
59
- /* The DOM's error encoding (caughtToDyn's shape) — what a dyn 'error'
59
+ /* The checked-dynamic tree's error encoding (caughtToDyn's shape) — what a dyn 'error'
60
60
  * listener body can instanceof-test and read .message from. */
61
61
  ScrDyn *arg = scr_dyn_new_obj();
62
62
  scr_dyn_obj_set(arg, "%error", 6, scr_dyn_new_bool(true));