@scriptc/cli-darwin-x64 0.2.1 → 0.2.2

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.
Files changed (118) hide show
  1. package/dist/THIRD_PARTY_NOTICES +1 -1
  2. package/dist/bin/scriptc +0 -0
  3. package/dist/bin/scriptc.json +1 -1
  4. package/dist/lib/declarations/scriptc-node-fallback.d.ts +59 -4
  5. package/dist/lib/llvm/bin/scriptc-llvm-codegen +0 -0
  6. package/dist/lib/llvm/package.json +1 -1
  7. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/default/scr_async.o +0 -0
  8. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/default/scr_async_dyn.o +0 -0
  9. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/default/scr_bytes.o +0 -0
  10. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/default/scr_bytes_io.o +0 -0
  11. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/default/scr_crypto_async.o +0 -0
  12. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/default/scr_dyn_invoke.o +0 -0
  13. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/default/scr_file_handle.o +0 -0
  14. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/default/scr_json.o +0 -0
  15. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/default/scr_lib.o +0 -0
  16. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/default/scr_qs.o +0 -0
  17. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/default/scr_regex.o +0 -0
  18. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/default/scr_url.o +0 -0
  19. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/dynamic/scr_async.o +0 -0
  20. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/dynamic/scr_async_dyn.o +0 -0
  21. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/dynamic/scr_bytes.o +0 -0
  22. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/dynamic/scr_bytes_io.o +0 -0
  23. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/dynamic/scr_crypto_async.o +0 -0
  24. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/dynamic/scr_dyn_invoke.o +0 -0
  25. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/dynamic/scr_file_handle.o +0 -0
  26. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/dynamic/scr_island.o +0 -0
  27. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/dynamic/scr_json.o +0 -0
  28. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/dynamic/scr_lib.o +0 -0
  29. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/dynamic/scr_qs.o +0 -0
  30. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/dynamic/scr_regex.o +0 -0
  31. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/dynamic/scr_url.o +0 -0
  32. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/dynamic/scr_web.o +0 -0
  33. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/dynamic-text-decoder-legacy/scr_bytes.o +0 -0
  34. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/text-decoder-legacy/scr_bytes.o +0 -0
  35. package/dist/lib/runtime-darwin-x64/artifacts/library-dev/runtime/default/scr_bytes.o +0 -0
  36. package/dist/lib/runtime-darwin-x64/artifacts/library-dev/runtime/default/scr_bytes_io.o +0 -0
  37. package/dist/lib/runtime-darwin-x64/artifacts/library-dev/runtime/default/scr_dyn_invoke.o +0 -0
  38. package/dist/lib/runtime-darwin-x64/artifacts/library-dev/runtime/default/scr_json.o +0 -0
  39. package/dist/lib/runtime-darwin-x64/artifacts/library-dev/runtime/default/scr_lib.o +0 -0
  40. package/dist/lib/runtime-darwin-x64/artifacts/library-dev/runtime/default/scr_regex.o +0 -0
  41. package/dist/lib/runtime-darwin-x64/artifacts/library-dev/runtime/default/scr_url.o +0 -0
  42. package/dist/lib/runtime-darwin-x64/artifacts/library-dev/runtime/text-decoder-legacy/scr_bytes.o +0 -0
  43. package/dist/lib/runtime-darwin-x64/artifacts/library-release/runtime/default/scr_bytes.o +0 -0
  44. package/dist/lib/runtime-darwin-x64/artifacts/library-release/runtime/default/scr_bytes_io.o +0 -0
  45. package/dist/lib/runtime-darwin-x64/artifacts/library-release/runtime/default/scr_dyn_invoke.o +0 -0
  46. package/dist/lib/runtime-darwin-x64/artifacts/library-release/runtime/default/scr_json.o +0 -0
  47. package/dist/lib/runtime-darwin-x64/artifacts/library-release/runtime/default/scr_lib.o +0 -0
  48. package/dist/lib/runtime-darwin-x64/artifacts/library-release/runtime/default/scr_regex.o +0 -0
  49. package/dist/lib/runtime-darwin-x64/artifacts/library-release/runtime/default/scr_url.o +0 -0
  50. package/dist/lib/runtime-darwin-x64/artifacts/library-release/runtime/text-decoder-legacy/scr_bytes.o +0 -0
  51. package/dist/lib/runtime-darwin-x64/artifacts/library-thread-dev/runtime/default/scr_bytes.o +0 -0
  52. package/dist/lib/runtime-darwin-x64/artifacts/library-thread-dev/runtime/default/scr_bytes_io.o +0 -0
  53. package/dist/lib/runtime-darwin-x64/artifacts/library-thread-dev/runtime/default/scr_dyn_invoke.o +0 -0
  54. package/dist/lib/runtime-darwin-x64/artifacts/library-thread-dev/runtime/default/scr_json.o +0 -0
  55. package/dist/lib/runtime-darwin-x64/artifacts/library-thread-dev/runtime/default/scr_lib.o +0 -0
  56. package/dist/lib/runtime-darwin-x64/artifacts/library-thread-dev/runtime/default/scr_regex.o +0 -0
  57. package/dist/lib/runtime-darwin-x64/artifacts/library-thread-dev/runtime/default/scr_url.o +0 -0
  58. package/dist/lib/runtime-darwin-x64/artifacts/library-thread-dev/runtime/text-decoder-legacy/scr_bytes.o +0 -0
  59. package/dist/lib/runtime-darwin-x64/artifacts/library-thread-release/runtime/default/scr_bytes.o +0 -0
  60. package/dist/lib/runtime-darwin-x64/artifacts/library-thread-release/runtime/default/scr_bytes_io.o +0 -0
  61. package/dist/lib/runtime-darwin-x64/artifacts/library-thread-release/runtime/default/scr_dyn_invoke.o +0 -0
  62. package/dist/lib/runtime-darwin-x64/artifacts/library-thread-release/runtime/default/scr_json.o +0 -0
  63. package/dist/lib/runtime-darwin-x64/artifacts/library-thread-release/runtime/default/scr_lib.o +0 -0
  64. package/dist/lib/runtime-darwin-x64/artifacts/library-thread-release/runtime/default/scr_regex.o +0 -0
  65. package/dist/lib/runtime-darwin-x64/artifacts/library-thread-release/runtime/default/scr_url.o +0 -0
  66. package/dist/lib/runtime-darwin-x64/artifacts/library-thread-release/runtime/text-decoder-legacy/scr_bytes.o +0 -0
  67. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/default/scr_async.o +0 -0
  68. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/default/scr_async_dyn.o +0 -0
  69. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/default/scr_bytes.o +0 -0
  70. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/default/scr_bytes_io.o +0 -0
  71. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/default/scr_crypto_async.o +0 -0
  72. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/default/scr_dyn_invoke.o +0 -0
  73. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/default/scr_file_handle.o +0 -0
  74. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/default/scr_json.o +0 -0
  75. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/default/scr_lib.o +0 -0
  76. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/default/scr_qs.o +0 -0
  77. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/default/scr_regex.o +0 -0
  78. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/default/scr_url.o +0 -0
  79. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/dynamic/scr_async.o +0 -0
  80. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/dynamic/scr_async_dyn.o +0 -0
  81. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/dynamic/scr_bytes.o +0 -0
  82. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/dynamic/scr_bytes_io.o +0 -0
  83. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/dynamic/scr_crypto_async.o +0 -0
  84. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/dynamic/scr_dyn_invoke.o +0 -0
  85. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/dynamic/scr_file_handle.o +0 -0
  86. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/dynamic/scr_island.o +0 -0
  87. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/dynamic/scr_json.o +0 -0
  88. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/dynamic/scr_lib.o +0 -0
  89. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/dynamic/scr_qs.o +0 -0
  90. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/dynamic/scr_regex.o +0 -0
  91. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/dynamic/scr_url.o +0 -0
  92. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/dynamic/scr_web.o +0 -0
  93. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/dynamic-text-decoder-legacy/scr_bytes.o +0 -0
  94. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/text-decoder-legacy/scr_bytes.o +0 -0
  95. package/dist/lib/runtime-darwin-x64/package.json +1 -1
  96. package/dist/lib/runtime-darwin-x64/runtime-pack.json +177 -177
  97. package/dist/lib/runtime-sources/package.json +1 -1
  98. package/dist/lib/runtime-sources/src/scr_abort.c +5 -0
  99. package/dist/lib/runtime-sources/src/scr_async.c +12 -4
  100. package/dist/lib/runtime-sources/src/scr_async_dyn.c +118 -24
  101. package/dist/lib/runtime-sources/src/scr_bytes.c +226 -0
  102. package/dist/lib/runtime-sources/src/scr_bytes_io.c +52 -5
  103. package/dist/lib/runtime-sources/src/scr_crypto_async.c +22 -2
  104. package/dist/lib/runtime-sources/src/scr_dyn_invoke.c +181 -43
  105. package/dist/lib/runtime-sources/src/scr_fetch.c +45 -1
  106. package/dist/lib/runtime-sources/src/scr_file_handle.c +31 -0
  107. package/dist/lib/runtime-sources/src/scr_island.c +1188 -392
  108. package/dist/lib/runtime-sources/src/scr_island_manifest.h +11 -9
  109. package/dist/lib/runtime-sources/src/scr_json.c +449 -52
  110. package/dist/lib/runtime-sources/src/scr_json.test.ts +1 -0
  111. package/dist/lib/runtime-sources/src/scr_lib.c +816 -34
  112. package/dist/lib/runtime-sources/src/scr_qs.c +10 -0
  113. package/dist/lib/runtime-sources/src/scr_regex.c +42 -5
  114. package/dist/lib/runtime-sources/src/scr_runtime.h +67 -8
  115. package/dist/lib/runtime-sources/src/scr_text_decoder_labels.h +12 -12
  116. package/dist/lib/runtime-sources/src/scr_url.c +34 -7
  117. package/dist/lib/runtime-sources/src/scr_web.c +129 -26
  118. package/package.json +1 -1
