From e368fb9e54ac096d5a260ff8a2690e7f3e67a9ca Mon Sep 17 00:00:00 2001 From: Paul Guyot Date: Wed, 15 Apr 2026 22:43:30 +0200 Subject: [PATCH] Use EXPORT_ES6 setting and .mjs suffix Signed-off-by: Paul Guyot --- .github/workflows/wasm-build.yaml | 38 +++++++++---------- CHANGELOG.md | 1 + UPDATING.md | 7 ++++ doc/src/build-instructions.md | 6 +-- doc/src/getting-started-guide.md | 10 ++--- examples/emscripten/call_cast.html | 9 +++-- examples/emscripten/echo_websocket.html | 9 +++-- examples/emscripten/hello_world_avm.html | 9 +++-- examples/emscripten/hello_world_beam.html | 9 +++-- examples/emscripten/html5_events.html | 9 +++-- examples/emscripten/run_script.html | 9 +++-- examples/emscripten/wasm_webserver.erl | 7 ++-- src/platforms/emscripten/src/CMakeLists.txt | 10 +++-- .../emscripten/src/atomvm.extern-post.js | 27 +++++++++++++ .../emscripten/tests/src/test_atomvm.html | 9 +++-- .../emscripten/tests/src/test_call.html | 9 +++-- .../emscripten/tests/src/test_html5.html | 9 +++-- .../emscripten/tests/src/test_websockets.html | 13 ++++--- 18 files changed, 124 insertions(+), 76 deletions(-) create mode 100644 src/platforms/emscripten/src/atomvm.extern-post.js diff --git a/.github/workflows/wasm-build.yaml b/.github/workflows/wasm-build.yaml index f22c028416..cdc3f7eeec 100644 --- a/.github/workflows/wasm-build.yaml +++ b/.github/workflows/wasm-build.yaml @@ -187,14 +187,14 @@ jobs: run: | set -euxo pipefail # Test compressed beams - node src/AtomVM.js ../../../../build/examples/erlang/hello_world.beam ../../../../build/libs/eavmlib/src/eavmlib.avm + node src/AtomVM.mjs ../../../../build/examples/erlang/hello_world.beam ../../../../build/libs/eavmlib/src/eavmlib.avm # Run tests that pass - node src/AtomVM.js ../../../../build/tests/libs/alisp/test_alisp.avm - node src/AtomVM.js ../../../../build/tests/libs/estdlib/test_estdlib.avm + node src/AtomVM.mjs ../../../../build/tests/libs/alisp/test_alisp.avm + node src/AtomVM.mjs ../../../../build/tests/libs/estdlib/test_estdlib.avm # test_eavmlib does not work with wasm due to http + ssl test - # node src/AtomVM.js ../../../../build/tests/libs/eavmlib/test_eavmlib.avm - node src/AtomVM.js ../../../../build/tests/libs/etest/test_etest.avm - node src/AtomVM.js ../../../../build/tests/erlang_tests/test_crypto.beam + # node src/AtomVM.mjs ../../../../build/tests/libs/eavmlib/test_eavmlib.avm + node src/AtomVM.mjs ../../../../build/tests/libs/etest/test_etest.avm + node src/AtomVM.mjs ../../../../build/tests/erlang_tests/test_crypto.beam - name: Test (JIT) if: matrix.jit != '' @@ -203,19 +203,19 @@ jobs: run: | set -euxo pipefail # Test hello_world with JIT compiler (runtime JIT compilation) - node src/AtomVM.js ../../../../build/examples/erlang/hello_world.beam ../../../../build/libs/atomvmlib-emscripten-wasm32.avm + node src/AtomVM.mjs ../../../../build/examples/erlang/hello_world.beam ../../../../build/libs/atomvmlib-emscripten-wasm32.avm # Library tests with JIT compiler (jit-wasm32.avm included in test avms via pack_test) - node src/AtomVM.js ../../../../build/tests/libs/alisp/test_alisp.avm - node src/AtomVM.js ../../../../build/tests/libs/estdlib/test_estdlib.avm - node src/AtomVM.js ../../../../build/tests/libs/etest/test_etest.avm + node src/AtomVM.mjs ../../../../build/tests/libs/alisp/test_alisp.avm + node src/AtomVM.mjs ../../../../build/tests/libs/estdlib/test_estdlib.avm + node src/AtomVM.mjs ../../../../build/tests/libs/etest/test_etest.avm - name: "Rename and write sha256sum (node)" if: startsWith(github.ref, 'refs/tags/') && matrix.jit == '' shell: bash working-directory: src/platforms/emscripten/build/src run: | - ATOMVM_JS=AtomVM-node-${{ github.ref_name }}.js - mv AtomVM.js "${ATOMVM_JS}" + ATOMVM_JS=AtomVM-node-${{ github.ref_name }}.mjs + mv AtomVM.mjs "${ATOMVM_JS}" sha256sum "${ATOMVM_JS}" > "${ATOMVM_JS}.sha256" ATOMVM_WASM=AtomVM-node-${{ github.ref_name }}.wasm mv AtomVM.wasm "${ATOMVM_WASM}" @@ -228,8 +228,8 @@ jobs: draft: true fail_on_unmatched_files: true files: | - src/platforms/emscripten/build/src/AtomVM-node-${{ github.ref_name }}.js - src/platforms/emscripten/build/src/AtomVM-node-${{ github.ref_name }}.js.sha256 + src/platforms/emscripten/build/src/AtomVM-node-${{ github.ref_name }}.mjs + src/platforms/emscripten/build/src/AtomVM-node-${{ github.ref_name }}.mjs.sha256 src/platforms/emscripten/build/src/AtomVM-node-${{ github.ref_name }}.wasm src/platforms/emscripten/build/src/AtomVM-node-${{ github.ref_name }}.wasm.sha256 @@ -283,7 +283,7 @@ jobs: name: atomvm-js-web path: | src/platforms/emscripten/build/**/*.wasm - src/platforms/emscripten/build/**/*.js + src/platforms/emscripten/build/**/*.mjs retention-days: 1 wasm_test_web: @@ -341,8 +341,8 @@ jobs: shell: bash working-directory: src/platforms/emscripten/build/src run: | - ATOMVM_JS=AtomVM-web-${{ github.ref_name }}.js - mv AtomVM.js "${ATOMVM_JS}" + ATOMVM_JS=AtomVM-web-${{ github.ref_name }}.mjs + mv AtomVM.mjs "${ATOMVM_JS}" sha256sum "${ATOMVM_JS}" > "${ATOMVM_JS}.sha256" ATOMVM_WASM=AtomVM-web-${{ github.ref_name }}.wasm mv AtomVM.wasm "${ATOMVM_WASM}" @@ -355,7 +355,7 @@ jobs: draft: true fail_on_unmatched_files: true files: | - src/platforms/emscripten/build/src/AtomVM-web-${{ github.ref_name }}.js - src/platforms/emscripten/build/src/AtomVM-web-${{ github.ref_name }}.js.sha256 + src/platforms/emscripten/build/src/AtomVM-web-${{ github.ref_name }}.mjs + src/platforms/emscripten/build/src/AtomVM-web-${{ github.ref_name }}.mjs.sha256 src/platforms/emscripten/build/src/AtomVM-web-${{ github.ref_name }}.wasm src/platforms/emscripten/build/src/AtomVM-web-${{ github.ref_name }}.wasm.sha256 diff --git a/CHANGELOG.md b/CHANGELOG.md index 0dfd0fe41b..025139af90 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed - Updated network type db() to dbm() to reflect the actual representation of the type +- Use ES6 modules for emscripten port, using .mjs suffix ### Fixed - Stop using deprecated `term_from_int32` on STM32 platform diff --git a/UPDATING.md b/UPDATING.md index 5865e7a703..b32e4a61c6 100644 --- a/UPDATING.md +++ b/UPDATING.md @@ -35,6 +35,13 @@ standard Erlang/OTP API, that takes maps instead of proplists. The `main.avm` offset is now `0x250000` for all images (previously `0x210000` for Erlang-only). Update flashing offsets in your tooling, build scripts, and `mix.exs` or `rebar.config` if you were using the `0x210000` offset. +- The emscripten port now uses ES6 modules (`.mjs` suffix). This is a breaking change for + existing web integrations: + * Replace `` with a module script + * Use ` - diff --git a/examples/emscripten/echo_websocket.html b/examples/emscripten/echo_websocket.html index 6e12c7f361..2c46d2d49b 100644 --- a/examples/emscripten/echo_websocket.html +++ b/examples/emscripten/echo_websocket.html @@ -76,13 +76,14 @@

