quickjs-tart

quickjs-based runtime for wallet-core logic
Log | Files | Refs | README | LICENSE

commit 768581e2b9e1a0ecba783ca9988d28029b299584
parent a9d2a10f9dfc2cacf17e574928e6b851e084beef
Author: Florian Dold <florian@dold.me>
Date:   Tue,  3 Jan 2023 00:18:26 +0100

wip

Diffstat:
Mquickjs/quickjs-libc.c | 57+++++++++++++++++++++++++++++++++++++++++++++++++++++++--
Mquickjs/quickjs.c | 11+++++++++--
Mtaler_wallet_core_lib.c | 43++++++++++++++++++++++++-------------------
Mwallet-client-example.c | 5++++-
4 files changed, 92 insertions(+), 24 deletions(-)

diff --git a/quickjs/quickjs-libc.c b/quickjs/quickjs-libc.c @@ -39,6 +39,7 @@ #include <limits.h> #include <sys/stat.h> #include <dirent.h> +#include <string.h> #if defined(_WIN32) #include <windows.h> #include <conio.h> @@ -476,6 +477,55 @@ static JSValue js_std_loadFile(JSContext *ctx, JSValueConst this_val, return ret; } +static JSValue js_std_writeFile(JSContext *ctx, JSValueConst this_val, + int argc, JSValueConst *argv) +{ + const char *filename_buf = NULL; + const char *data_buf = NULL; + size_t data_len; + FILE *file = NULL; + size_t bytes_written = 0; + JSValue ret = JS_UNDEFINED; + + filename_buf = JS_ToCString(ctx, argv[0]); + if (!filename_buf) { + ret = JS_EXCEPTION; + goto done; + } + + data_buf = JS_ToCStringLen(ctx, &data_len, argv[1]); + if (!data_buf) { + ret = JS_EXCEPTION; + goto done; + } + file = fopen(filename_buf, "w"); + if (!file) { + ret = JS_ThrowReferenceError(ctx, "could not open '%s'", filename_buf); + goto done; + } + + while (bytes_written < data_len) { + size_t sret; + sret = fwrite(data_buf + bytes_written, data_len - bytes_written, 1, file); + if (0 == sret) { + break; + } + bytes_written += sret; + } + + if (bytes_written != data_len) { + JS_ThrowReferenceError(ctx, "could not write all bytes"); + goto done; + } +done: + JS_FreeCString(ctx, filename_buf); + JS_FreeCString(ctx, data_buf); + if (file) { + fclose(file); + } + return ret; +} + typedef JSModuleDef *(JSInitModuleFunc)(JSContext *ctx, const char *module_name); @@ -1518,6 +1568,7 @@ static const JSCFunctionListEntry js_std_funcs[] = { JS_CFUNC_DEF("getenviron", 1, js_std_getenviron ), JS_CFUNC_DEF("urlGet", 1, js_std_urlGet ), JS_CFUNC_DEF("loadFile", 1, js_std_loadFile ), + JS_CFUNC_DEF("writeFile", 2, js_std_writeFile ), JS_CFUNC_DEF("strerror", 1, js_std_strerror ), JS_CFUNC_DEF("parseExtJSON", 1, js_std_parseExtJSON ), @@ -2587,7 +2638,7 @@ static int js_os_poll(JSContext *ctx) } if (list_empty(&ts->os_rw_handlers) && list_empty(&ts->os_timers) && - list_empty(&ts->port_list)) + list_empty(&ts->port_list) && JS_IsNull(ts->on_host_message_func)) return -1; /* no more events */ if (!list_empty(&ts->os_timers)) { @@ -4405,8 +4456,10 @@ void js_std_loop(JSContext *ctx) } } - if (!os_poll_func || os_poll_func(ctx)) + if (!os_poll_func || os_poll_func(ctx)) { + fprintf(stderr, "nothing more to wait on\n"); break; + } } } diff --git a/quickjs/quickjs.c b/quickjs/quickjs.c @@ -33799,8 +33799,9 @@ static JSValue __JS_EvalInternal(JSContext *ctx, JSValueConst this_obj, } } fd = js_new_function_def(ctx, NULL, TRUE, FALSE, filename, 1); - if (!fd) + if (!fd) { goto fail1; + } s->cur_func = fd; fd->eval_type = eval_type; fd->has_this_binding = (eval_type != JS_EVAL_TYPE_DIRECT); @@ -33819,8 +33820,10 @@ static JSValue __JS_EvalInternal(JSContext *ctx, JSValueConst this_obj, fd->js_mode = js_mode; fd->func_name = JS_DupAtom(ctx, JS_ATOM__eval_); if (b) { - if (add_closure_variables(ctx, fd, b, scope_idx)) + if (add_closure_variables(ctx, fd, b, scope_idx)) { + fprintf(stderr, "unable to add closure variables\n"); goto fail; + } } fd->module = m; s->is_module = (m != NULL); @@ -33831,12 +33834,16 @@ static JSValue __JS_EvalInternal(JSContext *ctx, JSValueConst this_obj, err = js_parse_program(s); if (err) { + fprintf(stderr, "unable to parse program\n"); fail: + fprintf(stderr, "fail in internal eval\n"); free_token(s, &s->token); js_free_function_def(ctx, fd); goto fail1; } + fprintf(stderr, "parsed program\n"); + /* create the function object and all the enclosed functions */ fun_obj = js_create_function(ctx, fd); if (JS_IsException(fun_obj)) diff --git a/taler_wallet_core_lib.c b/taler_wallet_core_lib.c @@ -35,16 +35,18 @@ struct HostMessage { char *data; }; -struct TALER_WALLET_Handle { - char *test; +struct TALER_WALLET_Handle +{ + // Mutex that is locked while initializing the handle + pthread_mutex_t handle_mutex; - JSRuntime *rt; - JSContext *ctx; + JSRuntime *rt; + JSContext *ctx; - pthread_t wallet_thread; + pthread_t wallet_thread; - TALER_WALLET_MessageHandlerFn handler_f; - void *handler_cls; + TALER_WALLET_MessageHandlerFn handler_f; + void *handler_cls; }; static int eval_buf(JSContext *ctx, const char *codestr, const char *filename) @@ -90,7 +92,10 @@ int TALER_WALLET_send_message (struct TALER_WALLET_Handle *h, const char *msg) { - return js_os_post_message_from_host(h->ctx, msg); + int ret; + pthread_mutex_lock(&h->handle_mutex); + pthread_mutex_unlock(&h->handle_mutex); + ret = js_os_post_message_from_host(h->ctx, msg); } static void @@ -109,9 +114,9 @@ TALER_WALLET_create(void) struct TALER_WALLET_Handle *wh; wh = malloc(sizeof (*wh)); memset(wh, 0, sizeof *wh); - wh->test = "foo"; - - wh->rt = JS_NewRuntime(); + if (0 != pthread_mutex_init(&wh->handle_mutex, NULL)) { + abort(); + } return wh; } @@ -121,7 +126,7 @@ run(void *cls) { struct TALER_WALLET_Handle *wh = cls; - printf("TEST: %s\n", wh->test); + wh->rt = JS_NewRuntime(); js_std_init_handlers(wh->rt); wh->ctx = JS_NewCustomContext(wh->rt); @@ -129,10 +134,10 @@ run(void *cls) if (!wh->ctx) { fprintf(stderr, "qjs: cannot allocate JS context\n"); + pthread_mutex_unlock(&wh->handle_mutex); return NULL; } - eval_buf(wh->ctx, "console.log('hi');", "<talerwallet>"); JS_SetHostPromiseRejectionTracker(wh->rt, js_std_promise_rejection_tracker, NULL); @@ -144,12 +149,12 @@ run(void *cls) js_os_set_host_message_handler(wh->ctx, wallet_host_message_handler, wh); - printf("starting main loop\n"); + pthread_mutex_unlock(&wh->handle_mutex); - eval_buf(wh->ctx, "console.log('hi');", "<talerwallet>"); - eval_buf(wh->ctx, "console.log(typeof testWithLocal);", "<talerwallet>"); - eval_buf(wh->ctx, "console.log('hello, world, bla!');", "<talerwallet>"); - eval_buf(wh->ctx, "testWithLocal();", "<talerwallet>"); + eval_buf(wh->ctx, "installNativeWalletListener()", "<talerwalletcore>"); + //eval_buf(wh->ctx, "setTimeout(() => console.log('hehe'), 1000);", "<talerwalletcore>"); + + printf("starting main loop\n"); js_std_loop(wh->ctx); @@ -163,7 +168,7 @@ TALER_WALLET_run (struct TALER_WALLET_Handle *wh) char *line; size_t line_sz; - //run(wh); + pthread_mutex_lock(&wh->handle_mutex); pthread_create(&wallet_thread, NULL, run, wh); diff --git a/wallet-client-example.c b/wallet-client-example.c @@ -38,7 +38,10 @@ int main(int argc, char **argv) TALER_WALLET_run(wh); - //TALER_WALLET_send_message(wh, "{}"); + TALER_WALLET_send_message(wh, "{}"); + // Wait for wallet thread to finish. + // If we don't call this, main() exits + // and the wallet thread is killed. TALER_WALLET_join(wh); }