Skip to content

Use EXPORT_ES6 setting and .mjs suffix#2273

Merged
bettio merged 1 commit intoatomvm:release-0.7from
pguyot:w16/mjs
Apr 21, 2026
Merged

Use EXPORT_ES6 setting and .mjs suffix#2273
bettio merged 1 commit intoatomvm:release-0.7from
pguyot:w16/mjs

Conversation

@pguyot
Copy link
Copy Markdown
Collaborator

@pguyot pguyot commented Apr 18, 2026

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

@petermm
Copy link
Copy Markdown
Contributor

petermm commented Apr 18, 2026

Amp - perhaps 6 and 7 which are docs but LGTM!

PR Review: Use EXPORT_ES6 setting and .mjs suffix

Commit: 88a7e95f47505f243253eb0c50b8c1c32423b459
Author: Paul Guyot
Files changed: 18


Summary

Migrates the AtomVM emscripten/WASM port from legacy CommonJS script loading to ES6 modules:

  • Adds -sEXPORT_ES6 linker flag, sets output suffix to .mjs
  • Converts all HTML examples/tests from <script async src="/AtomVM.js"> to <script type="module"> with import AtomVM from "/AtomVM.mjs" + await AtomVM({...})
  • Adds atomvm.extern-post.js for Node.js CLI auto-invocation
  • Exports ENV in EXPORTED_RUNTIME_METHODS for preRun callbacks
  • Removes AtomVM.worker.js route (no longer needed with ES6)
  • Updates CI, docs, CHANGELOG, UPDATING

Verdict: ✅ LGTM with minor suggestions

The core migration is correct. The EXPORT_ES6 flag produces a factory-function default export, and the import AtomVM from "/AtomVM.mjs"; await AtomVM({...}) pattern matches Emscripten's ES6 modularized output API. No stale .js references remain in the codebase.


Detailed Findings

1. ✅ ES6 Module Pattern — Correct

The Emscripten ES6 output's default export is a factory function. The pattern used across all HTML files:

import AtomVM from "/AtomVM.mjs";
window.Module = await AtomVM({ arguments: [...] });

is the correct browser-side instantiation pattern. Using window.Module is appropriate because existing examples use Module.cast()/Module.call() from JS snippets injected via emscripten:run_script.

2. ✅ ENV Export Addition — Correct

test_websockets.html sets module.ENV['ECHO_WEBSOCKET_URL'] inside a preRun callback. Adding 'ENV' to EXPORTED_RUNTIME_METHODS is required for this access pattern. The switch from the implicit global ENV to module.ENV is the correct ES6-aware approach.

3. ✅ No Stale References

Grep confirms zero remaining references to AtomVM.js or AtomVM.worker.js in the emscripten platform source, examples, tests, docs, and CI.

4. ✅ CI Workflow — Complete

All node src/AtomVM.js invocations updated to node src/AtomVM.mjs. Release artifact names updated from .js/.js.sha256 to .mjs/.mjs.sha256. Artifact upload glob updated.

5. ⚠️ atomvm.extern-post.js — Minor Robustness Issue

The main-module detection uses exact URL string comparison:

if (import.meta.url === pathToFileURL(process.argv[1]).href) {
    await Module();
}

This can break with symlinked paths. Suggested hardening:

--- a/src/platforms/emscripten/src/atomvm.extern-post.js
+++ b/src/platforms/emscripten/src/atomvm.extern-post.js
@@ -18,7 +18,8 @@
  */
 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(process.argv[1]).href) {
+  if (import.meta.url === pathToFileURL(realpathSync(process.argv[1])).href) {
     await Module();
   }
 }

6. ⚠️ UPDATING.md — Breaking Change Under-documented

Current text:

emscripten is now invoked with EXPORT_ES6 and generated scripts are ES6 modules with .mjs suffix

This doesn't give downstream users enough to migrate. Suggested expansion:

--- a/UPDATING.md
+++ b/UPDATING.md
@@ -37,1 +37,8 @@
 were using the `0x210000` offset.
-- emscripten is now invoked with EXPORT_ES6 and generated scripts are ES6 modules with .mjs suffix
+- The emscripten port now uses ES6 modules (`.mjs` suffix). This is a breaking change for
+  existing web integrations:
+  - Replace `<script async src="AtomVM.js"></script>` with a module script
+  - Use `<script type="module">` and `import AtomVM from "AtomVM.mjs"`
+  - Instantiate with `const module = await AtomVM({ arguments: [...] })`
+  - The old implicit global-script pattern is no longer supported
+  - `AtomVM.worker.js` is no longer emitted; only `AtomVM.mjs` and `AtomVM.wasm` are needed

7. ⚠️ build-instructions.md — Bare Invocation Example

The docs show node ./src/AtomVM.mjs with no arguments. With the new auto-run shim, this will just print an error. Consider adding an argument:

--- a/doc/src/build-instructions.md
+++ b/doc/src/build-instructions.md
@@ -1139,1 +1139,1 @@
-$ node ./src/AtomVM.mjs
+$ node ./src/AtomVM.mjs ../../../../build/examples/erlang/hello_world.beam

8. 💡 Guardrail Suggestion — CI Worker Output Assertion

If a future emsdk version reintroduces AtomVM.worker.js, browser startup would silently break (since routes/artifacts no longer include it). Consider adding a CI step after the web build:

- name: Verify no unexpected worker script
  shell: bash
  working-directory: src/platforms/emscripten/build/src
  run: |
    if [ -f AtomVM.worker.js ]; then
      echo "ERROR: AtomVM.worker.js was generated unexpectedly. Update routes/artifacts."
      exit 1
    fi

Risk Assessment

Risk Likelihood Impact Mitigation
Future emsdk emits worker.js again Low High (silent breakage) CI assertion (suggestion #8)
Downstream users stuck on old integration Medium Medium Better UPDATING.md (suggestion #6)
Symlink-based invocation fails Low Low realpathSync hardening (suggestion #5)

Files Reviewed

File Status
src/platforms/emscripten/src/CMakeLists.txt ✅ Correct
src/platforms/emscripten/src/atomvm.extern-post.js ⚠️ Minor (symlinks)
.github/workflows/wasm-build.yaml ✅ Complete
CHANGELOG.md ✅ Correct
UPDATING.md ⚠️ Under-documented
doc/src/build-instructions.md ⚠️ Bare invocation
doc/src/getting-started-guide.md ✅ Correct
examples/emscripten/*.html (6 files) ✅ Consistent
examples/emscripten/wasm_webserver.erl ✅ Correct
src/platforms/emscripten/tests/src/*.html (4 files) ✅ Consistent

Signed-off-by: Paul Guyot <pguyot@kallisys.net>
@bettio bettio merged commit 7020e92 into atomvm:release-0.7 Apr 21, 2026
149 of 155 checks passed
@pguyot pguyot deleted the w16/mjs branch April 21, 2026 20:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants