Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Automatically start execution on import. #1940

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion benchmarks/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,6 @@ function executeBenchmark(name, bm) {
// Load wasm files and when they're done (plus the DOM) then we initialize
// everything
const wasms = [];
wasms.push(wbindgen_init('./pkg/wasm_bindgen_benchmark_bg.wasm'));
wasms.push(fetch('./raw.wasm')
.then(r => r.arrayBuffer())
.then(m => WebAssembly.instantiate(m, { './globals.js': globals }))
Expand Down
33 changes: 28 additions & 5 deletions crates/cli-support/src/js/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,11 @@ impl<'a> Context<'a> {
Ok(())
}

pub fn finalize(&mut self, module_name: &str) -> Result<(String, String), Error> {
pub fn finalize(
&mut self,
module_name: &str,
auto_start: bool,
) -> Result<(String, String), Error> {
// Finalize all bindings for JS classes. This is where we'll generate JS
// glue for all classes as well as finish up a few final imports like
// `__wrap` and such.
Expand All @@ -184,7 +188,7 @@ impl<'a> Context<'a> {
// we don't ask for items which we can no longer emit.
drop(self.exposed_globals.take().unwrap());

self.finalize_js(module_name, needs_manual_start)
self.finalize_js(module_name, needs_manual_start, auto_start)
}

/// Performs the task of actually generating the final JS module, be it
Expand All @@ -194,6 +198,7 @@ impl<'a> Context<'a> {
&mut self,
module_name: &str,
needs_manual_start: bool,
auto_start: bool,
) -> Result<(String, String), Error> {
let mut ts = self.typescript.clone();
let mut js = String::new();
Expand All @@ -215,9 +220,17 @@ impl<'a> Context<'a> {
js.push_str("let wasm;\n");
init = self.gen_init(needs_manual_start, None)?;
footer.push_str(&format!(
"self.{} = Object.assign(init, __exports);\n",
global
"self.{} = Object.assign(init{}, __exports);\n",
global,
if needs_manual_start && auto_start {
"()"
} else {
""
}
));
if needs_manual_start && auto_start {
footer.push_str(&format!("self.{}.init = init;\n", global));
}
}

// With normal CommonJS node we need to defer requiring the wasm
Expand Down Expand Up @@ -275,7 +288,17 @@ impl<'a> Context<'a> {
OutputMode::Web => {
self.imports_post.push_str("let wasm;\n");
init = self.gen_init(needs_manual_start, Some(&mut imports))?;
footer.push_str("export default init;\n");
if needs_manual_start && auto_start {
footer.push_str("export { init };\n");
}
footer.push_str(&format!(
"export default init{};\n",
if needs_manual_start && auto_start {
"()"
} else {
""
}
));
}
}

Expand Down
9 changes: 8 additions & 1 deletion crates/cli-support/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ pub struct Bindgen {
multi_value: bool,
wasm_interface_types: bool,
encode_into: EncodeInto,
auto_start: bool,
}

pub struct Output {
Expand Down Expand Up @@ -108,6 +109,7 @@ impl Bindgen {
multi_value: multi_value || wasm_interface_types,
wasm_interface_types,
encode_into: EncodeInto::Test,
auto_start: true,
}
}

Expand Down Expand Up @@ -252,6 +254,11 @@ impl Bindgen {
self
}

pub fn auto_start(&mut self, auto_start: bool) -> &mut Bindgen {
self.auto_start = auto_start;
self
}

pub fn generate<P: AsRef<Path>>(&mut self, path: P) -> Result<(), Error> {
self.generate_output()?.emit(path.as_ref())
}
Expand Down Expand Up @@ -412,7 +419,7 @@ impl Bindgen {
.unwrap();
let mut cx = js::Context::new(&mut module, self, &adapters, &aux)?;
cx.generate()?;
let (js, ts) = cx.finalize(stem)?;
let (js, ts) = cx.finalize(stem, self.auto_start)?;
Generated::Js(JsGenerated {
snippets: aux.snippets.clone(),
local_modules: aux.local_modules.clone(),
Expand Down
5 changes: 4 additions & 1 deletion crates/cli/src/bin/wasm-bindgen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ Options:
--remove-producers-section Remove the telemetry `producers` section
--encode-into MODE Whether or not to use TextEncoder#encodeInto,
valid values are [test, always, never]
--no-auto-start Disable automatic start
--nodejs Deprecated, use `--target nodejs`
--web Deprecated, use `--target web`
--no-modules Deprecated, use `--target no-modules`
Expand All @@ -59,6 +60,7 @@ struct Args {
flag_remove_producers_section: bool,
flag_keep_debug: bool,
flag_encode_into: Option<String>,
flag_no_auto_start: bool,
flag_target: Option<String>,
arg_input: Option<PathBuf>,
}
Expand Down Expand Up @@ -109,7 +111,8 @@ fn rmain(args: &Args) -> Result<(), Error> {
.keep_debug(args.flag_keep_debug)
.remove_name_section(args.flag_remove_name_section)
.remove_producers_section(args.flag_remove_producers_section)
.typescript(typescript);
.typescript(typescript)
.auto_start(!args.flag_no_auto_start);
if let Some(ref name) = args.flag_no_modules_global {
b.no_modules_global(name)?;
}
Expand Down
1 change: 1 addition & 0 deletions examples/raytrace-parallel/build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ RUSTFLAGS='-C target-feature=+atomics,+bulk-memory' \
cargo run --manifest-path ../../crates/cli/Cargo.toml \
--bin wasm-bindgen -- \
../../target/wasm32-unknown-unknown/release/raytrace_parallel.wasm --out-dir . \
--no-auto-start \
--no-modules

python3 -m http.server
2 changes: 1 addition & 1 deletion examples/wasm2js/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,5 @@
<body>
<p>Open up the developer console to see "Hello, World!"</p>
</body>
<script src=index.js type=module></script>
<script src=pkg/wasm2js.js type=module></script>
</html>
4 changes: 0 additions & 4 deletions examples/wasm2js/index.js

This file was deleted.

2 changes: 1 addition & 1 deletion examples/websockets/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<head>
<meta charset="utf-8">
<title>WebSockets example</title>
<script type="module" src="index.js"></script>
<script type="module" src="pkg/websockets.js"></script>
</head>
<bodt>
</bodt>
Expand Down
5 changes: 0 additions & 5 deletions examples/websockets/index.js

This file was deleted.

2 changes: 1 addition & 1 deletion examples/without-a-bundler-no-modules/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
const { add } = wasm_bindgen;

async function run() {
await wasm_bindgen('./pkg/without_a_bundler_no_modules_bg.wasm');
await wasm_bindgen;

const result = add(1, 2);
console.log(`1 + 2 = ${result}`);
Expand Down
19 changes: 5 additions & 14 deletions examples/without-a-bundler/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,27 +8,18 @@
// Use ES module import syntax to import functionality from the module
// that we have compiled.
//
// Note that the `default` import is an initialization function which
// Note that the `default` import is an initialization promise which
// will "boot" the module and make it ready to use. Currently browsers
// don't support natively imported WebAssembly as an ES module, but
// eventually the manual initialization won't be required!
import init, { add } from './pkg/without_a_bundler.js';

async function run() {
// First up we need to actually load the wasm file, so we use the
// default export to inform it where the wasm file is located on the
// server, and then we wait on the returned promise to wait for the
// wasm to be loaded.
// It may look like this: `await init('./pkg/without_a_bundler_bg.wasm');`,
// but there is also a handy default inside `init` function, which uses
// `import.meta` to locate the wasm file relatively to js file
// First we wait on the promise to wait for the wasm to be loaded.
//
// Note that instead of a string here you can also pass in an instance
// of `WebAssembly.Module` which allows you to compile your own module.
// Also note that the promise, when resolved, yields the wasm module's
// exports which is the same as importing the `*_bg` module in other
// modes
await init();
// Note that the promise, when resolved, yields the wasm module's exports
// which is the same as importing the `*_bg` module in other modes
await init;

// And afterwards we can use all the functionality defined in wasm.
const result = add(1, 2);
Expand Down
5 changes: 5 additions & 0 deletions guide/src/reference/cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,3 +68,8 @@ sections.
When generating bundler-compatible code (see the section on [deployment]) this
indicates that the bundled code is always intended to go into a browser so a few
checks for Node.js can be elided.

### `--no-auto-start`

When generating web-compatible code, start executing the `start` function on importing
the file.