Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ option(AVM_RELEASE "Build an AtomVM release" OFF)
option(AVM_CREATE_STACKTRACES "Create stacktraces" ON)
option(AVM_BUILD_RUNTIME_ONLY "Only build the AtomVM runtime" OFF)
option(COVERAGE "Build for code coverage" OFF)
option(AVM_USE_WASM_MJS "Use ES modules for Emscripten platform" OFF)
option(AVM_PRINT_PROCESS_CRASH_DUMPS "Print crash reports when processes die with non-standard reasons" ON)

# JIT & execution of precompiled code
Expand Down
8 changes: 6 additions & 2 deletions src/platforms/emscripten/src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,12 @@ add_subdirectory(../../../libAtomVM libAtomVM)
target_link_libraries(AtomVM PUBLIC libAtomVM)
target_compile_options(libAtomVM PUBLIC -O3 -fno-exceptions -fno-rtti -pthread -sINLINING_LIMIT -sUSE_ZLIB=1)
target_compile_definitions(libAtomVM PRIVATE WITH_ZLIB)
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)
set(CMAKE_EXECUTABLE_SUFFIX ".mjs")
else()
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)
endif()
if (CMAKE_BUILD_TYPE STREQUAL "Debug")
target_link_options(AtomVM PRIVATE -sASSERTIONS=2 -sSAFE_HEAP -sSTACK_OVERFLOW_CHECK)
endif()
Expand Down
60 changes: 55 additions & 5 deletions src/platforms/emscripten/src/atomvm.pre.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,60 @@
*
* SPDX-License-Identifier: Apache-2.0 OR LGPL-2.1-or-later
*/
Module['cast'] = function(name, message) {
ccall("cast", 'void', ['string', 'string'], [name, message]);
Module["cast"] = function (name, message) {
ccall("cast", "void", ["string", "string"], [name, message]);
};
Module['call'] = async function(name, message) {
const promiseId = ccall("call", 'integer', ['string', 'string'], [name, message]);
return promiseMap.get(promiseId).promise;
Module["call"] = async function (name, message) {
const promiseId = ccall(
"call",
"integer",
["string", "string"],
[name, message],
);
return promiseMap.get(promiseId).promise;
};

// experimental API
Module["nextTrackedObjectKey"] = function () {
return ccall("next_tracked_object_key", "integer", [], []);
};
Module["trackedObjectsMap"] = new Map();
Module["onTrackedObjectDelete"] = (key) => {
Module["trackedObjectsMap"].delete(key);
};
Module["onGetTrackedObjects"] = (keys) => {
const getTrackedObject = (key) => Module["trackedObjectsMap"].get(key);
return keys.map(getTrackedObject);
};
Module["onRunTrackedJs"] = (scriptString, isDebug) => {
const trackValue = (value) => {
const key = Module["nextTrackedObjectKey"]();
Module["trackedObjectsMap"].set(key, value);
return key;
};

let result;
try {
const indirectEval = eval;
result = indirectEval(scriptString);
} catch (_e) {
return null;
}
isDebug && ensureValidResult(result);
return result?.map(trackValue) ?? [];
};

function ensureValidResult(result) {
const isIndex = (k) => typeof k === "number";

if (result === null) {
return;
}
if (Array.isArray(result) && keys.every(isIndex)) {
return;
}

const message =
"Evaluated script returned invalid value. Expected number array or null";
throw new Error(message);
}
2 changes: 2 additions & 0 deletions src/platforms/emscripten/src/lib/emscripten_sys.h
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ struct EmscriptenPlatformData
pthread_mutex_t poll_mutex;
pthread_cond_t poll_cond;
struct ListHead messages;
atomic_size_t next_tracked_object_key;
ErlNifResourceType *promise_resource_type;
ErlNifResourceType *htmlevent_user_data_resource_type;
ErlNifResourceType *websocket_resource_type;
Expand All @@ -134,6 +135,7 @@ void sys_enqueue_emscripten_cast_message(GlobalContext *glb, const char *target,
em_promise_t sys_enqueue_emscripten_call_message(GlobalContext *glb, const char *target, const char *message);
void sys_enqueue_emscripten_htmlevent_message(GlobalContext *glb, int32_t target_pid, term message, term user_data, HeapFragment *heap);
void sys_enqueue_emscripten_unregister_htmlevent_message(GlobalContext *glb, struct HTMLEventUserDataResource *rsrc);
size_t sys_get_next_tracked_object_key(GlobalContext *glb);
void sys_promise_resolve_int_and_destroy(em_promise_t promise, em_promise_result_t result, int value);
void sys_promise_resolve_str_and_destroy(em_promise_t promise, em_promise_result_t result, int value);

Expand Down
1 change: 1 addition & 0 deletions src/platforms/emscripten/src/lib/platform_defaultatoms.def
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,4 @@ X(WEBSOCKET_ATOM, "\x9", "websocket")
X(WEBSOCKET_OPEN_ATOM, "\xE", "websocket_open")
X(WEBSOCKET_CLOSE_ATOM, "\xF", "websocket_close")
X(WEBSOCKET_ERROR_ATOM, "\xF", "websocket_error")
X(BADVALUE_ATOM, "\x8", "badvalue")
Loading
Loading