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

Add a `#[wasm_bindgen(start)]` attribute #1057

Merged
merged 1 commit into from Nov 29, 2018

Conversation

Projects
None yet
2 participants
@alexcrichton
Copy link
Collaborator

alexcrichton commented Nov 28, 2018

This commit adds a new attribute to #[wasm_bindgen]: start. The
start attribute can be used to indicate that a function should be
executed when the module is loaded, configuring the start function of
the wasm executable. While this doesn't necessarily literally configure
the start section, it does its best!

Only one crate in a crate graph may indicate #[wasm_bindgen(start)],
so it's not recommended to be used in libraries but only end-user
applications. Currently this still must be used with the crate-type = ["cdylib"] annotation in Cargo.toml.

The implementation here is somewhat tricky because of the circular
dependency between our generated JS and the wasm file that we emit. This
circular dependency makes running initialization routines (like the
start shim) particularly fraught with complications because one may
need to run before the other but bundlers may not necessarily respect
it. Workarounds have been implemented for various emission strategies,
for example calling the start function directly after exports are wired
up with --no-modules and otherwise working around what appears to be
a Webpack bug with initializers running in a different order than we'd
like. In any case, this in theory doesn't show up to the end user!

Closes #74

@alexcrichton alexcrichton requested a review from fitzgen Nov 28, 2018

@alexcrichton alexcrichton force-pushed the alexcrichton:start branch from 9b8668b to 96a15d9 Nov 28, 2018

@alexcrichton

This comment has been minimized.

Copy link
Collaborator Author

alexcrichton commented Nov 28, 2018

For posterity, the major downside of #[wasm_bindgen(start)] is that you still have to crate-type = ["cdylib"] your crates. It's also not as ergonomic/idiomatic as using a bin crate type with fn main() { ... }.

The downsides of using fn main() {}, however, I think are:

  • The standard library isn't really ready for these semantics. It thinks that the "main function" is the entire program, tearing down standard library state when it exists. Contrasted with the wasm start function, the start function is just the beginning of execution and often schedules more work to happen later.
  • The standard library's fn main() {} also currently brings in some weighty initialization, meaning that binaries are a bit larger than they would otherwise need to be. This is likely surmountable though!

The thinking is that we can start off conservatively with a specific attribute like this, and then in the future if we see a way forward to fn main() { ... } working we can do that instead!

@fitzgen
Copy link
Member

fitzgen left a comment

LGTM!

Show resolved Hide resolved crates/cli-support/src/js/mod.rs Outdated
Show resolved Hide resolved crates/cli-support/src/js/mod.rs Outdated
pub fn foo2(x: u32) {}

#[wasm_bindgen(start)]
pub fn foo3<T>() {}

This comment has been minimized.

@fitzgen

fitzgen Nov 29, 2018

Member

Would be good to have a test for two otherwise valid start functions, to ensure that we properly error and don't accidentally just take the first one or something.

This comment has been minimized.

@alexcrichton

alexcrichton Nov 29, 2018

Author Collaborator

Ah unfortunately we don't have a great place to put such tests today, but I've filed #1058 to track this!

@@ -7,7 +7,7 @@ use wasm_bindgen::prelude::*;
use wasm_bindgen::JsCast;
use web_sys::{Document, Element, HtmlElement, Window};

#[wasm_bindgen]
#[wasm_bindgen(start)]

This comment has been minimized.

@fitzgen
Add a `#[wasm_bindgen(start)]` attribute
This commit adds a new attribute to `#[wasm_bindgen]`: `start`. The
`start` attribute can be used to indicate that a function should be
executed when the module is loaded, configuring the `start` function of
the wasm executable. While this doesn't necessarily literally configure
the `start` section, it does its best!

Only one crate in a crate graph may indicate `#[wasm_bindgen(start)]`,
so it's not recommended to be used in libraries but only end-user
applications. Currently this still must be used with the `crate-type =
["cdylib"]` annotation in `Cargo.toml`.

The implementation here is somewhat tricky because of the circular
dependency between our generated JS and the wasm file that we emit. This
circular dependency makes running initialization routines (like the
`start` shim) particularly fraught with complications because one may
need to run before the other but bundlers may not necessarily respect
it. Workarounds have been implemented for various emission strategies,
for example calling the start function directly after exports are wired
up with `--no-modules` and otherwise working around what appears to be
a Webpack bug with initializers running in a different order than we'd
like. In any case, this in theory doesn't show up to the end user!

Closes #74

@alexcrichton alexcrichton force-pushed the alexcrichton:start branch from 96a15d9 to a2aa28e Nov 29, 2018

@alexcrichton alexcrichton merged commit ed24a63 into rustwasm:master Nov 29, 2018

1 check was pending

continuous-integration/travis-ci/pr The Travis CI build is in progress
Details

@alexcrichton alexcrichton deleted the alexcrichton:start branch Nov 29, 2018

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment