From 84058766e9f247cac7b00543feeb10f3bba8120a Mon Sep 17 00:00:00 2001 From: Fabrice Bellard Date: Fri, 19 Jan 2024 10:19:58 +0100 Subject: [PATCH] added js_std_await() and use it to wait for the evaluation of a module (github issue #219) --- qjs.c | 1 + quickjs-libc.c | 52 +++++++++++++++++++++++++++++++++++++++++++------- quickjs-libc.h | 1 + 3 files changed, 47 insertions(+), 7 deletions(-) diff --git a/qjs.c b/qjs.c index 77b5cfb..22d5f32 100644 --- a/qjs.c +++ b/qjs.c @@ -64,6 +64,7 @@ static int eval_buf(JSContext *ctx, const void *buf, int buf_len, js_module_set_import_meta(ctx, val, TRUE, TRUE); val = JS_EvalFunction(ctx, val); } + val = js_std_await(ctx, val); } else { val = JS_Eval(ctx, buf, buf_len, filename, eval_flags); } diff --git a/quickjs-libc.c b/quickjs-libc.c index d4f4d67..aa9e861 100644 --- a/quickjs-libc.c +++ b/quickjs-libc.c @@ -3339,7 +3339,7 @@ static void *worker_func(void *opaque) JSRuntime *rt; JSThreadState *ts; JSContext *ctx; - JSValue promise; + JSValue val; rt = JS_NewRuntime(); if (rt == NULL) { @@ -3366,14 +3366,14 @@ static void *worker_func(void *opaque) js_std_add_helpers(ctx, -1, NULL); - promise = JS_LoadModule(ctx, args->basename, args->filename); - if (JS_IsException(promise)) - js_std_dump_error(ctx); - /* XXX: check */ - JS_FreeValue(ctx, promise); + val = JS_LoadModule(ctx, args->basename, args->filename); free(args->filename); free(args->basename); free(args); + val = js_std_await(ctx, val); + if (JS_IsException(val)) + js_std_dump_error(ctx); + JS_FreeValue(ctx, val); js_std_loop(ctx); @@ -3969,6 +3969,41 @@ void js_std_loop(JSContext *ctx) } } +/* Wait for a promise and execute pending jobs while waiting for + it. Return the promise result or JS_EXCEPTION in case of promise + rejection. */ +JSValue js_std_await(JSContext *ctx, JSValue obj) +{ + JSValue ret; + int state; + + for(;;) { + state = JS_PromiseState(ctx, obj); + if (state == JS_PROMISE_FULFILLED) { + ret = JS_PromiseResult(ctx, obj); + JS_FreeValue(ctx, obj); + break; + } else if (state == JS_PROMISE_REJECTED) { + ret = JS_Throw(ctx, JS_PromiseResult(ctx, obj)); + JS_FreeValue(ctx, obj); + break; + } else if (state == JS_PROMISE_PENDING) { + JSContext *ctx1; + int err; + err = JS_ExecutePendingJob(JS_GetRuntime(ctx), &ctx1); + if (err < 0) { + js_std_dump_error(ctx1); + } + if (os_poll_func) + os_poll_func(ctx); + } else { + /* not a promise */ + ret = obj; + } + } + return ret; +} + void js_std_eval_binary(JSContext *ctx, const uint8_t *buf, size_t buf_len, int load_only) { @@ -3987,8 +4022,11 @@ void js_std_eval_binary(JSContext *ctx, const uint8_t *buf, size_t buf_len, goto exception; } js_module_set_import_meta(ctx, obj, FALSE, TRUE); + val = JS_EvalFunction(ctx, obj); + val = js_std_await(ctx, val); + } else { + val = JS_EvalFunction(ctx, obj); } - val = JS_EvalFunction(ctx, obj); if (JS_IsException(val)) { exception: js_std_dump_error(ctx); diff --git a/quickjs-libc.h b/quickjs-libc.h index fbbe5b0..1dfdf53 100644 --- a/quickjs-libc.h +++ b/quickjs-libc.h @@ -37,6 +37,7 @@ JSModuleDef *js_init_module_std(JSContext *ctx, const char *module_name); JSModuleDef *js_init_module_os(JSContext *ctx, const char *module_name); void js_std_add_helpers(JSContext *ctx, int argc, char **argv); void js_std_loop(JSContext *ctx); +JSValue js_std_await(JSContext *ctx, JSValue obj); void js_std_init_handlers(JSRuntime *rt); void js_std_free_handlers(JSRuntime *rt); void js_std_dump_error(JSContext *ctx);