Skip to content

Commit ca742a8

Browse files
authored
Improving wasm loading logic (#1996)
* Improving wasm loading logic * Adding in note to the book about the new loading functionality
1 parent 91f0dbd commit ca742a8

File tree

2 files changed

+66
-49
lines changed

2 files changed

+66
-49
lines changed

crates/cli-support/src/js/mod.rs

+50-46
Original file line numberDiff line numberDiff line change
@@ -434,20 +434,20 @@ impl<'a> Context<'a> {
434434
let default_module_path = match self.config.mode {
435435
OutputMode::Web => {
436436
"\
437-
if (typeof module === 'undefined') {
438-
module = import.meta.url.replace(/\\.js$/, '_bg.wasm');
437+
if (typeof input === 'undefined') {
438+
input = import.meta.url.replace(/\\.js$/, '_bg.wasm');
439439
}"
440440
}
441441
OutputMode::NoModules { .. } => {
442442
"\
443-
if (typeof module === 'undefined') {
443+
if (typeof input === 'undefined') {
444444
let src;
445445
if (document === undefined) {
446446
src = location.href;
447447
} else {
448448
src = document.currentScript.src;
449449
}
450-
module = src.replace(/\\.js$/, '_bg.wasm');
450+
input = src.replace(/\\.js$/, '_bg.wasm');
451451
}"
452452
}
453453
_ => "",
@@ -504,54 +504,58 @@ impl<'a> Context<'a> {
504504

505505
let js = format!(
506506
"\
507-
function init(module{init_memory_arg}) {{
508-
{default_module_path}
509-
let result;
510-
const imports = {{}};
511-
{imports_init}
512-
if ((typeof URL === 'function' && module instanceof URL) || typeof module === 'string' || (typeof Request === 'function' && module instanceof Request)) {{
507+
async function load(module, imports) {{
508+
if (typeof Response === 'function' && module instanceof Response) {{
513509
{init_memory2}
514-
const response = fetch(module);
515510
if (typeof WebAssembly.instantiateStreaming === 'function') {{
516-
result = WebAssembly.instantiateStreaming(response, imports)
517-
.catch(e => {{
518-
return response
519-
.then(r => {{
520-
if (r.headers.get('Content-Type') != 'application/wasm') {{
521-
console.warn(\"`WebAssembly.instantiateStreaming` failed \
522-
because your server does not serve wasm with \
523-
`application/wasm` MIME type. Falling back to \
524-
`WebAssembly.instantiate` which is slower. Original \
525-
error:\\n\", e);
526-
return r.arrayBuffer();
527-
}} else {{
528-
throw e;
529-
}}
530-
}})
531-
.then(bytes => WebAssembly.instantiate(bytes, imports));
532-
}});
533-
}} else {{
534-
result = response
535-
.then(r => r.arrayBuffer())
536-
.then(bytes => WebAssembly.instantiate(bytes, imports));
511+
try {{
512+
return await WebAssembly.instantiateStreaming(module, imports);
513+
514+
}} catch (e) {{
515+
if (module.headers.get('Content-Type') != 'application/wasm') {{
516+
console.warn(\"`WebAssembly.instantiateStreaming` failed \
517+
because your server does not serve wasm with \
518+
`application/wasm` MIME type. Falling back to \
519+
`WebAssembly.instantiate` which is slower. Original \
520+
error:\\n\", e);
521+
522+
}} else {{
523+
throw e;
524+
}}
525+
}}
537526
}}
527+
528+
const bytes = await module.arrayBuffer();
529+
return await WebAssembly.instantiate(bytes, imports);
530+
538531
}} else {{
539532
{init_memory1}
540-
result = WebAssembly.instantiate(module, imports)
541-
.then(result => {{
542-
if (result instanceof WebAssembly.Instance) {{
543-
return {{ instance: result, module }};
544-
}} else {{
545-
return result;
546-
}}
547-
}});
533+
const instance = await WebAssembly.instantiate(module, imports);
534+
535+
if (instance instanceof WebAssembly.Instance) {{
536+
return {{ instance, module }};
537+
538+
}} else {{
539+
return instance;
540+
}}
548541
}}
549-
return result.then(({{instance, module}}) => {{
550-
wasm = instance.exports;
551-
init.__wbindgen_wasm_module = module;
552-
{start}
553-
return wasm;
554-
}});
542+
}}
543+
544+
async function init(input{init_memory_arg}) {{
545+
{default_module_path}
546+
const imports = {{}};
547+
{imports_init}
548+
549+
if (typeof input === 'string' || (typeof Request === 'function' && input instanceof Request) || (typeof URL === 'function' && input instanceof URL)) {{
550+
input = fetch(input);
551+
}}
552+
553+
const {{ instance, module }} = await load(await input, imports);
554+
555+
wasm = instance.exports;
556+
init.__wbindgen_wasm_module = module;
557+
{start}
558+
return wasm;
555559
}}
556560
",
557561
init_memory_arg = init_memory_arg,

examples/without-a-bundler/index.html

+16-3
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,25 @@
1919
// default export to inform it where the wasm file is located on the
2020
// server, and then we wait on the returned promise to wait for the
2121
// wasm to be loaded.
22+
//
2223
// It may look like this: `await init('./pkg/without_a_bundler_bg.wasm');`,
2324
// but there is also a handy default inside `init` function, which uses
24-
// `import.meta` to locate the wasm file relatively to js file
25+
// `import.meta` to locate the wasm file relatively to js file.
26+
//
27+
// Note that instead of a string you can also pass in any of the
28+
// following things:
29+
//
30+
// * `WebAssembly.Module`
31+
//
32+
// * `ArrayBuffer`
33+
//
34+
// * `Response`
35+
//
36+
// * `Promise` which returns any of the above, e.g. `fetch("./path/to/wasm")`
37+
//
38+
// This gives you complete control over how the module is loaded
39+
// and compiled.
2540
//
26-
// Note that instead of a string here you can also pass in an instance
27-
// of `WebAssembly.Module` which allows you to compile your own module.
2841
// Also note that the promise, when resolved, yields the wasm module's
2942
// exports which is the same as importing the `*_bg` module in other
3043
// modes

0 commit comments

Comments
 (0)