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.

make n-api gc safe

+199 -68
+199 -68
src/modules/napi.c
··· 1 + // TODO: split into multiple files 2 + 1 3 #include <compat.h> // IWYU pragma: keep 2 4 3 5 #ifdef _WIN32 ··· 33 35 34 36 #include "modules/buffer.h" 35 37 #include "modules/napi.h" 38 + #include "gc/roots.h" 39 + #include "gc/modules.h" 36 40 37 41 typedef struct napi_cleanup_hook_entry { 38 42 napi_cleanup_hook hook; ··· 48 52 napi_value pending_exception; 49 53 uint32_t version; 50 54 napi_cleanup_hook_entry_t *cleanup_hooks; 55 + struct napi_ref__ *refs; 56 + struct napi_deferred__ *deferreds; 57 + struct napi_threadsafe_function__ *tsfns; 58 + int open_handle_scopes; 59 + ant_value_t *handle_slots; 60 + size_t handle_slots_len; 61 + size_t handle_slots_cap; 51 62 } ant_napi_env_t; 52 63 53 64 typedef struct napi_callback_binding { ··· 70 81 ant_value_t ref_val; 71 82 napi_value value; 72 83 uint32_t refcount; 84 + struct napi_ref__ *next; 85 + struct napi_ref__ *prev; 73 86 }; 74 87 75 88 struct napi_deferred__ { 76 89 ant_napi_env_t *env; 77 90 ant_value_t promise_val; 78 91 bool settled; 92 + struct napi_deferred__ *next; 93 + struct napi_deferred__ *prev; 79 94 }; 80 95 81 96 struct napi_handle_scope__ { 82 97 ant_napi_env_t *env; 98 + size_t gc_root_mark; 99 + size_t handle_slots_mark; 83 100 }; 84 101 85 102 struct napi_escapable_handle_scope__ { 86 103 ant_napi_env_t *env; 104 + size_t gc_root_mark; 105 + size_t handle_slots_mark; 87 106 bool escaped; 107 + ant_value_t escaped_val; 88 108 }; 89 109 90 110 struct napi_async_context__ { ··· 142 162 uv_mutex_t mutex; 143 163 napi_tsfn_item_t *head; 144 164 napi_tsfn_item_t *tail; 165 + struct napi_threadsafe_function__ *next; 166 + struct napi_threadsafe_function__ *prev; 145 167 }; 146 168 147 - typedef napi_value(NAPI_CDECL* napi_register_module_v1_fn)(napi_env env, napi_value exports); 169 + typedef napi_value(NAPI_CDECL* napi_register_module_v1_fn)( 170 + napi_env env, napi_value exports 171 + ); 148 172 149 173 typedef struct napi_native_lib { 150 174 void *handle; ··· 158 182 static uint64_t g_napi_wrap_next_id = 1; 159 183 static napi_native_lib_t *g_napi_native_libs = NULL; 160 184 static napi_module *g_pending_napi_module = NULL; 185 + static int64_t g_napi_external_memory = 0; 186 + 161 187 static const napi_node_version g_napi_node_version = { 162 188 .major = 25, 163 189 .minor = 0, 164 190 .patch = 0, 165 191 .release = "ant", 166 192 }; 167 - static int64_t g_napi_external_memory = 0; 168 193 169 194 static const char *napi_status_text(napi_status status) { 170 - switch (status) { 171 - case napi_ok: return "ok"; 172 - case napi_invalid_arg: return "invalid argument"; 173 - case napi_object_expected: return "object expected"; 174 - case napi_string_expected: return "string expected"; 175 - case napi_name_expected: return "name expected"; 176 - case napi_function_expected: return "function expected"; 177 - case napi_number_expected: return "number expected"; 178 - case napi_boolean_expected: return "boolean expected"; 179 - case napi_array_expected: return "array expected"; 180 - case napi_generic_failure: return "generic failure"; 181 - case napi_pending_exception: return "pending exception"; 182 - case napi_cancelled: return "cancelled"; 183 - case napi_escape_called_twice: return "escape called twice"; 184 - case napi_handle_scope_mismatch: return "handle scope mismatch"; 185 - case napi_callback_scope_mismatch: return "callback scope mismatch"; 186 - case napi_queue_full: return "queue full"; 187 - case napi_closing: return "closing"; 188 - case napi_bigint_expected: return "bigint expected"; 189 - case napi_date_expected: return "date expected"; 190 - case napi_arraybuffer_expected: return "arraybuffer expected"; 191 - case napi_detachable_arraybuffer_expected: return "detachable arraybuffer expected"; 192 - case napi_would_deadlock: return "would deadlock"; 193 - case napi_no_external_buffers_allowed: return "no external buffers allowed"; 194 - case napi_cannot_run_js: return "cannot run js"; 195 - default: return "unknown"; 196 - } 197 - } 195 + switch (status) { 196 + case napi_ok: return "ok"; 197 + case napi_invalid_arg: return "invalid argument"; 198 + case napi_object_expected: return "object expected"; 199 + case napi_string_expected: return "string expected"; 200 + case napi_name_expected: return "name expected"; 201 + case napi_function_expected: return "function expected"; 202 + case napi_number_expected: return "number expected"; 203 + case napi_boolean_expected: return "boolean expected"; 204 + case napi_array_expected: return "array expected"; 205 + case napi_generic_failure: return "generic failure"; 206 + case napi_pending_exception: return "pending exception"; 207 + case napi_cancelled: return "cancelled"; 208 + case napi_escape_called_twice: return "escape called twice"; 209 + case napi_handle_scope_mismatch: return "handle scope mismatch"; 210 + case napi_callback_scope_mismatch: return "callback scope mismatch"; 211 + case napi_queue_full: return "queue full"; 212 + case napi_closing: return "closing"; 213 + case napi_bigint_expected: return "bigint expected"; 214 + case napi_date_expected: return "date expected"; 215 + case napi_arraybuffer_expected: return "arraybuffer expected"; 216 + case napi_detachable_arraybuffer_expected: return "detachable arraybuffer expected"; 217 + case napi_would_deadlock: return "would deadlock"; 218 + case napi_no_external_buffers_allowed: return "no external buffers allowed"; 219 + case napi_cannot_run_js: return "cannot run js"; 220 + default: return "unknown"; 221 + }} 198 222 199 223 static napi_status napi_set_last(napi_env env, napi_status status, const char *message) { 200 224 ant_napi_env_t *nenv = (ant_napi_env_t *)env; ··· 208 232 nenv->last_error.engine_error_code = 0; 209 233 nenv->last_error.error_code = status; 210 234 235 + if (status != napi_ok) { 236 + } 237 + 211 238 return status; 212 239 } 213 240 ··· 226 253 return (napi_env)napi_get_or_create_env(js); 227 254 } 228 255 256 + void gc_mark_napi(ant_t *js, gc_mark_fn mark) { 257 + if (!g_napi_env || g_napi_env->js != js) return; 258 + ant_napi_env_t *nenv = g_napi_env; 259 + 260 + if (nenv->has_pending_exception) 261 + mark(js, (ant_value_t)nenv->pending_exception); 262 + 263 + for (struct napi_ref__ *r = nenv->refs; r; r = r->next) { 264 + if (r->refcount > 0) mark(js, r->ref_val); 265 + mark(js, (ant_value_t)r->value); 266 + } 267 + 268 + for (struct napi_deferred__ *d = nenv->deferreds; d; d = d->next) 269 + if (!d->settled) mark(js, d->promise_val); 270 + 271 + for (struct napi_threadsafe_function__ *t = nenv->tsfns; t; t = t->next) mark(js, t->func_val); 272 + for (size_t i = 0; i < nenv->handle_slots_len; i++) mark(js, nenv->handle_slots[i]); 273 + } 274 + 275 + static inline napi_value napi_scope_pin(ant_napi_env_t *nenv, napi_value val) { 276 + ant_value_t v = (ant_value_t)val; 277 + if (!nenv || !is_object_type(v)) return val; 278 + 279 + if (nenv->handle_slots_len >= nenv->handle_slots_cap) { 280 + size_t new_cap = nenv->handle_slots_cap ? nenv->handle_slots_cap * 2 : 256; 281 + ant_value_t *new_slots = realloc(nenv->handle_slots, new_cap * sizeof(ant_value_t)); 282 + if (!new_slots) return val; 283 + nenv->handle_slots = new_slots; 284 + nenv->handle_slots_cap = new_cap; 285 + } 286 + nenv->handle_slots[nenv->handle_slots_len++] = v; 287 + return val; 288 + } 289 + 290 + #define NAPI_RETURN(nenv, val) napi_scope_pin((nenv), (napi_value)(val)) 291 + 229 292 static void napi_mark_pending_exception(napi_env env, napi_value exception) { 230 293 ant_napi_env_t *nenv = (ant_napi_env_t *)env; 231 294 if (!nenv) return; ··· 394 457 js_set(nenv->js, fn, "name", js_mkstr(nenv->js, utf8name, nlen)); 395 458 } 396 459 397 - *result = (napi_value)fn; 460 + *result = NAPI_RETURN(nenv, fn); 398 461 return napi_set_last(env, napi_ok, NULL); 399 462 } 400 463 ··· 429 492 ant_value_t proto = js_get_ctor_proto(js, name, strlen(name)); 430 493 if (is_object_type(proto)) js_set_proto_init(err, proto); 431 494 432 - *result = (napi_value)err; 495 + *result = NAPI_RETURN(nenv, err); 433 496 return napi_set_last(env, napi_ok, NULL); 434 497 } 435 498 ··· 491 554 492 555 if (tsfn->thread_finalize_cb) { 493 556 tsfn->thread_finalize_cb((napi_env)tsfn->env, tsfn->thread_finalize_data, NULL); 557 + } 558 + 559 + if (tsfn->env) { 560 + if (tsfn->prev) tsfn->prev->next = tsfn->next; 561 + else if (tsfn->env->tsfns == tsfn) tsfn->env->tsfns = tsfn->next; 562 + if (tsfn->next) tsfn->next->prev = tsfn->prev; 494 563 } 495 564 496 565 if (tsfn->env && tsfn->env->js) { ··· 661 730 NAPI_EXTERN napi_status NAPI_CDECL napi_get_global(napi_env env, napi_value *result) { 662 731 ant_napi_env_t *nenv = (ant_napi_env_t *)env; 663 732 if (!nenv || !nenv->js || !result) return napi_set_last(env, napi_invalid_arg, "invalid argument"); 664 - *result = (napi_value)js_glob(nenv->js); 733 + *result = NAPI_RETURN(nenv, js_glob(nenv->js)); 665 734 return napi_set_last(env, napi_ok, NULL); 666 735 } 667 736 ··· 674 743 NAPI_EXTERN napi_status NAPI_CDECL napi_create_object(napi_env env, napi_value *result) { 675 744 ant_napi_env_t *nenv = (ant_napi_env_t *)env; 676 745 if (!nenv || !nenv->js || !result) return napi_set_last(env, napi_invalid_arg, "invalid argument"); 677 - *result = (napi_value)js_mkobj(nenv->js); 746 + *result = NAPI_RETURN(nenv, js_mkobj(nenv->js)); 678 747 return napi_set_last(env, napi_ok, NULL); 679 748 } 680 749 681 750 NAPI_EXTERN napi_status NAPI_CDECL napi_create_array(napi_env env, napi_value *result) { 682 751 ant_napi_env_t *nenv = (ant_napi_env_t *)env; 683 752 if (!nenv || !nenv->js || !result) return napi_set_last(env, napi_invalid_arg, "invalid argument"); 684 - *result = (napi_value)js_mkarr(nenv->js); 753 + *result = NAPI_RETURN(nenv, js_mkarr(nenv->js)); 685 754 return napi_set_last(env, napi_ok, NULL); 686 755 } 687 756 ··· 699 768 js_mknum((double)length) 700 769 ); 701 770 if (is_err(r)) return napi_check_pending_from_result(env, r); 702 - *result = (napi_value)arr; 771 + *result = NAPI_RETURN(nenv, arr); 703 772 return napi_set_last(env, napi_ok, NULL); 704 773 } 705 774 ··· 735 804 ) { 736 805 ant_napi_env_t *nenv = (ant_napi_env_t *)env; 737 806 if (!nenv || !nenv->js || !result || !str) return napi_set_last(env, napi_invalid_arg, "invalid argument"); 738 - *result = (napi_value)napi_make_string(nenv->js, str, length); 807 + *result = NAPI_RETURN(nenv, napi_make_string(nenv->js, str, length)); 739 808 return napi_set_last(env, napi_ok, NULL); 740 809 } 741 810 ··· 747 816 ) { 748 817 ant_napi_env_t *nenv = (ant_napi_env_t *)env; 749 818 if (!nenv || !nenv->js || !result || !str) return napi_set_last(env, napi_invalid_arg, "invalid argument"); 750 - *result = (napi_value)napi_make_string(nenv->js, str, length); 819 + *result = NAPI_RETURN(nenv, napi_make_string(nenv->js, str, length)); 751 820 return napi_set_last(env, napi_ok, NULL); 752 821 } 753 822 ··· 768 837 desc = js_getstr(nenv->js, s, NULL); 769 838 } 770 839 771 - *result = (napi_value)js_mksym(nenv->js, desc); 840 + *result = NAPI_RETURN(nenv, js_mksym(nenv->js, desc)); 772 841 return napi_set_last(env, napi_ok, NULL); 773 842 } 774 843 ··· 834 903 835 904 ant_value_t obj = js_mkobj(nenv->js); 836 905 napi_slot_set_u64(nenv->js, obj, SLOT_NAPI_EXTERNAL_ID, entry->id); 837 - *result = (napi_value)obj; 906 + *result = NAPI_RETURN(nenv, obj); 838 907 839 908 return napi_set_last(env, napi_ok, NULL); 840 909 } ··· 857 926 def->promise_val = p; 858 927 def->settled = false; 859 928 929 + def->prev = NULL; 930 + def->next = nenv->deferreds; 931 + if (nenv->deferreds) nenv->deferreds->prev = def; 932 + nenv->deferreds = def; 933 + 860 934 *deferred = (napi_deferred)def; 861 935 *promise = (napi_value)p; 862 936 return napi_set_last(env, napi_ok, NULL); ··· 877 951 js_resolve_promise(nenv->js, promise, (ant_value_t)resolution); 878 952 def->settled = true; 879 953 def->promise_val = js_mkundef(); 954 + 955 + if (def->prev) def->prev->next = def->next; 956 + else if (nenv->deferreds == def) nenv->deferreds = def->next; 957 + if (def->next) def->next->prev = def->prev; 958 + 880 959 return napi_set_last(env, napi_ok, NULL); 881 960 } 882 961 ··· 895 974 js_reject_promise(nenv->js, promise, (ant_value_t)rejection); 896 975 def->settled = true; 897 976 def->promise_val = js_mkundef(); 977 + 978 + if (def->prev) def->prev->next = def->next; 979 + else if (nenv->deferreds == def) nenv->deferreds = def->next; 980 + if (def->next) def->next->prev = def->prev; 981 + 898 982 return napi_set_last(env, napi_ok, NULL); 899 983 } 900 984 ··· 914 998 if (is_err(value)) return napi_check_pending_from_result(env, value); 915 999 916 1000 if (data) *data = buf->data; 917 - *result = (napi_value)value; 1001 + *result = NAPI_RETURN(nenv, value); 918 1002 return napi_set_last(env, napi_ok, NULL); 919 1003 } 920 1004 ··· 963 1047 free_array_buffer_data(ab); 964 1048 965 1049 if (data) *data = ab->data; 966 - *result = (napi_value)ab_obj; 1050 + *result = NAPI_RETURN(nenv, ab_obj); 967 1051 return napi_set_last(env, napi_ok, NULL); 968 1052 } 969 1053 ··· 1037 1121 ); 1038 1122 1039 1123 if (is_err(out)) return napi_check_pending_from_result(env, out); 1040 - *result = (napi_value)out; 1124 + *result = NAPI_RETURN(nenv, out); 1041 1125 return napi_set_last(env, napi_ok, NULL); 1042 1126 } 1043 1127 ··· 1058 1142 ref->refcount = initial_refcount; 1059 1143 ref->ref_val = (initial_refcount > 0) ? (ant_value_t)value : js_mkundef(); 1060 1144 1145 + ref->prev = NULL; 1146 + ref->next = nenv->refs; 1147 + if (nenv->refs) nenv->refs->prev = ref; 1148 + nenv->refs = ref; 1149 + 1061 1150 *result = (napi_ref)ref; 1062 1151 return napi_set_last(env, napi_ok, NULL); 1063 1152 } ··· 1069 1158 ant_napi_env_t *nenv = (ant_napi_env_t *)env; 1070 1159 struct napi_ref__ *r = (struct napi_ref__ *)ref; 1071 1160 if (!nenv || !nenv->js || !r) return napi_set_last((napi_env)env, napi_invalid_arg, "invalid argument"); 1161 + 1162 + if (r->prev) r->prev->next = r->next; 1163 + else if (nenv->refs == r) nenv->refs = r->next; 1164 + if (r->next) r->next->prev = r->prev; 1165 + 1072 1166 r->ref_val = js_mkundef(); 1073 1167 free(r); 1074 1168 return napi_set_last((napi_env)env, napi_ok, NULL); ··· 1116 1210 struct napi_ref__ *r = (struct napi_ref__ *)ref; 1117 1211 if (!nenv || !nenv->js || !r || !result) return napi_set_last(env, napi_invalid_arg, "invalid argument"); 1118 1212 1119 - if (r->refcount > 0) *result = (napi_value)r->ref_val; 1213 + if (r->refcount > 0) *result = NAPI_RETURN(nenv, r->ref_val); 1120 1214 else *result = r->value; 1121 1215 1122 1216 return napi_set_last(env, napi_ok, NULL); ··· 1364 1458 ) { 1365 1459 ant_napi_env_t *nenv = (ant_napi_env_t *)env; 1366 1460 if (!nenv || !nenv->js || !result) return napi_set_last(env, napi_invalid_arg, "invalid argument"); 1367 - *result = (napi_value)js_get_proto(nenv->js, (ant_value_t)object); 1461 + *result = NAPI_RETURN(nenv, js_get_proto(nenv->js, (ant_value_t)object)); 1368 1462 return napi_set_last(env, napi_ok, NULL); 1369 1463 } 1370 1464 ··· 1388 1482 } 1389 1483 js_prop_iter_end(&iter); 1390 1484 1391 - *result = (napi_value)out; 1485 + *result = NAPI_RETURN(nenv, out); 1392 1486 return napi_set_last(env, napi_ok, NULL); 1393 1487 } 1394 1488 ··· 1439 1533 ant_value_t k = (ant_value_t)key; 1440 1534 if (vtype(k) == T_SYMBOL) { 1441 1535 ant_offset_t off = lkp_sym_proto(nenv->js, (ant_value_t)object, (ant_offset_t)vdata(k)); 1442 - *result = (napi_value)(off ? js_propref_load(nenv->js, off) : js_mkundef()); 1536 + *result = NAPI_RETURN(nenv, (off ? js_propref_load(nenv->js, off) : js_mkundef())); 1443 1537 return napi_set_last(env, napi_ok, NULL); 1444 1538 } 1445 1539 ··· 1455 1549 memcpy(name, ks, klen); 1456 1550 name[klen] = '\0'; 1457 1551 1458 - *result = (napi_value)js_getprop_fallback(nenv->js, (ant_value_t)object, name); 1552 + *result = NAPI_RETURN(nenv, js_getprop_fallback(nenv->js, (ant_value_t)object, name)); 1459 1553 free(name); 1460 1554 1461 1555 return napi_set_last(env, napi_ok, NULL); ··· 1591 1685 } 1592 1686 char idx[32]; 1593 1687 snprintf(idx, sizeof(idx), "%u", index); 1594 - *result = (napi_value)js_get(nenv->js, (ant_value_t)object, idx); 1688 + *result = NAPI_RETURN(nenv, js_get(nenv->js, (ant_value_t)object, idx)); 1595 1689 return napi_set_last(env, napi_ok, NULL); 1596 1690 } 1597 1691 ··· 1930 2024 return napi_set_last(env, napi_ok, NULL); 1931 2025 } 1932 2026 2027 + static _Thread_local int napi_strict_eq_call_count = 0; 2028 + 1933 2029 NAPI_EXTERN napi_status NAPI_CDECL napi_strict_equals( 1934 2030 napi_env env, 1935 2031 napi_value lhs, ··· 1939 2035 ant_napi_env_t *nenv = (ant_napi_env_t *)env; 1940 2036 if (!nenv || !nenv->js || !result) return napi_set_last(env, napi_invalid_arg, "invalid argument"); 1941 2037 *result = strict_eq_values(nenv->js, (ant_value_t)lhs, (ant_value_t)rhs); 2038 + if (getenv("ANT_NAPI_TRACE")) { 2039 + napi_strict_eq_call_count++; 2040 + if (napi_strict_eq_call_count >= 2000 && napi_strict_eq_call_count < 2030) { 2041 + fprintf(stderr, "[napi-seq] call#%d lhs=0x%llx(vt=%d) rhs=0x%llx(vt=%d) => %d\n", 2042 + napi_strict_eq_call_count, 2043 + (unsigned long long)(ant_value_t)lhs, vtype((ant_value_t)lhs), 2044 + (unsigned long long)(ant_value_t)rhs, vtype((ant_value_t)rhs), 2045 + *result); 2046 + } 2047 + } 1942 2048 return napi_set_last(env, napi_ok, NULL); 1943 2049 } 1944 2050 ··· 1967 2073 ); 1968 2074 1969 2075 if (is_err(out) || nenv->js->thrown_exists) return napi_check_pending_from_result(env, out); 1970 - if (result) *result = (napi_value)out; 2076 + if (result) *result = NAPI_RETURN(nenv, out); 1971 2077 return napi_set_last(env, napi_ok, NULL); 1972 2078 } 1973 2079 ··· 2003 2109 nenv->js->new_target = saved; 2004 2110 2005 2111 if (is_err(out) || nenv->js->thrown_exists) return napi_check_pending_from_result(env, out); 2006 - *result = (napi_value)(is_object_type(out) ? out : obj); 2112 + *result = NAPI_RETURN(nenv, (is_object_type(out) ? out : obj)); 2007 2113 return napi_set_last(env, napi_ok, NULL); 2008 2114 } 2009 2115 ··· 2014 2120 ) { 2015 2121 ant_napi_env_t *nenv = (ant_napi_env_t *)env; 2016 2122 if (!nenv || !nenv->js || !result) return napi_set_last(env, napi_invalid_arg, "invalid argument"); 2017 - *result = (napi_value)js_bool(js_truthy(nenv->js, (ant_value_t)value)); 2123 + *result = NAPI_RETURN(nenv, js_bool(js_truthy(nenv->js, (ant_value_t)value))); 2018 2124 return napi_set_last(env, napi_ok, NULL); 2019 2125 } 2020 2126 ··· 2025 2131 ) { 2026 2132 ant_napi_env_t *nenv = (ant_napi_env_t *)env; 2027 2133 if (!nenv || !nenv->js || !result) return napi_set_last(env, napi_invalid_arg, "invalid argument"); 2028 - *result = (napi_value)js_mknum(js_to_number(nenv->js, (ant_value_t)value)); 2134 + *result = NAPI_RETURN(nenv, js_mknum(js_to_number(nenv->js, (ant_value_t)value))); 2029 2135 return napi_set_last(env, napi_ok, NULL); 2030 2136 } 2031 2137 ··· 2047 2153 ant_value_t arg = (ant_value_t)value; 2048 2154 ant_value_t out = sv_vm_call(nenv->js->vm, nenv->js, obj_ctor, js_mkundef(), &arg, 1, NULL, false); 2049 2155 if (is_err(out) || nenv->js->thrown_exists) return napi_check_pending_from_result(env, out); 2050 - *result = (napi_value)out; 2156 + *result = NAPI_RETURN(nenv, out); 2051 2157 return napi_set_last(env, napi_ok, NULL); 2052 2158 } 2053 2159 ··· 2060 2166 if (!nenv || !nenv->js || !result) return napi_set_last(env, napi_invalid_arg, "invalid argument"); 2061 2167 ant_value_t out = coerce_to_str(nenv->js, (ant_value_t)value); 2062 2168 if (is_err(out) || nenv->js->thrown_exists) return napi_check_pending_from_result(env, out); 2063 - *result = (napi_value)out; 2169 + *result = NAPI_RETURN(nenv, out); 2064 2170 return napi_set_last(env, napi_ok, NULL); 2065 2171 } 2066 2172 ··· 2121 2227 nenv->has_pending_exception = false; 2122 2228 nenv->pending_exception = (napi_value)js_mkundef(); 2123 2229 } else if (nenv->js->thrown_exists) { 2124 - *result = (napi_value)nenv->js->thrown_value; 2230 + *result = NAPI_RETURN(nenv, nenv->js->thrown_value); 2125 2231 nenv->js->thrown_exists = false; 2126 2232 nenv->js->thrown_value = js_mkundef(); 2127 2233 nenv->js->thrown_stack = js_mkundef(); 2128 2234 } else { 2129 - *result = (napi_value)js_mkundef(); 2235 + *result = NAPI_RETURN(nenv, js_mkundef()); 2130 2236 } 2131 2237 2132 2238 return napi_set_last(env, napi_ok, NULL); ··· 2224 2330 napi_env env, 2225 2331 napi_handle_scope *result 2226 2332 ) { 2227 - if (!env || !result) return napi_set_last(env, napi_invalid_arg, "invalid argument"); 2333 + ant_napi_env_t *nenv = (ant_napi_env_t *)env; 2334 + if (!nenv || !nenv->js || !result) return napi_set_last(env, napi_invalid_arg, "invalid argument"); 2228 2335 struct napi_handle_scope__ *scope = (struct napi_handle_scope__ *)calloc(1, sizeof(*scope)); 2229 2336 if (!scope) return napi_set_last(env, napi_generic_failure, "out of memory"); 2230 - scope->env = (ant_napi_env_t *)env; 2337 + scope->env = nenv; 2338 + scope->gc_root_mark = gc_root_scope(nenv->js); 2339 + scope->handle_slots_mark = nenv->handle_slots_len; 2340 + nenv->open_handle_scopes++; 2231 2341 *result = (napi_handle_scope)scope; 2232 2342 return napi_set_last(env, napi_ok, NULL); 2233 2343 } ··· 2236 2346 napi_env env, 2237 2347 napi_handle_scope scope 2238 2348 ) { 2239 - (void)env; 2240 - if (!scope) return napi_set_last(env, napi_invalid_arg, "invalid argument"); 2349 + ant_napi_env_t *nenv = (ant_napi_env_t *)env; 2350 + if (!nenv || !scope) return napi_set_last(env, napi_invalid_arg, "invalid argument"); 2351 + struct napi_handle_scope__ *s = (struct napi_handle_scope__ *)scope; 2352 + if (nenv->js) gc_pop_roots(nenv->js, s->gc_root_mark); 2353 + nenv->handle_slots_len = s->handle_slots_mark; 2354 + if (nenv->open_handle_scopes > 0) nenv->open_handle_scopes--; 2241 2355 free(scope); 2242 2356 return napi_set_last(env, napi_ok, NULL); 2243 2357 } ··· 2246 2360 napi_env env, 2247 2361 napi_escapable_handle_scope *result 2248 2362 ) { 2249 - if (!env || !result) return napi_set_last(env, napi_invalid_arg, "invalid argument"); 2363 + ant_napi_env_t *nenv = (ant_napi_env_t *)env; 2364 + if (!nenv || !nenv->js || !result) return napi_set_last(env, napi_invalid_arg, "invalid argument"); 2250 2365 struct napi_escapable_handle_scope__ *scope = (struct napi_escapable_handle_scope__ *)calloc(1, sizeof(*scope)); 2251 2366 if (!scope) return napi_set_last(env, napi_generic_failure, "out of memory"); 2252 - scope->env = (ant_napi_env_t *)env; 2367 + scope->env = nenv; 2368 + scope->gc_root_mark = gc_root_scope(nenv->js); 2369 + scope->handle_slots_mark = nenv->handle_slots_len; 2253 2370 scope->escaped = false; 2371 + scope->escaped_val = js_mkundef(); 2372 + nenv->open_handle_scopes++; 2254 2373 *result = (napi_escapable_handle_scope)scope; 2255 2374 return napi_set_last(env, napi_ok, NULL); 2256 2375 } ··· 2259 2378 napi_env env, 2260 2379 napi_escapable_handle_scope scope 2261 2380 ) { 2262 - (void)env; 2263 - if (!scope) return napi_set_last(env, napi_invalid_arg, "invalid argument"); 2381 + ant_napi_env_t *nenv = (ant_napi_env_t *)env; 2382 + if (!nenv || !scope) return napi_set_last(env, napi_invalid_arg, "invalid argument"); 2383 + struct napi_escapable_handle_scope__ *s = (struct napi_escapable_handle_scope__ *)scope; 2384 + if (nenv->js) gc_pop_roots(nenv->js, s->gc_root_mark); 2385 + nenv->handle_slots_len = s->handle_slots_mark; 2386 + if (nenv->open_handle_scopes > 0) nenv->open_handle_scopes--; 2264 2387 free(scope); 2265 2388 return napi_set_last(env, napi_ok, NULL); 2266 2389 } ··· 2271 2394 napi_value escapee, 2272 2395 napi_value *result 2273 2396 ) { 2397 + ant_napi_env_t *nenv = (ant_napi_env_t *)env; 2274 2398 struct napi_escapable_handle_scope__ *esc = (struct napi_escapable_handle_scope__ *)scope; 2275 - if (!env || !esc || !result) return napi_set_last(env, napi_invalid_arg, "invalid argument"); 2399 + if (!nenv || !nenv->js || !esc || !result) return napi_set_last(env, napi_invalid_arg, "invalid argument"); 2276 2400 if (esc->escaped) return napi_set_last(env, napi_escape_called_twice, "escape already called"); 2277 2401 esc->escaped = true; 2402 + esc->escaped_val = (ant_value_t)escapee; 2403 + gc_push_root(nenv->js, &esc->escaped_val); 2278 2404 *result = escapee; 2279 2405 return napi_set_last(env, napi_ok, NULL); 2280 2406 } ··· 2377 2503 tsfn->context = context; 2378 2504 tsfn->max_queue_size = max_queue_size; 2379 2505 tsfn->thread_count = initial_thread_count > 0 ? initial_thread_count : 1; 2380 - tsfn->func_val = (ant_value_t)func; 2506 + tsfn->func_val = func ? (ant_value_t)func : js_mkundef(); 2381 2507 2382 2508 uv_mutex_init(&tsfn->mutex); 2383 2509 int rc = uv_async_init(uv_default_loop(), &tsfn->async, napi_tsfn_async_cb); ··· 2387 2513 return napi_set_last(env, napi_generic_failure, "uv_async_init failed"); 2388 2514 } 2389 2515 tsfn->async.data = tsfn; 2516 + 2517 + tsfn->prev = NULL; 2518 + tsfn->next = nenv->tsfns; 2519 + if (nenv->tsfns) nenv->tsfns->prev = tsfn; 2520 + nenv->tsfns = tsfn; 2390 2521 2391 2522 *result = (napi_threadsafe_function)tsfn; 2392 2523 return napi_set_last(env, napi_ok, NULL); ··· 2506 2637 2507 2638 ant_value_t out = js_eval_bytecode_eval(nenv->js, src, len); 2508 2639 if (is_err(out) || nenv->js->thrown_exists) return napi_check_pending_from_result(env, out); 2509 - *result = (napi_value)out; 2640 + *result = NAPI_RETURN(nenv, out); 2510 2641 return napi_set_last(env, napi_ok, NULL); 2511 2642 } 2512 2643