added js_std_await() and use it to wait for the evaluation of a module (github issue #219)

This commit is contained in:
Fabrice Bellard 2024-01-19 10:19:58 +01:00
parent d6c7d169de
commit 84058766e9
3 changed files with 47 additions and 7 deletions

1
qjs.c
View file

@ -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); js_module_set_import_meta(ctx, val, TRUE, TRUE);
val = JS_EvalFunction(ctx, val); val = JS_EvalFunction(ctx, val);
} }
val = js_std_await(ctx, val);
} else { } else {
val = JS_Eval(ctx, buf, buf_len, filename, eval_flags); val = JS_Eval(ctx, buf, buf_len, filename, eval_flags);
} }

View file

@ -3339,7 +3339,7 @@ static void *worker_func(void *opaque)
JSRuntime *rt; JSRuntime *rt;
JSThreadState *ts; JSThreadState *ts;
JSContext *ctx; JSContext *ctx;
JSValue promise; JSValue val;
rt = JS_NewRuntime(); rt = JS_NewRuntime();
if (rt == NULL) { if (rt == NULL) {
@ -3366,14 +3366,14 @@ static void *worker_func(void *opaque)
js_std_add_helpers(ctx, -1, NULL); js_std_add_helpers(ctx, -1, NULL);
promise = JS_LoadModule(ctx, args->basename, args->filename); val = JS_LoadModule(ctx, args->basename, args->filename);
if (JS_IsException(promise))
js_std_dump_error(ctx);
/* XXX: check */
JS_FreeValue(ctx, promise);
free(args->filename); free(args->filename);
free(args->basename); free(args->basename);
free(args); 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); 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, void js_std_eval_binary(JSContext *ctx, const uint8_t *buf, size_t buf_len,
int load_only) int load_only)
{ {
@ -3987,8 +4022,11 @@ void js_std_eval_binary(JSContext *ctx, const uint8_t *buf, size_t buf_len,
goto exception; goto exception;
} }
js_module_set_import_meta(ctx, obj, FALSE, TRUE); 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)) { if (JS_IsException(val)) {
exception: exception:
js_std_dump_error(ctx); js_std_dump_error(ctx);

View file

@ -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); 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_add_helpers(JSContext *ctx, int argc, char **argv);
void js_std_loop(JSContext *ctx); void js_std_loop(JSContext *ctx);
JSValue js_std_await(JSContext *ctx, JSValue obj);
void js_std_init_handlers(JSRuntime *rt); void js_std_init_handlers(JSRuntime *rt);
void js_std_free_handlers(JSRuntime *rt); void js_std_free_handlers(JSRuntime *rt);
void js_std_dump_error(JSContext *ctx); void js_std_dump_error(JSContext *ctx);