@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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@scriptc/runtime",
3
- "version": "0.0.8",
3
+ "version": "0.0.10",
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
@@ -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) return false;
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
- static size_t scr_bytes_received(double v, char out[48]); /* the numeric section below */
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', the rest
890
- * '>= 0 && <= max' (Node spells '&&' here, unlike the read/write
891
- * families' 'and'). max < 0 means copy's no-upper-bound '>= 0' render. */
892
- static bool scr_bytes_validate_off(const char *name, double value, double max) {
893
- if (floor(value) == value && value >= 0 && (max < 0 || value <= max)) return true;
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
- scr_bytes_received(value, recv);
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
- scr_throw_error_msg(SCR_ERR_RANGE, msg, (size_t)mlen);
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
- scr_throw_error_msg(SCR_ERR_TYPE, msg, sizeof msg - 1);
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
- scr_throw_error_msg(SCR_ERR_RANGE, msg, (size_t)mlen);
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
- static size_t scr_bytes_received(double v, char out[48]) {
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
- scr_bytes_received(value, recv);
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
- scr_throw_error_msg(SCR_ERR_RANGE, oob, sizeof oob - 1);
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
- scr_throw_error_msg(SCR_ERR_RANGE, msg, (size_t)mlen);
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
- scr_bytes_received(value, recv);
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
- scr_throw_error_msg(SCR_ERR_RANGE, msg, (size_t)mlen);
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);