{"id":24659123,"url":"https://github.com/viftodi/wasm_val","last_synced_at":"2025-10-07T21:31:39.755Z","repository":{"id":57671931,"uuid":"140486000","full_name":"viftodi/wasm_val","owner":"viftodi","description":"A Rust library that provides a typesafe API to call javascript from a wasm program","archived":false,"fork":false,"pushed_at":"2019-03-04T20:28:00.000Z","size":108,"stargazers_count":9,"open_issues_count":0,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2024-12-28T15:46:12.677Z","etag":null,"topics":["javascript","rust","rust-library","rust-wasm","wasm"],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/viftodi.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-07-10T20:50:50.000Z","updated_at":"2024-08-08T14:42:01.000Z","dependencies_parsed_at":"2022-08-30T19:21:37.023Z","dependency_job_id":null,"html_url":"https://github.com/viftodi/wasm_val","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/viftodi%2Fwasm_val","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/viftodi%2Fwasm_val/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/viftodi%2Fwasm_val/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/viftodi%2Fwasm_val/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/viftodi","download_url":"https://codeload.github.com/viftodi/wasm_val/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":235656465,"owners_count":19024772,"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":["javascript","rust","rust-library","rust-wasm","wasm"],"created_at":"2025-01-26T02:32:00.335Z","updated_at":"2025-10-07T21:31:34.417Z","avatar_url":"https://github.com/viftodi.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# wasm_val a rust wasm library that provides a type-safe API that can dynamically call into javascript.\r\n\r\n## Introduction\r\nwasm-val is a rust library accompanied by a javascript counterpart helper that provides a type-safe API to access dynamically into javascript.\r\n\r\nIt has been inspired by the emscripten's C++ [Val](https://kripken.github.io/emscripten-site/docs/porting/connecting_cpp_and_javascript/embind.html#using-val-to-transliterate-javascript-to-c) as well as the Graal-VM polyglot [Context](http://www.graalvm.org/sdk/javadoc/org/graalvm/polyglot/Context.html) API.\r\n\r\nWhile I am aware that there are already more mature solutions out there that allow to call into javascript from a rust wasm, such as wasm-bind I believe an alternative way of doing it could always be appreciated.\r\n\r\nThe end goal of this project is to have a dynamic and type-safe API to access any javascript API provided by the browser.\r\n\r\nThis is my first Rust project and it's been and I hope will continue to be a great learning experience as I discover more and more of rust.\r\n\r\n\r\n## License\r\n\r\nThis project is dual licenced under Apache 2 and the MIT license.\r\n\r\nFor more details check the LICENCE.md file\r\n\r\n## Preview\r\n\r\nIt is currently possible to obtain values from javascript and get/set their properties as well as call method on javascript objects.\r\n\r\nIt is also possible to call constructors and obtain functions for repeated calls.\r\n\r\nBelow is an example demonstrating various features:\r\n\r\n```rust\r\n// You can obtain a value from the global context\r\nlet document = JsValue::get_global(\"document\");\r\nlet body = document.get_val(\"body\").unwrap(); \r\n// And get a property of such a value\r\nlet title = document.get_val(\"title\").unwrap().as_str().unwrap();\r\nlet from_rust = format!(\"Hello from rust \u003c3 your title is: {}\", title);\r\n// You can also call a constructor\r\nlet textNode = document.call_method_with_arg(\"createTextNode\", from_rust.as_str()).unwrap();\r\n// Pass a previously obtained javascript value back to javascript\r\nbody.call_method_with_arg(\"appendChild\", textNode);\r\n\r\n// If you plan to call a function multiple times for efficiently reasons you can obtain a reference to it:\r\nlet console = JSValue::get_global(\"console\");\r\nlet console_log = console.get_val(\"log\").unwrap();\r\n\r\nconsole_log.call_with_arg(\"Hello world\");\r\nconsole_log.call_with_args(\u0026[\u0026\"hello world\", \u0026true, \u0026\" \", \u00263.14]);\r\n\r\n// You can also pass a closure on the javascript side, useful for registering callbacks\r\nconst CLOSURE: \u0026dyn Fn(JsValue) -\u003e () = \u0026|val: JsValue| {\r\n    let key_code = val.get_val(\"keyCode\").unwrap();\r\n\r\n    let console = JsValue::get_global(\"console\");\r\n\r\n    console.call_method_with_args(\"log\", \u0026[\"Keydown pressed :\", \u0026key_code]);\r\n};\r\n\r\nbody.call_method_with_args(\"addEventListener\", \u0026[\u0026\"keydown\", \u0026CLOSURE]);\r\n```\r\n\r\nThe following types implement the JsSerializable trait and can be send from rust to javascript:\r\n\r\n - boolean\r\n - primitive numeric types (except i64/u64)\r\n - str\r\n - String\r\n - JsValue (values obtained from javascript)\r\n - Fn() -\u003e () and Fn(JSValue) -\u003e () that are useful mostly to register event callbacks\r\n\r\n## JsSerializable \r\n\r\nJsSerializable is a trait that is implemented for certain types to allow passing values between rust and wasm.\r\n\r\nIf you want to pass a closure that returns a value (say for a promise), the return type must be a Box\u0026lt;JsSerializable\u0026gt;\r\n\r\nFor example:\r\n\r\n```rust\r\nuse wasm_val::{JsValue, JsSerializable};\r\n\r\nconst CLOSURE: \u0026dyn Fn() -\u003e (Box\u003cJsSerializable\u003e) = \u0026|val: JsValue| {\r\n    return Box::new(42);\r\n};\r\n````\r\n\r\n## Examples\r\n\r\nThere are multiple examples provided in the examples folder :\r\n - hello_world : shows the ability to get and set values, as well as call functions.\r\n - clock : makes use of the ability to call constructors and shows a basic animation managed by javascript\r\n - create_element : showcases mainly the ability to call functions with multiple parameters\r\n - canvas_animate_solar_system : A more complete example that has been adapted from the canvas animation example on mozilla's site\r\n - register_event_callback : Register callbacks on the rust side to animate the movement of a rectangle in a canvas\r\n - webgl_animate_squares : On click add a random animate square. Makes use of the ability to pass TypedArrays to javascript\r\n\r\n## Get started\r\n\r\nThe project has two parts: \r\n wasm_val the rust library that provides the API and wasm_val_module which is the javascript counterpart that allows the interfacing with rust.\r\n\r\n###  On the rust side\r\n\r\nIf you haven't done it already, add the wasm32-unknown-unknown target via rustup:\r\n\r\n```bash\r\nrustup target add wasm32-unknown-unknown\r\n```\r\n\r\nAdd the wasm_val depencendy to your Cargo.toml\r\n\r\n```toml\r\n[dependencies]\r\nwasm_val = \"0.3.5\"\r\n```\r\n\r\nIt is also important to also declare your rust project type as cdylib.\r\nFor example:\r\n\r\n```toml\r\n[lib]\r\npath = \"src/lib.rs\"\r\ncrate-type = [\"cdylib\"]\r\n```\r\n\r\nIn your main lib.rs declare the wasm_val crate\r\n\r\nAlso export an extern \"C\" main function with the #[no_mangle] atribute so that it can be accessible from javascript.\r\n\r\nBellow is a hello world example.\r\n\r\n```rust\r\nextern crate wasm_val;\r\n\r\nuse wasm_val::{JsValue};\r\n\r\n#[no_mangle]\r\npub extern \"C\" fn main() -\u003e () {\r\n    let console = JsValue::get_global(\"console\");\r\n\r\n    console.call_with_arg(\"log\", \"Hello from Rust :)\");\r\n}\r\n```\r\n\r\nNote: It is recommended to always build your project in release mode due to current limitations of the wasm32-unknown-unknown target. For example:\r\n\r\n```bash\r\ncargo build --target=wasm32-unknown-unknown --release\r\n````\r\n\r\n### On the javascript side\r\n\r\nAssuming you're in the folder where your web-app resides.\r\n\r\nFirstly either install the wasm_val_module using npm :\r\n\r\n```bash\r\nnpm install wasm_val_module@0.3.5\r\n\r\n```\r\n\r\nOr obtain it manually from this repository.\r\n\r\nThen in your index.html or equivalent:\r\n\r\n```html\r\n\u003cscript type=\"module\"\u003e\r\n    import { WasmValModule } from \"./node_modules/wasm-val-module/wasm_val_module.js\";\r\n    const mod = new WasmValModule('path/to/rust_lib.wasm', window);\r\n\r\n    mod.run()\r\n        .then((instance) =\u003e {\r\n            instance.exports.main();\r\n        });\r\n\u003c/script\u003e\r\n````\r\n\r\nThe WasmValModule constructor takes the path to the wasm file as well as a context object as well as an optional options object. \r\n\r\nThe context object is what provides the accessible javascript members on the rust side.\r\n\r\nThe default options are:\r\n\r\n```javascript\r\n{\r\n    rust_panic: {\r\n        register_hook: true,\r\n        panic_fn: console.error,\r\n    }\r\n}\r\n```\r\n\r\nConsult the documentation of wasm_val_module for additional information.\r\n\r\nAnd hopefully that's it.\r\n\r\n\r\n## Known issues and limitations\r\n\r\nCurrently rust closures send to the javascript side (such as event listeners) are never garbage collected. Use them sparingly. ","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fviftodi%2Fwasm_val","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fviftodi%2Fwasm_val","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fviftodi%2Fwasm_val/lists"}