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.

improve iterable-constructor

+218 -133
+5 -5
examples/results.txt
··· 534 534 compat-table/es6/Map.Symbol.species.js: OK 535 535 compat-table/es6/Map.constructor-accepts-null.js: OK 536 536 compat-table/es6/Map.constructor-arguments.js: OK 537 - compat-table/es6/Map.constructor-invokes-set.js: failed 537 + compat-table/es6/Map.constructor-invokes-set.js: OK 538 538 compat-table/es6/Map.constructor-requires-new.js: OK 539 539 compat-table/es6/Map.iterator-closing.js: OK 540 540 compat-table/es6/Map.iterator-prototype-chain.js: OK ··· 651 651 compat-table/es6/Set.Symbol.species.js: OK 652 652 compat-table/es6/Set.constructor-accepts-null.js: OK 653 653 compat-table/es6/Set.constructor-arguments.js: OK 654 - compat-table/es6/Set.constructor-invokes-add.js: failed 654 + compat-table/es6/Set.constructor-invokes-add.js: OK 655 655 compat-table/es6/Set.constructor-requires-new.js: OK 656 - compat-table/es6/Set.iterator-closing.js: failed 656 + compat-table/es6/Set.iterator-closing.js: OK 657 657 compat-table/es6/Set.iterator-prototype-chain.js: OK 658 658 compat-table/es6/Set.js: OK 659 659 compat-table/es6/Set.prototype-not-instance.js: OK ··· 694 694 compat-table/es6/WeakMap.accept-primitives.js: OK 695 695 compat-table/es6/WeakMap.constructor-accepts-null.js: OK 696 696 compat-table/es6/WeakMap.constructor-arguments.js: OK 697 - compat-table/es6/WeakMap.constructor-invokes-set.js: failed 697 + compat-table/es6/WeakMap.constructor-invokes-set.js: OK 698 698 compat-table/es6/WeakMap.constructor-requires-new.js: OK 699 699 compat-table/es6/WeakMap.frozen-keys.js: OK 700 700 compat-table/es6/WeakMap.iterator-closing.js: OK ··· 706 706 compat-table/es6/WeakSet.accept-primitives.js: OK 707 707 compat-table/es6/WeakSet.constructor-accepts-null.js: OK 708 708 compat-table/es6/WeakSet.constructor-arguments.js: OK 709 - compat-table/es6/WeakSet.constructor-invokes-add.js: failed 709 + compat-table/es6/WeakSet.constructor-invokes-add.js: OK 710 710 compat-table/es6/WeakSet.constructor-requires-new.js: OK 711 711 compat-table/es6/WeakSet.iterator-closing.js: OK 712 712 compat-table/es6/WeakSet.js: OK
+213 -128
src/modules/collections.c
··· 150 150 } 151 151 152 152 static bool set_store_entry(ant_t *js, set_entry_t **set_ptr, ant_value_t value) { 153 - ant_value_t stored_value = normalize_map_key(value); collection_key_t key; 153 + ant_value_t stored_value = normalize_map_key(value); 154 + 155 + collection_key_t key; 154 156 if (!collection_key_init(js, stored_value, &key)) return false; 155 157 156 158 set_entry_t *entry = NULL; ··· 181 183 collection_key_free(&key); 182 184 183 185 return true; 184 - } 185 - 186 - static ant_value_t map_init_from_iterable(ant_t *js, map_entry_t **map_head, ant_value_t iterable) { 187 - js_iter_t it; 188 - if (!js_iter_open(js, iterable, &it)) { 189 - return js_mkerr_typed(js, JS_ERR_TYPE, "Map constructor argument is not iterable"); 190 - } 191 - 192 - ant_value_t entry; 193 - while (js_iter_next(js, &it, &entry)) { 194 - uint8_t entry_t = vtype(entry); 195 - if (entry_t != T_ARR && entry_t != T_OBJ) { 196 - js_iter_close(js, &it); 197 - return js_mkerr_typed(js, JS_ERR_TYPE, "Map iterable entries must be pair sequences"); 198 - } 199 - 200 - ant_offset_t entry_len = js_arr_len(js, entry); 201 - if (entry_len < 2) { 202 - js_iter_close(js, &it); 203 - return js_mkerr_typed(js, JS_ERR_TYPE, "Map iterable entries must have at least 2 items"); 204 - } 205 - 206 - ant_value_t key = normalize_map_key(js_arr_get(js, entry, 0)); 207 - ant_value_t value = js_arr_get(js, entry, 1); 208 - if (!map_store_entry(js, map_head, key, key, value)) { 209 - js_iter_close(js, &it); 210 - return js_mkerr(js, "out of memory"); 211 - }} 212 - 213 - return js_mkundef(); 214 - } 215 - 216 - static ant_value_t set_init_from_iterable(ant_t *js, set_entry_t **set_head, ant_value_t iterable) { 217 - js_iter_t it; 218 - if (!js_iter_open(js, iterable, &it)) { 219 - return js_mkerr_typed(js, JS_ERR_TYPE, "Set constructor argument is not iterable"); 220 - } 221 - 222 - ant_value_t value; 223 - while (js_iter_next(js, &it, &value)) if (!set_store_entry(js, set_head, value)) { 224 - js_iter_close(js, &it); 225 - return js_mkerr(js, "out of memory"); 226 - } 227 - 228 - return js_mkundef(); 229 - } 230 - 231 - static ant_value_t weakmap_init_from_iterable(ant_t *js, weakmap_entry_t **wm_head, ant_value_t iterable) { 232 - js_iter_t it; 233 - if (!js_iter_open(js, iterable, &it)) { 234 - return js_mkerr_typed(js, JS_ERR_TYPE, "WeakMap constructor argument is not iterable"); 235 - } 236 - 237 - ant_value_t entry; 238 - while (js_iter_next(js, &it, &entry)) { 239 - uint8_t entry_t = vtype(entry); 240 - if (entry_t != T_ARR && entry_t != T_OBJ) { 241 - js_iter_close(js, &it); 242 - return js_mkerr_typed(js, JS_ERR_TYPE, "WeakMap iterable entries must be pair sequences"); 243 - } 244 - 245 - ant_offset_t entry_len = js_arr_len(js, entry); 246 - if (entry_len < 2) { 247 - js_iter_close(js, &it); 248 - return js_mkerr_typed(js, JS_ERR_TYPE, "WeakMap iterable entries must have at least 2 items"); 249 - } 250 - 251 - ant_value_t key = js_arr_get(js, entry, 0); 252 - ant_value_t value = js_arr_get(js, entry, 1); 253 - if (!is_object_type(key)) { 254 - js_iter_close(js, &it); 255 - return js_mkerr(js, "WeakMap key must be an object"); 256 - } 257 - 258 - weakmap_entry_t *wm_entry; 259 - HASH_FIND(hh, *wm_head, &key, sizeof(ant_value_t), wm_entry); 260 - if (wm_entry) { 261 - wm_entry->value = value; 262 - continue; 263 - } 264 - 265 - wm_entry = ant_calloc(sizeof(weakmap_entry_t)); 266 - if (!wm_entry) { 267 - js_iter_close(js, &it); 268 - return js_mkerr(js, "out of memory"); 269 - } 270 - 271 - wm_entry->key_obj = key; 272 - wm_entry->value = value; 273 - HASH_ADD(hh, *wm_head, key_obj, sizeof(ant_value_t), wm_entry); 274 - } 275 - 276 - return js_mkundef(); 277 - } 278 - 279 - static ant_value_t weakset_init_from_iterable(ant_t *js, weakset_entry_t **ws_head, ant_value_t iterable) { 280 - js_iter_t it; 281 - if (!js_iter_open(js, iterable, &it)) { 282 - return js_mkerr_typed(js, JS_ERR_TYPE, "WeakSet constructor argument is not iterable"); 283 - } 284 - 285 - ant_value_t value; 286 - while (js_iter_next(js, &it, &value)) { 287 - if (!is_object_type(value)) { 288 - js_iter_close(js, &it); 289 - return js_mkerr(js, "WeakSet value must be an object"); 290 - } 291 - 292 - weakset_entry_t *entry; 293 - HASH_FIND(hh, *ws_head, &value, sizeof(ant_value_t), entry); 294 - if (entry) continue; 295 - 296 - entry = ant_calloc(sizeof(weakset_entry_t)); 297 - if (!entry) { 298 - js_iter_close(js, &it); 299 - return js_mkerr(js, "out of memory"); 300 - } 301 - 302 - entry->value_obj = value; 303 - HASH_ADD(hh, *ws_head, value_obj, sizeof(ant_value_t), entry); 304 - } 305 - 306 - return js_mkundef(); 307 186 } 308 187 309 188 map_entry_t **get_map_from_obj(ant_value_t obj) { ··· 1424 1303 return map_obj; 1425 1304 } 1426 1305 1306 + static bool is_original_collection_adder(ant_value_t adder, ant_cfunc_t fn) { 1307 + return vtype(adder) == T_CFUNC && js_cfunc_same_entrypoint(adder, fn); 1308 + } 1309 + 1310 + 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) { 1311 + ant_value_t adder = js_getprop_fallback(js, map_obj, "set"); 1312 + if (is_err(adder)) return adder; 1313 + if (!is_callable(adder)) 1314 + return js_mkerr_typed(js, JS_ERR_TYPE, "Map constructor requires a callable set method"); 1315 + 1316 + bool use_fast_path 1317 + = is_original_collection_adder(adder, map_set); 1318 + 1319 + js_iter_t it; 1320 + if (!js_iter_open(js, iterable, &it)) 1321 + return js_mkerr_typed(js, JS_ERR_TYPE, "Map constructor argument is not iterable"); 1322 + 1323 + ant_value_t result = js_mkundef(); 1324 + ant_value_t entry; 1325 + 1326 + while (js_iter_next(js, &it, &entry)) { 1327 + uint8_t entry_t = vtype(entry); 1328 + if (entry_t != T_ARR && entry_t != T_OBJ) { 1329 + result = js_mkerr_typed(js, JS_ERR_TYPE, "Map iterable entries must be pair sequences"); 1330 + goto close_iter; 1331 + } 1332 + 1333 + ant_offset_t entry_len = js_arr_len(js, entry); 1334 + if (entry_len < 2) { 1335 + result = js_mkerr_typed(js, JS_ERR_TYPE, "Map iterable entries must have at least 2 items"); 1336 + goto close_iter; 1337 + } 1338 + 1339 + if (use_fast_path) { 1340 + ant_value_t key = normalize_map_key(js_arr_get(js, entry, 0)); 1341 + ant_value_t value = js_arr_get(js, entry, 1); 1342 + if (!map_store_entry(js, map_head, key, key, value)) { 1343 + result = js_mkerr(js, "out of memory"); 1344 + goto close_iter; 1345 + } 1346 + continue; 1347 + } 1348 + 1349 + ant_value_t call_args[2] = { js_arr_get(js, entry, 0), js_arr_get(js, entry, 1) }; 1350 + result = sv_vm_call(js->vm, js, adder, map_obj, call_args, 2, NULL, false); 1351 + if (is_err(result)) goto close_iter; 1352 + } 1353 + 1354 + return result; 1355 + 1356 + close_iter: 1357 + js_iter_close(js, &it); 1358 + return result; 1359 + } 1360 + 1361 + 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) { 1362 + ant_value_t adder = js_getprop_fallback(js, set_obj, "add"); 1363 + if (is_err(adder)) return adder; 1364 + if (!is_callable(adder)) 1365 + return js_mkerr_typed(js, JS_ERR_TYPE, "Set constructor requires a callable add method"); 1366 + 1367 + bool use_fast_path 1368 + = is_original_collection_adder(adder, set_add); 1369 + 1370 + js_iter_t it; 1371 + if (!js_iter_open(js, iterable, &it)) 1372 + return js_mkerr_typed(js, JS_ERR_TYPE, "Set constructor argument is not iterable"); 1373 + 1374 + ant_value_t result = js_mkundef(); 1375 + ant_value_t value; 1376 + 1377 + while (js_iter_next(js, &it, &value)) { 1378 + if (use_fast_path) { 1379 + if (!set_store_entry(js, set_head, value)) { 1380 + result = js_mkerr(js, "out of memory"); 1381 + goto close_iter; 1382 + } 1383 + continue; 1384 + } 1385 + 1386 + result = sv_vm_call(js->vm, js, adder, set_obj, &value, 1, NULL, false); 1387 + if (is_err(result)) goto close_iter; 1388 + } 1389 + 1390 + return result; 1391 + 1392 + close_iter: 1393 + js_iter_close(js, &it); 1394 + return result; 1395 + } 1396 + 1397 + 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) { 1398 + ant_value_t adder = js_getprop_fallback(js, wm_obj, "set"); 1399 + if (is_err(adder)) return adder; 1400 + if (!is_callable(adder)) 1401 + return js_mkerr_typed(js, JS_ERR_TYPE, "WeakMap constructor requires a callable set method"); 1402 + 1403 + bool use_fast_path = is_original_collection_adder(adder, weakmap_set); 1404 + 1405 + js_iter_t it; 1406 + if (!js_iter_open(js, iterable, &it)) 1407 + return js_mkerr_typed(js, JS_ERR_TYPE, "WeakMap constructor argument is not iterable"); 1408 + 1409 + ant_value_t result = js_mkundef(); 1410 + ant_value_t entry; 1411 + 1412 + while (js_iter_next(js, &it, &entry)) { 1413 + uint8_t entry_t = vtype(entry); 1414 + if (entry_t != T_ARR && entry_t != T_OBJ) { 1415 + result = js_mkerr_typed(js, JS_ERR_TYPE, "WeakMap iterable entries must be pair sequences"); 1416 + goto close_iter; 1417 + } 1418 + 1419 + ant_offset_t entry_len = js_arr_len(js, entry); 1420 + if (entry_len < 2) { 1421 + result = js_mkerr_typed(js, JS_ERR_TYPE, "WeakMap iterable entries must have at least 2 items"); 1422 + goto close_iter; 1423 + } 1424 + 1425 + if (!use_fast_path) { 1426 + ant_value_t call_args[2] = { js_arr_get(js, entry, 0), js_arr_get(js, entry, 1) }; 1427 + result = sv_vm_call(js->vm, js, adder, wm_obj, call_args, 2, NULL, false); 1428 + if (is_err(result)) goto close_iter; 1429 + continue; 1430 + } 1431 + 1432 + ant_value_t key = js_arr_get(js, entry, 0); 1433 + ant_value_t value = js_arr_get(js, entry, 1); 1434 + if (!is_object_type(key)) { 1435 + result = js_mkerr(js, "WeakMap key must be an object"); 1436 + goto close_iter; 1437 + } 1438 + 1439 + weakmap_entry_t *wm_entry; 1440 + HASH_FIND(hh, *wm_head, &key, sizeof(ant_value_t), wm_entry); 1441 + if (wm_entry) { 1442 + wm_entry->value = value; 1443 + continue; 1444 + } 1445 + 1446 + wm_entry = ant_calloc(sizeof(weakmap_entry_t)); 1447 + if (!wm_entry) { 1448 + result = js_mkerr(js, "out of memory"); 1449 + goto close_iter; 1450 + } 1451 + 1452 + wm_entry->key_obj = key; 1453 + wm_entry->value = value; 1454 + HASH_ADD(hh, *wm_head, key_obj, sizeof(ant_value_t), wm_entry); 1455 + } 1456 + 1457 + return result; 1458 + 1459 + close_iter: 1460 + js_iter_close(js, &it); 1461 + return result; 1462 + } 1463 + 1464 + 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) { 1465 + ant_value_t adder = js_getprop_fallback(js, ws_obj, "add"); 1466 + if (is_err(adder)) return adder; 1467 + if (!is_callable(adder)) 1468 + return js_mkerr_typed(js, JS_ERR_TYPE, "WeakSet constructor requires a callable add method"); 1469 + 1470 + bool use_fast_path = is_original_collection_adder(adder, weakset_add); 1471 + 1472 + js_iter_t it; 1473 + if (!js_iter_open(js, iterable, &it)) 1474 + return js_mkerr_typed(js, JS_ERR_TYPE, "WeakSet constructor argument is not iterable"); 1475 + 1476 + ant_value_t result = js_mkundef(); 1477 + ant_value_t value; 1478 + 1479 + while (js_iter_next(js, &it, &value)) { 1480 + if (!use_fast_path) { 1481 + result = sv_vm_call(js->vm, js, adder, ws_obj, &value, 1, NULL, false); 1482 + if (is_err(result)) goto close_iter; 1483 + continue; 1484 + } 1485 + 1486 + if (!is_object_type(value)) { 1487 + result = js_mkerr(js, "WeakSet value must be an object"); 1488 + goto close_iter; 1489 + } 1490 + 1491 + weakset_entry_t *entry; 1492 + HASH_FIND(hh, *ws_head, &value, sizeof(ant_value_t), entry); 1493 + if (entry) continue; 1494 + 1495 + entry = ant_calloc(sizeof(weakset_entry_t)); 1496 + if (!entry) { 1497 + result = js_mkerr(js, "out of memory"); 1498 + goto close_iter; 1499 + } 1500 + 1501 + entry->value_obj = value; 1502 + HASH_ADD(hh, *ws_head, value_obj, sizeof(ant_value_t), entry); 1503 + } 1504 + 1505 + return result; 1506 + 1507 + close_iter: 1508 + js_iter_close(js, &it); 1509 + return result; 1510 + } 1511 + 1427 1512 static ant_value_t builtin_Map(ant_t *js, ant_value_t *args, int nargs) { 1428 1513 if (vtype(js->new_target) == T_UNDEF) { 1429 1514 return js_mkerr_typed(js, JS_ERR_TYPE, "Map constructor requires 'new'"); ··· 1448 1533 js_set_native(map_obj, map_head, MAP_NATIVE_TAG); 1449 1534 1450 1535 if (nargs == 0 || vtype(args[0]) == T_UNDEF || vtype(args[0]) == T_NULL) return map_obj; 1451 - ant_value_t init_result = map_init_from_iterable(js, map_head, args[0]); 1536 + ant_value_t init_result = map_init_from_iterable(js, map_obj, map_head, args[0]); 1452 1537 if (is_err(init_result)) return init_result; 1453 1538 1454 1539 return map_obj; ··· 1478 1563 js_set_native(set_obj, set_head, SET_NATIVE_TAG); 1479 1564 1480 1565 if (nargs == 0 || vtype(args[0]) == T_UNDEF || vtype(args[0]) == T_NULL) return set_obj; 1481 - ant_value_t init_result = set_init_from_iterable(js, set_head, args[0]); 1566 + ant_value_t init_result = set_init_from_iterable(js, set_obj, set_head, args[0]); 1482 1567 if (is_err(init_result)) return init_result; 1483 1568 1484 1569 return set_obj; ··· 1508 1593 js_set_native(wm_obj, wm_head, WEAKMAP_NATIVE_TAG); 1509 1594 1510 1595 if (nargs == 0 || vtype(args[0]) == T_UNDEF || vtype(args[0]) == T_NULL) return wm_obj; 1511 - ant_value_t init_result = weakmap_init_from_iterable(js, wm_head, args[0]); 1596 + ant_value_t init_result = weakmap_init_from_iterable(js, wm_obj, wm_head, args[0]); 1512 1597 if (is_err(init_result)) return init_result; 1513 1598 1514 1599 return wm_obj; ··· 1538 1623 js_set_native(ws_obj, ws_head, WEAKSET_NATIVE_TAG); 1539 1624 1540 1625 if (nargs == 0 || vtype(args[0]) == T_UNDEF || vtype(args[0]) == T_NULL) return ws_obj; 1541 - ant_value_t init_result = weakset_init_from_iterable(js, ws_head, args[0]); 1626 + ant_value_t init_result = weakset_init_from_iterable(js, ws_obj, ws_head, args[0]); 1542 1627 if (is_err(init_result)) return init_result; 1543 1628 1544 1629 return ws_obj;