···463463compat-table/es6/Map.constructor-arguments.js: OK
464464compat-table/es6/Map.constructor-invokes-set.js: failed
465465compat-table/es6/Map.constructor-requires-new.js: OK
466466-compat-table/es6/Map.iterator-closing.js: failed
466466+compat-table/es6/Map.iterator-closing.js: OK
467467compat-table/es6/Map.iterator-prototype-chain.js: OK
468468compat-table/es6/Map.js: OK
469469compat-table/es6/Map.prototype-not-instance.js: failed
···624624compat-table/es6/WeakMap.constructor-invokes-set.js: failed
625625compat-table/es6/WeakMap.constructor-requires-new.js: OK
626626compat-table/es6/WeakMap.frozen-keys.js: OK
627627-compat-table/es6/WeakMap.iterator-closing.js: failed
627627+compat-table/es6/WeakMap.iterator-closing.js: OK
628628compat-table/es6/WeakMap.js: OK
629629compat-table/es6/WeakMap.no-clear.js: OK
630630compat-table/es6/WeakMap.prototype-not-instance.js: failed
···635635compat-table/es6/WeakSet.constructor-arguments.js: OK
636636compat-table/es6/WeakSet.constructor-invokes-add.js: failed
637637compat-table/es6/WeakSet.constructor-requires-new.js: OK
638638-compat-table/es6/WeakSet.iterator-closing.js: failed
638638+compat-table/es6/WeakSet.iterator-closing.js: OK
639639compat-table/es6/WeakSet.js: OK
640640compat-table/es6/WeakSet.no-clear.js: OK
641641compat-table/es6/WeakSet.prototype-not-instance.js: failed
+139-83
src/modules/collections.c
···182182 return true;
183183}
184184185185+static ant_value_t map_init_from_iterable(ant_t *js, map_entry_t **map_head, ant_value_t iterable) {
186186+ js_iter_t it;
187187+ if (!js_iter_open(js, iterable, &it)) {
188188+ return js_mkerr_typed(js, JS_ERR_TYPE, "Map constructor argument is not iterable");
189189+ }
190190+191191+ ant_value_t entry;
192192+ while (js_iter_next(js, &it, &entry)) {
193193+ uint8_t entry_t = vtype(entry);
194194+ if (entry_t != T_ARR && entry_t != T_OBJ) {
195195+ js_iter_close(js, &it);
196196+ return js_mkerr_typed(js, JS_ERR_TYPE, "Map iterable entries must be pair sequences");
197197+ }
198198+199199+ ant_offset_t entry_len = js_arr_len(js, entry);
200200+ if (entry_len < 2) {
201201+ js_iter_close(js, &it);
202202+ return js_mkerr_typed(js, JS_ERR_TYPE, "Map iterable entries must have at least 2 items");
203203+ }
204204+205205+ ant_value_t key = normalize_map_key(js_arr_get(js, entry, 0));
206206+ ant_value_t value = js_arr_get(js, entry, 1);
207207+ if (!map_store_entry(js, map_head, key, key, value)) {
208208+ js_iter_close(js, &it);
209209+ return js_mkerr(js, "out of memory");
210210+ }}
211211+212212+ return js_mkundef();
213213+}
214214+215215+static ant_value_t set_init_from_iterable(ant_t *js, set_entry_t **set_head, ant_value_t iterable) {
216216+ js_iter_t it;
217217+ if (!js_iter_open(js, iterable, &it)) {
218218+ return js_mkerr_typed(js, JS_ERR_TYPE, "Set constructor argument is not iterable");
219219+ }
220220+221221+ ant_value_t value;
222222+ while (js_iter_next(js, &it, &value)) if (!set_store_entry(js, set_head, value)) {
223223+ js_iter_close(js, &it);
224224+ return js_mkerr(js, "out of memory");
225225+ }
226226+227227+ return js_mkundef();
228228+}
229229+230230+static ant_value_t weakmap_init_from_iterable(ant_t *js, weakmap_entry_t **wm_head, ant_value_t iterable) {
231231+ js_iter_t it;
232232+ if (!js_iter_open(js, iterable, &it)) {
233233+ return js_mkerr_typed(js, JS_ERR_TYPE, "WeakMap constructor argument is not iterable");
234234+ }
235235+236236+ ant_value_t entry;
237237+ while (js_iter_next(js, &it, &entry)) {
238238+ uint8_t entry_t = vtype(entry);
239239+ if (entry_t != T_ARR && entry_t != T_OBJ) {
240240+ js_iter_close(js, &it);
241241+ return js_mkerr_typed(js, JS_ERR_TYPE, "WeakMap iterable entries must be pair sequences");
242242+ }
243243+244244+ ant_offset_t entry_len = js_arr_len(js, entry);
245245+ if (entry_len < 2) {
246246+ js_iter_close(js, &it);
247247+ return js_mkerr_typed(js, JS_ERR_TYPE, "WeakMap iterable entries must have at least 2 items");
248248+ }
249249+250250+ ant_value_t key = js_arr_get(js, entry, 0);
251251+ ant_value_t value = js_arr_get(js, entry, 1);
252252+ if (!is_object_type(key)) {
253253+ js_iter_close(js, &it);
254254+ return js_mkerr(js, "WeakMap key must be an object");
255255+ }
256256+257257+ weakmap_entry_t *wm_entry;
258258+ HASH_FIND(hh, *wm_head, &key, sizeof(ant_value_t), wm_entry);
259259+ if (wm_entry) {
260260+ wm_entry->value = value;
261261+ continue;
262262+ }
263263+264264+ wm_entry = ant_calloc(sizeof(weakmap_entry_t));
265265+ if (!wm_entry) {
266266+ js_iter_close(js, &it);
267267+ return js_mkerr(js, "out of memory");
268268+ }
269269+270270+ wm_entry->key_obj = key;
271271+ wm_entry->value = value;
272272+ HASH_ADD(hh, *wm_head, key_obj, sizeof(ant_value_t), wm_entry);
273273+ }
274274+275275+ return js_mkundef();
276276+}
277277+278278+static ant_value_t weakset_init_from_iterable(ant_t *js, weakset_entry_t **ws_head, ant_value_t iterable) {
279279+ js_iter_t it;
280280+ if (!js_iter_open(js, iterable, &it)) {
281281+ return js_mkerr_typed(js, JS_ERR_TYPE, "WeakSet constructor argument is not iterable");
282282+ }
283283+284284+ ant_value_t value;
285285+ while (js_iter_next(js, &it, &value)) {
286286+ if (!is_object_type(value)) {
287287+ js_iter_close(js, &it);
288288+ return js_mkerr(js, "WeakSet value must be an object");
289289+ }
290290+291291+ weakset_entry_t *entry;
292292+ HASH_FIND(hh, *ws_head, &value, sizeof(ant_value_t), entry);
293293+ if (entry) continue;
294294+295295+ entry = ant_calloc(sizeof(weakset_entry_t));
296296+ if (!entry) {
297297+ js_iter_close(js, &it);
298298+ return js_mkerr(js, "out of memory");
299299+ }
300300+301301+ entry->value_obj = value;
302302+ HASH_ADD(hh, *ws_head, value_obj, sizeof(ant_value_t), entry);
303303+ }
304304+305305+ return js_mkundef();
306306+}
307307+185308map_entry_t **get_map_from_obj(ant_t *js, ant_value_t obj) {
186309 (void)js;
187310 ant_object_t *ptr = js_obj_ptr(obj);
···851974 if (!map_head) return js_mkerr(js, "out of memory");
852975 *map_head = NULL;
853976854854- if (vtype(js->new_target) == T_FUNC || vtype(js->new_target) == T_CFUNC) {
977977+ if (vtype(js->new_target) == T_FUNC || vtype(js->new_target) == T_CFUNC)
855978 js_set_slot(map_obj, SLOT_CTOR, js->new_target);
856856- }
857979 js_set_slot(map_obj, SLOT_DATA, ANT_PTR(map_head));
858980859859- if (nargs == 0 || vtype(args[0]) != T_ARR) return map_obj;
860860-861861- ant_value_t iterable = args[0];
862862- ant_offset_t length = js_arr_len(js, iterable);
863863-864864- for (ant_offset_t i = 0; i < length; i++) {
865865- ant_value_t entry = js_arr_get(js, iterable, i);
866866- if (vtype(entry) != T_ARR) continue;
867867-868868- ant_offset_t entry_len = js_arr_len(js, entry);
869869- if (entry_len < 2) continue;
870870-871871- ant_value_t key = normalize_map_key(js_arr_get(js, entry, 0));
872872- ant_value_t value = js_arr_get(js, entry, 1);
873873- if (!map_store_entry(js, map_head, key, key, value))
874874- return js_mkerr(js, "out of memory");
875875- }
981981+ if (nargs == 0 || vtype(args[0]) == T_UNDEF || vtype(args[0]) == T_NULL) return map_obj;
982982+ ant_value_t init_result = map_init_from_iterable(js, map_head, args[0]);
983983+ if (is_err(init_result)) return init_result;
876984877985 return map_obj;
878986}
···8961004 if (!set_head) return js_mkerr(js, "out of memory");
8971005 *set_head = NULL;
8981006899899- if (vtype(js->new_target) == T_FUNC || vtype(js->new_target) == T_CFUNC) {
10071007+ if (vtype(js->new_target) == T_FUNC || vtype(js->new_target) == T_CFUNC)
9001008 js_set_slot(set_obj, SLOT_CTOR, js->new_target);
901901- }
9021009 js_set_slot(set_obj, SLOT_DATA, ANT_PTR(set_head));
9031010904904- if (nargs == 0 || vtype(args[0]) != T_ARR) return set_obj;
905905-906906- ant_value_t iterable = args[0];
907907- ant_offset_t length = js_arr_len(js, iterable);
908908-909909- for (ant_offset_t i = 0; i < length; i++) {
910910- ant_value_t value = js_arr_get(js, iterable, i);
911911- if (!set_store_entry(js, set_head, value)) return js_mkerr(js, "out of memory");
912912- }
10111011+ if (nargs == 0 || vtype(args[0]) == T_UNDEF || vtype(args[0]) == T_NULL) return set_obj;
10121012+ ant_value_t init_result = set_init_from_iterable(js, set_head, args[0]);
10131013+ if (is_err(init_result)) return init_result;
91310149141015 return set_obj;
9151016}
···9331034 if (!wm_head) return js_mkerr(js, "out of memory");
9341035 *wm_head = NULL;
9351036936936- if (vtype(js->new_target) == T_FUNC || vtype(js->new_target) == T_CFUNC) {
10371037+ if (vtype(js->new_target) == T_FUNC || vtype(js->new_target) == T_CFUNC)
9371038 js_set_slot(wm_obj, SLOT_CTOR, js->new_target);
938938- }
9391039 js_set_slot(wm_obj, SLOT_DATA, ANT_PTR(wm_head));
9401040941941- if (nargs == 0 || vtype(args[0]) != T_ARR) return wm_obj;
942942-943943- ant_value_t iterable = args[0];
944944- ant_offset_t length = js_arr_len(js, iterable);
945945-946946- for (ant_offset_t i = 0; i < length; i++) {
947947- ant_value_t entry = js_arr_get(js, iterable, i);
948948- if (vtype(entry) != T_ARR) continue;
949949-950950- ant_offset_t entry_len = js_arr_len(js, entry);
951951- if (entry_len < 2) continue;
952952-953953- ant_value_t key = js_arr_get(js, entry, 0);
954954- ant_value_t value = js_arr_get(js, entry, 1);
955955- if (!is_object_type(key)) return js_mkerr(js, "WeakMap key must be an object");
956956-957957- weakmap_entry_t *wm_entry;
958958- HASH_FIND(hh, *wm_head, &key, sizeof(ant_value_t), wm_entry);
959959-960960- if (wm_entry) {
961961- wm_entry->value = value;
962962- continue;
963963- }
964964-965965- wm_entry = ant_calloc(sizeof(weakmap_entry_t));
966966- if (!wm_entry) return js_mkerr(js, "out of memory");
967967-968968- wm_entry->key_obj = key;
969969- wm_entry->value = value;
970970- HASH_ADD(hh, *wm_head, key_obj, sizeof(ant_value_t), wm_entry);
971971- }
10411041+ if (nargs == 0 || vtype(args[0]) == T_UNDEF || vtype(args[0]) == T_NULL) return wm_obj;
10421042+ ant_value_t init_result = weakmap_init_from_iterable(js, wm_head, args[0]);
10431043+ if (is_err(init_result)) return init_result;
97210449731045 return wm_obj;
9741046}
···9921064 if (!ws_head) return js_mkerr(js, "out of memory");
9931065 *ws_head = NULL;
9941066995995- if (vtype(js->new_target) == T_FUNC || vtype(js->new_target) == T_CFUNC) {
10671067+ if (vtype(js->new_target) == T_FUNC || vtype(js->new_target) == T_CFUNC)
9961068 js_set_slot(ws_obj, SLOT_CTOR, js->new_target);
997997- }
9981069 js_set_slot(ws_obj, SLOT_DATA, ANT_PTR(ws_head));
999107010001000- if (nargs == 0 || vtype(args[0]) != T_ARR) return ws_obj;
10011001-10021002- ant_value_t iterable = args[0];
10031003- ant_offset_t length = js_arr_len(js, iterable);
10041004-10051005- for (ant_offset_t i = 0; i < length; i++) {
10061006- ant_value_t value = js_arr_get(js, iterable, i);
10071007- if (!is_object_type(value)) return js_mkerr(js, "WeakSet value must be an object");
10081008-10091009- weakset_entry_t *entry;
10101010- HASH_FIND(hh, *ws_head, &value, sizeof(ant_value_t), entry);
10111011- if (entry) continue;
10121012-10131013- entry = ant_calloc(sizeof(weakset_entry_t));
10141014- if (!entry) return js_mkerr(js, "out of memory");
10151015- entry->value_obj = value;
10161016- HASH_ADD(hh, *ws_head, value_obj, sizeof(ant_value_t), entry);
10171017- }
10711071+ if (nargs == 0 || vtype(args[0]) == T_UNDEF || vtype(args[0]) == T_NULL) return ws_obj;
10721072+ ant_value_t init_result = weakset_init_from_iterable(js, ws_head, args[0]);
10731073+ if (is_err(init_result)) return init_result;
1018107410191075 return ws_obj;
10201076}
+30
tests/test_collections_constructor_iterables.cjs
···11+function assert(condition, message) {
22+ if (!condition) throw new Error(message);
33+}
44+55+const map = new Map([
66+ ['x', 1],
77+ ['y', 2],
88+]);
99+const mapCopy = new Map(map);
1010+const mapNull = new Map(null);
1111+const mapUndef = new Map(undefined);
1212+1313+assert(mapCopy.size === 2, `expected copied map size 2, got ${mapCopy.size}`);
1414+assert(mapCopy.get('x') === 1, 'expected copied map to contain x => 1');
1515+assert(mapCopy.get('y') === 2, 'expected copied map to contain y => 2');
1616+assert(mapNull.size === 0, `expected null map size 0, got ${mapNull.size}`);
1717+assert(mapUndef.size === 0, `expected undefined map size 0, got ${mapUndef.size}`);
1818+1919+const set = new Set(['a', 'b']);
2020+const setCopy = new Set(set);
2121+const setNull = new Set(null);
2222+const setUndef = new Set(undefined);
2323+2424+assert(setCopy.size === 2, `expected copied set size 2, got ${setCopy.size}`);
2525+assert(setCopy.has('a'), 'expected copied set to contain a');
2626+assert(setCopy.has('b'), 'expected copied set to contain b');
2727+assert(setNull.size === 0, `expected null set size 0, got ${setNull.size}`);
2828+assert(setUndef.size === 0, `expected undefined set size 0, got ${setUndef.size}`);
2929+3030+console.log('collections constructor iterables ok');