Skip to content

Commit

Permalink
Fix broken JS glue for AUDIO_WORKLETS with EXPORT_ES6
Browse files Browse the repository at this point in the history
Building to WASM with AUDIO_WORKLETS and EXPORT_ES6 results in:

  test.js:989 Uncaught (in promise) TypeError: Cannot set property wasmTable of #<Object> which has only a getter
      at receiveInstance (test.js:989:25)
      at receiveInstantiationResult (test.js:1011:5)

The read-only getter at issue is created only when ASSERTIONS != 0;
however, ASSERTIONS defaults to 1. We therefore append wasmTable to
EXPORTED_RUNTIME_METHODS if necessary.

We also prevent an ES6 Audio Worklet from loading the .wasm binary
via `new URL()`, as `URL` is unavailable in AudioWorkletGlobalScope.
  • Loading branch information
kangtastic committed Jan 29, 2024
1 parent 0e5b3a8 commit a694482
Show file tree
Hide file tree
Showing 3 changed files with 9 additions and 3 deletions.
6 changes: 3 additions & 3 deletions src/preamble.js
Original file line number Diff line number Diff line change
Expand Up @@ -608,14 +608,14 @@ function instrumentWasmTableWithAbort() {
#endif
var wasmBinaryFile;
#if EXPORT_ES6 && USE_ES6_IMPORT_META && !SINGLE_FILE
#if EXPORT_ES6 && USE_ES6_IMPORT_META && !SINGLE_FILE && !AUDIO_WORKLET // `URL` is undefined in Audio Worklet scope, so we cannot use `new URL()`.
if (Module['locateFile']) {
#endif
wasmBinaryFile = '{{{ WASM_BINARY_FILE }}}';
if (!isDataURI(wasmBinaryFile)) {
wasmBinaryFile = locateFile(wasmBinaryFile);
}
#if EXPORT_ES6 && USE_ES6_IMPORT_META && !SINGLE_FILE // in single-file mode, repeating WASM_BINARY_FILE would emit the contents again
#if EXPORT_ES6 && USE_ES6_IMPORT_META && !SINGLE_FILE && !AUDIO_WORKLET // In single-file mode, repeating WASM_BINARY_FILE would emit the contents again. For an Audio Worklet, we cannot use `new URL()`.
} else {
#if ENVIRONMENT_MAY_BE_SHELL
if (ENVIRONMENT_IS_SHELL)
Expand Down Expand Up @@ -1001,7 +1001,7 @@ function createWasm() {
assert(wasmTable, 'table not found in wasm exports');
#endif

#if AUDIO_WORKLET
#if AUDIO_WORKLET && !(EXPORT_ES6 && ASSERTIONS) // If EXPORT_ES6, we may have already done this.
// If we are in the audio worklet environment, we can only access the Module object
// and not the global scope of the main JS script. Therefore we need to export
// all functions that the audio worklet scope needs onto the Module object.
Expand Down
2 changes: 2 additions & 0 deletions test/test_browser.py
Original file line number Diff line number Diff line change
Expand Up @@ -5759,6 +5759,8 @@ def test_full_js_library_strict(self):
'pthreads_and_closure': (['-pthread', '--closure', '1', '-Oz'],),
'minimal_runtime': (['-sMINIMAL_RUNTIME'],),
'minimal_runtime_pthreads_and_closure': (['-sMINIMAL_RUNTIME', '-pthread', '--closure', '1', '-Oz'],),
'pthreads_es6': (['-pthread', '-sPTHREAD_POOL_SIZE=2', '-sEXPORT_ES6'],),
'es6': (['-sEXPORT_ES6'],),
})
def test_audio_worklet(self, args):
if '-sMEMORY64' in args and is_firefox():
Expand Down
4 changes: 4 additions & 0 deletions tools/link.py
Original file line number Diff line number Diff line change
Expand Up @@ -1350,6 +1350,10 @@ def phase_linker_setup(options, state, newargs):
# MINIMAL_RUNTIME exports these manually, since this export mechanism is placed
# in global scope that is not suitable for MINIMAL_RUNTIME loader.
settings.EXPORTED_RUNTIME_METHODS += ['stackSave', 'stackAlloc', 'stackRestore']
if settings.EXPORT_ES6 and settings.ASSERTIONS:
# With ASSERTIONS, EXPORT_ES6 assigns a read-only getter that prevents assigning
# Module['wasmTable'], which will then prevent the Audio Worklet from loading.
settings.EXPORTED_RUNTIME_METHODS += ['wasmTable']

if settings.FORCE_FILESYSTEM and not settings.MINIMAL_RUNTIME:
# when the filesystem is forced, we export by default methods that filesystem usage
Expand Down

0 comments on commit a694482

Please sign in to comment.