emscripten-core / emscripten-core/emscripten

JSPI issues

Open
#19,287 5 comments 0 reactions 0 assignees View on GitHub
Dominant language
C++
Stars
27.6k
Forks
3.6k
Avg merge
1d 1h
Merged PRs (30d)
105

Description

**Version of emscripten/emsdk:**
emcc (Emscripten gcc/clang-like replacement + linker emulating GNU ld) 3.1.28 (f11d6196dd4e8748a726f19895c859b40ff6a4f3)
Copyright (C) 2014 the Emscripten authors (see AUTHORS.txt)
This is free and open source software under the MIT license.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

Hello, we recently tried out JSPI (using ASYNCIFY=2). Ultimately it's a promising feature for us, thanks for the awesome work. With that said, we ran into some issues that we had to work around on our end, we would like to share them with you and get your input.

1) invoke_* functions are marked as JSPI imports by default. We got around this by passing "-s ASYNCIFY_IGNORE_INDIRECT=1" which disables that behavior, but is ASYNCIFY=2 actually intended to also mark those invoke_* function as JSPI imports to begin with? It looks like this might be a holdover from the legacy ASYNCIFY=1 days

2) When pthreads are turned on, and PROXY_TO_PTHREAD is set, the actual entry point is emscripten's _main_thread instead of startFabric, so that needs to be JSPI export'd.

3) We would like to use a single WASM binary that can run on both on browsers that support JSPI, and on browser that do not. Specifically, we suspect that Firefox will probably have much later release date for JSPI support than Chrome.

We came with a way that appears to work given the current state of emscripten/JSPI. The idea is to override the Asyncify.instrumentWasmExports and Asyncify.instrumentWasmImports. When JSPI support is available, those functions behave as normal (create the necessary wrappers). On the other hand, when JSPI support is unavailable, "dummy" wrappers are created that pass in "null" as the suspender object in the export case, and discard the "null" suspender object (first argument) in the import case. Since within the WASM the suspender is simply stored in and retrieved from a global location but never manipulated otherwise, the WASM/JS boundary is the only place that needs changing (i.e. the dummy wrappers above).

Together with hack above, the functions that are listed as JSPI imports switch their behavior between acting asynchronously/synchronously depending again on whether JSPI support is detected.

In our testing, this hack appears to work, but do you foresee any issues with this approach?

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.