Strangely enough getting the instance from the Window object seems to require an unchecked cast.
// file: greeting/greeting.js
export class Greeting {
constructor(msg, recipient) {
this.msg = msg;
this.recipient = recipient;
}
greet() {
console.log(`${this.msg} ${this.recipient}`);
}
}
<html>
<!--
greeting/index.html
Based on:
https://rustwasm.github.io/docs/wasm-bindgen/examples/without-a-bundler.html
With Chrome Version 79.0.3945.88 (Official Build) (64-bit)
-->
<head>
<meta content="text/html;charset=utf-8" http-equiv="Content-Type"/>
</head>
<body>
<script type="module">
import { Greeting } from './greeting.js';
import init from './pkg/greeter.js';
window.greeting = new Greeting("Hello", "World");
init().then(module => {
module.greet();
}).catch(error => {
console.log(error);
});
</script>
</body>
</html>
// file: greeting/src/lib.rs
use wasm_bindgen::prelude::*;
use wasm_bindgen::JsCast;
use js_sys::{Error, Reflect};
use web_sys::{console};
// A macro to provide `println!(..)`-style syntax for `console.log` logging.
#[allow(unused_macros)]
macro_rules! log {
( $( $t:tt )* ) => {
console::log_1(&format!( $( $t )* ).into());
}
}
#[wasm_bindgen(module = "/greeting.js")]
extern "C" {
type Greeting;
#[wasm_bindgen(constructor)]
fn new(msg: &str, recipient: &str) -> Greeting;
#[wasm_bindgen(method)]
fn greet(this: &Greeting);
}
#[wasm_bindgen]
pub fn greet() -> Result<(),JsValue> {
log!("greet");
demo_it();
if let Some(window) = web_sys::window() {
match Reflect::get(&window, &JsValue::from_str("greeting")) {
Ok(value) if Ok(true) == Reflect::has(&value, &JsValue::from_str("greet")) => {
check_it("two", &value);
let x = value.unchecked_ref::<Greeting>();
x.greet();
Ok(())
},
_ =>
Err(Error::new("Window object doesn't have a suitable \"greeting\" property").into())
}
} else {
Err(Error::new("Can't access Window object").into())
}
}
fn check_it(label: &str, value: &JsValue) {
let result =
if value.has_type::<Greeting>() {
"checked cast will succeed"
} else {
"checked cast will fail"
};
console::log_2(
&format!("{}: {} ", label, result).into(),
value
);
}
fn demo_it() {
let x = Greeting::new("Hi", "there!");
check_it("one", &x);
x.greet();
}
/*
https://rustwasm.github.io/docs/wasm-bindgen/
https://rustwasm.github.io/wasm-bindgen/api/web_sys/fn.window.html
https://rustwasm.github.io/docs/wasm-bindgen/reference/types/result.html
https://rustwasm.github.io/wasm-bindgen/api/wasm_bindgen/struct.JsValue.html
https://rustwasm.github.io/wasm-bindgen/api/js_sys/struct.Error.html
https://rustwasm.github.io/docs/wasm-bindgen/contributing/design/importing-js-struct.html
https://rustwasm.github.io/wasm-bindgen/api/wasm_bindgen/trait.JsCast.html
*/
# file: greeting/Cargo.toml
[package]
name = "greeter"
version = "0.1.0"
edition = "2018"
[lib]
crate-type = ["cdylib"]
[dependencies]
wasm-bindgen = "0.2.56"
js-sys = "0.3.33"
[dependencies.web-sys]
version = "0.3.4"
features = [
'console',
'Window',
]
greeting$ wasm-pack build --target web
[INFO]: 🎯 Checking for the Wasm target...
[INFO]: 🌀 Compiling to Wasm...
Compiling proc-macro2 v1.0.7
Compiling unicode-xid v0.2.0
Compiling log v0.4.8
Compiling wasm-bindgen-shared v0.2.56
Compiling syn v1.0.13
Compiling cfg-if v0.1.10
Compiling lazy_static v1.4.0
Compiling bumpalo v2.6.0
Compiling memchr v2.2.1
Compiling version_check v0.1.5
Compiling anyhow v1.0.26
Compiling unicode-segmentation v1.6.0
Compiling wasm-bindgen v0.2.56
Compiling sourcefile v0.1.4
Compiling heck v0.3.1
Compiling nom v4.2.3
Compiling quote v1.0.2
Compiling weedle v0.10.0
Compiling wasm-bindgen-backend v0.2.56
Compiling wasm-bindgen-macro-support v0.2.56
Compiling wasm-bindgen-webidl v0.2.56
Compiling wasm-bindgen-macro v0.2.56
Compiling js-sys v0.3.33
Compiling web-sys v0.3.33
Compiling greeter v0.1.0 (/Users/wheatley/sbox/rasm/greeting)
Finished release [optimized] target(s) in 46.47s
⚠️ [WARN]: origin crate has no README
[INFO]: ⬇️ Installing wasm-bindgen...
[INFO]: Optional fields missing from Cargo.toml: 'description', 'repository', and 'license'. These are not necessary, but recommended
[INFO]: ✨ Done in 46.58s
[INFO]: 📦 Your wasm pkg is ready to publish at ./pkg.
greeting$ http-server ./ -c-1
Starting up http-server, serving ./
Available on:
http://127.0.0.1:8080
http://192.168.1.187:8080
Hit CTRL-C to stop the server
Developer console for localhost:8080/index.html
:
greet
greeter.js:94 one: checked cast will succeed Greeting {msg: "Hi", recipient: "there!"}
greeting.js:10 Hi there!
greeter.js:94 two: checked cast will fail Greeting {msg: "Hello", recipient: "World"}
greeting.js:10 Hello World