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 unhandled promise rejection tracking and handling

+61 -4
+1
include/ant.h
··· 145 145 146 146 void js_resolve_promise(struct js *js, jsval_t promise, jsval_t value); 147 147 void js_reject_promise(struct js *js, jsval_t promise, jsval_t value); 148 + void js_check_unhandled_rejections(struct js *js); 148 149 149 150 void js_run_event_loop(struct js *js); 150 151 void js_poll_events(struct js *js);
+58 -4
src/ant.c
··· 256 256 uint32_t trigger_pid; 257 257 jsoff_t obj_offset; 258 258 int state; 259 + bool has_rejection_handler; 259 260 UT_hash_handle hh; 261 + UT_hash_handle hh_unhandled; 260 262 } promise_data_entry_t; 261 263 262 264 static promise_data_entry_t *promise_registry = NULL; 265 + static promise_data_entry_t *unhandled_rejections = NULL; 263 266 static uint32_t next_promise_id = 1; 264 267 265 268 static promise_data_entry_t *get_promise_data(uint32_t promise_id, bool create); ··· 18611 18614 entry->obj_offset = 0; 18612 18615 entry->state = 0; 18613 18616 entry->value = js_mkundef(); 18617 + entry->has_rejection_handler = false; 18614 18618 utarray_new(entry->handlers, &promise_handler_icd); 18615 18619 HASH_ADD(hh, promise_registry, promise_id, sizeof(uint32_t), entry); 18616 18620 ··· 18729 18733 18730 18734 pd->state = 2; 18731 18735 pd->value = val; 18736 + 18737 + // Track unhandled rejection if no handler attached yet 18738 + if (!pd->has_rejection_handler) { 18739 + promise_data_entry_t *existing = NULL; 18740 + HASH_FIND(hh_unhandled, unhandled_rejections, &pd->promise_id, sizeof(uint32_t), existing); 18741 + if (!existing) { 18742 + HASH_ADD(hh_unhandled, unhandled_rejections, promise_id, sizeof(uint32_t), pd); 18743 + } 18744 + } 18745 + 18732 18746 trigger_handlers(js, p); 18733 18747 } 18734 18748 ··· 18810 18824 if (pd) { 18811 18825 promise_handler_t h = { onFulfilled, onRejected, nextP }; 18812 18826 utarray_push_back(pd->handlers, &h); 18827 + 18828 + if (vtype(onRejected) == T_FUNC || vtype(onRejected) == T_CFUNC) { 18829 + pd->has_rejection_handler = true; 18830 + HASH_DELETE(hh_unhandled, unhandled_rejections, pd); 18831 + } 18813 18832 } 18814 18833 18815 18834 if (pd && pd->state != 0) trigger_handlers(js, p); ··· 21827 21846 } 21828 21847 21829 21848 promise_data_entry_t *pd, *pd_tmp; 21830 - for (promise_data_entry_t *new_promise_registry = NULL, *_once = NULL; !_once; _once = (void*)1, promise_registry = new_promise_registry) 21849 + promise_data_entry_t *new_unhandled = NULL; 21850 + 21851 + for ( 21852 + promise_data_entry_t *new_promise_registry = NULL, *_once = NULL; !_once; _once = (void*)1, 21853 + promise_registry = new_promise_registry, unhandled_rejections = new_unhandled 21854 + ) 21831 21855 HASH_ITER(hh, promise_registry, pd, pd_tmp) { 21832 21856 HASH_DEL(promise_registry, pd); 21857 + promise_data_entry_t *in_unhandled = NULL; 21858 + HASH_FIND(hh_unhandled, unhandled_rejections, &pd->promise_id, sizeof(uint32_t), in_unhandled); 21859 + if (in_unhandled) HASH_DELETE(hh_unhandled, unhandled_rejections, pd); 21860 + 21833 21861 jsoff_t new_off = fwd_off(ctx, pd->obj_offset); 21834 21862 if (new_off == pd->obj_offset && pd->obj_offset != 0) { 21835 - // Object not forwarded means it's dead - free the entry 21836 21863 utarray_free(pd->handlers); 21837 - free(pd); 21838 - continue; 21864 + free(pd); continue; 21839 21865 } 21866 + 21840 21867 pd->obj_offset = new_off; 21841 21868 FWD_VAL(pd->value); 21842 21869 UTARRAY_EACH(pd->handlers, promise_handler_t, h) { ··· 21844 21871 FWD_VAL(h->onRejected); 21845 21872 FWD_VAL(h->nextPromise); 21846 21873 } 21874 + 21847 21875 HASH_ADD(hh, new_promise_registry, promise_id, sizeof(uint32_t), pd); 21876 + if (in_unhandled) HASH_ADD(hh_unhandled, new_unhandled, promise_id, sizeof(uint32_t), pd); 21848 21877 } 21849 21878 21850 21879 if (rt && rt->js == js) FWD_VAL(rt->ant_obj); ··· 22205 22234 jsval_t js_mkpromise(struct js *js) { return mkpromise(js); } 22206 22235 void js_resolve_promise(struct js *js, jsval_t promise, jsval_t value) { resolve_promise(js, promise, value); } 22207 22236 void js_reject_promise(struct js *js, jsval_t promise, jsval_t value) { reject_promise(js, promise, value); } 22237 + 22238 + void js_check_unhandled_rejections(struct js *js) { 22239 + promise_data_entry_t *pd, *tmp; 22240 + 22241 + HASH_ITER(hh_unhandled, unhandled_rejections, pd, tmp) { 22242 + if (pd->has_rejection_handler) { 22243 + HASH_DELETE(hh_unhandled, unhandled_rejections, pd); continue; 22244 + } 22245 + 22246 + if (pd->trigger_pid != 0) { 22247 + promise_data_entry_t *parent; 22248 + HASH_FIND(hh, promise_registry, &pd->trigger_pid, sizeof(uint32_t), parent); 22249 + if (parent && parent->has_rejection_handler) { 22250 + HASH_DELETE(hh_unhandled, unhandled_rejections, pd); continue; 22251 + } 22252 + } 22253 + 22254 + char buf[1024]; 22255 + buf[tostr(js, pd->value, buf, sizeof(buf) - 1)] = '\0'; 22256 + fprintf(stderr, "Uncaught (in promise) %s\n", buf); 22257 + 22258 + pd->has_rejection_handler = true; 22259 + HASH_DELETE(hh_unhandled, unhandled_rejections, pd); 22260 + } 22261 + } 22208 22262 22209 22263 bool js_is_slot_prop(jsoff_t header) { return is_slot_prop(header); } 22210 22264 jsoff_t js_next_prop(jsoff_t header) { return next_prop(header); }
+2
src/modules/timer.c
··· 220 220 221 221 ANT_GC_FREE(entry); 222 222 } 223 + 224 + js_check_unhandled_rejections(js); 223 225 } 224 226 225 227 void process_immediates(struct js *js) {