2019/04/05 10:00 am
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のアラートを出す場合のコードです。
| 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に記述する際のコードです。 web_sys クレートを介してWindowやDocumentにアクセスできます。
| 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を使って外部リソースを取得するコードです。Promiseを使います。
| 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などのサンプルが掲載されています。
作成者: moongift
カテゴリー: HTML5
タグ: WebAssembly
Mobile Site | Full Site
Get a free blog at WordPress.com Theme: WordPress Mobile Edition by Alex King.