@scriptc/runtime 0.0.11 → 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 +1 -1
- package/src/scr_assert.c +13 -13
- package/src/scr_async.c +5 -5
- package/src/scr_async_dyn.c +24 -24
- package/src/scr_bytes_io.c +5 -5
- package/src/scr_dc.c +8 -8
- package/src/scr_dgram.c +1 -1
- package/src/scr_dyn_handle.c +5 -5
- package/src/scr_dyn_invoke.c +15 -15
- package/src/scr_error.c +3 -3
- package/src/scr_events_emitter.c +1 -1
- package/src/scr_http.c +4 -4
- package/src/scr_http2.c +3 -3
- package/src/scr_inspect.c +3 -3
- package/src/scr_island.c +134 -25
- package/src/scr_json.c +103 -68
- package/src/scr_net.c +1 -1
- package/src/scr_qs.c +1 -1
- package/src/scr_runtime.h +144 -118
- package/src/scr_stream.c +4 -4
- package/src/scr_tls.c +3 -3
- package/src/scr_web.c +1 -1
package/package.json
CHANGED
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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 (
|
|
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
|
|
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
|
-
*
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
-
*
|
|
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 →
|
|
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
|
|
@@ -1024,7 +1024,7 @@ ScrStr *scr_promise_payload_str(ScrPromise *p) {
|
|
|
1024
1024
|
return scr_str_retain((ScrStr *)p->payload);
|
|
1025
1025
|
}
|
|
1026
1026
|
/* Thin views for the gated dyn-async TU (scr_async_dyn.c): the payload
|
|
1027
|
-
* KIND, whether a REF payload is a
|
|
1027
|
+
* KIND, whether a REF payload is a dyn value (the dyn adapters), and the
|
|
1028
1028
|
* settled-await primitive (park/hop + rejection re-throw; true =
|
|
1029
1029
|
* fulfilled). */
|
|
1030
1030
|
static bool scr_await_settled(ScrPromise *p); /* defined with the await family */
|
|
@@ -1439,12 +1439,12 @@ ScrPromise *scr_tp_set_immediate(void) {
|
|
|
1439
1439
|
return p;
|
|
1440
1440
|
}
|
|
1441
1441
|
|
|
1442
|
-
/* ── setImmediate as a first-class
|
|
1442
|
+
/* ── setImmediate as a first-class dyn value ─────────────────────────
|
|
1443
1443
|
* The global passed AS A FUNCTION VALUE into untyped code (the Node-suite
|
|
1444
1444
|
* traceCallback shape: `channel.traceCallback(setImmediate, 0, ctx, null,
|
|
1445
1445
|
* cb)`). The minted dyn callable schedules its own immediate that calls
|
|
1446
1446
|
* args[0] with the remaining arguments (Node's setImmediate(cb, ...args)
|
|
1447
|
-
* contract) and answers undefined (the Immediate handle object has no
|
|
1447
|
+
* contract) and answers undefined (the Immediate handle object has no dyn
|
|
1448
1448
|
* story — clearImmediate over this value is not modeled). A non-function
|
|
1449
1449
|
* first argument throws Node's ERR_INVALID_ARG_TYPE synchronously. */
|
|
1450
1450
|
|
|
@@ -2050,7 +2050,7 @@ void scr_loop_set_island_rejections(bool (*fn)(bool print)) {
|
|
|
2050
2050
|
}
|
|
2051
2051
|
|
|
2052
2052
|
/* ── process.on('unhandledRejection') ─────────────────────────────────
|
|
2053
|
-
*
|
|
2053
|
+
* dyn listeners called per never-observed rejection instead of the
|
|
2054
2054
|
* default report below. Node fires the event at end-of-turn; the
|
|
2055
2055
|
* compiled runtime fires at loop exhaustion, where the ledger is
|
|
2056
2056
|
* decided — the same values, later (SEMANTICS.md; mustCall-style
|
package/src/scr_async_dyn.c
CHANGED
|
@@ -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
|
|
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
|
-
*
|
|
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
|
|
201
|
-
* (the executor's resolve receives no argument; the
|
|
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
|
|
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
|
|
224
|
-
* returning a
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
491
|
-
*
|
|
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
|
|
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
|
|
514
|
-
* dyn or void fulfillment): the payload as a
|
|
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
|
|
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
|
|
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
|
|
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
|
-
*
|
|
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
|
|
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_io.c
CHANGED
|
@@ -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
|
-
*
|
|
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
|
|
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
|
-
*
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
472
|
-
* (scr_json.c) — identity-preserving for
|
|
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
|
|
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
|
|
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
|
|
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
|
package/src/scr_dyn_handle.c
CHANGED
|
@@ -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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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));
|
package/src/scr_dyn_invoke.c
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
/* Prototype-method dispatch on checked-dynamic receivers (scr_dyn_invoke)
|
|
2
|
-
* and its companions: JS String() over the
|
|
2
|
+
* and its companions: JS String() over the checked-dynamic tree (scr_dyn_display — join
|
|
3
3
|
* and the error texts need it standalone) and Object.defineProperties
|
|
4
|
-
* over
|
|
4
|
+
* over dyn values (scr_dyn_define_props). Linked only when the IR
|
|
5
5
|
* carries dynInvoke nodes or dyn.defineProps calls (cc.ts gates on
|
|
6
6
|
* moduleUsesDynInvoke — the scr_assert.c precedent), so dispatch-free
|
|
7
|
-
* binaries keep their exact size class. The
|
|
7
|
+
* binaries keep their exact size class. The checked-dynamic tree itself lives in
|
|
8
8
|
* scr_json.c; this unit uses only its public surface plus ScrJsonBuf.
|
|
9
9
|
*/
|
|
10
10
|
#include "scr_runtime.h"
|
|
@@ -16,8 +16,8 @@
|
|
|
16
16
|
|
|
17
17
|
/* ── checked-dynamic METHOD DISPATCH (scr_dyn_invoke) ──────────────────
|
|
18
18
|
*
|
|
19
|
-
* `recv.m(args)` where recv is a
|
|
20
|
-
*
|
|
19
|
+
* `recv.m(args)` where recv is a dyn value and `m` is a name a
|
|
20
|
+
* dyn-representable prototype declares (Array/String/Function shared
|
|
21
21
|
* names — push, slice, forEach, apply, ...): a stored-member read would
|
|
22
22
|
* silently mis-answer real methods, so the dispatch runs HERE, over the
|
|
23
23
|
* receiver's runtime kind. test/common's mustCall internals are the
|
|
@@ -38,10 +38,10 @@
|
|
|
38
38
|
* recv/args are BORROWED; the result is owned (+1). MAY THROW (returns
|
|
39
39
|
* NULL with the exception pending). */
|
|
40
40
|
|
|
41
|
-
/* JS String() over a
|
|
41
|
+
/* JS String() over a dyn value, runtime-side (join needs it standalone —
|
|
42
42
|
* the emitted sc_ds walker exists only in programs that spell
|
|
43
43
|
* String(unknown) themselves). Same rules: arrays join with "," and
|
|
44
|
-
* null/undefined elements print empty, the
|
|
44
|
+
* null/undefined elements print empty, the checked-dynamic tree's error encoding renders
|
|
45
45
|
* "name: message", functions render the native-code form, plain objects
|
|
46
46
|
* are [object Object]. */
|
|
47
47
|
static void scr_dyn_display_buf(ScrJsonBuf *b, const ScrDyn *d) {
|
|
@@ -192,7 +192,7 @@ static bool dyn_cb_check(ScrDyn *const *args, size_t argc) {
|
|
|
192
192
|
ScrDyn *cb = argc > 0 ? args[0] : scr_dyn_undefined();
|
|
193
193
|
if (cb->kind == SCR_DYN_FUNC) return true;
|
|
194
194
|
/* An ENGINE function is callable — scr_dyn_call's JSVAL arm routes it
|
|
195
|
-
* (the loops below call through scr_dyn_call, which converts the
|
|
195
|
+
* (the loops below call through scr_dyn_call, which converts the checked-dynamic tree
|
|
196
196
|
* element arguments per the uniform crossing). A wrapped NON-function
|
|
197
197
|
* falls through to the display path: String(cb) renders through the
|
|
198
198
|
* engine, exactly Node's message. */
|
|
@@ -215,7 +215,7 @@ static ScrDyn *scr_dynh_dispatch(ScrDyn *recv, const char *method, ScrDyn *const
|
|
|
215
215
|
return ops->invoke(recv->v.handle.ptr, recv, method, args, argc, what);
|
|
216
216
|
}
|
|
217
217
|
|
|
218
|
-
/* JS Array.prototype.sort over a
|
|
218
|
+
/* JS Array.prototype.sort over a dyn array: the spec's snapshot-sort —
|
|
219
219
|
* elements copy (retained) into a work list, a stable merge sort orders
|
|
220
220
|
* it (undefined elements sink to the end before any comparator runs),
|
|
221
221
|
* and the ordered list writes back index by index, so a comparator that
|
|
@@ -339,7 +339,7 @@ ScrDyn *scr_dyn_invoke(ScrDyn *recv, const char *method, ScrDyn *const *args, si
|
|
|
339
339
|
/* Island-held receivers: the ENGINE runs its own prototypes (JS-exact
|
|
340
340
|
* flatMap/map/forEach/filter — Array.prototype is the engine's) through
|
|
341
341
|
* scr_jsval_call_method; arguments cross per the uniform conversion
|
|
342
|
-
* (wrapped cells by reference,
|
|
342
|
+
* (wrapped cells by reference, dyn data deep-copied, FUNC boxes through
|
|
343
343
|
* the host shim), a missing member throws the engine's own TypeError,
|
|
344
344
|
* and the result wraps back scalar-normalized. `what` is unused — the
|
|
345
345
|
* engine's message names the failure. */
|
|
@@ -352,7 +352,7 @@ ScrDyn *scr_dyn_invoke(ScrDyn *recv, const char *method, ScrDyn *const *args, si
|
|
|
352
352
|
if (recv->kind == SCR_DYN_OBJ) {
|
|
353
353
|
ScrDyn *m = scr_dyn_obj_get(recv, method, strlen(method));
|
|
354
354
|
if (m && (m->kind == SCR_DYN_FUNC ||
|
|
355
|
-
/* a WRAPPED engine function stored as a
|
|
355
|
+
/* a WRAPPED engine function stored as a dyn member: the
|
|
356
356
|
* routed call (scr_dyn_call's JSVAL arm) runs it. */
|
|
357
357
|
(m->kind == SCR_DYN_JSVAL && scr_dyn_isl_typeof_is(m, "function")))) {
|
|
358
358
|
/* JS binds the receiver for the call (`obj.method()` — this === obj):
|
|
@@ -584,8 +584,8 @@ ScrDyn *scr_dyn_invoke(ScrDyn *recv, const char *method, ScrDyn *const *args, si
|
|
|
584
584
|
return scr_dyn_retain(scr_dyn_undefined()); /* forEach */
|
|
585
585
|
}
|
|
586
586
|
if (dyn_name_is(method, "flatMap")) {
|
|
587
|
-
/* JS Array.prototype.flatMap over a
|
|
588
|
-
* flatten. Native
|
|
587
|
+
/* JS Array.prototype.flatMap over a dyn array: map + a depth-1
|
|
588
|
+
* flatten. Native dyn-array results flatten element-by-element; a
|
|
589
589
|
* WRAPPED engine array flattens through the routed keyed reads
|
|
590
590
|
* (elements wrap back scalar-normalized); everything else pushes
|
|
591
591
|
* as a single element (JS keeps non-array callback results whole).
|
|
@@ -682,9 +682,9 @@ ScrDyn *scr_dyn_invoke(ScrDyn *recv, const char *method, ScrDyn *const *args, si
|
|
|
682
682
|
return NULL;
|
|
683
683
|
}
|
|
684
684
|
|
|
685
|
-
/* Object.defineProperties over
|
|
685
|
+
/* Object.defineProperties over dyn values (see scr_runtime.h). Value
|
|
686
686
|
* descriptors only: writable/enumerable/configurable accepted and IGNORED
|
|
687
|
-
* (
|
|
687
|
+
* (dyn properties are plain data properties — SEMANTICS.md); get/set
|
|
688
688
|
* throw the loud unsupported Error, never a silent drop. */
|
|
689
689
|
ScrDyn *scr_dyn_define_props(ScrDyn *target, ScrDyn *descs) {
|
|
690
690
|
/* Island-held operands ARE objects to Node — the non-object TypeError
|
package/src/scr_error.c
CHANGED
|
@@ -44,9 +44,9 @@ static void scr_error_gcfree(void *obj) {
|
|
|
44
44
|
scr_cyc_free(e);
|
|
45
45
|
}
|
|
46
46
|
|
|
47
|
-
/* DOMException teardown: the ScrError fields plus the owned cause
|
|
47
|
+
/* DOMException teardown: the ScrError fields plus the owned cause dyn
|
|
48
48
|
* value. The cause is a ScrDyn — scr_json.c territory — and this file
|
|
49
|
-
* must stay linkable WITHOUT the
|
|
49
|
+
* must stay linkable WITHOUT the checked-dynamic tree (the runtime C-unit tests link
|
|
50
50
|
* subsets), so the drop goes through a hook scr_json.c installs before
|
|
51
51
|
* any cause can exist (scr_domex_new is the only producer). */
|
|
52
52
|
static void (*scr_domex_cause_drop)(void *obj) = NULL;
|
|
@@ -273,7 +273,7 @@ void scr_undef_global_read(ScrStr *name) {
|
|
|
273
273
|
/* ── DOMException ─────────────────────────────────────────────────────
|
|
274
274
|
* The web-standard error shape (a Node global since v17): the ScrError
|
|
275
275
|
* prefix plus the WebIDL slots (legacy numeric code, the options form's
|
|
276
|
-
* cause). Construction resolves WebIDL's optionality over borrowed
|
|
276
|
+
* cause). Construction resolves WebIDL's optionality over borrowed dyn
|
|
277
277
|
* arguments — one place, shared by the compiled `new DOMException(...)`
|
|
278
278
|
* and the runtime's own throw sites (atob/btoa). */
|
|
279
279
|
|
package/src/scr_events_emitter.c
CHANGED
|
@@ -466,7 +466,7 @@ ScrEmitter *scr_emitter_off_dyn(ScrEmitter *em, ScrStr *name, const ScrDyn *cb)
|
|
|
466
466
|
* the simple '-quoted spelling — listener mistakes are words, not escape
|
|
467
467
|
* zoos). */
|
|
468
468
|
void scr_emitter_check_listener(const ScrDyn *cb) {
|
|
469
|
-
/* The shared gate lives in the always-linked
|
|
469
|
+
/* The shared gate lives in the always-linked dyn core (scr_json.c) so
|
|
470
470
|
* the handle dispatchers' .on paths render the same shapes without
|
|
471
471
|
* linking this unit. */
|
|
472
472
|
scr_dyn_check_listener(cb, "listener");
|
package/src/scr_http.c
CHANGED
|
@@ -2774,7 +2774,7 @@ void scr_http_resp_thunk_res(ScrClosure *cb, ScrHttpReq *res) {
|
|
|
2774
2774
|
*
|
|
2775
2775
|
* The receiver surface behind `server.on('request', mustCall((req, res)
|
|
2776
2776
|
* => ...))`: the mustCall wrapper makes the listener dyn, req/res box
|
|
2777
|
-
* into the
|
|
2777
|
+
* into the checked-dynamic tree as HANDLE values, and member uses inside the listener
|
|
2778
2778
|
* body dispatch HERE — onto the very entry points the static lowerings
|
|
2779
2779
|
* use, with per-argument gates shaped like Node's (the libCall signature
|
|
2780
2780
|
* table in validate.ts is the modeled surface; this dispatcher mirrors
|
|
@@ -2785,7 +2785,7 @@ void scr_http_resp_thunk_res(ScrClosure *cb, ScrHttpReq *res) {
|
|
|
2785
2785
|
* - a member the class HAS but this table does not model: a LOUD
|
|
2786
2786
|
* "not supported yet" Error — never a silent wrong answer;
|
|
2787
2787
|
* - anything else: Node's "<spelling> is not a function" for calls,
|
|
2788
|
-
* the undefined singleton for reads (the
|
|
2788
|
+
* the undefined singleton for reads (the checked-dynamic tree's own-property answer;
|
|
2789
2789
|
* SEMANTICS.md documents the remainder).
|
|
2790
2790
|
*
|
|
2791
2791
|
* Ownership: invoke/get/set receive BORROWED handles/args and answer
|
|
@@ -3009,7 +3009,7 @@ static ScrDyn *scr_http_dynh_req_get(void *h, const char *key, size_t key_len) {
|
|
|
3009
3009
|
double st = scr_http_req_status(r);
|
|
3010
3010
|
/* Node's IncomingMessage constructor sets statusCode = null; only a
|
|
3011
3011
|
* client response assigns a number (the static lane's typed surface
|
|
3012
|
-
* spells this number|undefined — the
|
|
3012
|
+
* spells this number|undefined — the checked-dynamic tree can afford Node's null). */
|
|
3013
3013
|
return st < 0 ? scr_dyn_new_null() : scr_dyn_new_num(st);
|
|
3014
3014
|
}
|
|
3015
3015
|
if (strcmp(key, "statusMessage") == 0) {
|
|
@@ -3049,7 +3049,7 @@ static bool scr_http_dynh_req_set(void *h, const char *key, size_t key_len, cons
|
|
|
3049
3049
|
|
|
3050
3050
|
/* ── ServerResponse (SCR_DYNH_HTTP_RES) ──────────────────────────────── */
|
|
3051
3051
|
|
|
3052
|
-
/* writeHead's header-object form over a
|
|
3052
|
+
/* writeHead's header-object form over a dyn OBJ: flatten into the
|
|
3053
3053
|
* [k0, v0, k1, v1, ...] pairs the static lowering feeds
|
|
3054
3054
|
* scr_http_res_write_head_pairs (repeats append — array values expand to
|
|
3055
3055
|
* consecutive same-name pairs). Numbers format through String(n). NULL =
|