···534534compat-table/es6/Map.Symbol.species.js: OK
535535compat-table/es6/Map.constructor-accepts-null.js: OK
536536compat-table/es6/Map.constructor-arguments.js: OK
537537-compat-table/es6/Map.constructor-invokes-set.js: failed
537537+compat-table/es6/Map.constructor-invokes-set.js: OK
538538compat-table/es6/Map.constructor-requires-new.js: OK
539539compat-table/es6/Map.iterator-closing.js: OK
540540compat-table/es6/Map.iterator-prototype-chain.js: OK
···651651compat-table/es6/Set.Symbol.species.js: OK
652652compat-table/es6/Set.constructor-accepts-null.js: OK
653653compat-table/es6/Set.constructor-arguments.js: OK
654654-compat-table/es6/Set.constructor-invokes-add.js: failed
654654+compat-table/es6/Set.constructor-invokes-add.js: OK
655655compat-table/es6/Set.constructor-requires-new.js: OK
656656-compat-table/es6/Set.iterator-closing.js: failed
656656+compat-table/es6/Set.iterator-closing.js: OK
657657compat-table/es6/Set.iterator-prototype-chain.js: OK
658658compat-table/es6/Set.js: OK
659659compat-table/es6/Set.prototype-not-instance.js: OK
···694694compat-table/es6/WeakMap.accept-primitives.js: OK
695695compat-table/es6/WeakMap.constructor-accepts-null.js: OK
696696compat-table/es6/WeakMap.constructor-arguments.js: OK
697697-compat-table/es6/WeakMap.constructor-invokes-set.js: failed
697697+compat-table/es6/WeakMap.constructor-invokes-set.js: OK
698698compat-table/es6/WeakMap.constructor-requires-new.js: OK
699699compat-table/es6/WeakMap.frozen-keys.js: OK
700700compat-table/es6/WeakMap.iterator-closing.js: OK
···706706compat-table/es6/WeakSet.accept-primitives.js: OK
707707compat-table/es6/WeakSet.constructor-accepts-null.js: OK
708708compat-table/es6/WeakSet.constructor-arguments.js: OK
709709-compat-table/es6/WeakSet.constructor-invokes-add.js: failed
709709+compat-table/es6/WeakSet.constructor-invokes-add.js: OK
710710compat-table/es6/WeakSet.constructor-requires-new.js: OK
711711compat-table/es6/WeakSet.iterator-closing.js: OK
712712compat-table/es6/WeakSet.js: OK
+213-128
src/modules/collections.c
···150150}
151151152152static bool set_store_entry(ant_t *js, set_entry_t **set_ptr, ant_value_t value) {
153153- ant_value_t stored_value = normalize_map_key(value); collection_key_t key;
153153+ ant_value_t stored_value = normalize_map_key(value);
154154+155155+ collection_key_t key;
154156 if (!collection_key_init(js, stored_value, &key)) return false;
155157156158 set_entry_t *entry = NULL;
···181183 collection_key_free(&key);
182184183185 return true;
184184-}
185185-186186-static ant_value_t map_init_from_iterable(ant_t *js, map_entry_t **map_head, ant_value_t iterable) {
187187- js_iter_t it;
188188- if (!js_iter_open(js, iterable, &it)) {
189189- return js_mkerr_typed(js, JS_ERR_TYPE, "Map constructor argument is not iterable");
190190- }
191191-192192- ant_value_t entry;
193193- while (js_iter_next(js, &it, &entry)) {
194194- uint8_t entry_t = vtype(entry);
195195- if (entry_t != T_ARR && entry_t != T_OBJ) {
196196- js_iter_close(js, &it);
197197- return js_mkerr_typed(js, JS_ERR_TYPE, "Map iterable entries must be pair sequences");
198198- }
199199-200200- ant_offset_t entry_len = js_arr_len(js, entry);
201201- if (entry_len < 2) {
202202- js_iter_close(js, &it);
203203- return js_mkerr_typed(js, JS_ERR_TYPE, "Map iterable entries must have at least 2 items");
204204- }
205205-206206- ant_value_t key = normalize_map_key(js_arr_get(js, entry, 0));
207207- ant_value_t value = js_arr_get(js, entry, 1);
208208- if (!map_store_entry(js, map_head, key, key, value)) {
209209- js_iter_close(js, &it);
210210- return js_mkerr(js, "out of memory");
211211- }}
212212-213213- return js_mkundef();
214214-}
215215-216216-static ant_value_t set_init_from_iterable(ant_t *js, set_entry_t **set_head, ant_value_t iterable) {
217217- js_iter_t it;
218218- if (!js_iter_open(js, iterable, &it)) {
219219- return js_mkerr_typed(js, JS_ERR_TYPE, "Set constructor argument is not iterable");
220220- }
221221-222222- ant_value_t value;
223223- while (js_iter_next(js, &it, &value)) if (!set_store_entry(js, set_head, value)) {
224224- js_iter_close(js, &it);
225225- return js_mkerr(js, "out of memory");
226226- }
227227-228228- return js_mkundef();
229229-}
230230-231231-static ant_value_t weakmap_init_from_iterable(ant_t *js, weakmap_entry_t **wm_head, ant_value_t iterable) {
232232- js_iter_t it;
233233- if (!js_iter_open(js, iterable, &it)) {
234234- return js_mkerr_typed(js, JS_ERR_TYPE, "WeakMap constructor argument is not iterable");
235235- }
236236-237237- ant_value_t entry;
238238- while (js_iter_next(js, &it, &entry)) {
239239- uint8_t entry_t = vtype(entry);
240240- if (entry_t != T_ARR && entry_t != T_OBJ) {
241241- js_iter_close(js, &it);
242242- return js_mkerr_typed(js, JS_ERR_TYPE, "WeakMap iterable entries must be pair sequences");
243243- }
244244-245245- ant_offset_t entry_len = js_arr_len(js, entry);
246246- if (entry_len < 2) {
247247- js_iter_close(js, &it);
248248- return js_mkerr_typed(js, JS_ERR_TYPE, "WeakMap iterable entries must have at least 2 items");
249249- }
250250-251251- ant_value_t key = js_arr_get(js, entry, 0);
252252- ant_value_t value = js_arr_get(js, entry, 1);
253253- if (!is_object_type(key)) {
254254- js_iter_close(js, &it);
255255- return js_mkerr(js, "WeakMap key must be an object");
256256- }
257257-258258- weakmap_entry_t *wm_entry;
259259- HASH_FIND(hh, *wm_head, &key, sizeof(ant_value_t), wm_entry);
260260- if (wm_entry) {
261261- wm_entry->value = value;
262262- continue;
263263- }
264264-265265- wm_entry = ant_calloc(sizeof(weakmap_entry_t));
266266- if (!wm_entry) {
267267- js_iter_close(js, &it);
268268- return js_mkerr(js, "out of memory");
269269- }
270270-271271- wm_entry->key_obj = key;
272272- wm_entry->value = value;
273273- HASH_ADD(hh, *wm_head, key_obj, sizeof(ant_value_t), wm_entry);
274274- }
275275-276276- return js_mkundef();
277277-}
278278-279279-static ant_value_t weakset_init_from_iterable(ant_t *js, weakset_entry_t **ws_head, ant_value_t iterable) {
280280- js_iter_t it;
281281- if (!js_iter_open(js, iterable, &it)) {
282282- return js_mkerr_typed(js, JS_ERR_TYPE, "WeakSet constructor argument is not iterable");
283283- }
284284-285285- ant_value_t value;
286286- while (js_iter_next(js, &it, &value)) {
287287- if (!is_object_type(value)) {
288288- js_iter_close(js, &it);
289289- return js_mkerr(js, "WeakSet value must be an object");
290290- }
291291-292292- weakset_entry_t *entry;
293293- HASH_FIND(hh, *ws_head, &value, sizeof(ant_value_t), entry);
294294- if (entry) continue;
295295-296296- entry = ant_calloc(sizeof(weakset_entry_t));
297297- if (!entry) {
298298- js_iter_close(js, &it);
299299- return js_mkerr(js, "out of memory");
300300- }
301301-302302- entry->value_obj = value;
303303- HASH_ADD(hh, *ws_head, value_obj, sizeof(ant_value_t), entry);
304304- }
305305-306306- return js_mkundef();
307186}
308187309188map_entry_t **get_map_from_obj(ant_value_t obj) {
···14241303 return map_obj;
14251304}
1426130513061306+static bool is_original_collection_adder(ant_value_t adder, ant_cfunc_t fn) {
13071307+ return vtype(adder) == T_CFUNC && js_cfunc_same_entrypoint(adder, fn);
13081308+}
13091309+13101310+static ant_value_t map_init_from_iterable(ant_t *js, ant_value_t map_obj, map_entry_t **map_head, ant_value_t iterable) {
13111311+ ant_value_t adder = js_getprop_fallback(js, map_obj, "set");
13121312+ if (is_err(adder)) return adder;
13131313+ if (!is_callable(adder))
13141314+ return js_mkerr_typed(js, JS_ERR_TYPE, "Map constructor requires a callable set method");
13151315+13161316+ bool use_fast_path
13171317+ = is_original_collection_adder(adder, map_set);
13181318+13191319+ js_iter_t it;
13201320+ if (!js_iter_open(js, iterable, &it))
13211321+ return js_mkerr_typed(js, JS_ERR_TYPE, "Map constructor argument is not iterable");
13221322+13231323+ ant_value_t result = js_mkundef();
13241324+ ant_value_t entry;
13251325+13261326+ while (js_iter_next(js, &it, &entry)) {
13271327+ uint8_t entry_t = vtype(entry);
13281328+ if (entry_t != T_ARR && entry_t != T_OBJ) {
13291329+ result = js_mkerr_typed(js, JS_ERR_TYPE, "Map iterable entries must be pair sequences");
13301330+ goto close_iter;
13311331+ }
13321332+13331333+ ant_offset_t entry_len = js_arr_len(js, entry);
13341334+ if (entry_len < 2) {
13351335+ result = js_mkerr_typed(js, JS_ERR_TYPE, "Map iterable entries must have at least 2 items");
13361336+ goto close_iter;
13371337+ }
13381338+13391339+ if (use_fast_path) {
13401340+ ant_value_t key = normalize_map_key(js_arr_get(js, entry, 0));
13411341+ ant_value_t value = js_arr_get(js, entry, 1);
13421342+ if (!map_store_entry(js, map_head, key, key, value)) {
13431343+ result = js_mkerr(js, "out of memory");
13441344+ goto close_iter;
13451345+ }
13461346+ continue;
13471347+ }
13481348+13491349+ ant_value_t call_args[2] = { js_arr_get(js, entry, 0), js_arr_get(js, entry, 1) };
13501350+ result = sv_vm_call(js->vm, js, adder, map_obj, call_args, 2, NULL, false);
13511351+ if (is_err(result)) goto close_iter;
13521352+ }
13531353+13541354+ return result;
13551355+13561356+close_iter:
13571357+ js_iter_close(js, &it);
13581358+ return result;
13591359+}
13601360+13611361+static ant_value_t set_init_from_iterable(ant_t *js, ant_value_t set_obj, set_entry_t **set_head, ant_value_t iterable) {
13621362+ ant_value_t adder = js_getprop_fallback(js, set_obj, "add");
13631363+ if (is_err(adder)) return adder;
13641364+ if (!is_callable(adder))
13651365+ return js_mkerr_typed(js, JS_ERR_TYPE, "Set constructor requires a callable add method");
13661366+13671367+ bool use_fast_path
13681368+ = is_original_collection_adder(adder, set_add);
13691369+13701370+ js_iter_t it;
13711371+ if (!js_iter_open(js, iterable, &it))
13721372+ return js_mkerr_typed(js, JS_ERR_TYPE, "Set constructor argument is not iterable");
13731373+13741374+ ant_value_t result = js_mkundef();
13751375+ ant_value_t value;
13761376+13771377+ while (js_iter_next(js, &it, &value)) {
13781378+ if (use_fast_path) {
13791379+ if (!set_store_entry(js, set_head, value)) {
13801380+ result = js_mkerr(js, "out of memory");
13811381+ goto close_iter;
13821382+ }
13831383+ continue;
13841384+ }
13851385+13861386+ result = sv_vm_call(js->vm, js, adder, set_obj, &value, 1, NULL, false);
13871387+ if (is_err(result)) goto close_iter;
13881388+ }
13891389+13901390+ return result;
13911391+13921392+close_iter:
13931393+ js_iter_close(js, &it);
13941394+ return result;
13951395+}
13961396+13971397+static ant_value_t weakmap_init_from_iterable(ant_t *js, ant_value_t wm_obj, weakmap_entry_t **wm_head, ant_value_t iterable) {
13981398+ ant_value_t adder = js_getprop_fallback(js, wm_obj, "set");
13991399+ if (is_err(adder)) return adder;
14001400+ if (!is_callable(adder))
14011401+ return js_mkerr_typed(js, JS_ERR_TYPE, "WeakMap constructor requires a callable set method");
14021402+14031403+ bool use_fast_path = is_original_collection_adder(adder, weakmap_set);
14041404+14051405+ js_iter_t it;
14061406+ if (!js_iter_open(js, iterable, &it))
14071407+ return js_mkerr_typed(js, JS_ERR_TYPE, "WeakMap constructor argument is not iterable");
14081408+14091409+ ant_value_t result = js_mkundef();
14101410+ ant_value_t entry;
14111411+14121412+ while (js_iter_next(js, &it, &entry)) {
14131413+ uint8_t entry_t = vtype(entry);
14141414+ if (entry_t != T_ARR && entry_t != T_OBJ) {
14151415+ result = js_mkerr_typed(js, JS_ERR_TYPE, "WeakMap iterable entries must be pair sequences");
14161416+ goto close_iter;
14171417+ }
14181418+14191419+ ant_offset_t entry_len = js_arr_len(js, entry);
14201420+ if (entry_len < 2) {
14211421+ result = js_mkerr_typed(js, JS_ERR_TYPE, "WeakMap iterable entries must have at least 2 items");
14221422+ goto close_iter;
14231423+ }
14241424+14251425+ if (!use_fast_path) {
14261426+ ant_value_t call_args[2] = { js_arr_get(js, entry, 0), js_arr_get(js, entry, 1) };
14271427+ result = sv_vm_call(js->vm, js, adder, wm_obj, call_args, 2, NULL, false);
14281428+ if (is_err(result)) goto close_iter;
14291429+ continue;
14301430+ }
14311431+14321432+ ant_value_t key = js_arr_get(js, entry, 0);
14331433+ ant_value_t value = js_arr_get(js, entry, 1);
14341434+ if (!is_object_type(key)) {
14351435+ result = js_mkerr(js, "WeakMap key must be an object");
14361436+ goto close_iter;
14371437+ }
14381438+14391439+ weakmap_entry_t *wm_entry;
14401440+ HASH_FIND(hh, *wm_head, &key, sizeof(ant_value_t), wm_entry);
14411441+ if (wm_entry) {
14421442+ wm_entry->value = value;
14431443+ continue;
14441444+ }
14451445+14461446+ wm_entry = ant_calloc(sizeof(weakmap_entry_t));
14471447+ if (!wm_entry) {
14481448+ result = js_mkerr(js, "out of memory");
14491449+ goto close_iter;
14501450+ }
14511451+14521452+ wm_entry->key_obj = key;
14531453+ wm_entry->value = value;
14541454+ HASH_ADD(hh, *wm_head, key_obj, sizeof(ant_value_t), wm_entry);
14551455+ }
14561456+14571457+ return result;
14581458+14591459+close_iter:
14601460+ js_iter_close(js, &it);
14611461+ return result;
14621462+}
14631463+14641464+static ant_value_t weakset_init_from_iterable(ant_t *js, ant_value_t ws_obj, weakset_entry_t **ws_head, ant_value_t iterable) {
14651465+ ant_value_t adder = js_getprop_fallback(js, ws_obj, "add");
14661466+ if (is_err(adder)) return adder;
14671467+ if (!is_callable(adder))
14681468+ return js_mkerr_typed(js, JS_ERR_TYPE, "WeakSet constructor requires a callable add method");
14691469+14701470+ bool use_fast_path = is_original_collection_adder(adder, weakset_add);
14711471+14721472+ js_iter_t it;
14731473+ if (!js_iter_open(js, iterable, &it))
14741474+ return js_mkerr_typed(js, JS_ERR_TYPE, "WeakSet constructor argument is not iterable");
14751475+14761476+ ant_value_t result = js_mkundef();
14771477+ ant_value_t value;
14781478+14791479+ while (js_iter_next(js, &it, &value)) {
14801480+ if (!use_fast_path) {
14811481+ result = sv_vm_call(js->vm, js, adder, ws_obj, &value, 1, NULL, false);
14821482+ if (is_err(result)) goto close_iter;
14831483+ continue;
14841484+ }
14851485+14861486+ if (!is_object_type(value)) {
14871487+ result = js_mkerr(js, "WeakSet value must be an object");
14881488+ goto close_iter;
14891489+ }
14901490+14911491+ weakset_entry_t *entry;
14921492+ HASH_FIND(hh, *ws_head, &value, sizeof(ant_value_t), entry);
14931493+ if (entry) continue;
14941494+14951495+ entry = ant_calloc(sizeof(weakset_entry_t));
14961496+ if (!entry) {
14971497+ result = js_mkerr(js, "out of memory");
14981498+ goto close_iter;
14991499+ }
15001500+15011501+ entry->value_obj = value;
15021502+ HASH_ADD(hh, *ws_head, value_obj, sizeof(ant_value_t), entry);
15031503+ }
15041504+15051505+ return result;
15061506+15071507+close_iter:
15081508+ js_iter_close(js, &it);
15091509+ return result;
15101510+}
15111511+14271512static ant_value_t builtin_Map(ant_t *js, ant_value_t *args, int nargs) {
14281513 if (vtype(js->new_target) == T_UNDEF) {
14291514 return js_mkerr_typed(js, JS_ERR_TYPE, "Map constructor requires 'new'");
···14481533 js_set_native(map_obj, map_head, MAP_NATIVE_TAG);
1449153414501535 if (nargs == 0 || vtype(args[0]) == T_UNDEF || vtype(args[0]) == T_NULL) return map_obj;
14511451- ant_value_t init_result = map_init_from_iterable(js, map_head, args[0]);
15361536+ ant_value_t init_result = map_init_from_iterable(js, map_obj, map_head, args[0]);
14521537 if (is_err(init_result)) return init_result;
1453153814541539 return map_obj;
···14781563 js_set_native(set_obj, set_head, SET_NATIVE_TAG);
1479156414801565 if (nargs == 0 || vtype(args[0]) == T_UNDEF || vtype(args[0]) == T_NULL) return set_obj;
14811481- ant_value_t init_result = set_init_from_iterable(js, set_head, args[0]);
15661566+ ant_value_t init_result = set_init_from_iterable(js, set_obj, set_head, args[0]);
14821567 if (is_err(init_result)) return init_result;
1483156814841569 return set_obj;
···15081593 js_set_native(wm_obj, wm_head, WEAKMAP_NATIVE_TAG);
1509159415101595 if (nargs == 0 || vtype(args[0]) == T_UNDEF || vtype(args[0]) == T_NULL) return wm_obj;
15111511- ant_value_t init_result = weakmap_init_from_iterable(js, wm_head, args[0]);
15961596+ ant_value_t init_result = weakmap_init_from_iterable(js, wm_obj, wm_head, args[0]);
15121597 if (is_err(init_result)) return init_result;
1513159815141599 return wm_obj;
···15381623 js_set_native(ws_obj, ws_head, WEAKSET_NATIVE_TAG);
1539162415401625 if (nargs == 0 || vtype(args[0]) == T_UNDEF || vtype(args[0]) == T_NULL) return ws_obj;
15411541- ant_value_t init_result = weakset_init_from_iterable(js, ws_head, args[0]);
16261626+ ant_value_t init_result = weakset_init_from_iterable(js, ws_obj, ws_head, args[0]);
15421627 if (is_err(init_result)) return init_result;
1543162815441629 return ws_obj;