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 async, add prev and next pointers to coroutine struct

+67 -93
+1 -1
meson.build
··· 79 79 build_date = run_command('date', '+%Y-%m-%d', check: true).stdout().strip() 80 80 81 81 version_conf = configuration_data() 82 - version_conf.set('ANT_VERSION', '0.2.2.9') 82 + version_conf.set('ANT_VERSION', '0.2.2.10') 83 83 version_conf.set('ANT_GIT_HASH', git_hash) 84 84 version_conf.set('ANT_BUILD_DATE', build_date) 85 85
+66 -92
src/ant.c
··· 87 87 bool is_done; 88 88 jsoff_t resume_point; 89 89 jsval_t yield_value; 90 + struct coroutine *prev; 90 91 struct coroutine *next; 91 92 mco_coro* mco; 92 93 bool mco_started; ··· 857 858 static void enqueue_coroutine(coroutine_t *coro) { 858 859 if (!coro) return; 859 860 coro->next = NULL; 861 + coro->prev = pending_coroutines.tail; 860 862 861 - if (pending_coroutines.tail && pending_coroutines.tail != coro) { 863 + if (pending_coroutines.tail) { 862 864 pending_coroutines.tail->next = coro; 863 - pending_coroutines.tail = coro; 864 - } else if (!pending_coroutines.tail) { 865 + } else { 865 866 pending_coroutines.head = coro; 866 - pending_coroutines.tail = coro; 867 867 } 868 + pending_coroutines.tail = coro; 868 869 } 869 870 870 - static coroutine_t *dequeue_coroutine(void) { 871 - coroutine_t *coro = pending_coroutines.head; 872 - if (coro) { 871 + static void remove_coroutine(coroutine_t *coro) { 872 + if (!coro) return; 873 + 874 + if (coro->prev) { 875 + coro->prev->next = coro->next; 876 + } else { 873 877 pending_coroutines.head = coro->next; 874 - if (!pending_coroutines.head) { 875 - pending_coroutines.tail = NULL; 876 - } 877 - coro->next = NULL; 878 + } 879 + 880 + if (coro->next) { 881 + coro->next->prev = coro->prev; 882 + } else { 883 + pending_coroutines.tail = coro->prev; 878 884 } 879 - return coro; 885 + 886 + coro->prev = NULL; 887 + coro->next = NULL; 880 888 } 881 889 882 890 static bool has_pending_coroutines(void) { ··· 906 914 process_microtasks(js); 907 915 908 916 coroutine_t *temp = pending_coroutines.head; 909 - coroutine_t *prev = NULL; 910 917 911 918 while (temp) { 912 919 coroutine_t *next = temp->next; 913 920 914 921 if (temp->is_ready && temp->mco && mco_status(temp->mco) == MCO_SUSPENDED) { 915 - if (prev) { 916 - prev->next = next; 917 - } else { 918 - pending_coroutines.head = next; 919 - } 920 - if (pending_coroutines.tail == temp) { 921 - pending_coroutines.tail = prev; 922 - } 922 + remove_coroutine(temp); 923 923 924 924 mco_result res = mco_resume(temp->mco); 925 925 ··· 927 927 free_coroutine(temp); 928 928 } else if (res == MCO_SUCCESS) { 929 929 temp->is_ready = false; 930 - temp->next = NULL; 931 - if (pending_coroutines.tail) { 932 - pending_coroutines.tail->next = temp; 933 - } else { 934 - pending_coroutines.head = temp; 935 - } 936 - pending_coroutines.tail = temp; 930 + enqueue_coroutine(temp); 937 931 } else { 938 932 free_coroutine(temp); 939 933 } 940 - 941 - temp = next; 942 - } else { 943 - prev = temp; 944 - temp = next; 945 934 } 935 + 936 + temp = next; 946 937 } 947 938 } 948 939 ··· 1022 1013 1023 1014 res = mco_resume(mco); 1024 1015 if (res != MCO_SUCCESS && mco_status(mco) != MCO_DEAD) { 1025 - dequeue_coroutine(); 1016 + remove_coroutine(coro); 1026 1017 free_coroutine(coro); 1027 1018 ANT_GC_FREE(ctx); 1028 1019 return js_mkerr(js, "failed to start coroutine"); ··· 1030 1021 1031 1022 coro->mco_started = true; 1032 1023 if (mco_status(mco) == MCO_DEAD) { 1033 - dequeue_coroutine(); 1024 + remove_coroutine(coro); 1034 1025 free_coroutine(coro); 1035 1026 ANT_GC_FREE(ctx); 1036 1027 } ··· 17899 17890 } 17900 17891 17901 17892 if (vtype(val) == T_PROMISE) { 17902 - if (vdata(val) == vdata(p)) { 17903 - jsval_t err = js_mkerr(js, "TypeError: Chaining cycle"); 17904 - reject_promise(js, p, err); 17905 - return; 17906 - } 17907 - jsval_t res_obj = mkobj(js, 0); 17908 - setprop(js, res_obj, js_mkstr(js, "__native_func", 13), js_mkfun(builtin_resolve_internal)); 17909 - setprop(js, res_obj, js_mkstr(js, "promise", 7), p); 17910 - jsval_t res_fn = mkval(T_FUNC, vdata(res_obj)); 17911 - 17912 - jsval_t rej_obj = mkobj(js, 0); 17913 - setprop(js, rej_obj, js_mkstr(js, "__native_func", 13), js_mkfun(builtin_reject_internal)); 17914 - setprop(js, rej_obj, js_mkstr(js, "promise", 7), p); 17915 - jsval_t rej_fn = mkval(T_FUNC, vdata(rej_obj)); 17916 - 17917 - jsval_t args[] = { res_fn, rej_fn }; 17918 - jsval_t then_prop = js_get(js, val, "then"); 17919 - if (vtype(then_prop) == T_FUNC || vtype(then_prop) == T_CFUNC) { 17920 - jsval_t saved_this = js->this_val; 17921 - js->this_val = val; 17922 - js_call(js, then_prop, args, 2); 17923 - js->this_val = saved_this; 17924 - return; 17925 - } 17893 + if (vdata(val) == vdata(p)) { 17894 + jsval_t err = js_mkerr(js, "TypeError: Chaining cycle"); 17895 + return reject_promise(js, p, err); 17896 + } 17897 + 17898 + jsval_t res_obj = mkobj(js, 0); 17899 + setprop(js, res_obj, js_mkstr(js, "__native_func", 13), js_mkfun(builtin_resolve_internal)); 17900 + setprop(js, res_obj, js_mkstr(js, "promise", 7), p); 17901 + jsval_t res_fn = mkval(T_FUNC, vdata(res_obj)); 17902 + 17903 + jsval_t rej_obj = mkobj(js, 0); 17904 + setprop(js, rej_obj, js_mkstr(js, "__native_func", 13), js_mkfun(builtin_reject_internal)); 17905 + setprop(js, rej_obj, js_mkstr(js, "promise", 7), p); 17906 + jsval_t rej_fn = mkval(T_FUNC, vdata(rej_obj)); 17907 + 17908 + jsval_t args[] = { res_fn, rej_fn }; 17909 + jsval_t then_prop = js_get(js, val, "then"); 17910 + 17911 + if (vtype(then_prop) == T_FUNC || vtype(then_prop) == T_CFUNC) { 17912 + (void)js_call_with_this(js, then_prop, val, args, 2); return; 17913 + } 17926 17914 } 17927 17915 17928 17916 setprop(js, p_obj, js_mkstr(js, "__state", 7), tov(1.0)); ··· 17958 17946 return js_mkundef(); 17959 17947 } 17960 17948 17961 - static jsval_t builtin_promise_executor_wrapper(struct js *js, jsval_t *args, int nargs); 17962 - 17963 17949 static jsval_t builtin_Promise(struct js *js, jsval_t *args, int nargs) { 17964 17950 jsval_t p = mkpromise(js); 17965 17951 jsval_t res_obj = mkobj(js, 0); ··· 17971 17957 setprop(js, rej_obj, js_mkstr(js, "promise", 7), p); 17972 17958 jsval_t rej_fn = mkval(T_FUNC, vdata(rej_obj)); 17973 17959 if (nargs > 0) { 17974 - jsval_t wrapper_obj = mkobj(js, 0); 17975 - setprop(js, wrapper_obj, js_mkstr(js, "__native_func", 13), js_mkfun(builtin_promise_executor_wrapper)); 17976 - setprop(js, wrapper_obj, js_mkstr(js, "executor", 8), args[0]); 17977 - setprop(js, wrapper_obj, js_mkstr(js, "resolve", 7), res_fn); 17978 - setprop(js, wrapper_obj, js_mkstr(js, "reject", 6), rej_fn); 17979 - jsval_t wrapper_fn = mkval(T_FUNC, vdata(wrapper_obj)); 17980 - queue_microtask(js, wrapper_fn); 17960 + jsval_t exec_args[] = { res_fn, rej_fn }; 17961 + js_call(js, args[0], exec_args, 2); 17981 17962 } 17982 17963 return p; 17983 - } 17984 - 17985 - static jsval_t builtin_promise_executor_wrapper(struct js *js, jsval_t *args, int nargs) { 17986 - jsval_t me = js->current_func; 17987 - jsval_t executor = js_get(js, me, "executor"); 17988 - jsval_t res_fn = js_get(js, me, "resolve"); 17989 - jsval_t rej_fn = js_get(js, me, "reject"); 17990 - jsval_t exec_args[] = { res_fn, rej_fn }; 17991 - js_call(js, executor, exec_args, 2); 17992 - return js_mkundef(); 17993 17964 } 17994 17965 17995 17966 static jsval_t builtin_Promise_resolve(struct js *js, jsval_t *args, int nargs) { ··· 20755 20726 jsoff_t off = lkp(js, arr_obj, key, key_len); 20756 20727 return off == 0 ? js_mkundef() : resolveprop(js, mkval(T_PROP, off)); 20757 20728 } 20729 + 20730 + uint8_t t = vtype(obj); 20731 + bool is_promise = (t == T_PROMISE); 20732 + if (is_promise) obj = mkval(T_OBJ, vdata(obj)); 20733 + else if (t != T_OBJ) return js_mkundef(); 20734 + jsoff_t off = lkp(js, obj, key, key_len); 20758 20735 20759 - if (vtype(obj) == T_PROMISE) { 20760 - jsval_t prom_obj = mkval(T_OBJ, vdata(obj)); 20761 - jsoff_t off = lkp(js, prom_obj, key, key_len); 20762 - if (off != 0) return resolveprop(js, mkval(T_PROP, off)); 20736 + if (off == 0) { 20737 + jsval_t result = try_dynamic_getter(js, obj, key, key_len); 20738 + if (vtype(result) != T_UNDEF) return result; 20739 + } 20740 + 20741 + if (off == 0 && is_promise) { 20763 20742 jsval_t promise_proto = get_ctor_proto(js, "Promise", 7); 20764 20743 if (vtype(promise_proto) != T_UNDEF && vtype(promise_proto) != T_NULL) { 20765 20744 off = lkp(js, promise_proto, key, key_len); 20766 20745 if (off != 0) return resolveprop(js, mkval(T_PROP, off)); 20767 20746 } 20768 - return js_mkundef(); 20769 - } 20770 - 20771 - if (vtype(obj) != T_OBJ) return js_mkundef(); 20772 - jsoff_t off = lkp(js, obj, key, key_len); 20773 - 20774 - if (off == 0) { 20775 - jsval_t result = try_dynamic_getter(js, obj, key, key_len); 20776 - if (vtype(result) != T_UNDEF) return result; 20777 20747 } 20778 20748 20779 20749 return off == 0 ? js_mkundef() : resolveprop(js, mkval(T_PROP, off)); ··· 20899 20869 if (vtype(func) == T_FFI) { 20900 20870 return ffi_call_by_index(js, (unsigned int)vdata(func), args, nargs); 20901 20871 } else if (vtype(func) == T_CFUNC) { 20872 + jsval_t saved_this = js->this_val; 20873 + if (use_bound_this) js->this_val = bound_this; 20902 20874 jsval_t (*fn)(struct js *, jsval_t *, int) = (jsval_t(*)(struct js *, jsval_t *, int)) vdata(func); 20903 - return fn(js, args, nargs); 20875 + jsval_t res = fn(js, args, nargs); 20876 + js->this_val = saved_this; 20877 + return res; 20904 20878 } else if (vtype(func) == T_FUNC) { 20905 20879 jsval_t func_obj = mkval(T_OBJ, vdata(func)); 20906 20880 jsoff_t native_off = lkp_interned(js, func_obj, INTERN_NATIVE_FUNC, 13);