Skip to content

Commit

Permalink
Enable createWasm to use async/await with closure
Browse files Browse the repository at this point in the history
I really which we had a better solution here, but this makes the use
of async/await independent of closure usage.

This is a workaround for emscripten-core#23158, but it also happens to fix emscripten-core#23687
which stems from the same issue.

Fixes: emscripten-core#23687
  • Loading branch information
sbc100 committed Feb 19, 2025
1 parent 02b5a05 commit 821b11c
Show file tree
Hide file tree
Showing 6 changed files with 14 additions and 12 deletions.
1 change: 1 addition & 0 deletions src/closure-externs/closure-externs.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
// Special placeholder for `import.meta` and `await import`.
var EMSCRIPTEN$IMPORT$META;
var EMSCRIPTEN$AWAIT$IMPORT;
var EMSCRIPTEN$AWAIT;

// Don't minify createRequire
var createRequire;
Expand Down
2 changes: 1 addition & 1 deletion test/other/codesize/test_codesize_minimal_esm.gzsize
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1436
1445
2 changes: 1 addition & 1 deletion test/other/codesize/test_codesize_minimal_esm.jssize
Original file line number Diff line number Diff line change
@@ -1 +1 @@
2995
2990
3 changes: 3 additions & 0 deletions test/test_other.py
Original file line number Diff line number Diff line change
Expand Up @@ -7098,6 +7098,9 @@ class Descriptor {
self.run_process([EMXX, 'src.cpp', '-O2', '-sEXPORT_ALL'])
self.assertExists('a.out.js')

def test_modularize_legacy(self):
self.do_runf('hello_world.c', emcc_args=['-sMODULARIZE', '-sLEGACY_VM_SUPPORT'])

def test_emmake_emconfigure(self):
def check(what, args, fail=True, expect=''):
args = [what] + args
Expand Down
13 changes: 5 additions & 8 deletions tools/emscripten.py
Original file line number Diff line number Diff line change
Expand Up @@ -877,13 +877,7 @@ def create_sending(metadata, library_symbols):


def can_use_await():
# In MODULARIZE mode we can use `await` since the factory function itself
# is marked as `async` and the generated code all lives inside that factory
# function.
# However, because closure does not see this (it runs only on the inner code),
# it sees this as a top-level-await, which it does not yet support.
# FIXME(https://github.com/emscripten-core/emscripten/issues/23158)
return settings.MODULARIZE and not settings.USE_CLOSURE_COMPILER
return settings.MODULARIZE


def make_export_wrappers(function_exports):
Expand Down Expand Up @@ -993,7 +987,10 @@ def create_module(receiving, metadata, global_exports, library_symbols):
if settings.WASM_ASYNC_COMPILATION:
if can_use_await():
# In modularize mode the generated code is within a factory function.
module.append("var wasmExports = await createWasm();\n")
# This magic string gets replaced by `await createWasm`. It needed to allow
# closure and acorn to process the module without seeing this as a top-level
# await.
module.append("var wasmExports = EMSCRIPTEN$AWAIT(createWasm());\n")
else:
module.append("var wasmExports;\ncreateWasm();\n")
else:
Expand Down
5 changes: 3 additions & 2 deletions tools/link.py
Original file line number Diff line number Diff line change
Expand Up @@ -2065,13 +2065,14 @@ def phase_source_transforms(options):
# both main code and libraries.
# See also: `preprocess` in parseTools.js.
def fix_es6_import_statements(js_file):
if not settings.EXPORT_ES6 or not settings.USE_ES6_IMPORT_META:
if not settings.MODULARIZE:
return

src = read_file(js_file)
write_file(js_file, src
.replace('EMSCRIPTEN$IMPORT$META', 'import.meta')
.replace('EMSCRIPTEN$AWAIT$IMPORT', 'await import'))
.replace('EMSCRIPTEN$AWAIT$IMPORT', 'await import')
.replace('EMSCRIPTEN$AWAIT(createWasm())', 'await createWasm()'))
save_intermediate('es6-module')


Expand Down

0 comments on commit 821b11c

Please sign in to comment.