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.

support super class expressions in class definitions

+67 -29
+67 -29
src/ant.c
··· 12845 12845 return js_mkerr_typed(js, JS_ERR_SYNTAX, "class name expected"); 12846 12846 } 12847 12847 12848 - jsoff_t super_off = 0, super_len = 0; 12849 - if (next(js) == TOK_IDENTIFIER && js->tlen == 7 && 12850 - streq(&js->code[js->toff], js->tlen, "extends", 7)) { 12848 + jsoff_t super_expr_off = 0, super_expr_len = 0; 12849 + if ( 12850 + next(js) == TOK_IDENTIFIER 12851 + && js->tlen == 7 12852 + && streq(&js->code[js->toff], js->tlen, "extends", 7) 12853 + ) { 12851 12854 js->consumed = 1; 12852 - EXPECT_IDENT(); 12853 - super_off = js->toff; 12854 - super_len = js->tlen; 12855 - js->consumed = 1; 12855 + if (next(js) == TOK_LBRACE || next(js) == TOK_EOF) { 12856 + return js_mkerr_typed(js, JS_ERR_SYNTAX, "super class expression expected"); 12857 + } 12858 + super_expr_off = js->toff; 12859 + uint8_t saved_flags = js->flags; 12860 + js->flags |= F_NOEXEC; 12861 + jsval_t super_expr = js_expr(js); 12862 + js->flags = saved_flags; 12863 + if (is_err(super_expr)) return super_expr; 12864 + super_expr_len = js->pos - super_expr_off; 12856 12865 } 12857 12866 12858 12867 EXPECT(TOK_LBRACE); ··· 12888 12897 12889 12898 uint8_t class_tok; 12890 12899 while ((class_tok = next(js)) != TOK_RBRACE && class_tok != TOK_EOF) { 12900 + if (class_tok == TOK_SEMICOLON) { js->consumed = 1; continue; } 12901 + 12891 12902 bool is_async_method = false; 12892 12903 bool is_static_member = false; 12893 12904 bool is_getter_method = false; ··· 12922 12933 int saved_stream_pos = js->token_stream_pos; 12923 12934 js->consumed = 1; 12924 12935 uint8_t peek = next(js); 12925 - bool next_is_name = (peek == TOK_IDENTIFIER); 12936 + bool next_is_name = ( 12937 + peek == TOK_IDENTIFIER || is_keyword_propname(peek) || 12938 + peek == TOK_STRING || peek == TOK_NUMBER || 12939 + peek == TOK_LBRACKET 12940 + ); 12926 12941 if (!next_is_name && peek == TOK_HASH) { 12927 12942 js->consumed = 1; 12928 12943 if (next(js) == TOK_IDENTIFIER) { ··· 13013 13028 continue; 13014 13029 } 13015 13030 13016 - if (next(js) != TOK_IDENTIFIER && (next(js) < TOK_ASYNC || next(js) > TOK_STATIC)) { 13031 + uint8_t name_tok = next(js); 13032 + bool name_is_ident = (name_tok == TOK_IDENTIFIER || is_keyword_propname(name_tok)); 13033 + bool name_is_literal = (name_tok == TOK_STRING || name_tok == TOK_NUMBER); 13034 + 13035 + if (!name_is_ident && !name_is_literal) { 13017 13036 js->flags = save_flags; 13018 13037 return js_mkerr_typed(js, JS_ERR_SYNTAX, "method name expected"); 13019 13038 } 13020 13039 13021 13040 jsoff_t method_name_off = is_private_member ? js->toff - 1 : js->toff; 13022 13041 jsoff_t method_name_len = is_private_member ? js->tlen + 1 : js->tlen; 13023 - js->consumed = 1; 13042 + bool name_needs_eval = name_is_literal; js->consumed = 1; 13024 13043 13025 13044 if (next(js) == TOK_ASSIGN) { 13026 13045 js->consumed = 1; ··· 13041 13060 .is_async = false, 13042 13061 .is_field = true, 13043 13062 .is_private = is_private_member, 13063 + .is_computed = name_needs_eval, 13044 13064 .field_start = field_start, 13045 13065 .field_end = field_end, 13046 13066 .fn_start = 0, ··· 13059 13079 .is_async = false, 13060 13080 .is_field = true, 13061 13081 .is_private = is_private_member, 13082 + .is_computed = name_needs_eval, 13062 13083 .field_start = 0, 13063 13084 .field_end = 0, 13064 13085 .fn_start = 0, ··· 13084 13105 return blk; 13085 13106 } 13086 13107 jsoff_t method_body_end = js->pos; 13087 - if (streq(&js->code[method_name_off], method_name_len, "constructor", 11)) { 13108 + if ( 13109 + !is_private_member 13110 + && !name_needs_eval 13111 + && streq(&js->code[method_name_off], method_name_len, "constructor", 11) 13112 + ) { 13088 13113 constructor_params_start = method_params_start; 13089 13114 constructor_body_start = method_body_start + 1; 13090 13115 constructor_body_end = method_body_end; ··· 13101 13126 .is_private = is_private_member, 13102 13127 .is_getter = is_getter_method, 13103 13128 .is_setter = is_setter_method, 13129 + .is_computed = name_needs_eval, 13104 13130 .field_start = 0, 13105 13131 .field_end = 0, 13106 13132 }; 13107 13133 utarray_push_back(methods, &func_method); 13108 - } 13109 - js->consumed = 1; 13134 + } js->consumed = 1; 13110 13135 } 13111 13136 13112 13137 EXPECT(TOK_RBRACE, js->flags = save_flags); ··· 13115 13140 if (exe) { 13116 13141 jsval_t super_constructor = js_mkundef(); 13117 13142 jsval_t super_proto = js_mknull(); 13118 - if (super_len > 0) { 13119 - jsval_t super_val = lookup(js, &js->code[super_off], super_len); 13143 + bool has_super_ctor = false; 13144 + if (super_expr_len > 0) { 13145 + jsval_t super_val = js_eval_slice(js, super_expr_off, super_expr_len); 13120 13146 if (is_err(super_val)) return super_val; 13121 13147 super_constructor = resolveprop(js, super_val); 13122 - if (vtype(super_constructor) != T_FUNC && vtype(super_constructor) != T_CFUNC) { 13123 - return js_mkerr(js, "super class must be a constructor"); 13124 - } 13125 - jsval_t super_obj = mkval(T_OBJ, vdata(super_constructor)); 13126 - jsoff_t super_proto_off = lkp_interned(js, super_obj, INTERN_PROTOTYPE, 9); 13127 - if (super_proto_off != 0) { 13128 - super_proto = resolveprop(js, mkval(T_PROP, super_proto_off)); 13129 - } 13148 + uint8_t super_type = vtype(super_constructor); 13149 + if (super_type == T_NULL) { 13150 + super_proto = js_mknull(); 13151 + } else if (super_type == T_FUNC) { 13152 + has_super_ctor = true; 13153 + jsval_t super_obj = mkval(T_OBJ, vdata(super_constructor)); 13154 + jsoff_t super_proto_off = lkp_interned(js, super_obj, INTERN_PROTOTYPE, 9); 13155 + if (super_proto_off != 0) { 13156 + super_proto = resolveprop(js, mkval(T_PROP, super_proto_off)); 13157 + } 13158 + if (vtype(super_proto) != T_OBJ && vtype(super_proto) != T_NULL) { 13159 + return js_mkerr(js, "super class prototype must be an object or null"); 13160 + } 13161 + } else return js_mkerr(js, "super class must be a constructor"); 13130 13162 } 13131 13163 13132 13164 jsval_t proto = js_mkobj(js); 13133 13165 if (is_err(proto)) return proto; 13134 13166 13135 - if (vtype(super_proto) == T_OBJ) { 13136 - set_proto(js, proto, super_proto); 13167 + if (super_expr_len > 0) { 13168 + if (vtype(super_proto) == T_OBJ || vtype(super_proto) == T_NULL) { 13169 + set_proto(js, proto, super_proto); 13170 + } else { 13171 + jsval_t object_proto = get_ctor_proto(js, "Object", 6); 13172 + if (vtype(object_proto) == T_OBJ) set_proto(js, proto, object_proto); 13173 + } 13137 13174 } else { 13138 13175 jsval_t object_proto = get_ctor_proto(js, "Object", 6); 13139 13176 if (vtype(object_proto) == T_OBJ) set_proto(js, proto, object_proto); ··· 13180 13217 if (vtype(func_proto) == T_FUNC) set_proto(js, method_obj, func_proto); 13181 13218 } 13182 13219 13183 - if (super_len > 0) set_slot(js, method_obj, SLOT_SUPER, super_constructor); 13220 + if (has_super_ctor) set_slot(js, method_obj, SLOT_SUPER, super_constructor); 13184 13221 jsval_t method_func = mkval(T_FUNC, (unsigned long) vdata(method_obj)); 13185 13222 13186 13223 if (m->is_getter || m->is_setter) { ··· 13206 13243 set_func_code(js, func_obj, &js->code[constructor_params_start], code_len); 13207 13244 } else { 13208 13245 set_func_code_ptr(js, func_obj, "(){}", 4); 13209 - if (super_len > 0) set_slot(js, func_obj, SLOT_DEFAULT_CTOR, js_true); 13246 + if (has_super_ctor) set_slot(js, func_obj, SLOT_DEFAULT_CTOR, js_true); 13210 13247 } 13211 13248 13212 13249 int instance_field_count = 0; ··· 13258 13295 } 13259 13296 13260 13297 set_slot(js, func_obj, SLOT_SCOPE, func_scope); 13261 - if (super_len > 0) set_slot(js, func_obj, SLOT_SUPER, super_constructor); 13298 + if (has_super_ctor) set_slot(js, func_obj, SLOT_SUPER, super_constructor); 13262 13299 13263 13300 jsval_t func_proto = get_slot(js, js_glob(js), SLOT_FUNC_PROTO); 13264 13301 if (vtype(func_proto) == T_FUNC) set_proto(js, func_obj, func_proto); 13302 + if (has_super_ctor) set_proto(js, func_obj, super_constructor); 13265 13303 13266 13304 jsval_t name_key = js_mkstr(js, "name", 4); 13267 13305 if (is_err(name_key)) return name_key; ··· 13330 13368 13331 13369 set_func_code(js, method_obj, &js->code[m->fn_start], mlen); 13332 13370 set_slot(js, method_obj, SLOT_SCOPE, func_scope); 13333 - if (super_len > 0) set_slot(js, method_obj, SLOT_SUPER, super_constructor); 13371 + if (has_super_ctor) set_slot(js, method_obj, SLOT_SUPER, super_constructor); 13334 13372 13335 13373 jsval_t method_func_proto = get_slot(js, js_glob(js), SLOT_FUNC_PROTO); 13336 13374 if (vtype(method_func_proto) == T_FUNC) set_proto(js, method_obj, method_func_proto);