@@ -524,6 +524,7 @@ static ScrDyn *scr_dyn_alloc(ScrDynKind kind) {
524
524
  d->v.arr.properties = NULL;
525
525
  d->v.arr.sealed = false;
526
526
  d->v.arr.frozen = false;
527
+ d->v.arr.presence = NULL;
527
528
  } else if (kind == SCR_DYN_OBJ) {
528
529
  d->v.obj.len = 0; /* cap/entries preserved */
529
530
  d->v.obj.source_identity = NULL;
@@ -570,6 +571,8 @@ static void scr_dyn_dispose(ScrDyn *d, bool collected) {
570
571
  scr_bytes_release(d->v.bytes);
571
572
  break;
572
573
  case SCR_DYN_ARR:
574
+ free(d->v.arr.presence);
575
+ d->v.arr.presence = NULL;
573
576
  if (!collected) {
574
577
  for (size_t i = 0; i < d->v.arr.len; i++) scr_dyn_release(d->v.arr.items[i]);
575
578
  scr_dyn_release(d->v.arr.properties);
@@ -733,11 +736,31 @@ void scr_dyn_arr_push(ScrDyn *arr, ScrDyn *item) {
733
736
  ScrDyn **items = realloc(arr->v.arr.items, cap * sizeof *items);
734
737
  if (!items) scr_json_oom();
735
738
  arr->v.arr.items = items;
739
+ if (arr->v.arr.presence) {
740
+ unsigned char *presence = realloc(arr->v.arr.presence, cap);
741
+ if (!presence) scr_json_oom();
742
+ arr->v.arr.presence = presence;
743
+ }
736
744
  arr->v.arr.cap = cap;
737
745
  }
746
+ if (arr->v.arr.presence) arr->v.arr.presence[arr->v.arr.len] = 1;
738
747
  arr->v.arr.items[arr->v.arr.len++] = item; /* ownership moves in */
739
748
  }
740
749
 
750
+ bool scr_dyn_arr_has_index(const ScrDyn *arr, size_t index) {
751
+ return index < arr->v.arr.len && (!arr->v.arr.presence || arr->v.arr.presence[index]);
752
+ }
753
+
754
+ void scr_dyn_arr_push_hole(ScrDyn *arr) {
755
+ scr_dyn_arr_push(arr, scr_dyn_retain(scr_dyn_undefined()));
756
+ if (!arr->v.arr.presence) {
757
+ arr->v.arr.presence = malloc(arr->v.arr.cap);
758
+ if (!arr->v.arr.presence) scr_json_oom();
759
+ memset(arr->v.arr.presence, 1, arr->v.arr.len);
760
+ }
761
+ arr->v.arr.presence[arr->v.arr.len - 1] = 0;
762
+ }
763
+
741
764
  /* Spread completion for a runtime-arity argument list (`f(...xs)` in the
742
765
  * checked-dynamic tier): JS's spread over the checked-dynamic tree's iterable kinds —
743
766
  * arrays element-by-element (retained), strings by code POINT (the string
@@ -925,7 +948,13 @@ ScrDyn *scr_dyn_arr_at(const ScrDyn *d, double i) {
925
948
  if (d->kind != SCR_DYN_ARR || i < 0 || i >= (double)d->v.arr.len) {
926
949
  return scr_dyn_retain(scr_dyn_undefined());
927
950
  }
928
- return scr_dyn_retain(d->v.arr.items[(size_t)i]);
951
+ if (scr_dyn_arr_has_index(d, (size_t)i)) return scr_dyn_retain(d->v.arr.items[(size_t)i]);
952
+ char text[32];
953
+ int length = snprintf(text, sizeof text, "%zu", (size_t)i);
954
+ ScrStr *key = scr_str_new(text, (size_t)length);
955
+ ScrDyn *result = scr_dyn_arr_named_get(d, key);
956
+ scr_str_release(key);
957
+ return result;
929
958
  }
930
959
 
931
960
  ScrDyn *scr_dyn_arr_named_get(const ScrDyn *d, const ScrStr *key) {
@@ -933,8 +962,13 @@ ScrDyn *scr_dyn_arr_named_get(const ScrDyn *d, const ScrStr *key) {
933
962
  return scr_dyn_obj_read_receiver(d->v.arr.properties, key->data, key->len, d);
934
963
  const ScrDyn *prototype = d->prototype ? d->prototype :
935
964
  d != scr_builtin_array_prototype ? scr_builtin_array_prototype : NULL;
936
- return prototype ? scr_dyn_obj_read_receiver(prototype, key->data, key->len, d)
965
+ ScrDyn *value = prototype ? scr_dyn_obj_read_receiver(prototype, key->data, key->len, d)
937
966
  : scr_dyn_retain(scr_dyn_undefined());
967
+ if (value && value->kind == SCR_DYN_UNDEF && !d->null_proto && key->len == 11 && !memcmp(key->data, "constructor", 11)) {
968
+ scr_dyn_release(value);
969
+ return scr_dyn_array_constructor();
970
+ }
971
+ return value;
938
972
  }
939
973
 
940
974
  /* Takes ownership of key (malloc'd) and value. Duplicate keys: the LATER
@@ -1177,8 +1211,8 @@ ScrDyn *scr_dyn_set_prototype(ScrDyn *object, ScrDyn *prototype) {
1177
1211
  scr_dyn_release(result);
1178
1212
  return scr_dyn_retain(object);
1179
1213
  }
1180
- if (object->kind != SCR_DYN_OBJ ||
1181
- (prototype->kind != SCR_DYN_OBJ && prototype->kind != SCR_DYN_FUNC && prototype->kind != SCR_DYN_NULL)) {
1214
+ if ((object->kind != SCR_DYN_OBJ && object->kind != SCR_DYN_ARR) ||
1215
+ (prototype->kind != SCR_DYN_OBJ && prototype->kind != SCR_DYN_ARR && prototype->kind != SCR_DYN_FUNC && prototype->kind != SCR_DYN_NULL)) {
1182
1216
  static const char message[] = "Object prototype may only be an Object or null";
1183
1217
  scr_throw_error_msg(SCR_ERR_TYPE, message, sizeof message - 1);
1184
1218
  return NULL;
@@ -1312,7 +1346,7 @@ ScrDyn *scr_dyn_proxy_new(const ScrDyn *target, const ScrDyn *handler) {
1312
1346
  if (scr_exc_pending()) return NULL;
1313
1347
  native_record = plain;
1314
1348
  }
1315
- if ((target->kind != SCR_DYN_OBJ && !native_record) || handler->kind != SCR_DYN_OBJ) {
1349
+ if ((target->kind != SCR_DYN_OBJ && target->kind != SCR_DYN_FUNC && !native_record) || handler->kind != SCR_DYN_OBJ) {
1316
1350
  scr_dyn_proxy_unsupported("non-plain targets or handlers");
1317
1351
  return NULL;
1318
1352
  }
@@ -1330,7 +1364,7 @@ static ScrDyn *scr_dyn_proxy_trap(const ScrDyn *proxy, const char *name) {
1330
1364
  scr_dyn_release(method);
1331
1365
  return NULL;
1332
1366
  }
1333
- if (method->kind != SCR_DYN_FUNC) {
1367
+ if (!scr_dyn_is_callable(method)) {
1334
1368
  ScrJsonBuf msg;
1335
1369
  scr_jb_init(&msg);
1336
1370
  scr_jb_puts(&msg, "Proxy handler '");
@@ -1369,14 +1403,14 @@ static bool scr_dyn_object_proto_key(const ScrDyn *target, const ScrStr *key) {
1369
1403
  return false;
1370
1404
  }
1371
1405
 
1372
- ScrDyn *scr_dyn_proxy_get(const ScrDyn *proxy, const ScrStr *key) {
1406
+ static ScrDyn *scr_dyn_proxy_get_receiver(const ScrDyn *proxy, const ScrStr *key, const ScrDyn *receiver) {
1373
1407
  ScrDyn *trap = scr_dyn_proxy_trap(proxy, "get");
1374
1408
  if (scr_exc_pending()) return NULL;
1375
1409
  if (!trap) {
1376
1410
  ScrDyn *target = proxy->v.proxy.target;
1377
1411
  if (target->kind == SCR_DYN_TYPED_REF) {
1378
1412
  ScrDyn *view = scr_dyn_typed_ref_materialize(target);
1379
- ScrDyn *result = scr_exc_pending() ? NULL : scr_dyn_obj_read_receiver(view, key->data, key->len, proxy);
1413
+ ScrDyn *result = scr_exc_pending() ? NULL : scr_dyn_obj_read_receiver(view, key->data, key->len, receiver);
1380
1414
  scr_dyn_release(view);
1381
1415
  return result;
1382
1416
  }
@@ -1384,10 +1418,10 @@ ScrDyn *scr_dyn_proxy_get(const ScrDyn *proxy, const ScrStr *key) {
1384
1418
  scr_dyn_proxy_unsupported("inherited Object.prototype member reads");
1385
1419
  return NULL;
1386
1420
  }
1387
- return scr_dyn_obj_read(target, key->data, key->len);
1421
+ return scr_dyn_obj_read_receiver(target, key->data, key->len, receiver);
1388
1422
  }
1389
1423
  ScrDyn *property = scr_dyn_new_str((ScrStr *)key);
1390
- ScrDyn *args[] = { proxy->v.proxy.target, property, (ScrDyn *)proxy };
1424
+ ScrDyn *args[] = { proxy->v.proxy.target, property, (ScrDyn *)receiver };
1391
1425
  ScrDyn *result = scr_dyn_proxy_call(proxy, trap, args, 3);
1392
1426
  scr_dyn_release(property);
1393
1427
  ScrDynEntry *entry = scr_dyn_entry(proxy->v.proxy.target, key);
@@ -1401,6 +1435,10 @@ ScrDyn *scr_dyn_proxy_get(const ScrDyn *proxy, const ScrStr *key) {
1401
1435
  return result;
1402
1436
  }
1403
1437
 
1438
+ ScrDyn *scr_dyn_proxy_get(const ScrDyn *proxy, const ScrStr *key) {
1439
+ return scr_dyn_proxy_get_receiver(proxy, key, proxy);
1440
+ }
1441
+
1404
1442
  bool scr_dyn_proxy_has(const ScrDyn *proxy, const ScrStr *key) {
1405
1443
  ScrDyn *trap = scr_dyn_proxy_trap(proxy, "has");
1406
1444
  if (scr_exc_pending()) return false;
@@ -1459,6 +1497,7 @@ ScrDyn *scr_dyn_own_descriptor(const ScrDyn *value, const ScrStr *key) {
1459
1497
  if (scr_dyn_canonical_own_index(key, value->v.arr.len)) {
1460
1498
  size_t index = 0;
1461
1499
  for (size_t i = 0; i < key->len; i++) index = index * 10 + (size_t)(key->data[i] - '0');
1500
+ if (!scr_dyn_arr_has_index(value, index)) return scr_dyn_retain(scr_dyn_undefined());
1462
1501
  ScrDyn *out = scr_dyn_new_obj();
1463
1502
  scr_dyn_obj_set(out, "value", 5, scr_dyn_retain(value->v.arr.items[index]));
1464
1503
  scr_dyn_obj_set(out, "writable", 8, scr_dyn_new_bool(!value->v.arr.frozen));
@@ -1920,6 +1959,39 @@ ScrDyn *scr_bytes_constructor(const ScrStr *name) {
1920
1959
  scr_trap("scriptc: invalid typed array constructor name\n");
1921
1960
  }
1922
1961
  static SCR_TL ScrDyn *scr_array_buffer_ctor;
1962
+ static SCR_TL ScrDyn *scr_array_ctor;
1963
+ static void scr_array_ctor_cleanup(void) {
1964
+ scr_dyn_release(scr_array_ctor);
1965
+ scr_array_ctor = NULL;
1966
+ }
1967
+ static ScrDyn *scr_array_ctor_call(ScrClosure *closure, ScrDyn *const *args, size_t argc) {
1968
+ (void)closure;
1969
+ ScrDyn *result = scr_dyn_new_arr();
1970
+ if (argc == 1 && args[0]->kind == SCR_DYN_NUM) {
1971
+ double length = args[0]->v.num;
1972
+ if (!isfinite(length) || length < 0 || length > 4294967295.0 || trunc(length) != length) {
1973
+ scr_dyn_release(result);
1974
+ static const char message[] = "Invalid array length";
1975
+ scr_throw_error_msg(SCR_ERR_RANGE, message, sizeof message - 1);
1976
+ return NULL;
1977
+ }
1978
+ if (length > 1000000) {
1979
+ scr_dyn_release(result);
1980
+ static const char message[] = "Checked array construction exceeds the native allocation limit";
1981
+ scr_throw_error_msg_code(SCR_ERR_ERROR, message, sizeof message - 1, "SC2020");
1982
+ return NULL;
1983
+ }
1984
+ for (size_t i = 0; i < (size_t)length; i++) scr_dyn_arr_push_hole(result);
1985
+ } else for (size_t i = 0; i < argc; i++) scr_dyn_arr_push(result, scr_dyn_retain(args[i]));
1986
+ return result;
1987
+ }
1988
+ ScrDyn *scr_dyn_array_constructor(void) {
1989
+ if (!scr_array_ctor) {
1990
+ scr_array_ctor = scr_dyn_new_func(scr_closure_new(NULL, 0), scr_array_ctor_call, 1, "native:Array", "Array");
1991
+ scr_atexit(scr_array_ctor_cleanup);
1992
+ }
1993
+ return scr_dyn_retain(scr_array_ctor);
1994
+ }
1923
1995
  static void scr_array_buffer_ctor_cleanup(void) {
1924
1996
  scr_dyn_release(scr_array_buffer_ctor);
1925
1997
  scr_array_buffer_ctor = NULL;
@@ -1945,6 +2017,7 @@ bool scr_bytes_instanceof(const ScrDyn *value, const ScrDyn *callee) {
1945
2017
  return false;
1946
2018
  }
1947
2019
  if (scr_array_buffer_ctor && callee->v.fn.clo == scr_array_buffer_ctor->v.fn.clo) return scr_array_buffer_is(value);
2020
+ if (scr_array_ctor && callee->v.fn.clo == scr_array_ctor->v.fn.clo) return value->kind == SCR_DYN_ARR || scr_dyn_isl_is_array(value);
1948
2021
  for (size_t i = 0; i < 9; i++) {
1949
2022
  if (scr_bytes_ctors[i] && callee->v.fn.clo == scr_bytes_ctors[i]->v.fn.clo)
1950
2023
  return scr_dyn_typed_array_is(value, (int)i);
@@ -1954,6 +2027,8 @@ bool scr_bytes_instanceof(const ScrDyn *value, const ScrDyn *callee) {
1954
2027
  return false;
1955
2028
  }
1956
2029
  ScrDyn *scr_bytes_construct(const ScrDyn *callee, const ScrDyn *args, const ScrStr *what) {
2030
+ if (callee->kind == SCR_DYN_FUNC && scr_array_ctor && callee->v.fn.clo == scr_array_ctor->v.fn.clo)
2031
+ return scr_array_ctor_call(callee->v.fn.clo, args->v.arr.items, args->v.arr.len);
1957
2032
  if (callee->kind == SCR_DYN_FUNC && scr_array_buffer_ctor && callee->v.fn.clo == scr_array_buffer_ctor->v.fn.clo)
1958
2033
  return scr_array_buffer_new(args->v.arr.len ? args->v.arr.items[0] : scr_dyn_undefined());
1959
2034
  for (size_t i = 0; i < 9; i++) {
@@ -2031,6 +2106,11 @@ ScrDyn *scr_dyn_new_chunk(const ScrBytes *b) {
2031
2106
  /* A boxed static function value (the compiler's static→dyn converters).
2032
2107
  * Ownership of the closure MOVES in; sig/name are static literals. */
2033
2108
  ScrDyn *scr_dyn_new_func(ScrClosure *clo, ScrDynThunk thunk, uint32_t arity, const char *sig, const char *name) {
2109
+ if (clo->function_kind & 8) {
2110
+ ScrDyn *original = scr_box_get_ref(clo->caps[0]);
2111
+ scr_closure_release(clo);
2112
+ return original;
2113
+ }
2034
2114
  ScrDyn *d = scr_dyn_alloc(SCR_DYN_FUNC);
2035
2115
  d->v.fn.clo = clo;
2036
2116
  d->v.fn.thunk = thunk;
@@ -2108,6 +2188,19 @@ ScrDyn *scr_dyn_class_prototype(ScrDyn *value, ScrDyn *base) {
2108
2188
  * compiled per signature). Args borrowed; result owned (+1) or NULL with
2109
2189
  * the exception pending. */
2110
2190
  ScrDyn *scr_dyn_call(const ScrDyn *d, ScrDyn *const *args, size_t argc, const char *what) {
2191
+ if (d->kind == SCR_DYN_PROXY && scr_dyn_is_callable(d->v.proxy.target)) {
2192
+ ScrDyn *trap = scr_dyn_proxy_trap(d, "apply");
2193
+ if (scr_exc_pending()) return NULL;
2194
+ if (!trap) return scr_dyn_call(d->v.proxy.target, args, argc, what);
2195
+ ScrDyn *receiver = scr_dyn_this_get();
2196
+ ScrDyn *arguments = scr_dyn_new_arr();
2197
+ for (size_t i = 0; i < argc; i++) scr_dyn_arr_push(arguments, scr_dyn_retain(args[i]));
2198
+ ScrDyn *trap_args[] = { d->v.proxy.target, receiver, arguments };
2199
+ ScrDyn *result = scr_dyn_proxy_call(d, trap, trap_args, 3);
2200
+ scr_dyn_release(arguments);
2201
+ scr_dyn_release(receiver);
2202
+ return result;
2203
+ }
2111
2204
  if (d->kind == SCR_DYN_JSVAL) {
2112
2205
  /* An ENGINE callee: the call routes through scr_jsval_call with the
2113
2206
  * uniform argument conversion (wrapped cells by reference, dyn data
@@ -2218,7 +2311,7 @@ const char *scr_dyn_specific_type(const ScrDyn *cb, char *detail, size_t cap) {
2218
2311
  case SCR_DYN_OBJ: d = "an instance of Object"; break;
2219
2312
  case SCR_DYN_ARR: d = "an instance of Array"; break;
2220
2313
  case SCR_DYN_BYTES:
2221
- snprintf(detail, cap, "an instance of %s", cb->buffer ? "Buffer" : scr_bytes_elem_name(cb->v.bytes->elem));
2314
+ snprintf(detail, cap, "an instance of %s", cb->buffer ? "Buffer" : cb->v.bytes->is_data_view ? "DataView" : scr_bytes_elem_name(cb->v.bytes->elem));
2222
2315
  break;
2223
2316
  case SCR_DYN_FUNC:
2224
2317
  /* determineSpecificType: `function ${value.name}` — anonymous
@@ -2245,6 +2338,18 @@ const char *scr_dyn_specific_type(const ScrDyn *cb, char *detail, size_t cap) {
2245
2338
  case SCR_DYN_BOOL:
2246
2339
  snprintf(detail, cap, "type boolean (%s)", cb->v.b ? "true" : "false");
2247
2340
  break;
2341
+ case SCR_DYN_BIGINT: {
2342
+ ScrStr *value = scr_bigint_inspect(cb->v.bigint);
2343
+ snprintf(detail, cap, "type bigint (%.*s)", (int)value->len, value->data);
2344
+ scr_str_release(value);
2345
+ break;
2346
+ }
2347
+ case SCR_DYN_SYMBOL: {
2348
+ ScrStr *value = cb->v.symbol.render(cb->v.symbol.value);
2349
+ snprintf(detail, cap, "type symbol (%.*s)", (int)value->len, value->data);
2350
+ scr_str_release(value);
2351
+ break;
2352
+ }
2248
2353
  case SCR_DYN_NUM: {
2249
2354
  char num[32];
2250
2355
  size_t n = scr_f64_to_str(cb->v.num, num);
@@ -2252,19 +2357,30 @@ const char *scr_dyn_specific_type(const ScrDyn *cb, char *detail, size_t cap) {
2252
2357
  break;
2253
2358
  }
2254
2359
  case SCR_DYN_STR: {
2255
- const ScrStr *sv = cb->v.str;
2256
- char insp[32];
2257
- size_t n = 0;
2258
- insp[n++] = '\'';
2259
- for (size_t i = 0; i < sv->len && n < 28; i++) insp[n++] = sv->data[i];
2260
- if (sv->len + 2 > 28) {
2261
- n = 25;
2262
- memcpy(insp + n, "...", 3);
2263
- n += 3;
2360
+ ScrStr *value = scr_str_retain(cb->v.str);
2361
+ if (scr_str_utf16_len(value) > 28) {
2362
+ ScrStr *prefix = scr_str_slice(value, 0, 25);
2363
+ ScrStr *dots = scr_str_new("...", 3);
2364
+ scr_str_release(value);
2365
+ value = scr_str_concat(prefix, dots);
2366
+ scr_str_release(prefix);
2367
+ scr_str_release(dots);
2368
+ }
2369
+ ScrJsonBuf shown;
2370
+ scr_jb_init(&shown);
2371
+ scr_jb_puts(&shown, "type string (");
2372
+ if (memchr(value->data, '\'', value->len)) {
2373
+ scr_jb_put_json_str(&shown, value);
2264
2374
  } else {
2265
- insp[n++] = '\'';
2375
+ scr_jb_putc(&shown, '\'');
2376
+ scr_jb_put_str(&shown, value);
2377
+ scr_jb_putc(&shown, '\'');
2266
2378
  }
2267
- snprintf(detail, cap, "type string (%.*s)", (int)n, insp);
2379
+ scr_jb_putc(&shown, ')');
2380
+ ScrStr *text = scr_jb_finish(&shown);
2381
+ snprintf(detail, cap, "%.*s", (int)text->len, text->data);
2382
+ scr_str_release(text);
2383
+ scr_str_release(value);
2268
2384
  break;
2269
2385
  }
2270
2386
  default: d = "an instance of Object"; break;
@@ -2286,7 +2402,7 @@ void scr_throw_arg_type(const ScrStr *argname, const ScrStr *expected, const Scr
2286
2402
  }
2287
2403
 
2288
2404
  void scr_dyn_arg_type_fail(const char *argname, const char *expected, const ScrDyn *got) {
2289
- char detail[64];
2405
+ char detail[256];
2290
2406
  const char *d = scr_dyn_specific_type(got, detail, sizeof detail);
2291
2407
  ScrJsonBuf b;
2292
2408
  scr_jb_init(&b);
@@ -2307,7 +2423,7 @@ void scr_dyn_arg_type_fail(const char *argname, const char *expected, const ScrD
2307
2423
  * wording on the name, but every property-path caller here knows it is
2308
2424
  * one). Same runtime-rendered Received tail; always throws catchably. */
2309
2425
  void scr_dyn_prop_type_fail(const char *name, const char *expected, const ScrDyn *got) {
2310
- char detail[64];
2426
+ char detail[256];
2311
2427
  const char *d = scr_dyn_specific_type(got, detail, sizeof detail);
2312
2428
  ScrJsonBuf b;
2313
2429
  scr_jb_init(&b);
@@ -2923,7 +3039,17 @@ static ScrDyn *scr_native_iterator_next(ScrNativeIterator *iterator) {
2923
3039
  } else value = iterator->selection == 1 || iterator->kind == 3
2924
3040
  ? scr_map_dyn_key(map, index) : scr_map_dyn_value(map, index);
2925
3041
  } else if (items->kind == SCR_DYN_ARR) {
2926
- value = scr_dyn_arr_at(items, iterator->index++);
3042
+ double index = iterator->index++;
3043
+ if (iterator->selection == 1) value = scr_dyn_new_num(index);
3044
+ else {
3045
+ value = scr_dyn_arr_at(items, index);
3046
+ if (value && iterator->selection == 2) {
3047
+ ScrDyn *entry = scr_dyn_new_arr();
3048
+ scr_dyn_arr_push(entry, scr_dyn_new_num(index));
3049
+ scr_dyn_arr_push(entry, value);
3050
+ value = entry;
3051
+ }
3052
+ }
2927
3053
  } else if (items->kind == SCR_DYN_BYTES) {
2928
3054
  value = scr_dyn_new_num(scr_bytes_get(items->v.bytes, iterator->index++));
2929
3055
  } else {
@@ -3248,6 +3374,15 @@ ScrDyn *scr_dyn_symbol_key_get(const ScrDyn *value, const ScrDyn *key, bool opti
3248
3374
  return out;
3249
3375
  }
3250
3376
 
3377
+ /* Native field tables retain presence and attributes without owning a second
3378
+ * copy of the field's value. This internal update bypasses writable flags. */
3379
+ void scr_dyn_symbol_key_placeholder(ScrDyn *value, ScrDyn *key) {
3380
+ ScrDynEntry *entry = scr_dyn_symbol_entry(value, key, true);
3381
+ if (!entry || entry->accessor) return;
3382
+ scr_dyn_release(entry->value);
3383
+ entry->value = scr_dyn_retain(scr_dyn_undefined());
3384
+ }
3385
+
3251
3386
  void scr_dyn_symbol_key_set(ScrDyn *value, ScrDyn *key, ScrDyn *stored) {
3252
3387
  ScrDyn *receiver = scr_dyn_symbol_receiver(value);
3253
3388
  if (!receiver) {
@@ -3643,6 +3778,7 @@ bool scr_dyn_truthy(const ScrDyn *d) {
3643
3778
  * null answers "object" — JS's oldest wart, preserved. */
3644
3779
  ScrStr *scr_dyn_typeof(const ScrDyn *d) {
3645
3780
  const char *s;
3781
+ if (d->kind == SCR_DYN_PROXY) return scr_dyn_typeof(d->v.proxy.target);
3646
3782
  if (d->kind == SCR_DYN_TYPED_REF) {
3647
3783
  if (d->v.typed_ref.type_key_len >= 7 &&
3648
3784
  memcmp(d->v.typed_ref.type_key, "object:", 7) == 0)
@@ -3677,6 +3813,16 @@ ScrStr *scr_dyn_typeof(const ScrDyn *d) {
3677
3813
  return scr_str_new(s, strlen(s));
3678
3814
  }
3679
3815
 
3816
+ bool scr_dyn_is_callable(const ScrDyn *value) {
3817
+ while (value->kind == SCR_DYN_PROXY) value = value->v.proxy.target;
3818
+ return value->kind == SCR_DYN_FUNC || scr_dyn_isl_typeof_is(value, "function");
3819
+ }
3820
+
3821
+ int scr_dyn_function_kind(const ScrDyn *value) {
3822
+ while (value->kind == SCR_DYN_PROXY) value = value->v.proxy.target;
3823
+ return value->kind == SCR_DYN_FUNC ? value->v.fn.clo->function_kind : 0;
3824
+ }
3825
+
3680
3826
  bool scr_dyn_is_object(const ScrDyn *d) {
3681
3827
  ScrStr *type = scr_dyn_typeof(d);
3682
3828
  bool object = type->len == 6 && memcmp(type->data, "object", 6) == 0;
@@ -4538,14 +4684,26 @@ double scr_dyn_number_constructor(const ScrDyn *d) {
4538
4684
  return result;
4539
4685
  }
4540
4686
 
4541
- ScrBigInt *scr_dyn_bigint_constructor(const ScrDyn *d) {
4687
+ static ScrBigInt *scr_dyn_bigint_convert(const ScrDyn *d, bool allow_number) {
4542
4688
  ScrDyn *primitive = scr_dyn_add_primitive(d);
4543
4689
  if (!primitive) return NULL;
4544
4690
  ScrBigInt *result = NULL;
4545
4691
  switch (primitive->kind) {
4546
4692
  case SCR_DYN_BIGINT: result = scr_bigint_retain(primitive->v.bigint); break;
4547
4693
  case SCR_DYN_STR: result = scr_bigint_parse(primitive->v.str); break;
4548
- case SCR_DYN_NUM: result = scr_bigint_from_f64(primitive->v.num); break;
4694
+ case SCR_DYN_NUM:
4695
+ if (allow_number) result = scr_bigint_from_f64(primitive->v.num);
4696
+ else {
4697
+ ScrStr *text = scr_dyn_string_coerce_js(primitive);
4698
+ ScrJsonBuf message;
4699
+ scr_jb_init(&message);
4700
+ scr_jb_puts(&message, "Cannot convert ");
4701
+ for (size_t i = 0; i < text->len; i++) scr_jb_putc(&message, text->data[i]);
4702
+ scr_jb_puts(&message, " to a BigInt");
4703
+ scr_str_release(text);
4704
+ scr_throw_error(SCR_ERR_TYPE, scr_jb_finish(&message));
4705
+ }
4706
+ break;
4549
4707
  case SCR_DYN_BOOL: result = scr_bigint_from_i64(primitive->v.b ? 1 : 0); break;
4550
4708
  default: {
4551
4709
  const char *message = primitive->kind == SCR_DYN_NULL ? "Cannot convert null to a BigInt"
@@ -4558,6 +4716,14 @@ ScrBigInt *scr_dyn_bigint_constructor(const ScrDyn *d) {
4558
4716
  return result;
4559
4717
  }
4560
4718
 
4719
+ ScrBigInt *scr_dyn_bigint_constructor(const ScrDyn *d) {
4720
+ return scr_dyn_bigint_convert(d, true);
4721
+ }
4722
+
4723
+ ScrBigInt *scr_dyn_bigint_coerce(const ScrDyn *d) {
4724
+ return scr_dyn_bigint_convert(d, false);
4725
+ }
4726
+
4561
4727
  /* OrdinaryToPrimitive's default hint is numeric for the represented
4562
4728
  * ordinary objects. Retain the primitive itself: addition must choose
4563
4729
  * string concatenation before either side is converted to a number. */
@@ -4826,6 +4992,8 @@ bool scr_dyn_has_key(const ScrDyn *v, const ScrStr *key) {
4826
4992
  if (v->kind == SCR_DYN_ARR) {
4827
4993
  if (key->len == 6 && memcmp(key->data, "length", 6) == 0) return true;
4828
4994
  if (v->v.arr.properties && scr_dyn_obj_get(v->v.arr.properties, key->data, key->len)) return true;
4995
+ const ScrDyn *prototype = v->prototype ? v->prototype : !v->null_proto && v != scr_builtin_array_prototype ? scr_builtin_array_prototype : NULL;
4996
+ if (prototype && scr_dyn_has_key(prototype, key)) return true;
4829
4997
  if (key->len == 0 || key->len > 10) return false;
4830
4998
  size_t idx = 0;
4831
4999
  for (size_t i = 0; i < key->len; i++) {
@@ -4835,7 +5003,7 @@ bool scr_dyn_has_key(const ScrDyn *v, const ScrStr *key) {
4835
5003
  if (idx > (4294967294ULL - (size_t)(c - '0')) / 10) return false;
4836
5004
  idx = idx * 10 + (size_t)(c - '0');
4837
5005
  }
4838
- return idx < v->v.arr.len;
5006
+ return scr_dyn_arr_has_index(v, idx);
4839
5007
  }
4840
5008
  if (v->kind == SCR_DYN_STR)
4841
5009
  return scr_dyn_canonical_own_index(key, (size_t)scr_str_utf16_len(v->v.str));
@@ -4863,9 +5031,16 @@ static void scr_dyn_object_key_set(ScrDyn *recv, ScrStr *key, ScrDyn *value, con
4863
5031
  }
4864
5032
  }
4865
5033
  if (!scr_dyn_entry(recv, key)) {
4866
- for (const ScrDyn *current = recv->prototype; current && current->kind == SCR_DYN_OBJ; current = current->prototype) {
4867
- ScrDynEntry *inherited = scr_dyn_entry((ScrDyn *)current, key);
4868
- if (!inherited) continue;
5034
+ for (const ScrDyn *current = recv->prototype; current;) {
5035
+ ScrDyn *table = current->kind == SCR_DYN_FUNC ? scr_dyn_fn_properties(current) : NULL;
5036
+ const ScrDyn *object = table ? table : current;
5037
+ if (object->kind != SCR_DYN_OBJ) { scr_dyn_release(table); break; }
5038
+ ScrDynEntry *inherited = scr_dyn_entry((ScrDyn *)object, key);
5039
+ if (!inherited) {
5040
+ current = object->prototype;
5041
+ scr_dyn_release(table);
5042
+ continue;
5043
+ }
4869
5044
  if (inherited->accessor && inherited->setter) {
4870
5045
  ScrDyn *args[] = {value};
4871
5046
  ScrDyn *setter = scr_dyn_retain(inherited->setter);
@@ -4874,13 +5049,16 @@ static void scr_dyn_object_key_set(ScrDyn *recv, ScrStr *key, ScrDyn *value, con
4874
5049
  scr_dyn_this_pop();
4875
5050
  scr_dyn_release(setter);
4876
5051
  scr_dyn_release(result);
5052
+ scr_dyn_release(table);
4877
5053
  return;
4878
5054
  }
4879
5055
  if (inherited->accessor || !inherited->writable) {
4880
5056
  static const char message[] = "Cannot assign to read only property";
4881
5057
  scr_throw_error_msg(SCR_ERR_TYPE, message, sizeof message - 1);
5058
+ scr_dyn_release(table);
4882
5059
  return;
4883
5060
  }
5061
+ scr_dyn_release(table);
4884
5062
  break;
4885
5063
  }
4886
5064
  }
@@ -4934,22 +5112,20 @@ void scr_dyn_key_set(ScrDyn *recv, ScrStr *key, ScrDyn *value) {
4934
5112
  return;
4935
5113
  }
4936
5114
  size_t length = (size_t)number;
4937
- if (length > recv->v.arr.len && recv->non_extensible) {
4938
- static const char message[] = "Cannot add property, object is not extensible";
4939
- scr_throw_error_msg(SCR_ERR_TYPE, message, sizeof message - 1);
4940
- return;
4941
- }
4942
- if (length > recv->v.arr.len) {
4943
- static const char message[] = "Sparse array lengths are not supported yet";
5115
+ if (length > recv->v.arr.len + 1000000) {
5116
+ static const char message[] = "Checked array growth exceeds the native allocation limit";
4944
5117
  scr_throw_error_msg_code(SCR_ERR_ERROR, message, sizeof message - 1, "SC2020");
4945
5118
  return;
4946
5119
  }
4947
- if (length < recv->v.arr.len && recv->v.arr.sealed) {
4948
- static const char message[] = "Cannot delete non-configurable property";
4949
- scr_throw_error_msg(SCR_ERR_TYPE, message, sizeof message - 1);
4950
- return;
5120
+ while (recv->v.arr.len < length) scr_dyn_arr_push_hole(recv);
5121
+ while (recv->v.arr.len > length) {
5122
+ if (recv->v.arr.sealed && scr_dyn_arr_has_index(recv, recv->v.arr.len - 1)) {
5123
+ static const char message[] = "Cannot delete non-configurable property";
5124
+ scr_throw_error_msg(SCR_ERR_TYPE, message, sizeof message - 1);
5125
+ return;
5126
+ }
5127
+ scr_dyn_release(recv->v.arr.items[--recv->v.arr.len]);
4951
5128
  }
4952
- while (recv->v.arr.len > length) scr_dyn_release(recv->v.arr.items[--recv->v.arr.len]);
4953
5129
  return;
4954
5130
  }
4955
5131
  /* Canonical indexes extend the dense portion; other names live in the
@@ -4967,7 +5143,7 @@ void scr_dyn_key_set(ScrDyn *recv, ScrStr *key, ScrDyn *value) {
4967
5143
  scr_throw_error_msg(SCR_ERR_TYPE, message, sizeof message - 1);
4968
5144
  return;
4969
5145
  }
4970
- if (recv->non_extensible && idx >= recv->v.arr.len) {
5146
+ if (recv->non_extensible && !scr_dyn_arr_has_index(recv, idx)) {
4971
5147
  static const char message[] = "Cannot add property, object is not extensible";
4972
5148
  scr_throw_error_msg(SCR_ERR_TYPE, message, sizeof message - 1);
4973
5149
  return;
@@ -4978,10 +5154,11 @@ void scr_dyn_key_set(ScrDyn *recv, ScrStr *key, ScrDyn *value) {
4978
5154
  return;
4979
5155
  }
4980
5156
  while (recv->v.arr.len <= idx) {
4981
- scr_dyn_arr_push(recv, scr_dyn_retain(scr_dyn_undefined()));
5157
+ scr_dyn_arr_push_hole(recv);
4982
5158
  }
4983
5159
  ScrDyn *old = recv->v.arr.items[idx];
4984
5160
  recv->v.arr.items[idx] = scr_dyn_retain(value);
5161
+ if (recv->v.arr.presence) recv->v.arr.presence[idx] = 1;
4985
5162
  scr_dyn_release(old);
4986
5163
  return;
4987
5164
  }
@@ -5850,6 +6027,27 @@ void scr_dyn_key_delete(ScrDyn *recv, const ScrStr *key, bool strict) {
5850
6027
  scr_error_sync_cause(recv, key);
5851
6028
  return;
5852
6029
  }
6030
+ if (recv->kind == SCR_DYN_ARR && scr_dyn_canonical_own_index(key, recv->v.arr.len)) {
6031
+ size_t index = 0;
6032
+ for (size_t i = 0; i < key->len; i++) index = index * 10 + (size_t)(key->data[i] - '0');
6033
+ if (!scr_dyn_arr_has_index(recv, index)) return;
6034
+ if (recv->v.arr.sealed) {
6035
+ if (strict) {
6036
+ static const char message[] = "Cannot delete non-configurable property";
6037
+ scr_throw_error_msg(SCR_ERR_TYPE, message, sizeof message - 1);
6038
+ }
6039
+ return;
6040
+ }
6041
+ if (!recv->v.arr.presence) {
6042
+ recv->v.arr.presence = malloc(recv->v.arr.cap);
6043
+ if (!recv->v.arr.presence) scr_json_oom();
6044
+ memset(recv->v.arr.presence, 1, recv->v.arr.len);
6045
+ }
6046
+ recv->v.arr.presence[index] = 0;
6047
+ scr_dyn_release(recv->v.arr.items[index]);
6048
+ recv->v.arr.items[index] = scr_dyn_retain(scr_dyn_undefined());
6049
+ return;
6050
+ }
5853
6051
  if (recv->kind == SCR_DYN_ARR && recv->v.arr.properties &&
5854
6052
  scr_dyn_obj_get(recv->v.arr.properties, key->data, key->len)) {
5855
6053
  scr_dyn_key_delete(recv->v.arr.properties, key, strict);
@@ -5953,7 +6151,7 @@ static ScrDyn *scr_json_replace(const ScrDyn *holder, const ScrStr *key, const S
5953
6151
  ScrDyn *view = value->kind == SCR_DYN_TYPED_REF ? scr_dyn_typed_ref_materialize(value) : NULL;
5954
6152
  const ScrDyn *inspected = view ? view : value;
5955
6153
  if (scr_exc_pending()) { scr_dyn_release(view); scr_dyn_release(value); return NULL; }
5956
- if (inspected->kind == SCR_DYN_HANDLE && inspected->v.handle.tag == SCR_DYNH_DATE) {
6154
+ if (inspected->kind == SCR_DYN_HANDLE && (inspected->v.handle.tag == SCR_DYNH_DATE || inspected->v.handle.tag == SCR_DYNH_URL)) {
5957
6155
  const ScrDynHandleOps *ops = scr_dyn_handle_ops_of(inspected);
5958
6156
  ScrDyn *converted = ops->invoke(inspected->v.handle.ptr, value, "toJSON", NULL, 0, "toJSON");
5959
6157
  scr_dyn_release(value);
@@ -6156,6 +6354,36 @@ bool scr_dyn_strict_eq(const ScrDyn *a, const ScrDyn *b) {
6156
6354
  }
6157
6355
  }
6158
6356
 
6357
+ bool scr_dyn_abstract_eq(const ScrDyn *a, const ScrDyn *b) {
6358
+ if (a->kind == b->kind) return scr_dyn_strict_eq(a, b);
6359
+ bool an = a->kind == SCR_DYN_NULL || a->kind == SCR_DYN_UNDEF;
6360
+ bool bn = b->kind == SCR_DYN_NULL || b->kind == SCR_DYN_UNDEF;
6361
+ if (an || bn) return an && bn;
6362
+ if (a->kind == SCR_DYN_BOOL || b->kind == SCR_DYN_BOOL) {
6363
+ ScrDyn *numeric = scr_dyn_new_num(a->kind == SCR_DYN_BOOL ? (a->v.b ? 1 : 0) : (b->v.b ? 1 : 0));
6364
+ bool equal = a->kind == SCR_DYN_BOOL ? scr_dyn_abstract_eq(numeric, b) : scr_dyn_abstract_eq(a, numeric);
6365
+ scr_dyn_release(numeric);
6366
+ return equal;
6367
+ }
6368
+ if (scr_dyn_to_primitive_result_is_object(a) || scr_dyn_to_primitive_result_is_object(b)) {
6369
+ if (scr_dyn_to_primitive_result_is_object(a) && scr_dyn_to_primitive_result_is_object(b)) return scr_dyn_strict_eq(a, b);
6370
+ const ScrDyn *object = scr_dyn_to_primitive_result_is_object(a) ? a : b;
6371
+ ScrDyn *primitive = scr_dyn_add_primitive(object);
6372
+ bool equal = primitive && (object == a ? scr_dyn_abstract_eq(primitive, b) : scr_dyn_abstract_eq(a, primitive));
6373
+ scr_dyn_release(primitive);
6374
+ return equal;
6375
+ }
6376
+ if (a->kind == SCR_DYN_SYMBOL || b->kind == SCR_DYN_SYMBOL) return false;
6377
+ if (a->kind == SCR_DYN_BIGINT || b->kind == SCR_DYN_BIGINT) {
6378
+ const ScrDyn *integer = a->kind == SCR_DYN_BIGINT ? a : b;
6379
+ const ScrDyn *other = integer == a ? b : a;
6380
+ return other->kind == SCR_DYN_STR ? scr_bigint_eq_string(integer->v.bigint, other->v.str)
6381
+ : other->kind == SCR_DYN_NUM && scr_bigint_cmp_number(integer->v.bigint, other->v.num) == 0;
6382
+ }
6383
+ double left, right;
6384
+ return scr_dyn_number_coerce_js(a, &left) && scr_dyn_number_coerce_js(b, &right) && left == right;
6385
+ }
6386
+
6159
6387
  static SCR_TL ScrDyn *scr_function_constructors[4];
6160
6388
  static SCR_TL bool scr_function_constructors_registered;
6161
6389
 
@@ -6234,7 +6462,7 @@ ScrDyn *scr_dyn_fn_get(const ScrDyn *d, const char *key, size_t key_len) {
6234
6462
  return scr_dyn_new_num((double)d->v.fn.arity);
6235
6463
  }
6236
6464
  if (key_len == 5 && memcmp(key, "apply", 5) == 0) return scr_dyn_function_apply();
6237
- if (d->v.fn.class_obj) {
6465
+ if (d->v.fn.class_obj && !d->v.fn.class_obj->static_data) {
6238
6466
  static const char message[] = "scriptc: class properties through unknown other than name and length are not supported";
6239
6467
  scr_throw_error_msg(SCR_ERR_TYPE, message, sizeof message - 1);
6240
6468
  }
@@ -6345,6 +6573,7 @@ static ScrDyn *scr_sc_clone(const ScrDyn *v, const ScrScParent *up) {
6345
6573
  if (v->kind == SCR_DYN_ARR) {
6346
6574
  ScrDyn *out = scr_dyn_new_arr();
6347
6575
  for (size_t i = 0; i < v->v.arr.len; i++) {
6576
+ if (!scr_dyn_arr_has_index(v, i)) { scr_dyn_arr_push_hole(out); continue; }
6348
6577
  ScrDyn *c = scr_sc_clone(v->v.arr.items[i], &self);
6349
6578
  if (c == NULL) { /* threw */
6350
6579
  scr_dyn_release(out);
@@ -6452,8 +6681,8 @@ static ScrDyn *scr_dyn_obj_read_receiver(const ScrDyn *d, const char *key, size_
6452
6681
  if (current->kind == SCR_DYN_ARR) {
6453
6682
  if (key_len == 6 && memcmp(key, "length", 6) == 0) return scr_dyn_new_num((double)current->v.arr.len);
6454
6683
  double index;
6455
- if (scr_dyn_key_is_index(key, key_len, &index) && index < (double)current->v.arr.len)
6456
- return scr_dyn_arr_at(current, index);
6684
+ if (scr_dyn_key_is_index(key, key_len, &index) && scr_dyn_arr_has_index(current, (size_t)index))
6685
+ return scr_dyn_retain(current->v.arr.items[(size_t)index]);
6457
6686
  if (current->v.arr.properties && scr_dyn_obj_get(current->v.arr.properties, key, key_len))
6458
6687
  return scr_dyn_obj_read_receiver(current->v.arr.properties, key, key_len, receiver);
6459
6688
  continue;
@@ -6571,6 +6800,155 @@ ScrDyn *scr_dyn_obj_read(const ScrDyn *d, const char *key, size_t key_len) {
6571
6800
  return scr_dyn_obj_read_receiver(d, key, key_len, d);
6572
6801
  }
6573
6802
 
6803
+ /* Compiler-owned class property tables use their native instance as the
6804
+ * receiver of inherited accessors, retaining field updates on that instance. */
6805
+ ScrDyn *scr_dyn_bag_get(ScrDyn *bag, ScrStr *key, ScrDyn *receiver) {
6806
+ return scr_dyn_obj_read_receiver(bag, key->data, key->len, receiver);
6807
+ }
6808
+
6809
+ void scr_dyn_bag_set(ScrDyn *bag, ScrStr *key, ScrDyn *value, ScrDyn *receiver) {
6810
+ scr_dyn_object_key_set(bag, key, value, receiver);
6811
+ }
6812
+
6813
+ /* Reflect uses OrdinaryGet/OrdinarySet with an independently supplied
6814
+ * receiver. Failed descriptor writes return false; user callbacks still
6815
+ * propagate their exceptions. Keys are converted once before dispatch. */
6816
+ ScrDyn *scr_dyn_reflect_get(ScrDyn *target, ScrDyn *raw_key, ScrDyn *receiver) {
6817
+ if (!scr_dyn_to_primitive_result_is_object(target)) {
6818
+ static const char message[] = "Reflect.get called on non-object";
6819
+ scr_throw_error_msg(SCR_ERR_TYPE, message, sizeof message - 1);
6820
+ return NULL;
6821
+ }
6822
+ ScrDyn *key = scr_dyn_property_key_value(raw_key);
6823
+ if (!key) return NULL;
6824
+ ScrDyn *result = NULL;
6825
+ if (target->kind == SCR_DYN_TYPED_REF) {
6826
+ ScrDyn *view = scr_dyn_typed_ref_materialize(target);
6827
+ if (!scr_exc_pending()) result = scr_dyn_reflect_get(view, key, receiver);
6828
+ scr_dyn_release(view);
6829
+ } else if (key->kind == SCR_DYN_SYMBOL) {
6830
+ ScrDyn *symbols = scr_dyn_symbol_receiver(target);
6831
+ ScrDynEntry *entry = symbols ? scr_dyn_symbol_entry(symbols, key, false) : NULL;
6832
+ if (entry && entry->accessor && entry->getter) {
6833
+ ScrDyn *getter = scr_dyn_retain(entry->getter);
6834
+ scr_dyn_this_push_dyn(receiver);
6835
+ result = scr_dyn_call(getter, NULL, 0, "getter");
6836
+ scr_dyn_this_pop();
6837
+ scr_dyn_release(getter);
6838
+ } else result = scr_dyn_symbol_key_get(target, key, false);
6839
+ scr_dyn_release(symbols);
6840
+ } else if (target->kind == SCR_DYN_PROXY) result = scr_dyn_proxy_get_receiver(target, key->v.str, receiver);
6841
+ else result = scr_dyn_obj_read_receiver(target, key->v.str->data, key->v.str->len, receiver);
6842
+ scr_dyn_release(key);
6843
+ return result;
6844
+ }
6845
+
6846
+ bool scr_dyn_reflect_define(ScrDyn *receiver, ScrDyn *raw_key, ScrDyn *value) {
6847
+ if (!scr_dyn_to_primitive_result_is_object(receiver)) return false;
6848
+ ScrDyn *key = scr_dyn_property_key_value(raw_key);
6849
+ if (!key) return false;
6850
+ bool ok = false;
6851
+ if (receiver->kind == SCR_DYN_TYPED_REF) {
6852
+ ScrDyn *view = scr_dyn_typed_ref_materialize(receiver);
6853
+ if (!scr_exc_pending()) ok = scr_dyn_reflect_define(view, key, value);
6854
+ if (ok) scr_dyn_typed_ref_commit(receiver);
6855
+ scr_dyn_release(view);
6856
+ } else if (receiver->kind == SCR_DYN_PROXY) {
6857
+ scr_dyn_proxy_unsupported("Reflect.set receiver definition");
6858
+ } else if (receiver->kind == SCR_DYN_FUNC) {
6859
+ ScrDyn *table = scr_dyn_fn_properties(receiver);
6860
+ ok = scr_dyn_reflect_define(table, key, value);
6861
+ scr_dyn_release(table);
6862
+ } else {
6863
+ ScrDyn *symbols = key->kind == SCR_DYN_SYMBOL ? scr_dyn_symbol_receiver(receiver) : NULL;
6864
+ ScrDynEntry *entry = key->kind == SCR_DYN_SYMBOL ? (symbols ? scr_dyn_symbol_entry(symbols, key, true) : NULL)
6865
+ : receiver->kind == SCR_DYN_OBJ ? scr_dyn_entry(receiver, key->v.str)
6866
+ : receiver->kind == SCR_DYN_ARR && receiver->v.arr.properties ? scr_dyn_entry(receiver->v.arr.properties, key->v.str) : NULL;
6867
+ if (!(entry && (entry->accessor || !entry->writable)) && !(receiver->non_extensible && !scr_dyn_has_own_computed(receiver, key))) {
6868
+ if (entry) {
6869
+ ScrDyn *old = entry->value;
6870
+ entry->value = scr_dyn_retain(value);
6871
+ scr_dyn_release(old);
6872
+ ok = true;
6873
+ } else if (key->kind == SCR_DYN_SYMBOL && symbols) {
6874
+ ScrDyn *descriptor = scr_dyn_new_obj();
6875
+ scr_dyn_obj_set(descriptor, "value", 5, scr_dyn_retain(value));
6876
+ scr_dyn_obj_set(descriptor, "writable", 8, scr_dyn_new_bool(true));
6877
+ scr_dyn_obj_set(descriptor, "enumerable", 10, scr_dyn_new_bool(true));
6878
+ scr_dyn_obj_set(descriptor, "configurable", 12, scr_dyn_new_bool(true));
6879
+ ScrDyn *defined = scr_dyn_define_symbol(receiver, key, descriptor);
6880
+ scr_dyn_release(defined);
6881
+ scr_dyn_release(descriptor);
6882
+ ok = !scr_exc_pending();
6883
+ } else if (receiver->kind == SCR_DYN_OBJ) {
6884
+ scr_dyn_obj_set(receiver, key->v.str->data, key->v.str->len, scr_dyn_retain(value));
6885
+ ok = true;
6886
+ } else if (receiver->kind == SCR_DYN_ARR) {
6887
+ if (!receiver->v.arr.frozen) {
6888
+ scr_dyn_key_set(receiver, key->v.str, value);
6889
+ ok = !scr_exc_pending();
6890
+ }
6891
+ }
6892
+ }
6893
+ scr_dyn_release(symbols);
6894
+ }
6895
+ scr_dyn_release(key);
6896
+ return ok && !scr_exc_pending();
6897
+ }
6898
+
6899
+ bool scr_dyn_reflect_set(ScrDyn *target, ScrDyn *raw_key, ScrDyn *value, ScrDyn *receiver) {
6900
+ if (!scr_dyn_to_primitive_result_is_object(target)) {
6901
+ static const char message[] = "Reflect.set called on non-object";
6902
+ scr_throw_error_msg(SCR_ERR_TYPE, message, sizeof message - 1);
6903
+ return false;
6904
+ }
6905
+ ScrDyn *key = scr_dyn_property_key_value(raw_key);
6906
+ if (!key) return false;
6907
+ bool ok = false;
6908
+ if (target->kind == SCR_DYN_TYPED_REF) {
6909
+ ScrDyn *view = scr_dyn_typed_ref_materialize(target);
6910
+ if (!scr_exc_pending()) ok = scr_dyn_reflect_set(view, key, value, receiver);
6911
+ scr_dyn_release(view);
6912
+ } else if (target->kind == SCR_DYN_PROXY) {
6913
+ ScrDyn *trap = scr_dyn_proxy_trap(target, "set");
6914
+ if (!scr_exc_pending() && !trap) ok = scr_dyn_reflect_set(target->v.proxy.target, key, value, receiver);
6915
+ else if (trap) {
6916
+ ScrDyn *args[] = {target->v.proxy.target, key, value, receiver};
6917
+ ScrDyn *result = scr_dyn_proxy_call(target, trap, args, 4);
6918
+ ok = result && scr_dyn_truthy(result);
6919
+ scr_dyn_release(result);
6920
+ ScrDynEntry *entry = key->kind == SCR_DYN_STR ? scr_dyn_entry(target->v.proxy.target, key->v.str) : NULL;
6921
+ if (ok && entry && !entry->configurable && ((entry->accessor && !entry->setter) || (!entry->accessor && !entry->writable && !scr_dyn_property_same_value(entry->value, value)))) scr_dyn_proxy_invariant();
6922
+ }
6923
+ } else if (target->kind == SCR_DYN_FUNC) {
6924
+ ScrDyn *table = scr_dyn_fn_properties(target);
6925
+ ok = scr_dyn_reflect_set(table, key, value, receiver);
6926
+ scr_dyn_release(table);
6927
+ } else {
6928
+ ScrDyn *symbols = key->kind == SCR_DYN_SYMBOL ? scr_dyn_symbol_receiver(target) : NULL;
6929
+ ScrDynEntry *entry = symbols ? scr_dyn_symbol_entry(symbols, key, false) : NULL;
6930
+ if (key->kind == SCR_DYN_STR) for (ScrDyn *current = target; current; current = current->prototype) {
6931
+ if (current->kind == SCR_DYN_OBJ) entry = scr_dyn_entry(current, key->v.str);
6932
+ else if (current->kind == SCR_DYN_ARR && current->v.arr.properties) entry = scr_dyn_entry(current->v.arr.properties, key->v.str);
6933
+ if (entry) break;
6934
+ }
6935
+ if (entry && entry->accessor) {
6936
+ if (entry->setter) {
6937
+ ScrDyn *setter = scr_dyn_retain(entry->setter);
6938
+ scr_dyn_this_push_dyn(receiver);
6939
+ ScrDyn *result = scr_dyn_call(setter, &value, 1, "setter");
6940
+ scr_dyn_this_pop();
6941
+ scr_dyn_release(result);
6942
+ scr_dyn_release(setter);
6943
+ ok = !scr_exc_pending();
6944
+ }
6945
+ } else if (!entry || entry->writable) ok = scr_dyn_reflect_define(receiver, key, value);
6946
+ scr_dyn_release(symbols);
6947
+ }
6948
+ scr_dyn_release(key);
6949
+ return ok && !scr_exc_pending();
6950
+ }
6951
+
6574
6952
  /* ── Object.keys/values/entries over the checked-dynamic tree ──────────────────────────
6575
6953
  * JS own-key order: array-index keys ascending first, then the rest in
6576
6954
  * insertion order. entries answers [key, value] pairs; values RETAIN
@@ -6659,6 +7037,7 @@ ScrDyn *scr_dyn_get_own_property_names(const ScrDyn *value) {
6659
7037
  value->kind == SCR_DYN_BYTES ? value->v.bytes->len :
6660
7038
  (size_t)scr_str_utf16_len(value->v.str);
6661
7039
  for (size_t i = 0; i < length; i++) {
7040
+ if (value->kind == SCR_DYN_ARR && !scr_dyn_arr_has_index(value, i)) continue;
6662
7041
  char name[24];
6663
7042
  int size = snprintf(name, sizeof name, "%zu", i);
6664
7043
  scr_dyn_arr_push(keys, scr_dyn_objwalk_key(name, (size_t)size));
@@ -6916,6 +7295,7 @@ static ScrDyn *scr_dyn_objwalk(const ScrDyn *v, ScrObjWalk mode) {
6916
7295
  if (v->kind == SCR_DYN_ARR || v->kind == SCR_DYN_BYTES) {
6917
7296
  size_t n = v->kind == SCR_DYN_ARR ? v->v.arr.len : v->v.bytes->len;
6918
7297
  for (size_t i = 0; i < n; i++) {
7298
+ if (v->kind == SCR_DYN_ARR && !scr_dyn_arr_has_index(v, i)) continue;
6919
7299
  char key[24];
6920
7300
  int klen = snprintf(key, sizeof key, "%zu", i);
6921
7301
  ScrDyn *val = NULL;
@@ -6981,7 +7361,8 @@ ScrDyn *scr_dyn_obj_keys(const ScrDyn *v) { return scr_dyn_objwalk(v, SCR_OBJWAL
6981
7361
  * Non-enumerable own names shadow names farther up the chain. */
6982
7362
  ScrDyn *scr_dyn_for_in_keys(const ScrDyn *v) {
6983
7363
  if (scr_dyn_class_reflection_fence(v)) return NULL;
6984
- if (v->kind == SCR_DYN_TYPED_REF && scr_dyn_isl_is_array(v)) {
7364
+ if (v->kind == SCR_DYN_TYPED_REF && (scr_dyn_isl_is_array(v) ||
7365
+ !strncmp(v->v.typed_ref.type_key, "record:", 7))) {
6985
7366
  ScrDyn *view = scr_dyn_typed_ref_materialize(v);
6986
7367
  ScrDyn *keys = scr_exc_pending() ? NULL : scr_dyn_for_in_keys(view);
6987
7368
  scr_dyn_release(view);
@@ -7238,6 +7619,19 @@ ScrDyn *scr_dyn_copy_property_descriptors(ScrDyn *target, const ScrDyn *src) {
7238
7619
  if (scr_exc_pending()) break;
7239
7620
  }
7240
7621
  scr_dyn_release(keys);
7622
+ if (!scr_exc_pending()) {
7623
+ ScrDyn *symbols = scr_dyn_get_own_property_symbols(src);
7624
+ if (!symbols) return NULL;
7625
+ for (size_t i = 0; i < symbols->v.arr.len; i++) {
7626
+ ScrDyn *key = symbols->v.arr.items[i];
7627
+ ScrDyn *descriptor = scr_dyn_get_own_property_descriptor((ScrDyn *)src, key);
7628
+ ScrDyn *result = descriptor ? scr_dyn_define_property(target, key, descriptor) : NULL;
7629
+ scr_dyn_release(descriptor);
7630
+ scr_dyn_release(result);
7631
+ if (scr_exc_pending()) break;
7632
+ }
7633
+ scr_dyn_release(symbols);
7634
+ }
7241
7635
  return scr_exc_pending() ? NULL : scr_dyn_retain(target);
7242
7636
  }
7243
7637
 
@@ -7427,7 +7821,10 @@ bool scr_dyn_has_own(const ScrDyn *v, const ScrStr *key) {
7427
7821
  if (v->kind == SCR_DYN_ARR) {
7428
7822
  if (key->len == 6 && memcmp(key->data, "length", 6) == 0) return true;
7429
7823
  if (v->v.arr.properties && scr_dyn_obj_get(v->v.arr.properties, key->data, key->len)) return true;
7430
- return scr_dyn_canonical_own_index(key, v->v.arr.len);
7824
+ if (!scr_dyn_canonical_own_index(key, v->v.arr.len)) return false;
7825
+ size_t index = 0;
7826
+ for (size_t i = 0; i < key->len; i++) index = index * 10 + (size_t)(key->data[i] - '0');
7827
+ return scr_dyn_arr_has_index(v, index);
7431
7828
  }
7432
7829
  if (v->kind == SCR_DYN_STR) {
7433
7830
  if (key->len == 6 && memcmp(key->data, "length", 6) == 0) return true;
@@ -7468,7 +7865,7 @@ bool scr_dyn_property_is_enumerable(const ScrDyn *value, const ScrStr *key) {
7468
7865
  if (value->kind == SCR_DYN_STR)
7469
7866
  return scr_dyn_canonical_own_index(key, (size_t)scr_str_utf16_len(value->v.str));
7470
7867
  if (value->kind == SCR_DYN_ARR)
7471
- return scr_dyn_canonical_own_index(key, value->v.arr.len) ||
7868
+ return (scr_dyn_canonical_own_index(key, value->v.arr.len) && scr_dyn_has_own(value, key)) ||
7472
7869
  (value->v.arr.properties && scr_dyn_obj_enumerable(value->v.arr.properties, key->data, key->len));
7473
7870
  if (value->kind == SCR_DYN_BYTES)
7474
7871
  return scr_dyn_canonical_own_index(key, value->v.bytes->len);