diff --git a/include/quickjs/quickjs.h b/include/quickjs/quickjs.h index c28c48cf4..290bb8e82 100644 --- a/include/quickjs/quickjs.h +++ b/include/quickjs/quickjs.h @@ -503,6 +503,8 @@ typedef struct JSClassDef { } JSClassDef; JSClassID JS_NewClassID(JSClassID *pclass_id); +JSClassID JS_GetClassID(JSValueConst v); + int JS_NewClass(JSRuntime *rt, JSClassID class_id, const JSClassDef *class_def); int JS_IsRegisteredClass(JSRuntime *rt, JSClassID class_id); @@ -795,6 +797,7 @@ JSValue JS_NewPromiseCapability(JSContext *ctx, JSValue *resolving_funcs); /* is_handled = TRUE means that the rejection is handled */ typedef void JSHostPromiseRejectionTracker(JSContext* ctx, JSValueConst promise, JSValueConst reason, JS_BOOL is_handled, void* opaque); void JS_SetHostPromiseRejectionTracker(JSRuntime *rt, JSHostPromiseRejectionTracker *cb, void *opaque); +void JS_SetHostUnhandledPromiseRejectionTracker(JSRuntime *rt, JSHostPromiseRejectionTracker *cb, void *opaque); /* return != 0 if the JS code needs to be interrupted */ typedef int JSInterruptHandler(JSRuntime *rt, void *opaque); diff --git a/src/core/builtins/js-promise.c b/src/core/builtins/js-promise.c index 324530ecc..a0b001d20 100644 --- a/src/core/builtins/js-promise.c +++ b/src/core/builtins/js-promise.c @@ -131,6 +131,14 @@ void JS_SetHostPromiseRejectionTracker(JSRuntime *rt, rt->host_promise_rejection_tracker_opaque = opaque; } +void JS_SetHostUnhandledPromiseRejectionTracker(JSRuntime *rt, + JSHostPromiseRejectionTracker *cb, + void *opaque) +{ + rt->host_unhandled_promise_rejection_tracker = cb; + rt->host_unhandled_promise_rejection_tracker_opaque = opaque; +} + void fulfill_or_reject_promise(JSContext *ctx, JSValueConst promise, JSValueConst value, BOOL is_reject) { @@ -335,6 +343,14 @@ void js_promise_finalizer(JSRuntime *rt, JSValue val) if (!s) return; + + if (s->promise_state == JS_PROMISE_REJECTED && !s->is_handled) { + if (rt->host_unhandled_promise_rejection_tracker) { + rt->host_unhandled_promise_rejection_tracker(rt, val, s->promise_result, FALSE, + rt->host_unhandled_promise_rejection_tracker_opaque); + } + } + for(i = 0; i < 2; i++) { list_for_each_safe(el, el1, &s->promise_reactions[i]) { JSPromiseReactionData *rd = diff --git a/src/core/runtime.c b/src/core/runtime.c index a6f99f4b5..ff83c3f13 100644 --- a/src/core/runtime.c +++ b/src/core/runtime.c @@ -230,6 +230,16 @@ JSClassID JS_NewClassID(JSClassID* pclass_id) { return class_id; } +JSClassID JS_GetClassID(JSValueConst v) { + JSObject *p; + + if (JS_VALUE_GET_TAG(v) != JS_TAG_OBJECT) + return 0; + p = JS_VALUE_GET_OBJ(v); + assert(p != 0); + return p->class_id; +} + BOOL JS_IsRegisteredClass(JSRuntime* rt, JSClassID class_id) { return (class_id < rt->class_count && rt->class_array[class_id].class_id != 0); } diff --git a/src/core/types.h b/src/core/types.h index 1532d39f7..af18a2abc 100644 --- a/src/core/types.h +++ b/src/core/types.h @@ -209,6 +209,9 @@ struct JSRuntime { JSHostPromiseRejectionTracker *host_promise_rejection_tracker; void *host_promise_rejection_tracker_opaque; + JSHostPromiseRejectionTracker *host_unhandled_promise_rejection_tracker; + void *host_unhandled_promise_rejection_tracker_opaque; + struct list_head job_list; /* list of JSJobEntry.link */ JSModuleNormalizeFunc *module_normalize_func;