diff --git a/Cargo.toml b/Cargo.toml index 2ce49eb48..7903a6cfa 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -58,11 +58,9 @@ members = [ "crates/webidl", "crates/webidl-tests", "examples/add", - "examples/asm.js", "examples/canvas", "examples/char", "examples/closures", - "examples/comments", "examples/console_log", "examples/duck-typed-interfaces", "examples/dom", @@ -71,12 +69,11 @@ members = [ "examples/hello_world", "examples/import_js", "examples/julia_set", - "examples/math", "examples/no_modules", "examples/paint", "examples/performance", - "examples/smorgasboard", "examples/wasm-in-wasm", + "examples/wasm2js", "examples/webaudio", "examples/webgl", "tests/no-std", diff --git a/crates/js-sys/src/lib.rs b/crates/js-sys/src/lib.rs index c7501da48..0dd9c5be6 100644 --- a/crates/js-sys/src/lib.rs +++ b/crates/js-sys/src/lib.rs @@ -1753,6 +1753,13 @@ extern "C" { #[wasm_bindgen(constructor)] pub fn new(init: &JsValue) -> Date; + /// Creates a JavaScript Date instance that represents the current moment in + /// time. + /// + /// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date) + #[wasm_bindgen(constructor)] + pub fn new_0() -> Date; + /// The `Date.now()` method returns the number of milliseconds /// elapsed since January 1, 1970 00:00:00 UTC. /// diff --git a/crates/macro/ui-tests/Cargo.toml b/crates/macro/ui-tests/Cargo.toml index ce105e8c2..3b51ff0ac 100644 --- a/crates/macro/ui-tests/Cargo.toml +++ b/crates/macro/ui-tests/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "ui-tests" version = "0.1.0" -authors = ["The wasm-bindgen Authors"] +authors = ["The wasm-bindgen Developers"] [lib] path = "test.rs" diff --git a/crates/test/sample/Cargo.toml b/crates/test/sample/Cargo.toml index 591e147ea..de4f27560 100644 --- a/crates/test/sample/Cargo.toml +++ b/crates/test/sample/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "sample" version = "0.1.0" -authors = ["The wasm-bindgen Authors"] +authors = ["The wasm-bindgen Developers"] [lib] test = false diff --git a/crates/webidl-tests/Cargo.toml b/crates/webidl-tests/Cargo.toml index 8c5b2ede8..e8c022c83 100644 --- a/crates/webidl-tests/Cargo.toml +++ b/crates/webidl-tests/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "webidl-tests" version = "0.1.0" -authors = ["The wasm-bindgen authors"] +authors = ["The wasm-bindgen Developers"] [lib] test = false diff --git a/examples/README.md b/examples/README.md index f4467e5bd..1f2e50eec 100644 --- a/examples/README.md +++ b/examples/README.md @@ -1,42 +1,7 @@ # Examples -This directory contains a number of examples of the `#[wasm_bindgen]` macro and -how to display them in the browser. Each directory contains a README with a link -to https://webassembly.studio so you can also explore the example online -(apologies if they're out of sync!), and each directory also contains a -`build.sh` which assembles all the relevant files locally. If you open up -`index.html` in a web browser you should be able to see everything in action -when using `build.sh`! +This directory contains a number of Cargo projects that are all examples of how +to use `wasm-bindgen` in various contexts. More documentation can be [found +online][dox] -The examples here are: - -* `add` - an example of generating a tiny wasm binary, one that only adds two - numbers. -* `asm.js` - an example of using the `wasm2js` tool from [binaryen] to convert - the generated WebAssembly to normal JS -* `char` - an example of passing the rust `char` type to and from the js `string` type -* `closures` - an example of how to invoke functions like `setInterval` or use - the `onclick` property in conjunction with closures. -* `comments` - an example of how Rust comments are copied into js bindings -* `console_log` - a showcase of `#[wasm_bindgen]` importing classes and how to - bind `console.log` -* `dom` - an example of accessing the global `document` object and appending - HTML to it -* `fetch` -- how to use the Fetch API to make async http requests -* `hello_world` - the "hello world" of `#[wasm_bindgen]`, aka throwing up a - dialog greeting you -* `import_js` - an example of importing local JS functionality into a crate -* `math` - like `console_log` except showing how to import Math-related - functions instead -* `no_modules` - an example of how to use the `--no-modules` flag to - the `wasm-bindgen` CLI tool -* `performance` - how to import APIs like `performance.now()` and time various - operations in Rust -* `smorgasboard` - a bunch of features all thrown into one, showing off the - various capabilities of the `#[wasm_bindgen]` macro and what you can do with - it from JS -* `wasm-in-wasm` - how to interact with namespaced APIs like - `WebAssembly.Module` and shows off creation of a WebAssembly module from Rust -* `webaudio` - how to use the Web Audio APIs to generate sounds - -[binaryen]: https://github.com/WebAssembly/binaryen +[dox]: https://rustwasm.github.io/wasm-bindgen/examples/index.html diff --git a/examples/add/README.md b/examples/add/README.md index a1f75d4eb..5bf9743b9 100644 --- a/examples/add/README.md +++ b/examples/add/README.md @@ -1,12 +1,10 @@ -# Adding Numbers +# Adding numbers (small wasm files) -[View this example online](https://webassembly.studio/?f=612vwsrmwft) +[View documentation for this example online][dox] -This directory is an example of using the `#[wasm_bindgen]` macro to simply add -two numbers. The neat part about this is that it's an example of how to generate -the smallest wasm-bindgen binary. +[dox]: https://rustwasm.github.io/wasm-bindgen/examples/add.html -You can build the example with: +You can build the example locally with: ``` $ ./build.sh @@ -14,48 +12,4 @@ $ ./build.sh (or running the commands on Windows manually) -Currently this generates a 651 byte wasm binary: - -``` -$ ls -alh add_bg.wasm --rw-rw-r-- 1 alex alex 651 Apr 20 22:16 add_bg.wasm -``` - -If you run [wasm-opt], a C++ tool for optimize WebAssembly, you can make it even -smaller too! - -``` -$ wasm-opt -Os add_bg.wasm -o add.wasm -$ ls -alh add.wasm --rw-rw-r-- 1 alex alex 100 Apr 20 22:19 add.wasm -``` - -And sure enough, using the [wasm2wat] tool it's quite small! - -``` -$ wasm2wat add.wasm -(module - (type (;0;) (func (param i32 i32) (result i32))) - (func (;0;) (type 0) (param i32 i32) (result i32) - get_local 1 - get_local 0 - i32.add) - (memory (;0;) 2) - (export "memory" (memory 0)) - (export "add" (func 0)) -(data (i32.const 1545) "invalid malloc request")) -``` - -Note that it's important to point out that the size reductions here are because -the wasm is compiled in release mode by the build script and this crate's -workspace has the following configuration - -```toml -[profile.release] -lto = true -opt-level = 's' -panic = 'abort' -``` - -[wasm2wat]: https://github.com/webassembly/wabt -[wasm-opt]: https://github.com/webassembly/binaryen +and then visiting http://localhost:8080 in a browser should run the example! diff --git a/examples/asm.js/README.md b/examples/asm.js/README.md deleted file mode 100644 index fa347257a..000000000 --- a/examples/asm.js/README.md +++ /dev/null @@ -1,19 +0,0 @@ -# WebAssembly to asm.js - -This directory is an example of using [binaryen]'s `wasm2js` tool to convert -the wasm output of `wasm-bindgen` to a normal JS file that can be executed like -asm.js. - -You can build the example locally with: - -``` -$ ./build.sh -``` - -When opened in a web browser this should print "Hello, World!" to the console. - -Note that the `wasm2js` tool is still pretty early days so there's likely to be -a number of bugs to run into or work around. If any are encountered though -please feel free to report them upstream! - -[binaryen]: https://github.com/WebAssembly/binaryen diff --git a/examples/asm.js/index.js b/examples/asm.js/index.js deleted file mode 100644 index 647c31e31..000000000 --- a/examples/asm.js/index.js +++ /dev/null @@ -1,3 +0,0 @@ -import { run } from './asmjs'; - -run(); diff --git a/examples/canvas/.gitignore b/examples/canvas/.gitignore index b2450cc7c..a5e6169e7 100644 --- a/examples/canvas/.gitignore +++ b/examples/canvas/.gitignore @@ -1,4 +1,4 @@ package-lock.json -wasm_bindgen_canvas_demo.js -wasm_bindgen_canvas_demo_bg.js -wasm_bindgen_canvas_demo_bg.wasm +canvas.js +canvas_bg.js +canvas_bg.wasm diff --git a/examples/canvas/Cargo.toml b/examples/canvas/Cargo.toml index 2f3420b02..3966d127e 100644 --- a/examples/canvas/Cargo.toml +++ b/examples/canvas/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "wasm-bindgen-canvas-demo" +name = "canvas" version = "0.1.0" authors = ["The wasm-bindgen Developers"] diff --git a/examples/canvas/README.md b/examples/canvas/README.md index a5cf37735..914f1b697 100644 --- a/examples/canvas/README.md +++ b/examples/canvas/README.md @@ -1,9 +1,10 @@ -# Canvas 2D Example +# 2D Canvas -This directory is an example of using the `web-sys` crate to draw on a 2D -canvas. +[View documentation for this example online][dox] -You can build and run the example with: +[dox]: https://rustwasm.github.io/wasm-bindgen/examples/2d-canvas.html + +You can build the example locally with: ``` $ ./build.sh @@ -11,5 +12,4 @@ $ ./build.sh (or running the commands on Windows manually) -and then opening up `http://localhost:8080/` in a web browser should show a -smiley face drawn on canvas by Rust and WebAssembly. +and then visiting http://localhost:8080 in a browser should run the example! diff --git a/examples/canvas/build.sh b/examples/canvas/build.sh index f9273ed42..d6313df38 100755 --- a/examples/canvas/build.sh +++ b/examples/canvas/build.sh @@ -9,7 +9,7 @@ cargo +nightly build --target wasm32-unknown-unknown cargo +nightly run --manifest-path ../../crates/cli/Cargo.toml \ --bin wasm-bindgen -- \ - ../../target/wasm32-unknown-unknown/debug/wasm_bindgen_canvas_demo.wasm --out-dir . + ../../target/wasm32-unknown-unknown/debug/canvas.wasm --out-dir . npm install npm run serve diff --git a/examples/canvas/index.html b/examples/canvas/index.html index c13b999e4..319ffd0ed 100644 --- a/examples/canvas/index.html +++ b/examples/canvas/index.html @@ -4,6 +4,5 @@ - diff --git a/examples/canvas/index.js b/examples/canvas/index.js index f46718050..4372fcf65 100644 --- a/examples/canvas/index.js +++ b/examples/canvas/index.js @@ -1,5 +1,5 @@ // For more comments about what's going on here, check out the `hello_world` // example. -import('./wasm_bindgen_canvas_demo').then(canvas => { +import('./canvas').then(canvas => { canvas.draw(); }); diff --git a/examples/char/README.md b/examples/char/README.md index 69a64d9a6..f61c53712 100644 --- a/examples/char/README.md +++ b/examples/char/README.md @@ -1,6 +1,8 @@ -# Char +# Working with the `char` type -This directory is an example of how the `#[wasm_bindgen]` macro will convert the rust `char` type to a single code-point js `string`. +[View documentation for this example online][dox] + +[dox]: https://rustwasm.github.io/wasm-bindgen/examples/char.html You can build the example locally with: @@ -8,6 +10,6 @@ You can build the example locally with: $ ./build.sh ``` -Opening your web browser should display a single counter with a random character for it's `key` and 0 for its `count`. You can click the `+` button to increase a counter's count. By clicking on the "add counter" button you should see a new counter added to the list with a different random character for it's `key`. +(or running the commands on Windows manually) -Under the hood javascript is choosing a random character from an Array of characters and passing that to the rust Counter struct's constructor so the character you are seeing on the page has made the full round trip from js to rust and back to js. \ No newline at end of file +and then visiting http://localhost:8080 in a browser should run the example! diff --git a/examples/char/chars.js b/examples/char/chars-list.js similarity index 100% rename from examples/char/chars.js rename to examples/char/chars-list.js diff --git a/examples/char/index.html b/examples/char/index.html index a60f86985..7cec14e9f 100644 --- a/examples/char/index.html +++ b/examples/char/index.html @@ -32,7 +32,7 @@ align-content: flex-start; } .counter { - margin-bottom: 10px; + margin-bottom: 10px; background: steelblue; color: white; align-items: center; @@ -49,8 +49,7 @@
- +
- - \ No newline at end of file + diff --git a/examples/char/index.js b/examples/char/index.js index d5adbf2f5..bf2b371be 100644 --- a/examples/char/index.js +++ b/examples/char/index.js @@ -1,5 +1,5 @@ /* eslint-disable no-unused-vars */ -import {chars} from './chars.js'; +import { chars } from './chars-list.js'; let imp = import('./char.js'); let mod; @@ -71,4 +71,4 @@ function newField(key, value) { val.appendChild(document.createTextNode(value)); ret.appendChild(val); return ret; -} \ No newline at end of file +} diff --git a/examples/char/src/lib.rs b/examples/char/src/lib.rs index 52dedf1ad..0d108df94 100644 --- a/examples/char/src/lib.rs +++ b/examples/char/src/lib.rs @@ -2,6 +2,7 @@ extern crate wasm_bindgen; use wasm_bindgen::prelude::*; +// lifted from the `console_log` example #[wasm_bindgen] extern "C" { #[wasm_bindgen(js_namespace = console)] diff --git a/examples/closures/Cargo.toml b/examples/closures/Cargo.toml index e33f3ac80..ba32397b3 100644 --- a/examples/closures/Cargo.toml +++ b/examples/closures/Cargo.toml @@ -9,3 +9,13 @@ crate-type = ["cdylib"] [dependencies] wasm-bindgen = { path = "../..", features = ['nightly'] } js-sys = { path = "../../crates/js-sys" } + +[dependencies.web-sys] +path = "../../crates/web-sys" +features = [ + 'CssStyleDeclaration', + 'Document', + 'Element', + 'HtmlElement', + 'Window', +] diff --git a/examples/closures/README.md b/examples/closures/README.md index 25d1613b8..7489e6e5b 100644 --- a/examples/closures/README.md +++ b/examples/closures/README.md @@ -1,11 +1,10 @@ -# Closure examples +# web-sys: Closures -[View this example online](https://webassembly.studio/?f=g3hc1qs6tka) +[View documentation for this example online][dox] -This directory is an example of using the `#[wasm_bindgen]` macro with closures -to interact with the DOM. +[dox]: https://rustwasm.github.io/wasm-bindgen/examples/closures.html -You can build the example with: +You can build the example locally with: ``` $ ./build.sh @@ -13,10 +12,4 @@ $ ./build.sh (or running the commands on Windows manually) -and then opening up `index.html` in a web browser should show a hello message on -the web page generated by the wasm. - -For more information about this example be sure to check out -[`hello_world`][hello] which also has more comments about caveats and such. - -[hello]: https://github.com/alexcrichton/wasm-bindgen/tree/master/examples/hello_world +and then visiting http://localhost:8080 in a browser should run the example! diff --git a/examples/closures/index.html b/examples/closures/index.html index e0b1d36a6..2926298e7 100644 --- a/examples/closures/index.html +++ b/examples/closures/index.html @@ -35,6 +35,5 @@ times

- diff --git a/examples/closures/src/lib.rs b/examples/closures/src/lib.rs index 3aa0c30ec..09d0db80d 100755 --- a/examples/closures/src/lib.rs +++ b/examples/closures/src/lib.rs @@ -1,74 +1,88 @@ extern crate wasm_bindgen; extern crate js_sys; +extern crate web_sys; -use js_sys::Date; +use js_sys::{Date, Array}; +use wasm_bindgen::JsCast; use wasm_bindgen::prelude::*; +use web_sys::{Document, Element, HtmlElement, Window}; #[wasm_bindgen] -extern "C" { - // Binding for the `setInverval` method in JS. This function takes a "long - // lived" closure as the first argument so we use `Closure` instead of - // a bare `&Fn()` which only surives for that one stack frame. - // - // The second argument is then the interval and the return value is how we - // clear this interval. We're not going to clear our interval in this - // example though so the return value is ignored. - #[wasm_bindgen(js_name = setInterval)] - fn set_interval(cb: &Closure, delay: u32) -> f64; +pub fn run() -> Result<(), JsValue> { + let window = web_sys::window().expect("should have a window in this context"); + let document = window.document().expect("window should have a document"); - // Bindings for `document` and various methods of updating HTML elements. - // Like with the `dom` example these'll ideally be upstream in a generated - // crate one day but for now we manually define them. - type HTMLDocument; - static document: HTMLDocument; - #[wasm_bindgen(method, js_name = getElementById)] - fn get_element_by_id(this: &HTMLDocument, id: &str) -> Element; - #[wasm_bindgen(method, js_name = getElementById)] - fn get_html_element_by_id(this: &HTMLDocument, id: &str) -> HTMLElement; + // One of the first interesting things we can do with closures is simply + // access stack data in Rust! + let array = Array::new(); + array.push(&"Hello".into()); + array.push(&1.into()); + let mut first_item = None; + array.for_each(&mut |obj, idx, _arr| { + match idx { + 0 => { + assert_eq!(obj, "Hello"); + first_item = obj.as_string(); + } + 1 => assert_eq!(obj, 1), + _ => panic!("unknown index: {}", idx) + } + }); + assert_eq!(first_item, Some("Hello".to_string())); - type Element; - #[wasm_bindgen(method, setter = innerHTML)] - fn set_inner_html(this: &Element, html: &str); + // Below are some more advanced usages of the `Closure` type for closures + // that need to live beyond our function call. - type HTMLElement; - #[wasm_bindgen(method, setter)] - fn set_onclick(this: &HTMLElement, cb: &Closure); - #[wasm_bindgen(method, getter)] - fn style(this: &HTMLElement) -> CSS2Properties; + setup_clock(&window, &document)?; + setup_clicker(&document); - type CSS2Properties; - #[wasm_bindgen(method, setter)] - fn set_display(this: &CSS2Properties, display: &str); + // And now that our demo is ready to go let's switch things up so + // everything is displayed and our loading prompt is hidden. + document + .get_element_by_id("loading") + .expect("should have #loading on the page") + .dyn_ref::() + .expect("#loading should be an `HtmlElement`") + .style() + .set_property("display", "none")?; + document + .get_element_by_id("script") + .expect("should have #script on the page") + .dyn_ref::() + .expect("#script should be an `HtmlElement`") + .style() + .set_property("display", "block")?; + + Ok(()) } -#[wasm_bindgen] -pub fn run() { - // Set up a clock on our page and update it each second to ensure it's got - // an accurate date. - let a = Closure::new(update_time); - set_interval(&a, 1000); - update_time(); - fn update_time() { - document - .get_element_by_id("current-time") +// Set up a clock on our page and update it each second to ensure it's got +// an accurate date. +// +// Note the usage of `Closure` here because the closure is "long lived", +// basically meaning it has to persist beyond the call to this one function. +// Also of note here is the `.as_ref().unchecked_ref()` chain, which is who +// you can extract `&Function`, what `web-sys` expects, from a `Closure` +// which only hands you `&JsValue` via `AsRef`. +fn setup_clock(window: &Window, document: &Document) -> Result<(), JsValue> { + let current_time = document + .get_element_by_id("current-time") + .expect("should have #current-time on the page"); + update_time(¤t_time); + let a = Closure::wrap(Box::new(move || { + update_time(¤t_time) + }) as Box); + window.set_interval_with_callback_and_timeout_and_arguments_0( + a.as_ref().unchecked_ref(), + 1000, + )?; + fn update_time(current_time: &Element) { + current_time .set_inner_html(&String::from( - Date::new(&JsValue::undefined()) - .to_locale_string("en-GB", &JsValue::undefined()), + Date::new_0().to_locale_string("en-GB", &JsValue::undefined()), )); } - // We also want to count the number of times that our green square has been - // clicked. Our callback will update the `#num-clicks` div - let square = document.get_html_element_by_id("green-square"); - let mut clicks = 0; - let b = Closure::new(move || { - clicks += 1; - document - .get_element_by_id("num-clicks") - .set_inner_html(&clicks.to_string()); - }); - square.set_onclick(&b); - // The instances of `Closure` that we created will invalidate their // corresponding JS callback whenever they're dropped, so if we were to // normally return from `run` then both of our registered closures will @@ -79,16 +93,29 @@ pub fn run() { // `forget` method to drop them without invalidating the closure. Note that // this is leaking memory in Rust, so this should be done judiciously! a.forget(); - b.forget(); - // And finally now that our demo is ready to go let's switch things up so - // everything is displayed and our loading prompt is hidden. - document - .get_html_element_by_id("loading") - .style() - .set_display("none"); - document - .get_html_element_by_id("script") - .style() - .set_display("block"); + Ok(()) +} + +// We also want to count the number of times that our green square has been +// clicked. Our callback will update the `#num-clicks` div. +// +// This is pretty similar above, but showing how closures can also implement +// `FnMut()`. +fn setup_clicker(document: &Document) { + let num_clicks = document + .get_element_by_id("num-clicks") + .expect("should have #num-clicks on the page"); + let mut clicks = 0; + let a = Closure::wrap(Box::new(move || { + clicks += 1; + num_clicks.set_inner_html(&clicks.to_string()); + }) as Box); + document + .get_element_by_id("green-square") + .expect("should have #green-square on the page") + .dyn_ref::() + .expect("#green-square be an `HtmlElement`") + .set_onclick(Some(a.as_ref().unchecked_ref())); + a.forget(); } diff --git a/examples/comments/Cargo.toml b/examples/comments/Cargo.toml deleted file mode 100644 index 521547e49..000000000 --- a/examples/comments/Cargo.toml +++ /dev/null @@ -1,14 +0,0 @@ -[package] -name = "comments" -version = "0.1.0" -authors = ["robert masen "] - -[dependencies] -# Here we're using a path dependency to use what's already in this repository, -# but you'd use the commented out version below if you're copying this into your -# project. -wasm-bindgen = { path = "../.." } -#wasm-bindgen = "0.2" - -[lib] -crate-type = ['cdylib'] \ No newline at end of file diff --git a/examples/comments/README.md b/examples/comments/README.md deleted file mode 100644 index 968b4f9c8..000000000 --- a/examples/comments/README.md +++ /dev/null @@ -1,16 +0,0 @@ -# Comments - -This directory is an example of how the `#[wasm_bindgen]` macro will -move your Rust doc comments to [JSDoc](http://usejsdoc.org/) comments - -You can build the example locally with: - -``` -$ ./build.sh -``` - -(or running the two commands on Windows manually) - -You should see the doc comments have been copied into the `comments.js` file. - -If you wanted to run the project itself, simply run `npm run serve` \ No newline at end of file diff --git a/examples/comments/build.sh b/examples/comments/build.sh deleted file mode 100755 index e70c1389c..000000000 --- a/examples/comments/build.sh +++ /dev/null @@ -1,20 +0,0 @@ -#!/bin/sh - -set -ex -# Build the comments project -cargo +nightly build --target wasm32-unknown-unknown - -# Run the `wasm-bindgen` CLI tool to postprocess the wasm file emitted by the -# Rust compiler to emit the JS support glue that's necessary -# -# Here we're using the version of the CLI in this repository, but for external -# usage you'd use the commented out version below -cargo +nightly run --manifest-path ../../crates/cli/Cargo.toml \ - --bin wasm-bindgen -- \ - ../../target/wasm32-unknown-unknown/debug/comments.wasm --out-dir . -# wasm-bindgen ../../target/wasm32-unknown-unknown/hello_world.wasm --out-dir . - -# Finally, package everything up using Webpack and start a server so we can -# browse the result -npm install -npm run serve \ No newline at end of file diff --git a/examples/comments/index.html b/examples/comments/index.html deleted file mode 100644 index 4e42b1fc3..000000000 --- a/examples/comments/index.html +++ /dev/null @@ -1,90 +0,0 @@ - - - - - - -
-
-
-
- - -
-
- - -
- -
- -
- - - diff --git a/examples/comments/index.js b/examples/comments/index.js deleted file mode 100644 index 72caa2cd9..000000000 --- a/examples/comments/index.js +++ /dev/null @@ -1,141 +0,0 @@ -/* eslint-disable no-unused-vars */ -const mod = import('./comments'); -let wasm; -mod.then(m => { - wasm = m; - let button = document.getElementById('add-comment-button'); - if (!button) return console.error('Unable to find add button'); - button.addEventListener('click', newComment); - displayComments(); -}); - -/** - * Click event handler for add button - * @param {MouseEvent} ev - */ -function newComment(ev) { - clearError(); - let name = document.getElementById('name'); - if (!name) return console.error('Failed to find name input'); - if (name.value == '') return displayError('Name cannot be blank'); - let comment = document.getElementById('comment'); - if (!comment) return console.error('Failed to find comment input'); - if (comment.value == '') return displayError('comment cannot be blank'); - addComment(name.value, comment.value); - name.form.reset(); - displayComments(); -} - -/** - * Add a comment to the list - * @param {string} name The name of the person submitting - * @param {string} content The actual text of the comment - */ -function addComment(name, content) { - let existing = comments(); - let count = existing.length; - existing.push(new wasm.Comment(name, content, count)); - storeComments(); -} - -/** - * Convert the rust comments to JSON comments and store - * in local storage - */ -function storeComments() { - let json = comments().map(c => { - console.log('mapping comments for storage', c); - return { - name: c.name(), - comment: c.comment(), - count: c.count, - }; - }); - localStorage.setItem('comments', JSON.stringify(json)); -} -/** - * Get the comments from local storage and convert them to - * rust comments - */ -function getComments() { - let json = localStorage.getItem('comments'); - if (!json) return []; - let raw = JSON.parse(json); - return raw.map(c => new wasm.Comment(c.name, c.comment, c.count)); -} - -/**A in memory cache of the localStorage comments for this site */ -let cachedComments = null; -/** - * Get a list of comments for this page - * @param {boolean} refresh force a refresh from localStorage - */ -function comments(refresh = false) { - if (refresh || !cachedComments) { - cachedComments = getComments(); - } - return cachedComments; -} - -/** - * Clear the comments section and re-render with the - * current comments list - */ -function displayComments() { - let node = document.getElementById('comments'); - if (!node) return console.error('Failed to get comments container'); - while (node.hasChildNodes()) { - node.removeChild(node.lastChild); - } - for (let comment of comments()) { - node.appendChild(renderComment(comment)); - } -} - -/** - * Generate the HTML needed to display a single comment - * @param {Comment} comment the comment to display - * @returns {HTMLDivElement} The div containing the comment html - */ -function renderComment(comment) { - let cls = `comment ${comment.color() == wasm.Color.Blue ? 'blue' : 'pink'}`; - let div = document.createElement('div'); - div.setAttribute('class', cls); - let top = document.createElement('div'); - top.setAttribute('class', 'comment-top'); - let ct = document.createElement('span'); - ct.setAttribute('class', 'count'); - ct.appendChild(document.createTextNode(`${comment.count}:`)); - let name = document.createElement('span'); - name.setAttribute('class', 'user-name'); - name.appendChild(document.createTextNode(`${comment.name()}`)); - top.appendChild(ct); - top.appendChild(name); - let bottom = document.createElement('div'); - bottom.setAttribute('class', 'comment-bottom'); - let title = document.createElement('span'); - title.setAttribute('class', 'comment-title'); - title.appendChild(document.createTextNode('comment')); - bottom.appendChild(title); - let text = document.createElement('span'); - text.setAttribute('class', 'comment-text'); - text.appendChild(document.createTextNode(comment.comment())); - bottom.appendChild(text); - div.appendChild(top); - div.appendChild(bottom); - return div; -} - -function displayError(message) { - let e = document.getElementById('error'); - if (!e) return console.error('Failed to find error container'); - if (e.innerHTML != '') return setTimeout(displayError, 1000, message); - e.innerHTML = message; - setTimeout(clearError, 3000); -} - -function clearError() { - let e = document.getElementById('error'); - if (!e) return console.error('Failed to find error container'); - e.innerHTML = ''; -} \ No newline at end of file diff --git a/examples/comments/package.json b/examples/comments/package.json deleted file mode 100644 index b5564ba6f..000000000 --- a/examples/comments/package.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "scripts": { - "serve": "webpack-dev-server" - }, - "devDependencies": { - "html-webpack-plugin": "^3.2.0", - "webpack": "^4.8.1", - "webpack-cli": "^2.0.10", - "webpack-dev-server": "^3.1.0" - } -} diff --git a/examples/comments/src/lib.rs b/examples/comments/src/lib.rs deleted file mode 100644 index cc0a7e123..000000000 --- a/examples/comments/src/lib.rs +++ /dev/null @@ -1,57 +0,0 @@ -extern crate wasm_bindgen; - -use wasm_bindgen::prelude::*; - -#[wasm_bindgen] -/// A user defined comment -pub struct Comment { - name: String, - comment: String, - /// The position this comment - /// should exist at - pub count: u32, - color: Color, -} - -#[wasm_bindgen] -impl Comment { - #[wasm_bindgen(method)] - /// The name of the user who - /// posted this comment - pub fn name(&self) -> String { - self.name.clone() - } - #[wasm_bindgen(method)] - /// The content of this comment - pub fn comment(&self) -> String { - self.comment.clone() - } - - #[wasm_bindgen(constructor)] - pub fn new(name: String, comment: String, count: u32) -> Comment { - let color = if count % 2 == 0 { - Color::Blue - } else { - Color::Pink - }; - Comment { - name, - comment, - count, - color, - } - } - #[wasm_bindgen(method)] - /// What color should this comment be - pub fn color(&self) -> Color { - self.color.clone() - } -} - -/// The border of a comment -#[wasm_bindgen] -#[derive(Clone)] -pub enum Color { - Blue, - Pink, -} diff --git a/examples/comments/webpack.config.js b/examples/comments/webpack.config.js deleted file mode 100644 index f672f58b4..000000000 --- a/examples/comments/webpack.config.js +++ /dev/null @@ -1,17 +0,0 @@ -const path = require('path'); -const HtmlWebpackPlugin = require('html-webpack-plugin'); - -module.exports = { - entry: './index.js', - output: { - path: path.resolve(__dirname, 'dist'), - filename: 'index.js', - }, - plugins: [ - new HtmlWebpackPlugin({ - template: "index.html" - }) - ], - mode: 'development', - devtool: 'source-map', -}; diff --git a/examples/console_log/Cargo.toml b/examples/console_log/Cargo.toml index 25761c2d1..0976b4bde 100644 --- a/examples/console_log/Cargo.toml +++ b/examples/console_log/Cargo.toml @@ -8,3 +8,4 @@ crate-type = ["cdylib"] [dependencies] wasm-bindgen = { path = "../.." } +web-sys = { path = '../../crates/web-sys' } diff --git a/examples/console_log/README.md b/examples/console_log/README.md index dec3ea2e8..ab99aaada 100644 --- a/examples/console_log/README.md +++ b/examples/console_log/README.md @@ -1,13 +1,10 @@ # `console.log` -[View this example online](https://webassembly.studio/?f=ppd7u8k9i9) +[View documentation for this example online][dox] +[dox]: https://rustwasm.github.io/wasm-bindgen/examples/console-log.html -This directory is an example of two ways to get access to the `console.log` function. -The first way uses the `#[wasm_bindgen]` macro to import the function and call it. -The second way uses the binding from the `web-sys` crate. - -You can build the example with: +You can build the example locally with: ``` $ ./build.sh @@ -15,9 +12,4 @@ $ ./build.sh (or running the commands on Windows manually) -and then opening up `index.html` in a web browser should show a dialog! - -For more information about this example be sure to check out -[`hello_world`][hello] which also has more comments about caveats and such. - -[hello]: https://github.com/rustwasm/wasm-bindgen/tree/master/examples/hello_world +and then visiting http://localhost:8080 in a browser should run the example! diff --git a/examples/console_log/index.html b/examples/console_log/index.html index 14e4ff723..e83a75f92 100644 --- a/examples/console_log/index.html +++ b/examples/console_log/index.html @@ -3,7 +3,6 @@ -

Open up the developer console and you should see "Hello from Rust!"

diff --git a/examples/console_log/src/lib.rs b/examples/console_log/src/lib.rs index b32bd7a27..b03de921d 100644 --- a/examples/console_log/src/lib.rs +++ b/examples/console_log/src/lib.rs @@ -1,21 +1,69 @@ extern crate wasm_bindgen; +extern crate web_sys; use wasm_bindgen::prelude::*; -// ... or you can manually write the bindings yourself +#[wasm_bindgen] +pub fn run() { + bare_bones(); + using_a_macro(); + using_web_sys(); +} + +// First up let's take a look of binding `console.log` manually, without the +// help of `web_sys`. Here we're writing the `#[wasm_bindgen]` annotations +// manually ourselves, and the correctness of our program relies on the +// correctness of these annotations! + #[wasm_bindgen] extern "C" { + // Use `js_namespace` here to bind `console.log(..)` instead of just + // `log(..)` #[wasm_bindgen(js_namespace = console)] fn log(s: &str); + + // The `console.log` is quite polymorphic, so we can bind it with multiple + // signatures. Note that we need to use `js_name` to ensure we always call + // `log` in JS. #[wasm_bindgen(js_namespace = console, js_name = log)] fn log_u32(a: u32); + + // Multiple arguments too! #[wasm_bindgen(js_namespace = console, js_name = log)] fn log_many(a: &str, b: &str); } -#[wasm_bindgen] -pub fn run() { +fn bare_bones() { log("Hello from Rust!"); log_u32(42); log_many("Logging", "many values!"); } + +// Next let's define a macro that's like `println!`, only it works for +// `console.log`. Note that `println!` doesn't actually work on the wasm target +// because the standard library currently just eats all output. To get +// `println!`-like behavior in your app you'll likely want a macro like this. + +macro_rules! console_log { + // Note that this is using the `log` function imported above during + // `bare_bones` + ($($t:tt)*) => (log(&format_args!($($t)*).to_string())) +} + +fn using_a_macro() { + console_log!("Hello {}!", "world"); + console_log!("Let's print some numbers..."); + console_log!("1 + 3 = {}", 1 + 3); +} + +// And finally, we don't even have to define the `log` function ourselves! The +// `web_sys` crate already has it defined for us. + +fn using_web_sys() { + use web_sys::console; + + console::log_1(&"Hello using web-sys".into()); + + let js: JsValue = 4.into(); + console::log_2(&"Logging arbitrary values looks like".into(), &js); +} diff --git a/examples/dom/Cargo.toml b/examples/dom/Cargo.toml index f0a0cd964..3b69fd408 100644 --- a/examples/dom/Cargo.toml +++ b/examples/dom/Cargo.toml @@ -1,10 +1,20 @@ [package] name = "dom" version = "0.1.0" -authors = ["Alex Crichton "] +authors = ["The wasm-bindgen Developers"] [lib] crate-type = ["cdylib"] [dependencies] wasm-bindgen = { path = "../.." } + +[dependencies.web-sys] +path = '../../crates/web-sys' +features = [ + 'Document', + 'Element', + 'HtmlElement', + 'Node', + 'Window', +] diff --git a/examples/dom/README.md b/examples/dom/README.md index a4f0f0fb6..ac8369319 100644 --- a/examples/dom/README.md +++ b/examples/dom/README.md @@ -1,13 +1,10 @@ -# DOM access +# web-sys: DOM hello world -[View this example online](https://webassembly.studio/?f=54xnz04tcke) +[View documentation for this example online][dox] -This directory is an example of using the `#[wasm_bindgen]` macro to interact -with the DOM, specifically the `document` object. You'll see here a few examples -of defining access to the global `document` variable as well as appending a new -HTML node to it. +[dox]: https://rustwasm.github.io/wasm-bindgen/examples/dom.html -You can build the example with: +You can build the example locally with: ``` $ ./build.sh @@ -15,10 +12,4 @@ $ ./build.sh (or running the commands on Windows manually) -and then opening up `index.html` in a web browser should show a hello message on -the web page generated by the wasm. - -For more information about this example be sure to check out -[`hello_world`][hello] which also has more comments about caveats and such. - -[hello]: https://github.com/alexcrichton/wasm-bindgen/tree/master/examples/hello_world +and then visiting http://localhost:8080 in a browser should run the example! diff --git a/examples/dom/index.html b/examples/dom/index.html index 4c18b0c25..5c5ad9f33 100644 --- a/examples/dom/index.html +++ b/examples/dom/index.html @@ -3,7 +3,6 @@ -

A greeting from rust looks like...

diff --git a/examples/dom/src/lib.rs b/examples/dom/src/lib.rs index 98c4021e9..acf796f86 100644 --- a/examples/dom/src/lib.rs +++ b/examples/dom/src/lib.rs @@ -1,37 +1,25 @@ extern crate wasm_bindgen; +extern crate web_sys; use wasm_bindgen::prelude::*; -// Definitions of the functionality available in JS, which wasm-bindgen will -// generate shims for today (and eventually these should be near-0 cost!) -// -// These definitions need to be hand-written today but the current vision is -// that we'll use WebIDL to generate this `extern` block into a crate which you -// can link and import. There's a tracking issue for this at -// https://github.com/rustwasm/wasm-bindgen/issues/42 -// -// In the meantime these are written out by hand and correspond to the names and -// signatures documented on MDN, for example -#[wasm_bindgen] -extern "C" { - type HTMLDocument; - static document: HTMLDocument; - #[wasm_bindgen(method)] - fn createElement(this: &HTMLDocument, tagName: &str) -> Element; - #[wasm_bindgen(method, getter)] - fn body(this: &HTMLDocument) -> Element; - - type Element; - #[wasm_bindgen(method, setter = innerHTML)] - fn set_inner_html(this: &Element, html: &str); - #[wasm_bindgen(method, js_name = appendChild)] - fn append_child(this: &Element, other: Element); -} - // Called by our JS entry point to run the example #[wasm_bindgen] -pub fn run() { - let val = document.createElement("p"); +pub fn run() -> Result<(), JsValue> { + // Use `web_sys`'s global `window` function to get a handle on the global + // window object. + let window = web_sys::window().expect("no global `window` exists"); + let document = window.document().expect("should have a document on window"); + let body = document.body().expect("document should have a body"); + + // Manufacture the element we're gonna append + let val = document.create_element("p")?; val.set_inner_html("Hello from Rust!"); - document.body().append_child(val); + + // Right now the class inheritance hierarchy of the DOM isn't super + // ergonomic, so we manually cast `val: Element` to `&Node` to call the + // `append_child` method. + AsRef::::as_ref(&body).append_child(val.as_ref())?; + + Ok(()) } diff --git a/examples/fetch/README.md b/examples/fetch/README.md new file mode 100644 index 000000000..1ca63780f --- /dev/null +++ b/examples/fetch/README.md @@ -0,0 +1,16 @@ +# The `fetch` API + +[View documentation for this example online][dox] + +[dox]: https://rustwasm.github.io/wasm-bindgen/examples/fetch.html + +You can build the example locally with: + +``` +$ ./build.sh +``` + +(or running the commands on Windows manually) + +and then visiting http://localhost:8080 in a browser should run the example! + diff --git a/examples/fetch/build.bat b/examples/fetch/build.bat deleted file mode 100644 index 590cd4033..000000000 --- a/examples/fetch/build.bat +++ /dev/null @@ -1,2 +0,0 @@ -cargo +nightly build --target wasm32-unknown-unknown -cargo +nightly run --manifest-path ../../crates/cli/Cargo.toml --bin wasm-bindgen -- ../../target/wasm32-unknown-unknown/debug/fetch.wasm --out-dir . diff --git a/examples/guide-supported-types-examples/README.md b/examples/guide-supported-types-examples/README.md deleted file mode 100644 index a1f75d4eb..000000000 --- a/examples/guide-supported-types-examples/README.md +++ /dev/null @@ -1,61 +0,0 @@ -# Adding Numbers - -[View this example online](https://webassembly.studio/?f=612vwsrmwft) - -This directory is an example of using the `#[wasm_bindgen]` macro to simply add -two numbers. The neat part about this is that it's an example of how to generate -the smallest wasm-bindgen binary. - -You can build the example with: - -``` -$ ./build.sh -``` - -(or running the commands on Windows manually) - -Currently this generates a 651 byte wasm binary: - -``` -$ ls -alh add_bg.wasm --rw-rw-r-- 1 alex alex 651 Apr 20 22:16 add_bg.wasm -``` - -If you run [wasm-opt], a C++ tool for optimize WebAssembly, you can make it even -smaller too! - -``` -$ wasm-opt -Os add_bg.wasm -o add.wasm -$ ls -alh add.wasm --rw-rw-r-- 1 alex alex 100 Apr 20 22:19 add.wasm -``` - -And sure enough, using the [wasm2wat] tool it's quite small! - -``` -$ wasm2wat add.wasm -(module - (type (;0;) (func (param i32 i32) (result i32))) - (func (;0;) (type 0) (param i32 i32) (result i32) - get_local 1 - get_local 0 - i32.add) - (memory (;0;) 2) - (export "memory" (memory 0)) - (export "add" (func 0)) -(data (i32.const 1545) "invalid malloc request")) -``` - -Note that it's important to point out that the size reductions here are because -the wasm is compiled in release mode by the build script and this crate's -workspace has the following configuration - -```toml -[profile.release] -lto = true -opt-level = 's' -panic = 'abort' -``` - -[wasm2wat]: https://github.com/webassembly/wabt -[wasm-opt]: https://github.com/webassembly/binaryen diff --git a/examples/hello_world/Cargo.toml b/examples/hello_world/Cargo.toml index 5e4c78de4..e61d58389 100644 --- a/examples/hello_world/Cargo.toml +++ b/examples/hello_world/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "hello_world" version = "0.1.0" -authors = ["Alex Crichton "] +authors = ["The wasm-bindgen Developers"] [lib] crate-type = ["cdylib"] diff --git a/examples/hello_world/README.md b/examples/hello_world/README.md index c66f0f00b..e6f5d18d4 100644 --- a/examples/hello_world/README.md +++ b/examples/hello_world/README.md @@ -1,9 +1,8 @@ # Hello, World! -[View this example online](https://webassembly.studio/?f=gzubao6tg3) +[View documentation for this example online][dox] -This directory is an example of using the `#[wasm_bindgen]` macro to create an -entry point that's called from the browser and then displays a dialog. +[dox]: https://rustwasm.github.io/wasm-bindgen/examples/hello-world.html You can build the example locally with: @@ -11,6 +10,6 @@ You can build the example locally with: $ ./build.sh ``` -(or running the two commands on Windows manually) +(or running the commands on Windows manually) -and then opening up `index.html` in a web browser should show a dialog! +and then visiting http://localhost:8080 in a browser should show a dialog! diff --git a/examples/import_js/README.md b/examples/import_js/README.md index 9a8b542fa..abb1599bf 100644 --- a/examples/import_js/README.md +++ b/examples/import_js/README.md @@ -1,9 +1,10 @@ # Importing non-browser JS -This directory is an example of using the `#[wasm_bindgen]` macro to import the -JS defined by you rather than the browser. +[View documentation for this example online][dox] -You can build the example with: +[dox]: https://rustwasm.github.io/wasm-bindgen/examples/import-js.html + +You can build the example locally with: ``` $ ./build.sh @@ -11,10 +12,4 @@ $ ./build.sh (or running the commands on Windows manually) -and then opening up `index.html` in a web browser and see some messages in the -console. - -For more information about this example be sure to check out -[`hello_world`][hello] which also has more comments about caveats and such. - -[hello]: https://github.com/alexcrichton/wasm-bindgen/tree/master/examples/hello_world +and then visiting http://localhost:8080 in a browser should run the example! diff --git a/examples/import_js/index.html b/examples/import_js/index.html index 14e4ff723..e83a75f92 100644 --- a/examples/import_js/index.html +++ b/examples/import_js/index.html @@ -3,7 +3,6 @@ -

Open up the developer console and you should see "Hello from Rust!"

diff --git a/examples/import_js/src/lib.rs b/examples/import_js/src/lib.rs index aab964d69..6ea0cbd02 100644 --- a/examples/import_js/src/lib.rs +++ b/examples/import_js/src/lib.rs @@ -19,7 +19,7 @@ extern "C" { fn render(this: &MyClass) -> String; } -// Import `console.log` so we can log something to the console +// lifted from the `console_log` example #[wasm_bindgen] extern "C" { #[wasm_bindgen(js_namespace = console)] diff --git a/examples/julia_set/Cargo.toml b/examples/julia_set/Cargo.toml index 509b6cc88..cb8b04c5e 100644 --- a/examples/julia_set/Cargo.toml +++ b/examples/julia_set/Cargo.toml @@ -8,3 +8,11 @@ crate-type = ["cdylib"] [dependencies] wasm-bindgen = { path = "../.." } +js-sys = { path = '../../crates/js-sys' } + +[dependencies.web-sys] +path = '../../crates/web-sys' +features = [ + 'ImageData', + 'CanvasRenderingContext2d', +] diff --git a/examples/julia_set/README.md b/examples/julia_set/README.md index 25c46854f..fcf1145e7 100644 --- a/examples/julia_set/README.md +++ b/examples/julia_set/README.md @@ -1,14 +1,15 @@ # Julia Set -[View this example online](https://webassembly.studio/?f=qmg1c6dbjos) +[View documentation for this example online][dox] -This is an example of more complex computations needed to generate a fractal (Julia Set). -It's also an example of direct interaction with CanvasRenderingContext2D's API via `#[wasm_bindgen]` macro. +[dox]: https://rustwasm.github.io/wasm-bindgen/examples/julia.html -You can build the example with: +You can build the example locally with: ``` $ ./build.sh ``` (or running the commands on Windows manually) + +and then visiting http://localhost:8080 in a browser should run the example! diff --git a/examples/julia_set/index.html b/examples/julia_set/index.html index e252a4cbf..45ed0ab47 100644 --- a/examples/julia_set/index.html +++ b/examples/julia_set/index.html @@ -21,6 +21,5 @@ - diff --git a/examples/julia_set/src/fractal/complex/mod.rs b/examples/julia_set/src/fractal/complex/mod.rs deleted file mode 100644 index fede5c936..000000000 --- a/examples/julia_set/src/fractal/complex/mod.rs +++ /dev/null @@ -1,27 +0,0 @@ -use std::ops::Add; - -#[derive(Clone, Copy, Debug)] -pub struct Complex { - pub real: f64, - pub imaginary: f64, -} - -impl Complex { - pub fn square(self) -> Complex { - let real = (self.real * self.real) - (self.imaginary * self.imaginary); - let imaginary = 2.0 * self.real * self.imaginary; - Complex { real, imaginary } - } - - pub fn norm(&self) -> f64 { - (self.real * self.real) + (self.imaginary * self.imaginary) - } -} - -impl Add for Complex { - type Output = Complex; - - fn add(self, rhs: Complex) -> Complex { - Complex { real: self.real + rhs.real, imaginary: self.imaginary + rhs.imaginary } - } -} \ No newline at end of file diff --git a/examples/julia_set/src/fractal/mod.rs b/examples/julia_set/src/fractal/mod.rs deleted file mode 100644 index ec49bdf0c..000000000 --- a/examples/julia_set/src/fractal/mod.rs +++ /dev/null @@ -1,36 +0,0 @@ -pub mod complex; -use self::complex::Complex; - -fn get_iter_index(z: Complex, c: Complex) -> u32 { - let mut iter_index: u32 = 0; - let mut z = z; - while iter_index < 900 { - if z.norm() > 2.0 { - break - } - z = z.square() + c; - iter_index += 1; - } - iter_index -} - -pub fn get_julia_set(width: u32, height: u32, c: Complex) -> Vec { - let mut data: Vec = vec![]; - - let param_i = 1.5; - let param_r = 1.5; - let scale = 0.005; - - for x in 0..width { - for y in 0..height { - let z = Complex { real: y as f64 * scale - param_r, imaginary: x as f64 * scale - param_i }; - let iter_index = get_iter_index(z, c); - data.push((iter_index / 4) as u8); - data.push((iter_index / 2) as u8); - data.push(iter_index as u8); - data.push(255); - } - } - - data -} diff --git a/examples/julia_set/src/lib.rs b/examples/julia_set/src/lib.rs index a92eea484..f8c5b11e1 100644 --- a/examples/julia_set/src/lib.rs +++ b/examples/julia_set/src/lib.rs @@ -1,39 +1,115 @@ +extern crate js_sys; extern crate wasm_bindgen; +extern crate web_sys; + +use std::ops::Add; +use wasm_bindgen::JsCast; use wasm_bindgen::prelude::*; +use web_sys::CanvasRenderingContext2d; +use js_sys::{WebAssembly, Uint8ClampedArray}; -mod fractal; -use fractal::get_julia_set; -use fractal::complex::Complex; - +// Unfortunately `web-sys` at this time doesn't bind APIs with +// `Uint8ClampedArray`. For more information see rustwasm/wasm-bindgen#421. +// +// For now we just bind it ourselves and do some manual frobbing below. #[wasm_bindgen] extern "C" { - pub type ImageData; + type ImageData; #[wasm_bindgen(constructor)] - pub fn new(arr: &Uint8ClampedArray, width: u32, height: u32) -> ImageData; + fn new(arr: &Uint8ClampedArray, width: u32, height: u32) -> ImageData; } #[wasm_bindgen] -extern "C" { - pub type Uint8ClampedArray; - - #[wasm_bindgen(constructor)] - pub fn new(arr: &[u8]) -> Uint8ClampedArray; -} - -#[wasm_bindgen] -extern "C" { - pub type CanvasRenderingContext2D; - - #[wasm_bindgen(method, js_name = putImageData)] - pub fn put_image_data(this: &CanvasRenderingContext2D, image_data: &ImageData, p_1: i32, p_2: i32); -} - -#[wasm_bindgen] -pub fn draw(ctx: &CanvasRenderingContext2D, width: u32, height: u32, real: f64, imaginary: f64) { - let c = Complex { real, imaginary }; +pub fn draw( + ctx: &CanvasRenderingContext2d, + width: u32, + height: u32, + real: f64, + imaginary: f64, +) -> Result<(), JsValue> { + // The real workhorse of this algorithm, generating pixel data + let c = Complex { real, imaginary, }; let data = get_julia_set(width, height, c); - let uint8_array = Uint8ClampedArray::new(&data); - ctx.put_image_data(&ImageData::new(&uint8_array, width, height), 0, 0); + // And now that we've got some pixels, let's create an `ImageData` with the + // pixels and then ship it off to the canvas. + // + // See notes in the `wasm-in-wasm` example for why this is a bit dangerous + let my_memory = wasm_bindgen::memory() + .dyn_into::() + .unwrap(); + let uint8_array = Uint8ClampedArray::new(&my_memory.buffer()) + .subarray( + data.as_ptr() as u32, + data.as_ptr() as u32 + data.len() as u32, + ); + let data = ImageData::new(&uint8_array, width, height); + ctx.put_image_data(data.unchecked_ref(), 0.0, 0.0) +} + +fn get_julia_set(width: u32, height: u32, c: Complex) -> Vec { + let mut data = Vec::new(); + + let param_i = 1.5; + let param_r = 1.5; + let scale = 0.005; + + for x in 0..width { + for y in 0..height { + let z = Complex { + real: y as f64 * scale - param_r, + imaginary: x as f64 * scale - param_i, + }; + let iter_index = get_iter_index(z, c); + data.push((iter_index / 4) as u8); + data.push((iter_index / 2) as u8); + data.push(iter_index as u8); + data.push(255); + } + } + + data +} + +fn get_iter_index(z: Complex, c: Complex) -> u32 { + let mut iter_index: u32 = 0; + let mut z = z; + while iter_index < 900 { + if z.norm() > 2.0 { + break + } + z = z.square() + c; + iter_index += 1; + } + iter_index +} + +#[derive(Clone, Copy, Debug)] +struct Complex { + real: f64, + imaginary: f64, +} + +impl Complex { + fn square(self) -> Complex { + let real = (self.real * self.real) - (self.imaginary * self.imaginary); + let imaginary = 2.0 * self.real * self.imaginary; + Complex { real, imaginary } + } + + fn norm(&self) -> f64 { + (self.real * self.real) + (self.imaginary * self.imaginary) + } +} + +impl Add for Complex { + type Output = Complex; + + fn add(self, rhs: Complex) -> Complex { + Complex { + real: self.real + rhs.real, + imaginary: self.imaginary + rhs.imaginary, + } + } } diff --git a/examples/math/.gitignore b/examples/math/.gitignore deleted file mode 100644 index 7d30d5edf..000000000 --- a/examples/math/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -package-lock.json -math.js -math_bg.js -math_bg.wasm diff --git a/examples/math/Cargo.toml b/examples/math/Cargo.toml deleted file mode 100644 index 7482f7e3b..000000000 --- a/examples/math/Cargo.toml +++ /dev/null @@ -1,10 +0,0 @@ -[package] -name = "math" -version = "0.1.0" -authors = ["Alex Crichton "] - -[lib] -crate-type = ["cdylib"] - -[dependencies] -wasm-bindgen = { path = "../.." } diff --git a/examples/math/README.md b/examples/math/README.md deleted file mode 100644 index a3740215b..000000000 --- a/examples/math/README.md +++ /dev/null @@ -1,21 +0,0 @@ -# `Math` - -[View this example online](https://webassembly.studio/?f=ffnm4kpzmib) - -This directory is an example of using the `#[wasm_bindgen]` macro to import the -`Math` object and invoke various functions on it. - -You can build the example with: - -``` -$ ./build.sh -``` - -(or running the commands on Windows manually) - -and then opening up `index.html` in a web browser should show a dialog! - -For more information about this example be sure to check out -[`hello_world`][hello] which also has more comments about caveats and such. - -[hello]: https://github.com/alexcrichton/wasm-bindgen/tree/master/examples/hello_world diff --git a/examples/math/build.sh b/examples/math/build.sh deleted file mode 100755 index 3d46e42b2..000000000 --- a/examples/math/build.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/sh - -# For more coments about what's going on here, see the `hello_world` example - -set -ex - -cargo +nightly build --target wasm32-unknown-unknown -cargo +nightly run --manifest-path ../../crates/cli/Cargo.toml \ - --bin wasm-bindgen -- \ - ../../target/wasm32-unknown-unknown/debug/math.wasm --out-dir . -npm install -npm run serve diff --git a/examples/math/index.html b/examples/math/index.html deleted file mode 100644 index 8bd8df2c7..000000000 --- a/examples/math/index.html +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - -

Open the developer console and you should see wasm invoking `Math` - functions

- - diff --git a/examples/math/index.js b/examples/math/index.js deleted file mode 100644 index 776e82959..000000000 --- a/examples/math/index.js +++ /dev/null @@ -1,10 +0,0 @@ -// For more comments about what's going on here, check out the `hello_world` -// example -const rust = import('./math'); - -rust.then(m => { - m.run(); - console.log('and in JS the answers look like:'); - console.log(`Math.log2(10.0) = ${Math.log2(10.0)}`); - console.log(`Math.sin(1.2) = ${Math.sin(1.2)}`); -}); diff --git a/examples/math/package.json b/examples/math/package.json deleted file mode 100644 index 176a69a49..000000000 --- a/examples/math/package.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "scripts": { - "serve": "webpack-dev-server" - }, - "devDependencies": { - "html-webpack-plugin": "^3.2.0", - "webpack": "^4.11.1", - "webpack-cli": "^2.0.10", - "webpack-dev-server": "^3.1.0" - } -} diff --git a/examples/math/src/lib.rs b/examples/math/src/lib.rs deleted file mode 100644 index 9f3449c3f..000000000 --- a/examples/math/src/lib.rs +++ /dev/null @@ -1,24 +0,0 @@ -extern crate wasm_bindgen; - -use wasm_bindgen::prelude::*; - -#[wasm_bindgen] -extern "C" { - #[wasm_bindgen(js_namespace = Math)] - fn log2(a: f64) -> f64; - #[wasm_bindgen(js_namespace = Math)] - fn sin(a: f64) -> f64; - - #[wasm_bindgen(js_namespace = console)] - fn log(a: &str); -} - -macro_rules! println { - ($($t:tt)*) => (log(&format_args!($($t)*).to_string())) -} - -#[wasm_bindgen] -pub fn run() { - println!("Math.log2(10.0) = {}", log2(10.0)); - println!("Math.sin(1.2) = {}", sin(1.2)); -} diff --git a/examples/math/webpack.config.js b/examples/math/webpack.config.js deleted file mode 100644 index 453a1a59e..000000000 --- a/examples/math/webpack.config.js +++ /dev/null @@ -1,16 +0,0 @@ -const path = require('path'); -const HtmlWebpackPlugin = require('html-webpack-plugin'); - -module.exports = { - entry: './index.js', - output: { - path: path.resolve(__dirname, 'dist'), - filename: 'index.js', - }, - plugins: [ - new HtmlWebpackPlugin({ - template: "index.html" - }) - ], - mode: 'development' -}; diff --git a/examples/no_modules/README.md b/examples/no_modules/README.md index abc697952..c6eb48838 100644 --- a/examples/no_modules/README.md +++ b/examples/no_modules/README.md @@ -1,10 +1,15 @@ -# `--no-modules` +# Using `--no-modules` -This directory is an example of using the `--no-modules` flag and how it -integrates with the rest of the HTML/JS used. +[View documentation for this example online][dox] + +[dox]: https://rustwasm.github.io/wasm-bindgen/examples/no-modules.html You can build the example locally with: ``` $ ./build.sh ``` + +(or running the commands on Windows manually) + +and then opening `index.html` in a browser should run the example! diff --git a/examples/no_modules/index.html b/examples/no_modules/index.html index 1949a7583..5430a1455 100644 --- a/examples/no_modules/index.html +++ b/examples/no_modules/index.html @@ -3,7 +3,22 @@ + + + +

The developer console should have timing log messages in it

diff --git a/examples/performance/src/lib.rs b/examples/performance/src/lib.rs index 9a50eb6f4..cd3c289f1 100644 --- a/examples/performance/src/lib.rs +++ b/examples/performance/src/lib.rs @@ -1,45 +1,35 @@ extern crate humantime; extern crate wasm_bindgen; +extern crate web_sys; use std::time::{Duration, SystemTime, UNIX_EPOCH}; use wasm_bindgen::prelude::*; -// Like with the `dom` example this block will eventually be auto-generated, but -// for now we can write it by hand to get by! +// lifted from the `console_log` example #[wasm_bindgen] extern "C" { - type Performance; - static performance: Performance; - #[wasm_bindgen(method)] - fn now(this: &Performance) -> f64; - #[wasm_bindgen(method, getter)] - fn timing(this: &Performance) -> PerformanceTiming; - - type PerformanceTiming; - #[wasm_bindgen(method, getter)] - fn requestStart(this: &PerformanceTiming) -> f64; - #[wasm_bindgen(method, getter)] - fn responseEnd(this: &PerformanceTiming) -> f64; - #[wasm_bindgen(js_namespace = console)] fn log(a: &str); } -macro_rules! println { +macro_rules! console_log { ($($t:tt)*) => (log(&format_args!($($t)*).to_string())) } // Called by our JS entry point to run the example #[wasm_bindgen] pub fn run() { - println!("the current time is {}", performance.now()); + let window = web_sys::window().expect("should have a window in this context"); + let performance = window.performance().expect("performance should be available"); - let start = perf_to_system(performance.timing().requestStart()); - let end = perf_to_system(performance.timing().responseEnd()); + console_log!("the current time (in ms) is {}", performance.now()); - println!("request started at {}", humantime::format_rfc3339(start)); - println!("request ended at {}", humantime::format_rfc3339(end)); + let start = perf_to_system(performance.timing().request_start()); + let end = perf_to_system(performance.timing().response_end()); + + console_log!("request started at {}", humantime::format_rfc3339(start)); + console_log!("request ended at {}", humantime::format_rfc3339(end)); } fn perf_to_system(amt: f64) -> SystemTime { diff --git a/examples/smorgasboard/.gitignore b/examples/smorgasboard/.gitignore deleted file mode 100644 index 1716d5f04..000000000 --- a/examples/smorgasboard/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -package-lock.json -smorgasboard.js -smorgasboard_bg.wasm diff --git a/examples/smorgasboard/Cargo.toml b/examples/smorgasboard/Cargo.toml deleted file mode 100644 index 8d130080c..000000000 --- a/examples/smorgasboard/Cargo.toml +++ /dev/null @@ -1,10 +0,0 @@ -[package] -name = "smorgasboard" -version = "0.1.0" -authors = ["Alex Crichton "] - -[lib] -crate-type = ["cdylib"] - -[dependencies] -wasm-bindgen = { path = "../.." } diff --git a/examples/smorgasboard/README.md b/examples/smorgasboard/README.md deleted file mode 100644 index 9f1cd28f6..000000000 --- a/examples/smorgasboard/README.md +++ /dev/null @@ -1,18 +0,0 @@ -# Smorgasboard of examples - -[View this example online](https://webassembly.studio/?f=t61j18noqz) - -This directory is a smattering of examples using the `#[wasm_bindgen]` macro. -Here we see passing strings back and for, exporting classes from Rust to JS, -importing classes from JS to Rust, etc. - -You can build the example with: - -``` -$ ./build.sh -``` - -(or running the two commands on Windows manually) - -and then opening up `index.html` in a web browser should show a dialog saying -"all passed" as well as some console output. diff --git a/examples/smorgasboard/app.js b/examples/smorgasboard/app.js deleted file mode 100644 index 69d9a689f..000000000 --- a/examples/smorgasboard/app.js +++ /dev/null @@ -1,32 +0,0 @@ -import { Foo, Bar, concat } from './smorgasboard'; - -function assertEq(a, b) { - if (a !== b) - throw new Error(`${a} != ${b}`); - console.log(`found ${a} === ${b}`); -} - -assertEq(concat('a', 'b'), 'ab'); - -// Note that to use `new Foo()` the constructor function must be annotated -// with `#[wasm_bindgen(constructor)]`, otherwise only `Foo.new()` can be used. -// Additionally objects allocated corresponding to Rust structs will need to -// be deallocated on the Rust side of things with an explicit call to `free`. -let foo = new Foo(); -assertEq(foo.add(10), 10); -foo.free(); - -// Pass objects to one another -let foo1 = new Foo(); -let bar = Bar.from_str('22', { opaque: 'object' }); -foo1.add_other(bar); - -// We also don't have to `free` the `bar` variable as this function is -// transferring ownership to `foo1` -bar.reset('34'); -foo1.consume_other(bar); - -assertEq(foo1.add(2), 22 + 34 + 2); -foo1.free(); - -alert('all passed!'); diff --git a/examples/smorgasboard/awesome.js b/examples/smorgasboard/awesome.js deleted file mode 100644 index e6824b703..000000000 --- a/examples/smorgasboard/awesome.js +++ /dev/null @@ -1,14 +0,0 @@ -export function bar_on_reset(s, token) { - console.log(token); - console.log(`this instance of bar was reset to ${s}`); -} - -export class Awesome { - constructor() { - this.internal = 32; - } - - get_internal() { - return this.internal; - } -} diff --git a/examples/smorgasboard/build.sh b/examples/smorgasboard/build.sh deleted file mode 100755 index e8279ae54..000000000 --- a/examples/smorgasboard/build.sh +++ /dev/null @@ -1,15 +0,0 @@ -#!/bin/sh - -set -ex - -cargo +nightly build --target wasm32-unknown-unknown - -# Here we're using the version of the CLI in this repository, but for external -# usage you'd use the commented out version below -cargo +nightly run --manifest-path ../../crates/cli/Cargo.toml \ - --bin wasm-bindgen -- \ - ../../target/wasm32-unknown-unknown/debug/smorgasboard.wasm --out-dir . -# wasm-bindgen ../../target/wasm32-unknown-unknown/hello_world.wasm --out-dir . - -npm install -npm run serve diff --git a/examples/smorgasboard/index.js b/examples/smorgasboard/index.js deleted file mode 100644 index b5fb9009e..000000000 --- a/examples/smorgasboard/index.js +++ /dev/null @@ -1 +0,0 @@ -import('./app'); diff --git a/examples/smorgasboard/package.json b/examples/smorgasboard/package.json deleted file mode 100644 index 176a69a49..000000000 --- a/examples/smorgasboard/package.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "scripts": { - "serve": "webpack-dev-server" - }, - "devDependencies": { - "html-webpack-plugin": "^3.2.0", - "webpack": "^4.11.1", - "webpack-cli": "^2.0.10", - "webpack-dev-server": "^3.1.0" - } -} diff --git a/examples/smorgasboard/src/lib.rs b/examples/smorgasboard/src/lib.rs deleted file mode 100644 index a1f1755d2..000000000 --- a/examples/smorgasboard/src/lib.rs +++ /dev/null @@ -1,76 +0,0 @@ -extern crate wasm_bindgen; - -use wasm_bindgen::prelude::*; - -// Strings can both be passed in and received -#[wasm_bindgen] -#[no_mangle] -pub extern "C" fn concat(a: &str, b: &str) -> String { - let mut a = a.to_string(); - a.push_str(b); - return a; -} - -// A struct will show up as a class on the JS side of things -#[wasm_bindgen] -pub struct Foo { - contents: u32, -} - -#[wasm_bindgen] -impl Foo { - #[wasm_bindgen(constructor)] - pub fn new() -> Foo { - Foo { contents: 0 } - } - - // Methods can be defined with `&mut self` or `&self`, and arguments you - // can pass to a normal free function also all work in methods. - pub fn add(&mut self, amt: u32) -> u32 { - self.contents += amt; - return self.contents; - } - - // You can also take a limited set of references to other types as well. - pub fn add_other(&mut self, bar: &Bar) { - self.contents += bar.contents; - } - - // Ownership can work too! - pub fn consume_other(&mut self, bar: Bar) { - self.contents += bar.contents; - } -} - -#[wasm_bindgen] -pub struct Bar { - contents: u32, - opaque: JsValue, // defined in `wasm_bindgen`, imported via prelude -} - -#[wasm_bindgen(module = "./awesome")] // what ES6 module to import from -extern "C" { - fn bar_on_reset(to: &str, opaque: &JsValue); - - // We can import classes and annotate functionality on those classes as well - type Awesome; - #[wasm_bindgen(constructor)] - fn new() -> Awesome; - #[wasm_bindgen(method)] - fn get_internal(this: &Awesome) -> u32; -} - -#[wasm_bindgen] -impl Bar { - pub fn from_str(s: &str, opaque: JsValue) -> Bar { - let contents = s.parse().unwrap_or_else(|_| Awesome::new().get_internal()); - Bar { contents, opaque } - } - - pub fn reset(&mut self, s: &str) { - if let Ok(n) = s.parse() { - bar_on_reset(s, &self.opaque); - self.contents = n; - } - } -} diff --git a/examples/smorgasboard/webpack.config.js b/examples/smorgasboard/webpack.config.js deleted file mode 100644 index a5caf17fc..000000000 --- a/examples/smorgasboard/webpack.config.js +++ /dev/null @@ -1,14 +0,0 @@ -const path = require('path'); -const HtmlWebpackPlugin = require('html-webpack-plugin'); - -module.exports = { - entry: './index.js', - output: { - path: path.resolve(__dirname, 'dist'), - filename: 'index.js', - }, - plugins: [ - new HtmlWebpackPlugin() - ], - mode: 'development' -}; diff --git a/examples/wasm-in-wasm/Cargo.toml b/examples/wasm-in-wasm/Cargo.toml index 35ff98d7f..4ffefe16f 100644 --- a/examples/wasm-in-wasm/Cargo.toml +++ b/examples/wasm-in-wasm/Cargo.toml @@ -8,3 +8,4 @@ crate-type = ["cdylib"] [dependencies] wasm-bindgen = { path = "../.." } +js-sys = { path = "../../crates/js-sys" } diff --git a/examples/wasm-in-wasm/README.md b/examples/wasm-in-wasm/README.md index f32ce2b73..fc46936b0 100644 --- a/examples/wasm-in-wasm/README.md +++ b/examples/wasm-in-wasm/README.md @@ -1,10 +1,10 @@ -# WASM in WASM! +# js-sys: WebAssembly in WebAssembly -This directory is an example of using the `#[wasm_bindgen]` macro to interact -with namespaced APIs like `WebAssembly.Module` and friends. This example -instantiates a wasm module (from Rust!) and then interacts with it. +[View documentation for this example online][dox] -You can build the example with: +[dox]: https://rustwasm.github.io/wasm-bindgen/examples/wasm-in-wasm.html + +You can build the example locally with: ``` $ ./build.sh @@ -12,10 +12,4 @@ $ ./build.sh (or running the commands on Windows manually) -and then opening up `index.html` in a web browser should show a hello message on -the web page generated by the wasm. - -For more information about this example be sure to check out -[`hello_world`][hello] which also has more comments about caveats and such. - -[hello]: https://github.com/alexcrichton/wasm-bindgen/tree/master/examples/hello_world +and then visiting http://localhost:8080 in a browser should run the example! diff --git a/examples/wasm-in-wasm/index.html b/examples/wasm-in-wasm/index.html index 9e83ee104..ddea59919 100644 --- a/examples/wasm-in-wasm/index.html +++ b/examples/wasm-in-wasm/index.html @@ -3,7 +3,6 @@ -

The developer console should have messages in it

diff --git a/examples/wasm-in-wasm/src/lib.rs b/examples/wasm-in-wasm/src/lib.rs index 2757438c8..f2382534a 100644 --- a/examples/wasm-in-wasm/src/lib.rs +++ b/examples/wasm-in-wasm/src/lib.rs @@ -1,52 +1,57 @@ extern crate wasm_bindgen; +extern crate js_sys; use wasm_bindgen::prelude::*; +use wasm_bindgen::JsCast; +use js_sys::{WebAssembly, Object, Reflect, Function, Uint8Array}; -// Like with the `dom` example this block will eventually be auto-generated, but -// for now we can write it by hand to get by! +// lifted from the `console_log` example #[wasm_bindgen] extern "C" { - type Module; - #[wasm_bindgen(constructor, js_namespace = WebAssembly)] - fn new(data: &[u8]) -> Module; - - type Instance; - #[wasm_bindgen(constructor, js_namespace = WebAssembly)] - fn new(module: Module) -> Instance; - #[wasm_bindgen(method, getter, js_namespace = WebAssembly)] - fn exports(this: &Instance) -> Exports; - - type Exports; - #[wasm_bindgen(method, structural)] - fn add(this: &Exports, a: u32, b: u32) -> u32; - #[wasm_bindgen(method, getter, structural)] - fn memory(this: &Exports) -> Memory; - - type Memory; - #[wasm_bindgen(method, js_namespace = WebAssembly)] - fn grow(this: &Memory, amt: u32) -> u32; - #[wasm_bindgen(js_namespace = console)] fn log(a: &str); } -macro_rules! println { +macro_rules! console_log { ($($t:tt)*) => (log(&format_args!($($t)*).to_string())) } const WASM: &[u8] = include_bytes!("add.wasm"); #[wasm_bindgen] -pub fn run() { - println!("instantiating a new wasm module directly"); - let a = Module::new(WASM); - let b = Instance::new(a); +pub fn run() -> Result<(), JsValue> { + console_log!("instantiating a new wasm module directly"); + let my_memory = wasm_bindgen::memory() + .dyn_into::() + .unwrap(); + + // Note that this is somewhat dangerous, once we look at our + // `WebAssembly.Memory` buffer then if we allocate more pages for ourself + // (aka do a memory allocation in Rust) it'll cause the buffer to change. + // That means we can't actually do any memory allocations after we do this + // until we pass it back to JS. + let my_memory = Uint8Array::new(&my_memory.buffer()) + .subarray( + WASM.as_ptr() as u32, + WASM.as_ptr() as u32 + WASM.len() as u32, + ); + let a = WebAssembly::Module::new(my_memory.as_ref())?; + let b = WebAssembly::Instance::new(&a, &Object::new())?; let c = b.exports(); - println!("1 + 2 = {}", c.add(1, 2)); - let mem = c.memory(); - println!("created module has {} pages of memory", mem.grow(0)); - println!("giving the module 4 more pages of memory"); + let add = Reflect::get(c.as_ref(), &"add".into()) + .dyn_into::() + .expect("add export wasn't a function"); + + let three = add.call2(&JsValue::undefined(), &1.into(), &2.into())?; + console_log!("1 + 2 = {:?}", three); + let mem = Reflect::get(c.as_ref(), &"memory".into()) + .dyn_into::() + .expect("memory export wasn't a `WebAssembly.Memory`"); + console_log!("created module has {} pages of memory", mem.grow(0)); + console_log!("giving the module 4 more pages of memory"); mem.grow(4); - println!("now the module has {} pages of memory", mem.grow(0)); + console_log!("now the module has {} pages of memory", mem.grow(0)); + + Ok(()) } diff --git a/examples/asm.js/.gitignore b/examples/wasm2js/.gitignore similarity index 66% rename from examples/asm.js/.gitignore rename to examples/wasm2js/.gitignore index 86a5ea51c..16611626c 100644 --- a/examples/asm.js/.gitignore +++ b/examples/wasm2js/.gitignore @@ -1,2 +1,2 @@ package-lock.json -asmjs* +wasm2js* diff --git a/examples/asm.js/Cargo.toml b/examples/wasm2js/Cargo.toml similarity index 95% rename from examples/asm.js/Cargo.toml rename to examples/wasm2js/Cargo.toml index 1bd53b647..f0d1e702d 100644 --- a/examples/asm.js/Cargo.toml +++ b/examples/wasm2js/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "asmjs" +name = "wasm2js" version = "0.1.0" authors = ["Alex Crichton "] diff --git a/examples/wasm2js/README.md b/examples/wasm2js/README.md new file mode 100644 index 000000000..b87905a71 --- /dev/null +++ b/examples/wasm2js/README.md @@ -0,0 +1,15 @@ +# Converting WebAssembly to JS + +[View documentation for this example online][dox] + +[dox]: https://rustwasm.github.io/wasm-bindgen/examples/wasm2js.html + +You can build the example locally with: + +``` +$ ./build.sh +``` + +(or running the commands on Windows manually) + +and then visiting http://localhost:8080 in a browser should run the example! diff --git a/examples/asm.js/build.sh b/examples/wasm2js/build.sh similarity index 50% rename from examples/asm.js/build.sh rename to examples/wasm2js/build.sh index 7fe068bab..11db81db7 100755 --- a/examples/asm.js/build.sh +++ b/examples/wasm2js/build.sh @@ -2,21 +2,17 @@ set -ex -# Compile our wasm module +# Compile our wasm module and run `wasm-bindgen` cargo +nightly build --target wasm32-unknown-unknown --release - -# Run wasm-bindgen, and note that the `--no-demangle` argument is here is -# important for compatibility with wasm2js! cargo +nightly run --manifest-path ../../crates/cli/Cargo.toml \ --bin wasm-bindgen -- \ - --no-demangle \ - ../../target/wasm32-unknown-unknown/release/asmjs.wasm --out-dir . + ../../target/wasm32-unknown-unknown/release/wasm2js.wasm --out-dir . # Run the `wasm2js` tool from `binaryen` -wasm2js asmjs_bg.wasm -o asmjs_bg.js +wasm2js wasm2js_bg.wasm -o wasm2js_bg.js # Move our original wasm out of the way to avoid cofusing Webpack. -mv asmjs_bg.wasm asmjs_bg.bak.wasm +mv wasm2js_bg.wasm wasm2js_bg.bak.wasm npm install npm run serve diff --git a/examples/asm.js/index.html b/examples/wasm2js/index.html similarity index 82% rename from examples/asm.js/index.html rename to examples/wasm2js/index.html index cba09e977..675fa94dc 100644 --- a/examples/asm.js/index.html +++ b/examples/wasm2js/index.html @@ -4,6 +4,5 @@

Open up the developer console to see "Hello, World!"

- diff --git a/examples/wasm2js/index.js b/examples/wasm2js/index.js new file mode 100644 index 000000000..63ed378eb --- /dev/null +++ b/examples/wasm2js/index.js @@ -0,0 +1,4 @@ +// Note that since we're not using `WebAssembly` we can do a synchronous import +// here! +import { run } from './wasm2js'; +run(); diff --git a/examples/asm.js/package.json b/examples/wasm2js/package.json similarity index 100% rename from examples/asm.js/package.json rename to examples/wasm2js/package.json diff --git a/examples/asm.js/src/lib.rs b/examples/wasm2js/src/lib.rs similarity index 83% rename from examples/asm.js/src/lib.rs rename to examples/wasm2js/src/lib.rs index c2689b1ba..27073ddb0 100644 --- a/examples/asm.js/src/lib.rs +++ b/examples/wasm2js/src/lib.rs @@ -2,6 +2,7 @@ extern crate wasm_bindgen; use wasm_bindgen::prelude::*; +// lifted from the `console_log` example #[wasm_bindgen] extern "C" { #[wasm_bindgen(js_namespace = console)] diff --git a/examples/asm.js/webpack.config.js b/examples/wasm2js/webpack.config.js similarity index 100% rename from examples/asm.js/webpack.config.js rename to examples/wasm2js/webpack.config.js diff --git a/examples/webaudio/README.md b/examples/webaudio/README.md index 98c9f0c6a..73465f639 100644 --- a/examples/webaudio/README.md +++ b/examples/webaudio/README.md @@ -1,14 +1,15 @@ -# Web Audio example +# WebAudio -This directory is an example of how to use the Web Audio APIs from Rust. It creates a very simple -FM (frequency modulation) synth, and let's you control the primary frequency, the modulation amount, -and the modulation frequency. +[View documentation for this example online][dox] -To run, first install some utilities via npm: +[dox]: https://rustwasm.github.io/wasm-bindgen/examples/web-audio.html - > npm install - - Then build the project with either `build.bat` or `build.sh`. - - Finally, run a development web server with `npm run serve` and then open - [http://localhost:8080/](http://localhost:8080/) in a browser! \ No newline at end of file +You can build the example locally with: + +``` +$ ./build.sh +``` + +(or running the commands on Windows manually) + +and then visiting http://localhost:8080 in a browser should run the example! diff --git a/examples/webaudio/build.bat b/examples/webaudio/build.bat deleted file mode 100644 index de86353e0..000000000 --- a/examples/webaudio/build.bat +++ /dev/null @@ -1,2 +0,0 @@ -cargo +nightly build --target wasm32-unknown-unknown -cargo +nightly run --manifest-path ../../crates/cli/Cargo.toml --bin wasm-bindgen -- ../../target/wasm32-unknown-unknown/debug/webaudio.wasm --out-dir . diff --git a/examples/webaudio/index.html b/examples/webaudio/index.html index 108ea885e..23a1ed931 100644 --- a/examples/webaudio/index.html +++ b/examples/webaudio/index.html @@ -3,8 +3,6 @@ - - (headphone users, please make sure your volume is not too loud!) diff --git a/examples/webgl/.gitignore b/examples/webgl/.gitignore index fc819eeba..3955bd3cf 100755 --- a/examples/webgl/.gitignore +++ b/examples/webgl/.gitignore @@ -1,4 +1,4 @@ package-lock.json -wasm_bindgen_webgl_demo.js -wasm_bindgen_webgl_demo_bg.js -wasm_bindgen_webgl_demo_bg.wasm +webgl.js +webgl_bg.js +webgl_bg.wasm diff --git a/examples/webgl/Cargo.toml b/examples/webgl/Cargo.toml index 7dd6581f6..b1c3e5ae7 100755 --- a/examples/webgl/Cargo.toml +++ b/examples/webgl/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "wasm-bindgen-webgl-demo" +name = "webgl" version = "0.1.0" authors = ["The wasm-bindgen Developers"] diff --git a/examples/webgl/README.md b/examples/webgl/README.md index b31d41c77..c57db471a 100755 --- a/examples/webgl/README.md +++ b/examples/webgl/README.md @@ -1,9 +1,10 @@ # WebGL Example -This directory is an example of using the `web-sys` crate to interact with -a WebGL context. +[View documentation for this example online][dox] -You can build and run the example with: +[dox]: https://rustwasm.github.io/wasm-bindgen/examples/webgl.html + +You can build the example locally with: ``` $ ./build.sh @@ -11,5 +12,4 @@ $ ./build.sh (or running the commands on Windows manually) -and then opening up `http://localhost:8080/` in a web browser should show a -nice triangle. +and then visiting http://localhost:8080 in a browser should run the example! diff --git a/examples/webgl/build.sh b/examples/webgl/build.sh index 55a54b0e2..424f39edb 100755 --- a/examples/webgl/build.sh +++ b/examples/webgl/build.sh @@ -9,7 +9,7 @@ cargo +nightly build --target wasm32-unknown-unknown cargo +nightly run --manifest-path ../../crates/cli/Cargo.toml \ --bin wasm-bindgen -- \ - ../../target/wasm32-unknown-unknown/debug/wasm_bindgen_webgl_demo.wasm --out-dir . + ../../target/wasm32-unknown-unknown/debug/webgl.wasm --out-dir . npm install npm run serve diff --git a/examples/webgl/index.html b/examples/webgl/index.html index c13b999e4..319ffd0ed 100755 --- a/examples/webgl/index.html +++ b/examples/webgl/index.html @@ -4,6 +4,5 @@ - diff --git a/examples/webgl/index.js b/examples/webgl/index.js index cb5f7a9a2..19a8762ca 100755 --- a/examples/webgl/index.js +++ b/examples/webgl/index.js @@ -1,5 +1,5 @@ // For more comments about what's going on here, check out the `hello_world` // example. -import('./wasm_bindgen_webgl_demo').then(webgl => { +import('./webgl').then(webgl => { webgl.draw(); }); diff --git a/guide/lib.rs b/guide/lib.rs new file mode 100644 index 000000000..e69de29bb diff --git a/guide/src/SUMMARY.md b/guide/src/SUMMARY.md index 8bf8d337b..a589224a7 100644 --- a/guide/src/SUMMARY.md +++ b/guide/src/SUMMARY.md @@ -8,6 +8,24 @@ - [Basic Usage](./whirlwind-tour/basic-usage.md) - [What Just Happened?](./whirlwind-tour/what-just-happened.md) - [What Else Can We Do?](./whirlwind-tour/what-else-can-we-do.md) +- [Examples](./examples/index.md) + - [Hello, World!](./examples/hello-world.md) + - [Using `console.log`](./examples/console-log.md) + - [Small wasm files](./examples/add.md) + - [Using `--no-modules`](./examples/no-modules.md) + - [Converting WebAssembly to JS](./examples/wasm2js.md) + - [Importing functions from JS](./examples/import-js.md) + - [Working with `char`](./examples/char.md) + - [js-sys: WebAssembly in WebAssembly](./examples/wasm-in-wasm.md) + - [web-sys: DOM hello world](./examples/dom.md) + - [web-sys: Closures](./examples/closures.md) + - [web-sys: `performance.now`](./examples/performance.md) + - [web-sys: using `fetch`](./examples/fetch.md) + - [web-sys: `canvas` hello world](./examples/2d-canvas.md) + - [web-sys: `canvas` Julia set](./examples/julia.md) + - [web-sys: WebAudio](./examples/web-audio.md) + - [web-sys: WebGL](./examples/webgl.md) + - [web-sys: A Simple Paint Program](./examples/paint.md) - [Reference](./reference/index.md) - [Passing Rust Closures to JS](./reference/passing-rust-closures-to-js.md) - [Receiving JS Closures in Rust](./reference/receiving-js-closures-in-rust.md) @@ -58,12 +76,6 @@ - [Cargo Features](./web-sys/cargo-features.md) - [Function Overloads](./web-sys/function-overloads.md) - [Type Translations](./web-sys/type-translations.md) - - [Examples](./web-sys/examples/index.md) - - [The `fetch` API](./web-sys/examples/fetch.md) - - [2D Canvas](./web-sys/examples/2d-canvas.md) - - [WebAudio](./web-sys/examples/web-audio.md) - - [WebGL](./web-sys/examples/webgl.md) - - [A Simple Paint Program](./web-sys/examples/paint.md) -------------------------------------------------------------------------------- diff --git a/guide/src/contributing/web-sys/overview.md b/guide/src/contributing/web-sys/overview.md index 96efa586e..0f07061c0 100644 --- a/guide/src/contributing/web-sys/overview.md +++ b/guide/src/contributing/web-sys/overview.md @@ -31,7 +31,7 @@ The only thing `src/lib.rs` does is include the bindings generated at compile time in `build.rs`. Here is the whole `src/lib.rs` file: ```rust -{{#include ../../../crates/web-sys/src/lib.rs}} +{{#include ../../../../crates/web-sys/src/lib.rs}} ``` ### Cargo features diff --git a/guide/src/web-sys/examples/2d-canvas.md b/guide/src/examples/2d-canvas.md similarity index 68% rename from guide/src/web-sys/examples/2d-canvas.md rename to guide/src/examples/2d-canvas.md index 33b2ec948..69527cbfa 100644 --- a/guide/src/web-sys/examples/2d-canvas.md +++ b/guide/src/examples/2d-canvas.md @@ -1,13 +1,14 @@ # 2D Canvas +[View full source code][code] + +[code]: https://github.com/rustwasm/wasm-bindgen/tree/master/examples/canvas + Drawing a smiley face with the 2D canvas API. This is a port of part of [this MDN tutorial](https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Tutorial/Drawing_shapes#Moving_the_pen) to `web-sys`. -[See the full source at -`wasm-bindgen/examples/canvas`.](https://github.com/rustwasm/wasm-bindgen/tree/master/examples/canvas) - ![A smiley face](./2d-canvas.png) ## `Cargo.toml` @@ -16,7 +17,7 @@ The `Cargo.toml` enables features necessary to query the DOM and work with 2D canvas. ```toml -{{#include ../../../../examples/canvas/Cargo.toml}} +{{#include ../../../examples/canvas/Cargo.toml}} ``` ## `src/lib.rs` @@ -25,5 +26,5 @@ Gets the `` element, creates a 2D rendering context, and draws the smiley face. ```rust -{{#include ../../../../examples/canvas/src/lib.rs}} +{{#include ../../../examples/canvas/src/lib.rs}} ``` diff --git a/guide/src/web-sys/examples/2d-canvas.png b/guide/src/examples/2d-canvas.png similarity index 100% rename from guide/src/web-sys/examples/2d-canvas.png rename to guide/src/examples/2d-canvas.png diff --git a/guide/src/examples/add.md b/guide/src/examples/add.md new file mode 100644 index 000000000..12f903f3e --- /dev/null +++ b/guide/src/examples/add.md @@ -0,0 +1,68 @@ +# Small wasm files + +[View full source code][code] + +[code]: https://github.com/rustwasm/wasm-bindgen/tree/master/examples/add + +One of `wasm-bindgen`'s core goals is a pay-only-for-what-you-use philosophy, so +if we don't use much then we shouldn't be paying much! As a result +`#[wasm_bindgen]` can generate super-small executables + +Currently this code... + +```rust +{{#include ../../../examples/add/src/lib.rs}} +``` + +generates a 723 byte wasm binary: + +``` +$ ls -l add_bg.wasm +-rw-rw-r-- 1 alex alex 723 Sep 19 17:32 add_bg.wasm +``` + +If you run [wasm-opt], a C++ tool for optimize WebAssembly, you can make it +even smaller too! + +``` +$ wasm-opt -Os add_bg.wasm -o add.wasm +$ ls -l add.wasm +-rw-rw-r-- 1 alex alex 182 Sep 19 17:33 add.wasm +``` + +And sure enough, using the [wasm2wat] tool it's quite small! + +``` +$ wasm2wat add.wasm +(module + (type (;0;) (func (param i32 i32) (result i32))) + (func (;0;) (type 0) (param i32 i32) (result i32) + i32.const 1048640 + i32.const 0 + i32.store + get_local 1 + get_local 0 + i32.add) + (table (;0;) 1 1 anyfunc) + (memory (;0;) 17) + (global (;0;) i32 (i32.const 1049118)) + (global (;1;) i32 (i32.const 1049118)) + (export "memory" (memory 0)) + (export "__indirect_function_table" (table 0)) + (export "__heap_base" (global 0)) + (export "__data_end" (global 1)) + (export "add" (func 0)) + (data (i32.const 1049096) "invalid malloc request")) +``` + +Also don't forget to compile in release mode for the smallest binaries! For +larger applications you'll likely also want to turn on LTO to generate the +smallest binaries: + +```toml +[profile.release] +lto = true +``` + +[wasm2wat]: https://github.com/webassembly/wabt +[wasm-opt]: https://github.com/webassembly/binaryen diff --git a/guide/src/examples/char.md b/guide/src/examples/char.md new file mode 100644 index 000000000..a2d4669f4 --- /dev/null +++ b/guide/src/examples/char.md @@ -0,0 +1,30 @@ +# Working with the `char` type + +[View full source code][code] + +[code]: https://github.com/rustwasm/wasm-bindgen/tree/master/examples/char + +The `#[wasm_bindgen]` macro will convert the rust `char` type to a single +code-point js `string`, and this example shows how to work with this. + +Opening this example should display a single counter with a random character +for it's `key` and 0 for its `count`. You can click the `+` button to increase a +counter's count. By clicking on the "add counter" button you should see a new +counter added to the list with a different random character for it's `key`. + +Under the hood javascript is choosing a random character from an Array of +characters and passing that to the rust Counter struct's constructor so the +character you are seeing on the page has made the full round trip from js to +rust and back to js. + +## `src/lib.rs` + +```rust +{{#include ../../../examples/char/src/lib.rs}} +``` + +## `index.js` + +```js +{{#include ../../../examples/char/index.js}} +``` diff --git a/guide/src/examples/closures.md b/guide/src/examples/closures.md new file mode 100644 index 000000000..7ab76d693 --- /dev/null +++ b/guide/src/examples/closures.md @@ -0,0 +1,15 @@ +# web-sys: Closures + +[View full source code][code] + +[code]: https://github.com/rustwasm/wasm-bindgen/tree/master/examples/closures + +One of the features of `#[wasm_bindgen]` is that you can pass closures defined +in Rust off to JS. This can be a bit tricky at times, though, so the example +here shows how to interact with some standard web APIs with closures. + +## `src/lib.rs` + +```rust +{{#include ../../../examples/closures/src/lib.rs}} +``` diff --git a/guide/src/examples/console-log.md b/guide/src/examples/console-log.md new file mode 100644 index 000000000..94b665de0 --- /dev/null +++ b/guide/src/examples/console-log.md @@ -0,0 +1,14 @@ +# `console.log` + +[View full source code][code] + +[code]: https://github.com/rustwasm/wasm-bindgen/tree/master/examples/console_log + +This example shows off how to use `console.log` in a variety of ways, all the +way from bare-bones usage to a `println!`-like macro with `web_sys`. + +## `src/lib.rs` + +```rust +{{#include ../../../examples/console_log/src/lib.rs}} +``` diff --git a/guide/src/examples/dom.md b/guide/src/examples/dom.md new file mode 100644 index 000000000..db2915d18 --- /dev/null +++ b/guide/src/examples/dom.md @@ -0,0 +1,25 @@ +# web-sys: DOM hello world + +[View full source code][code] + +[code]: https://github.com/rustwasm/wasm-bindgen/tree/master/examples/dom + +Using `web-sys` we're able to interact with all the standard web platform +methods, including those of the DOM! Here we take a look at a simple "Hello, +world!" which manufactures a DOM element in Rust, customizes it, and then +appends it to the page. + +## `Cargo.toml` + +You can see here how we depend on `web-sys` and activate associated features to +enable all the various APIs: + +```toml +{{#include ../../../examples/dom/Cargo.toml}} +``` + +## `src/lib.rs` + +```rust +{{#include ../../../examples/dom/src/lib.rs}} +``` diff --git a/guide/src/web-sys/examples/fetch.md b/guide/src/examples/fetch.md similarity index 61% rename from guide/src/web-sys/examples/fetch.md rename to guide/src/examples/fetch.md index 79e1f810b..fdd03c1f1 100644 --- a/guide/src/web-sys/examples/fetch.md +++ b/guide/src/examples/fetch.md @@ -1,11 +1,12 @@ # The `fetch` API +[View full source code][code] + +[code]: https://github.com/rustwasm/wasm-bindgen/tree/master/examples/fetch + This example uses the `fetch` API to make an HTTP request to the GitHub API and then parses the resulting JSON. -[See the full source at -`wasm-bindgen/examples/fetch`.](https://github.com/rustwasm/wasm-bindgen/tree/master/examples/fetch) - ## `Cargo.toml` The `Cargo.toml` enables a number of features related to the `fetch` API and @@ -13,11 +14,11 @@ types used: `Headers`, `Request`, etc. It also enables `wasm-bindgen`'s `serde` support. ```toml -{{#include ../../../../examples/fetch/Cargo.toml}} +{{#include ../../../examples/fetch/Cargo.toml}} ``` ## `src/lib.rs` ```rust -{{#include ../../../../examples/fetch/src/lib.rs}} +{{#include ../../../examples/fetch/src/lib.rs}} ``` diff --git a/guide/src/examples/hello-world.md b/guide/src/examples/hello-world.md new file mode 100644 index 000000000..457c95ac3 --- /dev/null +++ b/guide/src/examples/hello-world.md @@ -0,0 +1,55 @@ +# Hello, World! + +[View full source code][code] + +[code]: https://github.com/rustwasm/wasm-bindgen/tree/master/examples/hello_world + +This is the "Hello, world!" example of `#[wasm_bindgen]` showing how to set up +a project, export a function to JS, call it from JS, and then call the `alert` +function in Rust. + +## `Cargo.toml` + +The `Cargo.toml` enables depends on the `wasm-bindgen` crate. Here we're using +a `path` dependency because this example lives in the `wasm-bindgen` repository +itself, but you'd use the commented out version beneath it instead. + +Also of note is the `crate-type = ["cdylib"]` which is largely used for wasm +final artifacts today. + +```toml +{{#include ../../../examples/hello_world/Cargo.toml}} +``` + +## `src/lib.rs` + +Here we define our Rust entry point along with calling the `alert` function. + +```rust +{{#include ../../../examples/hello_world/src/lib.rs}} +``` + +## `index.js` + +Our JS entry point is quite small! + +```js +{{#include ../../../examples/hello_world/index.js}} +``` + +## Webpack-specific files + +And finally here's the Webpack configuration and `package.json` for this +project: + +**webpack.config.js** + +```js +{{#include ../../../examples/hello_world/webpack.config.js}} +``` + +**package.json** + +```json +{{#include ../../../examples/hello_world/package.json}} +``` diff --git a/guide/src/examples/import-js.md b/guide/src/examples/import-js.md new file mode 100644 index 000000000..3cd6f17cb --- /dev/null +++ b/guide/src/examples/import-js.md @@ -0,0 +1,26 @@ +# Importing non-browser JS + +[View full source code][code] + +[code]: https://github.com/rustwasm/wasm-bindgen/tree/master/examples/import_js + +The `#[wasm_bindgen]` attribute can be used on `extern { .. }` blocks to import +functionality from JS. This is how the `js-sys` and the `web-sys` crates are +built, but you can also use it in your own crate! + +For example if you're working with this JS file: + +```js +// defined-in-js.js +{{#include ../../../examples/import_js/defined-in-js.js}} +``` + +you can use it in Rust with: + +```rust +{{#include ../../../examples/import_js/src/lib.rs}} +``` + +You can also [explore the full list of ways to configure imports][attr] + +[attr]: ../reference/attributes/on-js-imports/index.html diff --git a/guide/src/examples/index.md b/guide/src/examples/index.md new file mode 100644 index 000000000..4ca1307a8 --- /dev/null +++ b/guide/src/examples/index.md @@ -0,0 +1,15 @@ +# Examples of using `wasm-bindgen`, `js-sys`, and `web-sys` + +This subsection contains examples of using the `wasm-bindgen`, `js-sys`, and +`web-sys` crates. Each example should have more information about what it's +doing. + +The source code for all examples can also be [found online][code] to download an +run locally. Each example is accompanied with a `build.sh` script to outline the +steps necessary to build and run it as well. + +Note that most examples currently use Webpack to assemble the final output +artifact, but this is not required! You can use the bundler of choice, +`--no-modules`, or native browser ESM support as alternatives to Webpack. + +[code]: https://github.com/rustwasm/wasm-bindgen/tree/master/examples diff --git a/guide/src/examples/julia.md b/guide/src/examples/julia.md new file mode 100644 index 000000000..0a57ddfb7 --- /dev/null +++ b/guide/src/examples/julia.md @@ -0,0 +1,24 @@ +# Julia Set + +[View full source code][code] + +[code]: https://github.com/rustwasm/wasm-bindgen/tree/master/examples/julia_set + +While not showing off a lot of `web_sys` API surface area, this example shows a +neat fractal that you can make! + +## `index.js` + +A small bit of glue is added for this example + +```js +{{#include ../../../examples/julia_set/index.js}} +``` + +## `src/lib.rs` + +The bulk of the logic is in the generation of the fractal + +```rust +{{#include ../../../examples/julia_set/src/lib.rs}} +``` diff --git a/guide/src/examples/no-modules.md b/guide/src/examples/no-modules.md new file mode 100644 index 000000000..fae7899d0 --- /dev/null +++ b/guide/src/examples/no-modules.md @@ -0,0 +1,20 @@ +# Using `--no-modules` + +[View full source code][code] + +[code]: https://github.com/rustwasm/wasm-bindgen/tree/master/examples/no_modules + +This example shows how the `--no-modules` flag can be used load code in a +browser directly (using the same code as the [hello world example][hello]). +Most of the magic happens in `index.html`: + +```html +{{#include ../../../examples/no_modules/index.html}} +``` + +And that's it! It's worth pointing out that if [`#[wasm_bindgen(module = +"...")]` imports are used][mod-imp] then `wasm-bindgen --no-modules` will fail +(as it doesn't know how to import modules). + +[hello]: hello-world.html +[mod-imp]: ../reference/attributes/on-js-imports/module.html diff --git a/guide/src/web-sys/examples/paint.md b/guide/src/examples/paint.md similarity index 58% rename from guide/src/web-sys/examples/paint.md rename to guide/src/examples/paint.md index 319c14375..2651aea84 100644 --- a/guide/src/web-sys/examples/paint.md +++ b/guide/src/examples/paint.md @@ -1,17 +1,18 @@ -# Paint +# Paint Example + +[View full source code][code] + +[code]: https://github.com/rustwasm/wasm-bindgen/tree/master/examples/paint A simple painting program. -[See the full source at -`wasm-bindgen/examples/paint`.](https://github.com/rustwasm/wasm-bindgen/tree/master/examples/paint) - ## `Cargo.toml` The `Cargo.toml` enables features necessary to work with the DOM, events and 2D canvas. ```toml -{{#include ../../../../examples/paint/Cargo.toml}} +{{#include ../../../examples/paint/Cargo.toml}} ``` ## `src/lib.rs` @@ -20,5 +21,5 @@ Creates the `` element, applies a CSS style to it, adds it to the docume get a 2D rendering context and adds listeners for mouse events. ```rust -{{#include ../../../../examples/paint/src/lib.rs}} +{{#include ../../../examples/paint/src/lib.rs}} ``` diff --git a/guide/src/examples/performance.md b/guide/src/examples/performance.md new file mode 100644 index 000000000..e5deffe6a --- /dev/null +++ b/guide/src/examples/performance.md @@ -0,0 +1,15 @@ +# web-sys: `performance.now` + +[View full source code][code] + +[code]: https://github.com/rustwasm/wasm-bindgen/tree/master/examples/performance + +Want to profile some Rust code in the browser? No problem! You can use the +`performance.now()` API and friends to get timing information to see how long +things take. + +## `src/lib.rs` + +```rust +{{#include ../../../examples/performance/src/lib.rs}} +``` diff --git a/guide/src/examples/wasm-in-wasm.md b/guide/src/examples/wasm-in-wasm.md new file mode 100644 index 000000000..8ce0572e1 --- /dev/null +++ b/guide/src/examples/wasm-in-wasm.md @@ -0,0 +1,14 @@ +# js-sys: WebAssembly in WebAssembly + +[View full source code][code] + +[code]: https://github.com/rustwasm/wasm-bindgen/tree/master/examples/wasm-in-wasm + +Using the `js-sys` crate we can get pretty meta and instantiate `WebAssembly` +modules from inside `WebAssembly` modules! + +## `src/lib.rs` + +```rust +{{#include ../../../examples/wasm-in-wasm/src/lib.rs}} +``` diff --git a/guide/src/examples/wasm2js.md b/guide/src/examples/wasm2js.md new file mode 100644 index 000000000..604ad2fc1 --- /dev/null +++ b/guide/src/examples/wasm2js.md @@ -0,0 +1,38 @@ +# Converting WebAssembly to JS + +[View full source code][code] + +[code]: https://github.com/rustwasm/wasm-bindgen/tree/master/examples/wasm2js + +Not all browsers have support for `WebAssembly` at this time (although all major +ones do). If you'd like to support older browsers, you probably want a method +that doesn't involve keeping two codebases in sync! + +Thankfully there's a tool from [binaryen] called `wasm2js` to convert a wasm +file to JS. This JS file, if successfully produced, is equivalent to the wasm +file (albeit a little bit larger and slower), and can be loaded into practically +any browser. + +This example is relatively simple (cribbing from the [`console.log` +example][console_log]): + +```rust +{{#include ../../../examples/wasm2js/src/lib.rs}} +``` + +The real magic happens when you actually build the app. Just after +`wasm-bindgen` we see here how we execute `wasm2js` in our build script: + +```sh +{{#include ../../../examples/wasm2js/build.sh}} +``` + +Note that the `wasm2js` tool is still pretty early days so there's likely to be +a number of bugs to run into or work around. If any are encountered though +please feel free to report them upstream! + +Also note that eventually this will ideally be automatically done by your +bundler and no action would be needed from you to work in older browsers via +`wasm2js`! + +[binaryen]: https://github.com/WebAssembly/binaryen diff --git a/guide/src/web-sys/examples/web-audio.md b/guide/src/examples/web-audio.md similarity index 65% rename from guide/src/web-sys/examples/web-audio.md rename to guide/src/examples/web-audio.md index 6202a9aa2..8b8b80c2f 100644 --- a/guide/src/web-sys/examples/web-audio.md +++ b/guide/src/examples/web-audio.md @@ -1,21 +1,22 @@ # WebAudio +[View full source code][code] + +[code]: https://github.com/rustwasm/wasm-bindgen/tree/master/examples/webaudio + This example creates an [FM oscillator](https://en.wikipedia.org/wiki/Frequency_modulation_synthesis) using the [WebAudio API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Audio_API) and `web-sys`. -[See the full source at -`wasm-bindgen/examples/webaudio`.](https://github.com/rustwasm/wasm-bindgen/tree/master/examples/webaudio) - ## `Cargo.toml` The `Cargo.toml` enables the types needed to use the relevant bits of the WebAudio API. ```toml -{{#include ../../../../examples/webaudio/Cargo.toml}} +{{#include ../../../examples/webaudio/Cargo.toml}} ``` ## `src/lib.rs` @@ -23,7 +24,7 @@ WebAudio API. The Rust code implements the FM oscillator. ```rust -{{#include ../../../../examples/webaudio/src/lib.rs}} +{{#include ../../../examples/webaudio/src/lib.rs}} ``` ## `index.js` @@ -32,5 +33,5 @@ A small bit of JavaScript glues the rust module to input widgets and translates events into calls into wasm code. ```js -{{#include ../../../../examples/webaudio/index.js}} +{{#include ../../../examples/webaudio/index.js}} ``` diff --git a/guide/src/web-sys/examples/webgl.md b/guide/src/examples/webgl.md similarity index 62% rename from guide/src/web-sys/examples/webgl.md rename to guide/src/examples/webgl.md index 38a886f82..82ac2471e 100644 --- a/guide/src/web-sys/examples/webgl.md +++ b/guide/src/examples/webgl.md @@ -1,17 +1,18 @@ -# 2D Canvas +# WebGL Example + +[View full source code][code] + +[code]: https://github.com/rustwasm/wasm-bindgen/tree/master/examples/webgl This example draws a triangle to the screen using the WebGL API. -[See the full source at -`wasm-bindgen/examples/webgl`.](https://github.com/rustwasm/wasm-bindgen/tree/master/examples/webgl) - ## `Cargo.toml` The `Cargo.toml` enables features necessary to obtain and use a WebGL rendering context. ```toml -{{#include ../../../../examples/webgl/Cargo.toml}} +{{#include ../../../examples/webgl/Cargo.toml}} ``` ## `src/lib.rs` @@ -21,5 +22,5 @@ context, compile shaders, fill a buffer with vertex coordinates, and draw a triangle to the screen. ```rust -{{#include ../../../../examples/webgl/src/lib.rs}} +{{#include ../../../examples/webgl/src/lib.rs}} ``` diff --git a/guide/src/introduction.md b/guide/src/introduction.md index e1cf5366c..d810dd6cd 100644 --- a/guide/src/introduction.md +++ b/guide/src/introduction.md @@ -19,7 +19,7 @@ Notable features of this project includes: * Importing JS functionality in to Rust such as [DOM manipulation][dom-ex], [console logging][console-log], or [performance monitoring][perf-ex]. -* [Exporting Rust functionality][smorg-ex] to JS such as classes, functions, etc. +* Exporting Rust functionality to JS such as classes, functions, etc. * Working with rich types like strings, numbers, classes, closures, and objects rather than simply `u32` and floats. @@ -32,5 +32,4 @@ what this crate can do, check out the [design doc]. [dom-ex]: https://github.com/rustwasm/wasm-bindgen/tree/master/examples/dom [console-log]: https://github.com/rustwasm/wasm-bindgen/tree/master/examples/console_log [perf-ex]: https://github.com/rustwasm/wasm-bindgen/tree/master/examples/performance -[smorg-ex]: https://github.com/rustwasm/wasm-bindgen/tree/master/examples/smorgasboard [hello-online]: https://webassembly.studio/?f=gzubao6tg3 diff --git a/guide/src/web-sys/examples/index.md b/guide/src/web-sys/examples/index.md deleted file mode 100644 index 6136b4763..000000000 --- a/guide/src/web-sys/examples/index.md +++ /dev/null @@ -1,3 +0,0 @@ -# Examples of using `web-sys` - -This subsection contains examples of using the `web-sys` crate. diff --git a/tests/crates/a/Cargo.toml b/tests/crates/a/Cargo.toml index d8d93d0a1..754df360a 100644 --- a/tests/crates/a/Cargo.toml +++ b/tests/crates/a/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "wasm-bindgen-test-crate-a" version = "0.1.0" -authors = ["The wasm-bindgen Authors"] +authors = ["The wasm-bindgen Developers"] license = "MIT/Apache-2.0" description = "internal test crate for wasm-bindgen" diff --git a/tests/crates/b/Cargo.toml b/tests/crates/b/Cargo.toml index aee2848b6..916107feb 100644 --- a/tests/crates/b/Cargo.toml +++ b/tests/crates/b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "wasm-bindgen-test-crate-b" version = "0.1.0" -authors = ["The wasm-bindgen Authors"] +authors = ["The wasm-bindgen Developers"] license = "MIT/Apache-2.0" description = "internal test crate for wasm-bindgen"