{"id":20073619,"url":"https://github.com/ragingwind/wasm-bindgen-summary","last_synced_at":"2025-07-05T18:33:55.707Z","repository":{"id":139546862,"uuid":"192240233","full_name":"ragingwind/wasm-bindgen-summary","owner":"ragingwind","description":"Summary for wasm-bindgen","archived":false,"fork":false,"pushed_at":"2019-06-24T23:04:44.000Z","size":183792,"stargazers_count":5,"open_issues_count":1,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-05-05T21:34:49.280Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ragingwind.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-06-16T21:53:30.000Z","updated_at":"2021-12-22T03:10:45.000Z","dependencies_parsed_at":null,"dependency_job_id":"dbaf721b-2b60-4307-916e-f01cb5c03d7a","html_url":"https://github.com/ragingwind/wasm-bindgen-summary","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/ragingwind/wasm-bindgen-summary","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ragingwind%2Fwasm-bindgen-summary","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ragingwind%2Fwasm-bindgen-summary/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ragingwind%2Fwasm-bindgen-summary/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ragingwind%2Fwasm-bindgen-summary/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ragingwind","download_url":"https://codeload.github.com/ragingwind/wasm-bindgen-summary/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ragingwind%2Fwasm-bindgen-summary/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":263785031,"owners_count":23511024,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-13T14:47:00.968Z","updated_at":"2025-07-05T18:33:55.673Z","avatar_url":"https://github.com/ragingwind.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# wasm-bindgen\n\n\u003e Rust library and CLI tool that faclitate high-level interactions between wasm modules and\n\u003e Javascript.\n\n## Hello, World\n\n- `crate-type = [\"cdylib\"]` is largely used for wasm file final artifacts today\n- Install [wasm-pack](https://rustwasm.github.io/wasm-pack/installer/) via curl\n- wasm-pack supports a variety options of target to bundle wasm\n\n## console.log\n\n- `#[wasm_bindgen(start)]` will be running implicitly after loading wasm\n- binding js apis by `#[wasm_bindgen(js_namespace = console, js_name = log)]`\n- using `web_sys::console::log_1`\n\n## Small wasm files\n\n- `[wasm-bindgen]` generate small size bundle\n- `wasm-opt` can make it even smaller\n- `wasm2wat` can make it quite smaller\n- using `lto`, Link Time Optimization option for release\n\n```toml\n[profile.release]\nlto = true\n```\n\n## Converting WebAssembly to JS\n\n- [Toolchain for WebAssembly](https://github.com/WebAssembly/binaryen), wasm2js, convert a wasm file to js\n- `wasm2js pkg/wasm2js_bg.wasm -o pkg/wasm2js_bg.js`\n\n## Importing non-browser JS\n\n```rust\nuse wasm_bindgen::prelude::*;\n\n// raw_module has been added, you can use relative path\n#[wasm_bindgen(module = \"/defined-in-js.js\")]\nextern \"C\" {\n    #[wasm_bindgen(constructor)]\n    fn new() -\u003e MyClass;\n\n    #[wasm_bindgen(method, getter)]\n    fn number(this: \u0026MyClass) -\u003e u32;\n    #[wasm_bindgen(method, setter)]\n    fn set_number(this: \u0026MyClass, number: u32) -\u003e MyClass;\n    #[wasm_bindgen(method)]\n    fn render(this: \u0026MyClass) -\u003e String;\n}\n```\n\n## Working with `char`\n\n- `#[wasm_bindgen] macro` will convert the rust char type to a single code-point js string\n\n```rust\n#[wasm_bindgen]\n#[derive(Debug)]\npub struct Counter {\n    key: char,\n    count: i32,\n}\n\n...\n\npub fn increment(\u0026mut self) {\n    log(\"Counter.increment\");\n    self.count += 1;\n}\n```\n\n## js-sys: WebAssembly in WebAssembly\n\n- `const WASM: \u0026[u8] = include_bytes!(\"add.wasm\");`\n\n## web-sys: DOM hello world\n\n- enable all the various APIs\n\n```\n[dependencies.web-sys]\nversion = \"0.3.4\"\nfeatures = [\n  'Document',\n  'Element',\n  'HtmlElement',\n  'Node',\n  'Window',\n]\n```\n\n- get elements\n\n```rust\nlet window = web_sys::window().expect(\"no global 'window' exists\");\nlet document = window.document().expect(\"should have a document on window\");\nlet body = document.body().expect(\"document should have a body\");\n```\n\n## web-sys: Closure\n\n- array function\n\n```rust\narray.for_each(\u0026mut |obj, idx, _arr| match idx { ... });\n```\n\n- timer\n\n```rust\nupdate_time(\u0026current_time);\n\nlet a = Closure::wrap(Box::new(move || update_time(\u0026current_time)) as Box\u003cdyn Fn()\u003e);\nwindow\n    .set_interval_with_callback_and_timeout_and_arguments_0(a.as_ref().unchecked_ref(), 1000)?;\n\nfn update_time(current_time: \u0026Element) {\n    current_time.set_inner_html(\u0026String::from(\n        Date::new_0().to_locale_string(\"en-GB\", \u0026JsValue::undefined()),\n    ));\n}\n```\n\n- click\n\n```rust\nlet mut clicks = 0;\nlet a = Closure::wrap(Box::new(move || {\n    clicks += 1;\n}) as Box\u003cdyn FnMut()\u003e);\n\ndocument\n  .get_element_by_id(\"green-square\")\n  .dyn_ref::\u003cHtmlElement\u003e()\n  .set_onclick(Some(a.as_ref().unchecked_ref()));\na.forget();\n```\n\n## web-sys: performance.now\n\n```rust\nlet start = perf_to_system(performance.timing().request_start());\nlet end = perf_to_system(performance.timing().response_end());\n```\n\n## web-sys: The fetch API\n\n```rust\nlet request = Request::new_with_str_and_init(\n      \"https://api.github.com/repos/rustwasm/wasm-bindgen/branches/master\",\n      \u0026opts,\n  )\n  .unwrap();\n\nrequest\n    .headers()\n    .set(\"Accept\", \"application/vnd.github.v3+json\")\n    .unwrap();\n\nlet window = web_sys::window().unwrap();\nlet request_promise = window.fetch_with_request(\u0026request);\n\nlet future = JsFuture::from(request_promise)\n    .and_then(|resp_value| {\n        // `resp_value` is a `Response` object.\n        assert!(resp_value.is_instance_of::\u003cResponse\u003e());\n        let resp: Response = resp_value.dyn_into().unwrap();\n        resp.json()\n    })\n    .and_then(|json_value: Promise| {\n        // Convert this other `Promise` into a rust `Future`.\n        JsFuture::from(json_value)\n    })\n    .and_then(|json| {\n        // Use serde to parse the JSON into a struct.\n        let branch_info: Branch = json.into_serde().unwrap();\n\n        // Send the `Branch` struct back to JS as an `Object`.\n        future::ok(JsValue::from_serde(\u0026branch_info).unwrap())\n    });\n\n// Convert this Rust `Future` back into a JS `Promise`.\nfuture_to_promise(future)\n```\n\n## web-sys: 2D Canvas\n\n```rust\nlet context = canvas\n        .get_context(\"2d\")\n        .unwrap()\n        .unwrap()\n        .dyn_into::\u003cweb_sys::CanvasRenderingContext2d\u003e()\n        .unwrap();\n```\n\n## web-sys: WebAudio\n\n```rust\nlet ctx = web_sys::AudioContext::new()?;\n\n// Create our web audio objects.\nlet primary = ctx.create_oscillator()?;\nlet fm_osc = ctx.create_oscillator()?;\nlet gain = ctx.create_gain()?;\nlet fm_gain = ctx.create_gain()?;\n\n// Some initial settings:\nprimary.set_type(OscillatorType::Sine);\nprimary.frequency().set_value(440.0); // A4 note\ngain.gain().set_value(0.0); // starts muted\nfm_gain.gain().set_value(0.0); // no initial frequency modulation\nfm_osc.set_type(OscillatorType::Sine);\nfm_osc.frequency().set_value(0.0);\n```\n\n## web-sys: WebGL\n\n```rust\nlet canvas = document.get_element_by_id(\"canvas\").unwrap();\nlet canvas: web_sys::HtmlCanvasElement = canvas.dyn_into::\u003cweb_sys::HtmlCanvasElement\u003e()?;\n\nlet context = canvas\n    .get_context(\"webgl\")?\n    .unwrap()\n    .dyn_into::\u003cWebGlRenderingContext\u003e()?;\n\nlet vert_shader = compile_shader(\n    \u0026context,\n    WebGlRenderingContext::VERTEX_SHADER,\n    r#\"\n    attribute vec4 position;\n    void main() {\n        gl_Position = position;\n    }\n\"#,\n)?;\nlet frag_shader = compile_shader(\n    \u0026context,\n    WebGlRenderingContext::FRAGMENT_SHADER,\n    r#\"\n    void main() {\n        gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);\n    }\n\"#,\n)?;\nlet program = link_program(\u0026context, \u0026vert_shader, \u0026frag_shader)?;\ncontext.use_program(Some(\u0026program));\n```\n\n## web-sys: WebSockets\n\n```rust\nlet ws = WebSocket::new(\"wss://echo.websocket.org\")?;\n\nlet onmessage_callback = Closure::wrap(Box::new(move |e: MessageEvent| {\n    let response = e\n        .data()\n        .as_string()\n        .expect(\"Can't convert received data to a string\");\n    console_log!(\"message event, received data: {:?}\", response);\n}) as Box\u003cdyn FnMut(MessageEvent)\u003e);\n```\n\n## web-sys: rAF\n\n```rust\nwindow()\n      .request_animation_frame(f.as_ref().unchecked_ref())\n      .expect(\"should register 'ra' ok\");\n```\n\n## web-sys: paint\n\n```rust\nlet closure = Closure::wrap(Box::new(move |event: web_sys::MouseEvent| {\n    context.begin_path();\n    context.move_to(event.offset_x() as f64, event.offset_y() as f64);\n    pressed.set(true);\n}) as Box\u003cdyn FnMut(_)\u003e);\ncanvas.add_event_listener_with_callback(\"mousedown\", closure.as_ref().unchecked_ref())?;\nclosure.forget();\n```\n\n## web-sys: Parallel Raytracing [WIP]\n\n```rust\nuse web_sys::{ErrorEvent, Event, Worker};\n...\nlet worker = Worker::new(\"./worker.js\")?;\nlet array = js_sys::Array::new();\narray.push(\u0026wasm_bindgen::module());\narray.push(\u0026wasm_bindgen::memory());\nworker.post_message(\u0026array)?;\n```\n\n## TODO MVC using wasm-bingen and web-sys\n\n- deletate API set for elements\n\n```rust\nimpl Element {\n    pub fn create_element(tag: \u0026str) -\u003e Option\u003cElement\u003e {\n        if let Some(el) = web_sys::window()?.document()?.create_element(tag).ok() {\n            Some(el.into())\n        } else {\n            None\n        }\n    }\n\n    pub fn qs(selector: \u0026str) -\u003e Option\u003cElement\u003e {\n        let body: web_sys::Element = web_sys::window()?.document()?.body()?.into();\n        let el = body.query_selector(selector).ok()?;\n        Some(Element { el })\n    }\n\n    pub fn add_event_listener\u003cT\u003e(\u0026mut self, event_name: \u0026str, handler: T)\n    where\n        T: 'static + FnMut(web_sys::Event),\n    {\n        let cb = Closure::wrap(Box::new(handler) as Box\u003cdyn FnMut(_)\u003e);\n        if let Some(el) = self.el.take() {\n            let el_et: EventTarget = el.into();\n            el_et\n                .add_event_listener_with_callback(event_name, cb.as_ref().unchecked_ref())\n                .unwrap();\n            cb.forget();\n            if let Ok(el) = el_et.dyn_into::\u003cweb_sys::Element\u003e() {\n                self.el = Some(el);\n            }\n        }\n    }\n}\n```\n\n- event binding and managing for route changing\n\n```rust\nlet set_page = Closure::wrap(Box::new(move || {\n    if let Some(location) = document.location() {\n        if let Ok(hash) = location.hash() {\n            if let Ok(sched) = \u0026(sched.try_borrow_mut()) {\n                sched.add_message(Message::Controller(ControllerMessage::SetPage(hash)));\n            }\n        }\n    }\n}) as Box\u003cdyn FnMut()\u003e);\n\nlet window_et: web_sys::EventTarget = window.into();\nwindow_et\n    .add_event_listener_with_callback(\"hashchange\", set_page.as_ref().unchecked_ref())\n    .unwrap();\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fragingwind%2Fwasm-bindgen-summary","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fragingwind%2Fwasm-bindgen-summary","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fragingwind%2Fwasm-bindgen-summary/lists"}