about summary refs log tree commit diff stats
path: root/lib/quickjs/quickjs.c
diff options
context:
space:
mode:
authorFabrice Bellard <fabrice@bellard.org>2023-12-13 19:01:59 +0100
committerbptato <nincsnevem662@gmail.com>2023-12-14 11:24:33 +0100
commit8f2f06255105f68bf81c064be4982961102128a6 (patch)
treef90692a61656e2b061ebec6a09a2b73658dc7809 /lib/quickjs/quickjs.c
parent24565a7a34dcaf4efd960640369095587e786ad5 (diff)
downloadchawan-8f2f06255105f68bf81c064be4982961102128a6.tar.gz
fixed async generator in case of exception in the implicit await in the 'return' statement
Diffstat (limited to 'lib/quickjs/quickjs.c')
-rw-r--r--lib/quickjs/quickjs.c29
1 files changed, 20 insertions, 9 deletions
diff --git a/lib/quickjs/quickjs.c b/lib/quickjs/quickjs.c
index ccc8cf2f..a737ea66 100644
--- a/lib/quickjs/quickjs.c
+++ b/lib/quickjs/quickjs.c
@@ -19317,7 +19317,7 @@ static int js_async_generator_completed_return(JSContext *ctx,
     // exception should be delivered to the catch handler.
     if (JS_IsException(promise)) {
         JSValue err = JS_GetException(ctx);
-        promise = js_promise_resolve(ctx, ctx->promise_ctor, 1, &err,
+        promise = js_promise_resolve(ctx, ctx->promise_ctor, 1, (JSValueConst *)&err,
                                      /*is_reject*/1);
         JS_FreeValue(ctx, err);
         if (JS_IsException(promise))
@@ -19370,7 +19370,6 @@ static void js_async_generator_resume_next(JSContext *ctx,
             } else if (next->completion_type == GEN_MAGIC_RETURN) {
                 s->state = JS_ASYNC_GENERATOR_STATE_AWAITING_RETURN;
                 js_async_generator_completed_return(ctx, s, next->result);
-                goto done;
             } else {
                 js_async_generator_reject(ctx, s, next->result);
             }
@@ -19401,7 +19400,7 @@ static void js_async_generator_resume_next(JSContext *ctx,
                 js_async_generator_reject(ctx, s, value);
                 JS_FreeValue(ctx, value);
             } else if (JS_VALUE_GET_TAG(func_ret) == JS_TAG_INT) {
-                int func_ret_code;
+                int func_ret_code, ret;
                 value = s->func_state.frame.cur_sp[-1];
                 s->func_state.frame.cur_sp[-1] = JS_UNDEFINED;
                 func_ret_code = JS_VALUE_GET_INT(func_ret);
@@ -19416,8 +19415,13 @@ static void js_async_generator_resume_next(JSContext *ctx,
                     JS_FreeValue(ctx, value);
                     break;
                 case FUNC_RET_AWAIT:
-                    js_async_generator_await(ctx, s, value);
+                    ret = js_async_generator_await(ctx, s, value);
                     JS_FreeValue(ctx, value);
+                    if (ret < 0) {
+                        /* exception: throw it */
+                        s->func_state.throw_flag = TRUE;
+                        goto resume_exec;
+                    }
                     goto done;
                 default:
                     abort();
@@ -25571,6 +25575,18 @@ static void emit_return(JSParseState *s, BOOL hasval)
     BlockEnv *top;
     int drop_count;
 
+    if (s->cur_func->func_kind != JS_FUNC_NORMAL) {
+        if (!hasval) {
+            /* no value: direct return in case of async generator */
+            emit_op(s, OP_undefined);
+            hasval = TRUE;
+        } else if (s->cur_func->func_kind == JS_FUNC_ASYNC_GENERATOR) {
+            /* the await must be done before handling the "finally" in
+               case it raises an exception */
+            emit_op(s, OP_await);
+        }
+    }
+    
     drop_count = 0;
     top = s->cur_func->top_break;
     while (top != NULL) {
@@ -25649,11 +25665,6 @@ static void emit_return(JSParseState *s, BOOL hasval)
         emit_label(s, label_return);
         emit_op(s, OP_return);
     } else if (s->cur_func->func_kind != JS_FUNC_NORMAL) {
-        if (!hasval) {
-            emit_op(s, OP_undefined);
-        } else if (s->cur_func->func_kind == JS_FUNC_ASYNC_GENERATOR) {
-            emit_op(s, OP_await);
-        }
         emit_op(s, OP_return_async);
     } else {
         emit_op(s, hasval ? OP_return : OP_return_undef);