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(promise): subclassing, Promise.try this binding, and AggregateError

+86 -10
+1
include/ant.h
··· 39 39 JS_ERR_EVAL, 40 40 JS_ERR_URI, 41 41 JS_ERR_INTERNAL, 42 + JS_ERR_AGGREGATE, 42 43 JS_ERR_GENERIC 43 44 } js_err_type_t; 44 45
+85 -10
src/ant.c
··· 2390 2390 case JS_ERR_EVAL: return "EvalError"; 2391 2391 case JS_ERR_URI: return "URIError"; 2392 2392 case JS_ERR_INTERNAL: return "InternalError"; 2393 + case JS_ERR_AGGREGATE: return "AggregateError"; 2393 2394 case JS_ERR_GENERIC: return "Error"; 2394 2395 default: return "Error"; 2395 2396 } ··· 12723 12724 return this_val; 12724 12725 } 12725 12726 12727 + static jsval_t builtin_AggregateError(struct js *js, jsval_t *args, int nargs) { 12728 + bool is_new = (vtype(js->new_target) != T_UNDEF); 12729 + jsval_t this_val = js->this_val; 12730 + 12731 + if (!is_new) { 12732 + this_val = js_mkobj(js); 12733 + jsoff_t proto_off = lkp_interned(js, mkval(T_OBJ, vdata(js->current_func)), INTERN_PROTOTYPE, 9); 12734 + if (proto_off) set_proto(js, this_val, resolveprop(js, mkval(T_PROP, proto_off))); 12735 + else set_proto(js, this_val, get_ctor_proto(js, "AggregateError", 14)); 12736 + } 12737 + 12738 + jsval_t errors = nargs > 0 ? args[0] : mkarr(js); 12739 + if (vtype(errors) != T_ARR) errors = mkarr(js); 12740 + setprop_fast(js, this_val, "errors", 6, errors); 12741 + 12742 + if (nargs > 1 && vtype(args[1]) != T_UNDEF) { 12743 + jsval_t msg = args[1]; 12744 + if (vtype(msg) != T_STR) { 12745 + const char *str = js_str(js, msg); 12746 + msg = js_mkstr(js, str, strlen(str)); 12747 + } 12748 + setprop_fast(js, this_val, "message", 7, msg); 12749 + } 12750 + 12751 + setprop_fast(js, this_val, "name", 4, ANT_STRING("AggregateError")); 12752 + return this_val; 12753 + } 12754 + 12726 12755 static jsval_t builtin_RegExp(struct js *js, jsval_t *args, int nargs) { 12727 12756 jsval_t regexp_obj = js->this_val; 12728 12757 bool use_this = (vtype(regexp_obj) == T_OBJ); ··· 18859 18888 pd->state = 2; 18860 18889 pd->value = val; 18861 18890 18862 - // Track unhandled rejection if no handler attached yet 18863 18891 if (!pd->has_rejection_handler) { 18864 18892 promise_data_entry_t *existing = NULL; 18865 18893 HASH_FIND(hh_unhandled, unhandled_rejections, &pd->promise_id, sizeof(uint32_t), existing); ··· 18898 18926 } 18899 18927 18900 18928 jsval_t p = mkpromise(js); 18929 + jsval_t new_target = js->new_target; 18930 + 18931 + if (vtype(new_target) == T_FUNC) { 18932 + jsoff_t proto_off = lkp_interned(js, mkval(T_OBJ, vdata(new_target)), INTERN_PROTOTYPE, 9); 18933 + jsval_t subclass_proto = proto_off ? resolveprop(js, mkval(T_PROP, proto_off)) : js_mkundef(); 18934 + 18935 + if (vtype(subclass_proto) == T_OBJ) { 18936 + jsval_t p_obj = mkval(T_OBJ, vdata(p)); 18937 + set_slot(js, p_obj, SLOT_PROTO, subclass_proto); 18938 + set_slot(js, p_obj, SLOT_CTOR, new_target); 18939 + } 18940 + } 18941 + 18901 18942 jsval_t res_obj = mkobj(js, 0); 18902 18943 18903 18944 set_slot(js, res_obj, SLOT_CFUNC, js_mkfun(builtin_resolve_internal)); ··· 18936 18977 if (vtype(p) != T_PROMISE) return js_mkerr(js, "not a promise"); 18937 18978 18938 18979 jsval_t nextP = mkpromise(js); 18980 + 18981 + jsval_t p_proto = get_slot(js, mkval(T_OBJ, vdata(p)), SLOT_PROTO); 18982 + if (vtype(p_proto) == T_OBJ) { 18983 + set_slot(js, mkval(T_OBJ, vdata(nextP)), SLOT_PROTO, p_proto); 18984 + jsval_t p_ctor = get_slot(js, mkval(T_OBJ, vdata(p)), SLOT_CTOR); 18985 + if (vtype(p_ctor) == T_FUNC) set_slot(js, mkval(T_OBJ, vdata(nextP)), SLOT_CTOR, p_ctor); 18986 + } 18987 + 18939 18988 jsval_t onFulfilled = nargs > 0 ? args[0] : js_mkundef(); 18940 18989 jsval_t onRejected = nargs > 1 ? args[1] : js_mkundef(); 18941 18990 ··· 19064 19113 static jsval_t builtin_Promise_try(struct js *js, jsval_t *args, int nargs) { 19065 19114 if (nargs == 0) return builtin_Promise_resolve(js, args, 0); 19066 19115 jsval_t fn = args[0]; 19067 - jsval_t res = js_call(js, fn, NULL, 0); 19116 + jsval_t *call_args = nargs > 1 ? &args[1] : NULL; 19117 + int call_nargs = nargs > 1 ? nargs - 1 : 0; 19118 + jsval_t res = js_call_with_this(js, fn, js_mkundef(), call_args, call_nargs); 19068 19119 if (is_err(res)) { 19069 - jsval_t err_str = js_mkstr(js, js->errmsg, strlen(js->errmsg)); 19070 - jsval_t rej_args[] = { err_str }; 19120 + jsval_t reject_val = js->thrown_value; 19121 + if (vtype(reject_val) == T_UNDEF) { 19122 + reject_val = js_mkstr(js, js->errmsg, strlen(js->errmsg)); 19123 + } 19124 + js->thrown_value = js_mkundef(); 19125 + jsval_t rej_args[] = { reject_val }; 19071 19126 return builtin_Promise_reject(js, rej_args, 1); 19072 19127 } 19073 19128 jsval_t res_args[] = { res }; ··· 19259 19314 } 19260 19315 19261 19316 static jsval_t mk_aggregate_error(struct js *js, jsval_t errors) { 19262 - jsval_t agg_err = js_mkobj(js); 19263 - js_set(js, agg_err, "name", js_mkstr(js, "AggregateError", 14)); 19264 - js_set(js, agg_err, "message", js_mkstr(js, "All promises were rejected", 26)); 19265 - js_set(js, agg_err, "errors", errors); 19266 - return agg_err; 19317 + jsval_t args[] = { errors, js_mkstr(js, "All promises were rejected", 26) }; 19318 + jsoff_t off = lkp(js, js_glob(js), "AggregateError", 14); 19319 + jsval_t ctor = off ? resolveprop(js, mkval(T_PROP, off)) : js_mkundef(); 19320 + return js_call(js, ctor, args, 2); 19267 19321 } 19268 19322 19269 19323 static bool promise_any_try_resolve(struct js *js, jsval_t tracker, jsval_t value) { ··· 19338 19392 uint32_t item_pid = get_promise_id(js, item); 19339 19393 promise_data_entry_t *pd = get_promise_data(item_pid, false); 19340 19394 if (pd) { 19395 + pd->has_rejection_handler = true; 19396 + promise_data_entry_t *in_unhandled = NULL; 19397 + HASH_FIND(hh_unhandled, unhandled_rejections, &pd->promise_id, sizeof(uint32_t), in_unhandled); 19398 + if (in_unhandled) HASH_DELETE(hh_unhandled, unhandled_rejections, pd); 19399 + 19341 19400 if (pd->state == 1) { 19342 19401 promise_any_try_resolve(js, tracker, pd->value); 19343 19402 return result_promise; ··· 21438 21497 21439 21498 #undef REGISTER_ERROR_SUBTYPE 21440 21499 21500 + jsval_t proto = js_mkobj(js); 21501 + set_proto(js, proto, error_proto); 21502 + setprop(js, proto, ANT_STRING("name"), ANT_STRING("AggregateError")); 21503 + jsval_t ctor = mkobj(js, 0); 21504 + set_proto(js, ctor, function_proto); 21505 + set_slot(js, ctor, SLOT_CFUNC, js_mkfun(builtin_AggregateError)); 21506 + js_setprop_nonconfigurable(js, ctor, "prototype", 9, proto); 21507 + setprop(js, ctor, ANT_STRING("name"), ANT_STRING("AggregateError")); 21508 + setprop(js, proto, ANT_STRING("constructor"), mkval(T_FUNC, vdata(ctor))); 21509 + js_set_descriptor(js, proto, "constructor", 11, JS_DESC_W | JS_DESC_C); 21510 + setprop(js, glob, ANT_STRING("AggregateError"), mkval(T_FUNC, vdata(ctor))); 21511 + 21441 21512 jsval_t date_proto = js_mkobj(js); 21442 21513 set_proto(js, date_proto, object_proto); 21443 21514 setprop(js, date_proto, js_mkstr(js, "getTime", 7), js_mkfun(builtin_Date_getTime)); ··· 22370 22441 } 22371 22442 } 22372 22443 22444 + if (code_uses_arguments(&fn[pf->body_start], pf->body_len)) { 22445 + setup_arguments(js, js->scope, final_args, final_nargs, pf->is_strict); 22446 + } 22447 + 22373 22448 jsval_t saved_this = js->this_val; 22374 22449 if (has_slot_bound_this) { 22375 22450 js->this_val = slot_bound_this; ··· 22381 22456 JS_SAVE_STATE(js, saved_state); 22382 22457 uint8_t caller_flags = js->flags; 22383 22458 22384 - js->flags = F_CALL; 22459 + js->flags = F_CALL | (pf->is_strict ? F_STRICT : 0); 22385 22460 jsval_t res = js_eval(js, &fn[pf->body_start], pf->body_len); 22386 22461 if (!is_err(res) && !(js->flags & F_RETURN)) res = js_mkundef(); 22387 22462