MIRROR: javascript for ๐Ÿœ's, a tiny runtime with big ambitions
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

migrate to collections module, use eval for ctor props

+1103 -943
+1
include/common.h
··· 54 54 SLOT_MODULE_SCOPE, 55 55 SLOT_STRICT_ARGS, 56 56 SLOT_NO_FUNC_DECLS, 57 + SLOT_ITER_STATE, 57 58 SLOT_MAX = 255 58 59 } internal_slot_t; 59 60
+5 -1
include/internal.h
··· 102 102 #define T_NON_NUMERIC_MASK (TYPE_FLAG(T_STR) | TYPE_FLAG(T_ARR) | TYPE_FLAG(T_FUNC) | TYPE_FLAG(T_CFUNC) | TYPE_FLAG(T_OBJ)) 103 103 104 104 bool is_internal_prop(const char *key, jsoff_t klen); 105 + size_t uint_to_str(char *buf, size_t bufsize, uint64_t val); 105 106 106 107 void js_gc_reserve_roots(GC_UPDATE_ARGS); 107 108 void js_gc_update_roots(GC_UPDATE_ARGS); ··· 110 111 jsval_t tov(double d); 111 112 double tod(jsval_t v); 112 113 114 + jsval_t resolveprop(struct js *js, jsval_t v); 115 + jsval_t setprop(struct js *js, jsval_t obj, jsval_t k, jsval_t v); 116 + 113 117 jsoff_t lkp(struct js *js, jsval_t obj, const char *buf, size_t len); 114 118 jsoff_t lkp_proto(struct js *js, jsval_t obj, const char *buf, size_t len); 115 119 jsoff_t vstr(struct js *js, jsval_t value, jsoff_t *len); 116 120 121 + jsval_t mkarr(struct js *js); 117 122 jsval_t mkval(uint8_t type, uint64_t data); 118 - jsval_t resolveprop(struct js *js, jsval_t v); 119 123 120 124 jsval_t call_js(ant_t *js, const char *fn, jsoff_t fnlen, jsval_t closure_scope); 121 125 jsval_t call_js_internal(ant_t *js, const char *fn, jsoff_t fnlen, jsval_t closure_scope, jsval_t *bound_args, int bound_argc, jsval_t func_val);
+57
include/modules/collections.h
··· 1 + #ifndef COLLECTIONS_H 2 + #define COLLECTIONS_H 3 + 4 + #include <uthash.h> 5 + #include "types.h" 6 + 7 + typedef struct map_entry { 8 + char *key; 9 + jsval_t value; 10 + UT_hash_handle hh; 11 + } map_entry_t; 12 + 13 + typedef struct set_entry { 14 + jsval_t value; 15 + char *key; 16 + UT_hash_handle hh; 17 + } set_entry_t; 18 + 19 + typedef struct weakmap_entry { 20 + jsval_t key_obj; 21 + jsval_t value; 22 + UT_hash_handle hh; 23 + } weakmap_entry_t; 24 + 25 + typedef struct weakset_entry { 26 + jsval_t value_obj; 27 + UT_hash_handle hh; 28 + } weakset_entry_t; 29 + 30 + typedef enum { 31 + ITER_TYPE_MAP_VALUES, 32 + ITER_TYPE_MAP_KEYS, 33 + ITER_TYPE_MAP_ENTRIES, 34 + ITER_TYPE_SET_VALUES, 35 + ITER_TYPE_SET_ENTRIES 36 + } iter_type_t; 37 + 38 + typedef struct map_iterator_state { 39 + map_entry_t **head; 40 + map_entry_t *current; 41 + iter_type_t type; 42 + } map_iterator_state_t; 43 + 44 + typedef struct set_iterator_state { 45 + set_entry_t **head; 46 + set_entry_t *current; 47 + iter_type_t type; 48 + } set_iterator_state_t; 49 + 50 + void init_collections_module(void); 51 + void cleanup_collections_module(void); 52 + void collections_gc_update_roots(void (*op_val)(void *, jsval_t *), void *ctx); 53 + 54 + map_entry_t **get_map_from_obj(ant_t *js, jsval_t obj); 55 + set_entry_t **get_set_from_obj(ant_t *js, jsval_t obj); 56 + 57 + #endif
+17 -934
src/ant.c
··· 50 50 #include "modules/process.h" 51 51 #include "modules/json.h" 52 52 #include "modules/buffer.h" 53 + #include "modules/collections.h" 53 54 #include "esm/remote.h" 54 55 55 56 #define D(x) ((double)(x)) ··· 206 207 static uint32_t get_promise_id(struct js *js, jsval_t p); 207 208 static bool js_try_grow_memory(struct js *js, size_t needed); 208 209 209 - typedef struct map_entry { 210 - char *key; 211 - jsval_t value; 212 - UT_hash_handle hh; 213 - } map_entry_t; 214 - 215 - typedef struct set_entry { 216 - jsval_t value; 217 - char *key; 218 - UT_hash_handle hh; 219 - } set_entry_t; 220 - 221 210 typedef struct proxy_data { 222 211 jsoff_t obj_offset; 223 212 jsval_t target; ··· 293 282 static proxy_data_t *proxy_registry = NULL; 294 283 static dynamic_accessors_t *accessor_registry = NULL; 295 284 static descriptor_entry_t *desc_registry = NULL; 296 - 297 - typedef struct map_registry_entry { 298 - map_entry_t **head; 299 - UT_hash_handle hh; 300 - } map_registry_entry_t; 301 - 302 - typedef struct set_registry_entry { 303 - set_entry_t **head; 304 - UT_hash_handle hh; 305 - } set_registry_entry_t; 306 - 307 - static map_registry_entry_t *map_registry = NULL; 308 - static set_registry_entry_t *set_registry = NULL; 309 285 310 286 void ant_register_library(ant_library_init_fn init_fn, const char *name, ...) { 311 287 va_list args; ··· 741 717 742 718 static jsval_t get_prototype_for_type(struct js *js, uint8_t type); 743 719 static jsval_t get_ctor_proto(struct js *js, const char *name, size_t len); 744 - 745 - static jsval_t setprop(struct js *js, jsval_t obj, jsval_t k, jsval_t v); 746 720 static jsoff_t lkp_interned(struct js *js, jsval_t obj, const char *search_intern, size_t len); 747 721 748 722 static descriptor_entry_t *lookup_descriptor(jsoff_t obj_off, const char *key, size_t klen); ··· 810 784 return srclen; 811 785 } 812 786 813 - static inline size_t uint_to_str(char *buf, size_t bufsize, uint64_t val) { 787 + size_t uint_to_str(char *buf, size_t bufsize, uint64_t val) { 814 788 if (bufsize == 0) return 0; 815 789 if (val == 0) { 816 790 buf[0] = '0'; ··· 2530 2504 return mkentity(js, 0 | T_OBJ, buf, sizeof(buf)); 2531 2505 } 2532 2506 2533 - static jsval_t mkarr(struct js *js) { 2507 + jsval_t mkarr(struct js *js) { 2534 2508 jsval_t arr = mkobj(js, 0); 2535 2509 jsoff_t off = (jsoff_t) vdata(arr); 2536 2510 jsoff_t header = loadoff(js, off); ··· 3052 3026 return result; 3053 3027 } 3054 3028 3055 - static inline jsval_t setprop(struct js *js, jsval_t obj, jsval_t k, jsval_t v) { 3029 + jsval_t setprop(struct js *js, jsval_t obj, jsval_t k, jsval_t v) { 3056 3030 return js_setprop(js, obj, k, v); 3057 3031 } 3058 3032 ··· 10023 9997 uint8_t saved_flags = js->flags; 10024 9998 10025 9999 jsval_t iter_method = loadval(js, iter_prop + sizeof(jsoff_t) * 2); 10000 + jsval_t outer_saved_this = js->this_val; 10026 10001 push_this(iterable); 10002 + js->this_val = iterable; 10027 10003 jsval_t iterator = call_js_with_args(js, iter_method, NULL, 0); 10028 10004 pop_this(); 10005 + js->this_val = outer_saved_this; 10029 10006 JS_RESTORE_STATE(js, saved_state); 10030 10007 js->flags = saved_flags; 10031 10008 ··· 10046 10023 } 10047 10024 10048 10025 cur_iter = js_deref(js, h_iterator); 10026 + jsval_t saved_this = js->this_val; 10049 10027 push_this(cur_iter); 10028 + js->this_val = cur_iter; 10050 10029 jsval_t result = call_js_with_args(js, next_method, NULL, 0); 10051 10030 pop_this(); 10031 + js->this_val = saved_this; 10052 10032 JS_RESTORE_STATE(js, saved_state); 10053 10033 js->flags = saved_flags; 10054 10034 ··· 11328 11308 if (next(js) == TOK_ASSIGN) { 11329 11309 js->consumed = 1; 11330 11310 jsoff_t field_start = js->pos; 11331 - int depth = 0; 11332 - bool done = false; 11333 - while (!done && next(js) != TOK_EOF) { 11334 - uint8_t tok = next(js); 11335 - if (depth == 0 && (tok == TOK_SEMICOLON || tok == TOK_RBRACE || 11336 - (tok == TOK_IDENTIFIER && js->pos > field_start + 1))) { 11337 - if (tok != TOK_SEMICOLON && tok != TOK_RBRACE) { 11338 - js->consumed = 0; 11339 - } 11340 - done = true; 11341 - } else if (tok == TOK_LPAREN || tok == TOK_LBRACKET || tok == TOK_LBRACE) { 11342 - depth++; 11343 - js->consumed = 1; 11344 - } else if (tok == TOK_RPAREN || tok == TOK_RBRACKET || tok == TOK_RBRACE) { 11345 - if (depth == 0) { 11346 - done = true; 11347 - } else { 11348 - depth--; 11349 - js->consumed = 1; 11350 - } 11351 - } else { 11352 - js->consumed = 1; 11353 - } 11311 + jsval_t field_expr = js_expr(js); 11312 + if (is_err(field_expr)) { 11313 + js->flags = save_flags; 11314 + utarray_free(methods); 11315 + return field_expr; 11354 11316 } 11355 11317 jsoff_t field_end = js->pos; 11356 11318 if (next(js) == TOK_SEMICOLON) js->consumed = 1; ··· 20403 20365 return js_mkerr(js, "Invalid export statement"); 20404 20366 } 20405 20367 20406 - typedef struct weakmap_entry { 20407 - jsval_t key_obj; 20408 - jsval_t value; 20409 - UT_hash_handle hh; 20410 - } weakmap_entry_t; 20411 - 20412 - typedef struct weakset_entry { 20413 - jsval_t value_obj; 20414 - UT_hash_handle hh; 20415 - } weakset_entry_t; 20416 - 20417 - static const char* jsval_to_key(struct js *js, jsval_t val) { 20418 - if (vtype(val) == T_STR) { 20419 - jsoff_t len; 20420 - jsoff_t off = vstr(js, val, &len); 20421 - return (char *)&js->mem[off]; 20422 - } else return js_str(js, val); 20423 - } 20424 - 20425 - static jsval_t builtin_Map(struct js *js, jsval_t *args, int nargs) { 20426 - jsval_t map_obj = mkobj(js, 0); 20427 - 20428 - jsval_t map_proto = get_ctor_proto(js, "Map", 3); 20429 - if (vtype(map_proto) == T_OBJ) set_proto(js, map_obj, map_proto); 20430 - 20431 - map_entry_t **map_head = (map_entry_t **)ant_calloc(sizeof(map_entry_t *)); 20432 - if (!map_head) return js_mkerr(js, "out of memory"); 20433 - *map_head = NULL; 20434 - 20435 - map_registry_entry_t *reg = (map_registry_entry_t *)ant_calloc(sizeof(map_registry_entry_t)); 20436 - if (reg) { 20437 - reg->head = map_head; 20438 - HASH_ADD_PTR(map_registry, head, reg); 20439 - } 20440 - 20441 - jsval_t map_ptr = tov((double)(size_t)map_head); 20442 - set_slot(js, map_obj, SLOT_MAP, map_ptr); 20443 - 20444 - if (nargs == 0 || vtype(args[0]) != T_ARR) return map_obj; 20445 - 20446 - jsval_t iterable = args[0]; 20447 - jsoff_t length = js_arr_len(js, iterable); 20448 - 20449 - for (jsoff_t i = 0; i < length; i++) { 20450 - jsval_t entry = js_arr_get(js, iterable, i); 20451 - if (vtype(entry) != T_ARR) continue; 20452 - 20453 - jsoff_t entry_len = js_arr_len(js, entry); 20454 - if (entry_len < 2) continue; 20455 - 20456 - jsval_t key = js_arr_get(js, entry, 0); 20457 - jsval_t value = js_arr_get(js, entry, 1); 20458 - const char *key_str = jsval_to_key(js, key); 20459 - 20460 - map_entry_t *map_entry; 20461 - HASH_FIND_STR(*map_head, key_str, map_entry); 20462 - if (map_entry) { 20463 - map_entry->value = value; 20464 - continue; 20465 - } 20466 - 20467 - map_entry = (map_entry_t *)ant_calloc(sizeof(map_entry_t)); 20468 - if (!map_entry) return js_mkerr(js, "out of memory"); 20469 - map_entry->key = strdup(key_str); 20470 - map_entry->value = value; 20471 - HASH_ADD_STR(*map_head, key, map_entry); 20472 - } 20473 - 20474 - return map_obj; 20475 - } 20476 - 20477 - static jsval_t builtin_Set(struct js *js, jsval_t *args, int nargs) { 20478 - jsval_t set_obj = mkobj(js, 0); 20479 - 20480 - jsval_t set_proto_val = get_ctor_proto(js, "Set", 3); 20481 - if (vtype(set_proto_val) == T_OBJ) set_proto(js, set_obj, set_proto_val); 20482 - 20483 - set_entry_t **set_head = (set_entry_t **)ant_calloc(sizeof(set_entry_t *)); 20484 - if (!set_head) return js_mkerr(js, "out of memory"); 20485 - *set_head = NULL; 20486 - 20487 - set_registry_entry_t *reg = (set_registry_entry_t *)ant_calloc(sizeof(set_registry_entry_t)); 20488 - if (reg) { 20489 - reg->head = set_head; 20490 - HASH_ADD_PTR(set_registry, head, reg); 20491 - } 20492 - 20493 - jsval_t set_ptr = tov((double)(size_t)set_head); 20494 - set_slot(js, set_obj, SLOT_SET, set_ptr); 20495 - 20496 - if (nargs == 0 || vtype(args[0]) != T_ARR) return set_obj; 20497 - 20498 - jsval_t iterable = args[0]; 20499 - jsoff_t length = js_arr_len(js, iterable); 20500 - 20501 - for (jsoff_t i = 0; i < length; i++) { 20502 - jsval_t value = js_arr_get(js, iterable, i); 20503 - const char *key_str = jsval_to_key(js, value); 20504 - 20505 - set_entry_t *entry; 20506 - HASH_FIND_STR(*set_head, key_str, entry); 20507 - if (entry) continue; 20508 - 20509 - entry = (set_entry_t *)ant_calloc(sizeof(set_entry_t)); 20510 - if (!entry) return js_mkerr(js, "out of memory"); 20511 - entry->value = value; 20512 - entry->key = strdup(key_str); 20513 - HASH_ADD_KEYPTR(hh, *set_head, entry->key, strlen(entry->key), entry); 20514 - } 20515 - 20516 - return set_obj; 20517 - } 20518 - 20519 - static map_entry_t** get_map_from_obj(struct js *js, jsval_t obj) { 20520 - jsval_t map_val = js_get_slot(js, obj, SLOT_MAP); 20521 - if (vtype(map_val) == T_UNDEF) return NULL; 20522 - return (map_entry_t**)(size_t)tod(map_val); 20523 - } 20524 - 20525 - static set_entry_t** get_set_from_obj(struct js *js, jsval_t obj) { 20526 - jsval_t set_val = js_get_slot(js, obj, SLOT_SET); 20527 - if (vtype(set_val) == T_UNDEF) return NULL; 20528 - return (set_entry_t**)(size_t)tod(set_val); 20529 - } 20530 - 20531 - static jsval_t map_set(struct js *js, jsval_t *args, int nargs) { 20532 - if (nargs < 2) return js_mkerr(js, "Map.set() requires 2 arguments"); 20533 - 20534 - jsval_t this_val = js->this_val; 20535 - map_entry_t **map_ptr = get_map_from_obj(js, this_val); 20536 - if (!map_ptr) return js_mkerr(js, "Invalid Map object"); 20537 - 20538 - const char *key_str; 20539 - if (vtype(args[0]) == T_STR) { 20540 - jsoff_t len; 20541 - jsoff_t off = vstr(js, args[0], &len); 20542 - key_str = (char *)&js->mem[off]; 20543 - } else key_str = js_str(js, args[0]); 20544 - 20545 - map_entry_t *entry; 20546 - HASH_FIND_STR(*map_ptr, key_str, entry); 20547 - if (entry) { 20548 - entry->value = args[1]; 20549 - } else { 20550 - entry = (map_entry_t *)ant_calloc(sizeof(map_entry_t)); 20551 - if (!entry) return js_mkerr(js, "out of memory"); 20552 - entry->key = strdup(key_str); 20553 - entry->value = args[1]; 20554 - HASH_ADD_STR(*map_ptr, key, entry); 20555 - } 20556 - 20557 - return this_val; 20558 - } 20559 - 20560 - static jsval_t map_get(struct js *js, jsval_t *args, int nargs) { 20561 - if (nargs < 1) return js_mkerr(js, "Map.get() requires 1 argument"); 20562 - 20563 - jsval_t this_val = js->this_val; 20564 - map_entry_t **map_ptr = get_map_from_obj(js, this_val); 20565 - if (!map_ptr) return js_mkundef(); 20566 - 20567 - const char *key_str; 20568 - if (vtype(args[0]) == T_STR) { 20569 - jsoff_t len; 20570 - jsoff_t off = vstr(js, args[0], &len); 20571 - key_str = (char *)&js->mem[off]; 20572 - } else key_str = js_str(js, args[0]); 20573 - 20574 - map_entry_t *entry; 20575 - HASH_FIND_STR(*map_ptr, key_str, entry); 20576 - return entry ? entry->value : js_mkundef(); 20577 - } 20578 - 20579 - static jsval_t map_has(struct js *js, jsval_t *args, int nargs) { 20580 - if (nargs < 1) return js_mkerr(js, "Map.has() requires 1 argument"); 20581 - 20582 - jsval_t this_val = js->this_val; 20583 - map_entry_t **map_ptr = get_map_from_obj(js, this_val); 20584 - if (!map_ptr) return mkval(T_BOOL, 0); 20585 - 20586 - const char *key_str; 20587 - if (vtype(args[0]) == T_STR) { 20588 - jsoff_t len; 20589 - jsoff_t off = vstr(js, args[0], &len); 20590 - key_str = (char *)&js->mem[off]; 20591 - } else key_str = js_str(js, args[0]); 20592 - 20593 - map_entry_t *entry; 20594 - HASH_FIND_STR(*map_ptr, key_str, entry); 20595 - return mkval(T_BOOL, entry ? 1 : 0); 20596 - } 20597 - 20598 - static jsval_t map_delete(struct js *js, jsval_t *args, int nargs) { 20599 - if (nargs < 1) return js_mkerr(js, "Map.delete() requires 1 argument"); 20600 - 20601 - jsval_t this_val = js->this_val; 20602 - map_entry_t **map_ptr = get_map_from_obj(js, this_val); 20603 - if (!map_ptr) return mkval(T_BOOL, 0); 20604 - 20605 - const char *key_str; 20606 - if (vtype(args[0]) == T_STR) { 20607 - jsoff_t len; 20608 - jsoff_t off = vstr(js, args[0], &len); 20609 - key_str = (char *)&js->mem[off]; 20610 - } else key_str = js_str(js, args[0]); 20611 - 20612 - map_entry_t *entry; 20613 - HASH_FIND_STR(*map_ptr, key_str, entry); 20614 - if (entry) { 20615 - HASH_DEL(*map_ptr, entry); 20616 - free(entry->key); 20617 - free(entry); 20618 - return mkval(T_BOOL, 1); 20619 - } 20620 - return mkval(T_BOOL, 0); 20621 - } 20622 - 20623 - static jsval_t map_clear(struct js *js, jsval_t *args, int nargs) { 20624 - jsval_t this_val = js->this_val; 20625 - map_entry_t **map_ptr = get_map_from_obj(js, this_val); 20626 - if (!map_ptr) return js_mkundef(); 20627 - 20628 - map_entry_t *entry, *tmp; 20629 - HASH_ITER(hh, *map_ptr, entry, tmp) { 20630 - HASH_DEL(*map_ptr, entry); 20631 - free(entry->key); 20632 - free(entry); 20633 - } 20634 - *map_ptr = NULL; 20635 - 20636 - return js_mkundef(); 20637 - } 20638 - 20639 - static jsval_t map_size(struct js *js, jsval_t *args, int nargs) { 20640 - (void)args; (void)nargs; 20641 - jsval_t this_val = js->this_val; 20642 - map_entry_t **map_ptr = get_map_from_obj(js, this_val); 20643 - if (!map_ptr) return tov(0); 20644 - 20645 - size_t count = HASH_COUNT(*map_ptr); 20646 - return tov((double)count); 20647 - } 20648 - 20649 - static jsval_t map_iter_next(struct js *js, jsval_t *args, int nargs) { 20650 - (void)args; (void)nargs; 20651 - jsval_t this_val = js->this_val; 20652 - jsval_t idx_val = js_get(js, this_val, "__idx"); 20653 - jsval_t keys = js_get(js, this_val, "__keys"); 20654 - jsval_t vals = js_get(js, this_val, "__vals"); 20655 - jsval_t len_val = js_get(js, this_val, "__len"); 20656 - 20657 - int idx = (int)js_getnum(idx_val); 20658 - int len = (int)js_getnum(len_val); 20659 - 20660 - jsval_t result = js_mkobj(js); 20661 - if (idx >= len) { 20662 - js_set(js, result, "done", js_true); 20663 - js_set(js, result, "value", js_mkundef()); 20664 - } else { 20665 - char idxstr[16]; 20666 - uint_to_str(idxstr, sizeof(idxstr), (unsigned)idx); 20667 - jsval_t k = js_get(js, keys, idxstr); 20668 - jsval_t v = js_get(js, vals, idxstr); 20669 - jsval_t entry = js_mkarr(js); 20670 - js_arr_push(js, entry, k); 20671 - js_arr_push(js, entry, v); 20672 - js_set(js, result, "value", entry); 20673 - js_set(js, result, "done", js_false); 20674 - js_set(js, this_val, "__idx", js_mknum(idx + 1)); 20675 - } 20676 - return result; 20677 - } 20678 - 20679 - static jsval_t map_entries(struct js *js, jsval_t *args, int nargs) { 20680 - (void)args; (void)nargs; 20681 - jsval_t this_val = js->this_val; 20682 - map_entry_t **map_ptr = get_map_from_obj(js, this_val); 20683 - 20684 - jsval_t keys = js_mkarr(js); 20685 - jsval_t vals = js_mkarr(js); 20686 - int count = 0; 20687 - 20688 - if (map_ptr && *map_ptr) { 20689 - map_entry_t *entry, *tmp; 20690 - HASH_ITER(hh, *map_ptr, entry, tmp) { 20691 - js_arr_push(js, keys, js_mkstr(js, entry->key, strlen(entry->key))); 20692 - js_arr_push(js, vals, entry->value); 20693 - count++; 20694 - } 20695 - } 20696 - 20697 - jsval_t iter = js_mkobj(js); 20698 - js_set(js, iter, "__keys", keys); 20699 - js_set(js, iter, "__vals", vals); 20700 - js_set(js, iter, "__idx", js_mknum(0)); 20701 - js_set(js, iter, "__len", js_mknum(count)); 20702 - js_set(js, iter, "next", js_mkfun(map_iter_next)); 20703 - return iter; 20704 - } 20705 - 20706 - static jsval_t set_iter_next(struct js *js, jsval_t *args, int nargs) { 20707 - (void)args; (void)nargs; 20708 - jsval_t this_val = js->this_val; 20709 - jsval_t idx_val = js_get(js, this_val, "__idx"); 20710 - jsval_t vals = js_get(js, this_val, "__vals"); 20711 - jsval_t len_val = js_get(js, this_val, "__len"); 20712 - 20713 - int idx = (int)js_getnum(idx_val); 20714 - int len = (int)js_getnum(len_val); 20715 - 20716 - jsval_t result = js_mkobj(js); 20717 - if (idx >= len) { 20718 - js_set(js, result, "done", js_true); 20719 - js_set(js, result, "value", js_mkundef()); 20720 - } else { 20721 - char idxstr[16]; 20722 - uint_to_str(idxstr, sizeof(idxstr), (unsigned)idx); 20723 - jsval_t v = js_get(js, vals, idxstr); 20724 - js_set(js, result, "value", v); 20725 - js_set(js, result, "done", js_false); 20726 - js_set(js, this_val, "__idx", js_mknum(idx + 1)); 20727 - } 20728 - return result; 20729 - } 20730 - 20731 - static jsval_t set_values(struct js *js, jsval_t *args, int nargs) { 20732 - (void)args; (void)nargs; 20733 - jsval_t this_val = js->this_val; 20734 - set_entry_t **set_ptr = get_set_from_obj(js, this_val); 20735 - 20736 - jsval_t vals = js_mkarr(js); 20737 - int count = 0; 20738 - 20739 - if (set_ptr && *set_ptr) { 20740 - set_entry_t *entry, *tmp; 20741 - HASH_ITER(hh, *set_ptr, entry, tmp) { 20742 - js_arr_push(js, vals, entry->value); 20743 - count++; 20744 - } 20745 - } 20746 - 20747 - jsval_t iter = js_mkobj(js); 20748 - js_set(js, iter, "__vals", vals); 20749 - js_set(js, iter, "__idx", js_mknum(0)); 20750 - js_set(js, iter, "__len", js_mknum(count)); 20751 - js_set(js, iter, "next", js_mkfun(set_iter_next)); 20752 - return iter; 20753 - } 20754 - 20755 - static jsval_t set_add(struct js *js, jsval_t *args, int nargs) { 20756 - if (nargs < 1) return js_mkerr(js, "Set.add() requires 1 argument"); 20757 - 20758 - jsval_t this_val = js->this_val; 20759 - set_entry_t **set_ptr = get_set_from_obj(js, this_val); 20760 - if (!set_ptr) return js_mkerr(js, "Invalid Set object"); 20761 - 20762 - const char *key_str = jsval_to_key(js, args[0]); 20763 - 20764 - set_entry_t *entry; 20765 - HASH_FIND_STR(*set_ptr, key_str, entry); 20766 - 20767 - if (!entry) { 20768 - entry = (set_entry_t *)ant_calloc(sizeof(set_entry_t)); 20769 - if (!entry) return js_mkerr(js, "out of memory"); 20770 - entry->value = args[0]; 20771 - entry->key = strdup(key_str); 20772 - HASH_ADD_KEYPTR(hh, *set_ptr, entry->key, strlen(entry->key), entry); 20773 - } 20774 - 20775 - return this_val; 20776 - } 20777 - 20778 - static jsval_t set_has(struct js *js, jsval_t *args, int nargs) { 20779 - if (nargs < 1) return js_mkerr(js, "Set.has() requires 1 argument"); 20780 - 20781 - jsval_t this_val = js->this_val; 20782 - set_entry_t **set_ptr = get_set_from_obj(js, this_val); 20783 - if (!set_ptr) return mkval(T_BOOL, 0); 20784 - 20785 - const char *key_str = jsval_to_key(js, args[0]); 20786 - 20787 - set_entry_t *entry; 20788 - HASH_FIND_STR(*set_ptr, key_str, entry); 20789 - 20790 - return mkval(T_BOOL, entry ? 1 : 0); 20791 - } 20792 - 20793 - static jsval_t set_delete(struct js *js, jsval_t *args, int nargs) { 20794 - if (nargs < 1) return js_mkerr(js, "Set.delete() requires 1 argument"); 20795 - 20796 - jsval_t this_val = js->this_val; 20797 - set_entry_t **set_ptr = get_set_from_obj(js, this_val); 20798 - if (!set_ptr) return mkval(T_BOOL, 0); 20799 - 20800 - const char *key_str = jsval_to_key(js, args[0]); 20801 - set_entry_t *entry; 20802 - HASH_FIND_STR(*set_ptr, key_str, entry); 20803 - 20804 - if (entry) { 20805 - HASH_DEL(*set_ptr, entry); 20806 - free(entry->key); 20807 - free(entry); 20808 - return mkval(T_BOOL, 1); 20809 - } 20810 - return mkval(T_BOOL, 0); 20811 - } 20812 - 20813 - static jsval_t set_clear(struct js *js, jsval_t *args, int nargs) { 20814 - jsval_t this_val = js->this_val; 20815 - set_entry_t **set_ptr = get_set_from_obj(js, this_val); 20816 - if (!set_ptr) return js_mkundef(); 20817 - 20818 - set_entry_t *entry, *tmp; 20819 - HASH_ITER(hh, *set_ptr, entry, tmp) { 20820 - HASH_DEL(*set_ptr, entry); 20821 - free(entry->key); 20822 - free(entry); 20823 - } 20824 - *set_ptr = NULL; 20825 - 20826 - return js_mkundef(); 20827 - } 20828 - 20829 - static jsval_t set_size(struct js *js, jsval_t *args, int nargs) { 20830 - jsval_t this_val = js->this_val; 20831 - set_entry_t **set_ptr = get_set_from_obj(js, this_val); 20832 - if (!set_ptr) return tov(0); 20833 - 20834 - size_t count = HASH_COUNT(*set_ptr); 20835 - return tov((double)count); 20836 - } 20837 - 20838 - static jsval_t builtin_WeakMap(struct js *js, jsval_t *args, int nargs) { 20839 - jsval_t wm_obj = mkobj(js, 0); 20840 - 20841 - jsval_t wm_proto = get_ctor_proto(js, "WeakMap", 7); 20842 - if (vtype(wm_proto) == T_OBJ) set_proto(js, wm_obj, wm_proto); 20843 - 20844 - weakmap_entry_t **wm_head = (weakmap_entry_t **)ant_calloc(sizeof(weakmap_entry_t *)); 20845 - if (!wm_head) return js_mkerr(js, "out of memory"); 20846 - *wm_head = NULL; 20847 - 20848 - jsval_t wm_ptr = mkval(T_NUM, (size_t)wm_head); 20849 - jsval_t wm_key = js_mkstr(js, "__weakmap", 9); 20850 - setprop(js, wm_obj, wm_key, wm_ptr); 20851 - 20852 - if (nargs == 0 || vtype(args[0]) != T_ARR) return wm_obj; 20853 - 20854 - jsval_t iterable = args[0]; 20855 - jsoff_t length = js_arr_len(js, iterable); 20856 - 20857 - for (jsoff_t i = 0; i < length; i++) { 20858 - jsval_t entry = js_arr_get(js, iterable, i); 20859 - if (vtype(entry) != T_ARR) continue; 20860 - 20861 - jsoff_t entry_len = js_arr_len(js, entry); 20862 - if (entry_len < 2) continue; 20863 - 20864 - jsval_t key = js_arr_get(js, entry, 0); 20865 - jsval_t value = js_arr_get(js, entry, 1); 20866 - 20867 - if (vtype(key) != T_OBJ) return js_mkerr(js, "WeakMap key must be an object"); 20868 - 20869 - weakmap_entry_t *wm_entry; 20870 - HASH_FIND(hh, *wm_head, &key, sizeof(jsval_t), wm_entry); 20871 - if (wm_entry) { 20872 - wm_entry->value = value; 20873 - continue; 20874 - } 20875 - 20876 - wm_entry = (weakmap_entry_t *)ant_calloc(sizeof(weakmap_entry_t)); 20877 - if (!wm_entry) return js_mkerr(js, "out of memory"); 20878 - wm_entry->key_obj = key; 20879 - wm_entry->value = value; 20880 - HASH_ADD(hh, *wm_head, key_obj, sizeof(jsval_t), wm_entry); 20881 - } 20882 - 20883 - return wm_obj; 20884 - } 20885 - 20886 - static jsval_t builtin_WeakSet(struct js *js, jsval_t *args, int nargs) { 20887 - jsval_t ws_obj = mkobj(js, 0); 20888 - 20889 - jsval_t ws_proto = get_ctor_proto(js, "WeakSet", 7); 20890 - if (vtype(ws_proto) == T_OBJ) set_proto(js, ws_obj, ws_proto); 20891 - 20892 - weakset_entry_t **ws_head = (weakset_entry_t **)ant_calloc(sizeof(weakset_entry_t *)); 20893 - if (!ws_head) return js_mkerr(js, "out of memory"); 20894 - *ws_head = NULL; 20895 - 20896 - jsval_t ws_ptr = mkval(T_NUM, (size_t)ws_head); 20897 - jsval_t ws_key = js_mkstr(js, "__weakset", 9); 20898 - setprop(js, ws_obj, ws_key, ws_ptr); 20899 - 20900 - if (nargs == 0 || vtype(args[0]) != T_ARR) return ws_obj; 20901 - 20902 - jsval_t iterable = args[0]; 20903 - jsoff_t length = js_arr_len(js, iterable); 20904 - 20905 - for (jsoff_t i = 0; i < length; i++) { 20906 - jsval_t value = js_arr_get(js, iterable, i); 20907 - 20908 - if (vtype(value) != T_OBJ) return js_mkerr(js, "WeakSet value must be an object"); 20909 - 20910 - weakset_entry_t *entry; 20911 - HASH_FIND(hh, *ws_head, &value, sizeof(jsval_t), entry); 20912 - if (entry) continue; 20913 - 20914 - entry = (weakset_entry_t *)ant_calloc(sizeof(weakset_entry_t)); 20915 - if (!entry) return js_mkerr(js, "out of memory"); 20916 - entry->value_obj = value; 20917 - HASH_ADD(hh, *ws_head, value_obj, sizeof(jsval_t), entry); 20918 - } 20919 - 20920 - return ws_obj; 20921 - } 20922 - 20923 - static jsval_t builtin_WeakRef(struct js *js, jsval_t *args, int nargs) { 20924 - if (nargs < 1 || vtype(args[0]) != T_OBJ) { 20925 - return js_mkerr(js, "WeakRef target must be an object"); 20926 - } 20927 - 20928 - jsval_t wr_obj = mkobj(js, 0); 20929 - jsval_t wr_proto = get_ctor_proto(js, "WeakRef", 7); 20930 - if (vtype(wr_proto) == T_OBJ) set_proto(js, wr_obj, wr_proto); 20931 - set_slot(js, wr_obj, SLOT_DATA, args[0]); 20932 - 20933 - return wr_obj; 20934 - } 20935 - 20936 - static jsval_t weakref_deref(struct js *js, jsval_t *args, int nargs) { 20937 - (void)args; (void)nargs; 20938 - jsval_t this_val = js->this_val; 20939 - if (vtype(this_val) != T_OBJ) return js_mkundef(); 20940 - 20941 - jsval_t target = get_slot(js, this_val, SLOT_DATA); 20942 - if (vtype(target) != T_OBJ) return js_mkundef(); 20943 - 20944 - return target; 20945 - } 20946 - 20947 - static jsval_t builtin_FinalizationRegistry(struct js *js, jsval_t *args, int nargs) { 20948 - if (nargs < 1 || (vtype(args[0]) != T_FUNC && vtype(args[0]) != T_CFUNC)) { 20949 - return js_mkerr(js, "FinalizationRegistry callback must be a function"); 20950 - } 20951 - 20952 - jsval_t fr_obj = mkobj(js, 0); 20953 - jsval_t fr_proto = get_ctor_proto(js, "FinalizationRegistry", 20); 20954 - if (vtype(fr_proto) == T_OBJ) set_proto(js, fr_obj, fr_proto); 20955 - 20956 - set_slot(js, fr_obj, SLOT_DATA, args[0]); 20957 - set_slot(js, fr_obj, SLOT_MAP, mkarr(js)); 20958 - 20959 - return fr_obj; 20960 - } 20961 - 20962 - static jsval_t finreg_register(struct js *js, jsval_t *args, int nargs) { 20963 - jsval_t this_val = js->this_val; 20964 - if (vtype(this_val) != T_OBJ) return js_mkundef(); 20965 - 20966 - if (nargs < 1 || vtype(args[0]) != T_OBJ) { 20967 - return js_mkerr(js, "FinalizationRegistry.register target must be an object"); 20968 - } 20969 - 20970 - jsval_t target = args[0]; 20971 - jsval_t held_value = nargs > 1 ? args[1] : js_mkundef(); 20972 - jsval_t unregister_token = nargs > 2 ? args[2] : js_mkundef(); 20973 - 20974 - if (vdata(target) == vdata(held_value) && vtype(held_value) == T_OBJ) { 20975 - return js_mkerr(js, "target and held value must not be the same"); 20976 - } 20977 - 20978 - jsval_t registrations = get_slot(js, this_val, SLOT_MAP); 20979 - if (vtype(registrations) != T_ARR) return js_mkundef(); 20980 - 20981 - jsval_t entry = mkarr(js); 20982 - jsoff_t len = js_arr_len(js, registrations); 20983 - 20984 - char idx[16]; 20985 - size_t idx_len = uint_to_str(idx, sizeof(idx), 0); 20986 - setprop(js, entry, js_mkstr(js, idx, idx_len), target); 20987 - idx_len = uint_to_str(idx, sizeof(idx), 1); 20988 - setprop(js, entry, js_mkstr(js, idx, idx_len), held_value); 20989 - idx_len = uint_to_str(idx, sizeof(idx), 2); 20990 - setprop(js, entry, js_mkstr(js, idx, idx_len), unregister_token); 20991 - setprop(js, entry, js_mkstr(js, "length", 6), tov(3.0)); 20992 - 20993 - idx_len = uint_to_str(idx, sizeof(idx), len); 20994 - setprop(js, registrations, js_mkstr(js, idx, idx_len), entry); 20995 - setprop(js, registrations, js_mkstr(js, "length", 6), tov((double)(len + 1))); 20996 - 20997 - return js_mkundef(); 20998 - } 20999 - 21000 - static jsval_t finreg_unregister(struct js *js, jsval_t *args, int nargs) { 21001 - jsval_t this_val = js->this_val; 21002 - if (vtype(this_val) != T_OBJ) return js_false; 21003 - 21004 - if (nargs < 1 || vtype(args[0]) != T_OBJ) { 21005 - return js_mkerr(js, "FinalizationRegistry.unregister token must be an object"); 21006 - } 21007 - 21008 - jsval_t token = args[0]; 21009 - jsval_t registrations = get_slot(js, this_val, SLOT_MAP); 21010 - if (vtype(registrations) != T_ARR) return js_false; 21011 - 21012 - jsoff_t len = js_arr_len(js, registrations); 21013 - bool removed = false; 21014 - 21015 - for (jsoff_t i = 0; i < len; i++) { 21016 - jsval_t entry = js_arr_get(js, registrations, i); 21017 - if (vtype(entry) != T_ARR) continue; 21018 - jsval_t entry_token = js_arr_get(js, entry, 2); 21019 - if (vtype(entry_token) == T_OBJ && vdata(entry_token) == vdata(token)) { 21020 - char idx[16]; size_t idx_len = uint_to_str(idx, sizeof(idx), i); 21021 - setprop(js, registrations, js_mkstr(js, idx, idx_len), js_mkundef()); 21022 - removed = true; 21023 - } 21024 - } 21025 - 21026 - return js_bool(removed); 21027 - } 21028 - 21029 20368 static proxy_data_t *get_proxy_data(jsval_t obj) { 21030 20369 if (vtype(obj) != T_OBJ) return NULL; 21031 20370 jsoff_t off = (jsoff_t)vdata(obj); ··· 21219 20558 return result; 21220 20559 } 21221 20560 21222 - static weakmap_entry_t** get_weakmap_from_obj(struct js *js, jsval_t obj) { 21223 - jsoff_t wm_off = lkp(js, obj, "__weakmap", 9); 21224 - if (wm_off == 0) return NULL; 21225 - jsval_t wm_val = resolveprop(js, mkval(T_PROP, wm_off)); 21226 - if (vtype(wm_val) != T_NUM) return NULL; 21227 - return (weakmap_entry_t**)(size_t)vdata(wm_val); 21228 - } 21229 - 21230 - static weakset_entry_t** get_weakset_from_obj(struct js *js, jsval_t obj) { 21231 - jsoff_t ws_off = lkp(js, obj, "__weakset", 9); 21232 - if (ws_off == 0) return NULL; 21233 - jsval_t ws_val = resolveprop(js, mkval(T_PROP, ws_off)); 21234 - if (vtype(ws_val) != T_NUM) return NULL; 21235 - return (weakset_entry_t**)(size_t)vdata(ws_val); 21236 - } 21237 - 21238 - static jsval_t weakmap_set(struct js *js, jsval_t *args, int nargs) { 21239 - if (nargs < 2) return js_mkerr(js, "WeakMap.set() requires 2 arguments"); 21240 - 21241 - jsval_t this_val = js->this_val; 21242 - weakmap_entry_t **wm_ptr = get_weakmap_from_obj(js, this_val); 21243 - if (!wm_ptr) return js_mkerr(js, "Invalid WeakMap object"); 21244 - 21245 - if (vtype(args[0]) != T_OBJ) { 21246 - return js_mkerr(js, "WeakMap key must be an object"); 21247 - } 21248 - 21249 - jsval_t key_obj = args[0]; 21250 - 21251 - weakmap_entry_t *entry; 21252 - HASH_FIND(hh, *wm_ptr, &key_obj, sizeof(jsval_t), entry); 21253 - if (entry) { 21254 - entry->value = args[1]; 21255 - } else { 21256 - entry = (weakmap_entry_t *)ant_calloc(sizeof(weakmap_entry_t)); 21257 - if (!entry) return js_mkerr(js, "out of memory"); 21258 - entry->key_obj = key_obj; 21259 - entry->value = args[1]; 21260 - HASH_ADD(hh, *wm_ptr, key_obj, sizeof(jsval_t), entry); 21261 - } 21262 - 21263 - return this_val; 21264 - } 21265 - 21266 - static jsval_t weakmap_get(struct js *js, jsval_t *args, int nargs) { 21267 - if (nargs < 1) return js_mkerr(js, "WeakMap.get() requires 1 argument"); 21268 - 21269 - jsval_t this_val = js->this_val; 21270 - weakmap_entry_t **wm_ptr = get_weakmap_from_obj(js, this_val); 21271 - if (!wm_ptr) return js_mkundef(); 21272 - 21273 - if (vtype(args[0]) != T_OBJ) return js_mkundef(); 21274 - 21275 - jsval_t key_obj = args[0]; 21276 - weakmap_entry_t *entry; 21277 - HASH_FIND(hh, *wm_ptr, &key_obj, sizeof(jsval_t), entry); 21278 - return entry ? entry->value : js_mkundef(); 21279 - } 21280 - 21281 - static jsval_t weakmap_has(struct js *js, jsval_t *args, int nargs) { 21282 - if (nargs < 1) return js_mkerr(js, "WeakMap.has() requires 1 argument"); 21283 - 21284 - jsval_t this_val = js->this_val; 21285 - weakmap_entry_t **wm_ptr = get_weakmap_from_obj(js, this_val); 21286 - if (!wm_ptr) return mkval(T_BOOL, 0); 21287 - 21288 - if (vtype(args[0]) != T_OBJ) return mkval(T_BOOL, 0); 21289 - 21290 - jsval_t key_obj = args[0]; 21291 - weakmap_entry_t *entry; 21292 - HASH_FIND(hh, *wm_ptr, &key_obj, sizeof(jsval_t), entry); 21293 - return mkval(T_BOOL, entry ? 1 : 0); 21294 - } 21295 - 21296 - static jsval_t weakmap_delete(struct js *js, jsval_t *args, int nargs) { 21297 - if (nargs < 1) return js_mkerr(js, "WeakMap.delete() requires 1 argument"); 21298 - 21299 - jsval_t this_val = js->this_val; 21300 - weakmap_entry_t **wm_ptr = get_weakmap_from_obj(js, this_val); 21301 - if (!wm_ptr) return mkval(T_BOOL, 0); 21302 - 21303 - if (vtype(args[0]) != T_OBJ) return mkval(T_BOOL, 0); 21304 - 21305 - jsval_t key_obj = args[0]; 21306 - weakmap_entry_t *entry; 21307 - HASH_FIND(hh, *wm_ptr, &key_obj, sizeof(jsval_t), entry); 21308 - if (entry) { 21309 - HASH_DEL(*wm_ptr, entry); 21310 - free(entry); 21311 - return mkval(T_BOOL, 1); 21312 - } 21313 - return mkval(T_BOOL, 0); 21314 - } 21315 - 21316 - static jsval_t weakset_add(struct js *js, jsval_t *args, int nargs) { 21317 - if (nargs < 1) return js_mkerr(js, "WeakSet.add() requires 1 argument"); 21318 - 21319 - jsval_t this_val = js->this_val; 21320 - weakset_entry_t **ws_ptr = get_weakset_from_obj(js, this_val); 21321 - if (!ws_ptr) return js_mkerr(js, "Invalid WeakSet object"); 21322 - 21323 - if (vtype(args[0]) != T_OBJ) { 21324 - return js_mkerr(js, "WeakSet value must be an object"); 21325 - } 21326 - 21327 - jsval_t value_obj = args[0]; 21328 - 21329 - weakset_entry_t *entry; 21330 - HASH_FIND(hh, *ws_ptr, &value_obj, sizeof(jsval_t), entry); 21331 - 21332 - if (!entry) { 21333 - entry = (weakset_entry_t *)ant_calloc(sizeof(weakset_entry_t)); 21334 - if (!entry) return js_mkerr(js, "out of memory"); 21335 - entry->value_obj = value_obj; 21336 - HASH_ADD(hh, *ws_ptr, value_obj, sizeof(jsval_t), entry); 21337 - } 21338 - 21339 - return this_val; 21340 - } 21341 - 21342 - static jsval_t weakset_has(struct js *js, jsval_t *args, int nargs) { 21343 - if (nargs < 1) return js_mkerr(js, "WeakSet.has() requires 1 argument"); 21344 - 21345 - jsval_t this_val = js->this_val; 21346 - weakset_entry_t **ws_ptr = get_weakset_from_obj(js, this_val); 21347 - if (!ws_ptr) return mkval(T_BOOL, 0); 21348 - 21349 - if (vtype(args[0]) != T_OBJ) return mkval(T_BOOL, 0); 21350 - 21351 - jsval_t value_obj = args[0]; 21352 - weakset_entry_t *entry; 21353 - HASH_FIND(hh, *ws_ptr, &value_obj, sizeof(jsval_t), entry); 21354 - 21355 - return mkval(T_BOOL, entry ? 1 : 0); 21356 - } 21357 - 21358 - static jsval_t weakset_delete(struct js *js, jsval_t *args, int nargs) { 21359 - if (nargs < 1) return js_mkerr(js, "WeakSet.delete() requires 1 argument"); 21360 - 21361 - jsval_t this_val = js->this_val; 21362 - weakset_entry_t **ws_ptr = get_weakset_from_obj(js, this_val); 21363 - if (!ws_ptr) return mkval(T_BOOL, 0); 21364 - 21365 - if (vtype(args[0]) != T_OBJ) return mkval(T_BOOL, 0); 21366 - 21367 - jsval_t value_obj = args[0]; 21368 - weakset_entry_t *entry; 21369 - HASH_FIND(hh, *ws_ptr, &value_obj, sizeof(jsval_t), entry); 21370 - 21371 - if (entry) { 21372 - HASH_DEL(*ws_ptr, entry); 21373 - free(entry); 21374 - return mkval(T_BOOL, 1); 21375 - } 21376 - return mkval(T_BOOL, 0); 21377 - } 21378 - 21379 20561 ant_t *js_create(void *buf, size_t len) { 21380 20562 assert( 21381 20563 (uintptr_t)buf <= ((1ULL << 53) - 1) && ··· 21647 20829 setprop(js, regexp_proto, js_mkstr(js, "test", 4), js_mkfun(builtin_regexp_test)); 21648 20830 setprop(js, regexp_proto, js_mkstr(js, "exec", 4), js_mkfun(builtin_regexp_exec)); 21649 20831 setprop(js, regexp_proto, js_mkstr(js, "toString", 8), js_mkfun(builtin_regexp_toString)); 21650 - 21651 - jsval_t map_proto = js_mkobj(js); 21652 - set_proto(js, map_proto, object_proto); 21653 - setprop(js, map_proto, js_mkstr(js, "set", 3), js_mkfun(map_set)); 21654 - setprop(js, map_proto, js_mkstr(js, "get", 3), js_mkfun(map_get)); 21655 - setprop(js, map_proto, js_mkstr(js, "has", 3), js_mkfun(map_has)); 21656 - setprop(js, map_proto, js_mkstr(js, "delete", 6), js_mkfun(map_delete)); 21657 - setprop(js, map_proto, js_mkstr(js, "clear", 5), js_mkfun(map_clear)); 21658 - setprop(js, map_proto, js_mkstr(js, "size", 4), js_mkfun(map_size)); 21659 - setprop(js, map_proto, js_mkstr(js, "entries", 7), js_mkfun(map_entries)); 21660 - 21661 - jsval_t set_proto_obj = js_mkobj(js); 21662 - set_proto(js, set_proto_obj, object_proto); 21663 - setprop(js, set_proto_obj, js_mkstr(js, "add", 3), js_mkfun(set_add)); 21664 - setprop(js, set_proto_obj, js_mkstr(js, "has", 3), js_mkfun(set_has)); 21665 - setprop(js, set_proto_obj, js_mkstr(js, "delete", 6), js_mkfun(set_delete)); 21666 - setprop(js, set_proto_obj, js_mkstr(js, "clear", 5), js_mkfun(set_clear)); 21667 - setprop(js, set_proto_obj, js_mkstr(js, "size", 4), js_mkfun(set_size)); 21668 - setprop(js, set_proto_obj, js_mkstr(js, "values", 6), js_mkfun(set_values)); 21669 - 21670 - jsval_t weakmap_proto = js_mkobj(js); 21671 - set_proto(js, weakmap_proto, object_proto); 21672 - setprop(js, weakmap_proto, js_mkstr(js, "set", 3), js_mkfun(weakmap_set)); 21673 - setprop(js, weakmap_proto, js_mkstr(js, "get", 3), js_mkfun(weakmap_get)); 21674 - setprop(js, weakmap_proto, js_mkstr(js, "has", 3), js_mkfun(weakmap_has)); 21675 - setprop(js, weakmap_proto, js_mkstr(js, "delete", 6), js_mkfun(weakmap_delete)); 21676 - 21677 - jsval_t weakset_proto = js_mkobj(js); 21678 - set_proto(js, weakset_proto, object_proto); 21679 - setprop(js, weakset_proto, js_mkstr(js, "add", 3), js_mkfun(weakset_add)); 21680 - setprop(js, weakset_proto, js_mkstr(js, "has", 3), js_mkfun(weakset_has)); 21681 - setprop(js, weakset_proto, js_mkstr(js, "delete", 6), js_mkfun(weakset_delete)); 21682 - 21683 - jsval_t weakref_proto = js_mkobj(js); 21684 - set_proto(js, weakref_proto, object_proto); 21685 - setprop(js, weakref_proto, js_mkstr(js, "deref", 5), js_mkfun(weakref_deref)); 21686 - 21687 - jsval_t finreg_proto = js_mkobj(js); 21688 - set_proto(js, finreg_proto, object_proto); 21689 - setprop(js, finreg_proto, js_mkstr(js, "register", 8), js_mkfun(finreg_register)); 21690 - setprop(js, finreg_proto, js_mkstr(js, "unregister", 10), js_mkfun(finreg_unregister)); 21691 20832 21692 20833 jsval_t promise_proto = js_mkobj(js); 21693 20834 set_proto(js, promise_proto, object_proto); ··· 21797 20938 js_set_descriptor(js, arr_ctor_obj, "length", 6, JS_DESC_C); 21798 20939 setprop(js, arr_ctor_obj, ANT_STRING("name"), ANT_STRING("Array")); 21799 20940 setprop(js, glob, js_mkstr(js, "Array", 5), mkval(T_FUNC, vdata(arr_ctor_obj))); 21800 - 21801 - jsval_t map_ctor_obj = mkobj(js, 0); 21802 - set_proto(js, map_ctor_obj, function_proto); 21803 - set_slot(js, map_ctor_obj, SLOT_CFUNC, js_mkfun(builtin_Map)); 21804 - js_setprop_nonconfigurable(js, map_ctor_obj, "prototype", 9, map_proto); 21805 - setprop(js, map_ctor_obj, ANT_STRING("name"), ANT_STRING("Map")); 21806 - setprop(js, glob, js_mkstr(js, "Map", 3), mkval(T_FUNC, vdata(map_ctor_obj))); 21807 - 21808 - jsval_t set_ctor_obj = mkobj(js, 0); 21809 - set_proto(js, set_ctor_obj, function_proto); 21810 - set_slot(js, set_ctor_obj, SLOT_CFUNC, js_mkfun(builtin_Set)); 21811 - js_setprop_nonconfigurable(js, set_ctor_obj, "prototype", 9, set_proto_obj); 21812 - setprop(js, set_ctor_obj, ANT_STRING("name"), ANT_STRING("Set")); 21813 - setprop(js, glob, js_mkstr(js, "Set", 3), mkval(T_FUNC, vdata(set_ctor_obj))); 21814 - 21815 - jsval_t weakmap_ctor_obj = mkobj(js, 0); 21816 - set_proto(js, weakmap_ctor_obj, function_proto); 21817 - set_slot(js, weakmap_ctor_obj, SLOT_CFUNC, js_mkfun(builtin_WeakMap)); 21818 - js_setprop_nonconfigurable(js, weakmap_ctor_obj, "prototype", 9, weakmap_proto); 21819 - setprop(js, weakmap_ctor_obj, ANT_STRING("name"), ANT_STRING("WeakMap")); 21820 - setprop(js, glob, js_mkstr(js, "WeakMap", 7), mkval(T_FUNC, vdata(weakmap_ctor_obj))); 21821 - 21822 - jsval_t weakset_ctor_obj = mkobj(js, 0); 21823 - set_proto(js, weakset_ctor_obj, function_proto); 21824 - set_slot(js, weakset_ctor_obj, SLOT_CFUNC, js_mkfun(builtin_WeakSet)); 21825 - js_setprop_nonconfigurable(js, weakset_ctor_obj, "prototype", 9, weakset_proto); 21826 - setprop(js, weakset_ctor_obj, ANT_STRING("name"), ANT_STRING("WeakSet")); 21827 - setprop(js, glob, js_mkstr(js, "WeakSet", 7), mkval(T_FUNC, vdata(weakset_ctor_obj))); 21828 - 21829 - jsval_t weakref_ctor_obj = mkobj(js, 0); 21830 - set_proto(js, weakref_ctor_obj, function_proto); 21831 - set_slot(js, weakref_ctor_obj, SLOT_CFUNC, js_mkfun(builtin_WeakRef)); 21832 - js_setprop_nonconfigurable(js, weakref_ctor_obj, "prototype", 9, weakref_proto); 21833 - setprop(js, weakref_ctor_obj, ANT_STRING("name"), ANT_STRING("WeakRef")); 21834 - setprop(js, glob, js_mkstr(js, "WeakRef", 7), mkval(T_FUNC, vdata(weakref_ctor_obj))); 21835 - 21836 - jsval_t finreg_ctor_obj = mkobj(js, 0); 21837 - set_proto(js, finreg_ctor_obj, function_proto); 21838 - set_slot(js, finreg_ctor_obj, SLOT_CFUNC, js_mkfun(builtin_FinalizationRegistry)); 21839 - js_setprop_nonconfigurable(js, finreg_ctor_obj, "prototype", 9, finreg_proto); 21840 - setprop(js, finreg_ctor_obj, ANT_STRING("name"), ANT_STRING("FinalizationRegistry")); 21841 - setprop(js, glob, js_mkstr(js, "FinalizationRegistry", 20), mkval(T_FUNC, vdata(finreg_ctor_obj))); 21842 20941 21843 20942 jsval_t proxy_ctor_obj = mkobj(js, 0); 21844 20943 set_proto(js, proxy_ctor_obj, function_proto); ··· 21846 20945 setprop(js, proxy_ctor_obj, js_mkstr(js, "revocable", 9), js_mkfun(builtin_Proxy_revocable)); 21847 20946 setprop(js, proxy_ctor_obj, ANT_STRING("name"), ANT_STRING("Proxy")); 21848 20947 setprop(js, glob, js_mkstr(js, "Proxy", 5), mkval(T_FUNC, vdata(proxy_ctor_obj))); 21849 - 21850 - 21851 20948 21852 20949 jsval_t regex_ctor_obj = mkobj(js, 0); 21853 20950 set_proto(js, regex_ctor_obj, function_proto); ··· 22027 21124 esm_cleanup_module_cache(); 22028 21125 code_arena_reset(); 22029 21126 cleanup_buffer_module(); 21127 + cleanup_collections_module(); 22030 21128 22031 21129 if (js->errmsg) { 22032 21130 free(js->errmsg); ··· 22346 21444 child_process_gc_update_roots(op_val, c); 22347 21445 readline_gc_update_roots(op_val, c); 22348 21446 process_gc_update_roots(op_val, c); 22349 - 22350 - map_registry_entry_t *map_reg, *map_reg_tmp; 22351 - HASH_ITER(hh, map_registry, map_reg, map_reg_tmp) { 22352 - if (map_reg->head && *map_reg->head) { 22353 - map_entry_t *me, *me_tmp; 22354 - HASH_ITER(hh, *map_reg->head, me, me_tmp) op_val(c, &me->value); 22355 - } 22356 - } 22357 - 22358 - set_registry_entry_t *set_reg, *set_reg_tmp; 22359 - HASH_ITER(hh, set_registry, set_reg, set_reg_tmp) { 22360 - if (set_reg->head && *set_reg->head) { 22361 - set_entry_t *se, *se_tmp; 22362 - HASH_ITER(hh, *set_reg->head, se, se_tmp) op_val(c, &se->value); 22363 - } 22364 - } 21447 + collections_gc_update_roots(op_val, c); 22365 21448 22366 21449 for (int i = 0; i < c->js->for_let_stack_len; i++) { 22367 21450 op_val(c, &c->js->for_let_stack[i].body_scope);
+2
src/main.c
··· 45 45 #include "modules/child_process.h" 46 46 #include "modules/readline.h" 47 47 #include "modules/observable.h" 48 + #include "modules/collections.h" 48 49 49 50 int js_result = EXIT_SUCCESS; 50 51 ··· 221 222 ant_runtime_init(js, argc, argv, localstorage_file); 222 223 223 224 init_symbol_module(); 225 + init_collections_module(); 224 226 init_builtin_module(); 225 227 init_buffer_module(); 226 228 init_fs_module();
+1021
src/modules/collections.c
··· 1 + #include <stdlib.h> 2 + #include <string.h> 3 + #include <stdio.h> 4 + 5 + #include "ant.h" 6 + #include "errors.h" 7 + #include "runtime.h" 8 + #include "internal.h" 9 + #include "arena.h" 10 + 11 + #include "modules/collections.h" 12 + #include "modules/symbol.h" 13 + 14 + static map_entry_t ***map_registry_heads = NULL; 15 + static size_t map_registry_count = 0; 16 + static size_t map_registry_cap = 0; 17 + 18 + static set_entry_t ***set_registry_heads = NULL; 19 + static size_t set_registry_count = 0; 20 + static size_t set_registry_cap = 0; 21 + 22 + static jsval_t iter_return_this(ant_t *js, jsval_t *args, int nargs) { 23 + return js->this_val; 24 + } 25 + 26 + static void register_map(map_entry_t **head) { 27 + if (!head) return; 28 + if (map_registry_count >= map_registry_cap) { 29 + size_t new_cap = map_registry_cap ? map_registry_cap * 2 : 64; 30 + map_entry_t ***new_reg = realloc(map_registry_heads, new_cap * sizeof(map_entry_t **)); 31 + if (!new_reg) return; 32 + map_registry_heads = new_reg; 33 + map_registry_cap = new_cap; 34 + } 35 + map_registry_heads[map_registry_count++] = head; 36 + } 37 + 38 + static void register_set(set_entry_t **head) { 39 + if (!head) return; 40 + if (set_registry_count >= set_registry_cap) { 41 + size_t new_cap = set_registry_cap ? set_registry_cap * 2 : 64; 42 + set_entry_t ***new_reg = realloc(set_registry_heads, new_cap * sizeof(set_entry_t **)); 43 + if (!new_reg) return; 44 + set_registry_heads = new_reg; 45 + set_registry_cap = new_cap; 46 + } 47 + set_registry_heads[set_registry_count++] = head; 48 + } 49 + 50 + static const char *jsval_to_key(ant_t *js, jsval_t val) { 51 + if (vtype(val) == T_STR) { 52 + jsoff_t len; 53 + jsoff_t off = vstr(js, val, &len); 54 + return (char *)&js->mem[off]; 55 + } 56 + return js_str(js, val); 57 + } 58 + 59 + map_entry_t **get_map_from_obj(ant_t *js, jsval_t obj) { 60 + jsval_t map_val = js_get_slot(js, obj, SLOT_MAP); 61 + if (vtype(map_val) == T_UNDEF) return NULL; 62 + return (map_entry_t **)(uintptr_t)js_getnum(map_val); 63 + } 64 + 65 + set_entry_t **get_set_from_obj(ant_t *js, jsval_t obj) { 66 + jsval_t set_val = js_get_slot(js, obj, SLOT_SET); 67 + if (vtype(set_val) == T_UNDEF) return NULL; 68 + return (set_entry_t **)(uintptr_t)js_getnum(set_val); 69 + } 70 + 71 + static weakmap_entry_t **get_weakmap_from_obj(ant_t *js, jsval_t obj) { 72 + jsval_t wm_val = js_get_slot(js, obj, SLOT_DATA); 73 + if (vtype(wm_val) == T_UNDEF) return NULL; 74 + return (weakmap_entry_t **)(uintptr_t)js_getnum(wm_val); 75 + } 76 + 77 + static weakset_entry_t **get_weakset_from_obj(ant_t *js, jsval_t obj) { 78 + jsval_t ws_val = js_get_slot(js, obj, SLOT_DATA); 79 + if (vtype(ws_val) == T_UNDEF) return NULL; 80 + return (weakset_entry_t **)(uintptr_t)js_getnum(ws_val); 81 + } 82 + 83 + static map_iterator_state_t *get_map_iter_state(ant_t *js, jsval_t obj) { 84 + jsval_t state_val = js_get_slot(js, obj, SLOT_ITER_STATE); 85 + if (vtype(state_val) == T_UNDEF) return NULL; 86 + return (map_iterator_state_t *)(uintptr_t)js_getnum(state_val); 87 + } 88 + 89 + static set_iterator_state_t *get_set_iter_state(ant_t *js, jsval_t obj) { 90 + jsval_t state_val = js_get_slot(js, obj, SLOT_ITER_STATE); 91 + if (vtype(state_val) == T_UNDEF) return NULL; 92 + return (set_iterator_state_t *)(uintptr_t)js_getnum(state_val); 93 + } 94 + 95 + static jsval_t map_set(ant_t *js, jsval_t *args, int nargs) { 96 + if (nargs < 2) return js_mkerr(js, "Map.set() requires 2 arguments"); 97 + 98 + jsval_t this_val = js->this_val; 99 + map_entry_t **map_ptr = get_map_from_obj(js, this_val); 100 + if (!map_ptr) return js_mkerr(js, "Invalid Map object"); 101 + const char *key_str = jsval_to_key(js, args[0]); 102 + 103 + map_entry_t *entry; 104 + HASH_FIND_STR(*map_ptr, key_str, entry); 105 + if (entry) { 106 + entry->value = args[1]; 107 + } else { 108 + entry = ant_calloc(sizeof(map_entry_t)); 109 + if (!entry) return js_mkerr(js, "out of memory"); 110 + entry->key = strdup(key_str); 111 + entry->value = args[1]; 112 + HASH_ADD_STR(*map_ptr, key, entry); 113 + } 114 + 115 + return this_val; 116 + } 117 + 118 + static jsval_t map_get(ant_t *js, jsval_t *args, int nargs) { 119 + if (nargs < 1) return js_mkerr(js, "Map.get() requires 1 argument"); 120 + 121 + jsval_t this_val = js->this_val; 122 + map_entry_t **map_ptr = get_map_from_obj(js, this_val); 123 + if (!map_ptr) return js_mkundef(); 124 + 125 + const char *key_str = jsval_to_key(js, args[0]); 126 + 127 + map_entry_t *entry; 128 + HASH_FIND_STR(*map_ptr, key_str, entry); 129 + return entry ? entry->value : js_mkundef(); 130 + } 131 + 132 + static jsval_t map_has(ant_t *js, jsval_t *args, int nargs) { 133 + if (nargs < 1) return js_mkerr(js, "Map.has() requires 1 argument"); 134 + 135 + jsval_t this_val = js->this_val; 136 + map_entry_t **map_ptr = get_map_from_obj(js, this_val); 137 + 138 + if (!map_ptr) return js_false; 139 + const char *key_str = jsval_to_key(js, args[0]); 140 + 141 + map_entry_t *entry; 142 + HASH_FIND_STR(*map_ptr, key_str, entry); 143 + return js_bool(entry != NULL); 144 + } 145 + 146 + static jsval_t map_delete(ant_t *js, jsval_t *args, int nargs) { 147 + if (nargs < 1) return js_mkerr(js, "Map.delete() requires 1 argument"); 148 + 149 + jsval_t this_val = js->this_val; 150 + map_entry_t **map_ptr = get_map_from_obj(js, this_val); 151 + 152 + if (!map_ptr) return js_false; 153 + const char *key_str = jsval_to_key(js, args[0]); 154 + 155 + map_entry_t *entry; 156 + HASH_FIND_STR(*map_ptr, key_str, entry); 157 + if (entry) { 158 + HASH_DEL(*map_ptr, entry); 159 + free(entry->key); 160 + free(entry); 161 + return js_true; 162 + } 163 + return js_false; 164 + } 165 + 166 + static jsval_t map_clear(ant_t *js, jsval_t *args, int nargs) { 167 + jsval_t this_val = js->this_val; 168 + map_entry_t **map_ptr = get_map_from_obj(js, this_val); 169 + if (!map_ptr) return js_mkundef(); 170 + 171 + map_entry_t *entry, *tmp; 172 + HASH_ITER(hh, *map_ptr, entry, tmp) { 173 + HASH_DEL(*map_ptr, entry); 174 + free(entry->key); 175 + free(entry); 176 + } 177 + *map_ptr = NULL; 178 + 179 + return js_mkundef(); 180 + } 181 + 182 + static jsval_t map_size(ant_t *js, jsval_t *args, int nargs) { 183 + jsval_t this_val = js->this_val; 184 + map_entry_t **map_ptr = get_map_from_obj(js, this_val); 185 + if (!map_ptr) return js_mknum(0); 186 + 187 + return js_mknum((double)HASH_COUNT(*map_ptr)); 188 + } 189 + 190 + static jsval_t map_forEach(ant_t *js, jsval_t *args, int nargs) { 191 + jsval_t this_val = js->this_val; 192 + map_entry_t **map_ptr = get_map_from_obj(js, this_val); 193 + 194 + if (nargs < 1 || vtype(args[0]) != T_FUNC) 195 + return js_mkerr(js, "forEach requires a callback function"); 196 + 197 + jsval_t callback = args[0]; 198 + 199 + if (map_ptr && *map_ptr) { 200 + map_entry_t *entry, *tmp; 201 + HASH_ITER(hh, *map_ptr, entry, tmp) { 202 + jsval_t k = js_mkstr(js, entry->key, strlen(entry->key)); 203 + jsval_t call_args[3] = { entry->value, k, this_val }; 204 + jsval_t result = js_call(js, callback, call_args, 3); 205 + if (is_err(result)) return result; 206 + } 207 + } 208 + 209 + return js_mkundef(); 210 + } 211 + 212 + static jsval_t map_iter_next(ant_t *js, jsval_t *args, int nargs) { 213 + (void)args; (void)nargs; 214 + jsval_t this_val = js->this_val; 215 + 216 + map_iterator_state_t *state = get_map_iter_state(js, this_val); 217 + if (!state) return js_mkerr(js, "Invalid iterator"); 218 + 219 + jsval_t result = js_mkobj(js); 220 + 221 + if (!state->current) { 222 + js_set(js, result, "done", js_true); 223 + js_set(js, result, "value", js_mkundef()); 224 + return result; 225 + } 226 + 227 + map_entry_t *entry = state->current; 228 + jsval_t value; 229 + 230 + switch (state->type) { 231 + case ITER_TYPE_MAP_VALUES: 232 + value = entry->value; 233 + break; 234 + case ITER_TYPE_MAP_KEYS: 235 + value = js_mkstr(js, entry->key, strlen(entry->key)); 236 + break; 237 + case ITER_TYPE_MAP_ENTRIES: { 238 + jsval_t pair = js_mkarr(js); 239 + js_arr_push(js, pair, js_mkstr(js, entry->key, strlen(entry->key))); 240 + js_arr_push(js, pair, entry->value); 241 + value = pair; 242 + break; 243 + } 244 + default: 245 + value = js_mkundef(); 246 + } 247 + 248 + state->current = entry->hh.next; 249 + 250 + js_set(js, result, "value", value); 251 + js_set(js, result, "done", js_false); 252 + return result; 253 + } 254 + 255 + static jsval_t create_map_iterator(ant_t *js, jsval_t map_obj, iter_type_t type) { 256 + map_entry_t **map_ptr = get_map_from_obj(js, map_obj); 257 + 258 + map_iterator_state_t *state = ant_calloc(sizeof(map_iterator_state_t)); 259 + if (!state) return js_mkerr(js, "out of memory"); 260 + 261 + state->head = map_ptr; 262 + state->current = map_ptr ? *map_ptr : NULL; 263 + state->type = type; 264 + 265 + jsval_t iter = js_mkobj(js); 266 + js_set_slot(js, iter, SLOT_ITER_STATE, ANT_PTR(state)); 267 + js_set(js, iter, "next", js_mkfun(map_iter_next)); 268 + 269 + const char *iter_key = get_iterator_sym_key(); 270 + if (iter_key && iter_key[0]) { 271 + js_set(js, iter, iter_key, js_mkfun(iter_return_this)); 272 + } 273 + 274 + return iter; 275 + } 276 + 277 + static jsval_t map_values(ant_t *js, jsval_t *args, int nargs) { 278 + (void)args; (void)nargs; 279 + return create_map_iterator(js, js->this_val, ITER_TYPE_MAP_VALUES); 280 + } 281 + 282 + static jsval_t map_keys(ant_t *js, jsval_t *args, int nargs) { 283 + (void)args; (void)nargs; 284 + return create_map_iterator(js, js->this_val, ITER_TYPE_MAP_KEYS); 285 + } 286 + 287 + static jsval_t map_entries(ant_t *js, jsval_t *args, int nargs) { 288 + (void)args; (void)nargs; 289 + return create_map_iterator(js, js->this_val, ITER_TYPE_MAP_ENTRIES); 290 + } 291 + 292 + static jsval_t map_iterator(ant_t *js, jsval_t *args, int nargs) { 293 + (void)args; (void)nargs; 294 + return create_map_iterator(js, js->this_val, ITER_TYPE_MAP_ENTRIES); 295 + } 296 + 297 + static jsval_t set_iter_next(ant_t *js, jsval_t *args, int nargs) { 298 + (void)args; (void)nargs; 299 + jsval_t this_val = js->this_val; 300 + 301 + set_iterator_state_t *state = get_set_iter_state(js, this_val); 302 + if (!state) return js_mkerr(js, "Invalid iterator"); 303 + 304 + jsval_t result = js_mkobj(js); 305 + 306 + if (!state->current) { 307 + js_set(js, result, "done", js_true); 308 + js_set(js, result, "value", js_mkundef()); 309 + return result; 310 + } 311 + 312 + set_entry_t *entry = state->current; 313 + jsval_t value; 314 + 315 + if (state->type == ITER_TYPE_SET_ENTRIES) { 316 + jsval_t pair = js_mkarr(js); 317 + js_arr_push(js, pair, entry->value); 318 + js_arr_push(js, pair, entry->value); 319 + value = pair; 320 + } else { 321 + value = entry->value; 322 + } 323 + 324 + state->current = entry->hh.next; 325 + 326 + js_set(js, result, "value", value); 327 + js_set(js, result, "done", js_false); 328 + return result; 329 + } 330 + 331 + static jsval_t create_set_iterator(ant_t *js, jsval_t set_obj, iter_type_t type) { 332 + set_entry_t **set_ptr = get_set_from_obj(js, set_obj); 333 + 334 + set_iterator_state_t *state = ant_calloc(sizeof(set_iterator_state_t)); 335 + if (!state) return js_mkerr(js, "out of memory"); 336 + 337 + state->head = set_ptr; 338 + state->current = set_ptr ? *set_ptr : NULL; 339 + state->type = type; 340 + 341 + jsval_t iter = js_mkobj(js); 342 + js_set_slot(js, iter, SLOT_ITER_STATE, ANT_PTR(state)); 343 + js_set(js, iter, "next", js_mkfun(set_iter_next)); 344 + 345 + const char *iter_key = get_iterator_sym_key(); 346 + if (iter_key && iter_key[0]) { 347 + js_set(js, iter, iter_key, js_mkfun(iter_return_this)); 348 + } 349 + 350 + return iter; 351 + } 352 + 353 + static jsval_t set_add(ant_t *js, jsval_t *args, int nargs) { 354 + if (nargs < 1) return js_mkerr(js, "Set.add() requires 1 argument"); 355 + 356 + jsval_t this_val = js->this_val; 357 + set_entry_t **set_ptr = get_set_from_obj(js, this_val); 358 + if (!set_ptr) return js_mkerr(js, "Invalid Set object"); 359 + 360 + const char *key_str = jsval_to_key(js, args[0]); 361 + 362 + set_entry_t *entry; 363 + HASH_FIND_STR(*set_ptr, key_str, entry); 364 + 365 + if (!entry) { 366 + entry = ant_calloc(sizeof(set_entry_t)); 367 + if (!entry) return js_mkerr(js, "out of memory"); 368 + entry->value = args[0]; 369 + entry->key = strdup(key_str); 370 + HASH_ADD_KEYPTR(hh, *set_ptr, entry->key, strlen(entry->key), entry); 371 + } 372 + 373 + return this_val; 374 + } 375 + 376 + static jsval_t set_has(ant_t *js, jsval_t *args, int nargs) { 377 + if (nargs < 1) return js_mkerr(js, "Set.has() requires 1 argument"); 378 + 379 + jsval_t this_val = js->this_val; 380 + set_entry_t **set_ptr = get_set_from_obj(js, this_val); 381 + if (!set_ptr) return js_false; 382 + 383 + const char *key_str = jsval_to_key(js, args[0]); 384 + 385 + set_entry_t *entry; 386 + HASH_FIND_STR(*set_ptr, key_str, entry); 387 + return js_bool(entry != NULL); 388 + } 389 + 390 + static jsval_t set_delete(ant_t *js, jsval_t *args, int nargs) { 391 + if (nargs < 1) return js_mkerr(js, "Set.delete() requires 1 argument"); 392 + 393 + jsval_t this_val = js->this_val; 394 + set_entry_t **set_ptr = get_set_from_obj(js, this_val); 395 + if (!set_ptr) return js_false; 396 + 397 + const char *key_str = jsval_to_key(js, args[0]); 398 + set_entry_t *entry; 399 + HASH_FIND_STR(*set_ptr, key_str, entry); 400 + 401 + if (entry) { 402 + HASH_DEL(*set_ptr, entry); 403 + free(entry->key); 404 + free(entry); 405 + return js_true; 406 + } 407 + return js_false; 408 + } 409 + 410 + static jsval_t set_clear(ant_t *js, jsval_t *args, int nargs) { 411 + (void)args; (void)nargs; 412 + jsval_t this_val = js->this_val; 413 + set_entry_t **set_ptr = get_set_from_obj(js, this_val); 414 + if (!set_ptr) return js_mkundef(); 415 + 416 + set_entry_t *entry, *tmp; 417 + HASH_ITER(hh, *set_ptr, entry, tmp) { 418 + HASH_DEL(*set_ptr, entry); 419 + free(entry->key); 420 + free(entry); 421 + } 422 + *set_ptr = NULL; 423 + 424 + return js_mkundef(); 425 + } 426 + 427 + static jsval_t set_size(ant_t *js, jsval_t *args, int nargs) { 428 + (void)args; (void)nargs; 429 + jsval_t this_val = js->this_val; 430 + set_entry_t **set_ptr = get_set_from_obj(js, this_val); 431 + if (!set_ptr) return js_mknum(0); 432 + 433 + return js_mknum((double)HASH_COUNT(*set_ptr)); 434 + } 435 + 436 + static jsval_t set_values(ant_t *js, jsval_t *args, int nargs) { 437 + (void)args; (void)nargs; 438 + return create_set_iterator(js, js->this_val, ITER_TYPE_SET_VALUES); 439 + } 440 + 441 + static jsval_t set_entries(ant_t *js, jsval_t *args, int nargs) { 442 + (void)args; (void)nargs; 443 + return create_set_iterator(js, js->this_val, ITER_TYPE_SET_ENTRIES); 444 + } 445 + 446 + static jsval_t set_iterator(ant_t *js, jsval_t *args, int nargs) { 447 + (void)args; (void)nargs; 448 + return create_set_iterator(js, js->this_val, ITER_TYPE_SET_VALUES); 449 + } 450 + 451 + static jsval_t set_forEach(ant_t *js, jsval_t *args, int nargs) { 452 + jsval_t this_val = js->this_val; 453 + set_entry_t **set_ptr = get_set_from_obj(js, this_val); 454 + 455 + if (nargs < 1 || vtype(args[0]) != T_FUNC) 456 + return js_mkerr(js, "forEach requires a callback function"); 457 + 458 + jsval_t callback = args[0]; 459 + 460 + if (set_ptr && *set_ptr) { 461 + set_entry_t *entry, *tmp; 462 + HASH_ITER(hh, *set_ptr, entry, tmp) { 463 + jsval_t call_args[3] = { entry->value, entry->value, this_val }; 464 + jsval_t result = js_call(js, callback, call_args, 3); 465 + if (is_err(result)) return result; 466 + } 467 + } 468 + 469 + return js_mkundef(); 470 + } 471 + 472 + static jsval_t weakmap_set(ant_t *js, jsval_t *args, int nargs) { 473 + if (nargs < 2) return js_mkerr(js, "WeakMap.set() requires 2 arguments"); 474 + 475 + jsval_t this_val = js->this_val; 476 + weakmap_entry_t **wm_ptr = get_weakmap_from_obj(js, this_val); 477 + if (!wm_ptr) return js_mkerr(js, "Invalid WeakMap object"); 478 + 479 + if (vtype(args[0]) != T_OBJ) 480 + return js_mkerr(js, "WeakMap key must be an object"); 481 + 482 + jsval_t key_obj = args[0]; 483 + 484 + weakmap_entry_t *entry; 485 + HASH_FIND(hh, *wm_ptr, &key_obj, sizeof(jsval_t), entry); 486 + if (entry) { 487 + entry->value = args[1]; 488 + } else { 489 + entry = ant_calloc(sizeof(weakmap_entry_t)); 490 + if (!entry) return js_mkerr(js, "out of memory"); 491 + entry->key_obj = key_obj; 492 + entry->value = args[1]; 493 + HASH_ADD(hh, *wm_ptr, key_obj, sizeof(jsval_t), entry); 494 + } 495 + 496 + return this_val; 497 + } 498 + 499 + static jsval_t weakmap_get(ant_t *js, jsval_t *args, int nargs) { 500 + if (nargs < 1) return js_mkerr(js, "WeakMap.get() requires 1 argument"); 501 + 502 + jsval_t this_val = js->this_val; 503 + weakmap_entry_t **wm_ptr = get_weakmap_from_obj(js, this_val); 504 + if (!wm_ptr) return js_mkundef(); 505 + 506 + if (vtype(args[0]) != T_OBJ) return js_mkundef(); 507 + 508 + jsval_t key_obj = args[0]; 509 + weakmap_entry_t *entry; 510 + HASH_FIND(hh, *wm_ptr, &key_obj, sizeof(jsval_t), entry); 511 + return entry ? entry->value : js_mkundef(); 512 + } 513 + 514 + static jsval_t weakmap_has(ant_t *js, jsval_t *args, int nargs) { 515 + if (nargs < 1) return js_mkerr(js, "WeakMap.has() requires 1 argument"); 516 + 517 + jsval_t this_val = js->this_val; 518 + weakmap_entry_t **wm_ptr = get_weakmap_from_obj(js, this_val); 519 + if (!wm_ptr) return js_false; 520 + 521 + if (vtype(args[0]) != T_OBJ) return js_false; 522 + 523 + jsval_t key_obj = args[0]; 524 + weakmap_entry_t *entry; 525 + HASH_FIND(hh, *wm_ptr, &key_obj, sizeof(jsval_t), entry); 526 + return js_bool(entry != NULL); 527 + } 528 + 529 + static jsval_t weakmap_delete(ant_t *js, jsval_t *args, int nargs) { 530 + if (nargs < 1) return js_mkerr(js, "WeakMap.delete() requires 1 argument"); 531 + 532 + jsval_t this_val = js->this_val; 533 + weakmap_entry_t **wm_ptr = get_weakmap_from_obj(js, this_val); 534 + if (!wm_ptr) return js_false; 535 + 536 + if (vtype(args[0]) != T_OBJ) return js_false; 537 + 538 + jsval_t key_obj = args[0]; 539 + weakmap_entry_t *entry; 540 + HASH_FIND(hh, *wm_ptr, &key_obj, sizeof(jsval_t), entry); 541 + if (entry) { 542 + HASH_DEL(*wm_ptr, entry); 543 + free(entry); 544 + return js_true; 545 + } 546 + return js_false; 547 + } 548 + 549 + static jsval_t weakset_add(ant_t *js, jsval_t *args, int nargs) { 550 + if (nargs < 1) return js_mkerr(js, "WeakSet.add() requires 1 argument"); 551 + 552 + jsval_t this_val = js->this_val; 553 + weakset_entry_t **ws_ptr = get_weakset_from_obj(js, this_val); 554 + if (!ws_ptr) return js_mkerr(js, "Invalid WeakSet object"); 555 + 556 + if (vtype(args[0]) != T_OBJ) 557 + return js_mkerr(js, "WeakSet value must be an object"); 558 + 559 + jsval_t value_obj = args[0]; 560 + 561 + weakset_entry_t *entry; 562 + HASH_FIND(hh, *ws_ptr, &value_obj, sizeof(jsval_t), entry); 563 + 564 + if (!entry) { 565 + entry = ant_calloc(sizeof(weakset_entry_t)); 566 + if (!entry) return js_mkerr(js, "out of memory"); 567 + entry->value_obj = value_obj; 568 + HASH_ADD(hh, *ws_ptr, value_obj, sizeof(jsval_t), entry); 569 + } 570 + 571 + return this_val; 572 + } 573 + 574 + static jsval_t weakset_has(ant_t *js, jsval_t *args, int nargs) { 575 + if (nargs < 1) return js_mkerr(js, "WeakSet.has() requires 1 argument"); 576 + 577 + jsval_t this_val = js->this_val; 578 + weakset_entry_t **ws_ptr = get_weakset_from_obj(js, this_val); 579 + if (!ws_ptr) return js_false; 580 + 581 + if (vtype(args[0]) != T_OBJ) return js_false; 582 + 583 + jsval_t value_obj = args[0]; 584 + weakset_entry_t *entry; 585 + HASH_FIND(hh, *ws_ptr, &value_obj, sizeof(jsval_t), entry); 586 + return js_bool(entry != NULL); 587 + } 588 + 589 + static jsval_t weakset_delete(ant_t *js, jsval_t *args, int nargs) { 590 + if (nargs < 1) return js_mkerr(js, "WeakSet.delete() requires 1 argument"); 591 + 592 + jsval_t this_val = js->this_val; 593 + weakset_entry_t **ws_ptr = get_weakset_from_obj(js, this_val); 594 + if (!ws_ptr) return js_false; 595 + 596 + if (vtype(args[0]) != T_OBJ) return js_false; 597 + 598 + jsval_t value_obj = args[0]; 599 + weakset_entry_t *entry; 600 + HASH_FIND(hh, *ws_ptr, &value_obj, sizeof(jsval_t), entry); 601 + 602 + if (entry) { 603 + HASH_DEL(*ws_ptr, entry); 604 + free(entry); 605 + return js_true; 606 + } 607 + return js_false; 608 + } 609 + 610 + static jsval_t builtin_WeakRef(ant_t *js, jsval_t *args, int nargs) { 611 + if (nargs < 1 || vtype(args[0]) != T_OBJ) { 612 + return js_mkerr(js, "WeakRef target must be an object"); 613 + } 614 + 615 + jsval_t wr_obj = js_mkobj(js); 616 + jsval_t wr_proto = js_get_ctor_proto(js, "WeakRef", 7); 617 + if (is_special_object(wr_proto)) js_set_proto(js, wr_obj, wr_proto); 618 + js_set_slot(js, wr_obj, SLOT_DATA, args[0]); 619 + 620 + return wr_obj; 621 + } 622 + 623 + static jsval_t weakref_deref(ant_t *js, jsval_t *args, int nargs) { 624 + (void)args; (void)nargs; 625 + jsval_t this_val = js->this_val; 626 + if (vtype(this_val) != T_OBJ) return js_mkundef(); 627 + 628 + jsval_t target = js_get_slot(js, this_val, SLOT_DATA); 629 + if (vtype(target) != T_OBJ) return js_mkundef(); 630 + 631 + return target; 632 + } 633 + 634 + static jsval_t builtin_FinalizationRegistry(ant_t *js, jsval_t *args, int nargs) { 635 + if (nargs < 1 || (vtype(args[0]) != T_FUNC && vtype(args[0]) != T_CFUNC)) { 636 + return js_mkerr(js, "FinalizationRegistry callback must be a function"); 637 + } 638 + 639 + jsval_t fr_obj = js_mkobj(js); 640 + jsval_t fr_proto = js_get_ctor_proto(js, "FinalizationRegistry", 20); 641 + if (is_special_object(fr_proto)) js_set_proto(js, fr_obj, fr_proto); 642 + 643 + js_set_slot(js, fr_obj, SLOT_DATA, args[0]); 644 + js_set_slot(js, fr_obj, SLOT_MAP, mkarr(js)); 645 + 646 + return fr_obj; 647 + } 648 + 649 + static jsval_t finreg_register(ant_t *js, jsval_t *args, int nargs) { 650 + jsval_t this_val = js->this_val; 651 + if (vtype(this_val) != T_OBJ) return js_mkundef(); 652 + 653 + if (nargs < 1 || vtype(args[0]) != T_OBJ) { 654 + return js_mkerr(js, "FinalizationRegistry.register target must be an object"); 655 + } 656 + 657 + jsval_t target = args[0]; 658 + jsval_t held_value = nargs > 1 ? args[1] : js_mkundef(); 659 + jsval_t unregister_token = nargs > 2 ? args[2] : js_mkundef(); 660 + 661 + if (vdata(target) == vdata(held_value) && vtype(held_value) == T_OBJ) { 662 + return js_mkerr(js, "target and held value must not be the same"); 663 + } 664 + 665 + jsval_t registrations = js_get_slot(js, this_val, SLOT_MAP); 666 + if (vtype(registrations) != T_ARR) return js_mkundef(); 667 + 668 + jsval_t entry = mkarr(js); 669 + jsoff_t len = js_arr_len(js, registrations); 670 + 671 + char idx[16]; 672 + size_t idx_len = uint_to_str(idx, sizeof(idx), 0); 673 + setprop(js, entry, js_mkstr(js, idx, idx_len), target); 674 + idx_len = uint_to_str(idx, sizeof(idx), 1); 675 + setprop(js, entry, js_mkstr(js, idx, idx_len), held_value); 676 + idx_len = uint_to_str(idx, sizeof(idx), 2); 677 + setprop(js, entry, js_mkstr(js, idx, idx_len), unregister_token); 678 + setprop(js, entry, js_mkstr(js, "length", 6), tov(3.0)); 679 + 680 + idx_len = uint_to_str(idx, sizeof(idx), len); 681 + setprop(js, registrations, js_mkstr(js, idx, idx_len), entry); 682 + setprop(js, registrations, js_mkstr(js, "length", 6), tov((double)(len + 1))); 683 + 684 + return js_mkundef(); 685 + } 686 + 687 + static jsval_t finreg_unregister(ant_t *js, jsval_t *args, int nargs) { 688 + jsval_t this_val = js->this_val; 689 + if (vtype(this_val) != T_OBJ) return js_false; 690 + 691 + if (nargs < 1 || vtype(args[0]) != T_OBJ) { 692 + return js_mkerr(js, "FinalizationRegistry.unregister token must be an object"); 693 + } 694 + 695 + jsval_t token = args[0]; 696 + jsval_t registrations = js_get_slot(js, this_val, SLOT_MAP); 697 + if (vtype(registrations) != T_ARR) return js_false; 698 + 699 + jsoff_t len = js_arr_len(js, registrations); 700 + bool removed = false; 701 + 702 + for (jsoff_t i = 0; i < len; i++) { 703 + jsval_t entry = js_arr_get(js, registrations, i); 704 + if (vtype(entry) != T_ARR) continue; 705 + jsval_t entry_token = js_arr_get(js, entry, 2); 706 + if (vtype(entry_token) == T_OBJ && vdata(entry_token) == vdata(token)) { 707 + char idx[16]; 708 + size_t idx_len = uint_to_str(idx, sizeof(idx), i); 709 + setprop(js, registrations, js_mkstr(js, idx, idx_len), js_mkundef()); 710 + removed = true; 711 + } 712 + } 713 + 714 + return js_bool(removed); 715 + } 716 + 717 + static jsval_t builtin_Map(ant_t *js, jsval_t *args, int nargs) { 718 + jsval_t map_obj = js_mkobj(js); 719 + 720 + jsval_t map_proto = js_get_ctor_proto(js, "Map", 3); 721 + if (is_special_object(map_proto)) js_set_proto(js, map_obj, map_proto); 722 + 723 + map_entry_t **map_head = ant_calloc(sizeof(map_entry_t *)); 724 + if (!map_head) return js_mkerr(js, "out of memory"); 725 + *map_head = NULL; 726 + 727 + register_map(map_head); 728 + js_set_slot(js, map_obj, SLOT_MAP, ANT_PTR(map_head)); 729 + 730 + if (nargs == 0 || vtype(args[0]) != T_ARR) return map_obj; 731 + 732 + jsval_t iterable = args[0]; 733 + jsoff_t length = js_arr_len(js, iterable); 734 + 735 + for (jsoff_t i = 0; i < length; i++) { 736 + jsval_t entry = js_arr_get(js, iterable, i); 737 + if (vtype(entry) != T_ARR) continue; 738 + 739 + jsoff_t entry_len = js_arr_len(js, entry); 740 + if (entry_len < 2) continue; 741 + 742 + jsval_t key = js_arr_get(js, entry, 0); 743 + jsval_t value = js_arr_get(js, entry, 1); 744 + const char *key_str = jsval_to_key(js, key); 745 + 746 + map_entry_t *map_entry; 747 + HASH_FIND_STR(*map_head, key_str, map_entry); 748 + if (map_entry) { 749 + map_entry->value = value; 750 + continue; 751 + } 752 + 753 + map_entry = ant_calloc(sizeof(map_entry_t)); 754 + if (!map_entry) return js_mkerr(js, "out of memory"); 755 + map_entry->key = strdup(key_str); 756 + map_entry->value = value; 757 + HASH_ADD_STR(*map_head, key, map_entry); 758 + } 759 + 760 + return map_obj; 761 + } 762 + 763 + static jsval_t builtin_Set(ant_t *js, jsval_t *args, int nargs) { 764 + jsval_t set_obj = js_mkobj(js); 765 + 766 + jsval_t set_proto = js_get_ctor_proto(js, "Set", 3); 767 + if (is_special_object(set_proto)) js_set_proto(js, set_obj, set_proto); 768 + 769 + set_entry_t **set_head = ant_calloc(sizeof(set_entry_t *)); 770 + if (!set_head) return js_mkerr(js, "out of memory"); 771 + *set_head = NULL; 772 + 773 + register_set(set_head); 774 + js_set_slot(js, set_obj, SLOT_SET, ANT_PTR(set_head)); 775 + 776 + if (nargs == 0 || vtype(args[0]) != T_ARR) return set_obj; 777 + 778 + jsval_t iterable = args[0]; 779 + jsoff_t length = js_arr_len(js, iterable); 780 + 781 + for (jsoff_t i = 0; i < length; i++) { 782 + jsval_t value = js_arr_get(js, iterable, i); 783 + const char *key_str = jsval_to_key(js, value); 784 + 785 + set_entry_t *entry; 786 + HASH_FIND_STR(*set_head, key_str, entry); 787 + if (entry) continue; 788 + 789 + entry = ant_calloc(sizeof(set_entry_t)); 790 + if (!entry) return js_mkerr(js, "out of memory"); 791 + entry->value = value; 792 + entry->key = strdup(key_str); 793 + HASH_ADD_KEYPTR(hh, *set_head, entry->key, strlen(entry->key), entry); 794 + } 795 + 796 + return set_obj; 797 + } 798 + 799 + static jsval_t builtin_WeakMap(ant_t *js, jsval_t *args, int nargs) { 800 + jsval_t wm_obj = js_mkobj(js); 801 + 802 + jsval_t wm_proto = js_get_ctor_proto(js, "WeakMap", 7); 803 + if (is_special_object(wm_proto)) js_set_proto(js, wm_obj, wm_proto); 804 + 805 + weakmap_entry_t **wm_head = ant_calloc(sizeof(weakmap_entry_t *)); 806 + if (!wm_head) return js_mkerr(js, "out of memory"); 807 + *wm_head = NULL; 808 + 809 + js_set_slot(js, wm_obj, SLOT_DATA, ANT_PTR(wm_head)); 810 + 811 + if (nargs == 0 || vtype(args[0]) != T_ARR) return wm_obj; 812 + 813 + jsval_t iterable = args[0]; 814 + jsoff_t length = js_arr_len(js, iterable); 815 + 816 + for (jsoff_t i = 0; i < length; i++) { 817 + jsval_t entry = js_arr_get(js, iterable, i); 818 + if (vtype(entry) != T_ARR) continue; 819 + 820 + jsoff_t entry_len = js_arr_len(js, entry); 821 + if (entry_len < 2) continue; 822 + 823 + jsval_t key = js_arr_get(js, entry, 0); 824 + jsval_t value = js_arr_get(js, entry, 1); 825 + 826 + if (vtype(key) != T_OBJ) return js_mkerr(js, "WeakMap key must be an object"); 827 + 828 + weakmap_entry_t *wm_entry; 829 + HASH_FIND(hh, *wm_head, &key, sizeof(jsval_t), wm_entry); 830 + if (wm_entry) { 831 + wm_entry->value = value; 832 + continue; 833 + } 834 + 835 + wm_entry = ant_calloc(sizeof(weakmap_entry_t)); 836 + if (!wm_entry) return js_mkerr(js, "out of memory"); 837 + wm_entry->key_obj = key; 838 + wm_entry->value = value; 839 + HASH_ADD(hh, *wm_head, key_obj, sizeof(jsval_t), wm_entry); 840 + } 841 + 842 + return wm_obj; 843 + } 844 + 845 + static jsval_t builtin_WeakSet(ant_t *js, jsval_t *args, int nargs) { 846 + jsval_t ws_obj = js_mkobj(js); 847 + 848 + jsval_t ws_proto = js_get_ctor_proto(js, "WeakSet", 7); 849 + if (is_special_object(ws_proto)) js_set_proto(js, ws_obj, ws_proto); 850 + 851 + weakset_entry_t **ws_head = ant_calloc(sizeof(weakset_entry_t *)); 852 + if (!ws_head) return js_mkerr(js, "out of memory"); 853 + *ws_head = NULL; 854 + 855 + js_set_slot(js, ws_obj, SLOT_DATA, ANT_PTR(ws_head)); 856 + 857 + if (nargs == 0 || vtype(args[0]) != T_ARR) return ws_obj; 858 + 859 + jsval_t iterable = args[0]; 860 + jsoff_t length = js_arr_len(js, iterable); 861 + 862 + for (jsoff_t i = 0; i < length; i++) { 863 + jsval_t value = js_arr_get(js, iterable, i); 864 + 865 + if (vtype(value) != T_OBJ) return js_mkerr(js, "WeakSet value must be an object"); 866 + 867 + weakset_entry_t *entry; 868 + HASH_FIND(hh, *ws_head, &value, sizeof(jsval_t), entry); 869 + if (entry) continue; 870 + 871 + entry = ant_calloc(sizeof(weakset_entry_t)); 872 + if (!entry) return js_mkerr(js, "out of memory"); 873 + entry->value_obj = value; 874 + HASH_ADD(hh, *ws_head, value_obj, sizeof(jsval_t), entry); 875 + } 876 + 877 + return ws_obj; 878 + } 879 + 880 + void init_collections_module(void) { 881 + ant_t *js = rt->js; 882 + jsval_t glob = js_glob(js); 883 + 884 + const char *iter_key = get_iterator_sym_key(); 885 + const char *toStringTag_key = get_toStringTag_sym_key(); 886 + 887 + jsval_t map_proto = js_mkobj(js); 888 + js_set(js, map_proto, "set", js_mkfun(map_set)); 889 + js_set(js, map_proto, "get", js_mkfun(map_get)); 890 + js_set(js, map_proto, "has", js_mkfun(map_has)); 891 + js_set(js, map_proto, "delete", js_mkfun(map_delete)); 892 + js_set(js, map_proto, "clear", js_mkfun(map_clear)); 893 + js_set(js, map_proto, "size", js_mkfun(map_size)); 894 + js_set(js, map_proto, "entries", js_mkfun(map_entries)); 895 + js_set(js, map_proto, "keys", js_mkfun(map_keys)); 896 + js_set(js, map_proto, "values", js_mkfun(map_values)); 897 + js_set(js, map_proto, "forEach", js_mkfun(map_forEach)); 898 + js_set(js, map_proto, iter_key, js_mkfun(map_iterator)); 899 + js_set(js, map_proto, toStringTag_key, js_mkstr(js, "Map", 3)); 900 + 901 + jsval_t map_ctor = js_mkobj(js); 902 + js_set_slot(js, map_ctor, SLOT_CFUNC, js_mkfun(builtin_Map)); 903 + js_mkprop_fast(js, map_ctor, "prototype", 9, map_proto); 904 + js_mkprop_fast(js, map_ctor, "name", 4, ANT_STRING("Map")); 905 + js_set_descriptor(js, map_ctor, "name", 4, 0); 906 + js_set(js, glob, "Map", js_obj_to_func(map_ctor)); 907 + 908 + jsval_t set_proto = js_mkobj(js); 909 + js_set(js, set_proto, "add", js_mkfun(set_add)); 910 + js_set(js, set_proto, "has", js_mkfun(set_has)); 911 + js_set(js, set_proto, "delete", js_mkfun(set_delete)); 912 + js_set(js, set_proto, "clear", js_mkfun(set_clear)); 913 + js_set(js, set_proto, "size", js_mkfun(set_size)); 914 + js_set(js, set_proto, "values", js_mkfun(set_values)); 915 + js_set(js, set_proto, "keys", js_mkfun(set_values)); 916 + js_set(js, set_proto, "entries", js_mkfun(set_entries)); 917 + js_set(js, set_proto, "forEach", js_mkfun(set_forEach)); 918 + js_set(js, set_proto, iter_key, js_mkfun(set_iterator)); 919 + js_set(js, set_proto, toStringTag_key, js_mkstr(js, "Set", 3)); 920 + 921 + jsval_t set_ctor = js_mkobj(js); 922 + js_set_slot(js, set_ctor, SLOT_CFUNC, js_mkfun(builtin_Set)); 923 + js_mkprop_fast(js, set_ctor, "prototype", 9, set_proto); 924 + js_mkprop_fast(js, set_ctor, "name", 4, ANT_STRING("Set")); 925 + js_set_descriptor(js, set_ctor, "name", 4, 0); 926 + js_set(js, glob, "Set", js_obj_to_func(set_ctor)); 927 + 928 + jsval_t weakmap_proto = js_mkobj(js); 929 + js_set(js, weakmap_proto, "set", js_mkfun(weakmap_set)); 930 + js_set(js, weakmap_proto, "get", js_mkfun(weakmap_get)); 931 + js_set(js, weakmap_proto, "has", js_mkfun(weakmap_has)); 932 + js_set(js, weakmap_proto, "delete", js_mkfun(weakmap_delete)); 933 + js_set(js, weakmap_proto, toStringTag_key, js_mkstr(js, "WeakMap", 7)); 934 + 935 + jsval_t weakmap_ctor = js_mkobj(js); 936 + js_set_slot(js, weakmap_ctor, SLOT_CFUNC, js_mkfun(builtin_WeakMap)); 937 + js_mkprop_fast(js, weakmap_ctor, "prototype", 9, weakmap_proto); 938 + js_mkprop_fast(js, weakmap_ctor, "name", 4, ANT_STRING("WeakMap")); 939 + js_set_descriptor(js, weakmap_ctor, "name", 4, 0); 940 + js_set(js, glob, "WeakMap", js_obj_to_func(weakmap_ctor)); 941 + 942 + jsval_t weakset_proto = js_mkobj(js); 943 + js_set(js, weakset_proto, "add", js_mkfun(weakset_add)); 944 + js_set(js, weakset_proto, "has", js_mkfun(weakset_has)); 945 + js_set(js, weakset_proto, "delete", js_mkfun(weakset_delete)); 946 + js_set(js, weakset_proto, toStringTag_key, js_mkstr(js, "WeakSet", 7)); 947 + 948 + jsval_t weakset_ctor = js_mkobj(js); 949 + js_set_slot(js, weakset_ctor, SLOT_CFUNC, js_mkfun(builtin_WeakSet)); 950 + js_mkprop_fast(js, weakset_ctor, "prototype", 9, weakset_proto); 951 + js_mkprop_fast(js, weakset_ctor, "name", 4, ANT_STRING("WeakSet")); 952 + js_set_descriptor(js, weakset_ctor, "name", 4, 0); 953 + js_set(js, glob, "WeakSet", js_obj_to_func(weakset_ctor)); 954 + 955 + jsval_t weakref_proto = js_mkobj(js); 956 + js_set(js, weakref_proto, "deref", js_mkfun(weakref_deref)); 957 + js_set(js, weakref_proto, toStringTag_key, js_mkstr(js, "WeakRef", 7)); 958 + 959 + jsval_t weakref_ctor = js_mkobj(js); 960 + js_set_slot(js, weakref_ctor, SLOT_CFUNC, js_mkfun(builtin_WeakRef)); 961 + js_mkprop_fast(js, weakref_ctor, "prototype", 9, weakref_proto); 962 + js_mkprop_fast(js, weakref_ctor, "name", 4, ANT_STRING("WeakRef")); 963 + js_set_descriptor(js, weakref_ctor, "name", 4, 0); 964 + js_set(js, glob, "WeakRef", js_obj_to_func(weakref_ctor)); 965 + 966 + jsval_t finreg_proto = js_mkobj(js); 967 + js_set(js, finreg_proto, "register", js_mkfun(finreg_register)); 968 + js_set(js, finreg_proto, "unregister", js_mkfun(finreg_unregister)); 969 + js_set(js, finreg_proto, toStringTag_key, js_mkstr(js, "FinalizationRegistry", 20)); 970 + 971 + jsval_t finreg_ctor = js_mkobj(js); 972 + js_set_slot(js, finreg_ctor, SLOT_CFUNC, js_mkfun(builtin_FinalizationRegistry)); 973 + js_mkprop_fast(js, finreg_ctor, "prototype", 9, finreg_proto); 974 + js_mkprop_fast(js, finreg_ctor, "name", 4, ANT_STRING("FinalizationRegistry")); 975 + js_set_descriptor(js, finreg_ctor, "name", 4, 0); 976 + js_set(js, glob, "FinalizationRegistry", js_obj_to_func(finreg_ctor)); 977 + } 978 + 979 + void collections_gc_update_roots(void (*op_val)(void *, jsval_t *), void *ctx) { 980 + for (size_t i = 0; i < map_registry_count; i++) { 981 + map_entry_t **head = map_registry_heads[i]; 982 + if (head && *head) { 983 + map_entry_t *entry, *tmp; 984 + HASH_ITER(hh, *head, entry, tmp) op_val(ctx, &entry->value); 985 + } 986 + } 987 + 988 + for (size_t i = 0; i < set_registry_count; i++) { 989 + set_entry_t **head = set_registry_heads[i]; 990 + if (head && *head) { 991 + set_entry_t *entry, *tmp; 992 + HASH_ITER(hh, *head, entry, tmp) op_val(ctx, &entry->value); 993 + } 994 + } 995 + } 996 + 997 + #define CLEANUP_REGISTRY(type, heads, count, cap) do { \ 998 + for (size_t i = 0; i < count; i++) { \ 999 + type##_entry_t **head = heads[i]; \ 1000 + if (head && *head) { \ 1001 + type##_entry_t *entry, *tmp; \ 1002 + HASH_ITER(hh, *head, entry, tmp) { \ 1003 + HASH_DEL(*head, entry); \ 1004 + free(entry->key); \ 1005 + free(entry); \ 1006 + } \ 1007 + } \ 1008 + free(head); \ 1009 + } \ 1010 + free(heads); \ 1011 + heads = NULL; \ 1012 + count = 0; \ 1013 + cap = 0; \ 1014 + } while(0) 1015 + 1016 + void cleanup_collections_module(void) { 1017 + CLEANUP_REGISTRY(map, map_registry_heads, map_registry_count, map_registry_cap); 1018 + CLEANUP_REGISTRY(set, set_registry_heads, set_registry_count, set_registry_cap); 1019 + } 1020 + 1021 + #undef CLEANUP_REGISTRY
-8
src/modules/symbol.c
··· 195 195 jsval_t string_ctor = js_get(js, js_glob(js), "String"); 196 196 jsval_t string_proto = js_get(js, string_ctor, "prototype"); 197 197 js_set(js, string_proto, g_iter_sym_key, js_mkfun(string_iterator)); 198 - 199 - jsval_t map_ctor = js_get(js, js_glob(js), "Map"); 200 - jsval_t map_proto = js_get(js, map_ctor, "prototype"); 201 - js_set(js, map_proto, g_toStringTag_sym_key, js_mkstr(js, "Map", 3)); 202 - 203 - jsval_t set_ctor = js_get(js, js_glob(js), "Set"); 204 - jsval_t set_proto = js_get(js, set_ctor, "prototype"); 205 - js_set(js, set_proto, g_toStringTag_sym_key, js_mkstr(js, "Set", 3)); 206 198 }