-
Notifications
You must be signed in to change notification settings - Fork 135
Experimental JS API based on tracking values #2013
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
Signed-off-by: Jakub Gonet <jakub.gonet@swmansion.com>
Signed-off-by: Jakub Gonet <jakub.gonet@swmansion.com>
It's a field in emscripten platform struct. It could be a callback entirely in JS but we use threads. Threads are emulated via webworkers which have their own contexts and variables aren't shared with each other. This means that we would lose uniqueness of the keys. This commit also changes output format from file loaded and ran at <script src=...> to ES6 classes which have greater control over initialization of Wasm. Signed-off-by: Jakub Gonet <jakub.gonet@swmansion.com>
Signed-off-by: Jakub Gonet <jakub.gonet@swmansion.com>
Signed-off-by: Jakub Gonet <jakub.gonet@swmansion.com>
|
cc @pguyot |
bettio
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added just some minor comments.
I'm not the emscripten expert here, however it would be good (and useful) having some documentation in emscripten module (and where it makes sense) about how this is supposed to be used. Some additional documentation would be super appreciated during review.
| term result = term_invalid_term(); | ||
| term refs = term_nil(); | ||
| if (UNLIKELY(memory_ensure_free_opt(target_ctx, TUPLE_SIZE(2) + LIST_SIZE(keys_n, TERM_BOXED_REFC_BINARY_SIZE), MEMORY_CAN_SHRINK) != MEMORY_GC_OK)) { | ||
| // TODO: how to raise? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this TODO still valid?
| free(keys); | ||
| mailbox_send_term_signal(target_ctx, TrapAnswerSignal, result); | ||
| globalcontext_get_process_unlock(global, target_ctx); | ||
| } else { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
style: you can either remove this } else { and just free() at the end of function, or even do an early return when target_ctx == NULL. Maybe the second option is more readable.
| }); | ||
| // clang-format on | ||
|
|
||
| static void do_get_tracked_objects(uint32_t *ref_keys, size_t keys_n, int32_t sync_caller_pid, GlobalContext *global) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right now we are using uint32_t for process ids. Also we are using the extended process_id name instead of pid when talking about the id itself (not encoded as a term having type pid).
| }); | ||
| // clang-format on | ||
|
|
||
| static void do_run_script_tracked(const char *script, int32_t sync_caller_pid, GlobalContext *global) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right now we are using uint32_t for process ids. Also we are using the extended process_id name instead of pid when talking about the id itself (not encoded as a term having type pid).
| target_link_options(AtomVM PRIVATE -sEXPORTED_RUNTIME_METHODS=ccall -sUSE_ZLIB=1 -O3 -pthread -sFETCH -lwebsocket.js --pre-js ${CMAKE_CURRENT_SOURCE_DIR}/atomvm.pre.js) | ||
|
|
||
| if (AVM_USE_WASM_MJS) | ||
| target_link_options(AtomVM PRIVATE -sEXPORTED_RUNTIME_METHODS=ccall,cwrap,stringToNewUTF8 -sEMULATE_FUNCTION_POINTER_CASTS=1 -sEXPORTED_FUNCTIONS=_malloc,_cast,_call,_next_tracked_object_key,_main -sEXPORT_ES6=1 -sUSE_ZLIB=1 -O3 -pthread -sFETCH -lwebsocket.js --pre-js ${CMAKE_CURRENT_SOURCE_DIR}/atomvm.pre.js) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
-O3 if a pretty aggressive optimization option. Do we really want to hardcode it?
| { | ||
| static const uint8_t OK = 0; | ||
| static const uint8_t BAD_KEY = 1; | ||
| static const uint8_t NOT_STRING = 2; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't we define an enum here?
| if (strcmp("run_script/2", nifname) == 0) { | ||
| return &emscripten_run_script_nif; | ||
| } | ||
| if (strcmp("run_script_tracked/1", nifname) == 0) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
They should be added to emscripten module: libs/eavmlib/src/emscripten.erl
typespecs and documentation about how they should be used is appreciated.
This PR upstreams API we're using in Popcorn.
It doesn't have tests or extended docs. I'd gladly take some instructions about testing Wasm. Docs will be added after first round of review – I need to know if approach is sane at all.
Design notes
We needed some API to track values in JS with their lifetime in the VM. This was achieved by using new type of resource –
TrackedValue. Popcorn also wants to customize JS behavior without maintaining custom Emscripten hooks in.cfiles – we extracted them to functions inatomvm.pre.js. You can see our implementation in Popcorn repo.We also need JS to have access to DOM. We hardcoded thread executing JS to be main thread (or in our case, iframe thread).
We were thinking about relaxing that constraint but it'd need
js_tracked_evalto forward script to it's destination JS context (e.g.postMessage()to iframe).js_get_tracked_objectsworks by batchingTrackedObjects and their status (missing, bad type, etc). This allows to reduce communication overhead between JS and Wasm.We also needed to use ES modules instead of current, IIFE format. It makes it easier to load in iframes and to use in modern JS projects.
These changes are made under both the "Apache 2.0" and the "GNU Lesser General
Public License 2.1 or later" license terms (dual license).
SPDX-License-Identifier: Apache-2.0 OR LGPL-2.1-or-later