Skip to content

Commit 292321d

Browse files
authored
[SPLIT_MODULE] Make getWasmImports return Proxy (#25559)
When `SPLIT_MODULE` is set, this makes the `imports` object returned by `getWasmImports` itself a Proxy, which redirects property requests starting with `placeholder` to an inner handler that processes the second module loading, and process all other property requests to the original `imports` object itself. This is a prepration to add multi-split loading functionality to the JS runtime. In the multi-split mode, we don't have a single seconday module `[modulename].deferred.wasm`, but instead multiple secondary modules. We plan to have multiple placeholder namespace (e.g., `placeholder2`, `placeholder3`, ...) that match those multiple files, and this can't be hardcoded with one `placeholder` string as we currently do, so having the `imports` object itself as a `Proxy` provides us flexibility to handle multiple placeholder namespaces and load correct modules later. Thanks @tlively for the idea!
1 parent c862f75 commit 292321d

File tree

4 files changed

+45
-30
lines changed

4 files changed

+45
-30
lines changed

src/preamble.js

Lines changed: 32 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -488,26 +488,38 @@ async function getWasmBinary(binaryFile) {
488488
#if SPLIT_MODULE
489489
{{{ makeModuleReceiveWithVar('loadSplitModule', undefined, 'instantiateSync') }}}
490490
var splitModuleProxyHandler = {
491-
get(target, prop, receiver) {
492-
return (...args) => {
491+
get(target, moduleName, receiver) {
492+
if (moduleName.startsWith('placeholder')) {
493+
return new Proxy({}, {
494+
get(target, base, receiver) {
495+
return (...args) => {
493496
#if ASYNCIFY == 2
494-
throw new Error('Placeholder function "' + prop + '" should not be called when using JSPI.');
497+
throw new Error('Placeholder function "' + base + '" should not be called when using JSPI.');
495498
#else
496-
err(`placeholder function called: ${prop}`);
497-
var imports = {'primary': wasmExports};
498-
// Replace '.wasm' suffix with '.deferred.wasm'.
499-
var deferred = wasmBinaryFile.slice(0, -5) + '.deferred.wasm'
500-
loadSplitModule(deferred, imports, prop);
501-
err('instantiated deferred module, continuing');
499+
// TODO: Implement multi-split module loading
500+
#if RUNTIME_DEBUG
501+
dbg(`placeholder function called: ${base}`);
502+
#endif
503+
var imports = {'primary': wasmExports};
504+
// Replace '.wasm' suffix with '.deferred.wasm'.
505+
var deferred = wasmBinaryFile.slice(0, -5) + '.deferred.wasm'
506+
loadSplitModule(deferred, imports, base);
507+
#if RUNTIME_DEBUG
508+
dbg('instantiated deferred module, continuing');
509+
#endif
502510
#if RELOCATABLE
503-
// When the table is dynamically laid out, the placeholder functions names
504-
// are offsets from the table base. In the main module, the table base is
505-
// always 1.
506-
prop = 1 + parseInt(prop);
511+
// When the table is dynamically laid out, the placeholder functions names
512+
// are offsets from the table base. In the main module, the table base is
513+
// always 1.
514+
base = 1 + parseInt(base);
507515
#endif
508-
return wasmTable.get({{{ toIndexType('prop') }}})(...args);
516+
return wasmTable.get({{{ toIndexType('base') }}})(...args);
509517
#endif
518+
}
519+
}
520+
});
510521
}
522+
return target[moduleName];
511523
}
512524
};
513525
#endif
@@ -653,21 +665,22 @@ function getWasmImports() {
653665
#endif
654666
#endif
655667
// prepare imports
656-
return {
668+
var imports = {
657669
#if MINIFY_WASM_IMPORTED_MODULES
658670
'a': wasmImports,
659671
#else // MINIFY_WASM_IMPORTED_MODULES
660672
'env': wasmImports,
661673
'{{{ WASI_MODULE_NAME }}}': wasmImports,
662674
#endif // MINIFY_WASM_IMPORTED_MODULES
663-
#if SPLIT_MODULE
664-
'placeholder': new Proxy({}, splitModuleProxyHandler),
665-
#endif
666675
#if RELOCATABLE
667676
'GOT.mem': new Proxy(wasmImports, GOTHandler),
668677
'GOT.func': new Proxy(wasmImports, GOTHandler),
669678
#endif
670-
}
679+
};
680+
#if SPLIT_MODULE
681+
imports = new Proxy(imports, splitModuleProxyHandler);
682+
#endif
683+
return imports;
671684
}
672685

673686
// Create the wasm instance.

test/codesize/test_codesize_file_preload.expected.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -447,9 +447,10 @@ async function instantiateAsync(binary, binaryFile, imports) {
447447

448448
function getWasmImports() {
449449
// prepare imports
450-
return {
450+
var imports = {
451451
"a": wasmImports
452452
};
453+
return imports;
453454
}
454455

455456
// Create the wasm instance.

test/codesize/test_codesize_minimal_O0.expected.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -658,10 +658,11 @@ async function instantiateAsync(binary, binaryFile, imports) {
658658

659659
function getWasmImports() {
660660
// prepare imports
661-
return {
661+
var imports = {
662662
'env': wasmImports,
663663
'wasi_snapshot_preview1': wasmImports,
664-
}
664+
};
665+
return imports;
665666
}
666667

667668
// Create the wasm instance.
Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
{
2-
"hello_world.js": 56566,
3-
"hello_world.js.gz": 17601,
2+
"hello_world.js": 56592,
3+
"hello_world.js.gz": 17608,
44
"hello_world.wasm": 15119,
55
"hello_world.wasm.gz": 7444,
6-
"no_asserts.js": 26608,
7-
"no_asserts.js.gz": 8874,
6+
"no_asserts.js": 26634,
7+
"no_asserts.js.gz": 8883,
88
"no_asserts.wasm": 12219,
99
"no_asserts.wasm.gz": 6005,
10-
"strict.js": 54581,
11-
"strict.js.gz": 16947,
10+
"strict.js": 54607,
11+
"strict.js.gz": 16955,
1212
"strict.wasm": 15119,
1313
"strict.wasm.gz": 7442,
14-
"total": 180212,
15-
"total_gz": 64313
14+
"total": 180290,
15+
"total_gz": 64337
1616
}

0 commit comments

Comments
 (0)