Echo websocket example

- - diff --git a/examples/emscripten/hello_world_avm.html b/examples/emscripten/hello_world_avm.html index 582810c50f..a371505ee4 100644 --- a/examples/emscripten/hello_world_avm.html +++ b/examples/emscripten/hello_world_avm.html @@ -26,13 +26,14 @@

Hello world (AVM version)

Please check the console for hello_world output.

- - diff --git a/examples/emscripten/hello_world_beam.html b/examples/emscripten/hello_world_beam.html index 1f17afe83f..aabef1b853 100644 --- a/examples/emscripten/hello_world_beam.html +++ b/examples/emscripten/hello_world_beam.html @@ -30,16 +30,17 @@

Hello world (Beam version)

in arguments, typically loading AtomVM library as a packed avm file.

Please check the console for hello_world output.

- - diff --git a/examples/emscripten/html5_events.html b/examples/emscripten/html5_events.html index 3b16b6abc4..960c145e4a 100644 --- a/examples/emscripten/html5_events.html +++ b/examples/emscripten/html5_events.html @@ -144,13 +144,14 @@

Event log

- - diff --git a/examples/emscripten/run_script.html b/examples/emscripten/run_script.html index 83b23e1e4e..c2e3b64c47 100644 --- a/examples/emscripten/run_script.html +++ b/examples/emscripten/run_script.html @@ -50,13 +50,14 @@

