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.

add support for null prototype objects in stringification

+90 -27
+1
include/config.h
··· 53 53 SLOT_PROXY_REF, 54 54 SLOT_BUILTIN, 55 55 SLOT_DATA, 56 + SLOT_CTOR, 56 57 SLOT_MAX = 255 57 58 } internal_slot_t; 58 59
+1
include/config.h.in
··· 42 42 SLOT_PROXY_REF, 43 43 SLOT_BUILTIN, 44 44 SLOT_DATA, 45 + SLOT_CTOR, 45 46 SLOT_MAX = 255 46 47 } internal_slot_t; 47 48
+88 -27
src/ant.c
··· 1343 1343 uint8_t t = vtype(val); 1344 1344 if (t == T_OBJ || t == T_ARR || t == T_FUNC) has_nested = true; 1345 1345 count++; 1346 - } else { 1347 - count++; 1348 - } 1346 + } else count++; 1349 1347 } 1350 1348 1351 1349 if (elem_count) *elem_count = count; ··· 1377 1375 int elem_count = 0; 1378 1376 bool inline_mode = is_small_array(js, obj, &elem_count); 1379 1377 1380 - size_t n = cpy(buf, len, inline_mode ? "[ " : "[\n", 2); 1378 + if (length == 0) { 1379 + pop_stringify(); 1380 + return cpy(buf, len, "[]", 2); 1381 + } 1381 1382 1383 + size_t n = cpy(buf, len, inline_mode ? "[ " : "[\n", 2); 1382 1384 if (!inline_mode) stringify_indent++; 1383 1385 1384 1386 for (jsoff_t i = 0; i < length; i++) { ··· 1408 1410 1409 1411 if (found) { 1410 1412 n += tostr(js, val, buf + n, len - n); 1411 - } else { 1412 - n += cpy(buf + n, len - n, "undefined", 9); 1413 - } 1413 + } else n += cpy(buf + n, len - n, "undefined", 9); 1414 1414 } 1415 1415 1416 1416 if (!inline_mode) { ··· 1421 1421 1422 1422 n += cpy(buf + n, len - n, inline_mode ? " ]" : "]", inline_mode ? 2 : 1); 1423 1423 pop_stringify(); 1424 + 1424 1425 return n; 1425 1426 } 1426 1427 ··· 1627 1628 static bool is_small_object(struct js *js, jsval_t obj, int *prop_count) { 1628 1629 int count = 0; 1629 1630 bool has_nested = false; 1630 - jsoff_t next = loadoff(js, (jsoff_t) vdata(obj)) & ~(3U | FLAGMASK); 1631 + 1632 + jsoff_t obj_off = (jsoff_t)vdata(obj); 1633 + jsoff_t next = loadoff(js, obj_off) & ~(3U | FLAGMASK); 1631 1634 1632 1635 while (next < js->brk && next != 0) { 1633 1636 jsoff_t header = loadoff(js, next); ··· 1635 1638 1636 1639 jsoff_t koff = loadoff(js, next + (jsoff_t) sizeof(next)); 1637 1640 jsoff_t klen = offtolen(loadoff(js, koff)); 1641 + 1638 1642 const char *key = (char *) &js->mem[koff + sizeof(koff)]; 1643 + const char *tag_sym_key = get_toStringTag_sym_key(); 1644 + bool should_hide = streq(key, klen, tag_sym_key, strlen(tag_sym_key)); 1639 1645 1640 - bool is_desc = (klen > 7 && key[0] == '_' && key[1] == '_' && key[2] == 'd' && key[3] == 'e' && key[4] == 's' && key[5] == 'c' && key[6] == '_'); 1641 - const char *tag_sym_key = get_toStringTag_sym_key(); 1642 - bool should_hide = streq(key, klen, STR_PROTO, STR_PROTO_LEN) || streq(key, klen, tag_sym_key, strlen(tag_sym_key)) || is_desc; 1646 + if (!should_hide) { 1647 + descriptor_entry_t *desc = lookup_descriptor(obj_off, key, klen); 1648 + if (desc) if (desc->has_getter || desc->has_setter || !desc->enumerable) should_hide = true; 1649 + } 1643 1650 1644 1651 if (!should_hide) { 1645 1652 jsval_t val = loadval(js, next + (jsoff_t) (sizeof(next) + sizeof(koff))); ··· 1647 1654 if (t == T_OBJ || t == T_ARR || t == T_FUNC) has_nested = true; 1648 1655 count++; 1649 1656 } 1657 + 1650 1658 next = next_prop(header); 1651 1659 } 1652 1660 ··· 1776 1784 1777 1785 jsval_t proto_val = js_get_proto(js, obj); 1778 1786 bool is_null_proto = (vtype(proto_val) == T_NULL); 1787 + bool proto_is_null_proto = false; 1779 1788 const char *class_name = NULL; 1780 1789 jsoff_t class_name_len = 0; 1781 1790 ··· 1784 1793 uint8_t pt = vtype(proto_val); 1785 1794 if (pt != T_OBJ && pt != T_FUNC) break; 1786 1795 1796 + jsval_t proto_proto = js_get_proto(js, proto_val); 1797 + jsval_t object_proto = get_ctor_proto(js, "Object", 6); 1798 + proto_is_null_proto = (vtype(proto_proto) == T_NULL) && 1799 + (vdata(proto_val) != vdata(object_proto)); 1800 + 1801 + jsval_t ctor_val = js_mkundef(); 1787 1802 jsoff_t ctor_off = lkp(js, proto_val, "constructor", 11); 1788 - if (ctor_off == 0) break; 1803 + if (ctor_off != 0) ctor_val = resolveprop(js, mkval(T_PROP, ctor_off)); 1789 1804 1790 - jsval_t ctor_val = resolveprop(js, mkval(T_PROP, ctor_off)); 1805 + if (vtype(ctor_val) != T_FUNC) ctor_val = get_slot(js, obj, SLOT_CTOR); 1791 1806 if (vtype(ctor_val) != T_FUNC) break; 1792 1807 1793 1808 jsoff_t name_off = lkp(js, mkval(T_OBJ, vdata(ctor_val)), "name", 4); ··· 1810 1825 n += cpy(buf + n, len - n, "[Object: null prototype] {}", 27); 1811 1826 } else if (class_name && class_name_len > 0) { 1812 1827 n += cpy(buf + n, len - n, class_name, class_name_len); 1813 - n += cpy(buf + n, len - n, " {}", 3); 1814 - } else { 1815 - n += cpy(buf + n, len - n, "{}", 2); 1816 - } 1828 + if (proto_is_null_proto) { 1829 + n += cpy(buf + n, len - n, " <[Object: null prototype] {}> {}", 33); 1830 + } else n += cpy(buf + n, len - n, " {}", 3); 1831 + } else if (proto_is_null_proto) { 1832 + n += cpy(buf + n, len - n, "<[Object: null prototype] {}> {}", 32); 1833 + } else n += cpy(buf + n, len - n, "{}", 2); 1817 1834 pop_stringify(); 1818 1835 return n; 1819 1836 } ··· 1822 1839 n += cpy(buf + n, len - n, "[Object: null prototype] ", 25); 1823 1840 } else if (class_name && class_name_len > 0) { 1824 1841 n += cpy(buf + n, len - n, class_name, class_name_len); 1825 - n += cpy(buf + n, len - n, " ", 1); 1842 + if (proto_is_null_proto) { 1843 + n += cpy(buf + n, len - n, " <[Object: null prototype] {}> ", 31); 1844 + } else n += cpy(buf + n, len - n, " ", 1); 1845 + } else if (proto_is_null_proto) { 1846 + n += cpy(buf + n, len - n, "<[Object: null prototype] {}> ", 30); 1826 1847 } 1827 1848 1828 1849 n += cpy(buf + n, len - n, inline_mode ? "{ " : "{\n", 2); ··· 1843 1864 1844 1865 jsoff_t koff = loadoff(js, next + (jsoff_t) sizeof(next)); 1845 1866 jsoff_t klen = offtolen(loadoff(js, koff)); 1846 - const char *key = (char *) &js->mem[koff + sizeof(koff)]; 1847 1867 1848 - bool is_desc = (klen > 7 && key[0] == '_' && key[1] == '_' && key[2] == 'd' && key[3] == 'e' && key[4] == 's' && key[5] == 'c' && key[6] == '_'); 1868 + const char *key = (char *) &js->mem[koff + sizeof(koff)]; 1849 1869 const char *tag_sym_key = get_toStringTag_sym_key(); 1850 - bool should_hide = streq(key, klen, STR_PROTO, STR_PROTO_LEN) || streq(key, klen, tag_sym_key, strlen(tag_sym_key)) || is_desc; 1870 + bool should_hide = streq(key, klen, tag_sym_key, strlen(tag_sym_key)); 1851 1871 1852 1872 if (!should_hide) { 1853 1873 jsoff_t obj_off = (jsoff_t)vdata(obj); 1854 1874 descriptor_entry_t *desc = lookup_descriptor(obj_off, key, klen); 1855 - if (desc) { 1856 - if (desc->has_getter || desc->has_setter) { 1857 - should_hide = true; 1858 - } else if (!desc->enumerable) should_hide = true; 1859 - } 1875 + if (desc) if (desc->has_getter || desc->has_setter || !desc->enumerable) should_hide = true; 1860 1876 } 1861 1877 1862 1878 if (!should_hide) { ··· 3242 3258 js_set_descriptor(js, func, "prototype", 9, JS_DESC_W); 3243 3259 3244 3260 return js_mkundef(); 3261 + } 3262 + 3263 + static void infer_func_name(struct js *js, jsval_t func, const char *name, size_t len) { 3264 + jsval_t func_obj = mkval(T_OBJ, vdata(func)); 3265 + if (vtype(get_slot(js, func_obj, SLOT_NAME)) != T_UNDEF) return; 3266 + jsval_t name_val = js_mkstr(js, name, len); 3267 + set_slot(js, func_obj, SLOT_NAME, name_val); 3268 + setprop(js, func_obj, js_mkstr(js, "name", 4), name_val); 3245 3269 } 3246 3270 3247 3271 static jsval_t validate_array_length(struct js *js, jsval_t v) { ··· 8525 8549 rtype == T_OBJ || rtype == T_ARR || 8526 8550 rtype == T_PROMISE || rtype == T_FUNC 8527 8551 ) ? result : constructed_obj; 8552 + 8553 + if (vtype(new_result) == T_OBJ && (vtype(ctor) == T_FUNC || vtype(ctor) == T_CFUNC)) { 8554 + set_slot(js, new_result, SLOT_CTOR, ctor); 8555 + } 8528 8556 8529 8557 jsval_t call_obj = js_mkundef(); 8530 8558 while (next(js) == TOK_DOT || next(js) == TOK_LBRACKET || next(js) == TOK_OPTIONAL_CHAIN || next(js) == TOK_LPAREN) { ··· 9441 9469 char decoded_name[256]; 9442 9470 size_t decoded_len = decode_ident_escapes(name, nlen, decoded_name, sizeof(decoded_name)); 9443 9471 9472 + jsval_t resolved = resolveprop(js, v); 9473 + if (vtype(resolved) == T_FUNC) infer_func_name(js, resolved, decoded_name, decoded_len); 9474 + 9444 9475 if (lkp_scope(js, js->scope, decoded_name, decoded_len) > 0) return js_mkerr(js, "'%.*s' already declared", (int) decoded_len, decoded_name); 9445 - jsval_t x = mkprop(js, js->scope, js_mkstr(js, decoded_name, decoded_len), resolveprop(js, v), is_const ? CONSTMASK : 0); 9476 + jsval_t x = mkprop(js, js->scope, js_mkstr(js, decoded_name, decoded_len), resolved, is_const ? CONSTMASK : 0); 9477 + 9446 9478 if (is_err(x)) return x; 9447 9479 } 9448 9480 } ··· 20826 20858 jsval_t glob = js->scope; 20827 20859 jsval_t object_proto = js_mkobj(js); 20828 20860 set_proto(js, object_proto, js_mknull()); 20861 + 20829 20862 setprop(js, object_proto, js_mkstr(js, "toString", 8), js_mkfun(builtin_object_toString)); 20863 + js_set_descriptor(js, object_proto, "toString", 8, JS_DESC_W | JS_DESC_C); 20864 + 20830 20865 setprop(js, object_proto, js_mkstr(js, "valueOf", 7), js_mkfun(builtin_object_valueOf)); 20866 + js_set_descriptor(js, object_proto, "valueOf", 7, JS_DESC_W | JS_DESC_C); 20867 + 20831 20868 setprop(js, object_proto, js_mkstr(js, "toLocaleString", 14), js_mkfun(builtin_object_toLocaleString)); 20869 + js_set_descriptor(js, object_proto, "toLocaleString", 14, JS_DESC_W | JS_DESC_C); 20870 + 20832 20871 setprop(js, object_proto, js_mkstr(js, "hasOwnProperty", 14), js_mkfun(builtin_object_hasOwnProperty)); 20872 + js_set_descriptor(js, object_proto, "hasOwnProperty", 14, JS_DESC_W | JS_DESC_C); 20873 + 20833 20874 setprop(js, object_proto, js_mkstr(js, "isPrototypeOf", 13), js_mkfun(builtin_object_isPrototypeOf)); 20875 + js_set_descriptor(js, object_proto, "isPrototypeOf", 13, JS_DESC_W | JS_DESC_C); 20876 + 20834 20877 setprop(js, object_proto, js_mkstr(js, "propertyIsEnumerable", 20), js_mkfun(builtin_object_propertyIsEnumerable)); 20878 + js_set_descriptor(js, object_proto, "propertyIsEnumerable", 20, JS_DESC_W | JS_DESC_C); 20835 20879 20836 20880 jsval_t proto_getter = js_mkfun(builtin_proto_getter); 20837 20881 jsval_t proto_setter = js_mkfun(builtin_proto_setter); ··· 21345 21389 js->module_ns = js_mkundef(); 21346 21390 21347 21391 setprop(js, object_proto, js_mkstr(js, "constructor", 11), mkval(T_FUNC, vdata(obj_func_obj))); 21392 + js_set_descriptor(js, object_proto, "constructor", 11, JS_DESC_W | JS_DESC_C); 21393 + 21348 21394 setprop(js, function_proto, js_mkstr(js, "constructor", 11), mkval(T_FUNC, vdata(func_ctor_obj))); 21395 + js_set_descriptor(js, function_proto, "constructor", 11, JS_DESC_W | JS_DESC_C); 21396 + 21349 21397 setprop(js, array_proto, js_mkstr(js, "constructor", 11), mkval(T_FUNC, vdata(arr_ctor_obj))); 21398 + js_set_descriptor(js, array_proto, "constructor", 11, JS_DESC_W | JS_DESC_C); 21399 + 21350 21400 setprop(js, string_proto, js_mkstr(js, "constructor", 11), mkval(T_FUNC, vdata(str_ctor_obj))); 21401 + js_set_descriptor(js, string_proto, "constructor", 11, JS_DESC_W | JS_DESC_C); 21402 + 21351 21403 setprop(js, number_proto, js_mkstr(js, "constructor", 11), mkval(T_FUNC, vdata(number_ctor_obj))); 21404 + js_set_descriptor(js, number_proto, "constructor", 11, JS_DESC_W | JS_DESC_C); 21405 + 21352 21406 setprop(js, boolean_proto, js_mkstr(js, "constructor", 11), mkval(T_FUNC, vdata(bool_ctor_obj))); 21407 + js_set_descriptor(js, boolean_proto, "constructor", 11, JS_DESC_W | JS_DESC_C); 21408 + 21353 21409 setprop(js, date_proto, js_mkstr(js, "constructor", 11), mkval(T_FUNC, vdata(date_ctor_obj))); 21410 + js_set_descriptor(js, date_proto, "constructor", 11, JS_DESC_W | JS_DESC_C); 21411 + 21354 21412 setprop(js, regexp_proto, js_mkstr(js, "constructor", 11), mkval(T_FUNC, vdata(regex_ctor_obj))); 21413 + js_set_descriptor(js, regexp_proto, "constructor", 11, JS_DESC_W | JS_DESC_C); 21414 + 21355 21415 setprop(js, error_proto, js_mkstr(js, "constructor", 11), mkval(T_FUNC, vdata(err_ctor_obj))); 21416 + js_set_descriptor(js, error_proto, "constructor", 11, JS_DESC_W | JS_DESC_C); 21356 21417 21357 21418 set_proto(js, glob, object_proto); 21358 21419