@scriptc/runtime 0.0.8 → 0.0.10
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_bytes.c +65 -18
- package/src/scr_bytes_io.c +507 -1
- package/src/scr_dc.c +6 -0
- package/src/scr_dgram.c +176 -1
- package/src/scr_dyn_handle.c +8 -66
- package/src/scr_dyn_invoke.c +96 -2
- package/src/scr_error.c +15 -0
- package/src/scr_events_emitter.c +34 -0
- package/src/scr_exception.c +4 -1
- package/src/scr_inspect.c +27 -3
- package/src/scr_island.c +417 -3
- package/src/scr_json.c +643 -6
- package/src/scr_lib.c +122 -4
- package/src/scr_library.c +105 -2
- package/src/scr_net.c +112 -0
- package/src/scr_number.c +29 -19
- package/src/scr_runtime.h +358 -9
- package/src/scr_stream.c +49 -2
- package/src/scr_tls.c +172 -0
package/package.json
CHANGED
package/src/scr_assert.c
CHANGED
|
@@ -439,6 +439,11 @@ static bool scr_assert_dyn_same_value(const ScrDyn *a, const ScrDyn *b) {
|
|
|
439
439
|
case SCR_DYN_PROMISE:
|
|
440
440
|
/* Identity is the PROMISE (the strict_eq stance). */
|
|
441
441
|
return a->v.promise == b->v.promise;
|
|
442
|
+
case SCR_DYN_JSVAL:
|
|
443
|
+
/* Identity is the ENGINE VALUE (the strict_eq stance): the engine's
|
|
444
|
+
* === — exact for SameValue too, since wrap-time scalar
|
|
445
|
+
* normalization leaves only reference kinds behind. */
|
|
446
|
+
return a == b || scr_dyn_jsval_ops()->strict_eq(a->v.jsval.cell, b->v.jsval.cell);
|
|
442
447
|
default:
|
|
443
448
|
return a == b; /* ARR/OBJ/BYTES: node identity */
|
|
444
449
|
}
|
|
@@ -454,7 +459,16 @@ static bool scr_assert_dyn_same_value(const ScrDyn *a, const ScrDyn *b) {
|
|
|
454
459
|
* memo here where Node carries one (documented divergence). */
|
|
455
460
|
static bool scr_assert_dyn_deep_eq(const ScrDyn *a, const ScrDyn *b) {
|
|
456
461
|
if (a == b) return true;
|
|
457
|
-
if (a->kind != b->kind)
|
|
462
|
+
if (a->kind != b->kind) {
|
|
463
|
+
/* A MIXED comparison with an island side (wrapped engine object vs
|
|
464
|
+
* DOM data): Node walks both structurally — a plain `false` would
|
|
465
|
+
* mint a fabricated AssertionError for values Node may call equal.
|
|
466
|
+
* Loud fence (the long-tail lane's structural walk). */
|
|
467
|
+
if (a->kind == SCR_DYN_JSVAL || b->kind == SCR_DYN_JSVAL) {
|
|
468
|
+
scr_dyn_isl_fence(a->kind == SCR_DYN_JSVAL ? a : b, "deepStrictEqual");
|
|
469
|
+
}
|
|
470
|
+
return false;
|
|
471
|
+
}
|
|
458
472
|
switch (a->kind) {
|
|
459
473
|
case SCR_DYN_UNDEF:
|
|
460
474
|
case SCR_DYN_NULL:
|
|
@@ -493,6 +507,7 @@ static bool scr_assert_dyn_deep_eq(const ScrDyn *a, const ScrDyn *b) {
|
|
|
493
507
|
return true;
|
|
494
508
|
}
|
|
495
509
|
case SCR_DYN_OBJ: {
|
|
510
|
+
if (a->null_proto != b->null_proto) return false; /* the prototype gate */
|
|
496
511
|
if (a->v.obj.len != b->v.obj.len) return false;
|
|
497
512
|
for (size_t i = 0; i < a->v.obj.len; i++) {
|
|
498
513
|
const ScrDynEntry *ent = &a->v.obj.entries[i];
|
|
@@ -501,6 +516,14 @@ static bool scr_assert_dyn_deep_eq(const ScrDyn *a, const ScrDyn *b) {
|
|
|
501
516
|
}
|
|
502
517
|
return true;
|
|
503
518
|
}
|
|
519
|
+
case SCR_DYN_JSVAL:
|
|
520
|
+
/* Node walks the engine objects structurally — a walk this runtime
|
|
521
|
+
* cannot run. Engine-identical answers true honestly; anything else
|
|
522
|
+
* throws the loud ladder (scr_assert_eq_dyn propagates the pending
|
|
523
|
+
* exception INSTEAD of minting an AssertionError). */
|
|
524
|
+
if (scr_dyn_jsval_ops()->strict_eq(a->v.jsval.cell, b->v.jsval.cell)) return true;
|
|
525
|
+
scr_dyn_isl_fence(a, "deepStrictEqual");
|
|
526
|
+
return false;
|
|
504
527
|
}
|
|
505
528
|
return false; /* unreachable */
|
|
506
529
|
}
|
|
@@ -653,15 +676,26 @@ static void scr_assert_cf_value(ScrAssertBuf *b, const ScrDyn *d, size_t indent,
|
|
|
653
676
|
ab_char(b, ']');
|
|
654
677
|
return;
|
|
655
678
|
}
|
|
679
|
+
case SCR_DYN_JSVAL: {
|
|
680
|
+
/* The depth-elided placeholder (the handle stance): Node renders
|
|
681
|
+
* the engine object's property dump — internals this walker does
|
|
682
|
+
* not model; the text only appears inside FAILURE reports, which
|
|
683
|
+
* already diverge in format. */
|
|
684
|
+
ab_cstr(b, "[island value]");
|
|
685
|
+
return;
|
|
686
|
+
}
|
|
656
687
|
case SCR_DYN_OBJ: {
|
|
688
|
+
/* The null-proto dictionary renders with Node's prefix in the
|
|
689
|
+
* failure diff too (assertion_error.js inspects both sides). */
|
|
657
690
|
if (d->v.obj.len == 0) {
|
|
658
|
-
ab_cstr(b, "{}");
|
|
691
|
+
ab_cstr(b, d->null_proto ? "[Object: null prototype] {}" : "{}");
|
|
659
692
|
return;
|
|
660
693
|
}
|
|
661
694
|
if (depth == 0) {
|
|
662
|
-
ab_cstr(b, "[Object]");
|
|
695
|
+
ab_cstr(b, d->null_proto ? "[Object: null prototype]" : "[Object]");
|
|
663
696
|
return;
|
|
664
697
|
}
|
|
698
|
+
if (d->null_proto) ab_cstr(b, "[Object: null prototype] ");
|
|
665
699
|
/* Render every entry, then sort the RENDERED texts (Node's
|
|
666
700
|
* sorted:true sorts formatted entries, quotes included). */
|
|
667
701
|
ScrCfEntry *ents = malloc(d->v.obj.len * sizeof *ents);
|
|
@@ -893,7 +927,8 @@ static bool scr_assert_print_myers(ScrAssertBuf *b, const ScrDiffOp *diff, size_
|
|
|
893
927
|
/* Is this DOM kind `typeof == "object" && != null` to assertion_error.js? */
|
|
894
928
|
static bool scr_assert_dyn_is_object(const ScrDyn *d) {
|
|
895
929
|
return d->kind == SCR_DYN_ARR || d->kind == SCR_DYN_OBJ || d->kind == SCR_DYN_BYTES ||
|
|
896
|
-
d->kind == SCR_DYN_HANDLE || d->kind == SCR_DYN_PROMISE
|
|
930
|
+
d->kind == SCR_DYN_HANDLE || d->kind == SCR_DYN_PROMISE ||
|
|
931
|
+
scr_dyn_isl_typeof_is(d, "object"); /* engine-held: the engine's typeof */
|
|
897
932
|
}
|
|
898
933
|
|
|
899
934
|
/* The failing EQUAL operators over dyn operands — createErrDiff. */
|
|
@@ -1065,6 +1100,10 @@ static void scr_assert_dyn_neq_fail(ScrDyn *a, bool deep, ScrStr *msg, bool has_
|
|
|
1065
1100
|
void scr_assert_eq_dyn(ScrDyn *a, ScrDyn *b, bool negated, bool deep,
|
|
1066
1101
|
ScrStr *msg, bool has_msg) {
|
|
1067
1102
|
bool same = deep ? scr_assert_dyn_deep_eq(a, b) : scr_assert_dyn_same_value(a, b);
|
|
1103
|
+
/* The deep walk's JSVAL arm fences loudly (an island value it cannot
|
|
1104
|
+
* compare structurally): propagate THAT, never a fabricated
|
|
1105
|
+
* AssertionError over a comparison that did not run. */
|
|
1106
|
+
if (scr_exc_pending()) return;
|
|
1068
1107
|
if ((negated && !same) || (!negated && same)) return;
|
|
1069
1108
|
if (negated) {
|
|
1070
1109
|
scr_assert_dyn_neq_fail(a, deep, msg, has_msg);
|
package/src/scr_bytes.c
CHANGED
|
@@ -312,6 +312,49 @@ double scr_dataview_get(const ScrBytes *b, double byte_off, ScrDataViewGet kind,
|
|
|
312
312
|
return 0; /* unreachable */
|
|
313
313
|
}
|
|
314
314
|
|
|
315
|
+
void scr_dataview_set(ScrBytes *b, double byte_off, double value, ScrDataViewGet kind, bool le) {
|
|
316
|
+
size_t width = scr_dataview_get_size(kind);
|
|
317
|
+
/* ToIndex + the view-relative bounds check — the getters' ONE message. */
|
|
318
|
+
double off = (byte_off != byte_off) ? 0 : trunc(byte_off);
|
|
319
|
+
if (!(off >= 0) || off > 9007199254740991.0 || off + (double)width > (double)b->len) {
|
|
320
|
+
static const char msg[] = "Offset is outside the bounds of the DataView";
|
|
321
|
+
scr_throw_error_msg(SCR_ERR_RANGE, msg, sizeof msg - 1);
|
|
322
|
+
return;
|
|
323
|
+
}
|
|
324
|
+
/* Coerce to the stored bit pattern. The integer kinds share ToUint32's
|
|
325
|
+
* 2^32 residue (signed/unsigned store the same bits; narrower widths
|
|
326
|
+
* take the low bytes — 2^width divides 2^32, so the residues agree);
|
|
327
|
+
* F32 rounds double→float to nearest even, exactly the spec. */
|
|
328
|
+
uint64_t u = 0;
|
|
329
|
+
switch (kind) {
|
|
330
|
+
case SCR_DV_U8:
|
|
331
|
+
case SCR_DV_I8:
|
|
332
|
+
case SCR_DV_U16:
|
|
333
|
+
case SCR_DV_I16:
|
|
334
|
+
case SCR_DV_U32:
|
|
335
|
+
case SCR_DV_I32:
|
|
336
|
+
u = (uint64_t)scr_bytes_to_u32(value);
|
|
337
|
+
break;
|
|
338
|
+
case SCR_DV_F32: {
|
|
339
|
+
float f = (float)value;
|
|
340
|
+
uint32_t bits;
|
|
341
|
+
memcpy(&bits, &f, 4);
|
|
342
|
+
u = bits;
|
|
343
|
+
break;
|
|
344
|
+
}
|
|
345
|
+
case SCR_DV_F64:
|
|
346
|
+
memcpy(&u, &value, 8);
|
|
347
|
+
break;
|
|
348
|
+
default:
|
|
349
|
+
return; /* BIG kinds never lower (bigint arguments) */
|
|
350
|
+
}
|
|
351
|
+
/* Scatter host-independently; le false is the JS big-endian default. */
|
|
352
|
+
uint8_t *p = b->data + (size_t)off;
|
|
353
|
+
for (size_t i = 0; i < width; i++) {
|
|
354
|
+
p[le ? i : width - 1 - i] = (uint8_t)(u >> (8 * i));
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
|
|
315
358
|
/* ── encodings (u8 only — the compiler routes only u8 receivers here) ──── */
|
|
316
359
|
|
|
317
360
|
static const char scr_hex_digits[] = "0123456789abcdef";
|
|
@@ -884,18 +927,21 @@ ScrBytes *scr_bytes_from_arr(ScrBytesElem elem, const ScrArr *arr) {
|
|
|
884
927
|
* the '>= 0 && <= max' render, ERR_OUT_OF_RANGE's Received rules — and
|
|
885
928
|
* copy's C++-side ladder; pinned by corpus 1663) ─────────────────────── */
|
|
886
929
|
|
|
887
|
-
|
|
930
|
+
size_t scr_num_received(double v, char out[48]); /* the numeric section below */
|
|
888
931
|
|
|
889
|
-
/* validateOffset(name, 0, max): non-integers are 'an integer'
|
|
890
|
-
*
|
|
891
|
-
*
|
|
892
|
-
|
|
893
|
-
|
|
932
|
+
/* validateOffset(name, 0, max): non-integers are 'an integer' (Number.
|
|
933
|
+
* isInteger — ±Infinity render 'an integer' too), the rest '>= 0 && <=
|
|
934
|
+
* max' (Node spells '&&' here, unlike the read/write families' 'and').
|
|
935
|
+
* max < 0 means copy's no-upper-bound '>= 0' render. Exported: the
|
|
936
|
+
* checked-dynamic compare/equals validators (scr_bytes_io.c) run the
|
|
937
|
+
* same ladder after their own type gate. */
|
|
938
|
+
bool scr_bytes_validate_off(const char *name, double value, double max) {
|
|
939
|
+
if (isfinite(value) && floor(value) == value && value >= 0 && (max < 0 || value <= max)) return true;
|
|
894
940
|
char recv[48];
|
|
895
|
-
|
|
941
|
+
scr_num_received(value, recv);
|
|
896
942
|
char msg[160];
|
|
897
943
|
int mlen;
|
|
898
|
-
if (floor(value) != value) {
|
|
944
|
+
if (floor(value) != value || !isfinite(value)) {
|
|
899
945
|
mlen = snprintf(msg, sizeof msg,
|
|
900
946
|
"The value of \"%s\" is out of range. It must be an integer. Received %s",
|
|
901
947
|
name, recv);
|
|
@@ -909,7 +955,7 @@ static bool scr_bytes_validate_off(const char *name, double value, double max) {
|
|
|
909
955
|
"The value of \"%s\" is out of range. It must be >= 0 && <= %s. Received %s",
|
|
910
956
|
name, maxb, recv);
|
|
911
957
|
}
|
|
912
|
-
|
|
958
|
+
scr_throw_error_msg_code(SCR_ERR_RANGE, msg, (size_t)mlen, "ERR_OUT_OF_RANGE");
|
|
913
959
|
return false;
|
|
914
960
|
}
|
|
915
961
|
|
|
@@ -994,7 +1040,7 @@ static ScrBytes *scr_bytes_fill_core(ScrBytes *b, const uint8_t *pat, size_t pat
|
|
|
994
1040
|
bool zero_ok, double nargs, double offset, double end) {
|
|
995
1041
|
if (patn == 0 && !zero_ok) {
|
|
996
1042
|
static const char msg[] = "The argument 'value' is invalid. Received <Buffer >";
|
|
997
|
-
|
|
1043
|
+
scr_throw_error_msg_code(SCR_ERR_TYPE, msg, sizeof msg - 1, "ERR_INVALID_ARG_VALUE");
|
|
998
1044
|
return NULL;
|
|
999
1045
|
}
|
|
1000
1046
|
size_t n = (size_t)nargs;
|
|
@@ -1065,7 +1111,7 @@ ScrBytes *scr_bytes_swap(ScrBytes *b, double width) {
|
|
|
1065
1111
|
if (b->len % w != 0) {
|
|
1066
1112
|
char msg[64];
|
|
1067
1113
|
int mlen = snprintf(msg, sizeof msg, "Buffer size must be a multiple of %zu-bits", w * 8);
|
|
1068
|
-
|
|
1114
|
+
scr_throw_error_msg_code(SCR_ERR_RANGE, msg, (size_t)mlen, "ERR_INVALID_BUFFER_SIZE");
|
|
1069
1115
|
return NULL;
|
|
1070
1116
|
}
|
|
1071
1117
|
for (size_t g = 0; g < b->len; g += w) {
|
|
@@ -1204,8 +1250,9 @@ ScrBytes *scr_bytes_concat(const ScrArr *list) {
|
|
|
1204
1250
|
/* ERR_OUT_OF_RANGE's "Received" rendering: integers with |v| > 2^32 get
|
|
1205
1251
|
* Node's addNumericalSeparator underscores applied to the plain String()
|
|
1206
1252
|
* form — INCLUDING its quirks on exponent renderings ("1e_+21",
|
|
1207
|
-
* "1e+_300"); everything else is the shortest-roundtrip number.
|
|
1208
|
-
|
|
1253
|
+
* "1e+_300"); everything else is the shortest-roundtrip number. Shared
|
|
1254
|
+
* with the fs/net option-ladder validators (scr_num_received). */
|
|
1255
|
+
size_t scr_num_received(double v, char out[48]) {
|
|
1209
1256
|
char plain[32];
|
|
1210
1257
|
size_t n = scr_f64_to_str(v, plain);
|
|
1211
1258
|
if (!(isfinite(v) && trunc(v) == v && fabs(v) > 4294967296.0)) {
|
|
@@ -1235,7 +1282,7 @@ static size_t scr_bytes_received(double v, char out[48]) {
|
|
|
1235
1282
|
* "byteLength" renders min 1. All catchable RangeErrors. */
|
|
1236
1283
|
static void scr_bytes_bounds_error(double value, double length, const char *type) {
|
|
1237
1284
|
char recv[48];
|
|
1238
|
-
|
|
1285
|
+
scr_num_received(value, recv);
|
|
1239
1286
|
char msg[160];
|
|
1240
1287
|
int mlen;
|
|
1241
1288
|
if (floor(value) != value) {
|
|
@@ -1244,7 +1291,7 @@ static void scr_bytes_bounds_error(double value, double length, const char *type
|
|
|
1244
1291
|
type ? type : "offset", recv);
|
|
1245
1292
|
} else if (length < 0) {
|
|
1246
1293
|
static const char oob[] = "Attempt to access memory outside buffer bounds";
|
|
1247
|
-
|
|
1294
|
+
scr_throw_error_msg_code(SCR_ERR_RANGE, oob, sizeof oob - 1, "ERR_BUFFER_OUT_OF_BOUNDS");
|
|
1248
1295
|
return;
|
|
1249
1296
|
} else {
|
|
1250
1297
|
char lenbuf[32];
|
|
@@ -1253,7 +1300,7 @@ static void scr_bytes_bounds_error(double value, double length, const char *type
|
|
|
1253
1300
|
"The value of \"%s\" is out of range. It must be >= %d and <= %s. Received %s",
|
|
1254
1301
|
type ? type : "offset", type ? 1 : 0, lenbuf, recv);
|
|
1255
1302
|
}
|
|
1256
|
-
|
|
1303
|
+
scr_throw_error_msg_code(SCR_ERR_RANGE, msg, (size_t)mlen, "ERR_OUT_OF_RANGE");
|
|
1257
1304
|
}
|
|
1258
1305
|
|
|
1259
1306
|
/* The shared offset gate: width bytes at offset must lie inside b. */
|
|
@@ -1276,7 +1323,7 @@ static bool scr_bytes_check_int(const ScrBytes *b, double value, double offset,
|
|
|
1276
1323
|
double min = sign ? -exp2((double)(8 * width - 1)) : 0;
|
|
1277
1324
|
if (value > max || value < min) {
|
|
1278
1325
|
char recv[48];
|
|
1279
|
-
|
|
1326
|
+
scr_num_received(value, recv);
|
|
1280
1327
|
char msg[160];
|
|
1281
1328
|
int mlen;
|
|
1282
1329
|
if (width > 4) {
|
|
@@ -1297,7 +1344,7 @@ static bool scr_bytes_check_int(const ScrBytes *b, double value, double offset,
|
|
|
1297
1344
|
"The value of \"value\" is out of range. It must be >= %s and <= %s. Received %s",
|
|
1298
1345
|
minb, maxb, recv);
|
|
1299
1346
|
}
|
|
1300
|
-
|
|
1347
|
+
scr_throw_error_msg_code(SCR_ERR_RANGE, msg, (size_t)mlen, "ERR_OUT_OF_RANGE");
|
|
1301
1348
|
return false;
|
|
1302
1349
|
}
|
|
1303
1350
|
return scr_bytes_rw_check(b, offset, width);
|