WebAssemblyがDOM、APIに対応します!
WebAssemblyはWebアプリケーションを高速に処理できる技術ですが、幾つかの欠点もありました。その一つがDOMを処理できないこと、さらにFetch APIやWebAudioなどのAPIが使えない点です。
しかし先日Announcing the web-sys crate! | Rust and WebAssemblyがアナウンスされ、WebAssemblyでもDOMや各種APIの利用が可能となっています。
実際にはラッピング?
今回発表されたのはweb-sysというクレート(パッケージ)です。すでにWebAssemblyに対応しているWebブラウザであれば利用可能となっていることから、WebAssemblyエンジン自体のバージョンアップは不要なようです。そのため、DOMやAPI操作はメインスレッド側のJavaScriptで行っているかと思われます。ただし、Fetch APIで使ったURLなどはWebブラウザ側のソースにはありませんでした(ネットワークログを見ると、どこにアクセスしたかは分かります)。
Hello World
Hello Worldのアラートを出す場合のコードです。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
extern crate wasm_bindgen; | |
use wasm_bindgen::prelude::*; | |
#[wasm_bindgen] | |
extern "C" { | |
fn alert(s: &str); | |
} | |
#[wasm_bindgen] | |
pub fn greet(name: &str) { | |
alert(&format!("Hello, {}!", name)); | |
} |
DOM操作
DOMに記述する際のコードです。 web_sys
クレートを介してWindowやDocumentにアクセスできます。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
extern crate wasm_bindgen; | |
extern crate web_sys; | |
use wasm_bindgen::prelude::*; | |
#[wasm_bindgen] | |
pub fn run() -> Result<(), JsValue> { | |
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"); | |
let val = document.create_element("p")?; | |
val.set_inner_html("Hello from Rust!"); | |
AsRef::<web_sys::Node>::as_ref(&body).append_child(val.as_ref())?; | |
Ok(()) | |
} |
Fetch API
Fetch APIを使って外部リソースを取得するコードです。Promiseを使います。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
extern crate futures; | |
extern crate js_sys; | |
extern crate wasm_bindgen; | |
extern crate wasm_bindgen_futures; | |
extern crate web_sys; | |
#[macro_use] | |
extern crate serde_derive; | |
use futures::{future, Future}; | |
use js_sys::Promise; | |
use wasm_bindgen::prelude::*; | |
use wasm_bindgen::JsCast; | |
use wasm_bindgen_futures::future_to_promise; | |
use wasm_bindgen_futures::JsFuture; | |
use web_sys::{Request, RequestInit, RequestMode, Response}; | |
#[derive(Debug, Serialize, Deserialize)] | |
pub struct Branch { | |
pub name: String, | |
pub commit: Commit, | |
} | |
#[derive(Debug, Serialize, Deserialize)] | |
pub struct Commit { | |
pub sha: String, | |
pub commit: CommitDetails, | |
} | |
#[derive(Debug, Serialize, Deserialize)] | |
pub struct CommitDetails { | |
pub author: Signature, | |
pub committer: Signature, | |
} | |
#[derive(Debug, Serialize, Deserialize)] | |
pub struct Signature { | |
pub name: String, | |
pub email: String, | |
} | |
#[wasm_bindgen] | |
pub fn run() -> Promise { | |
let mut opts = RequestInit::new(); | |
opts.method("GET"); | |
opts.mode(RequestMode::Cors); | |
let request = Request::new_with_str_and_init( | |
"https://api.github.com/repos/rustwasm/wasm-bindgen/branches/master", | |
&opts, | |
).unwrap(); | |
request | |
.headers() | |
.set("Accept", "application/vnd.github.v3+json") | |
.unwrap(); | |
let window = web_sys::window().unwrap(); | |
let request_promise = window.fetch_with_request(&request); | |
let future = JsFuture::from(request_promise) | |
.and_then(|resp_value| { | |
assert!(resp_value.is_instance_of::<Response>()); | |
let resp: Response = resp_value.dyn_into().unwrap(); | |
resp.json() | |
}).and_then(|json_value: Promise| { | |
JsFuture::from(json_value) | |
}).and_then(|json| { | |
let branch_info: Branch = json.into_serde().unwrap(); | |
future::ok(JsValue::from_serde(&branch_info).unwrap()) | |
}); | |
future_to_promise(future) | |
} |
rustwasm/wasm-bindgen: Facilitating high-level interactions between wasm modules and JavaScriptに多数のサンプルが掲載されていますので、ぜひコードを見てください。動いているコードはExamples – The wasm-bindgen
Guideにて確認できます。WebGLやCanvas、WebAudioなどのサンプルが掲載されています。
コメントは受け付けていません。