Skip to content

Commit 1386520

Browse files
authored
Move wasm module preload plugin out of library_browser.js. NFC (#18963)
Also test the preload plugin system under node. It was working previously but not covered by any of the test we run in CI. I'm hoping to unify this preloading system with the one planned as part of #18552.
1 parent b6d5f3b commit 1386520

13 files changed

+124
-71
lines changed

src/compiler.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,12 @@ Object.assign(global, settings);
6464

6565
global.symbolsOnly = symbolsOnlyArg != -1;
6666

67+
// In case compiler.js is run directly (as in gen_sig_info)
68+
// ALL_INCOMING_MODULE_JS_API might not be populated yet.
69+
if (!ALL_INCOMING_MODULE_JS_API.length) {
70+
ALL_INCOMING_MODULE_JS_API = INCOMING_MODULE_JS_API
71+
}
72+
6773
EXPORTED_FUNCTIONS = new Set(EXPORTED_FUNCTIONS);
6874
WASM_EXPORTS = new Set(WASM_EXPORTS);
6975
SIDE_MODULE_EXPORTS = new Set(SIDE_MODULE_EXPORTS);

src/library_browser.js

Lines changed: 7 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@ var LibraryBrowser = {
1212
'$safeSetTimeout',
1313
'$warnOnce',
1414
'emscripten_set_main_loop_timing',
15+
'$preloadPlugins',
16+
#if MAIN_MODULE
17+
'$preloadedWasm',
18+
#endif
1519
],
1620
$Browser__postset: `
1721
// exports
@@ -25,9 +29,6 @@ var LibraryBrowser = {
2529
Module["resumeMainLoop"] = function Module_resumeMainLoop() { Browser.mainLoop.resume() };
2630
Module["getUserMedia"] = function Module_getUserMedia() { Browser.getUserMedia() };
2731
Module["createContext"] = function Module_createContext(canvas, useWebGL, setInModule, webGLContextAttributes) { return Browser.createContext(canvas, useWebGL, setInModule, webGLContextAttributes) };
28-
#if MAIN_MODULE
29-
var preloadedWasm = {};
30-
#endif
3132
var preloadedImages = {};
3233
var preloadedAudios = {};`,
3334

@@ -101,13 +102,11 @@ var LibraryBrowser = {
101102
workers: [],
102103

103104
init: function() {
104-
if (!Module["preloadPlugins"]) Module["preloadPlugins"] = []; // needs to exist even in workers
105-
106105
if (Browser.initted) return;
107106
Browser.initted = true;
108107

109108
// Support for plugins that can process preloaded files. You can add more of these to
110-
// your app by creating and appending to Module.preloadPlugins.
109+
// your app by creating and appending to preloadPlugins.
111110
//
112111
// Each plugin is asked if it can handle a file based on the file's name. If it can,
113112
// it is given the file's raw data. When it is done, it calls a callback with the file's
@@ -146,7 +145,7 @@ var LibraryBrowser = {
146145
};
147146
img.src = url;
148147
};
149-
Module['preloadPlugins'].push(imagePlugin);
148+
preloadPlugins.push(imagePlugin);
150149

151150
var audioPlugin = {};
152151
audioPlugin['canHandle'] = function audioPlugin_canHandle(name) {
@@ -209,34 +208,7 @@ var LibraryBrowser = {
209208
finish(audio); // try to use it even though it is not necessarily ready to play
210209
}, 10000);
211210
};
212-
Module['preloadPlugins'].push(audioPlugin);
213-
214-
#if MAIN_MODULE
215-
// Use string keys here to avoid minification since the plugin consumer
216-
// also uses string keys.
217-
var wasmPlugin = {
218-
'promiseChainEnd': Promise.resolve(),
219-
'canHandle': function(name) {
220-
return !Module.noWasmDecoding && name.endsWith('.so')
221-
},
222-
'handle': function(byteArray, name, onload, onerror) {
223-
// loadWebAssemblyModule can not load modules out-of-order, so rather
224-
// than just running the promises in parallel, this makes a chain of
225-
// promises to run in series.
226-
wasmPlugin['promiseChainEnd'] = wasmPlugin['promiseChainEnd'].then(
227-
() => loadWebAssemblyModule(byteArray, {loadAsync: true, nodelete: true})).then(
228-
(module) => {
229-
preloadedWasm[name] = module;
230-
onload();
231-
},
232-
(err) => {
233-
console.warn("Couldn't instantiate wasm: " + name + " '" + err + "'");
234-
onerror();
235-
});
236-
}
237-
};
238-
Module['preloadPlugins'].push(wasmPlugin);
239-
#endif // MAIN_MODULE
211+
preloadPlugins.push(audioPlugin);
240212

241213
// Canvas event setup
242214

@@ -279,23 +251,6 @@ var LibraryBrowser = {
279251
}
280252
},
281253

