Add a smorgasboard example

This commit is contained in:
Alex Crichton 2018-03-02 20:19:39 -08:00
parent 4aa6793b9e
commit 4ebb3df330
14 changed files with 213 additions and 1 deletions

View File

@ -17,4 +17,5 @@ test-support = { path = "crates/test-support" }
members = [
"crates/wasm-bindgen-cli",
"examples/hello_world",
"examples/smorgasboard",
]

View File

@ -223,6 +223,12 @@ $ npm run serve
If you open https://localhost:8080 in a browser you should see a `Hello, world!`
dialog pop up!
If that was all a bit much, no worries! You can [follow along
online][hello-tree] to see all the files necessary as well as a script to set it
all up.
[hello-tree]: https://github.com/alexcrichton/wasm-bindgen/tree/master/examples/hello_world
## What just happened?
Phew! That was a lot of words and a lot ended up happening along the way. There
@ -329,7 +335,7 @@ extern {
#[wasm_bindgen]
impl Bar {
pub fn from_str(s: &str, opaque: JsValue) -> Bar {
let contents = s.parse().unwrap_or_else(|| {
let contents = s.parse().unwrap_or_else(|_| {
Awesome::new().get_internal()
});
Bar { contents, opaque }

View File

@ -9,3 +9,6 @@ The examples here are:
* `hello_world` - the "hello world" of `#[wasm_bindgen]`, aka throwing up a
dialog greeting you
* `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

3
examples/smorgasboard/.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
package-lock.json
smorgasboard.js
smorgasboard_wasm.wasm

View File

@ -0,0 +1,14 @@
[package]
name = "smorgasboard"
version = "0.1.0"
authors = ["Alex Crichton <alex@alexcrichton.com>"]
[lib]
crate-type = ["cdylib"]
[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 = { git = "https://github.com/alexcrichton/wasm-bindgen" }

View File

@ -0,0 +1,16 @@
# Smorgasboard of examples
This directory is an 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.

View File

@ -0,0 +1,32 @@
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 the `new Foo()` syntax cannot be used, static function
// constructors must be used instead. 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 = Foo.new();
assertEq(foo.add(10), 10);
foo.free();
// Pass objects to one another
let foo1 = Foo.new();
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!')

View File

@ -0,0 +1,14 @@
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;
}
}

15
examples/smorgasboard/build.sh Executable file
View File

@ -0,0 +1,15 @@
#!/bin/sh
set -ex
cargo +nightly build --target wasm32-unknown-unknown --release
# 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/wasm-bindgen-cli/Cargo.toml \
--bin wasm-bindgen -- \
../../target/wasm32-unknown-unknown/release/smorgasboard.wasm --out-dir .
# wasm-bindgen ../../target/wasm32-unknown-unknown/hello_world.wasm --out-dir .
npm install
npm run serve

View File

@ -0,0 +1,8 @@
<html>
<head>
<meta content="text/html;charset=utf-8" http-equiv="Content-Type"/>
</head>
<body>
<script src='./index.js'></script>
</body>
</html>

View File

@ -0,0 +1 @@
import("./app");

View File

@ -0,0 +1,10 @@
{
"scripts": {
"serve": "webpack-dev-server"
},
"devDependencies": {
"webpack": "^4.0.1",
"webpack-cli": "^2.0.10",
"webpack-dev-server": "^3.1.0"
}
}

View File

@ -0,0 +1,79 @@
#![feature(proc_macro)]
extern crate wasm_bindgen;
use wasm_bindgen::prelude::*;
// Strings can both be passed in and received
#[wasm_bindgen]
#[no_mangle]
pub extern 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 {
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 {
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;
}
}
}

View File

@ -0,0 +1,10 @@
const path = require('path');
module.exports = {
entry: "./index.js",
output: {
path: path.resolve(__dirname, "dist"),
filename: "index.js",
},
mode: "development"
};