[quickjs-devel] [PATCH] make js_std_promise_rejection_tracker trigger async

  • From: 宋xx <sxs930329@xxxxxxxxx>
  • To: quickjs-devel@xxxxxxxxxxxxx
  • Date: Mon, 4 May 2020 12:00:09 +0800

Hi

js_std_promise_rejection_tracker trigger sync may cause problem

new Promise(() => {throw new Error(222)}).catch(e => console.log(e))

output with two error:

Possibly unhandled promise rejection: Error: some error
    at <anonymous> (./hello.js)
    at Promise (native)
    at <eval> (./hello.js:39)

Error: some error

the correct output should be:
Error: some error


greets

Tony


-- snip --



diff --git a/quickjs-libc.c b/quickjs-libc.c
index 4e6d221..e96dc80 100644
--- a/quickjs-libc.c
+++ b/quickjs-libc.c
@@ -84,6 +84,15 @@ typedef struct {
     JSValue func;
 } JSOSTimer;

+typedef struct
+{
+    struct list_head link;
+    JSValue promise;
+    JSValueConst reason;
+} JSUnCaughtPromiseReject;
+
+static struct list_head js_uncaught_promise_reject =
LIST_HEAD_INIT(js_uncaught_promise_reject);
+
 /* initialize the lists so js_std_free_handlers() can always be called */
 static struct list_head os_rw_handlers = LIST_HEAD_INIT(os_rw_handlers);
 static struct list_head os_signal_handlers =
LIST_HEAD_INIT(os_signal_handlers);
@@ -2980,9 +2989,49 @@ void js_std_promise_rejection_tracker(JSContext
*ctx, JSValueConst promise,
                                       JSValueConst reason,
                                       BOOL is_handled, void *opaque)
 {
-    if (!is_handled) {
-        fprintf(stderr, "Possibly unhandled promise rejection: ");
-        js_std_dump_error1(ctx, reason);
+    if (!is_handled)
+    {
+        JSUnCaughtPromiseReject *jr;
+
+        jr = js_mallocz(ctx, sizeof(*jr));
+        if (!jr) {
+            return;
+        }
+        jr->reason = JS_DupValue(ctx, reason);
+        jr->promise = JS_DupValue(ctx, promise);
+        list_add_tail(&jr->link, &js_uncaught_promise_reject);
+    }
+
+    if (is_handled)
+    {
+        struct list_head *el, *el1;
+        list_for_each_safe(el, el1, &js_uncaught_promise_reject)
+        {
+            JSUnCaughtPromiseReject *jr = list_entry(el,
JSUnCaughtPromiseReject, link);
+
+            if (JS_VALUE_GET_OBJ(promise) ==
JS_VALUE_GET_OBJ(jr->promise)) {
+                list_del(&jr->link);
+                JS_FreeValue(ctx, jr->promise);
+                JS_FreeValue(ctx, jr->reason);
+                js_free(ctx, jr);
+            }
+        }
+    }
+}
+
+void js_flush_uncaught_promise_rejection(JSContext *ctx)
+{
+    struct list_head *el, *el1;
+
+    list_for_each_safe(el, el1, &js_uncaught_promise_reject)
+    {
+        JSUnCaughtPromiseReject *jr = list_entry(el,
JSUnCaughtPromiseReject, link);
+        fprintf(stderr, "unhandled promise rejection: ");
+        js_std_dump_error1(ctx, jr->reason);
+        list_del(&jr->link);
+        JS_FreeValue(ctx, jr->promise);
+        JS_FreeValue(ctx, jr->reason);
+        js_free(ctx, jr);
     }
 }

@@ -3004,6 +3053,8 @@ void js_std_loop(JSContext *ctx)
             }
         }

+        js_flush_uncaught_promise_rejection(ctx);
+
         if (!os_poll_func || os_poll_func(ctx))
             break;
     }

Other related posts:

  • » [quickjs-devel] [PATCH] make js_std_promise_rejection_tracker trigger async - 宋xx