@scriptc/runtime 0.0.9 → 0.0.11
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 +43 -4
- package/src/scr_async.c +24 -4
- package/src/scr_bytes.c +47 -9
- package/src/scr_bytes_io.c +410 -0
- package/src/scr_dc.c +6 -0
- package/src/scr_dgram.c +176 -1
- package/src/scr_dyn_invoke.c +96 -2
- package/src/scr_events_emitter.c +58 -5
- package/src/scr_inspect.c +27 -3
- package/src/scr_island.c +389 -3
- package/src/scr_json.c +488 -7
- package/src/scr_lib.c +21 -1
- package/src/scr_library.c +15 -0
- package/src/scr_net.c +112 -0
- package/src/scr_regex.c +39 -6
- package/src/scr_runtime.h +296 -17
- package/src/scr_stream.c +214 -7
- package/src/scr_tls.c +172 -0
package/src/scr_dyn_invoke.c
CHANGED
|
@@ -114,6 +114,11 @@ static void scr_dyn_display_buf(ScrJsonBuf *b, const ScrDyn *d) {
|
|
|
114
114
|
* for a bare promise is "[object Promise]". */
|
|
115
115
|
scr_jb_puts(b, "[object Promise]");
|
|
116
116
|
return;
|
|
117
|
+
case SCR_DYN_JSVAL:
|
|
118
|
+
/* The engine's own ToString (a bridged failure leaves the exception
|
|
119
|
+
* pending and appends nothing — the loud path). */
|
|
120
|
+
scr_dyn_isl_tostr_buf(b, d);
|
|
121
|
+
return;
|
|
117
122
|
}
|
|
118
123
|
}
|
|
119
124
|
|
|
@@ -186,6 +191,12 @@ static ScrDyn *dyn_call_cb(ScrDyn *cb, ScrDyn *item, size_t i, ScrDyn *recv) {
|
|
|
186
191
|
static bool dyn_cb_check(ScrDyn *const *args, size_t argc) {
|
|
187
192
|
ScrDyn *cb = argc > 0 ? args[0] : scr_dyn_undefined();
|
|
188
193
|
if (cb->kind == SCR_DYN_FUNC) return true;
|
|
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 DOM
|
|
196
|
+
* element arguments per the uniform crossing). A wrapped NON-function
|
|
197
|
+
* falls through to the display path: String(cb) renders through the
|
|
198
|
+
* engine, exactly Node's message. */
|
|
199
|
+
if (cb->kind == SCR_DYN_JSVAL && scr_dyn_isl_typeof_is(cb, "function")) return true;
|
|
189
200
|
ScrJsonBuf b;
|
|
190
201
|
scr_jb_init(&b);
|
|
191
202
|
scr_dyn_display_buf(&b, cb);
|
|
@@ -289,7 +300,7 @@ static bool dyn_arr_sort(ScrDyn *recv, ScrDyn *cmp) {
|
|
|
289
300
|
/* Names each prototype declares BEYOND what's implemented here — these
|
|
290
301
|
* fence loudly instead of mis-answering "is not a function". */
|
|
291
302
|
static bool dyn_arr_proto_unimpl(const char *m) {
|
|
292
|
-
static const char *names[] = { "splice", "reduce", "reduceRight", "flat",
|
|
303
|
+
static const char *names[] = { "splice", "reduce", "reduceRight", "flat",
|
|
293
304
|
"fill", "copyWithin", "keys", "values", "entries", "toReversed", "toSorted", "toSpliced",
|
|
294
305
|
"with", "toString", "toLocaleString", NULL };
|
|
295
306
|
for (size_t i = 0; names[i]; i++) if (dyn_name_is(m, names[i])) return true;
|
|
@@ -325,11 +336,25 @@ ScrDyn *scr_dyn_invoke(ScrDyn *recv, const char *method, ScrDyn *const *args, si
|
|
|
325
336
|
return scr_dynh_dispatch(recv, method, args, argc, what);
|
|
326
337
|
}
|
|
327
338
|
|
|
339
|
+
/* Island-held receivers: the ENGINE runs its own prototypes (JS-exact
|
|
340
|
+
* flatMap/map/forEach/filter — Array.prototype is the engine's) through
|
|
341
|
+
* scr_jsval_call_method; arguments cross per the uniform conversion
|
|
342
|
+
* (wrapped cells by reference, DOM data deep-copied, FUNC boxes through
|
|
343
|
+
* the host shim), a missing member throws the engine's own TypeError,
|
|
344
|
+
* and the result wraps back scalar-normalized. `what` is unused — the
|
|
345
|
+
* engine's message names the failure. */
|
|
346
|
+
if (recv->kind == SCR_DYN_JSVAL) {
|
|
347
|
+
return scr_dyn_jsval_ops()->invoke(recv->v.jsval.cell, method, args, argc, what);
|
|
348
|
+
}
|
|
349
|
+
|
|
328
350
|
/* OBJ: the own member calls (own properties shadow prototypes in JS
|
|
329
351
|
* too); anything else is Node's is-not-a-function. */
|
|
330
352
|
if (recv->kind == SCR_DYN_OBJ) {
|
|
331
353
|
ScrDyn *m = scr_dyn_obj_get(recv, method, strlen(method));
|
|
332
|
-
if (m && m->kind == SCR_DYN_FUNC
|
|
354
|
+
if (m && (m->kind == SCR_DYN_FUNC ||
|
|
355
|
+
/* a WRAPPED engine function stored as a DOM member: the
|
|
356
|
+
* routed call (scr_dyn_call's JSVAL arm) runs it. */
|
|
357
|
+
(m->kind == SCR_DYN_JSVAL && scr_dyn_isl_typeof_is(m, "function")))) {
|
|
333
358
|
/* JS binds the receiver for the call (`obj.method()` — this === obj):
|
|
334
359
|
* the ambient-receiver window (scr_runtime.h). */
|
|
335
360
|
scr_dyn_this_push_dyn(recv);
|
|
@@ -374,6 +399,23 @@ ScrDyn *scr_dyn_invoke(ScrDyn *recv, const char *method, ScrDyn *const *args, si
|
|
|
374
399
|
dyn_throw_unsupported("Function", method);
|
|
375
400
|
return NULL;
|
|
376
401
|
}
|
|
402
|
+
/* An OWN property on the FUNC box (defineProperties writes — the
|
|
403
|
+
* mustCall-wrapper expando family): a callable member runs with the
|
|
404
|
+
* box bound (JS's o.m() receiver), everything else keeps Node's
|
|
405
|
+
* is-not-a-function. */
|
|
406
|
+
{
|
|
407
|
+
ScrDyn *own = scr_dyn_fn_get(recv, method, strlen(method));
|
|
408
|
+
if (own) {
|
|
409
|
+
if (own->kind == SCR_DYN_FUNC || own->kind == SCR_DYN_JSVAL) {
|
|
410
|
+
scr_dyn_this_push_dyn(recv);
|
|
411
|
+
ScrDyn *r = scr_dyn_call(own, args, argc, what);
|
|
412
|
+
scr_dyn_this_pop();
|
|
413
|
+
scr_dyn_release(own);
|
|
414
|
+
return r;
|
|
415
|
+
}
|
|
416
|
+
scr_dyn_release(own);
|
|
417
|
+
}
|
|
418
|
+
}
|
|
377
419
|
dyn_throw_not_fn(what);
|
|
378
420
|
return NULL;
|
|
379
421
|
}
|
|
@@ -541,6 +583,53 @@ ScrDyn *scr_dyn_invoke(ScrDyn *recv, const char *method, ScrDyn *const *args, si
|
|
|
541
583
|
if (dyn_name_is(method, "findIndex")) return scr_dyn_new_num(-1);
|
|
542
584
|
return scr_dyn_retain(scr_dyn_undefined()); /* forEach */
|
|
543
585
|
}
|
|
586
|
+
if (dyn_name_is(method, "flatMap")) {
|
|
587
|
+
/* JS Array.prototype.flatMap over a DOM array: map + a depth-1
|
|
588
|
+
* flatten. Native DOM-array results flatten element-by-element; a
|
|
589
|
+
* WRAPPED engine array flattens through the routed keyed reads
|
|
590
|
+
* (elements wrap back scalar-normalized); everything else pushes
|
|
591
|
+
* as a single element (JS keeps non-array callback results whole).
|
|
592
|
+
* JS's spec snapshots the length up front (elements appended by
|
|
593
|
+
* the callback are not visited). */
|
|
594
|
+
if (!dyn_cb_check(args, argc)) return NULL;
|
|
595
|
+
ScrDyn *cb = args[0];
|
|
596
|
+
ScrDyn *out = scr_dyn_new_arr();
|
|
597
|
+
size_t n = recv->v.arr.len;
|
|
598
|
+
for (size_t i = 0; i < n && i < recv->v.arr.len; i++) {
|
|
599
|
+
ScrDyn *item = scr_dyn_retain(recv->v.arr.items[i]);
|
|
600
|
+
ScrDyn *r = dyn_call_cb(cb, item, i, recv);
|
|
601
|
+
scr_dyn_release(item);
|
|
602
|
+
if (!r) { scr_dyn_release(out); return NULL; }
|
|
603
|
+
if (r->kind == SCR_DYN_ARR) {
|
|
604
|
+
for (size_t j = 0; j < r->v.arr.len; j++) {
|
|
605
|
+
scr_dyn_arr_push(out, scr_dyn_retain(r->v.arr.items[j]));
|
|
606
|
+
}
|
|
607
|
+
scr_dyn_release(r);
|
|
608
|
+
} else if (scr_dyn_isl_is_array(r)) {
|
|
609
|
+
/* An engine-array result: length + element reads through the
|
|
610
|
+
* routed engine ops (a bridged surprise unwinds). */
|
|
611
|
+
ScrStr *lk = scr_str_new("length", 6);
|
|
612
|
+
ScrDyn *lenv = scr_dyn_isl_key_get(r, lk);
|
|
613
|
+
scr_str_release(lk);
|
|
614
|
+
if (!lenv) { scr_dyn_release(r); scr_dyn_release(out); return NULL; }
|
|
615
|
+
size_t rn = lenv->kind == SCR_DYN_NUM ? (size_t)lenv->v.num : 0;
|
|
616
|
+
scr_dyn_release(lenv);
|
|
617
|
+
for (size_t j = 0; j < rn; j++) {
|
|
618
|
+
char idx[24];
|
|
619
|
+
int ilen = snprintf(idx, sizeof idx, "%zu", j);
|
|
620
|
+
ScrStr *jk = scr_str_new(idx, (size_t)ilen);
|
|
621
|
+
ScrDyn *el = scr_dyn_isl_key_get(r, jk);
|
|
622
|
+
scr_str_release(jk);
|
|
623
|
+
if (!el) { scr_dyn_release(r); scr_dyn_release(out); return NULL; }
|
|
624
|
+
scr_dyn_arr_push(out, el); /* ownership moves in */
|
|
625
|
+
}
|
|
626
|
+
scr_dyn_release(r);
|
|
627
|
+
} else {
|
|
628
|
+
scr_dyn_arr_push(out, r); /* ownership moves in */
|
|
629
|
+
}
|
|
630
|
+
}
|
|
631
|
+
return out;
|
|
632
|
+
}
|
|
544
633
|
if (dyn_name_is(method, "sort")) {
|
|
545
634
|
ScrDyn *cmp = argc > 0 ? args[0] : scr_dyn_undefined();
|
|
546
635
|
if (cmp->kind != SCR_DYN_UNDEF && cmp->kind != SCR_DYN_FUNC) {
|
|
@@ -598,6 +687,11 @@ ScrDyn *scr_dyn_invoke(ScrDyn *recv, const char *method, ScrDyn *const *args, si
|
|
|
598
687
|
* (DOM properties are plain data properties — SEMANTICS.md); get/set
|
|
599
688
|
* throw the loud unsupported Error, never a silent drop. */
|
|
600
689
|
ScrDyn *scr_dyn_define_props(ScrDyn *target, ScrDyn *descs) {
|
|
690
|
+
/* Island-held operands ARE objects to Node — the non-object TypeError
|
|
691
|
+
* below would be a wrong claim. Loud fence (lane dyn-routing-ops). */
|
|
692
|
+
scr_dyn_isl_fence(target, "Object.defineProperties");
|
|
693
|
+
if (!scr_exc_pending()) scr_dyn_isl_fence(descs, "Object.defineProperties");
|
|
694
|
+
if (scr_exc_pending()) return NULL;
|
|
601
695
|
if (target->kind != SCR_DYN_OBJ && target->kind != SCR_DYN_FUNC) {
|
|
602
696
|
scr_throw_error_msg(SCR_ERR_TYPE, "Object.defineProperties called on non-object",
|
|
603
697
|
strlen("Object.defineProperties called on non-object"));
|
package/src/scr_events_emitter.c
CHANGED
|
@@ -85,6 +85,12 @@ typedef struct ScrEeBucket {
|
|
|
85
85
|
struct ScrEeReg {
|
|
86
86
|
ScrEeBucket *head; /* singly linked, first-registration order */
|
|
87
87
|
double max; /* -1 = unset (follows the default), 0 = unlimited */
|
|
88
|
+
/* Node's kShapeMode: set when names were PRE-CREATED (the stream
|
|
89
|
+
* constructors). In shape mode removeListener KEEPS an emptied name's
|
|
90
|
+
* rank (Node writes events[type] = undefined instead of deleting) —
|
|
91
|
+
* only removeAllListeners deletes: the named form drops the one key,
|
|
92
|
+
* the no-argument wipe resets everything and leaves shape mode. */
|
|
93
|
+
bool shape;
|
|
88
94
|
};
|
|
89
95
|
|
|
90
96
|
/* The vtable of BARE `new EventEmitter()` instances; the emitted main()
|
|
@@ -145,6 +151,21 @@ static ScrEeBucket *scr_ee_bucket_ensure(ScrEeReg *reg, ScrStr *name) {
|
|
|
145
151
|
return b;
|
|
146
152
|
}
|
|
147
153
|
|
|
154
|
+
/* Reserve a name's first-registration RANK without any listener: Node's
|
|
155
|
+
* stream classes pre-create their known _events keys (a V8 shape
|
|
156
|
+
* optimization eventNames() order observes — 'error'/'data'/... list
|
|
157
|
+
* before user events added earlier). An empty bucket is ABSENT for every
|
|
158
|
+
* read (n == 0 everywhere); the first add fills it in place, and a bucket
|
|
159
|
+
* emptied by removal still drops — Node deleting the key. */
|
|
160
|
+
void scr_emitter_reserve(ScrEmitter *em, const char *name) {
|
|
161
|
+
ScrEeReg *reg = scr_ee_reg_ensure(em);
|
|
162
|
+
reg->shape = true;
|
|
163
|
+
if (scr_ee_bucket_find(reg, name, strlen(name))) return;
|
|
164
|
+
ScrStr *n = scr_str_new(name, strlen(name));
|
|
165
|
+
scr_ee_bucket_ensure(reg, n);
|
|
166
|
+
scr_str_release(n);
|
|
167
|
+
}
|
|
168
|
+
|
|
148
169
|
/* Drops an emptied bucket from the list (Node deletes the _events key; a
|
|
149
170
|
* later add re-appends at the end). */
|
|
150
171
|
static void scr_ee_bucket_drop(ScrEeReg *reg, ScrEeBucket *b) {
|
|
@@ -402,13 +423,14 @@ void scr_ee_inv_fixed4(ScrClosure *cb, va_list ap) {
|
|
|
402
423
|
|
|
403
424
|
/* Removes one entry (by index) from a bucket's live list and fires the
|
|
404
425
|
* 'removeListener' meta event AFTER the removal, Node's order. Drops the
|
|
405
|
-
* bucket when emptied
|
|
426
|
+
* bucket when emptied — except in shape mode, where the emptied name
|
|
427
|
+
* keeps its rank (Node's events[type] = undefined). */
|
|
406
428
|
static void scr_ee_remove_at(ScrEmitter *em, ScrEeBucket *b, size_t i) {
|
|
407
429
|
ScrEeEntry *e = b->ls[i];
|
|
408
430
|
memmove(b->ls + i, b->ls + i + 1, (b->n - i - 1) * sizeof *b->ls);
|
|
409
431
|
b->n--;
|
|
410
432
|
ScrStr *name = scr_str_retain(b->name);
|
|
411
|
-
if (b->n == 0) scr_ee_bucket_drop(em->reg, b);
|
|
433
|
+
if (b->n == 0 && !em->reg->shape) scr_ee_bucket_drop(em->reg, b);
|
|
412
434
|
scr_ee_entry_unref(e);
|
|
413
435
|
scr_ee_emit_meta(em, "removeListener", name);
|
|
414
436
|
scr_str_release(name);
|
|
@@ -456,6 +478,13 @@ void scr_emitter_check_listener(const ScrDyn *cb) {
|
|
|
456
478
|
* firing the meta event — and the whole-emitter form does every other
|
|
457
479
|
* event first (bucket order), 'removeListener' itself LAST. Returns em +1. */
|
|
458
480
|
static void scr_ee_remove_all_named(ScrEmitter *em, ScrEeBucket *b, bool meta) {
|
|
481
|
+
if (b->n == 0) {
|
|
482
|
+
/* An empty rank-holding bucket reaches here only from the WIPE scan
|
|
483
|
+
* (the named form skips undefined keys — Node no-ops and the rank
|
|
484
|
+
* stays): drop it, the wipe resets _events wholesale. */
|
|
485
|
+
scr_ee_bucket_drop(em->reg, b);
|
|
486
|
+
return;
|
|
487
|
+
}
|
|
459
488
|
if (!meta) {
|
|
460
489
|
for (size_t i = 0; i < b->n; i++) scr_ee_entry_unref(b->ls[i]);
|
|
461
490
|
b->n = 0;
|
|
@@ -497,7 +526,26 @@ ScrEmitter *scr_emitter_remove_all(ScrEmitter *em, ScrStr *name, bool all) {
|
|
|
497
526
|
bool meta = scr_ee_has(reg, "removeListener");
|
|
498
527
|
if (!all) {
|
|
499
528
|
ScrEeBucket *b = scr_ee_bucket_find(reg, name->data, name->len);
|
|
500
|
-
|
|
529
|
+
/* A rank-holding empty bucket is Node's `events[type] === undefined`:
|
|
530
|
+
* the named form no-ops there (the rank survives). A POPULATED name
|
|
531
|
+
* deletes its key even in shape mode — but through the meta path each
|
|
532
|
+
* listener leaves via removeListener, whose shape rule KEEPS the
|
|
533
|
+
* emptied rank (Node's exact split). */
|
|
534
|
+
if (b && b->n > 0) {
|
|
535
|
+
scr_ee_remove_all_named(em, b, meta);
|
|
536
|
+
if (!meta) {
|
|
537
|
+
/* Node's non-meta named branch: the count hitting zero replaces
|
|
538
|
+
* _events wholesale — every rank (pre-created included) goes,
|
|
539
|
+
* though kShapeMode itself stays set (Node's exact quirk). */
|
|
540
|
+
bool any_live = false;
|
|
541
|
+
for (ScrEeBucket *w = reg->head; w; w = w->next) {
|
|
542
|
+
if (w->n > 0) { any_live = true; break; }
|
|
543
|
+
}
|
|
544
|
+
if (!any_live) {
|
|
545
|
+
while (reg->head) scr_ee_bucket_drop(reg, reg->head);
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
}
|
|
501
549
|
return scr_emitter_retain(em);
|
|
502
550
|
}
|
|
503
551
|
/* Every event except 'removeListener' first, in bucket order; then
|
|
@@ -515,6 +563,10 @@ ScrEmitter *scr_emitter_remove_all(ScrEmitter *em, ScrStr *name, bool all) {
|
|
|
515
563
|
}
|
|
516
564
|
ScrEeBucket *rl = scr_ee_bucket_find(reg, "removeListener", 14);
|
|
517
565
|
if (rl) scr_ee_remove_all_named(em, rl, meta);
|
|
566
|
+
/* The wipe replaces _events wholesale in Node — pre-created ranks are
|
|
567
|
+
* gone and the emitter leaves shape mode. */
|
|
568
|
+
while (reg->head) scr_ee_bucket_drop(reg, reg->head);
|
|
569
|
+
reg->shape = false;
|
|
518
570
|
return scr_emitter_retain(em);
|
|
519
571
|
}
|
|
520
572
|
|
|
@@ -633,12 +685,13 @@ double scr_emitter_listener_count_fn(ScrEmitter *em, ScrStr *name, ScrClosure *f
|
|
|
633
685
|
}
|
|
634
686
|
|
|
635
687
|
/* eventNames(): +1 string[] of the bucket names in first-registration
|
|
636
|
-
* order (exactly Node's _events key order).
|
|
688
|
+
* order (exactly Node's _events key order). Reserved-but-empty buckets
|
|
689
|
+
* (the stream pre-created keys) are invisible until a listener lands. */
|
|
637
690
|
ScrArr *scr_emitter_event_names(ScrEmitter *em) {
|
|
638
691
|
ScrArr *out = scr_arr_new(SCR_ELEM_STR, 0);
|
|
639
692
|
if (em->reg) {
|
|
640
693
|
for (ScrEeBucket *b = em->reg->head; b; b = b->next) {
|
|
641
|
-
scr_arr_push_ref(out, scr_str_retain(b->name));
|
|
694
|
+
if (b->n > 0) scr_arr_push_ref(out, scr_str_retain(b->name));
|
|
642
695
|
}
|
|
643
696
|
}
|
|
644
697
|
return out;
|
package/src/scr_inspect.c
CHANGED
|
@@ -775,8 +775,18 @@ ScrStr *scr_insp_dyn(ScrDyn *d, double recurse, double depth) {
|
|
|
775
775
|
return out;
|
|
776
776
|
}
|
|
777
777
|
case SCR_DYN_OBJ: {
|
|
778
|
-
|
|
779
|
-
|
|
778
|
+
/* Object.create(null)'s dictionary: Node prefixes the rendering
|
|
779
|
+
* with "[Object: null prototype]" (formatValue's constructor-less
|
|
780
|
+
* base), the empty form included, and the beyond-depth answer IS
|
|
781
|
+
* the bare marker (where a plain object says [Object]). */
|
|
782
|
+
if (d->v.obj.len == 0) {
|
|
783
|
+
return d->null_proto ? scr_str_new("[Object: null prototype] {}", 27)
|
|
784
|
+
: scr_str_new("{}", 2);
|
|
785
|
+
}
|
|
786
|
+
if (recurse > depth) {
|
|
787
|
+
return d->null_proto ? scr_str_new("[Object: null prototype]", 24)
|
|
788
|
+
: scr_str_new("[Object]", 8);
|
|
789
|
+
}
|
|
780
790
|
scr_insp_begin(recurse + 1);
|
|
781
791
|
for (size_t i = 0; i < d->v.obj.len; i++) {
|
|
782
792
|
ScrDynEntry *ent = &d->v.obj.entries[i];
|
|
@@ -790,7 +800,8 @@ ScrStr *scr_insp_dyn(ScrDyn *d, double recurse, double depth) {
|
|
|
790
800
|
scr_insp_entry(entry, false);
|
|
791
801
|
scr_str_release(entry);
|
|
792
802
|
}
|
|
793
|
-
ScrStr *base = scr_str_new("",
|
|
803
|
+
ScrStr *base = d->null_proto ? scr_str_new("[Object: null prototype]", 24)
|
|
804
|
+
: scr_str_new("", 0);
|
|
794
805
|
ScrStr *b0 = scr_str_new("{", 1);
|
|
795
806
|
ScrStr *b1 = scr_str_new("}", 1);
|
|
796
807
|
ScrStr *out = scr_insp_end(base, b0, b1, recurse + 1, false, false);
|
|
@@ -825,6 +836,19 @@ ScrStr *scr_insp_dyn(ScrDyn *d, double recurse, double depth) {
|
|
|
825
836
|
scr_throw_error(SCR_ERR_ERROR, ib_take(&out));
|
|
826
837
|
return scr_str_new("", 0);
|
|
827
838
|
}
|
|
839
|
+
case SCR_DYN_JSVAL: {
|
|
840
|
+
/* An island value inside the DOM: Node prints the engine object's
|
|
841
|
+
* property dump — fence loudly, naming the engine typeof (the
|
|
842
|
+
* scr_insp_jsval wording for bare 'any' composites). */
|
|
843
|
+
ScrStr *t = scr_dyn_typeof(d); /* routes to the engine; +1 */
|
|
844
|
+
InspBuf out = {0};
|
|
845
|
+
ib_cstr(&out, "util.inspect of a composite 'any' value (typeof '");
|
|
846
|
+
ib_bytes(&out, t->data, t->len);
|
|
847
|
+
ib_cstr(&out, "') is not supported yet");
|
|
848
|
+
scr_str_release(t);
|
|
849
|
+
scr_throw_error(SCR_ERR_ERROR, ib_take(&out));
|
|
850
|
+
return scr_str_new("", 0);
|
|
851
|
+
}
|
|
828
852
|
case SCR_DYN_PROMISE: {
|
|
829
853
|
/* Node renders Promise { <pending> } / Promise { value } — the
|
|
830
854
|
* settled-value rendering pulls in the whole inspector; fence
|