Run script example

the main thread) using JS function.

- - diff --git a/examples/emscripten/wasm_webserver.erl b/examples/emscripten/wasm_webserver.erl index 8ce2b2eb5f..65356b89c2 100644 --- a/examples/emscripten/wasm_webserver.erl +++ b/examples/emscripten/wasm_webserver.erl @@ -40,12 +40,10 @@ handle_req(Method, Path, Conn) when Method =:= "GET" orelse Method =:= "HEAD" -> case Path of [] -> "../examples/emscripten/index.html"; - ["AtomVM.js"] -> - "../src/platforms/emscripten/build/src/AtomVM.js"; + ["AtomVM.mjs"] -> + "../src/platforms/emscripten/build/src/AtomVM.mjs"; ["AtomVM.wasm"] -> "../src/platforms/emscripten/build/src/AtomVM.wasm"; - ["AtomVM.worker.js"] -> - "../src/platforms/emscripten/build/src/AtomVM.worker.js"; ["tests", "build" | Tail] -> lists:flatten([ "../src/platforms/emscripten/build/tests/src/" | lists:join($/, Tail) @@ -60,6 +58,7 @@ handle_req(Method, Path, Conn) when Method =:= "GET" orelse Method =:= "HEAD" -> MimeType = case lists:reverse(Filename) of "sj." ++ _ -> "text/javascript"; + "sjm." ++ _ -> "text/javascript"; "lmth." ++ _ -> "text/html"; "msaw." ++ _ -> "application/wasm"; "mva." ++ _ -> "application/binary"; diff --git a/src/platforms/emscripten/src/CMakeLists.txt b/src/platforms/emscripten/src/CMakeLists.txt index ed371dc235..f5372b0c00 100644 --- a/src/platforms/emscripten/src/CMakeLists.txt +++ b/src/platforms/emscripten/src/CMakeLists.txt @@ -21,6 +21,7 @@ cmake_minimum_required (VERSION 3.13) add_executable(AtomVM main.c) +set_target_properties(AtomVM PROPERTIES SUFFIX ".mjs") target_compile_features(AtomVM PUBLIC c_std_11) @@ -30,11 +31,14 @@ target_compile_options(libAtomVM PUBLIC -O3 -fno-exceptions -fno-rtti -pthread - target_compile_definitions(libAtomVM PRIVATE WITH_ZLIB) if (NOT AVM_DISABLE_JIT) # JIT requires addFunction to register dynamically compiled WASM functions - set(JIT_LINK_FLAGS -sALLOW_TABLE_GROWTH -sEXPORTED_RUNTIME_METHODS=ccall,addFunction) + set(JIT_LINK_FLAGS + -sALLOW_TABLE_GROWTH + "-sEXPORTED_RUNTIME_METHODS=['ccall','addFunction','ENV']" + ) else() - set(JIT_LINK_FLAGS -sEXPORTED_RUNTIME_METHODS=ccall) + set(JIT_LINK_FLAGS "-sEXPORTED_RUNTIME_METHODS=['ccall','ENV']") endif() -target_link_options(AtomVM PRIVATE ${JIT_LINK_FLAGS} -sUSE_ZLIB=1 -O3 -pthread -sFETCH -lwebsocket.js --pre-js ${CMAKE_CURRENT_SOURCE_DIR}/atomvm.pre.js -sINITIAL_MEMORY=67108864 -sALLOW_MEMORY_GROWTH) +target_link_options(AtomVM PRIVATE ${JIT_LINK_FLAGS} -sEXPORT_ES6 -sUSE_ZLIB=1 -O3 -pthread -sFETCH -lwebsocket.js --pre-js ${CMAKE_CURRENT_SOURCE_DIR}/atomvm.pre.js --extern-post-js ${CMAKE_CURRENT_SOURCE_DIR}/atomvm.extern-post.js -sINITIAL_MEMORY=67108864 -sALLOW_MEMORY_GROWTH) if (CMAKE_BUILD_TYPE STREQUAL "Debug") target_link_options(AtomVM PRIVATE -sASSERTIONS=2 -sSAFE_HEAP -sSTACK_OVERFLOW_CHECK) diff --git a/src/platforms/emscripten/src/atomvm.extern-post.js b/src/platforms/emscripten/src/atomvm.extern-post.js new file mode 100644 index 0000000000..ba7a9301dd --- /dev/null +++ b/src/platforms/emscripten/src/atomvm.extern-post.js @@ -0,0 +1,27 @@ +/* + * This file is part of AtomVM. + * + * Copyright 2026 Paul Guyot + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 OR LGPL-2.1-or-later + */ +if (typeof process === "object" && process.versions?.node && process.argv[1]) { + const { pathToFileURL } = await import("url"); + const { realpathSync } = await import("fs"); + + if (import.meta.url === pathToFileURL(realpathSync(process.argv[1])).href) { + await Module(); + } +} diff --git a/src/platforms/emscripten/tests/src/test_atomvm.html b/src/platforms/emscripten/tests/src/test_atomvm.html index cde06286ff..6c251b92af 100644 --- a/src/platforms/emscripten/tests/src/test_atomvm.html +++ b/src/platforms/emscripten/tests/src/test_atomvm.html @@ -27,19 +27,20 @@
- - diff --git a/src/platforms/emscripten/tests/src/test_call.html b/src/platforms/emscripten/tests/src/test_call.html index 59ae9db66d..1609a9ab4b 100644 --- a/src/platforms/emscripten/tests/src/test_call.html +++ b/src/platforms/emscripten/tests/src/test_call.html @@ -28,14 +28,15 @@
- - diff --git a/src/platforms/emscripten/tests/src/test_html5.html b/src/platforms/emscripten/tests/src/test_html5.html index 9b7ed24166..452bb4eaf6 100644 --- a/src/platforms/emscripten/tests/src/test_html5.html +++ b/src/platforms/emscripten/tests/src/test_html5.html @@ -29,14 +29,15 @@
- - diff --git a/src/platforms/emscripten/tests/src/test_websockets.html b/src/platforms/emscripten/tests/src/test_websockets.html index c8853b4d3a..4c86f18e7e 100644 --- a/src/platforms/emscripten/tests/src/test_websockets.html +++ b/src/platforms/emscripten/tests/src/test_websockets.html @@ -24,7 +24,9 @@
N/A
- -