@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.
- package/dist/THIRD_PARTY_NOTICES +1 -1
- package/dist/bin/scriptc +0 -0
- package/dist/bin/scriptc.json +1 -1
- package/dist/lib/declarations/scriptc-node-fallback.d.ts +59 -4
- package/dist/lib/llvm/bin/scriptc-llvm-codegen +0 -0
- package/dist/lib/llvm/package.json +1 -1
- package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/default/scr_async.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/default/scr_async_dyn.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/default/scr_bytes.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/default/scr_bytes_io.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/default/scr_crypto_async.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/default/scr_dyn_invoke.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/default/scr_file_handle.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/default/scr_json.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/default/scr_lib.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/default/scr_qs.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/default/scr_regex.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/default/scr_url.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/dynamic/scr_async.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/dynamic/scr_async_dyn.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/dynamic/scr_bytes.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/dynamic/scr_bytes_io.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/dynamic/scr_crypto_async.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/dynamic/scr_dyn_invoke.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/dynamic/scr_file_handle.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/dynamic/scr_island.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/dynamic/scr_json.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/dynamic/scr_lib.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/dynamic/scr_qs.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/dynamic/scr_regex.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/dynamic/scr_url.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/dynamic/scr_web.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/dynamic-text-decoder-legacy/scr_bytes.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/text-decoder-legacy/scr_bytes.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/library-dev/runtime/default/scr_bytes.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/library-dev/runtime/default/scr_bytes_io.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/library-dev/runtime/default/scr_dyn_invoke.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/library-dev/runtime/default/scr_json.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/library-dev/runtime/default/scr_lib.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/library-dev/runtime/default/scr_regex.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/library-dev/runtime/default/scr_url.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/library-dev/runtime/text-decoder-legacy/scr_bytes.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/library-release/runtime/default/scr_bytes.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/library-release/runtime/default/scr_bytes_io.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/library-release/runtime/default/scr_dyn_invoke.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/library-release/runtime/default/scr_json.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/library-release/runtime/default/scr_lib.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/library-release/runtime/default/scr_regex.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/library-release/runtime/default/scr_url.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/library-release/runtime/text-decoder-legacy/scr_bytes.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/library-thread-dev/runtime/default/scr_bytes.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/library-thread-dev/runtime/default/scr_bytes_io.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/library-thread-dev/runtime/default/scr_dyn_invoke.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/library-thread-dev/runtime/default/scr_json.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/library-thread-dev/runtime/default/scr_lib.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/library-thread-dev/runtime/default/scr_regex.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/library-thread-dev/runtime/default/scr_url.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/library-thread-dev/runtime/text-decoder-legacy/scr_bytes.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/library-thread-release/runtime/default/scr_bytes.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/library-thread-release/runtime/default/scr_bytes_io.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/library-thread-release/runtime/default/scr_dyn_invoke.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/library-thread-release/runtime/default/scr_json.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/library-thread-release/runtime/default/scr_lib.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/library-thread-release/runtime/default/scr_regex.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/library-thread-release/runtime/default/scr_url.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/library-thread-release/runtime/text-decoder-legacy/scr_bytes.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/default/scr_async.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/default/scr_async_dyn.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/default/scr_bytes.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/default/scr_bytes_io.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/default/scr_crypto_async.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/default/scr_dyn_invoke.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/default/scr_file_handle.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/default/scr_json.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/default/scr_lib.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/default/scr_qs.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/default/scr_regex.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/default/scr_url.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/dynamic/scr_async.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/dynamic/scr_async_dyn.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/dynamic/scr_bytes.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/dynamic/scr_bytes_io.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/dynamic/scr_crypto_async.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/dynamic/scr_dyn_invoke.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/dynamic/scr_file_handle.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/dynamic/scr_island.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/dynamic/scr_json.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/dynamic/scr_lib.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/dynamic/scr_qs.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/dynamic/scr_regex.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/dynamic/scr_url.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/dynamic/scr_web.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/dynamic-text-decoder-legacy/scr_bytes.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/text-decoder-legacy/scr_bytes.o +0 -0
- package/dist/lib/runtime-darwin-x64/package.json +1 -1
- package/dist/lib/runtime-darwin-x64/runtime-pack.json +177 -177
- package/dist/lib/runtime-sources/package.json +1 -1
- package/dist/lib/runtime-sources/src/scr_abort.c +5 -0
- package/dist/lib/runtime-sources/src/scr_async.c +12 -4
- package/dist/lib/runtime-sources/src/scr_async_dyn.c +118 -24
- package/dist/lib/runtime-sources/src/scr_bytes.c +226 -0
- package/dist/lib/runtime-sources/src/scr_bytes_io.c +52 -5
- package/dist/lib/runtime-sources/src/scr_crypto_async.c +22 -2
- package/dist/lib/runtime-sources/src/scr_dyn_invoke.c +181 -43
- package/dist/lib/runtime-sources/src/scr_fetch.c +45 -1
- package/dist/lib/runtime-sources/src/scr_file_handle.c +31 -0
- package/dist/lib/runtime-sources/src/scr_island.c +1188 -392
- package/dist/lib/runtime-sources/src/scr_island_manifest.h +11 -9
- package/dist/lib/runtime-sources/src/scr_json.c +449 -52
- package/dist/lib/runtime-sources/src/scr_json.test.ts +1 -0
- package/dist/lib/runtime-sources/src/scr_lib.c +816 -34
- package/dist/lib/runtime-sources/src/scr_qs.c +10 -0
- package/dist/lib/runtime-sources/src/scr_regex.c +42 -5
- package/dist/lib/runtime-sources/src/scr_runtime.h +67 -8
- package/dist/lib/runtime-sources/src/scr_text_decoder_labels.h +12 -12
- package/dist/lib/runtime-sources/src/scr_url.c +34 -7
- package/dist/lib/runtime-sources/src/scr_web.c +129 -26
- 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
|
-
|
|
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
|
|
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 *
|
|
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,
|
|
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
|
|
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 *)
|
|
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
|
-
|
|
2256
|
-
|
|
2257
|
-
|
|
2258
|
-
|
|
2259
|
-
|
|
2260
|
-
|
|
2261
|
-
|
|
2262
|
-
|
|
2263
|
-
|
|
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
|
-
|
|
2375
|
+
scr_jb_putc(&shown, '\'');
|
|
2376
|
+
scr_jb_put_str(&shown, value);
|
|
2377
|
+
scr_jb_putc(&shown, '\'');
|
|
2266
2378
|
}
|
|
2267
|
-
|
|
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[
|
|
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[
|
|
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
|
-
|
|
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 *
|
|
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:
|
|
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
|
|
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
|
|
4867
|
-
|
|
4868
|
-
|
|
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
|
|
4938
|
-
static const char message[] = "
|
|
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
|
-
|
|
4948
|
-
|
|
4949
|
-
|
|
4950
|
-
|
|
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
|
|
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
|
-
|
|
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) &&
|
|
6456
|
-
return
|
|
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
|
-
|
|
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);
|