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 array stringification and super call handling

+81 -126
+81 -126
src/ant.c
··· 657 657 return vtype(v) == T_UNDEF; 658 658 } 659 659 660 + #define T_OBJECT_MASK (TYPE_FLAG(T_OBJ) | TYPE_FLAG(T_ARR) | TYPE_FLAG(T_FUNC) | TYPE_FLAG(T_PROMISE)) 661 + #define is_object_type(v) ((1u << vtype(v)) & T_OBJECT_MASK) 662 + 660 663 static inline bool is_true(jsval_t v) { 661 664 return vtype(v) == T_BOOL && vdata(v) != 0; 662 665 } ··· 1374 1377 return true; 1375 1378 } 1376 1379 1380 + static void get_prop_key(struct js *js, jsoff_t prop, const char **key, jsoff_t *klen) { 1381 + jsoff_t koff = loadoff(js, prop + (jsoff_t) sizeof(prop)); 1382 + *klen = offtolen(loadoff(js, koff)); 1383 + *key = (char *) &js->mem[koff + sizeof(koff)]; 1384 + } 1385 + 1386 + static jsval_t get_prop_val(struct js *js, jsoff_t prop) { 1387 + jsoff_t koff = loadoff(js, prop + (jsoff_t) sizeof(prop)); 1388 + return loadval(js, prop + (jsoff_t) (sizeof(prop) + sizeof(koff))); 1389 + } 1390 + 1391 + static jsoff_t get_array_length(struct js *js, jsval_t arr) { 1392 + jsoff_t off = lkp_interned(js, arr, INTERN_LENGTH, 6); 1393 + if (!off) return 0; 1394 + jsval_t val = resolveprop(js, mkval(T_PROP, off)); 1395 + return vtype(val) == T_NUM ? (jsoff_t) tod(val) : 0; 1396 + } 1397 + 1398 + static jsval_t get_obj_ctor(struct js *js, jsval_t obj) { 1399 + jsval_t ctor = get_slot(js, obj, SLOT_CTOR); 1400 + if (vtype(ctor) == T_FUNC) return ctor; 1401 + jsval_t proto = get_slot(js, obj, SLOT_PROTO); 1402 + if (vtype(proto) != T_OBJ) return js_mkundef(); 1403 + jsoff_t off = lkp(js, proto, "constructor", 11); 1404 + return off ? resolveprop(js, mkval(T_PROP, off)) : js_mkundef(); 1405 + } 1406 + 1407 + static const char *get_func_name(struct js *js, jsval_t func, jsoff_t *out_len) { 1408 + if (vtype(func) != T_FUNC) return NULL; 1409 + jsoff_t off = lkp(js, mkval(T_OBJ, vdata(func)), "name", 4); 1410 + if (!off) return NULL; 1411 + jsval_t name = resolveprop(js, mkval(T_PROP, off)); 1412 + if (vtype(name) != T_STR) return NULL; 1413 + jsoff_t str_off = vstr(js, name, out_len); 1414 + return (const char *) &js->mem[str_off]; 1415 + } 1416 + 1417 + static const char *get_class_name(struct js *js, jsval_t obj, jsoff_t *out_len, const char *skip) { 1418 + const char *name = get_func_name(js, get_obj_ctor(js, obj), out_len); 1419 + if (!name) return NULL; 1420 + if (skip && *out_len == (jsoff_t)strlen(skip) && memcmp(name, skip, *out_len) == 0) return NULL; 1421 + return name; 1422 + } 1423 + 1377 1424 static size_t strarr(struct js *js, jsval_t obj, char *buf, size_t len) { 1378 1425 int ref = get_circular_ref(obj); 1379 1426 if (ref) return ref > 0 ? (size_t) snprintf(buf, len, "[Circular *%d]", ref) : cpy(buf, len, "[Circular]", 10); 1380 1427 1381 1428 push_stringify(obj); 1382 - jsoff_t next = loadoff(js, (jsoff_t) vdata(obj)) & ~(3U | FLAGMASK); 1383 - jsoff_t length = 0; 1384 - jsoff_t scan = next; 1429 + jsoff_t first = loadoff(js, (jsoff_t) vdata(obj)) & ~(3U | FLAGMASK); 1430 + jsoff_t length = get_array_length(js, obj); 1385 1431 1386 - while (scan < js->brk && scan != 0) { 1387 - jsoff_t koff = loadoff(js, scan + (jsoff_t) sizeof(scan)); 1388 - jsoff_t klen = offtolen(loadoff(js, koff)); 1389 - const char *key = (char *) &js->mem[koff + sizeof(koff)]; 1390 - 1391 - if (streq(key, klen, "length", 6)) { 1392 - jsval_t val = loadval(js, scan + (jsoff_t) (sizeof(scan) + sizeof(koff))); 1393 - if (vtype(val) == T_NUM) length = (jsoff_t) tod(val); 1394 - break; 1395 - } 1396 - scan = loadoff(js, scan) & ~(3U | FLAGMASK); 1397 - } 1398 - 1399 - const char *class_name = NULL; 1400 - jsoff_t class_name_len = 0; 1401 - do { 1402 - jsval_t ctor_val = get_slot(js, obj, SLOT_CTOR); 1403 - if (vtype(ctor_val) != T_FUNC) { 1404 - jsval_t proto_val = get_slot(js, obj, SLOT_PROTO); 1405 - if (vtype(proto_val) == T_OBJ) { 1406 - jsoff_t ctor_off = lkp(js, proto_val, "constructor", 11); 1407 - if (ctor_off != 0) ctor_val = resolveprop(js, mkval(T_PROP, ctor_off)); 1408 - } 1409 - } 1410 - if (vtype(ctor_val) != T_FUNC) break; 1411 - 1412 - jsoff_t name_off = lkp(js, mkval(T_OBJ, vdata(ctor_val)), "name", 4); 1413 - if (name_off == 0) break; 1414 - 1415 - jsval_t name_val = resolveprop(js, mkval(T_PROP, name_off)); 1416 - if (vtype(name_val) != T_STR) break; 1417 - 1418 - jsoff_t name_str_off = vstr(js, name_val, &class_name_len); 1419 - class_name = (const char *) &js->mem[name_str_off]; 1420 - 1421 - if (class_name_len == 5 && memcmp(class_name, "Array", 5) == 0) { 1422 - class_name = NULL; 1423 - class_name_len = 0; 1424 - } 1425 - } while (0); 1432 + jsoff_t class_len = 0; 1433 + const char *class_name = get_class_name(js, obj, &class_len, "Array"); 1426 1434 1427 1435 int elem_count = 0; 1428 1436 bool inline_mode = is_small_array(js, obj, &elem_count); 1429 - 1430 1437 size_t n = 0; 1431 1438 1432 - if (class_name && class_name_len > 0) { 1433 - n += cpy(buf + n, len - n, class_name, class_name_len); 1439 + if (class_name) { 1440 + n += cpy(buf + n, len - n, class_name, class_len); 1434 1441 n += (size_t) snprintf(buf + n, len - n, "(%u) ", (unsigned) length); 1435 1442 } 1436 1443 ··· 1449 1456 1450 1457 char idx[16]; 1451 1458 snprintf(idx, sizeof(idx), "%u", (unsigned) i); 1452 - 1453 1459 jsoff_t idxlen = (jsoff_t) strlen(idx); 1454 - jsoff_t prop = next; 1455 - jsval_t val = js_mkundef(); 1456 1460 1457 1461 bool found = false; 1458 - 1459 - while (prop < js->brk && prop != 0) { 1460 - jsoff_t koff = loadoff(js, prop + (jsoff_t) sizeof(prop)); 1461 - jsoff_t klen = offtolen(loadoff(js, koff)); 1462 - const char *key = (char *) &js->mem[koff + sizeof(koff)]; 1462 + jsval_t val = js_mkundef(); 1463 + for (jsoff_t p = first; p < js->brk && p != 0; p = next_prop(loadoff(js, p))) { 1464 + const char *key; jsoff_t klen; 1465 + get_prop_key(js, p, &key, &klen); 1463 1466 if (streq(key, klen, idx, idxlen)) { 1464 - val = loadval(js, prop + (jsoff_t) (sizeof(prop) + sizeof(koff))); 1465 - found = true; 1466 - break; 1467 + val = get_prop_val(js, p); 1468 + found = true; break; 1467 1469 } 1468 - prop = loadoff(js, prop) & ~(3U | FLAGMASK); 1469 1470 } 1470 - 1471 - if (found) { 1472 - n += tostr(js, val, buf + n, len - n); 1473 - } else n += cpy(buf + n, len - n, "undefined", 9); 1471 + n += found ? tostr(js, val, buf + n, len - n) : cpy(buf + n, len - n, "undefined", 9); 1474 1472 } 1475 1473 1476 - scan = next; 1477 - while (scan < js->brk && scan != 0) { 1478 - jsoff_t header = loadoff(js, scan); 1479 - if (!is_slot_prop(header)) { 1480 - jsoff_t koff = loadoff(js, scan + (jsoff_t) sizeof(scan)); 1481 - jsoff_t klen = offtolen(loadoff(js, koff)); 1482 - const char *key = (char *) &js->mem[koff + sizeof(koff)]; 1483 - 1484 - if (!streq(key, klen, "length", 6) && !is_array_index(key, klen)) { 1485 - n += cpy(buf + n, len - n, inline_mode ? ", " : ",\n", 2); 1486 - if (!inline_mode) n += add_indent(buf + n, len - n, stringify_indent); 1487 - n += cpy(buf + n, len - n, key, klen); 1488 - n += cpy(buf + n, len - n, ": ", 2); 1489 - jsval_t val = loadval(js, scan + (jsoff_t) (sizeof(scan) + sizeof(koff))); 1490 - n += tostr(js, val, buf + n, len - n); 1491 - } 1492 - } 1493 - scan = header & ~(3U | FLAGMASK); 1474 + for (jsoff_t p = first; p < js->brk && p != 0; p = next_prop(loadoff(js, p))) { 1475 + jsoff_t header = loadoff(js, p); 1476 + if (is_slot_prop(header)) continue; 1477 + 1478 + const char *key; jsoff_t klen; 1479 + get_prop_key(js, p, &key, &klen); 1480 + if (streq(key, klen, "length", 6) || is_array_index(key, klen)) continue; 1481 + 1482 + n += cpy(buf + n, len - n, inline_mode ? ", " : ",\n", 2); 1483 + if (!inline_mode) n += add_indent(buf + n, len - n, stringify_indent); 1484 + n += cpy(buf + n, len - n, key, klen); 1485 + n += cpy(buf + n, len - n, ": ", 2); 1486 + n += tostr(js, get_prop_val(js, p), buf + n, len - n); 1494 1487 } 1495 1488 1496 1489 if (!inline_mode) { ··· 1501 1494 1502 1495 n += cpy(buf + n, len - n, inline_mode ? " ]" : "]", inline_mode ? 2 : 1); 1503 1496 pop_stringify(); 1504 - 1505 1497 return n; 1506 1498 } 1507 1499 ··· 1803 1795 proto_is_null_proto = (vtype(proto_proto) == T_NULL) && 1804 1796 (vdata(proto_val) != vdata(object_proto)); 1805 1797 1806 - jsval_t ctor_val = js_mkundef(); 1807 - jsoff_t ctor_off = lkp(js, proto_val, "constructor", 11); 1808 - if (ctor_off != 0) ctor_val = resolveprop(js, mkval(T_PROP, ctor_off)); 1809 - 1810 - if (vtype(ctor_val) != T_FUNC) ctor_val = get_slot(js, obj, SLOT_CTOR); 1811 - if (vtype(ctor_val) != T_FUNC) break; 1812 - 1813 - jsoff_t name_off = lkp(js, mkval(T_OBJ, vdata(ctor_val)), "name", 4); 1814 - if (name_off == 0) break; 1815 - 1816 - jsval_t name_val = resolveprop(js, mkval(T_PROP, name_off)); 1817 - if (vtype(name_val) != T_STR) break; 1818 - 1819 - jsoff_t name_str_off = vstr(js, name_val, &class_name_len); 1820 - class_name = (const char *) &js->mem[name_str_off]; 1821 - 1822 - if (class_name_len == 6 && memcmp(class_name, "Object", 6) == 0) { 1823 - class_name = NULL; 1824 - class_name_len = 0; 1825 - } 1798 + class_name = get_class_name(js, obj, &class_name_len, "Object"); 1826 1799 } while (0); 1827 1800 1828 1801 if (prop_count == 0) { ··· 2061 2034 } 2062 2035 2063 2036 static size_t strfunc(struct js *js, jsval_t value, char *buf, size_t len) { 2037 + jsoff_t name_len = 0; 2038 + const char *name = get_func_name(js, value, &name_len); 2064 2039 jsval_t func_obj = mkval(T_OBJ, vdata(value)); 2065 2040 jsval_t code_slot = get_slot(js, func_obj, SLOT_CODE); 2066 - 2067 - jsoff_t name_off = lkp(js, func_obj, "name", 4); 2068 - const char *name = NULL; 2069 - jsoff_t name_len = 0; 2070 - if (name_off != 0) { 2071 - jsval_t name_val = resolveprop(js, mkval(T_PROP, name_off)); 2072 - if (vtype(name_val) == T_STR) { 2073 - name_len = 0; 2074 - jsoff_t noff = vstr(js, name_val, &name_len); 2075 - name = (const char *) &js->mem[noff]; 2076 - } 2077 - } 2078 - 2079 2041 jsval_t builtin_slot = get_slot(js, func_obj, SLOT_BUILTIN); 2080 2042 if (vtype(builtin_slot) == T_NUM) { 2081 2043 if (name && name_len > 0) { ··· 8515 8477 } 8516 8478 res = do_op(js, TOK_CALL, res, params); 8517 8479 pop_this(); 8518 - // to be cleaned up 8519 - if (is_super_call && !is_err(res)) { 8520 - uint8_t rt = vtype(res); 8521 - if (rt == T_OBJ || rt == T_ARR || rt == T_FUNC || rt == T_PROMISE) { 8522 - jsoff_t proto_off = lkp_interned(js, mkval(T_OBJ, vdata(js->current_func)), INTERN_PROTOTYPE, 9); 8523 - if (proto_off != 0) { 8524 - jsval_t subclass_proto = resolveprop(js, mkval(T_PROP, proto_off)); 8525 - set_proto(js, res, subclass_proto); 8526 - } 8527 - js->this_val = res; 8528 - if (global_this_stack.depth > 0) global_this_stack.stack[global_this_stack.depth - 1] = res; 8529 - } 8480 + if (is_super_call && !is_err(res) && is_object_type(res)) { 8481 + jsoff_t proto_off = lkp_interned(js, mkval(T_OBJ, vdata(js->current_func)), INTERN_PROTOTYPE, 9); 8482 + if (proto_off) set_proto(js, res, resolveprop(js, mkval(T_PROP, proto_off))); 8483 + js->this_val = res; 8484 + if (global_this_stack.depth > 0) global_this_stack.stack[global_this_stack.depth - 1] = res; 8530 8485 } 8531 8486 obj = js_mkundef(); 8532 8487 }