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 super method support to internal_slot_t

+109 -23
+1 -1
.gitignore
··· 19 19 *.todo 20 20 *.trace 21 21 22 - spec.txt 22 + zoo.sh 23 23 todo.txt 24 24 25 25 node_modules
+19
examples/spec/classes.js
··· 141 141 test('instanceof parent', dog instanceof Animal, true); 142 142 test('instanceof child', dog instanceof Dog, true); 143 143 144 + class Cat extends Animal { 145 + speak() { 146 + return super.speak() + ' - meow!'; 147 + } 148 + } 149 + 150 + let cat = new Cat('Whiskers'); 151 + test('super.method()', cat.speak(), 'Whiskers makes a sound - meow!'); 152 + 153 + class Bird extends Animal { 154 + speak() { 155 + let method = 'speak'; 156 + return super[method]() + ' - chirp!'; 157 + } 158 + } 159 + 160 + let bird = new Bird('Tweety'); 161 + test('super[method]()', bird.speak(), 'Tweety makes a sound - chirp!'); 162 + 144 163 class Static { 145 164 static value = 42; 146 165 static method() {
+2
include/config.h
··· 53 53 SLOT_BUILTIN, 54 54 SLOT_DATA, 55 55 SLOT_CTOR, 56 + SLOT_SUPER, 57 + SLOT_DEFAULT_CTOR, 56 58 SLOT_MAX = 255 57 59 } internal_slot_t; 58 60
+2
include/config.h.in
··· 42 42 SLOT_BUILTIN, 43 43 SLOT_DATA, 44 44 SLOT_CTOR, 45 + SLOT_SUPER, 46 + SLOT_DEFAULT_CTOR, 45 47 SLOT_MAX = 255 46 48 } internal_slot_t; 47 49
+1
include/internal.h
··· 29 29 jsval_t tval; // holds last parsed numeric or string literal value 30 30 jsval_t scope; // current scope 31 31 jsval_t this_val; // 'this' value for currently executing function 32 + jsval_t super_val; // 'super' value for class methods 32 33 jsval_t new_target; // constructor called with 'new', undefined otherwise 33 34 jsval_t module_ns; // current ESM module namespace 34 35 uint8_t *mem; // available JS memory
+84 -22
src/ant.c
··· 97 97 coroutine_type_t type; 98 98 jsval_t scope; 99 99 jsval_t this_val; 100 + jsval_t super_val; 101 + jsval_t new_target; 100 102 jsval_t awaited_promise; 101 103 jsval_t result; 102 104 jsval_t async_func; ··· 401 403 TOK_ASYNC, TOK_AWAIT, TOK_BREAK, TOK_CASE, TOK_CATCH, TOK_CLASS, TOK_CONST, TOK_CONTINUE, 402 404 TOK_DEFAULT, TOK_DELETE, TOK_DO, TOK_DEBUGGER, TOK_ELSE, TOK_EXPORT, TOK_FINALLY, TOK_FOR, 403 405 TOK_FROM, TOK_FUNC, TOK_IF, TOK_IMPORT, TOK_IN, TOK_INSTANCEOF, TOK_LET, TOK_NEW, TOK_OF, 404 - TOK_RETURN, TOK_SWITCH, TOK_THIS, TOK_THROW, TOK_TRY, TOK_VAR, TOK_VOID, TOK_WHILE, TOK_WITH, 406 + TOK_RETURN, TOK_SUPER, TOK_SWITCH, TOK_THIS, TOK_THROW, TOK_TRY, TOK_VAR, TOK_VOID, TOK_WHILE, TOK_WITH, 405 407 TOK_YIELD, TOK_UNDEF, TOK_NULL, TOK_TRUE, TOK_FALSE, TOK_AS, TOK_STATIC, TOK_TYPEOF, 406 408 TOK_WINDOW, TOK_GLOBAL_THIS, 407 409 TOK_IDENT_LIKE_END, ··· 864 866 coroutine_t *coro = ctx->coro; 865 867 jsval_t result; 866 868 869 + jsval_t saved_super = js->super_val; 870 + jsval_t saved_new_target = js->new_target; 871 + if (coro) { 872 + js->super_val = coro->super_val; 873 + js->new_target = coro->new_target; 874 + } 875 + 867 876 if (coro && coro->nargs > 0 && coro->args) { 868 877 result = call_js_code_with_args(js, ctx->code, (jsoff_t)ctx->code_len, ctx->closure_scope, coro->args, coro->nargs, js_mkundef()); 869 878 } else result = call_js(js, ctx->code, (jsoff_t)ctx->code_len, ctx->closure_scope); 879 + 880 + js->super_val = saved_super; 881 + js->new_target = saved_new_target; 870 882 871 883 ctx->result = result; 872 884 ctx->has_error = is_err(result); ··· 1035 1047 coro->type = CORO_ASYNC_AWAIT; 1036 1048 coro->scope = closure_scope; 1037 1049 coro->this_val = js->this_val; 1050 + coro->super_val = js->super_val; 1051 + coro->new_target = js->new_target; 1038 1052 coro->awaited_promise = js_mkundef(); 1039 1053 coro->result = js_mkundef(); 1040 1054 coro->async_func = js->current_func; ··· 3527 3541 K("return", TOK_RETURN); 3528 3542 break; 3529 3543 case 's': 3544 + K("super", TOK_SUPER); 3530 3545 K("static", TOK_STATIC); 3531 3546 K("switch", TOK_SWITCH); 3532 3547 break; ··· 6082 6097 const char *fn = (const char *) (&js->mem[fnoff]); 6083 6098 6084 6099 jsval_t closure_scope = get_slot(js, func_obj, SLOT_SCOPE); 6100 + jsval_t saved_super = js->super_val; 6101 + 6102 + jsval_t func_super = get_slot(js, func_obj, SLOT_SUPER); 6103 + if (vtype(func_super) != T_UNDEF) js->super_val = func_super; 6085 6104 6086 6105 jsval_t captured_this = get_slot(js, func_obj, SLOT_THIS); 6087 6106 if (vtype(captured_this) != T_UNDEF) { ··· 6096 6115 } 6097 6116 6098 6117 jsval_t result = call_js_code_with_args(js, fn, fnlen, closure_scope, args, nargs, func); 6118 + js->super_val = saved_super; 6099 6119 if (combined_args) ANT_GC_FREE(combined_args); 6100 6120 6101 6121 return result; ··· 6456 6476 js->current_func = func; 6457 6477 js->nogc = (jsoff_t) (fnoff - sizeof(jsoff_t)); 6458 6478 6479 + jsval_t saved_super = js->super_val; 6480 + jsval_t func_super = get_slot(js, func_obj, SLOT_SUPER); 6481 + if (vtype(func_super) != T_UNDEF) js->super_val = func_super; 6482 + 6459 6483 if (is_arrow || is_bound) { 6460 6484 pop_this(); 6461 6485 push_this(captured_this); ··· 6509 6533 } 6510 6534 pop_call_frame(); 6511 6535 if (bound_args) ANT_GC_FREE(bound_args); 6536 + js->super_val = saved_super; 6512 6537 js->current_func = saved_func; 6513 6538 } 6514 6539 } ··· 8053 8078 return js_mkerr_typed(js, JS_ERR_SYNTAX, "unexpected token after async"); 8054 8079 } 8055 8080 8081 + case TOK_SUPER: { 8082 + jsval_t super_ctor = js->super_val; 8083 + uint8_t la = lookahead(js); 8084 + if ((la == TOK_DOT || la == TOK_LBRACKET) && vtype(super_ctor) == T_FUNC) { 8085 + jsval_t ctor_obj = mkval(T_OBJ, vdata(super_ctor)); 8086 + jsoff_t proto_off = lkp_interned(js, ctor_obj, INTERN_PROTOTYPE, 9); 8087 + if (proto_off == 0) return js_mkundef(); 8088 + jsval_t proto = resolveprop(js, mkval(T_PROP, proto_off)); 8089 + 8090 + next(js); js->consumed = 1; 8091 + const char *prop; jsoff_t prop_len; 8092 + if (la == TOK_DOT) { 8093 + if (next(js) != TOK_IDENTIFIER && !is_keyword_propname(js->tok)) 8094 + return js_mkerr_typed(js, JS_ERR_SYNTAX, "identifier expected"); 8095 + prop = &js->code[js->toff]; prop_len = js->tlen; 8096 + js->consumed = 1; 8097 + } else { 8098 + jsval_t idx = js_expr(js); 8099 + if (is_err(idx)) return idx; 8100 + if (next(js) != TOK_RBRACKET) return js_mkerr_typed(js, JS_ERR_SYNTAX, "] expected"); 8101 + js->consumed = 1; 8102 + idx = resolveprop(js, idx); 8103 + if (vtype(idx) == T_STR) { 8104 + prop_len = 0; prop = (const char *)&js->mem[vstr(js, idx, &prop_len)]; 8105 + } else { 8106 + char buf[32]; prop_len = tostr(js, idx, buf, sizeof(buf)); 8107 + prop = buf; 8108 + } 8109 + } 8110 + 8111 + jsoff_t off = lkp(js, proto, prop, prop_len); 8112 + if (off == 0) off = lkp_proto(js, proto, prop, prop_len); 8113 + if (off == 0) return js_mkundef(); 8114 + 8115 + jsval_t method = resolveprop(js, mkval(T_PROP, off)); 8116 + if (vtype(method) != T_FUNC) return method; 8117 + 8118 + jsval_t bound = mkobj(js, 0); 8119 + set_slot(js, bound, SLOT_CODE, get_slot(js, mkval(T_OBJ, vdata(method)), SLOT_CODE)); 8120 + set_slot(js, bound, SLOT_SCOPE, get_slot(js, mkval(T_OBJ, vdata(method)), SLOT_SCOPE)); 8121 + set_slot(js, bound, SLOT_BOUND_THIS, js->this_val); 8122 + return mkval(T_FUNC, vdata(bound)); 8123 + } 8124 + return super_ctor; 8125 + } 8126 + 8056 8127 case TOK_NULL: return js_mknull(); 8057 8128 case TOK_UNDEF: return js_mkundef(); 8058 8129 case TOK_TRUE: return js_mktrue(); ··· 11237 11308 } 11238 11309 11239 11310 jsval_t func_scope = mkobj(js, (jsoff_t) vdata(js->scope)); 11240 - if (super_len > 0) { 11241 - jsval_t super_key = js_mkstr(js, "super", 5); 11242 - if (is_err(super_key)) return super_key; 11243 - jsval_t res_super = setprop(js, func_scope, super_key, super_constructor); 11244 - if (is_err(res_super)) return res_super; 11245 - } 11246 11311 11247 11312 for (unsigned int i = 0; i < utarray_len(methods); i++) { 11248 11313 MethodInfo *m = (MethodInfo *)utarray_eltptr(methods, i); ··· 11260 11325 if (is_err(method_obj)) return method_obj; 11261 11326 11262 11327 set_slot(js, method_obj, SLOT_CODE, method_code); 11328 + set_slot(js, method_obj, SLOT_SCOPE, func_scope); 11263 11329 11264 - if (m->is_async) { 11265 - set_slot(js, method_obj, SLOT_ASYNC, js_mktrue()); 11266 - } 11267 - 11268 - set_slot(js, method_obj, SLOT_SCOPE, func_scope); 11330 + if (m->is_async) set_slot(js, method_obj, SLOT_ASYNC, js_mktrue()); 11331 + if (super_len > 0) set_slot(js, method_obj, SLOT_SUPER, super_constructor); 11269 11332 11270 11333 jsval_t method_func = mkval(T_FUNC, (unsigned long) vdata(method_obj)); 11271 11334 ··· 11294 11357 } else { 11295 11358 if (super_len > 0) { 11296 11359 ctor_str = js_mkstr(js, "(...args){super(...args);}", 26); 11297 - } else { ctor_str = js_mkstr(js, "(){}", 4); } 11360 + } else ctor_str = js_mkstr(js, "(){}", 4); 11298 11361 } 11299 11362 if (is_err(ctor_str)) return ctor_str; 11300 - 11301 11363 set_slot(js, func_obj, SLOT_CODE, ctor_str); 11302 11364 11303 11365 int instance_field_count = 0; ··· 11343 11405 } 11344 11406 11345 11407 set_slot(js, func_obj, SLOT_SCOPE, func_scope); 11408 + if (super_len > 0) set_slot(js, func_obj, SLOT_SUPER, super_constructor); 11346 11409 11347 11410 jsval_t name_key = js_mkstr(js, "name", 4); 11348 11411 if (is_err(name_key)) return name_key; ··· 11397 11460 11398 11461 set_slot(js, method_obj, SLOT_CODE, method_code); 11399 11462 set_slot(js, method_obj, SLOT_SCOPE, func_scope); 11463 + if (super_len > 0) set_slot(js, method_obj, SLOT_SUPER, super_constructor); 11400 11464 11401 11465 jsval_t method_func = mkval(T_FUNC, (unsigned long) vdata(method_obj)); 11402 11466 jsval_t set_res = setprop(js, func_obj, member_name, method_func); ··· 11415 11479 static void js_throw_handle(struct js *js, jsval_t *res) { 11416 11480 js->consumed = 1; 11417 11481 jsval_t throw_val = js_expr(js); 11418 - if (js->flags & F_NOEXEC) { 11419 - *res = js_mkundef(); 11420 - } else { 11482 + if (js->flags & F_NOEXEC) *res = js_mkundef(); else { 11421 11483 throw_val = resolveprop(js, throw_val); 11422 - if (is_err(throw_val)) { 11423 - *res = throw_val; 11424 - } else { 11425 - *res = js_throw(js, throw_val); 11426 - } 11484 + if (is_err(throw_val)) *res = throw_val; 11485 + else *res = js_throw(js, throw_val); 11427 11486 } 11428 11487 } 11429 11488 ··· 20634 20693 js->size = js->size / 8U * 8U; 20635 20694 js->lwm = js->size; 20636 20695 js->this_val = js->scope; 20696 + js->super_val = js_mkundef(); 20637 20697 js->new_target = js_mkundef(); 20638 20698 js->errmsg_size = 4096; 20639 20699 js->errmsg = (char *)malloc(js->errmsg_size); ··· 21452 21512 for (coroutine_t *coro = pending_coroutines.head; coro; coro = coro->next) { 21453 21513 FWD_VAL(coro->scope); 21454 21514 FWD_VAL(coro->this_val); 21515 + FWD_VAL(coro->super_val); 21516 + FWD_VAL(coro->new_target); 21455 21517 FWD_VAL(coro->awaited_promise); 21456 21518 FWD_VAL(coro->result); 21457 21519 FWD_VAL(coro->async_func);