282-
// Tries to handle an input byteArray using preload plugins. Returns true if
283-
// it was handled.
284-
handledByPreloadPlugin: function(byteArray, fullname, finish, onerror) {
285-
// Ensure plugins are ready.
286-
Browser.init();
287-
288-
var handled = false;
289-
Module['preloadPlugins'].forEach((plugin) => {
290-
if (handled) return;
291-
if (plugin['canHandle'](fullname)) {
292-
plugin['handle'](byteArray, fullname, finish, onerror);
293-
handled = true;
294-
}
295-
});
296-
return handled;
297-
},
298-
299254
createContext: function(/** @type {HTMLCanvasElement} */ canvas, useWebGL, setInModule, webGLContextAttributes) {
300255
if (useWebGL && Module.ctx && canvas == Module.canvas) return Module.ctx; // no need to recreate GL context if it's already been created for this canvas.
301256

src/library_dylink.js

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,39 @@ var dlopenMissingError = "'To use dlopen, you need enable dynamic linking, see h
1010

1111
var LibraryDylink = {
1212
#if RELOCATABLE
13+
$registerWasmPlugin__deps: ['$preloadPlugins'],
14+
$registerWasmPlugin: function() {
15+
// Use string keys here to avoid minification since the plugin consumer
16+
// also uses string keys.
17+
var wasmPlugin = {
18+
'promiseChainEnd': Promise.resolve(),
19+
'canHandle': function(name) {
20+
return !Module.noWasmDecoding && name.endsWith('.so')
21+
},
22+
'handle': function(byteArray, name, onload, onerror) {
23+
// loadWebAssemblyModule can not load modules out-of-order, so rather
24+
// than just running the promises in parallel, this makes a chain of
25+
// promises to run in series.
26+
wasmPlugin['promiseChainEnd'] = wasmPlugin['promiseChainEnd'].then(
27+
() => loadWebAssemblyModule(byteArray, {loadAsync: true, nodelete: true})).then(
28+
(module) => {
29+
preloadedWasm[name] = module;
30+
onload();
31+
},
32+
(error) => {
33+
err('failed to instantiate wasm: ' + name + ': ' + error);
34+
onerror();
35+
});
36+
}
37+
};
38+
preloadPlugins.push(wasmPlugin);
39+
},
40+
41+
$preloadedWasm__deps: ['$registerWasmPlugin'],
42+
$preloadedWasm__postset: `
43+
registerWasmPlugin();
44+
`,
45+
$preloadedWasm: {},
1346

1447
$isSymbolDefined: function(symName) {
1548
// Ignore 'stub' symbols that are auto-generated as part of the original
@@ -884,7 +917,9 @@ var LibraryDylink = {
884917
// If a library was already loaded, it is not loaded a second time. However
885918
// flags.global and flags.nodelete are handled every time a load request is made.
886919
// Once a library becomes "global" or "nodelete", it cannot be removed or unloaded.
887-
$loadDynamicLibrary__deps: ['$LDSO', '$loadWebAssemblyModule', '$isInternalSym', '$mergeLibSymbols', '$newDSO', '$asyncLoad'],
920+
$loadDynamicLibrary__deps: ['$LDSO', '$loadWebAssemblyModule',
921+
'$isInternalSym', '$mergeLibSymbols', '$newDSO',
922+
'$asyncLoad', '$preloadedWasm'],
888923
$loadDynamicLibrary__docs: `
889924
/**
890925
* @param {number=} handle
@@ -955,7 +990,10 @@ var LibraryDylink = {
955990
// libName -> exports
956991
function getExports() {
957992
// lookup preloaded cache first
958-
if (typeof preloadedWasm != 'undefined' && preloadedWasm[libName]) {
993+
if (preloadedWasm[libName]) {
994+
#if DYLINK_DEBUG
995+
err('using preloaded module for: ' + libName);
996+
#endif
959997
var libModule = preloadedWasm[libName];
960998
return flags.loadAsync ? Promise.resolve(libModule) : libModule;
961999
}

src/library_fs.js

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -93,10 +93,6 @@ Object.defineProperties(FSNode.prototype, {
9393
FS.FSNode = FSNode;
9494
FS.createPreloadedFile = FS_createPreloadedFile;
9595
FS.staticInit();` +
96-
#if USE_CLOSURE_COMPILER
97-
// Declare variable for Closure, FS.createPreloadedFile() below calls Browser.handledByPreloadPlugin()
98-
'/**@suppress {duplicate, undefinedVars}*/var Browser;' +
99-
#endif
10096
// Get module methods from settings
10197
'{{{ EXPORTED_RUNTIME_METHODS.filter(function(func) { return func.substr(0, 3) === 'FS_' }).map(function(func){return 'Module["' + func + '"] = FS.' + func.substr(3) + ";"}).reduce(function(str, func){return str + func;}, '') }}}';
10298
},

src/library_fs_shared.js

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,31 @@
55
*/
66

77
mergeInto(LibraryManager.library, {
8+
$preloadPlugins: "{{{ makeModuleReceiveExpr('preloadPlugins', '[]') }}}",
9+
10+
#if !MINIMAL_RUNTIME
11+
// Tries to handle an input byteArray using preload plugins. Returns true if
12+
// it was handled.
13+
$FS_handledByPreloadPlugin__internal: true,
14+
$FS_handledByPreloadPlugin__deps: ['$preloadPlugins'],
15+
$FS_handledByPreloadPlugin: function(byteArray, fullname, finish, onerror) {
16+
#if LibraryManager.has('library_browser.js')
17+
// Ensure plugins are ready.
18+
if (typeof Browser != 'undefined') Browser.init();
19+
#endif
20+
21+
var handled = false;
22+
preloadPlugins.forEach(function(plugin) {
23+
if (handled) return;
24+
if (plugin['canHandle'](fullname)) {
25+
plugin['handle'](byteArray, fullname, finish, onerror);
26+
handled = true;
27+
}
28+
});
29+
return handled;
30+
},
31+
#endif
32+
833
// Preloads a file asynchronously. You can call this before run, for example in
934
// preRun. run will be delayed until this file arrives and is set up.
1035
// If you call it after run(), you may want to pause the main loop until it
@@ -17,7 +42,11 @@ mergeInto(LibraryManager.library, {
1742
// You can also call this with a typed array instead of a url. It will then
1843
// do preloading for the Image/Audio part, as if the typed array were the
1944
// result of an XHR that you did manually.
20-
$FS_createPreloadedFile__deps: ['$asyncLoad'],
45+
$FS_createPreloadedFile__deps: ['$asyncLoad',
46+
#if !MINIMAL_RUNTIME
47+
'$FS_handledByPreloadPlugin',
48+
#endif
49+
],
2150
$FS_createPreloadedFile: function(parent, name, url, canRead, canWrite, onload, onerror, dontCreateFile, canOwn, preFinish) {
2251
#if WASMFS
2352
// TODO: use WasmFS code to resolve and join the path here?
@@ -38,7 +67,7 @@ mergeInto(LibraryManager.library, {
3867
removeRunDependency(dep);
3968
}
4069
#if !MINIMAL_RUNTIME
41-
if (Browser.handledByPreloadPlugin(byteArray, fullname, finish, () => {
70+
if (FS_handledByPreloadPlugin(byteArray, fullname, finish, () => {
4271
if (onerror) onerror();
4372
removeRunDependency(dep);
4473
})) {
@@ -76,4 +105,5 @@ mergeInto(LibraryManager.library, {
76105
if (canWrite) mode |= {{{ cDefs.S_IWUGO }}};
77106
return mode;
78107
},
108+
79109
});

src/library_lz4.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
#if LZ4
88
mergeInto(LibraryManager.library, {
9-
$LZ4__deps: ['$FS'],
9+
$LZ4__deps: ['$FS', '$preloadPlugins'],
1010
$LZ4: {
1111
DIR_MODE: {{{ cDefs.S_IFDIR }}} | 511 /* 0777 */,
1212
FILE_MODE: {{{ cDefs.S_IFREG }}} | 511 /* 0777 */,
@@ -52,7 +52,7 @@ mergeInto(LibraryManager.library, {
5252
pack['metadata'].files.forEach(function(file) {
5353
var handled = false;
5454
var fullname = file.filename;
55-
Module['preloadPlugins'].forEach(function(plugin) {
55+
preloadPlugins.forEach(function(plugin) {
5656
if (handled) return;
5757
if (plugin['canHandle'](fullname)) {
5858
var dep = getUniqueRunDependency('fp ' + fullname);

src/library_wasmfs.js

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,7 @@
77
mergeInto(LibraryManager.library, {
88
$wasmFSPreloadedFiles: [],
99
$wasmFSPreloadedDirs: [],
10-
// Declare variable for Closure, FS.createPreloadedFile() below calls Browser.handledByPreloadPlugin()
1110
$FS__postset: `
12-
#if USE_CLOSURE_COMPILER
13-
/**@suppress {duplicate, undefinedVars}*/var Browser;
14-
#endif
1511
FS.createPreloadedFile = FS_createPreloadedFile;
1612
`,
1713
$FS__deps: [
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
23827
1+
23842
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
27887
1+
28153
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
20076
1+
20091

0 commit comments

Comments
 (0)