From e87498e9391198a5c6eadd89ba10414b9c1c76a9 Mon Sep 17 00:00:00 2001 From: Nick Fitzgerald Date: Fri, 10 Aug 2018 16:56:40 -0700 Subject: [PATCH] guide: Start adding example usage to "supported types" section --- Cargo.toml | 1 + .../guide-supported-types-examples/.gitignore | 3 + .../guide-supported-types-examples/Cargo.toml | 10 ++ .../guide-supported-types-examples/README.md | 61 ++++++++ .../bootstrap.js | 2 + .../guide-supported-types-examples/build.sh | 12 ++ .../exported_types.js | 1 + .../imported_types.js | 26 ++++ .../guide-supported-types-examples/index.html | 8 + .../guide-supported-types-examples/index.js | 5 + .../package.json | 10 ++ .../src/exported_types.rs | 6 + .../src/imported_types.rs | 25 ++++ .../guide-supported-types-examples/src/lib.rs | 7 + .../webpack.config.js | 10 ++ guide/src/reference/types.md | 139 +++++++++++++++--- 16 files changed, 307 insertions(+), 19 deletions(-) create mode 100644 examples/guide-supported-types-examples/.gitignore create mode 100644 examples/guide-supported-types-examples/Cargo.toml create mode 100644 examples/guide-supported-types-examples/README.md create mode 100644 examples/guide-supported-types-examples/bootstrap.js create mode 100755 examples/guide-supported-types-examples/build.sh create mode 100644 examples/guide-supported-types-examples/exported_types.js create mode 100644 examples/guide-supported-types-examples/imported_types.js create mode 100644 examples/guide-supported-types-examples/index.html create mode 100644 examples/guide-supported-types-examples/index.js create mode 100644 examples/guide-supported-types-examples/package.json create mode 100644 examples/guide-supported-types-examples/src/exported_types.rs create mode 100644 examples/guide-supported-types-examples/src/imported_types.rs create mode 100755 examples/guide-supported-types-examples/src/lib.rs create mode 100644 examples/guide-supported-types-examples/webpack.config.js diff --git a/Cargo.toml b/Cargo.toml index 66579efa..af895770 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -55,6 +55,7 @@ members = [ "examples/comments", "examples/console_log", "examples/dom", + "examples/guide-supported-types-examples", "examples/hello_world", "examples/import_js", "examples/julia_set", diff --git a/examples/guide-supported-types-examples/.gitignore b/examples/guide-supported-types-examples/.gitignore new file mode 100644 index 00000000..d0b14fad --- /dev/null +++ b/examples/guide-supported-types-examples/.gitignore @@ -0,0 +1,3 @@ +package-lock.json +guide_supported_types_examples.js +guide_supported_types_examples_bg.wasm diff --git a/examples/guide-supported-types-examples/Cargo.toml b/examples/guide-supported-types-examples/Cargo.toml new file mode 100644 index 00000000..9c73077a --- /dev/null +++ b/examples/guide-supported-types-examples/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "guide-supported-types-examples" +version = "0.1.0" +authors = ["Nick Fitzgerald "] + +[lib] +crate-type = ["cdylib"] + +[dependencies] +wasm-bindgen = { path = "../.." } diff --git a/examples/guide-supported-types-examples/README.md b/examples/guide-supported-types-examples/README.md new file mode 100644 index 00000000..a1f75d4e --- /dev/null +++ b/examples/guide-supported-types-examples/README.md @@ -0,0 +1,61 @@ +# 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/guide-supported-types-examples/bootstrap.js b/examples/guide-supported-types-examples/bootstrap.js new file mode 100644 index 00000000..ddd62bb5 --- /dev/null +++ b/examples/guide-supported-types-examples/bootstrap.js @@ -0,0 +1,2 @@ +import * as imported_types from './imported_types.js'; +import * as exported_types from './exported_types.js'; diff --git a/examples/guide-supported-types-examples/build.sh b/examples/guide-supported-types-examples/build.sh new file mode 100755 index 00000000..d99253c5 --- /dev/null +++ b/examples/guide-supported-types-examples/build.sh @@ -0,0 +1,12 @@ +#!/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 --release +cargo +nightly run --manifest-path ../../crates/cli/Cargo.toml \ + --bin wasm-bindgen -- \ + ../../target/wasm32-unknown-unknown/release/guide_supported_types_examples.wasm --out-dir . +npm install +npm run serve diff --git a/examples/guide-supported-types-examples/exported_types.js b/examples/guide-supported-types-examples/exported_types.js new file mode 100644 index 00000000..97dd4313 --- /dev/null +++ b/examples/guide-supported-types-examples/exported_types.js @@ -0,0 +1 @@ +console.log("todo") diff --git a/examples/guide-supported-types-examples/imported_types.js b/examples/guide-supported-types-examples/imported_types.js new file mode 100644 index 00000000..41d1c682 --- /dev/null +++ b/examples/guide-supported-types-examples/imported_types.js @@ -0,0 +1,26 @@ +import { + imported_type_by_value, + imported_type_by_shared_ref, + return_imported_type, + take_option_imported_type, + return_option_imported_type, +} from './guide_supported_types_examples'; + +imported_type_by_value(new SomeJsType()); +imported_type_by_shared_ref(new SomeJsType()); + +let x = return_imported_type(); +console.log(x instanceof SomeJsType); +// true + +take_option_imported_type(null); +take_option_imported_type(undefined); +take_option_imported_type(new SomeJsType()); + +let y = return_option_imported_type(); +if (y == null) { + // ... +} else { + console.log(y instanceof SomeJsType); + // true +} diff --git a/examples/guide-supported-types-examples/index.html b/examples/guide-supported-types-examples/index.html new file mode 100644 index 00000000..bad47a7c --- /dev/null +++ b/examples/guide-supported-types-examples/index.html @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/examples/guide-supported-types-examples/index.js b/examples/guide-supported-types-examples/index.js new file mode 100644 index 00000000..a1819bb5 --- /dev/null +++ b/examples/guide-supported-types-examples/index.js @@ -0,0 +1,5 @@ +// For more comments about what's going on here, check out the `hello_world` +// example +import('./bootstrap').then(() => { + console.log("done"); +}); diff --git a/examples/guide-supported-types-examples/package.json b/examples/guide-supported-types-examples/package.json new file mode 100644 index 00000000..41eba8c8 --- /dev/null +++ b/examples/guide-supported-types-examples/package.json @@ -0,0 +1,10 @@ +{ + "scripts": { + "serve": "webpack-dev-server" + }, + "devDependencies": { + "webpack": "^4.11.1", + "webpack-cli": "^2.0.10", + "webpack-dev-server": "^3.1.0" + } +} diff --git a/examples/guide-supported-types-examples/src/exported_types.rs b/examples/guide-supported-types-examples/src/exported_types.rs new file mode 100644 index 00000000..018374cb --- /dev/null +++ b/examples/guide-supported-types-examples/src/exported_types.rs @@ -0,0 +1,6 @@ +use wasm_bindgen::prelude::*; + +#[wasm_bindgen] +pub struct RustType { + inner: u32, +} diff --git a/examples/guide-supported-types-examples/src/imported_types.rs b/examples/guide-supported-types-examples/src/imported_types.rs new file mode 100644 index 00000000..22578ca5 --- /dev/null +++ b/examples/guide-supported-types-examples/src/imported_types.rs @@ -0,0 +1,25 @@ +use wasm_bindgen::prelude::*; + +#[wasm_bindgen] +extern { + pub type SomeJsType; +} + +#[wasm_bindgen] +pub fn imported_type_by_value(x: SomeJsType) { /* ... */ } + +#[wasm_bindgen] +pub fn imported_type_by_shared_ref(x: &SomeJsType) { /* ... */ } + +#[wasm_bindgen] +pub fn return_imported_type() -> SomeJsType { + unimplemented!() +} + +#[wasm_bindgen] +pub fn take_option_imported_type(x: Option) { /* ... */ } + +#[wasm_bindgen] +pub fn return_option_imported_type() -> Option { + unimplemented!() +} diff --git a/examples/guide-supported-types-examples/src/lib.rs b/examples/guide-supported-types-examples/src/lib.rs new file mode 100755 index 00000000..afe92e4b --- /dev/null +++ b/examples/guide-supported-types-examples/src/lib.rs @@ -0,0 +1,7 @@ +#![feature(use_extern_macros)] +#![allow(unused_variables, dead_code)] + +extern crate wasm_bindgen; + +pub mod imported_types; +pub mod exported_types; diff --git a/examples/guide-supported-types-examples/webpack.config.js b/examples/guide-supported-types-examples/webpack.config.js new file mode 100644 index 00000000..dce27149 --- /dev/null +++ b/examples/guide-supported-types-examples/webpack.config.js @@ -0,0 +1,10 @@ +const path = require('path'); + +module.exports = { + entry: './index.js', + output: { + path: path.resolve(__dirname, 'dist'), + filename: 'index.js', + }, + mode: 'development' +}; diff --git a/guide/src/reference/types.md b/guide/src/reference/types.md index c3b0a7dc..a29d61fd 100644 --- a/guide/src/reference/types.md +++ b/guide/src/reference/types.md @@ -1,21 +1,122 @@ -# Supported Types +# Supported Rust Types and their JavaScript Representations -The table below provides an overview of all the types that `wasm-bindgen` can -send and receive across the WebAssembly ABI boundary. +This section provides an overview of all the types that `wasm-bindgen` can send +and receive across the WebAssembly ABI boundary, and how they translate into +JavaScript. -| Type | `T` parameter | `&T` parameter | `&mut T` parameter | `T` return value | `Option` parameter | `Option` return value | -|:---:|:---:|:---:|:---:|:---:|:---:| -| Imported `extern Whatever;` JavaScript Types | Yes | Yes | Yes | Yes | Yes | Yes | -| Exported `struct Whatever` Rust Types | Yes | Yes | Yes | Yes | Yes | Yes | -| `str` | No | Yes | No | Yes | Yes | No | -| `String` | Yes | No | No | Yes | Yes | Yes | -| `char` | Yes | No | No | Yes | No | No | -| `bool` | Yes | No | No | Yes | No | No | -| `JsValue` | Yes | Yes | Yes | Yes | No | No | -| `Box<[JsValue]>` | Yes | No | No | Yes | Yes | yes | -| `*const T` | Yes | No | No | Yes | No | No | -| `*mut T` | Yes | No | No | Yes | No | No | -| `u8` `i8` `u16` `i16` `u64` `i64` `isize` `size` | Yes | No | No | Yes | No | No | -| `u32` `i32` `f32` `f64` | Yes | Yes | Yes | Yes | No | No | -| `Box<[u8]>` `Box<[i8]>` `Box<[u16]>` `Box<[i16]>` `Box<[u32]>` `Box<[i32]>` `Box<[u64]>` `Box<[i64]>` `Box<[f32]>` `Box<[f64]`> | Yes | No | No | Yes | Yes | Yes | -| `[u8]` `[i8]` `[u16]` `[i16]` `[u32]` `[i32]` `[u64]` `[i64]` `[f32]` `[f64]` | No | Yes | Yes | No | Yes | No | +## Imported `extern Whatever;` JavaScript Types + +| `T` parameter | `&T` parameter | `&mut T` parameter | `T` return value | `Option` parameter | `Option` return value | JavaScript representation | +|:---:|:---:|:---:|:---:|:---:|:---:|:---:| +| Yes | Yes | No | Yes | Yes | Yes | Instances of the extant `Whatever` JavaScript class / prototype constructor | + +### Example Rust Usage + +```rust +{{#include ../../../examples/guide-supported-types-examples/src/imported_types.rs}} +``` + +### Example JavaScript Usage + +```js +{{#include ../../../examples/guide-supported-types-examples/imported_types.js}} +``` + +## Exported `struct Whatever` Rust Types + +| `T` parameter | `&T` parameter | `&mut T` parameter | `T` return value | `Option` parameter | `Option` return value | JavaScript representation | +|:---:|:---:|:---:|:---:|:---:|:---:|:---:| +| Yes | Yes | Yes | Yes | Yes | Yes | Instances of a `wasm-bindgen`-generated JavaScript `class Whatever { ... }` | + +### Example Rust Usage + +```rust +{{#include ../../../examples/guide-supported-types-examples/src/exported_types.rs}} +``` + +### Example JavaScript Usage + +```js +{{#include ../../../examples/guide-supported-types-examples/exported_types.js}} +``` + +## `str` + +| `T` parameter | `&T` parameter | `&mut T` parameter | `T` return value | `Option` parameter | `Option` return value | JavaScript representation | +|:---:|:---:|:---:|:---:|:---:|:---:|:---:| +| No | Yes | No | Yes | Yes | No | JavaScript string value | + +Copies the string's contents back and forth between the JavaScript +garbage-collected heap and the Wasm linear memory with `TextDecoder` and +`TextEncoder`. If you don't want to perform this copy, and would rather work +with handles to JavaScript string values, use the `js_sys::JsString` type. + +## `String` + +| `T` parameter | `&T` parameter | `&mut T` parameter | `T` return value | `Option` parameter | `Option` return value | JavaScript representation | +|:---:|:---:|:---:|:---:|:---:|:---:|:---:| +| Yes | No | No | Yes | Yes | Yes | JavaScript string value | + +Copies the string's contents back and forth between the JavaScript +garbage-collected heap and the Wasm linear memory with `TextDecoder` and +`TextEncoder` + +## `char` + +| `T` parameter | `&T` parameter | `&mut T` parameter | `T` return value | `Option` parameter | `Option` return value | JavaScript representation | +|:---:|:---:|:---:|:---:|:---:|:---:|:---:| +| Yes | No | No | Yes | No | No | A JavaScript string value | + +## `bool` + +| `T` parameter | `&T` parameter | `&mut T` parameter | `T` return value | `Option` parameter | `Option` return value | JavaScript representation | +|:---:|:---:|:---:|:---:|:---:|:---:|:---:| +| Yes | No | No | Yes | No | No | A JavaScript boolean value | + +## `wasm_bindgen::JsValue` + +| `T` parameter | `&T` parameter | `&mut T` parameter | `T` return value | `Option` parameter | `Option` return value | JavaScript representation | +|:---:|:---:|:---:|:---:|:---:|:---:|:---:| +| Yes | Yes | Yes | Yes | No | No | Any JavaScript value | + +## `Box<[JsValue]>` + +| `T` parameter | `&T` parameter | `&mut T` parameter | `T` return value | `Option` parameter | `Option` return value | JavaScript representation | +|:---:|:---:|:---:|:---:|:---:|:---:|:---:| +| Yes | No | No | Yes | Yes | Yes | A JavaScript `Array` object | + +## `*const T` `*mut T` + +| `T` parameter | `&T` parameter | `&mut T` parameter | `T` return value | `Option` parameter | `Option` return value | JavaScript representation | +|:---:|:---:|:---:|:---:|:---:|:---:|:---:| +| Yes | No | No | Yes | No | No | A JavaScript number value | + +## `u8` `i8` `u16` `i16` `u64` `i64` `isize` `size` + +| `T` parameter | `&T` parameter | `&mut T` parameter | `T` return value | `Option` parameter | `Option` return value | JavaScript representation | +|:---:|:---:|:---:|:---:|:---:|:---:|:---:| +| Yes | No | No | Yes | No | No | A JavaScript number value | + +## `u32` `i32` `f32` `f64` + +| `T` parameter | `&T` parameter | `&mut T` parameter | `T` return value | `Option` parameter | `Option` return value | JavaScript representation | +|:---:|:---:|:---:|:---:|:---:|:---:|:---:| +| Yes | Yes | Yes | Yes | No | No | A JavaScript number value | + +## `Box<[u8]>` `Box<[i8]>` `Box<[u16]>` `Box<[i16]>` `Box<[u32]>` `Box<[i32]>` `Box<[u64]>` `Box<[i64]>` `Box<[f32]>` `Box<[f64]>` + +| `T` parameter | `&T` parameter | `&mut T` parameter | `T` return value | `Option` parameter | `Option` return value | JavaScript representation | +|:---:|:---:|:---:|:---:|:---:|:---:|:---:| +| Yes | No | No | Yes | Yes | Yes | A JavaScript `TypedArray` view of the Wasm memory for the boxed slice of the appropriate type (`Int32Array`, `Uint8Array`, etc) | + +Note that this does ***not*** copy the whole slice of memory back and forth into +the JavaScript heap from the Wasm linear memory. + +## `[u8]` `[i8]` `[u16]` `[i16]` `[u32]` `[i32]` `[u64]` `[i64]` `[f32]` `[f64]` + +| `T` parameter | `&T` parameter | `&mut T` parameter | `T` return value | `Option` parameter | `Option` return value | JavaScript representation | +|:---:|:---:|:---:|:---:|:---:|:---:|:---:| +| No | Yes | Yes | No | Yes | No | A JavaScript `TypedArray` view of the Wasm memory for the boxed slice of the appropriate type (`Int32Array`, `Uint8Array`, etc) | + +Note that this does ***not*** copy the whole slice of memory back and forth into +the JavaScript heap from the Wasm linear memory.