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.

fix es2019 symbol descriptions and function source strings

+101 -36
+9 -9
examples/results.txt
··· 1297 1297 compat-table/es2019/Object.fromEntries.js: OK 1298 1298 compat-table/es2019/String.prototype.trimEnd.js: OK 1299 1299 compat-table/es2019/String.prototype.trimStart.js: OK 1300 - compat-table/es2019/Symbol.prototype.description.empty.js: failed 1300 + compat-table/es2019/Symbol.prototype.description.empty.js: OK 1301 1301 compat-table/es2019/Symbol.prototype.description.js: OK 1302 - compat-table/es2019/Symbol.prototype.description.undefined.js: TypeError: undefined is not a function 1303 - compat-table/es2019/annex-b.String.prototype.trimLeft.js: TypeError: undefined is not a function 1304 - compat-table/es2019/annex-b.String.prototype.trimRight.js: TypeError: undefined is not a function 1302 + compat-table/es2019/Symbol.prototype.description.undefined.js: OK 1303 + compat-table/es2019/annex-b.String.prototype.trimLeft.js: OK 1304 + compat-table/es2019/annex-b.String.prototype.trimRight.js: OK 1305 1305 compat-table/es2019/misc.Function-toString.Function-constructor.js: OK 1306 - compat-table/es2019/misc.Function-toString.arrows.js: failed 1307 - compat-table/es2019/misc.Function-toString.class-explicit-constructor.js: failed 1308 - compat-table/es2019/misc.Function-toString.class-implicit-constructor.js: failed 1309 - compat-table/es2019/misc.Function-toString.computed-names.js: failed 1306 + compat-table/es2019/misc.Function-toString.arrows.js: OK 1307 + compat-table/es2019/misc.Function-toString.class-explicit-constructor.js: OK 1308 + compat-table/es2019/misc.Function-toString.class-implicit-constructor.js: OK 1309 + compat-table/es2019/misc.Function-toString.computed-names.js: OK 1310 1310 compat-table/es2019/misc.Function-toString.native-code.js: OK 1311 - compat-table/es2019/misc.Function-toString.unicode-escapes.js: failed 1311 + compat-table/es2019/misc.Function-toString.unicode-escapes.js: OK 1312 1312 compat-table/es2019/misc.JSON-stringify-well-formed.js: OK 1313 1313 compat-table/es2019/misc.JSON-superset.line-separator.js: OK 1314 1314 compat-table/es2019/misc.JSON-superset.paragraph-separator.js: OK
+2 -2
include/silver/opcode.h
··· 217 217 OP_DEF( APPEND, 1, 3, 2, none) /* append to array, update length */ 218 218 OP_DEF( COPY_DATA_PROPS, 2, 3, 3, u8) /* Object.assign-like */ 219 219 220 - OP_DEF( DEFINE_CLASS, 6, 2, 2, atom_u8) /* parent ctor -> ctor proto */ 221 - OP_DEF( DEFINE_CLASS_COMP, 6, 3, 3, atom_u8) /* computed name variant */ 220 + OP_DEF( DEFINE_CLASS, 14, 2, 2, atom_u8) /* parent ctor -> ctor proto */ 221 + OP_DEF( DEFINE_CLASS_COMP, 14, 3, 3, atom_u8) /* computed name variant */ 222 222 OP_DEF( ADD_BRAND, 1, 2, 0, none) /* this_obj home_obj -> (private brand) */ 223 223 224 224 OP_DEF( TO_OBJECT, 1, 1, 1, none) /* coerce to object wrapper */
+21 -15
src/ant.c
··· 4237 4237 return result; 4238 4238 } 4239 4239 4240 - #define SYM_FLAG_GLOBAL 1u 4241 - #define SYM_FLAG_WELL_KNOWN 2u 4240 + enum { 4241 + SYM_FLAG_GLOBAL = 1u, 4242 + SYM_FLAG_WELL_KNOWN = 2u, 4243 + SYM_FLAG_HAS_DESC = 4u, 4244 + }; 4242 4245 4243 4246 typedef struct sym_registry_entry { 4244 4247 const char *key; ··· 4248 4251 4249 4252 ant_value_t js_mksym(ant_t *js, const char *desc) { 4250 4253 uint32_t id = (uint32_t)(++js->sym.counter); 4251 - size_t desc_len = (desc && *desc) ? strlen(desc) : 0; 4252 - size_t total = sizeof(ant_symbol_heap_t) + (desc_len ? desc_len + 1 : 0); 4254 + bool has_desc = desc != NULL; 4255 + 4256 + size_t desc_len = has_desc ? strlen(desc) : 0; 4257 + size_t total = sizeof(ant_symbol_heap_t) + (has_desc ? desc_len + 1 : 0); 4258 + 4253 4259 ant_symbol_heap_t *sym_ptr = (ant_symbol_heap_t *)js_type_alloc( 4254 - js, ANT_ALLOC_SYMBOL, total, _Alignof(ant_symbol_heap_t) 4255 - ); 4256 - if (!sym_ptr) return js_mkerr(js, "oom"); 4260 + js, ANT_ALLOC_SYMBOL, total, 4261 + _Alignof(ant_symbol_heap_t) 4262 + ); if (!sym_ptr) return js_mkerr(js, "oom"); 4257 4263 4258 4264 sym_ptr->id = id; 4259 - sym_ptr->flags = 0; 4265 + sym_ptr->flags = has_desc ? SYM_FLAG_HAS_DESC : 0; 4260 4266 sym_ptr->key = NULL; 4261 4267 sym_ptr->desc_len = (uint32_t)desc_len; 4262 - if (desc_len) { 4268 + 4269 + if (has_desc) { 4263 4270 memcpy(sym_ptr->desc, desc, desc_len); 4264 4271 sym_ptr->desc[desc_len] = '\0'; 4265 4272 } ··· 4296 4303 4297 4304 const inline char *js_sym_desc(ant_value_t sym) { 4298 4305 ant_symbol_heap_t *ptr = sym_ptr(sym); 4299 - if (!ptr || ptr->desc_len == 0) return NULL; 4306 + if (!ptr || !(ptr->flags & SYM_FLAG_HAS_DESC)) return NULL; 4300 4307 return ptr->desc; 4301 4308 } 4302 4309 ··· 5706 5713 memcpy(bc->bound_argv, bound_args, sizeof(ant_value_t) * (size_t)bound_argc); 5707 5714 bc->bound_argc = bound_argc; 5708 5715 } 5709 - js_setprop(js, bound_func, js->length_str, tov((double) bound_length)); 5710 5716 5717 + js_setprop(js, bound_func, js->length_str, tov((double) bound_length)); 5711 5718 ant_value_t proto_setup = setup_func_prototype(js, bound); 5719 + 5712 5720 if (is_err(proto_setup)) return proto_setup; 5713 - 5714 5721 js_mark_constructor(bound_func, js_is_constructor(func)); 5715 5722 5716 5723 return bound; ··· 10662 10669 } 10663 10670 10664 10671 static ant_value_t builtin_string_trim(ant_t *js, ant_value_t *args, int nargs) { 10665 - (void) args; (void) nargs; 10666 10672 ant_value_t str = to_string_val(js, js->this_val); 10667 10673 if (vtype(str) != T_STR) return js_mkerr(js, "trim called on non-string"); 10668 10674 ··· 10677 10683 } 10678 10684 10679 10685 static ant_value_t builtin_string_trimStart(ant_t *js, ant_value_t *args, int nargs) { 10680 - (void) args; (void) nargs; 10681 10686 ant_value_t str = to_string_val(js, js->this_val); 10682 10687 if (vtype(str) != T_STR) return js_mkerr(js, "trimStart called on non-string"); 10683 10688 ··· 10691 10696 } 10692 10697 10693 10698 static ant_value_t builtin_string_trimEnd(ant_t *js, ant_value_t *args, int nargs) { 10694 - (void) args; (void) nargs; 10695 10699 ant_value_t str = to_string_val(js, js->this_val); 10696 10700 if (vtype(str) != T_STR) return js_mkerr(js, "trimEnd called on non-string"); 10697 10701 ··· 14422 14426 defmethod(js, string_proto, "trim", 4, js_mkfun(builtin_string_trim)); 14423 14427 defmethod(js, string_proto, "trimStart", 9, js_mkfun(builtin_string_trimStart)); 14424 14428 defmethod(js, string_proto, "trimEnd", 7, js_mkfun(builtin_string_trimEnd)); 14429 + defmethod(js, string_proto, "trimLeft", 8, js_mkfun(builtin_string_trimStart)); 14430 + defmethod(js, string_proto, "trimRight", 9, js_mkfun(builtin_string_trimEnd)); 14425 14431 defmethod(js, string_proto, "repeat", 6, js_mkfun(builtin_string_repeat)); 14426 14432 defmethod(js, string_proto, "padStart", 8, js_mkfun(builtin_string_padStart)); 14427 14433 defmethod(js, string_proto, "padEnd", 6, js_mkfun(builtin_string_padEnd));
+22
src/modules/symbol.c
··· 64 64 return js_symbol_to_string(js, this_val); 65 65 } 66 66 67 + static ant_value_t builtin_Symbol_description(ant_t *js, ant_value_t *args, int nargs) { 68 + ant_value_t this_val = js_getthis(js); 69 + ant_value_t sym = this_val; 70 + 71 + if (vtype(sym) != T_SYMBOL && is_object_type(sym)) { 72 + ant_value_t prim = js_get_slot(sym, SLOT_PRIMITIVE); 73 + if (vtype(prim) == T_SYMBOL) sym = prim; 74 + } 75 + 76 + if (vtype(sym) != T_SYMBOL) 77 + return js_mkerr_typed(js, JS_ERR_TYPE, "Symbol.prototype.description requires a symbol"); 78 + 79 + const char *desc = js_sym_desc(sym); 80 + if (!desc) return js_mkundef(); 81 + 82 + return js_mkstr(js, desc, strlen(desc)); 83 + } 84 + 67 85 static ant_value_t get_iterator_prototype(ant_t *js) { 68 86 if (vtype(js->sym.iterator_proto) == T_OBJ) return js->sym.iterator_proto; 69 87 ··· 298 316 #undef INIT_SYM 299 317 300 318 ant_value_t symbol_proto = js_mkobj(js); 319 + ant_value_t object_proto = js->sym.object_proto; 320 + 321 + if (is_object_type(object_proto)) js_set_proto_init(symbol_proto, object_proto); 301 322 js_set(js, symbol_proto, "toString", js_mkfun(builtin_Symbol_toString)); 323 + js_set_getter_desc(js, symbol_proto, "description", 11, js_mkfun(builtin_Symbol_description), JS_DESC_C); 302 324 303 325 ant_value_t symbol_ctor = js_mkobj(js); 304 326 js_set_slot(symbol_ctor, SLOT_CFUNC, js_mkfun(builtin_Symbol));
+28 -7
src/silver/ast.c
··· 36 36 37 37 bool sv_ast_can_be_expression_statement(const sv_ast_t *node) { 38 38 if (!node) return false; 39 + if ((node->type == N_FUNC || node->type == N_CLASS) && (node->flags & FN_PAREN)) return true; 39 40 40 41 static const uint8_t expr_stmt_nodes[N__COUNT] = { 41 42 [N_NUMBER] = 1, [N_STRING] = 1, [N_BIGINT] = 1, [N_BOOL] = 1, ··· 269 270 return parse_assign(p); 270 271 } 271 272 273 + static inline uint32_t node_src_end(P, sv_ast_t *node) { 274 + if (node && node->src_end > node->src_off) return node->src_end; 275 + return (uint32_t)(TOFF + TLEN); 276 + } 277 + 272 278 static void sv_parse_stmt_list(P, sv_ast_list_t *out, bool stop_at_rbrace, bool directive_ctx) { 273 279 bool strict_mode = p->lx.strict; 274 280 bool saved_lexer_strict = p->lx.strict; ··· 416 422 fn->flags = FN_ARROW | FN_ASYNC; 417 423 fn->body = parse_arrow_body(p); 418 424 fn->src_off = async_off; 419 - fn->src_end = (uint32_t)(TOFF + TLEN); 425 + fn->src_end = node_src_end(p, fn->body); 420 426 return fn; 421 427 } 422 428 } ··· 431 437 push_arrow_params_from_expr(fn, expr); 432 438 fn->body = parse_arrow_body(p); 433 439 fn->src_off = async_off; 434 - fn->src_end = (uint32_t)(TOFF + TLEN); 440 + fn->src_end = node_src_end(p, fn->body); 435 441 return fn; 436 442 } 437 443 sv_lexer_restore_state(&p->lx, &saved); ··· 450 456 sv_ast_list_push(&fn->args, id); 451 457 fn->body = parse_arrow_body(p); 452 458 fn->src_off = async_off; 453 - fn->src_end = (uint32_t)(TOFF + TLEN); 459 + fn->src_end = node_src_end(p, fn->body); 454 460 return fn; 455 461 } 456 462 sv_lexer_restore_state(&p->lx, &saved); ··· 550 556 sv_ast_t *expr = parse_paren_expr(p); 551 557 expect(p, TOK_RPAREN); 552 558 expr->flags |= FN_PAREN; 553 - expr->src_off = paren_off; 559 + if (expr->type != N_FUNC && expr->type != N_CLASS) expr->src_off = paren_off; 554 560 return expr; 555 561 } 556 562 ··· 559 565 l_func: { CONSUME(); return parse_func(p); } 560 566 561 567 l_class: { 568 + uint32_t class_off = (uint32_t)TOFF; 562 569 CONSUME(); 563 - return parse_class(p); 570 + sv_ast_t *cls = parse_class(p); 571 + cls->src_off = class_off; 572 + return cls; 564 573 } 565 574 566 575 l_async: { ··· 883 892 884 893 prop->right = parse_func(p); 885 894 prop->right->flags |= FN_GENERATOR | FN_METHOD; 895 + prop->right->src_off = prop->src_off; 886 896 sv_ast_list_push(&n->args, prop); 887 897 if (NEXT() == TOK_COMMA) CONSUME(); 888 898 continue; ··· 917 927 918 928 prop->right = parse_func(p); 919 929 prop->right->flags |= FN_METHOD; 930 + prop->right->src_off = prop->src_off; 920 931 sv_ast_list_push(&n->args, prop); 921 932 if (NEXT() == TOK_COMMA) CONSUME(); 922 933 continue; ··· 958 969 prop->right->flags |= FN_ASYNC | FN_METHOD; 959 970 if (prop->flags & FN_GENERATOR) 960 971 prop->right->flags |= FN_GENERATOR; 972 + prop->right->src_off = prop->src_off; 961 973 sv_ast_list_push(&n->args, prop); 962 974 if (NEXT() == TOK_COMMA) CONSUME(); 963 975 continue; ··· 991 1003 } else if (TOK == TOK_LPAREN) { 992 1004 prop->right = parse_func(p); 993 1005 prop->right->flags |= FN_METHOD; 1006 + prop->right->src_off = prop->src_off; 994 1007 } else { 995 1008 prop->right = mk_ident(prop->left->str, prop->left->len); 996 1009 if (NEXT() == TOK_ASSIGN) { ··· 1219 1232 return mk(N_EMPTY); 1220 1233 } 1221 1234 fn->body = parse_arrow_body(p); 1222 - fn->src_end = (uint32_t)(TOFF + TLEN); 1235 + fn->src_end = node_src_end(p, fn->body); 1223 1236 return fn; 1224 1237 } 1225 1238 if (is_assign_op(op)) { ··· 1478 1491 sv_ast_list_push(&cls->args, method); 1479 1492 } 1480 1493 expect(p, TOK_RBRACE); 1494 + cls->src_end = (uint32_t)(TOFF + TLEN); 1481 1495 return cls; 1482 1496 } 1483 1497 ··· 1693 1707 return decl; 1694 1708 } 1695 1709 if (TOK == TOK_CLASS) { 1710 + uint32_t class_off = (uint32_t)TOFF; 1696 1711 CONSUME(); 1697 1712 decl->left = parse_class(p); 1713 + decl->left->src_off = class_off; 1698 1714 if (NEXT() == TOK_SEMICOLON) CONSUME(); 1699 1715 return decl; 1700 1716 } ··· 1727 1743 } 1728 1744 if (TOK == TOK_CLASS) { 1729 1745 decl->flags |= EX_DECL; 1746 + uint32_t class_off = (uint32_t)TOFF; 1730 1747 CONSUME(); 1731 1748 decl->left = parse_class(p); 1749 + decl->left->src_off = class_off; 1732 1750 if (!decl->left->str || decl->left->len == 0) 1733 1751 SV_MKERR_TYPED(JS, JS_ERR_SYNTAX, "exported class declarations require a name"); 1734 1752 return decl; ··· 2093 2111 } 2094 2112 2095 2113 l_class: { 2114 + uint32_t class_off = (uint32_t)TOFF; 2096 2115 CONSUME(); 2097 - return parse_class(p); 2116 + sv_ast_t *cls = parse_class(p); 2117 + cls->src_off = class_off; 2118 + return cls; 2098 2119 } 2099 2120 2100 2121 l_async: {
+3
src/silver/compiler.c
··· 4200 4200 emit_u32(c, 0); 4201 4201 emit(c, 0); 4202 4202 } 4203 + 4204 + emit_u32(c, node->src_off); 4205 + emit_u32(c, node->src_end); 4203 4206 4204 4207 int proto_local = add_local(c, "", 0, false, c->scope_depth); 4205 4208 int ctor_local = add_local(c, "", 0, false, c->scope_depth);
+3 -3
src/silver/engine.c
··· 1845 1845 L_APPEND: { sv_op_append(vm, js); NEXT(1); } 1846 1846 L_COPY_DATA_PROPS: { sv_op_copy_data_props(vm, js, ip); NEXT(2); } 1847 1847 1848 - L_DEFINE_CLASS: { sv_op_define_class(vm, js, func, ip); NEXT(6); } 1849 - L_DEFINE_CLASS_COMP: { sv_op_define_class_comp(vm, js, func, ip); NEXT(6); } 1850 - L_ADD_BRAND: { sv_op_add_brand(vm); NEXT(1); } 1848 + L_DEFINE_CLASS: { sv_op_define_class(vm, js, func, ip); NEXT(14); } 1849 + L_DEFINE_CLASS_COMP: { sv_op_define_class_comp(vm, js, func, ip); NEXT(14); } 1850 + L_ADD_BRAND: { sv_op_add_brand(vm); NEXT(1); } 1851 1851 1852 1852 L_TO_OBJECT: { VM_CHECK(sv_op_to_object(vm, js)); NEXT(1); } 1853 1853 L_TO_PROPKEY: { sv_op_to_propkey(vm, js); NEXT(1); }
+13
src/silver/ops/objects.h
··· 226 226 uint32_t atom_idx = sv_get_u32(ip + 1); 227 227 uint8_t cls_flags = sv_get_u8(ip + 5); 228 228 229 + uint32_t source_start = sv_get_u32(ip + 6); 230 + uint32_t source_end = sv_get_u32(ip + 10); 231 + 229 232 bool has_name = (cls_flags & 1) && (int)atom_idx < func->atom_count; 230 233 sv_atom_t *a = has_name ? &func->atoms[atom_idx] : NULL; 231 234 ant_value_t ctor = vm->stack[vm->sp - 1]; ··· 269 272 } 270 273 271 274 if (vtype(ctor) == T_FUNC) js_mark_constructor(js_func_obj(ctor), true); 275 + 276 + if ( 277 + vtype(ctor) == T_FUNC && func->source && 278 + source_end > source_start && source_end <= (uint32_t)func->source_len 279 + ) { 280 + js_set_slot(ctor, SLOT_CODE, mkval(T_NTARG, (uintptr_t)(func->source + source_start))); 281 + js_set_slot(ctor, SLOT_CODE_LEN, tov((double)(source_end - source_start))); 282 + } 283 + 272 284 setprop_interned(js, proto, "constructor", 11, ctor); 273 285 ant_value_t ctor_obj = (vtype(ctor) == T_FUNC) ? js_func_obj(ctor) : ctor; 274 286 js_mkprop_fast(js, ctor_obj, "prototype", 9, proto); 287 + 275 288 if (a && a->len > 0) 276 289 setprop_cstr(js, ctor, "name", 4, js_mkstr(js, a->str, a->len)); 277 290