Skip to content

Conversation

aheejin
Copy link
Member

@aheejin aheejin commented Oct 16, 2025

Currently, if the primary module name is test.wasm and when a placeholder function is called, the emscripten JS runtime loads test.deferred.wasm, which is hardcoded. But as we want emscripten to support multi-split, the runtime has to know which secondary module to load.

Binaryen's WebAssembly/binaryen#7975 changes the placeholder import module naming scheme. Currently placeholder's import modules are all placeholder: https://github.com/WebAssembly/binaryen/blob/dcc704ce20e4723ae42012039bdb3b84ec2035f9/test/lit/wasm-split/multi-split.wast#L291-L295

But the Binaryen's companion PR will change this to the format of placeholder.[secondaryName]. Then Emscripten runtime will parse this module name to learn which secondary file to load. For example, if the import module is placeholder.2 and the import base is 3 and the primary wasm file is test.wasm,

(import "placeholder.2" "3" (func $placeholder_3 (result i32)))

when placeholder_3 function is loaded, the runtime will parse placeholder.2 and correctly figure out that it should load test.2.wasm.

This PR still supports the old placeholder namespace, because this PR has to land first for the Binaryen companion PR to land. After it lands, we can remove the placeholder handling part.

Companion PR: WebAssembly/binaryen#7975

Currently, if the primary module name is `test.wasm` and when a
placeholder function is called, the emscripten JS runtime loads
`test.deferred.wasm`, which is hardcoded. But as we want emscripten to
support multi-split, the runtime has to know which secondary module to
load.

Binaryen's #??? changes the placeholder import module naming scheme.
Currently placeholder's import modules are all `placeholder`:
https://github.com/WebAssembly/binaryen/blob/dcc704ce20e4723ae42012039bdb3b84ec2035f9/test/lit/wasm-split/multi-split.wast#L291-L295

But #???? will change this to the format of
`placeholder.[secondaryName]`. Then Emscripten runtime will parse this
module name to learn which secondary file to load. For example, if the
import module is `placeholder.2` and the import base is `3` and the
primary wasm file is `test.wasm`,
```wast
(import "placeholder.2" "3" (func $placeholder_3 (result i32)))
```
when `placeholder_3` function is loaded, the runtime will parse
`placeholder.2` and correctly figure out that it should load
`test.2.wasm`.

This PR still supports the old `placeholder` namespace, because this PR
has to land first for ???? to land. After ???? lands, we can remove the
`placeholder` handling part.

Companion PR:
Comment on lines +494 to +495
if (moduleName == 'placeholder') { // old format
secondaryFile = wasmBinaryFile.slice(0, -5) + '.deferred.wasm';
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In case I wasn't clear, the plan is to remove this special old format handling after WebAssembly/binaryen#7975 lands.

@aheejin aheejin merged commit 56ed8e9 into emscripten-core:main Oct 16, 2025
34 checks passed
@aheejin aheejin deleted the multi_module_loading branch October 16, 2025 22:34
aheejin added a commit to WebAssembly/binaryen that referenced this pull request Oct 17, 2025
For now we use a single namespace for all placeholder imports. This
namespace can be set by `--placeholder-namespace` and if not set it is
by default `placeholder`.

This changes it so that the namespace is in the format of
`placeholder.[secondaryName]`. That `placeholder`, or a user-specified
string via `--placeholder-namespace`, is a prefix of the namespace and
not the namespace itself. In `secondaryName` part we put the name of
secondary modules.

To be consistent with that change, I'd like to rename
`--placeholder-namespace` to `--placeholder-namespace-prefix`. But in
order not to break people who are using the old option, this just adds
`--placeholder-namespace-prefix` and keeps `--placeholder-namespace` but
make its behavior the same as `--placeholder-namespace-prefix`.

This is done to make multi-split module loading work in emscripten.
Currently, if the primary module name is `test.wasm` and when a
placeholder function is called, the emscripten JS runtime loads
`test.deferred.wasm`, which is hardcoded. But as we want emscripten to
support multi-split, the runtime has to know which secondary module to
load.

The companion PR in emscripten
(emscripten-core/emscripten#25571) makes
emscripten runtime use that `secondaryName` part to figure out which
secondary module file to load in case a placeholder function is called.
For example, if the import module is `placeholder.2` and the import base
is `3` and the primary wasm file is `test.wasm`,
```wast
(import "placeholder.2" "3" (func $placeholder_3 (result i32)))
```
when `placeholder_3` function is loaded, the runtime will parse
`placeholder.2` and correctly figure out that it should load
`test.2.wasm`.

Companion PR: emscripten-core/emscripten#25571,
which has to land first.
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.

2 participants