mirror of
https://github.com/rustwasm/wasm-bindgen.git
synced 2025-01-05 19:53:55 +03:00
Modernize some documentation
Mostly around the raytrace example but also contributing new web-sys APIs.
This commit is contained in:
parent
c6db488076
commit
b1daf81803
@ -149,7 +149,7 @@ impl Task {
|
||||
// * `AWAKE` - the Promise will immediately be resolved and
|
||||
// we'll execute the work on the next microtask queue.
|
||||
Poll::Pending => {
|
||||
wait_async(&self.atomic.state, SLEEPING).then(&inner.closure);
|
||||
drop(wait_async(&self.atomic.state, SLEEPING).then(&inner.closure));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -20,12 +20,11 @@ set -ex
|
||||
RUSTFLAGS='-C target-feature=+atomics,+bulk-memory' \
|
||||
cargo build --target wasm32-unknown-unknown --release -Z build-std=std,panic_abort
|
||||
|
||||
# Note the usage of `--no-modules` here which is used to create an output which
|
||||
# is usable from Web Workers. We notably can't use `--target bundler` since
|
||||
# Webpack doesn't have support for atomics yet.
|
||||
cargo run --manifest-path ../../crates/cli/Cargo.toml \
|
||||
--bin wasm-bindgen -- \
|
||||
../../target/wasm32-unknown-unknown/release/raytrace_parallel.wasm --out-dir . \
|
||||
--no-modules
|
||||
# Note the usage of `--target no-modules` here which is required for passing
|
||||
# the memory import to each wasm module.
|
||||
cargo run -p wasm-bindgen-cli -- \
|
||||
../../target/wasm32-unknown-unknown/release/raytrace_parallel.wasm \
|
||||
--out-dir . \
|
||||
--target no-modules
|
||||
|
||||
python3 -m http.server
|
||||
python3 server.py
|
||||
|
@ -12,8 +12,7 @@ concurrency.disabled = true;
|
||||
|
||||
// First up, but try to do feature detection to provide better error messages
|
||||
function loadWasm() {
|
||||
let msg = 'This demo requires a current version of Firefox (e.g., 70.0) with\n'
|
||||
msg += 'the `javascript.options.shared_memory` option enabled in `about:config`';
|
||||
let msg = 'This demo requires a current version of Firefox (e.g., 79.0)';
|
||||
if (typeof SharedArrayBuffer !== 'function') {
|
||||
alert('this browser does not have SharedArrayBuffer support enabled' + '\n\n' + msg);
|
||||
return
|
||||
|
@ -1,6 +1,6 @@
|
||||
# Supporting More Web APIs in `web-sys`
|
||||
|
||||
1. <input type="checkbox"/> Ensure that the `.webidl` file describing the
|
||||
1. Ensure that the `.webidl` file describing the
|
||||
interface exists somewhere within the `crates/web-sys/webidls/enabled`
|
||||
directory.
|
||||
|
||||
@ -28,49 +28,12 @@
|
||||
git mv webidls/unavailable_enum_ident/MyWebApi.webidl webidls/enabled/MyWebApi.webidl
|
||||
```
|
||||
|
||||
2. <input type="checkbox"/> Verify that the `web-sys` crate still builds and
|
||||
that its tests still pass with the new `.webidl` file enabled:
|
||||
2. Regenerate the `web-sys` crate auto-generated bindings, which you can do with
|
||||
the following commands:
|
||||
|
||||
```sh
|
||||
cd crates/web-sys
|
||||
cargo build
|
||||
cargo test
|
||||
cargo run --release --package wasm-bindgen-webidl webidls src/features
|
||||
```
|
||||
|
||||
3. <input type="checkbox"/> Verify that bindings are being generated for your new
|
||||
API by generating the documentation and searching for the new API in it:
|
||||
|
||||
```sh
|
||||
cd crates/web-sys
|
||||
cargo doc --open
|
||||
# search for the new API in the opened docs
|
||||
```
|
||||
|
||||
* <input type="checkbox"/> If the new API is **not** showing up in the docs,
|
||||
rebuild the `web-sys` crate [with logging enabled](logging.html)
|
||||
and look for warning messages that mention your new API. Figure out why
|
||||
bindings weren't generated and then add support to `wasm_bindgen_webidl` for
|
||||
whatever is needed to generate your API's bindings.
|
||||
|
||||
> You might find it helpful to view the generated rust bindings, to see if
|
||||
> they are what you would expect. The file will be located at
|
||||
> `target/wasm32-unknown-unknown/debug/build/web-sys-xxx/out/bindings.rs`,
|
||||
> where `xxx` is a combinations of numbers and letters that represents your
|
||||
> build. This file is pretty unintelligable until you run `rustfmt` on it, like
|
||||
> `rustfmt target/wasm32-unknown-unknown/debug/build/web-sys-xxx/out/bindings.rs`.
|
||||
|
||||
> There are commented out lines in `web-sys/build.rs` that run rustfmt as part of
|
||||
> the build process, and this can be very helpful for debugging as any error
|
||||
> messages with inline code will display it in a readable format.
|
||||
|
||||
4. <input type="checkbox"/> Add tests for as many of the features in the WebIDL file
|
||||
as possible to `crates/web-sys/tests/all/`. See the
|
||||
[`web-sys` testing documentation](testing.html) for details.
|
||||
|
||||
> __Note__: Start here at __4__ if the WebIDL has already been added but doesn't have
|
||||
> full test coverage, then go back to __3__ if you find any problems.
|
||||
|
||||
5. <input type="checkbox"/> If all entities in the WebIDL file have full test coverage,
|
||||
mark the WebIDL script in the `README.md` file as complete by changing `[ ]` to `[x]`.
|
||||
|
||||
6. <input type="checkbox"/> Send a pull request! 😊
|
||||
You can then use `git diff` to ensure the bindings look correct.
|
||||
|
@ -5,20 +5,120 @@
|
||||
[online]: https://wasm-bindgen.netlify.app/exbuild/raytrace-parallel/
|
||||
[code]: https://github.com/rustwasm/wasm-bindgen/tree/master/examples/raytrace-parallel
|
||||
|
||||
**This is an unstable and experimental example** of using threads with
|
||||
WebAssembly and Rust, culminating in a parallel raytracer demo. The browser requirements are:
|
||||
This is an of using threads with WebAssembly, Rust, and `wasm-bindgen`,
|
||||
culminating in a parallel raytracer demo. There's a number of moving pieces to
|
||||
this demo and it's unfortunately not the easiest thing to wrangle, but it's
|
||||
hoped that this'll give you a bit of a taste of what it's like to use threads
|
||||
and wasm with Rust on the web.
|
||||
|
||||
* Firefox Nightly
|
||||
- `SharedArrayBuffer` is enabled in `about:config` in Firefox
|
||||
* Google Chrome
|
||||
- No flags required on recent versions of Chrome
|
||||
* other browsers haven't implemented the proposed WebAssembly features yet.
|
||||
### Building the demo
|
||||
|
||||
Locally to build this demo you'll need `xargo` and the `rust-src` rustup
|
||||
component, and afterwards `./build.sh` like other examples should build the
|
||||
example.
|
||||
One of the major gotchas with threaded WebAssembly is that Rust does not ship a
|
||||
precompiled target (e.g. standard library) which has threading support enabled.
|
||||
This means that you'll need to recompile the standard library with the
|
||||
appropriate rustc flags, namely `-C target-feature=+atomics,+bulk-memory`.
|
||||
|
||||
Again, to reiterate, this is all experimental and we're working through various
|
||||
issues as we're working on this. If you're curious to see how this works it's
|
||||
best to explore via the source code right now! More info will be available here
|
||||
once WebAssembly threads are closer to stabilization.
|
||||
To do this you can use the `RUSTFLAGS` environment variable that Cargo reads:
|
||||
|
||||
```sh
|
||||
export RUSTFLAGS='-C target-feature=+atomics,+bulk-memory'
|
||||
```
|
||||
|
||||
To recompile the standard library it's recommended to use Cargo's
|
||||
[`-Zbuild-std`](https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#build-std)
|
||||
feature:
|
||||
|
||||
```sh
|
||||
cargo build --target wasm32-unknown-unknown -Z build-std=panic_abort,std
|
||||
```
|
||||
|
||||
Note that you can also configure this via `.cargo/config.toml`:
|
||||
|
||||
```toml
|
||||
[unstable]
|
||||
build-std = ['std', 'panic_abort']
|
||||
|
||||
[build]
|
||||
target = "wasm32-unknown-unknown"
|
||||
rustflags = '-Ctarget-feature=+atomics,+bulk-memory'
|
||||
```
|
||||
|
||||
After this `cargo build` should produce a WebAssembly file with threading
|
||||
enabled, and the standard library will be appropriately compiled as well.
|
||||
|
||||
The final step in this is to run `wasm-bindgen` as usual, and `wasm-bindgen`
|
||||
needs no extra configuration to work with threads. You can continue to run it
|
||||
through `wasm-pack`, for example.
|
||||
|
||||
### Running the demo
|
||||
|
||||
Currently it's required to use the `--target no-modules` flag with
|
||||
`wasm-bindgen` to run threaded code. This is because the WebAssembly file
|
||||
imports memory instead of exporting it, so we need to hook initialization of the
|
||||
wasm module at this time to provide the appropriate memory object.
|
||||
|
||||
With `--target no-modules` you'll be able to use `importScripts` inside of each
|
||||
web worker to import the shim JS generated by `wasm-bindgen` as well as calling
|
||||
the `wasm_bindgen` initialization function with the shared memory instance from
|
||||
the main thread. The expected usage is that WebAssembly on the main thread will
|
||||
post its memory object to all other threads to get instantiated with.
|
||||
|
||||
### Caveats
|
||||
|
||||
Unfortunately at this time running wasm on the web with threads has a number of
|
||||
caveats, although some are specific to just `wasm-bindgen`. These are some
|
||||
pieces to consider and watch out for, although we're always looking for
|
||||
improvements to be made so if you have an idea please file an issue!
|
||||
|
||||
* The main thread in a browser cannot block. This means that if you run
|
||||
WebAssembly code on the main thread you can *never* block, meaning you can't
|
||||
do so much as acquire a mutex. This is an extremely difficult limitation to
|
||||
work with on the web, although one workaround is to run wasm exclusively in
|
||||
web workers and run JS on the main thread. It is possible to run the same wasm
|
||||
across all threads, but you need to be extremely vigilant about
|
||||
synchronization with the main thread.
|
||||
|
||||
* Setting up a threaded environment is a bit wonky and doesn't feel smooth
|
||||
today. For example `--target no-modules` is required with `wasm-bindgen` and
|
||||
very specific shims are required on both the main thread and worker threads.
|
||||
These are possible to work with but are somewhat brittle since there's no
|
||||
standard way to spin up web workers as wasm threads.
|
||||
|
||||
* There is no standard notion of a "thread". For example the standard library
|
||||
has no viable route to implement the `std::thread` module. As a consequence
|
||||
there is no concept of thread exit and TLS destructors will never run. With no
|
||||
concept of a thread exit thread stacks will also never be deallocated.
|
||||
Currently the intention is that with threaded wasm a pool of threads will be
|
||||
used but that pool is initialized once and never changes over time, since
|
||||
resources are never reclaimed from it. Much of this has to do with the
|
||||
`#[wasm_bindgen]`-specific handling of threads. You can get more advanced, but
|
||||
at that point you may have to not use `wasm-bindgen` as well.
|
||||
|
||||
* Web Workers executing WebAssembly code cannot receive events from JS. A Web
|
||||
Worker has to fully return back to the browser (and ideally should do so
|
||||
occasionally) to receive JS messages and such. This means that common
|
||||
paradigms like a rayon thread pool do not apply straightforward-ly to the web.
|
||||
The intention of the web is that all long-term blocking happens in the browser
|
||||
itself, not in each thread, but many crates in the ecosystem leveraging
|
||||
threading are not necessarily engineered this way.
|
||||
|
||||
These caveats are all largely inherited from the web platform itself, and
|
||||
they're important to consider when designing an application for threading. It's
|
||||
highly unlikely that you can pull a crate off the shelf and "just use it" due to
|
||||
these limitations. You'll need to be sure to carefully plan ahead and ensure
|
||||
that gotchas such as these don't cause issues in the future. As mentioned before
|
||||
though we're always trying to actively develop this support so if folks have
|
||||
ideas about how to improve, or if web standards change, we'll try to update this
|
||||
documentation!
|
||||
|
||||
### Browser Requirements
|
||||
|
||||
This demo should work in the latest Firefox and Chrome versions at this time,
|
||||
and other browsers are likely to follow suit. Note that threads and
|
||||
`SharedArrayBuffer` require HTTP headers to be set to work correctly. For more
|
||||
information see the [documentation on
|
||||
MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/SharedArrayBuffer)
|
||||
under "Security requirements" as well as [Firefox's rollout blog
|
||||
post](https://hacks.mozilla.org/2020/07/safely-reviving-shared-memory/). This
|
||||
means that during local development you'll need to configure your web server
|
||||
appropriately or enable a workaround in your browser.
|
||||
|
Loading…
Reference in New Issue
Block a user