wasm-bindgen/print.html

6962 lines
328 KiB
HTML
Raw Blame History

<!DOCTYPE HTML>
<html lang="en" class="sidebar-visible no-js">
<head>
<!-- Book generated using mdBook -->
<meta charset="UTF-8">
<title>The `wasm-bindgen` Guide</title>
<meta name="robots" content="noindex" />
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="theme-color" content="#ffffff" />
<link rel="shortcut icon" href="favicon.png">
<link rel="stylesheet" href="css/variables.css">
<link rel="stylesheet" href="css/general.css">
<link rel="stylesheet" href="css/chrome.css">
<link rel="stylesheet" href="css/print.css" media="print">
<!-- Fonts -->
<link rel="stylesheet" href="FontAwesome/css/font-awesome.css">
<link href="https://fonts.googleapis.com/css?family=Open+Sans:300italic,400italic,600italic,700italic,800italic,400,300,600,700,800" rel="stylesheet" type="text/css">
<link href="https://fonts.googleapis.com/css?family=Source+Code+Pro:500" rel="stylesheet" type="text/css">
<!-- Highlight.js Stylesheets -->
<link rel="stylesheet" href="highlight.css">
<link rel="stylesheet" href="tomorrow-night.css">
<link rel="stylesheet" href="ayu-highlight.css">
<!-- Custom theme stylesheets -->
</head>
<body class="light">
<!-- Provide site root to javascript -->
<script type="text/javascript">
var path_to_root = "";
var default_theme = "light";
</script>
<!-- Work around some values being stored in localStorage wrapped in quotes -->
<script type="text/javascript">
try {
var theme = localStorage.getItem('mdbook-theme');
var sidebar = localStorage.getItem('mdbook-sidebar');
if (theme.startsWith('"') && theme.endsWith('"')) {
localStorage.setItem('mdbook-theme', theme.slice(1, theme.length - 1));
}
if (sidebar.startsWith('"') && sidebar.endsWith('"')) {
localStorage.setItem('mdbook-sidebar', sidebar.slice(1, sidebar.length - 1));
}
} catch (e) { }
</script>
<!-- Set the theme before any content is loaded, prevents flash -->
<script type="text/javascript">
var theme;
try { theme = localStorage.getItem('mdbook-theme'); } catch(e) { }
if (theme === null || theme === undefined) { theme = default_theme; }
document.body.className = theme;
document.querySelector('html').className = theme + ' js';
</script>
<!-- Hide / unhide sidebar before it is displayed -->
<script type="text/javascript">
var html = document.querySelector('html');
var sidebar = 'hidden';
if (document.body.clientWidth >= 1080) {
try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch(e) { }
sidebar = sidebar || 'visible';
}
html.classList.remove('sidebar-visible');
html.classList.add("sidebar-" + sidebar);
</script>
<nav id="sidebar" class="sidebar" aria-label="Table of contents">
<div class="sidebar-scrollbox">
<ol class="chapter"><li class="affix"><a href="introduction.html">Introduction</a></li><li class="spacer"></li><li><a href="examples/index.html"><strong aria-hidden="true">1.</strong> Examples</a></li><li><ol class="section"><li><a href="examples/hello-world.html"><strong aria-hidden="true">1.1.</strong> Hello, World!</a></li><li><a href="examples/console-log.html"><strong aria-hidden="true">1.2.</strong> Using console.log</a></li><li><a href="examples/add.html"><strong aria-hidden="true">1.3.</strong> Small wasm files</a></li><li><a href="examples/without-a-bundler.html"><strong aria-hidden="true">1.4.</strong> Without a Bundler</a></li><li><a href="examples/wasm2js.html"><strong aria-hidden="true">1.5.</strong> Converting WebAssembly to JS</a></li><li><a href="examples/import-js.html"><strong aria-hidden="true">1.6.</strong> Importing functions from JS</a></li><li><a href="examples/char.html"><strong aria-hidden="true">1.7.</strong> Working with char</a></li><li><a href="examples/wasm-in-wasm.html"><strong aria-hidden="true">1.8.</strong> js-sys: WebAssembly in WebAssembly</a></li><li><a href="examples/dom.html"><strong aria-hidden="true">1.9.</strong> web-sys: DOM hello world</a></li><li><a href="examples/closures.html"><strong aria-hidden="true">1.10.</strong> web-sys: Closures</a></li><li><a href="examples/performance.html"><strong aria-hidden="true">1.11.</strong> web-sys: performance.now</a></li><li><a href="examples/fetch.html"><strong aria-hidden="true">1.12.</strong> web-sys: using fetch</a></li><li><a href="examples/2d-canvas.html"><strong aria-hidden="true">1.13.</strong> web-sys: canvas hello world</a></li><li><a href="examples/julia.html"><strong aria-hidden="true">1.14.</strong> web-sys: canvas Julia set</a></li><li><a href="examples/web-audio.html"><strong aria-hidden="true">1.15.</strong> web-sys: WebAudio</a></li><li><a href="examples/webgl.html"><strong aria-hidden="true">1.16.</strong> web-sys: WebGL</a></li><li><a href="examples/websockets.html"><strong aria-hidden="true">1.17.</strong> web-sys: WebSockets</a></li><li><a href="examples/webrtc_datachannel.html"><strong aria-hidden="true">1.18.</strong> web-sys: WebRTC DataChannel</a></li><li><a href="examples/request-animation-frame.html"><strong aria-hidden="true">1.19.</strong> web-sys: requestAnimationFrame</a></li><li><a href="examples/paint.html"><strong aria-hidden="true">1.20.</strong> web-sys: A Simple Paint Program</a></li><li><a href="examples/raytrace.html"><strong aria-hidden="true">1.21.</strong> Parallel Raytracing</a></li><li><a href="examples/todomvc.html"><strong aria-hidden="true">1.22.</strong> web-sys: A TODO MVC App</a></li></ol></li><li><a href="reference/index.html"><strong aria-hidden="true">2.</strong> Reference</a></li><li><ol class="section"><li><a href="reference/deployment.html"><strong aria-hidden="true">2.1.</strong> Deployment</a></li><li><a href="reference/js-snippets.html"><strong aria-hidden="true">2.2.</strong> JS snippets</a></li><li><a href="reference/passing-rust-closures-to-js.html"><strong aria-hidden="true">2.3.</strong> Passing Rust Closures to JS</a></li><li><a href="reference/receiving-js-closures-in-rust.html"><strong aria-hidden="true">2.4.</strong> Receiving JS Closures in Rust</a></li><li><a href="reference/js-promises-and-rust-futures.html"><strong aria-hidden="true">2.5.</strong> Promises and Futures</a></li><li><a href="reference/iterating-over-js-values.html"><strong aria-hidden="true">2.6.</strong> Iterating over JS Values</a></li><li><a href="reference/arbitrary-data-with-serde.html"><strong aria-hidden="true">2.7.</strong> Arbitrary Data with Serde</a></li><li><a href="reference/accessing-properties-of-untyped-js-values.html"><strong aria-hidden="true">2.8.</strong> Accessing Properties of Untyped JS Values</a></li><li><a href="reference/working-with-duck-typed-interfaces.html"><strong aria-hidden="true">2.9.</strong> Working with Duck-Typed Interfaces</a></li><li><a href="reference/cli.html"><strong aria-hidden="true">2.10.</strong> Command Line Interface</a></li><li><a href="reference/optimize-size.html"><strong aria-hidden="true">2.11.</strong> Optimizing for Size</a></li><li><a href="reference/rust-targets.html"><strong aria-hidden="true">2.12.</strong> Supported Rust Targets</a></li><li><a href="reference/browser-support.html"><strong aria-hidden="true">2.13.</strong> Supported Browsers</a></li><li><a href="reference/types.html"><strong aria-hidden="true">2.14.</strong> Supported Types</a></li><li><ol class="section"><li><a href="reference/types/imported-js-types.html"><strong aria-hidden="true">2.14.1.</strong> Imported JavaScript Types</a></li><li><a href="reference/types/exported-rust-types.html"><strong aria-hidden="true">2.14.2.</strong> Exported Rust Types</a></li><li><a href="reference/types/jsvalue.html"><strong aria-hidden="true">2.14.3.</strong> JsValue</a></li><li><a href="reference/types/boxed-jsvalue-slice.html"><strong aria-hidden="true">2.14.4.</strong> Box&lt;[JsValue]&gt;</a></li><li><a href="reference/types/pointers.html"><strong aria-hidden="true">2.14.5.</strong> *const T and *mut T</a></li><li><a href="reference/types/numbers.html"><strong aria-hidden="true">2.14.6.</strong> Numbers</a></li><li><a href="reference/types/bool.html"><strong aria-hidden="true">2.14.7.</strong> bool</a></li><li><a href="reference/types/char.html"><strong aria-hidden="true">2.14.8.</strong> char</a></li><li><a href="reference/types/str.html"><strong aria-hidden="true">2.14.9.</strong> str</a></li><li><a href="reference/types/string.html"><strong aria-hidden="true">2.14.10.</strong> String</a></li><li><a href="reference/types/number-slices.html"><strong aria-hidden="true">2.14.11.</strong> Number Slices</a></li><li><a href="reference/types/boxed-number-slices.html"><strong aria-hidden="true">2.14.12.</strong> Boxed Number Slices</a></li><li><a href="reference/types/result.html"><strong aria-hidden="true">2.14.13.</strong> Result&lt;T, JsValue&gt;</a></li></ol></li><li><a href="reference/attributes/index.html"><strong aria-hidden="true">2.15.</strong> #[wasm_bindgen] Attributes</a></li><li><ol class="section"><li><a href="reference/attributes/on-js-imports/index.html"><strong aria-hidden="true">2.15.1.</strong> On JavaScript Imports</a></li><li><ol class="section"><li><a href="reference/attributes/on-js-imports/catch.html"><strong aria-hidden="true">2.15.1.1.</strong> catch</a></li><li><a href="reference/attributes/on-js-imports/constructor.html"><strong aria-hidden="true">2.15.1.2.</strong> constructor</a></li><li><a href="reference/attributes/on-js-imports/extends.html"><strong aria-hidden="true">2.15.1.3.</strong> extends</a></li><li><a href="reference/attributes/on-js-imports/getter-and-setter.html"><strong aria-hidden="true">2.15.1.4.</strong> getter and setter</a></li><li><a href="reference/attributes/on-js-imports/final.html"><strong aria-hidden="true">2.15.1.5.</strong> final</a></li><li><a href="reference/attributes/on-js-imports/indexing-getter-setter-deleter.html"><strong aria-hidden="true">2.15.1.6.</strong> indexing_getter, indexing_setter, and indexing_deleter</a></li><li><a href="reference/attributes/on-js-imports/js_class.html"><strong aria-hidden="true">2.15.1.7.</strong> js_class = &quot;Blah&quot;</a></li><li><a href="reference/attributes/on-js-imports/js_name.html"><strong aria-hidden="true">2.15.1.8.</strong> js_name</a></li><li><a href="reference/attributes/on-js-imports/js_namespace.html"><strong aria-hidden="true">2.15.1.9.</strong> js_namespace</a></li><li><a href="reference/attributes/on-js-imports/method.html"><strong aria-hidden="true">2.15.1.10.</strong> method</a></li><li><a href="reference/attributes/on-js-imports/module.html"><strong aria-hidden="true">2.15.1.11.</strong> module = &quot;blah&quot;</a></li><li><a href="reference/attributes/on-js-imports/raw_module.html"><strong aria-hidden="true">2.15.1.12.</strong> raw_module = &quot;blah&quot;</a></li><li><a href="reference/attributes/on-js-imports/static_method_of.html"><strong aria-hidden="true">2.15.1.13.</strong> static_method_of = Blah</a></li><li><a href="reference/attributes/on-js-imports/structural.html"><strong aria-hidden="true">2.15.1.14.</strong> structural</a></li><li><a href="reference/attributes/on-js-imports/variadic.html"><strong aria-hidden="true">2.15.1.15.</strong> variadic</a></li><li><a href="reference/attributes/on-js-imports/vendor_prefix.html"><strong aria-hidden="true">2.15.1.16.</strong> vendor_prefix</a></li></ol></li><li><a href="reference/attributes/on-rust-exports/index.html"><strong aria-hidden="true">2.15.2.</strong> On Rust Exports</a></li><li><ol class="section"><li><a href="reference/attributes/on-rust-exports/constructor.html"><strong aria-hidden="true">2.15.2.1.</strong> constructor</a></li><li><a href="reference/attributes/on-rust-exports/js_name.html"><strong aria-hidden="true">2.15.2.2.</strong> js_name = Blah</a></li><li><a href="reference/attributes/on-rust-exports/readonly.html"><strong aria-hidden="true">2.15.2.3.</strong> readonly</a></li><li><a href="reference/attributes/on-rust-exports/skip.html"><strong aria-hidden="true">2.15.2.4.</strong> skip</a></li><li><a href="reference/attributes/on-rust-exports/start.html"><strong aria-hidden="true">2.15.2.5.</strong> start</a></li><li><a href="reference/attributes/on-rust-exports/typescript_custom_section.html"><strong aria-hidden="true">2.15.2.6.</strong> typescript_custom_section</a></li><li><a href="reference/attributes/on-rust-exports/getter-and-setter.html"><strong aria-hidden="true">2.15.2.7.</strong> getter and setter</a></li><li><a href="reference/attributes/on-rust-exports/inspectable.html"><strong aria-hidden="true">2.15.2.8.</strong> inspectable</a></li><li><a href="reference/attributes/on-rust-exports/skip_typescript.html"><strong aria-hidden="true">2.15.2.9.</strong> skip_typescript</a></li><li><a href="reference/attributes/on-rust-exports/typescript_type.html"><strong aria-hidden="true">2.15.2.10.</strong> typescript_type</a></li></ol></li></ol></li></ol></li><li><a href="web-sys/index.html"><strong aria-hidden="true">3.</strong> web-sys</a></li><li><ol class="section"><li><a href="web-sys/using-web-sys.html"><strong aria-hidden="true">3.1.</strong> Using web-sys</a></li><li><a href="web-sys/cargo-features.html"><strong aria-hidden="true">3.2.</strong> Cargo Features</a></li><li><a href="web-sys/function-overloads.html"><strong aria-hidden="true">3.3.</strong> Function Overloads</a></li><li><a href="web-sys/type-translations.html"><strong aria-hidden="true">3.4.</strong> Type Translations</a></li><li><a href="web-sys/inheritance.html"><strong aria-hidden="true">3.5.</strong> Inheritance</a></li><li><a href="web-sys/unstable-apis.html"><strong aria-hidden="true">3.6.</strong> Unstable APIs</a></li></ol></li><li><a href="wasm-bindgen-test/index.html"><strong aria-hidden="true">4.</strong> Testing with wasm-bindgen-test</a></li><li><ol class="section"><li><a href="wasm-bindgen-test/usage.html"><strong aria-hidden="true">4.1.</strong> Usage</a></li><li><a href="wasm-bindgen-test/asynchronous-tests.html"><strong aria-hidden="true">4.2.</strong> Writing Asynchronous Tests</a></li><li><a href="wasm-bindgen-test/browsers.html"><strong aria-hidden="true">4.3.</strong> Testing in Headless Browsers</a></li><li><a href="wasm-bindgen-test/continuous-integration.html"><strong aria-hidden="true">4.4.</strong> Continuous Integration</a></li></ol></li><li><a href="contributing/index.html"><strong aria-hidden="true">5.</strong> Contributing to wasm-bindgen</a></li><li><ol class="section"><li><a href="contributing/testing.html"><strong aria-hidden="true">5.1.</strong> Testing</a></li><li><a href="contributing/design/index.html"><strong aria-hidden="true">5.2.</strong> Internal Design</a></li><li><ol class="section"><li><a href="contributing/design/js-objects-in-rust.html"><strong aria-hidden="true">5.2.1.</strong> JS Objects in Rust</a></li><li><a href="contributing/design/exporting-rust.html"><strong aria-hidden="true">5.2.2.</strong> Exporting a function to JS</a></li><li><a href="contributing/design/exporting-rust-struct.html"><strong aria-hidden="true">5.2.3.</strong> Exporting a struct to JS</a></li><li><a href="contributing/design/importing-js.html"><strong aria-hidden="true">5.2.4.</strong> Importing a function from JS</a></li><li><a href="contributing/design/importing-js-struct.html"><strong aria-hidden="true">5.2.5.</strong> Importing a class from JS</a></li><li><a href="contributing/design/rust-type-conversions.html"><strong aria-hidden="true">5.2.6.</strong> Rust Type conversions</a></li><li><a href="contributing/design/describe.html"><strong aria-hidden="true">5.2.7.</strong> Types in wasm-bindgen</a></li></ol></li><li><a href="contributing/js-sys/index.html"><strong aria-hidden="true">5.3.</strong> js-sys</a></li><li><ol class="section"><li><a href="contributing/js-sys/testing.html"><strong aria-hidden="true">5.3.1.</strong> Testing</a></li><li><a href="contributing/js-sys/adding-more-apis.html"><strong aria-hidden="true">5.3.2.</strong> Adding More APIs</a></li></ol></li><li><a href="contributing/web-sys/index.html"><strong aria-hidden="true">5.4.</strong> web-sys</a></li><li><ol class="section"><li><a href="contributing/web-sys/overview.html"><strong aria-hidden="true">5.4.1.</strong> Overview</a></li><li><a href="contributing/web-sys/testing.html"><strong aria-hidden="true">5.4.2.</strong> Testing</a></li><li><a href="contributing/web-sys/logging.html"><strong aria-hidden="true">5.4.3.</strong> Logging</a></li><li><a href="contributing/web-sys/supporting-more-web-apis.html"><strong aria-hidden="true">5.4.4.</strong> Supporting More Web APIs</a></li></ol></li><li><a href="contributing/publishing.html"><strong aria-hidden="true">5.5.</strong> Publishing</a></li><li><a href="contributing/team.html"><strong aria-hidden="true">5.6.</strong> Team</a></li></ol></li></ol>
</div>
<div id="sidebar-resize-handle" class="sidebar-resize-handle"></div>
</nav>
<div id="page-wrapper" class="page-wrapper">
<div class="page">
<style>
header.warning {
background-color: rgb(242, 222, 222);
border-bottom-color: rgb(238, 211, 215);
border-bottom-left-radius: 4px;
border-bottom-right-radius: 4px;
border-bottom-style: solid;
border-bottom-width: 0.666667px;
border-image-outset: 0 0 0 0;
border-image-repeat: stretch stretch;
border-image-slice: 100% 100% 100% 100%;
border-image-source: none;
border-image-width: 1 1 1 1;
border-left-color: rgb(238, 211, 215);
border-left-style: solid;
border-left-width: 0.666667px;
border-right-color: rgb(238, 211, 215);
border-right-style: solid;
border-right-width: 0.666667px;
border-top-color: rgb(238, 211, 215);
border-top-left-radius: 4px;
border-top-right-radius: 4px;
border-top-style: solid;
border-top-width: 0.666667px;
color: rgb(185, 74, 72);
margin-bottom: 0px;
margin-left: 0px;
margin-right: 0px;
margin-top: 30px;
padding-bottom: 8px;
padding-left: 14px;
padding-right: 35px;
padding-top: 8px;
text-align: center;
}
</style>
<header class='warning'>
This is the <strong>unpublished</strong> documentation of
<code>wasm-bindgen</code>, the published documentation is available
<a href="https://rustwasm.github.io/docs/wasm-bindgen/">
on the main Rust and WebAssembly documentation site
</a>. Features documented here may not be available in released versions of
<code>wasm-bindgen</code>.
</header>
<div id="menu-bar" class="menu-bar">
<div id="menu-bar-sticky-container">
<div class="left-buttons">
<button id="sidebar-toggle" class="icon-button" type="button" title="Toggle Table of Contents" aria-label="Toggle Table of Contents" aria-controls="sidebar">
<i class="fa fa-bars"></i>
</button>
<button id="theme-toggle" class="icon-button" type="button" title="Change theme" aria-label="Change theme" aria-haspopup="true" aria-expanded="false" aria-controls="theme-list">
<i class="fa fa-paint-brush"></i>
</button>
<ul id="theme-list" class="theme-popup" aria-label="Themes" role="menu">
<li role="none"><button role="menuitem" class="theme" id="light">Light (default)</button></li>
<li role="none"><button role="menuitem" class="theme" id="rust">Rust</button></li>
<li role="none"><button role="menuitem" class="theme" id="coal">Coal</button></li>
<li role="none"><button role="menuitem" class="theme" id="navy">Navy</button></li>
<li role="none"><button role="menuitem" class="theme" id="ayu">Ayu</button></li>
</ul>
<button id="search-toggle" class="icon-button" type="button" title="Search. (Shortkey: s)" aria-label="Toggle Searchbar" aria-expanded="false" aria-keyshortcuts="S" aria-controls="searchbar">
<i class="fa fa-search"></i>
</button>
</div>
<h1 class="menu-title">The `wasm-bindgen` Guide</h1>
<div class="right-buttons">
<a href="print.html" title="Print this book" aria-label="Print this book">
<i id="print-button" class="fa fa-print"></i>
</a>
</div>
</div>
</div>
<div id="search-wrapper" class="hidden">
<form id="searchbar-outer" class="searchbar-outer">
<input type="search" name="search" id="searchbar" name="searchbar" placeholder="Search this book ..." aria-controls="searchresults-outer" aria-describedby="searchresults-header">
</form>
<div id="searchresults-outer" class="searchresults-outer hidden">
<div id="searchresults-header" class="searchresults-header"></div>
<ul id="searchresults">
</ul>
</div>
</div>
<!-- Apply ARIA attributes after the sidebar and the sidebar toggle button are added to the DOM -->
<script type="text/javascript">
document.getElementById('sidebar-toggle').setAttribute('aria-expanded', sidebar === 'visible');
document.getElementById('sidebar').setAttribute('aria-hidden', sidebar !== 'visible');
Array.from(document.querySelectorAll('#sidebar a')).forEach(function(link) {
link.setAttribute('tabIndex', sidebar === 'visible' ? 0 : -1);
});
</script>
<div id="content" class="content">
<main>
<h1><a class="header" href="#introduction" id="introduction">Introduction</a></h1>
<p>This book is about <code>wasm-bindgen</code>, a Rust library and CLI tool that facilitate
high-level interactions between wasm modules and JavaScript. The <code>wasm-bindgen</code>
tool and crate are only one part of the <a href="https://rustwasm.github.io/">Rust and WebAssembly
ecosystem</a>. If you're not familiar already with <code>wasm-bindgen</code> it's
recommended to start by reading the <a href="https://rustwasm.github.io/docs/book/">Game of Life tutorial</a>. If you're
curious about <code>wasm-pack</code>, you can find that <a href="https://rustwasm.github.io/docs/wasm-pack/">documentation here</a>.</p>
<p>The <code>wasm-bindgen</code> tool is sort of half polyfill for features like the <a href="https://github.com/WebAssembly/host-bindings">host
bindings proposal</a> and half features for empowering high-level
interactions between JS and wasm-compiled code (currently mostly from Rust).
More specifically this project allows JS/wasm to communicate with strings, JS
objects, classes, etc, as opposed to purely integers and floats. Using
<code>wasm-bindgen</code> for example you can define a JS class in Rust or take a string
from JS or return one. The functionality is growing as well!</p>
<p>Currently this tool is Rust-focused but the underlying foundation is
language-independent, and it's hoping that over time as this tool stabilizes
that it can be used for languages like C/C++!</p>
<p>Notable features of this project includes:</p>
<ul>
<li>Importing JS functionality in to Rust such as <a href="https://github.com/rustwasm/wasm-bindgen/tree/master/examples/dom">DOM manipulation</a>,
<a href="https://github.com/rustwasm/wasm-bindgen/tree/master/examples/console_log">console logging</a>, or <a href="https://github.com/rustwasm/wasm-bindgen/tree/master/examples/performance">performance monitoring</a>.</li>
<li>Exporting Rust functionality to JS such as classes, functions, etc.</li>
<li>Working with rich types like strings, numbers, classes, closures, and objects
rather than simply <code>u32</code> and floats.</li>
<li>Automatically generating TypeScript bindings for Rust code being consumed by
JS.</li>
</ul>
<p>With the addition of <a href="https://rustwasm.github.io/docs/wasm-pack/"><code>wasm-pack</code></a> you can run the gamut from running Rust on
the web locally, publishing it as part of a larger application, or even
publishing Rust-compiled-to-WebAssembly on NPM!</p>
<h1><a class="header" href="#examples-of-using-wasm-bindgen-js-sys-and-web-sys" id="examples-of-using-wasm-bindgen-js-sys-and-web-sys">Examples of using <code>wasm-bindgen</code>, <code>js-sys</code>, and <code>web-sys</code></a></h1>
<p>This subsection contains examples of using the <code>wasm-bindgen</code>, <code>js-sys</code>, and
<code>web-sys</code> crates. Each example should have more information about what it's
doing.</p>
<p>These examples all assume familiarity with <code>wasm-bindgen</code>, <code>wasm-pack</code>, and
building a Rust and WebAssembly project. If you're unfamiliar with these check
out the <a href="https://rustwasm.github.io/docs/book/">Game of Life tutorial</a> or <a href="https://rustwasm.github.io/docs/wasm-pack/tutorials/index.html">wasm pack tutorials</a> to help you
get started.</p>
<p>The source code for all examples can also be <a href="https://github.com/rustwasm/wasm-bindgen/tree/master/examples">found online</a> to download
and run locally. Most examples are configured with Webpack/<code>wasm-pack</code> and can
be built with <code>npm run serve</code>. Other examples which don't use Webpack are
accompanied with instructions or a <code>build.sh</code> showing how to build it.</p>
<p>Note that most examples currently use Webpack to assemble the final output
artifact, but this is not required! You can review the <a href="examples/../reference/deployment.html">deployment
documentation</a> for other options of how to deploy Rust and WebAssembly.</p>
<h1><a class="header" href="#hello-world" id="hello-world">Hello, World!</a></h1>
<p><a href="https://github.com/rustwasm/wasm-bindgen/tree/master/examples/hello_world">View full source code</a> or <a href="https://rustwasm.github.io/wasm-bindgen/exbuild/hello_world/">view the compiled example online</a></p>
<p>This is the &quot;Hello, world!&quot; example of <code>#[wasm_bindgen]</code> showing how to set up
a project, export a function to JS, call it from JS, and then call the <code>alert</code>
function in Rust.</p>
<h2><a class="header" href="#cargotoml" id="cargotoml"><code>Cargo.toml</code></a></h2>
<p>The <code>Cargo.toml</code> lists the <code>wasm-bindgen</code> crate as a dependency.</p>
<p>Also of note is the <code>crate-type = [&quot;cdylib&quot;]</code> which is largely used for wasm
final artifacts today.</p>
<pre><code class="language-toml">[package]
name = &quot;hello_world&quot;
version = &quot;0.1.0&quot;
authors = [&quot;The wasm-bindgen Developers&quot;]
edition = &quot;2018&quot;
[lib]
crate-type = [&quot;cdylib&quot;]
[dependencies]
wasm-bindgen = &quot;0.2.63&quot;
</code></pre>
<h2><a class="header" href="#srclibrs" id="srclibrs"><code>src/lib.rs</code></a></h2>
<p>Here we define our Rust entry point along with calling the <code>alert</code> function.</p>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
extern &quot;C&quot; {
fn alert(s: &amp;str);
}
#[wasm_bindgen]
pub fn greet(name: &amp;str) {
alert(&amp;format!(&quot;Hello, {}!&quot;, name));
}
#}</code></pre></pre>
<h2><a class="header" href="#indexjs" id="indexjs"><code>index.js</code></a></h2>
<p>Our JS entry point is quite small!</p>
<pre><code class="language-js">// Note that a dynamic `import` statement here is required due to
// webpack/webpack#6615, but in theory `import { greet } from './pkg';`
// will work here one day as well!
const rust = import('./pkg');
rust
.then(m =&gt; m.greet('World!'))
.catch(console.error);
</code></pre>
<h2><a class="header" href="#webpack-specific-files" id="webpack-specific-files">Webpack-specific files</a></h2>
<blockquote>
<p><strong>Note</strong>: Webpack is not required for this example, and if you're interested
in options that don't use a JS bundler <a href="examples/without-a-bundler.html">see other examples</a>.</p>
</blockquote>
<p>And finally here's the Webpack configuration and <code>package.json</code> for this
project:</p>
<p><strong>webpack.config.js</strong></p>
<pre><code class="language-js">const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const webpack = require('webpack');
const WasmPackPlugin = require(&quot;@wasm-tool/wasm-pack-plugin&quot;);
module.exports = {
entry: './index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'index.js',
},
plugins: [
new HtmlWebpackPlugin(),
new WasmPackPlugin({
crateDirectory: path.resolve(__dirname, &quot;.&quot;)
}),
// Have this example work in Edge which doesn't ship `TextEncoder` or
// `TextDecoder` at this time.
new webpack.ProvidePlugin({
TextDecoder: ['text-encoding', 'TextDecoder'],
TextEncoder: ['text-encoding', 'TextEncoder']
})
],
mode: 'development'
};
</code></pre>
<p><strong>package.json</strong></p>
<pre><code class="language-json">{
&quot;scripts&quot;: {
&quot;build&quot;: &quot;webpack&quot;,
&quot;serve&quot;: &quot;webpack-dev-server&quot;
},
&quot;devDependencies&quot;: {
&quot;@wasm-tool/wasm-pack-plugin&quot;: &quot;1.0.1&quot;,
&quot;text-encoding&quot;: &quot;^0.7.0&quot;,
&quot;html-webpack-plugin&quot;: &quot;^3.2.0&quot;,
&quot;webpack&quot;: &quot;^4.29.4&quot;,
&quot;webpack-cli&quot;: &quot;^3.1.1&quot;,
&quot;webpack-dev-server&quot;: &quot;^3.1.0&quot;
}
}
</code></pre>
<h1><a class="header" href="#consolelog" id="consolelog"><code>console.log</code></a></h1>
<p><a href="https://github.com/rustwasm/wasm-bindgen/tree/master/examples/console_log">View full source code</a> or <a href="https://rustwasm.github.io/wasm-bindgen/exbuild/console_log/">view the compiled example online</a></p>
<p>This example shows off how to use <code>console.log</code> in a variety of ways, all the
way from bare-bones usage to a <code>println!</code>-like macro with <code>web_sys</code>.</p>
<h2><a class="header" href="#srclibrs-1" id="srclibrs-1"><code>src/lib.rs</code></a></h2>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
use wasm_bindgen::prelude::*;
#[wasm_bindgen(start)]
pub fn run() {
bare_bones();
using_a_macro();
using_web_sys();
}
// First up let's take a look of binding `console.log` manually, without the
// help of `web_sys`. Here we're writing the `#[wasm_bindgen]` annotations
// manually ourselves, and the correctness of our program relies on the
// correctness of these annotations!
#[wasm_bindgen]
extern &quot;C&quot; {
// Use `js_namespace` here to bind `console.log(..)` instead of just
// `log(..)`
#[wasm_bindgen(js_namespace = console)]
fn log(s: &amp;str);
// The `console.log` is quite polymorphic, so we can bind it with multiple
// signatures. Note that we need to use `js_name` to ensure we always call
// `log` in JS.
#[wasm_bindgen(js_namespace = console, js_name = log)]
fn log_u32(a: u32);
// Multiple arguments too!
#[wasm_bindgen(js_namespace = console, js_name = log)]
fn log_many(a: &amp;str, b: &amp;str);
}
fn bare_bones() {
log(&quot;Hello from Rust!&quot;);
log_u32(42);
log_many(&quot;Logging&quot;, &quot;many values!&quot;);
}
// Next let's define a macro that's like `println!`, only it works for
// `console.log`. Note that `println!` doesn't actually work on the wasm target
// because the standard library currently just eats all output. To get
// `println!`-like behavior in your app you'll likely want a macro like this.
macro_rules! console_log {
// Note that this is using the `log` function imported above during
// `bare_bones`
($($t:tt)*) =&gt; (log(&amp;format_args!($($t)*).to_string()))
}
fn using_a_macro() {
console_log!(&quot;Hello {}!&quot;, &quot;world&quot;);
console_log!(&quot;Let's print some numbers...&quot;);
console_log!(&quot;1 + 3 = {}&quot;, 1 + 3);
}
// And finally, we don't even have to define the `log` function ourselves! The
// `web_sys` crate already has it defined for us.
fn using_web_sys() {
use web_sys::console;
console::log_1(&amp;&quot;Hello using web-sys&quot;.into());
let js: JsValue = 4.into();
console::log_2(&amp;&quot;Logging arbitrary values looks like&quot;.into(), &amp;js);
}
#}</code></pre></pre>
<h1><a class="header" href="#small-wasm-files" id="small-wasm-files">Small wasm files</a></h1>
<p><a href="https://github.com/rustwasm/wasm-bindgen/tree/master/examples/add">View full source code</a> or <a href="https://rustwasm.github.io/wasm-bindgen/exbuild/add/">view the compiled example online</a></p>
<p>One of <code>wasm-bindgen</code>'s core goals is a pay-only-for-what-you-use philosophy, so
if we don't use much then we shouldn't be paying much! As a result
<code>#[wasm_bindgen]</code> can generate super-small executables</p>
<p>Currently this code...</p>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
pub fn add(a: u32, b: u32) -&gt; u32 {
a + b
}
#}</code></pre></pre>
<p>generates a 710 byte wasm binary:</p>
<pre><code>$ ls -l add_bg.wasm
-rw-rw-r-- 1 alex alex 710 Sep 19 17:32 add_bg.wasm
</code></pre>
<p>If you run <a href="https://github.com/webassembly/binaryen">wasm-opt</a>, a C++ tool for optimize WebAssembly, you can make it
even smaller too!</p>
<pre><code>$ wasm-opt -Os add_bg.wasm -o add.wasm
$ ls -l add.wasm
-rw-rw-r-- 1 alex alex 172 Sep 19 17:33 add.wasm
</code></pre>
<p>And sure enough, using the <a href="https://github.com/webassembly/wabt">wasm2wat</a> tool it's quite small!</p>
<pre><code>$ wasm2wat add.wasm
(module
(type (;0;) (func (param i32 i32) (result i32)))
(func (;0;) (type 0) (param i32 i32) (result i32)
get_local 1
get_local 0
i32.add)
(table (;0;) 1 1 anyfunc)
(memory (;0;) 17)
(global (;0;) i32 (i32.const 1049118))
(global (;1;) i32 (i32.const 1049118))
(export &quot;memory&quot; (memory 0))
(export &quot;__indirect_function_table&quot; (table 0))
(export &quot;__heap_base&quot; (global 0))
(export &quot;__data_end&quot; (global 1))
(export &quot;add&quot; (func 0))
(data (i32.const 1049096) &quot;invalid malloc request&quot;))
</code></pre>
<p>Also don't forget to compile in release mode for the smallest binaries! For
larger applications you'll likely also want to turn on LTO to generate the
smallest binaries:</p>
<pre><code class="language-toml">[profile.release]
lto = true
</code></pre>
<h1><a class="header" href="#without-a-bundler" id="without-a-bundler">Without a Bundler</a></h1>
<p><a href="https://github.com/rustwasm/wasm-bindgen/tree/master/examples/without-a-bundler">View full source code</a></p>
<p>This example shows how the <code>--target web</code> flag can be used load code in a
browser directly. For this deployment strategy bundlers like Webpack are not
required. For more information on deployment see the <a href="examples/../reference/deployment.html">dedicated
documentation</a>.</p>
<p>First let's take a look at the code and see how when we're using <code>--target web</code>
we're not actually losing any functionality!</p>
<pre><pre class="playpen"><code class="language-rust">use wasm_bindgen::prelude::*;
// Called when the wasm module is instantiated
#[wasm_bindgen(start)]
pub fn main() -&gt; Result&lt;(), JsValue&gt; {
// Use `web_sys`'s global `window` function to get a handle on the global
// window object.
let window = web_sys::window().expect(&quot;no global `window` exists&quot;);
let document = window.document().expect(&quot;should have a document on window&quot;);
let body = document.body().expect(&quot;document should have a body&quot;);
// Manufacture the element we're gonna append
let val = document.create_element(&quot;p&quot;)?;
val.set_inner_html(&quot;Hello from Rust!&quot;);
body.append_child(&amp;val)?;
Ok(())
}
#[wasm_bindgen]
pub fn add(a: u32, b: u32) -&gt; u32 {
a + b
}
</code></pre></pre>
<p>Otherwise the rest of the deployment magic happens in <code>index.html</code>:</p>
<pre><code class="language-html">&lt;html&gt;
&lt;head&gt;
&lt;meta content=&quot;text/html;charset=utf-8&quot; http-equiv=&quot;Content-Type&quot;/&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;!-- Note the usage of `type=module` here as this is an ES6 module --&gt;
&lt;script type=&quot;module&quot;&gt;
// Use ES module import syntax to import functionality from the module
// that we have compiled.
//
// Note that the `default` import is an initialization function which
// will &quot;boot&quot; the module and make it ready to use. Currently browsers
// don't support natively imported WebAssembly as an ES module, but
// eventually the manual initialization won't be required!
import init, { add } from './pkg/without_a_bundler.js';
async function run() {
// First up we need to actually load the wasm file, so we use the
// default export to inform it where the wasm file is located on the
// server, and then we wait on the returned promise to wait for the
// wasm to be loaded.
//
// It may look like this: `await init('./pkg/without_a_bundler_bg.wasm');`,
// but there is also a handy default inside `init` function, which uses
// `import.meta` to locate the wasm file relatively to js file.
//
// Note that instead of a string you can also pass in any of the
// following things:
//
// * `WebAssembly.Module`
//
// * `ArrayBuffer`
//
// * `Response`
//
// * `Promise` which returns any of the above, e.g. `fetch(&quot;./path/to/wasm&quot;)`
//
// This gives you complete control over how the module is loaded
// and compiled.
//
// Also note that the promise, when resolved, yields the wasm module's
// exports which is the same as importing the `*_bg` module in other
// modes
await init();
// And afterwards we can use all the functionality defined in wasm.
const result = add(1, 2);
console.log(`1 + 2 = ${result}`);
if (result !== 3)
throw new Error(&quot;wasm addition doesn't work!&quot;);
}
run();
&lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;
</code></pre>
<p>And that's it! Be sure to read up on the <a href="examples/../reference/deployment.html">deployment options</a> to see
what it means to deploy without a bundler.</p>
<h2><a class="header" href="#using-the-older---target-no-modules" id="using-the-older---target-no-modules">Using the older <code>--target no-modules</code></a></h2>
<p><a href="https://github.com/rustwasm/wasm-bindgen/tree/master/examples/without-a-bundler">View full source code</a></p>
<p>The older version of using <code>wasm-bindgen</code> without a bundler is to use the
<code>--target no-modules</code> flag to the <code>wasm-bindgen</code> CLI.</p>
<p>While similar to the newer <code>--target web</code>, the <code>--target no-modules</code> flag has a
few caveats:</p>
<ul>
<li>It does not support <a href="examples/../reference/js-snippets.html">local JS snippets</a></li>
<li>It does not generate an ES module</li>
</ul>
<p>With that in mind the main difference is how the wasm/JS code is loaded, and
here's an example of loading the output of <code>wasm-pack</code> for the same module as
above.</p>
<pre><code class="language-html">&lt;html&gt;
&lt;head&gt;
&lt;meta content=&quot;text/html;charset=utf-8&quot; http-equiv=&quot;Content-Type&quot;/&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;!-- Include the JS generated by `wasm-pack build` --&gt;
&lt;script src='pkg/without_a_bundler_no_modules.js'&gt;&lt;/script&gt;
&lt;script&gt;
// Like with the `--target web` output the exports are immediately
// available but they won't work until we initialize the module. Unlike
// `--target web`, however, the globals are all stored on a
// `wasm_bindgen` global. The global itself is the initialization
// function and then the properties of the global are all the exported
// functions.
//
// Note that the name `wasm_bindgen` can be configured with the
// `--no-modules-global` CLI flag
const { add } = wasm_bindgen;
async function run() {
await wasm_bindgen('./pkg/without_a_bundler_no_modules_bg.wasm');
const result = add(1, 2);
console.log(`1 + 2 = ${result}`);
}
run();
&lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;
</code></pre>
<h1><a class="header" href="#converting-webassembly-to-js" id="converting-webassembly-to-js">Converting WebAssembly to JS</a></h1>
<p><a href="https://github.com/rustwasm/wasm-bindgen/tree/master/examples/wasm2js">View full source code</a></p>
<p>Not all browsers have support for <code>WebAssembly</code> at this time (although all major
ones do). If you'd like to support older browsers, you probably want a method
that doesn't involve keeping two codebases in sync!</p>
<p>Thankfully there's a tool from <a href="https://github.com/WebAssembly/binaryen">binaryen</a> called <code>wasm2js</code> to convert a wasm
file to JS. This JS file, if successfully produced, is equivalent to the wasm
file (albeit a little bit larger and slower), and can be loaded into practically
any browser.</p>
<p>This example is relatively simple (cribbing from the <a href="examples/console-log.html"><code>console.log</code>
example</a>):</p>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
use wasm_bindgen::prelude::*;
// lifted from the `console_log` example
#[wasm_bindgen]
extern &quot;C&quot; {
#[wasm_bindgen(js_namespace = console)]
fn log(s: &amp;str);
}
#[wasm_bindgen(start)]
pub fn run() {
log(&quot;Hello, World!&quot;);
}
#}</code></pre></pre>
<p>The real magic happens when you actually build the app. Just after
<code>wasm-bindgen</code> we see here how we execute <code>wasm2js</code> in our build script:</p>
<pre><code class="language-sh">#!/bin/sh
set -ex
# Compile our wasm module and run `wasm-bindgen`
wasm-pack build --target web
# Run the `wasm2js` tool from `binaryen`
wasm2js pkg/wasm2js_bg.wasm -o pkg/wasm2js_bg.js
# Update our JS shim to require the JS file instead
sed -i 's/wasm2js_bg.wasm/wasm2js_bg.js/' pkg/wasm2js.js
http
</code></pre>
<p>Note that the <code>wasm2js</code> tool is still pretty early days so there's likely to be
a number of bugs to run into or work around. If any are encountered though
please feel free to report them upstream!</p>
<p>Also note that eventually this will ideally be automatically done by your
bundler and no action would be needed from you to work in older browsers via
<code>wasm2js</code>!</p>
<h1><a class="header" href="#importing-non-browser-js" id="importing-non-browser-js">Importing non-browser JS</a></h1>
<p><a href="https://github.com/rustwasm/wasm-bindgen/tree/master/examples/import_js">View full source code</a> or <a href="https://rustwasm.github.io/wasm-bindgen/exbuild/import_js/">view the compiled example online</a></p>
<p>The <code>#[wasm_bindgen]</code> attribute can be used on <code>extern &quot;C&quot; { .. }</code> blocks to import
functionality from JS. This is how the <code>js-sys</code> and the <code>web-sys</code> crates are
built, but you can also use it in your own crate!</p>
<p>For example if you're working with this JS file:</p>
<pre><code class="language-js">// defined-in-js.js
export function name() {
return 'Rust';
}
export class MyClass {
constructor() {
this._number = 42;
}
get number() {
return this._number;
}
set number(n) {
return this._number = n;
}
render() {
return `My number is: ${this.number}`;
}
}
</code></pre>
<p>you can use it in Rust with:</p>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
use wasm_bindgen::prelude::*;
#[wasm_bindgen(module = &quot;/defined-in-js.js&quot;)]
extern &quot;C&quot; {
fn name() -&gt; String;
type MyClass;
#[wasm_bindgen(constructor)]
fn new() -&gt; MyClass;
#[wasm_bindgen(method, getter)]
fn number(this: &amp;MyClass) -&gt; u32;
#[wasm_bindgen(method, setter)]
fn set_number(this: &amp;MyClass, number: u32) -&gt; MyClass;
#[wasm_bindgen(method)]
fn render(this: &amp;MyClass) -&gt; String;
}
// lifted from the `console_log` example
#[wasm_bindgen]
extern &quot;C&quot; {
#[wasm_bindgen(js_namespace = console)]
fn log(s: &amp;str);
}
#[wasm_bindgen(start)]
pub fn run() {
log(&amp;format!(&quot;Hello from {}!&quot;, name())); // should output &quot;Hello from Rust!&quot;
let x = MyClass::new();
assert_eq!(x.number(), 42);
x.set_number(10);
log(&amp;x.render());
}
#}</code></pre></pre>
<p>You can also <a href="examples/../reference/attributes/on-js-imports/index.html">explore the full list of ways to configure imports</a></p>
<h1><a class="header" href="#working-with-the-char-type" id="working-with-the-char-type">Working with the <code>char</code> type</a></h1>
<p><a href="https://github.com/rustwasm/wasm-bindgen/tree/master/examples/char">View full source code</a> or <a href="https://rustwasm.github.io/wasm-bindgen/exbuild/char/">view the compiled example online</a></p>
<p>The <code>#[wasm_bindgen]</code> macro will convert the rust <code>char</code> type to a single
code-point js <code>string</code>, and this example shows how to work with this.</p>
<p>Opening this example should display a single counter with a random character
for it's <code>key</code> and 0 for its <code>count</code>. You can click the <code>+</code> button to increase a
counter's count. By clicking on the &quot;add counter&quot; button you should see a new
counter added to the list with a different random character for it's <code>key</code>.</p>
<p>Under the hood javascript is choosing a random character from an Array of
characters and passing that to the rust Counter struct's constructor so the
character you are seeing on the page has made the full round trip from js to
rust and back to js.</p>
<h2><a class="header" href="#srclibrs-2" id="srclibrs-2"><code>src/lib.rs</code></a></h2>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
use wasm_bindgen::prelude::*;
// lifted from the `console_log` example
#[wasm_bindgen]
extern &quot;C&quot; {
#[wasm_bindgen(js_namespace = console)]
fn log(s: &amp;str);
}
#[wasm_bindgen]
#[derive(Debug)]
pub struct Counter {
key: char,
count: i32,
}
#[wasm_bindgen]
impl Counter {
pub fn default() -&gt; Counter {
log(&quot;Counter::default&quot;);
Self::new('a', 0)
}
pub fn new(key: char, count: i32) -&gt; Counter {
log(&amp;format!(&quot;Counter::new({}, {})&quot;, key, count));
Counter {
key: key,
count: count,
}
}
pub fn key(&amp;self) -&gt; char {
log(&quot;Counter.key()&quot;);
self.key
}
pub fn count(&amp;self) -&gt; i32 {
log(&quot;Counter.count&quot;);
self.count
}
pub fn increment(&amp;mut self) {
log(&quot;Counter.increment&quot;);
self.count += 1;
}
pub fn update_key(&amp;mut self, key: char) {
self.key = key;
}
}
#}</code></pre></pre>
<h2><a class="header" href="#indexjs-1" id="indexjs-1"><code>index.js</code></a></h2>
<pre><code class="language-js">/* eslint-disable no-unused-vars */
import { chars } from './chars-list.js';
let imp = import('./pkg');
let mod;
let counters = [];
imp
.then(wasm =&gt; {
mod = wasm;
addCounter();
let b = document.getElementById('add-counter');
if (!b) throw new Error('Unable to find #add-counter');
b.addEventListener('click', ev =&gt; addCounter());
})
.catch(console.error);
function addCounter() {
let ctr = mod.Counter.new(randomChar(), 0);
counters.push(ctr);
update();
}
function update() {
let container = document.getElementById('container');
if (!container) throw new Error('Unable to find #container in dom');
while (container.hasChildNodes()) {
if (container.lastChild.id == 'add-counter') break;
container.removeChild(container.lastChild);
}
for (var i = 0; i &lt; counters.length; i++) {
let counter = counters[i];
container.appendChild(newCounter(counter.key(), counter.count(), ev =&gt; {
counter.increment();
update();
}));
}
}
function randomChar() {
console.log('randomChar');
let idx = Math.floor(Math.random() * (chars.length - 1));
console.log('index', idx);
let ret = chars.splice(idx, 1)[0];
console.log('char', ret);
return ret;
}
function newCounter(key, value, cb) {
let container = document.createElement('div');
container.setAttribute('class', 'counter');
let title = document.createElement('h1');
title.appendChild(document.createTextNode('Counter ' + key));
container.appendChild(title);
container.appendChild(newField('Count', value));
let plus = document.createElement('button');
plus.setAttribute('type', 'button');
plus.setAttribute('class', 'plus-button');
plus.appendChild(document.createTextNode('+'));
plus.addEventListener('click', cb);
container.appendChild(plus);
return container;
}
function newField(key, value) {
let ret = document.createElement('div');
ret.setAttribute('class', 'field');
let name = document.createElement('span');
name.setAttribute('class', 'name');
name.appendChild(document.createTextNode(key));
ret.appendChild(name);
let val = document.createElement('span');
val.setAttribute('class', 'value');
val.appendChild(document.createTextNode(value));
ret.appendChild(val);
return ret;
}
</code></pre>
<h1><a class="header" href="#js-sys-webassembly-in-webassembly" id="js-sys-webassembly-in-webassembly">js-sys: WebAssembly in WebAssembly</a></h1>
<p><a href="https://github.com/rustwasm/wasm-bindgen/tree/master/examples/wasm-in-wasm">View full source code</a> or <a href="https://rustwasm.github.io/wasm-bindgen/exbuild/wasm-in-wasm/">view the compiled example online</a></p>
<p>Using the <code>js-sys</code> crate we can get pretty meta and instantiate <code>WebAssembly</code>
modules from inside <code>WebAssembly</code> modules!</p>
<h2><a class="header" href="#srclibrs-3" id="srclibrs-3"><code>src/lib.rs</code></a></h2>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
use js_sys::{Function, Object, Reflect, WebAssembly};
use wasm_bindgen::prelude::*;
use wasm_bindgen::JsCast;
use wasm_bindgen_futures::{spawn_local, JsFuture};
// lifted from the `console_log` example
#[wasm_bindgen]
extern &quot;C&quot; {
#[wasm_bindgen(js_namespace = console)]
fn log(a: &amp;str);
}
macro_rules! console_log {
($($t:tt)*) =&gt; (log(&amp;format_args!($($t)*).to_string()))
}
const WASM: &amp;[u8] = include_bytes!(&quot;add.wasm&quot;);
async fn run_async() -&gt; Result&lt;(), JsValue&gt; {
console_log!(&quot;instantiating a new wasm module directly&quot;);
let a = JsFuture::from(WebAssembly::instantiate_buffer(WASM, &amp;Object::new())).await?;
let b: WebAssembly::Instance = Reflect::get(&amp;a, &amp;&quot;instance&quot;.into())?.dyn_into()?;
let c = b.exports();
let add = Reflect::get(c.as_ref(), &amp;&quot;add&quot;.into())?
.dyn_into::&lt;Function&gt;()
.expect(&quot;add export wasn't a function&quot;);
let three = add.call2(&amp;JsValue::undefined(), &amp;1.into(), &amp;2.into())?;
console_log!(&quot;1 + 2 = {:?}&quot;, three);
let mem = Reflect::get(c.as_ref(), &amp;&quot;memory&quot;.into())?
.dyn_into::&lt;WebAssembly::Memory&gt;()
.expect(&quot;memory export wasn't a `WebAssembly.Memory`&quot;);
console_log!(&quot;created module has {} pages of memory&quot;, mem.grow(0));
console_log!(&quot;giving the module 4 more pages of memory&quot;);
mem.grow(4);
console_log!(&quot;now the module has {} pages of memory&quot;, mem.grow(0));
Ok(())
}
#[wasm_bindgen(start)]
pub fn run() {
spawn_local(async {
run_async().await.unwrap_throw();
});
}
#}</code></pre></pre>
<h1><a class="header" href="#web-sys-dom-hello-world" id="web-sys-dom-hello-world">web-sys: DOM hello world</a></h1>
<p><a href="https://github.com/rustwasm/wasm-bindgen/tree/master/examples/dom">View full source code</a> or <a href="https://rustwasm.github.io/wasm-bindgen/exbuild/dom/">view the compiled example online</a></p>
<p>Using <code>web-sys</code> we're able to interact with all the standard web platform
methods, including those of the DOM! Here we take a look at a simple &quot;Hello,
world!&quot; which manufactures a DOM element in Rust, customizes it, and then
appends it to the page.</p>
<h2><a class="header" href="#cargotoml-1" id="cargotoml-1"><code>Cargo.toml</code></a></h2>
<p>You can see here how we depend on <code>web-sys</code> and activate associated features to
enable all the various APIs:</p>
<pre><code class="language-toml">[package]
name = &quot;dom&quot;
version = &quot;0.1.0&quot;
authors = [&quot;The wasm-bindgen Developers&quot;]
edition = &quot;2018&quot;
[lib]
crate-type = [&quot;cdylib&quot;]
[dependencies]
wasm-bindgen = &quot;0.2.63&quot;
[dependencies.web-sys]
version = &quot;0.3.4&quot;
features = [
'Document',
'Element',
'HtmlElement',
'Node',
'Window',
]
</code></pre>
<h2><a class="header" href="#srclibrs-4" id="srclibrs-4"><code>src/lib.rs</code></a></h2>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
use wasm_bindgen::prelude::*;
// Called by our JS entry point to run the example
#[wasm_bindgen(start)]
pub fn run() -&gt; Result&lt;(), JsValue&gt; {
// Use `web_sys`'s global `window` function to get a handle on the global
// window object.
let window = web_sys::window().expect(&quot;no global `window` exists&quot;);
let document = window.document().expect(&quot;should have a document on window&quot;);
let body = document.body().expect(&quot;document should have a body&quot;);
// Manufacture the element we're gonna append
let val = document.create_element(&quot;p&quot;)?;
val.set_inner_html(&quot;Hello from Rust!&quot;);
body.append_child(&amp;val)?;
Ok(())
}
#}</code></pre></pre>
<h1><a class="header" href="#web-sys-closures" id="web-sys-closures">web-sys: Closures</a></h1>
<p><a href="https://github.com/rustwasm/wasm-bindgen/tree/master/examples/closures">View full source code</a> or <a href="https://rustwasm.github.io/wasm-bindgen/exbuild/closures/">view the compiled example online</a></p>
<p>One of the features of <code>#[wasm_bindgen]</code> is that you can pass closures defined
in Rust off to JS. This can be a bit tricky at times, though, so the example
here shows how to interact with some standard web APIs with closures.</p>
<h2><a class="header" href="#srclibrs-5" id="srclibrs-5"><code>src/lib.rs</code></a></h2>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
use js_sys::{Array, Date};
use wasm_bindgen::prelude::*;
use wasm_bindgen::JsCast;
use web_sys::{Document, Element, HtmlElement, Window};
#[wasm_bindgen(start)]
pub fn run() -&gt; Result&lt;(), JsValue&gt; {
let window = web_sys::window().expect(&quot;should have a window in this context&quot;);
let document = window.document().expect(&quot;window should have a document&quot;);
// One of the first interesting things we can do with closures is simply
// access stack data in Rust!
let array = Array::new();
array.push(&amp;&quot;Hello&quot;.into());
array.push(&amp;1.into());
let mut first_item = None;
array.for_each(&amp;mut |obj, idx, _arr| match idx {
0 =&gt; {
assert_eq!(obj, &quot;Hello&quot;);
first_item = obj.as_string();
}
1 =&gt; assert_eq!(obj, 1),
_ =&gt; panic!(&quot;unknown index: {}&quot;, idx),
});
assert_eq!(first_item, Some(&quot;Hello&quot;.to_string()));
// Below are some more advanced usages of the `Closure` type for closures
// that need to live beyond our function call.
setup_clock(&amp;window, &amp;document)?;
setup_clicker(&amp;document);
// And now that our demo is ready to go let's switch things up so
// everything is displayed and our loading prompt is hidden.
document
.get_element_by_id(&quot;loading&quot;)
.expect(&quot;should have #loading on the page&quot;)
.dyn_ref::&lt;HtmlElement&gt;()
.expect(&quot;#loading should be an `HtmlElement`&quot;)
.style()
.set_property(&quot;display&quot;, &quot;none&quot;)?;
document
.get_element_by_id(&quot;script&quot;)
.expect(&quot;should have #script on the page&quot;)
.dyn_ref::&lt;HtmlElement&gt;()
.expect(&quot;#script should be an `HtmlElement`&quot;)
.style()
.set_property(&quot;display&quot;, &quot;block&quot;)?;
Ok(())
}
// Set up a clock on our page and update it each second to ensure it's got
// an accurate date.
//
// Note the usage of `Closure` here because the closure is &quot;long lived&quot;,
// basically meaning it has to persist beyond the call to this one function.
// Also of note here is the `.as_ref().unchecked_ref()` chain, which is how
// you can extract `&amp;Function`, what `web-sys` expects, from a `Closure`
// which only hands you `&amp;JsValue` via `AsRef`.
fn setup_clock(window: &amp;Window, document: &amp;Document) -&gt; Result&lt;(), JsValue&gt; {
let current_time = document
.get_element_by_id(&quot;current-time&quot;)
.expect(&quot;should have #current-time on the page&quot;);
update_time(&amp;current_time);
let a = Closure::wrap(Box::new(move || update_time(&amp;current_time)) as Box&lt;dyn Fn()&gt;);
window
.set_interval_with_callback_and_timeout_and_arguments_0(a.as_ref().unchecked_ref(), 1000)?;
fn update_time(current_time: &amp;Element) {
current_time.set_inner_html(&amp;String::from(
Date::new_0().to_locale_string(&quot;en-GB&quot;, &amp;JsValue::undefined()),
));
}
// The instance of `Closure` that we created will invalidate its
// corresponding JS callback whenever it is dropped, so if we were to
// normally return from `setup_clock` then our registered closure will
// raise an exception when invoked.
//
// Normally we'd store the handle to later get dropped at an appropriate
// time but for now we want it to be a global handler so we use the
// `forget` method to drop it without invalidating the closure. Note that
// this is leaking memory in Rust, so this should be done judiciously!
a.forget();
Ok(())
}
// We also want to count the number of times that our green square has been
// clicked. Our callback will update the `#num-clicks` div.
//
// This is pretty similar above, but showing how closures can also implement
// `FnMut()`.
fn setup_clicker(document: &amp;Document) {
let num_clicks = document
.get_element_by_id(&quot;num-clicks&quot;)
.expect(&quot;should have #num-clicks on the page&quot;);
let mut clicks = 0;
let a = Closure::wrap(Box::new(move || {
clicks += 1;
num_clicks.set_inner_html(&amp;clicks.to_string());
}) as Box&lt;dyn FnMut()&gt;);
document
.get_element_by_id(&quot;green-square&quot;)
.expect(&quot;should have #green-square on the page&quot;)
.dyn_ref::&lt;HtmlElement&gt;()
.expect(&quot;#green-square be an `HtmlElement`&quot;)
.set_onclick(Some(a.as_ref().unchecked_ref()));
// See comments in `setup_clock` above for why we use `a.forget()`.
a.forget();
}
#}</code></pre></pre>
<h1><a class="header" href="#web-sys-performancenow" id="web-sys-performancenow">web-sys: <code>performance.now</code></a></h1>
<p><a href="https://github.com/rustwasm/wasm-bindgen/tree/master/examples/performance">View full source code</a> or <a href="https://rustwasm.github.io/wasm-bindgen/exbuild/performance/">view the compiled example online</a></p>
<p>Want to profile some Rust code in the browser? No problem! You can use the
<code>performance.now()</code> API and friends to get timing information to see how long
things take.</p>
<h2><a class="header" href="#srclibrs-6" id="srclibrs-6"><code>src/lib.rs</code></a></h2>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
use std::time::{Duration, SystemTime, UNIX_EPOCH};
use wasm_bindgen::prelude::*;
// lifted from the `console_log` example
#[wasm_bindgen]
extern &quot;C&quot; {
#[wasm_bindgen(js_namespace = console)]
fn log(a: &amp;str);
}
macro_rules! console_log {
($($t:tt)*) =&gt; (log(&amp;format_args!($($t)*).to_string()))
}
#[wasm_bindgen(start)]
pub fn run() {
let window = web_sys::window().expect(&quot;should have a window in this context&quot;);
let performance = window
.performance()
.expect(&quot;performance should be available&quot;);
console_log!(&quot;the current time (in ms) is {}&quot;, performance.now());
let start = perf_to_system(performance.timing().request_start());
let end = perf_to_system(performance.timing().response_end());
console_log!(&quot;request started at {}&quot;, humantime::format_rfc3339(start));
console_log!(&quot;request ended at {}&quot;, humantime::format_rfc3339(end));
}
fn perf_to_system(amt: f64) -&gt; SystemTime {
let secs = (amt as u64) / 1_000;
let nanos = ((amt as u32) % 1_000) * 1_000_000;
UNIX_EPOCH + Duration::new(secs, nanos)
}
#}</code></pre></pre>
<h1><a class="header" href="#the-fetch-api" id="the-fetch-api">The <code>fetch</code> API</a></h1>
<p><a href="https://github.com/rustwasm/wasm-bindgen/tree/master/examples/fetch">View full source code</a> or <a href="https://rustwasm.github.io/wasm-bindgen/exbuild/fetch/">view the compiled example online</a></p>
<p>This example uses the <code>fetch</code> API to make an HTTP request to the GitHub API and
then parses the resulting JSON.</p>
<h2><a class="header" href="#cargotoml-2" id="cargotoml-2"><code>Cargo.toml</code></a></h2>
<p>The <code>Cargo.toml</code> enables a number of features related to the <code>fetch</code> API and
types used: <code>Headers</code>, <code>Request</code>, etc. It also enables <code>wasm-bindgen</code>'s <code>serde</code>
support.</p>
<pre><code class="language-toml">[package]
name = &quot;fetch&quot;
version = &quot;0.1.0&quot;
authors = [&quot;The wasm-bindgen Developers&quot;]
edition = &quot;2018&quot;
[lib]
crate-type = [&quot;cdylib&quot;]
[dependencies]
wasm-bindgen = { version = &quot;0.2.63&quot;, features = [&quot;serde-serialize&quot;] }
js-sys = &quot;0.3.40&quot;
wasm-bindgen-futures = &quot;0.4.13&quot;
serde = { version = &quot;1.0.80&quot;, features = [&quot;derive&quot;] }
serde_derive = &quot;^1.0.59&quot;
[dependencies.web-sys]
version = &quot;0.3.4&quot;
features = [
'Headers',
'Request',
'RequestInit',
'RequestMode',
'Response',
'Window',
]
</code></pre>
<h2><a class="header" href="#srclibrs-7" id="srclibrs-7"><code>src/lib.rs</code></a></h2>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
use serde::{Deserialize, Serialize};
use wasm_bindgen::prelude::*;
use wasm_bindgen::JsCast;
use wasm_bindgen_futures::JsFuture;
use web_sys::{Request, RequestInit, RequestMode, Response};
/// A struct to hold some data from the github Branch API.
///
/// Note how we don't have to define every member -- serde will ignore extra
/// data when deserializing
#[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 async fn run(repo: String) -&gt; Result&lt;JsValue, JsValue&gt; {
let mut opts = RequestInit::new();
opts.method(&quot;GET&quot;);
opts.mode(RequestMode::Cors);
let url = format!(&quot;https://api.github.com/repos/{}/branches/master&quot;, repo);
let request = Request::new_with_str_and_init(&amp;url, &amp;opts)?;
request
.headers()
.set(&quot;Accept&quot;, &quot;application/vnd.github.v3+json&quot;)?;
let window = web_sys::window().unwrap();
let resp_value = JsFuture::from(window.fetch_with_request(&amp;request)).await?;
// `resp_value` is a `Response` object.
assert!(resp_value.is_instance_of::&lt;Response&gt;());
let resp: Response = resp_value.dyn_into().unwrap();
// Convert this other `Promise` into a rust `Future`.
let json = JsFuture::from(resp.json()?).await?;
// Use serde to parse the JSON into a struct.
let branch_info: Branch = json.into_serde().unwrap();
// Send the `Branch` struct back to JS as an `Object`.
Ok(JsValue::from_serde(&amp;branch_info).unwrap())
}
#}</code></pre></pre>
<h1><a class="header" href="#2d-canvas" id="2d-canvas">2D Canvas</a></h1>
<p><a href="https://github.com/rustwasm/wasm-bindgen/tree/master/examples/canvas">View full source code</a> or <a href="https://rustwasm.github.io/wasm-bindgen/exbuild/canvas/">view the compiled example online</a></p>
<p>Drawing a smiley face with the 2D canvas API. This is a port of part of <a href="https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Tutorial/Drawing_shapes#Moving_the_pen">this
MDN
tutorial</a>
to <code>web-sys</code>.</p>
<p><img src="examples/./2d-canvas.png" alt="A smiley face" /></p>
<h2><a class="header" href="#cargotoml-3" id="cargotoml-3"><code>Cargo.toml</code></a></h2>
<p>The <code>Cargo.toml</code> enables features necessary to query the DOM and work with 2D
canvas.</p>
<pre><code class="language-toml">[package]
name = &quot;canvas&quot;
version = &quot;0.1.0&quot;
authors = [&quot;The wasm-bindgen Developers&quot;]
edition = &quot;2018&quot;
[lib]
crate-type = [&quot;cdylib&quot;]
[dependencies]
js-sys = &quot;0.3.40&quot;
wasm-bindgen = &quot;0.2.63&quot;
[dependencies.web-sys]
version = &quot;0.3.4&quot;
features = [
'CanvasRenderingContext2d',
'Document',
'Element',
'HtmlCanvasElement',
'Window',
]
</code></pre>
<h2><a class="header" href="#srclibrs-8" id="srclibrs-8"><code>src/lib.rs</code></a></h2>
<p>Gets the <code>&lt;canvas&gt;</code> element, creates a 2D rendering context, and draws the
smiley face.</p>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
use std::f64;
use wasm_bindgen::prelude::*;
use wasm_bindgen::JsCast;
#[wasm_bindgen(start)]
pub fn start() {
let document = web_sys::window().unwrap().document().unwrap();
let canvas = document.get_element_by_id(&quot;canvas&quot;).unwrap();
let canvas: web_sys::HtmlCanvasElement = canvas
.dyn_into::&lt;web_sys::HtmlCanvasElement&gt;()
.map_err(|_| ())
.unwrap();
let context = canvas
.get_context(&quot;2d&quot;)
.unwrap()
.unwrap()
.dyn_into::&lt;web_sys::CanvasRenderingContext2d&gt;()
.unwrap();
context.begin_path();
// Draw the outer circle.
context
.arc(75.0, 75.0, 50.0, 0.0, f64::consts::PI * 2.0)
.unwrap();
// Draw the mouth.
context.move_to(110.0, 75.0);
context.arc(75.0, 75.0, 35.0, 0.0, f64::consts::PI).unwrap();
// Draw the left eye.
context.move_to(65.0, 65.0);
context
.arc(60.0, 65.0, 5.0, 0.0, f64::consts::PI * 2.0)
.unwrap();
// Draw the right eye.
context.move_to(95.0, 65.0);
context
.arc(90.0, 65.0, 5.0, 0.0, f64::consts::PI * 2.0)
.unwrap();
context.stroke();
}
#}</code></pre></pre>
<h1><a class="header" href="#julia-set" id="julia-set">Julia Set</a></h1>
<p><a href="https://github.com/rustwasm/wasm-bindgen/tree/master/examples/julia_set">View full source code</a> or <a href="https://rustwasm.github.io/wasm-bindgen/exbuild/julia_set/">view the compiled example online</a></p>
<p>While not showing off a lot of <code>web_sys</code> API surface area, this example shows a
neat fractal that you can make!</p>
<h2><a class="header" href="#indexjs-2" id="indexjs-2"><code>index.js</code></a></h2>
<p>A small bit of glue is added for this example</p>
<pre><code class="language-js">import('./pkg')
.then(wasm =&gt; {
const canvas = document.getElementById('drawing');
const ctx = canvas.getContext('2d');
const realInput = document.getElementById('real');
const imaginaryInput = document.getElementById('imaginary');
const renderBtn = document.getElementById('render');
renderBtn.addEventListener('click', () =&gt; {
const real = parseFloat(realInput.value) || 0;
const imaginary = parseFloat(imaginaryInput.value) || 0;
wasm.draw(ctx, 600, 600, real, imaginary);
});
wasm.draw(ctx, 600, 600, -0.15, 0.65);
})
.catch(console.error);
</code></pre>
<h2><a class="header" href="#srclibrs-9" id="srclibrs-9"><code>src/lib.rs</code></a></h2>
<p>The bulk of the logic is in the generation of the fractal</p>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
use std::ops::Add;
use wasm_bindgen::prelude::*;
use wasm_bindgen::Clamped;
use web_sys::{CanvasRenderingContext2d, ImageData};
#[wasm_bindgen]
pub fn draw(
ctx: &amp;CanvasRenderingContext2d,
width: u32,
height: u32,
real: f64,
imaginary: f64,
) -&gt; Result&lt;(), JsValue&gt; {
// The real workhorse of this algorithm, generating pixel data
let c = Complex { real, imaginary };
let mut data = get_julia_set(width, height, c);
let data = ImageData::new_with_u8_clamped_array_and_sh(Clamped(&amp;mut data), width, height)?;
ctx.put_image_data(&amp;data, 0.0, 0.0)
}
fn get_julia_set(width: u32, height: u32, c: Complex) -&gt; Vec&lt;u8&gt; {
let mut data = Vec::new();
let param_i = 1.5;
let param_r = 1.5;
let scale = 0.005;
for x in 0..width {
for y in 0..height {
let z = Complex {
real: y as f64 * scale - param_r,
imaginary: x as f64 * scale - param_i,
};
let iter_index = get_iter_index(z, c);
data.push((iter_index / 4) as u8);
data.push((iter_index / 2) as u8);
data.push(iter_index as u8);
data.push(255);
}
}
data
}
fn get_iter_index(z: Complex, c: Complex) -&gt; u32 {
let mut iter_index: u32 = 0;
let mut z = z;
while iter_index &lt; 900 {
if z.norm() &gt; 2.0 {
break;
}
z = z.square() + c;
iter_index += 1;
}
iter_index
}
#[derive(Clone, Copy, Debug)]
struct Complex {
real: f64,
imaginary: f64,
}
impl Complex {
fn square(self) -&gt; Complex {
let real = (self.real * self.real) - (self.imaginary * self.imaginary);
let imaginary = 2.0 * self.real * self.imaginary;
Complex { real, imaginary }
}
fn norm(&amp;self) -&gt; f64 {
(self.real * self.real) + (self.imaginary * self.imaginary)
}
}
impl Add&lt;Complex&gt; for Complex {
type Output = Complex;
fn add(self, rhs: Complex) -&gt; Complex {
Complex {
real: self.real + rhs.real,
imaginary: self.imaginary + rhs.imaginary,
}
}
}
#}</code></pre></pre>
<h1><a class="header" href="#webaudio" id="webaudio">WebAudio</a></h1>
<p><a href="https://github.com/rustwasm/wasm-bindgen/tree/master/examples/webaudio">View full source code</a> or <a href="https://rustwasm.github.io/wasm-bindgen/exbuild/webaudio/">view the compiled example online</a></p>
<p>This example creates an <a href="https://en.wikipedia.org/wiki/Frequency_modulation_synthesis">FM
oscillator</a> using
the <a href="https://developer.mozilla.org/en-US/docs/Web/API/Web_Audio_API">WebAudio
API</a> and
<code>web-sys</code>.</p>
<h2><a class="header" href="#cargotoml-4" id="cargotoml-4"><code>Cargo.toml</code></a></h2>
<p>The <code>Cargo.toml</code> enables the types needed to use the relevant bits of the
WebAudio API.</p>
<pre><code class="language-toml">[package]
name = &quot;webaudio&quot;
version = &quot;0.1.0&quot;
authors = [&quot;The wasm-bindgen Developers&quot;]
edition = &quot;2018&quot;
[lib]
crate-type = [&quot;cdylib&quot;]
[dependencies]
wasm-bindgen = &quot;0.2.63&quot;
[dependencies.web-sys]
version = &quot;0.3.4&quot;
features = [
'AudioContext',
'AudioDestinationNode',
'AudioNode',
'AudioParam',
'GainNode',
'OscillatorNode',
'OscillatorType',
]
</code></pre>
<h2><a class="header" href="#srclibrs-10" id="srclibrs-10"><code>src/lib.rs</code></a></h2>
<p>The Rust code implements the FM oscillator.</p>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
use wasm_bindgen::prelude::*;
use web_sys::{AudioContext, OscillatorType};
/// Converts a midi note to frequency
///
/// A midi note is an integer, generally in the range of 21 to 108
pub fn midi_to_freq(note: u8) -&gt; f32 {
27.5 * 2f32.powf((note as f32 - 21.0) / 12.0)
}
#[wasm_bindgen]
pub struct FmOsc {
ctx: AudioContext,
/// The primary oscillator. This will be the fundamental frequency
primary: web_sys::OscillatorNode,
/// Overall gain (volume) control
gain: web_sys::GainNode,
/// Amount of frequency modulation
fm_gain: web_sys::GainNode,
/// The oscillator that will modulate the primary oscillator's frequency
fm_osc: web_sys::OscillatorNode,
/// The ratio between the primary frequency and the fm_osc frequency.
///
/// Generally fractional values like 1/2 or 1/4 sound best
fm_freq_ratio: f32,
fm_gain_ratio: f32,
}
impl Drop for FmOsc {
fn drop(&amp;mut self) {
let _ = self.ctx.close();
}
}
#[wasm_bindgen]
impl FmOsc {
#[wasm_bindgen(constructor)]
pub fn new() -&gt; Result&lt;FmOsc, JsValue&gt; {
let ctx = web_sys::AudioContext::new()?;
// Create our web audio objects.
let primary = ctx.create_oscillator()?;
let fm_osc = ctx.create_oscillator()?;
let gain = ctx.create_gain()?;
let fm_gain = ctx.create_gain()?;
// Some initial settings:
primary.set_type(OscillatorType::Sine);
primary.frequency().set_value(440.0); // A4 note
gain.gain().set_value(0.0); // starts muted
fm_gain.gain().set_value(0.0); // no initial frequency modulation
fm_osc.set_type(OscillatorType::Sine);
fm_osc.frequency().set_value(0.0);
// Connect the nodes up!
// The primary oscillator is routed through the gain node, so that
// it can control the overall output volume.
primary.connect_with_audio_node(&amp;gain)?;
// Then connect the gain node to the AudioContext destination (aka
// your speakers).
gain.connect_with_audio_node(&amp;ctx.destination())?;
// The FM oscillator is connected to its own gain node, so it can
// control the amount of modulation.
fm_osc.connect_with_audio_node(&amp;fm_gain)?;
// Connect the FM oscillator to the frequency parameter of the main
// oscillator, so that the FM node can modulate its frequency.
fm_gain.connect_with_audio_param(&amp;primary.frequency())?;
// Start the oscillators!
primary.start()?;
fm_osc.start()?;
Ok(FmOsc {
ctx,
primary,
gain,
fm_gain,
fm_osc,
fm_freq_ratio: 0.0,
fm_gain_ratio: 0.0,
})
}
/// Sets the gain for this oscillator, between 0.0 and 1.0.
#[wasm_bindgen]
pub fn set_gain(&amp;self, mut gain: f32) {
if gain &gt; 1.0 {
gain = 1.0;
}
if gain &lt; 0.0 {
gain = 0.0;
}
self.gain.gain().set_value(gain);
}
#[wasm_bindgen]
pub fn set_primary_frequency(&amp;self, freq: f32) {
self.primary.frequency().set_value(freq);
// The frequency of the FM oscillator depends on the frequency of the
// primary oscillator, so we update the frequency of both in this method.
self.fm_osc.frequency().set_value(self.fm_freq_ratio * freq);
self.fm_gain.gain().set_value(self.fm_gain_ratio * freq);
}
#[wasm_bindgen]
pub fn set_note(&amp;self, note: u8) {
let freq = midi_to_freq(note);
self.set_primary_frequency(freq);
}
/// This should be between 0 and 1, though higher values are accepted.
#[wasm_bindgen]
pub fn set_fm_amount(&amp;mut self, amt: f32) {
self.fm_gain_ratio = amt;
self.fm_gain
.gain()
.set_value(self.fm_gain_ratio * self.primary.frequency().value());
}
/// This should be between 0 and 1, though higher values are accepted.
#[wasm_bindgen]
pub fn set_fm_frequency(&amp;mut self, amt: f32) {
self.fm_freq_ratio = amt;
self.fm_osc
.frequency()
.set_value(self.fm_freq_ratio * self.primary.frequency().value());
}
}
#}</code></pre></pre>
<h2><a class="header" href="#indexjs-3" id="indexjs-3"><code>index.js</code></a></h2>
<p>A small bit of JavaScript glues the rust module to input widgets and translates
events into calls into wasm code.</p>
<pre><code class="language-js">import('./pkg')
.then(rust_module =&gt; {
let fm = null;
const play_button = document.getElementById(&quot;play&quot;);
play_button.addEventListener(&quot;click&quot;, event =&gt; {
if (fm === null) {
fm = new rust_module.FmOsc();
fm.set_note(50);
fm.set_fm_frequency(0);
fm.set_fm_amount(0);
fm.set_gain(0.8);
} else {
fm.free();
fm = null;
}
});
const primary_slider = document.getElementById(&quot;primary_input&quot;);
primary_slider.addEventListener(&quot;input&quot;, event =&gt; {
if (fm) {
fm.set_note(parseInt(event.target.value));
}
});
const fm_freq = document.getElementById(&quot;fm_freq&quot;);
fm_freq.addEventListener(&quot;input&quot;, event =&gt; {
if (fm) {
fm.set_fm_frequency(parseFloat(event.target.value));
}
});
const fm_amount = document.getElementById(&quot;fm_amount&quot;);
fm_amount.addEventListener(&quot;input&quot;, event =&gt; {
if (fm) {
fm.set_fm_amount(parseFloat(event.target.value));
}
});
})
.catch(console.error);
</code></pre>
<h1><a class="header" href="#webgl-example" id="webgl-example">WebGL Example</a></h1>
<p><a href="https://github.com/rustwasm/wasm-bindgen/tree/master/examples/webgl">View full source code</a> or <a href="https://rustwasm.github.io/wasm-bindgen/exbuild/webgl/">view the compiled example online</a></p>
<p>This example draws a triangle to the screen using the WebGL API.</p>
<h2><a class="header" href="#cargotoml-5" id="cargotoml-5"><code>Cargo.toml</code></a></h2>
<p>The <code>Cargo.toml</code> enables features necessary to obtain and use a WebGL
rendering context.</p>
<pre><code class="language-toml">[package]
name = &quot;webgl&quot;
version = &quot;0.1.0&quot;
authors = [&quot;The wasm-bindgen Developers&quot;]
edition = &quot;2018&quot;
[lib]
crate-type = [&quot;cdylib&quot;]
[dependencies]
js-sys = &quot;0.3.40&quot;
wasm-bindgen = &quot;0.2.63&quot;
[dependencies.web-sys]
version = &quot;0.3.4&quot;
features = [
'Document',
'Element',
'HtmlCanvasElement',
'WebGlBuffer',
'WebGlRenderingContext',
'WebGlProgram',
'WebGlShader',
'Window',
]
</code></pre>
<h2><a class="header" href="#srclibrs-11" id="srclibrs-11"><code>src/lib.rs</code></a></h2>
<p>This source file handles all of the necessary logic to obtain a rendering
context, compile shaders, fill a buffer with vertex coordinates, and draw a
triangle to the screen.</p>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
use wasm_bindgen::prelude::*;
use wasm_bindgen::JsCast;
use web_sys::{WebGlProgram, WebGlRenderingContext, WebGlShader};
#[wasm_bindgen(start)]
pub fn start() -&gt; Result&lt;(), JsValue&gt; {
let document = web_sys::window().unwrap().document().unwrap();
let canvas = document.get_element_by_id(&quot;canvas&quot;).unwrap();
let canvas: web_sys::HtmlCanvasElement = canvas.dyn_into::&lt;web_sys::HtmlCanvasElement&gt;()?;
let context = canvas
.get_context(&quot;webgl&quot;)?
.unwrap()
.dyn_into::&lt;WebGlRenderingContext&gt;()?;
let vert_shader = compile_shader(
&amp;context,
WebGlRenderingContext::VERTEX_SHADER,
r#&quot;
attribute vec4 position;
void main() {
gl_Position = position;
}
&quot;#,
)?;
let frag_shader = compile_shader(
&amp;context,
WebGlRenderingContext::FRAGMENT_SHADER,
r#&quot;
void main() {
gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);
}
&quot;#,
)?;
let program = link_program(&amp;context, &amp;vert_shader, &amp;frag_shader)?;
context.use_program(Some(&amp;program));
let vertices: [f32; 9] = [-0.7, -0.7, 0.0, 0.7, -0.7, 0.0, 0.0, 0.7, 0.0];
let buffer = context.create_buffer().ok_or(&quot;failed to create buffer&quot;)?;
context.bind_buffer(WebGlRenderingContext::ARRAY_BUFFER, Some(&amp;buffer));
// Note that `Float32Array::view` is somewhat dangerous (hence the
// `unsafe`!). This is creating a raw view into our module's
// `WebAssembly.Memory` buffer, but if we allocate more pages for ourself
// (aka do a memory allocation in Rust) it'll cause the buffer to change,
// causing the `Float32Array` to be invalid.
//
// As a result, after `Float32Array::view` we have to be very careful not to
// do any memory allocations before it's dropped.
unsafe {
let vert_array = js_sys::Float32Array::view(&amp;vertices);
context.buffer_data_with_array_buffer_view(
WebGlRenderingContext::ARRAY_BUFFER,
&amp;vert_array,
WebGlRenderingContext::STATIC_DRAW,
);
}
context.vertex_attrib_pointer_with_i32(0, 3, WebGlRenderingContext::FLOAT, false, 0, 0);
context.enable_vertex_attrib_array(0);
context.clear_color(0.0, 0.0, 0.0, 1.0);
context.clear(WebGlRenderingContext::COLOR_BUFFER_BIT);
context.draw_arrays(
WebGlRenderingContext::TRIANGLES,
0,
(vertices.len() / 3) as i32,
);
Ok(())
}
pub fn compile_shader(
context: &amp;WebGlRenderingContext,
shader_type: u32,
source: &amp;str,
) -&gt; Result&lt;WebGlShader, String&gt; {
let shader = context
.create_shader(shader_type)
.ok_or_else(|| String::from(&quot;Unable to create shader object&quot;))?;
context.shader_source(&amp;shader, source);
context.compile_shader(&amp;shader);
if context
.get_shader_parameter(&amp;shader, WebGlRenderingContext::COMPILE_STATUS)
.as_bool()
.unwrap_or(false)
{
Ok(shader)
} else {
Err(context
.get_shader_info_log(&amp;shader)
.unwrap_or_else(|| String::from(&quot;Unknown error creating shader&quot;)))
}
}
pub fn link_program(
context: &amp;WebGlRenderingContext,
vert_shader: &amp;WebGlShader,
frag_shader: &amp;WebGlShader,
) -&gt; Result&lt;WebGlProgram, String&gt; {
let program = context
.create_program()
.ok_or_else(|| String::from(&quot;Unable to create shader object&quot;))?;
context.attach_shader(&amp;program, vert_shader);
context.attach_shader(&amp;program, frag_shader);
context.link_program(&amp;program);
if context
.get_program_parameter(&amp;program, WebGlRenderingContext::LINK_STATUS)
.as_bool()
.unwrap_or(false)
{
Ok(program)
} else {
Err(context
.get_program_info_log(&amp;program)
.unwrap_or_else(|| String::from(&quot;Unknown error creating program object&quot;)))
}
}
#}</code></pre></pre>
<h1><a class="header" href="#websockets-example" id="websockets-example">WebSockets Example</a></h1>
<p><a href="https://github.com/rustwasm/wasm-bindgen/tree/master/examples/websockets/">View full source code</a> or <a href="https://rustwasm.github.io/wasm-bindgen/exbuild/websockets/">view the compiled example online</a></p>
<p>This example connects to an echo server on <code>wss://echo.websocket.org</code>,
sends a <code>ping</code> message, and receives the response.</p>
<h2><a class="header" href="#cargotoml-6" id="cargotoml-6"><code>Cargo.toml</code></a></h2>
<p>The <code>Cargo.toml</code> enables features necessary to create a <code>WebSocket</code> object and
to access events such as <code>MessageEvent</code> or <code>ErrorEvent</code>.</p>
<pre><code class="language-toml">[package]
name = &quot;websockets&quot;
version = &quot;0.1.0&quot;
authors = [&quot;The wasm-bindgen Developers&quot;]
edition = &quot;2018&quot;
[lib]
crate-type = [&quot;cdylib&quot;]
[dependencies]
wasm-bindgen = &quot;0.2.63&quot;
js-sys = &quot;0.3&quot;
[dependencies.web-sys]
version = &quot;0.3.22&quot;
features = [
&quot;BinaryType&quot;,
&quot;Blob&quot;,
&quot;ErrorEvent&quot;,
&quot;FileReader&quot;,
&quot;MessageEvent&quot;,
&quot;ProgressEvent&quot;,
&quot;WebSocket&quot;,
]
</code></pre>
<h2><a class="header" href="#srclibrs-12" id="srclibrs-12"><code>src/lib.rs</code></a></h2>
<p>This code shows the basic steps required to work with a <code>WebSocket</code>.
At first it opens the connection, then subscribes to events <code>onmessage</code>, <code>onerror</code>, <code>onopen</code>.
After the socket is opened it sends a <code>ping</code> message, receives an echoed response
and prints it to the browser console.</p>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
use wasm_bindgen::prelude::*;
use wasm_bindgen::JsCast;
use web_sys::{ErrorEvent, MessageEvent, WebSocket};
macro_rules! console_log {
($($t:tt)*) =&gt; (log(&amp;format_args!($($t)*).to_string()))
}
#[wasm_bindgen]
extern &quot;C&quot; {
#[wasm_bindgen(js_namespace = console)]
fn log(s: &amp;str);
}
#[wasm_bindgen(start)]
pub fn start_websocket() -&gt; Result&lt;(), JsValue&gt; {
// Connect to an echo server
let ws = WebSocket::new(&quot;wss://echo.websocket.org&quot;)?;
// For small binary messages, like CBOR, Arraybuffer is more efficient than Blob handling
ws.set_binary_type(web_sys::BinaryType::Arraybuffer);
// create callback
let cloned_ws = ws.clone();
let onmessage_callback = Closure::wrap(Box::new(move |e: MessageEvent| {
// Handle difference Text/Binary,...
if let Ok(abuf) = e.data().dyn_into::&lt;js_sys::ArrayBuffer&gt;() {
console_log!(&quot;message event, received arraybuffer: {:?}&quot;, abuf);
let array = js_sys::Uint8Array::new(&amp;abuf);
let len = array.byte_length() as usize;
console_log!(&quot;Arraybuffer received {}bytes: {:?}&quot;, len, array.to_vec());
// here you can for example use Serde Deserialize decode the message
// for demo purposes we switch back to Blob-type and send off another binary message
cloned_ws.set_binary_type(web_sys::BinaryType::Blob);
match cloned_ws.send_with_u8_array(&amp;vec![5, 6, 7, 8]) {
Ok(_) =&gt; console_log!(&quot;binary message successfully sent&quot;),
Err(err) =&gt; console_log!(&quot;error sending message: {:?}&quot;, err),
}
} else if let Ok(blob) = e.data().dyn_into::&lt;web_sys::Blob&gt;() {
console_log!(&quot;message event, received blob: {:?}&quot;, blob);
// better alternative to juggling with FileReader is to use https://crates.io/crates/gloo-file
let fr = web_sys::FileReader::new().unwrap();
let fr_c = fr.clone();
// create onLoadEnd callback
let onloadend_cb = Closure::wrap(Box::new(move |_e: web_sys::ProgressEvent| {
let array = js_sys::Uint8Array::new(&amp;fr_c.result().unwrap());
let len = array.byte_length() as usize;
console_log!(&quot;Blob received {}bytes: {:?}&quot;, len, array.to_vec());
// here you can for example use the received image/png data
})
as Box&lt;dyn FnMut(web_sys::ProgressEvent)&gt;);
fr.set_onloadend(Some(onloadend_cb.as_ref().unchecked_ref()));
fr.read_as_array_buffer(&amp;blob).expect(&quot;blob not readable&quot;);
onloadend_cb.forget();
} else if let Ok(txt) = e.data().dyn_into::&lt;js_sys::JsString&gt;() {
console_log!(&quot;message event, received Text: {:?}&quot;, txt);
} else {
console_log!(&quot;message event, received Unknown: {:?}&quot;, e.data());
}
}) as Box&lt;dyn FnMut(MessageEvent)&gt;);
// set message event handler on WebSocket
ws.set_onmessage(Some(onmessage_callback.as_ref().unchecked_ref()));
// forget the callback to keep it alive
onmessage_callback.forget();
let onerror_callback = Closure::wrap(Box::new(move |e: ErrorEvent| {
console_log!(&quot;error event: {:?}&quot;, e);
}) as Box&lt;dyn FnMut(ErrorEvent)&gt;);
ws.set_onerror(Some(onerror_callback.as_ref().unchecked_ref()));
onerror_callback.forget();
let cloned_ws = ws.clone();
let onopen_callback = Closure::wrap(Box::new(move |_| {
console_log!(&quot;socket opened&quot;);
match cloned_ws.send_with_str(&quot;ping&quot;) {
Ok(_) =&gt; console_log!(&quot;message successfully sent&quot;),
Err(err) =&gt; console_log!(&quot;error sending message: {:?}&quot;, err),
}
// send off binary message
match cloned_ws.send_with_u8_array(&amp;vec![0, 1, 2, 3]) {
Ok(_) =&gt; console_log!(&quot;binary message successfully sent&quot;),
Err(err) =&gt; console_log!(&quot;error sending message: {:?}&quot;, err),
}
}) as Box&lt;dyn FnMut(JsValue)&gt;);
ws.set_onopen(Some(onopen_callback.as_ref().unchecked_ref()));
onopen_callback.forget();
Ok(())
}
#}</code></pre></pre>
<h1><a class="header" href="#webrtc-datachannel-example" id="webrtc-datachannel-example">WebRTC DataChannel Example</a></h1>
<p><a href="https://github.com/rustwasm/wasm-bindgen/tree/master/examples/webrtc_datachannel/">View full source code</a> or <a href="https://rustwasm.github.io/wasm-bindgen/exbuild/webrtc_datachannel/">view the compiled example online</a></p>
<p>This example creates 2 peer connections and 2 data channels in single browser tab.
Send ping/pong between <code>peer1.dc</code> and <code>peer2.dc</code>.</p>
<h2><a class="header" href="#cargotoml-7" id="cargotoml-7"><code>Cargo.toml</code></a></h2>
<p>The <code>Cargo.toml</code> enables features necessary to use WebRTC DataChannel and its negotiation.</p>
<pre><code class="language-toml">[package]
name = &quot;webrtc_datachannel&quot;
version = &quot;0.1.0&quot;
authors = [&quot;The wasm-bindgen Developers&quot;]
edition = &quot;2018&quot;
[lib]
crate-type = [&quot;cdylib&quot;]
[dependencies]
wasm-bindgen = &quot;0.2.63&quot;
js-sys = &quot;0.3&quot;
wasm-bindgen-futures = &quot;0.4.13&quot;
[dependencies.web-sys]
version = &quot;0.3.22&quot;
features = [
&quot;MessageEvent&quot;,
&quot;RtcPeerConnection&quot;,
&quot;RtcSignalingState&quot;,
&quot;RtcSdpType&quot;,
&quot;RtcSessionDescriptionInit&quot;,
&quot;RtcPeerConnectionIceEvent&quot;,
&quot;RtcIceCandidate&quot;,
&quot;RtcDataChannel&quot;,
&quot;RtcDataChannelEvent&quot;,
]
</code></pre>
<h2><a class="header" href="#srclibrs-13" id="srclibrs-13"><code>src/lib.rs</code></a></h2>
<p>The Rust code connects WebRTC data channel.</p>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
use js_sys::Reflect;
use wasm_bindgen::prelude::*;
use wasm_bindgen::JsCast;
use wasm_bindgen_futures::JsFuture;
use web_sys::{
MessageEvent, RtcDataChannelEvent, RtcPeerConnection, RtcPeerConnectionIceEvent, RtcSdpType,
RtcSessionDescriptionInit,
};
macro_rules! console_log {
($($t:tt)*) =&gt; (log(&amp;format_args!($($t)*).to_string()))
}
macro_rules! console_warn {
($($t:tt)*) =&gt; (warn(&amp;format_args!($($t)*).to_string()))
}
#[wasm_bindgen]
extern &quot;C&quot; {
#[wasm_bindgen(js_namespace = console)]
fn log(s: &amp;str);
#[wasm_bindgen(js_namespace = console)]
fn warn(s: &amp;str);
}
#[wasm_bindgen(start)]
pub async fn start() -&gt; Result&lt;(), JsValue&gt; {
/*
* Set up PeerConnections
* pc1 &lt;=&gt; pc2
*
*/
let pc1 = RtcPeerConnection::new()?;
console_log!(&quot;pc1 created: state {:?}&quot;, pc1.signaling_state());
let pc2 = RtcPeerConnection::new()?;
console_log!(&quot;pc2 created: state {:?}&quot;, pc2.signaling_state());
/*
* Create DataChannel on pc1 to negotiate
* Message will be shonw here after connection established
*
*/
let dc1 = pc1.create_data_channel(&quot;my-data-channel&quot;);
console_log!(&quot;dc1 created: label {:?}&quot;, dc1.label());
let dc1_clone = dc1.clone();
let onmessage_callback =
Closure::wrap(
Box::new(move |ev: MessageEvent| match ev.data().as_string() {
Some(message) =&gt; {
console_warn!(&quot;{:?}&quot;, message);
dc1_clone.send_with_str(&quot;Pong from pc1.dc!&quot;).unwrap();
}
None =&gt; {}
}) as Box&lt;dyn FnMut(MessageEvent)&gt;,
);
dc1.set_onmessage(Some(onmessage_callback.as_ref().unchecked_ref()));
onmessage_callback.forget();
/*
* If negotiaion has done, this closure will be called
*
*/
let ondatachannel_callback = Closure::wrap(Box::new(move |ev: RtcDataChannelEvent| {
let dc2 = ev.channel();
console_log!(&quot;pc2.ondatachannel!: {:?}&quot;, dc2.label());
let onmessage_callback =
Closure::wrap(
Box::new(move |ev: MessageEvent| match ev.data().as_string() {
Some(message) =&gt; console_warn!(&quot;{:?}&quot;, message),
None =&gt; {}
}) as Box&lt;dyn FnMut(MessageEvent)&gt;,
);
dc2.set_onmessage(Some(onmessage_callback.as_ref().unchecked_ref()));
onmessage_callback.forget();
dc2.send_with_str(&quot;Ping from pc2.dc!&quot;).unwrap();
}) as Box&lt;dyn FnMut(RtcDataChannelEvent)&gt;);
pc2.set_ondatachannel(Some(ondatachannel_callback.as_ref().unchecked_ref()));
ondatachannel_callback.forget();
/*
* Handle ICE candidate each other
*
*/
let pc2_clone = pc2.clone();
let onicecandidate_callback1 =
Closure::wrap(
Box::new(move |ev: RtcPeerConnectionIceEvent| match ev.candidate() {
Some(candidate) =&gt; {
console_log!(&quot;pc1.onicecandidate: {:#?}&quot;, candidate.candidate());
let _ =
pc2_clone.add_ice_candidate_with_opt_rtc_ice_candidate(Some(&amp;candidate));
}
None =&gt; {}
}) as Box&lt;dyn FnMut(RtcPeerConnectionIceEvent)&gt;,
);
pc1.set_onicecandidate(Some(onicecandidate_callback1.as_ref().unchecked_ref()));
onicecandidate_callback1.forget();
let pc1_clone = pc1.clone();
let onicecandidate_callback2 =
Closure::wrap(
Box::new(move |ev: RtcPeerConnectionIceEvent| match ev.candidate() {
Some(candidate) =&gt; {
console_log!(&quot;pc2.onicecandidate: {:#?}&quot;, candidate.candidate());
let _ =
pc1_clone.add_ice_candidate_with_opt_rtc_ice_candidate(Some(&amp;candidate));
}
None =&gt; {}
}) as Box&lt;dyn FnMut(RtcPeerConnectionIceEvent)&gt;,
);
pc2.set_onicecandidate(Some(onicecandidate_callback2.as_ref().unchecked_ref()));
onicecandidate_callback2.forget();
/*
* Send OFFER from pc1 to pc2
*
*/
let offer = JsFuture::from(pc1.create_offer()).await?;
let offer_sdp = Reflect::get(&amp;offer, &amp;JsValue::from_str(&quot;sdp&quot;))?
.as_string()
.unwrap();
console_log!(&quot;pc1: offer {:?}&quot;, offer_sdp);
let mut offer_obj = RtcSessionDescriptionInit::new(RtcSdpType::Offer);
offer_obj.sdp(&amp;offer_sdp);
let sld_promise = pc1.set_local_description(&amp;offer_obj);
JsFuture::from(sld_promise).await?;
console_log!(&quot;pc1: state {:?}&quot;, pc1.signaling_state());
/*
* Receive OFFER from pc1
* Create and send ANSWER from pc2 to pc1
*
*/
let mut offer_obj = RtcSessionDescriptionInit::new(RtcSdpType::Offer);
offer_obj.sdp(&amp;offer_sdp);
let srd_promise = pc2.set_remote_description(&amp;offer_obj);
JsFuture::from(srd_promise).await?;
console_log!(&quot;pc2: state {:?}&quot;, pc2.signaling_state());
let answer = JsFuture::from(pc2.create_answer()).await?;
let answer_sdp = Reflect::get(&amp;answer, &amp;JsValue::from_str(&quot;sdp&quot;))?
.as_string()
.unwrap();
console_log!(&quot;pc2: answer {:?}&quot;, answer_sdp);
let mut answer_obj = RtcSessionDescriptionInit::new(RtcSdpType::Answer);
answer_obj.sdp(&amp;answer_sdp);
let sld_promise = pc2.set_local_description(&amp;answer_obj);
JsFuture::from(sld_promise).await?;
console_log!(&quot;pc2: state {:?}&quot;, pc2.signaling_state());
/*
* Receive ANSWER from pc2
*
*/
let mut answer_obj = RtcSessionDescriptionInit::new(RtcSdpType::Answer);
answer_obj.sdp(&amp;answer_sdp);
let srd_promise = pc1.set_remote_description(&amp;answer_obj);
JsFuture::from(srd_promise).await?;
console_log!(&quot;pc1: state {:?}&quot;, pc1.signaling_state());
Ok(())
}
#}</code></pre></pre>
<h1><a class="header" href="#web-sys-a-requestanimationframe-loop" id="web-sys-a-requestanimationframe-loop"><code>web-sys</code>: A <code>requestAnimationFrame</code> Loop</a></h1>
<p><a href="https://github.com/rustwasm/wasm-bindgen/tree/master/examples/request-animation-frame">View full source code</a> or <a href="https://rustwasm.github.io/wasm-bindgen/exbuild/request-animation-frame/">view the compiled example online</a></p>
<p>This is an example of a <code>requestAnimationFrame</code> loop using the <code>web-sys</code> crate!
It renders a count of how many times a <code>requestAnimationFrame</code> callback has been
invoked and then it breaks out of the <code>requestAnimationFrame</code> loop after 300
iterations.</p>
<h2><a class="header" href="#cargotoml-8" id="cargotoml-8"><code>Cargo.toml</code></a></h2>
<p>You can see here how we depend on <code>web-sys</code> and activate associated features to
enable all the various APIs:</p>
<pre><code class="language-toml">[package]
name = &quot;request-animation-frame&quot;
version = &quot;0.1.0&quot;
authors = [&quot;The wasm-bindgen Developers&quot;]
edition = &quot;2018&quot;
[lib]
crate-type = [&quot;cdylib&quot;]
[dependencies]
wasm-bindgen = &quot;0.2.63&quot;
[dependencies.web-sys]
version = &quot;0.3.4&quot;
features = [
'Document',
'Element',
'HtmlElement',
'Node',
'Window',
]
</code></pre>
<h2><a class="header" href="#srclibrs-14" id="srclibrs-14"><code>src/lib.rs</code></a></h2>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
use std::cell::RefCell;
use std::rc::Rc;
use wasm_bindgen::prelude::*;
use wasm_bindgen::JsCast;
fn window() -&gt; web_sys::Window {
web_sys::window().expect(&quot;no global `window` exists&quot;)
}
fn request_animation_frame(f: &amp;Closure&lt;dyn FnMut()&gt;) {
window()
.request_animation_frame(f.as_ref().unchecked_ref())
.expect(&quot;should register `requestAnimationFrame` OK&quot;);
}
fn document() -&gt; web_sys::Document {
window()
.document()
.expect(&quot;should have a document on window&quot;)
}
fn body() -&gt; web_sys::HtmlElement {
document().body().expect(&quot;document should have a body&quot;)
}
// This function is automatically invoked after the wasm module is instantiated.
#[wasm_bindgen(start)]
pub fn run() -&gt; Result&lt;(), JsValue&gt; {
// Here we want to call `requestAnimationFrame` in a loop, but only a fixed
// number of times. After it's done we want all our resources cleaned up. To
// achieve this we're using an `Rc`. The `Rc` will eventually store the
// closure we want to execute on each frame, but to start out it contains
// `None`.
//
// After the `Rc` is made we'll actually create the closure, and the closure
// will reference one of the `Rc` instances. The other `Rc` reference is
// used to store the closure, request the first frame, and then is dropped
// by this function.
//
// Inside the closure we've got a persistent `Rc` reference, which we use
// for all future iterations of the loop
let f = Rc::new(RefCell::new(None));
let g = f.clone();
let mut i = 0;
*g.borrow_mut() = Some(Closure::wrap(Box::new(move || {
if i &gt; 300 {
body().set_text_content(Some(&quot;All done!&quot;));
// Drop our handle to this closure so that it will get cleaned
// up once we return.
let _ = f.borrow_mut().take();
return;
}
// Set the body's text content to how many times this
// requestAnimationFrame callback has fired.
i += 1;
let text = format!(&quot;requestAnimationFrame has been called {} times.&quot;, i);
body().set_text_content(Some(&amp;text));
// Schedule ourself for another requestAnimationFrame callback.
request_animation_frame(f.borrow().as_ref().unwrap());
}) as Box&lt;dyn FnMut()&gt;));
request_animation_frame(g.borrow().as_ref().unwrap());
Ok(())
}
#}</code></pre></pre>
<h1><a class="header" href="#paint-example" id="paint-example">Paint Example</a></h1>
<p><a href="https://github.com/rustwasm/wasm-bindgen/tree/master/examples/paint">View full source code</a> or <a href="https://rustwasm.github.io/wasm-bindgen/exbuild/paint/">view the compiled example online</a></p>
<p>A simple painting program.</p>
<h2><a class="header" href="#cargotoml-9" id="cargotoml-9"><code>Cargo.toml</code></a></h2>
<p>The <code>Cargo.toml</code> enables features necessary to work with the DOM, events and
2D canvas.</p>
<pre><code class="language-toml">[package]
name = &quot;wasm-bindgen-paint&quot;
version = &quot;0.1.0&quot;
authors = [&quot;The wasm-bindgen Developers&quot;]
edition = &quot;2018&quot;
[lib]
crate-type = [&quot;cdylib&quot;]
[dependencies]
js-sys = &quot;0.3.40&quot;
wasm-bindgen = &quot;0.2.63&quot;
[dependencies.web-sys]
version = &quot;0.3.4&quot;
features = [
'CanvasRenderingContext2d',
'CssStyleDeclaration',
'Document',
'Element',
'EventTarget',
'HtmlCanvasElement',
'HtmlElement',
'MouseEvent',
'Node',
'Window',
]
</code></pre>
<h2><a class="header" href="#srclibrs-15" id="srclibrs-15"><code>src/lib.rs</code></a></h2>
<p>Creates the <code>&lt;canvas&gt;</code> element, applies a CSS style to it, adds it to the document,
get a 2D rendering context and adds listeners for mouse events.</p>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
use std::cell::Cell;
use std::rc::Rc;
use wasm_bindgen::prelude::*;
use wasm_bindgen::JsCast;
#[wasm_bindgen(start)]
pub fn start() -&gt; Result&lt;(), JsValue&gt; {
let document = web_sys::window().unwrap().document().unwrap();
let canvas = document
.create_element(&quot;canvas&quot;)?
.dyn_into::&lt;web_sys::HtmlCanvasElement&gt;()?;
document.body().unwrap().append_child(&amp;canvas)?;
canvas.set_width(640);
canvas.set_height(480);
canvas.style().set_property(&quot;border&quot;, &quot;solid&quot;)?;
let context = canvas
.get_context(&quot;2d&quot;)?
.unwrap()
.dyn_into::&lt;web_sys::CanvasRenderingContext2d&gt;()?;
let context = Rc::new(context);
let pressed = Rc::new(Cell::new(false));
{
let context = context.clone();
let pressed = pressed.clone();
let closure = Closure::wrap(Box::new(move |event: web_sys::MouseEvent| {
context.begin_path();
context.move_to(event.offset_x() as f64, event.offset_y() as f64);
pressed.set(true);
}) as Box&lt;dyn FnMut(_)&gt;);
canvas.add_event_listener_with_callback(&quot;mousedown&quot;, closure.as_ref().unchecked_ref())?;
closure.forget();
}
{
let context = context.clone();
let pressed = pressed.clone();
let closure = Closure::wrap(Box::new(move |event: web_sys::MouseEvent| {
if pressed.get() {
context.line_to(event.offset_x() as f64, event.offset_y() as f64);
context.stroke();
context.begin_path();
context.move_to(event.offset_x() as f64, event.offset_y() as f64);
}
}) as Box&lt;dyn FnMut(_)&gt;);
canvas.add_event_listener_with_callback(&quot;mousemove&quot;, closure.as_ref().unchecked_ref())?;
closure.forget();
}
{
let context = context.clone();
let pressed = pressed.clone();
let closure = Closure::wrap(Box::new(move |event: web_sys::MouseEvent| {
pressed.set(false);
context.line_to(event.offset_x() as f64, event.offset_y() as f64);
context.stroke();
}) as Box&lt;dyn FnMut(_)&gt;);
canvas.add_event_listener_with_callback(&quot;mouseup&quot;, closure.as_ref().unchecked_ref())?;
closure.forget();
}
Ok(())
}
#}</code></pre></pre>
<h1><a class="header" href="#parallel-raytracing" id="parallel-raytracing">Parallel Raytracing</a></h1>
<p><a href="https://github.com/rustwasm/wasm-bindgen/tree/master/examples/raytrace-parallel">View full source code</a> or <a href="https://rustwasm.github.io/wasm-bindgen/exbuild/raytrace-parallel/">view the compiled example online</a></p>
<p><strong>This is an unstable and experimental example</strong> of using threads with
WebAssembly and Rust, culminating in a parallel raytracer demo. The browser requirements are:</p>
<ul>
<li>Firefox Nightly
<ul>
<li><code>SharedArrayBuffer</code> is enabled in <code>about:config</code> in Firefox</li>
</ul>
</li>
<li>Google Chrome
<ul>
<li>No flags required on recent versions of Chrome</li>
</ul>
</li>
<li>other browsers haven't implemented the proposed WebAssembly features yet.</li>
</ul>
<p>Locally to build this demo you'll need <code>xargo</code> and the <code>rust-src</code> rustup
component, and afterwards <code>./build.sh</code> like other examples should build the
example.</p>
<p>Again, to reiterate, this is all experimental and we're working through various
issues as we're working on this. If you're curious to see how this works it's
best to explore via the source code right now! More info will be available here
once WebAssembly threads are closer to stabilization.</p>
<h1><a class="header" href="#todo-mvc-using-wasm-bingen-and-web-sys" id="todo-mvc-using-wasm-bingen-and-web-sys">TODO MVC using wasm-bingen and web-sys</a></h1>
<p><a href="https://github.com/rustwasm/wasm-bindgen/tree/master/examples/todomvc">View full source code</a> or <a href="https://rustwasm.github.io/wasm-bindgen/exbuild/todomvc/">view the compiled example online</a></p>
<p><a href="https://github.com/rustwasm/wasm-bindgen">wasm-bindgen</a> and <a href="https://rustwasm.github.io/wasm-bindgen/api/web_sys/">web-sys</a> coded <a href="http://todomvc.com/">TODO MVC</a></p>
<p>The code was rewritten from the <a href="http://todomvc.com/examples/vanilla-es6/">ES6 version</a>.</p>
<p>The core differences are:</p>
<ul>
<li>Having an <a href="https://github.com/rustwasm/wasm-bindgen/tree/master/examples/todomvc/src/element.rs">Element wrapper</a> that takes care of dyn and into refs in web-sys,</li>
<li>A <a href="https://github.com/rustwasm/wasm-bindgen/tree/master/examples/todomvc/src/scheduler.rs">Scheduler</a> that allows Controller and View to communicate to each other by emulating something similar to the JS event loop.</li>
</ul>
<h2><a class="header" href="#size" id="size">Size</a></h2>
<p>The size of the project hasn't undergone much work to make it optimised yet.</p>
<ul>
<li>~96kb release build</li>
<li>~76kb optimised with binaryen</li>
<li>~28kb brotli compressed</li>
</ul>
<h1><a class="header" href="#reference" id="reference">Reference</a></h1>
<p>This section contains reference material for using <code>wasm-bindgen</code>. It is not
intended to be read start to finish. Instead, it aims to quickly answer
questions like:</p>
<ul>
<li>
<p>Is type X supported as a parameter in a Rust function exported to JavaScript?</p>
</li>
<li>
<p>What was that CLI flag to disable ECMAScript modules output, and instead
attach the JavaScript bindings directly to <code>window</code>?</p>
</li>
</ul>
<h1><a class="header" href="#deploying-rust-and-webassembly" id="deploying-rust-and-webassembly">Deploying Rust and WebAssembly</a></h1>
<p>At this point in time deploying Rust and WebAssembly to the web or other
locations unfortunately isn't a trivial task to do. This page hopes to serve
as documentation for the various known options, and as always PRs are welcome
to update this if it's out of date!</p>
<p>The methods of deployment and integration here are primarily tied to the
<code>--target</code> flag. Note that the <code>--target</code> flag of <code>wasm-pack</code> and <code>wasm-bindgen</code>
should behave the same way in this respect. The values possible here are:</p>
<table><thead><tr><th>Value</th><th>Summary</th></tr></thead><tbody>
<tr><td><a href="reference/#bundlers"><code>bundler</code></a></td><td>Suitable for loading in bundlers like Webpack</td></tr>
<tr><td><a href="reference/#without-a-bundler"><code>web</code></a></td><td>Directly loadable in a web browser</td></tr>
<tr><td><a href="reference/#nodejs"><code>nodejs</code></a></td><td>Loadable via <code>require</code> as a Node.js module</td></tr>
<tr><td><a href="reference/#Deno"><code>deno</code></a></td><td>Loadable using imports from Deno modules</td></tr>
<tr><td><a href="reference/#without-a-bundler"><code>no-modules</code></a></td><td>Like <code>web</code>, but older and doesn't use ES modules</td></tr>
</tbody></table>
<h2><a class="header" href="#bundlers" id="bundlers">Bundlers</a></h2>
<p><strong><code>--target bundler</code></strong></p>
<p>The default output of <code>wasm-bindgen</code>, or the <code>bundler</code> target, assumes a model
where the wasm module itself is natively an ES module. This model, however, is not
natively implemented in any JS implementation at this time. As a result, to
consume the default output of <code>wasm-bindgen</code> you will need a bundler of some
form.</p>
<blockquote>
<p><strong>Note</strong>: the choice of this default output was done to reflect the trends of
the JS ecosystem. While tools other than bundlers don't support wasm files as
native ES modules today they're all very much likely to in the future!</p>
</blockquote>
<p>Currently the only known bundler known to be fully compatible with
<code>wasm-bindgen</code> is <a href="https://webpack.js.org/">webpack</a>. Most <a href="reference/../examples/index.html">examples</a> use webpack, and you can check out
the <a href="reference/../examples/hello-world.html">hello world example online</a> to see the details of webpack configuration
necessary.</p>
<h2><a class="header" href="#without-a-bundler-1" id="without-a-bundler-1">Without a Bundler</a></h2>
<p><strong><code>--target web</code> or <code>--target no-modules</code></strong></p>
<p>If you're not using a bundler but you're still running code in a web browser,
<code>wasm-bindgen</code> still supports this! For this use case you'll want to use the
<code>--target web</code> flag. You can check out a <a href="reference/../examples/without-a-bundler.html">full example</a> in the
documentation, but the highlights of this output are:</p>
<ul>
<li>When compiling you'll pass <code>--target web</code> to <code>wasm-pack</code> (or <code>wasm-bindgen</code>
directly).</li>
<li>The output can natively be included on a web page, and doesn't require any
further postprocessing. The output is included as an ES module.</li>
<li>The <code>--target web</code> mode is not able to use NPM dependencies.</li>
<li>You'll want to review the <a href="reference/browser-support.html">browser requirements</a> for <code>wasm-bindgen</code> because
no polyfills will be available.</li>
</ul>
<p>The CLI also supports an output mode called <code>--target no-modules</code> which is
similar to the <code>web</code> target in that it requires manual initialization of the
wasm and is intended to be included in web pages without any further
postprocessing. See the <a href="reference/../examples/without-a-bundler.html">without a bundler example</a> for some more
information about <code>--target no-modules</code>.</p>
<h2><a class="header" href="#nodejs" id="nodejs">Node.js</a></h2>
<p><strong><code>--target nodejs</code></strong></p>
<p>If you're deploying WebAssembly into Node.js (perhaps as an alternative to a
native module), then you'll want to pass the <code>--target nodejs</code> flag to
<code>wasm-pack</code> or <code>wasm-bindgen</code>.</p>
<p>Like the &quot;without a bundler&quot; strategy, this method of deployment does not
require any further postprocessing. The generated JS shims can be <code>require</code>'d
just like any other Node module (even the <code>*_bg</code> wasm file can be <code>require</code>'d
as it has a JS shim generated as well).</p>
<p>Note that this method requires a version of Node.js with WebAssembly support,
which is currently Node 8 and above.</p>
<h2><a class="header" href="#deno" id="deno">Deno</a></h2>
<p><strong><code>--target deno</code></strong></p>
<p>To deploy WebAssembly to Deno, use the <code>--target deno</code> flag.
To then import your module inside deno, use</p>
<pre><code class="language-ts">// @deno-types=&quot;./out/crate_name.d.ts&quot;
import { yourFunction } from &quot;./out/crate_name.js&quot;;
</code></pre>
<h2><a class="header" href="#npm" id="npm">NPM</a></h2>
<p>If you'd like to deploy compiled WebAssembly to NPM, then the tool for the job
is <a href="https://rustwasm.github.io/docs/wasm-pack/"><code>wasm-pack</code></a>. More information on this coming soon!</p>
<h1><a class="header" href="#js-snippets" id="js-snippets">JS Snippets</a></h1>
<p>Often when developing a crate you want to run on the web you'll want to include
some JS code here and there. While <a href="https://docs.rs/js-sys"><code>js-sys</code></a> and
<a href="https://docs.rs/web-sys"><code>web-sys</code></a> cover many needs they don't cover
everything, so <code>wasm-bindgen</code> supports the ability to write JS code next to your
Rust code and have it included in the final output artifact.</p>
<p>To include a local JS file, you'll use the <code>#[wasm_bindgen(module)]</code> macro:</p>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
#[wasm_bindgen(module = &quot;/js/foo.js&quot;)]
extern &quot;C&quot; {
fn add(a: u32, b: u32) -&gt; u32;
}
#}</code></pre></pre>
<p>This declaration indicates that all the functions contained in the <code>extern</code>
block are imported from the file <code>/js/foo.js</code>, where the root is relative to the
crate root (where <code>Cargo.toml</code> is located).</p>
<p>The <code>/js/foo.js</code> file will make its way to the final output when <code>wasm-bindgen</code>
executes, so you can use the <code>module</code> annotation in a library without having to
worry users of your library!</p>
<p>The JS file itself must be written with ES module syntax:</p>
<pre><code class="language-js">export function add(a, b) {
return a + b;
}
</code></pre>
<p>A full design of this feature can be found in <a href="https://github.com/rustwasm/rfcs/pull/6">RFC 6</a> as well if you're
interested!</p>
<h3><a class="header" href="#using-inline_js" id="using-inline_js">Using <code>inline_js</code></a></h3>
<p>In addition to <code>module = &quot;...&quot;</code> if you're a macro author you also have the
ability to use the <code>inline_js</code> attribute:</p>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
#[wasm_bindgen(inline_js = &quot;export function add(a, b) { return a + b; }&quot;)]
extern &quot;C&quot; {
fn add(a: u32, b: u32) -&gt; u32;
}
#}</code></pre></pre>
<p>Using <code>inline_js</code> indicates that the JS module is specified inline in the
attribute itself, and no files are loaded from the filesystem. They have the
same limitations and caveats as when using <code>module</code>, but can sometimes be easier
to generate for macros themselves. It's not recommended for hand-written code to
make use of <code>inline_js</code> but instead to leverage <code>module</code> where possible.</p>
<h3><a class="header" href="#caveats" id="caveats">Caveats</a></h3>
<p>While quite useful local JS snippets currently suffer from a few caveats which
are important to be aware of. Many of these are temporary though!</p>
<ul>
<li>
<p>Currently <code>import</code> statements are not supported in the JS file. This is a
restriction we may lift in the future once we settle on a good way to support
this. For now, though, js snippets must be standalone modules and can't import
from anything else.</p>
</li>
<li>
<p>Only <code>--target web</code> and the default bundler output mode are supported. To
support <code>--target nodejs</code> we'd need to translate ES module syntax to CommonJS
(this is
planned to be done, just hasn't been done yet). Additionally to support
<code>--target no-modules</code> we'd have to similarly translate from ES modules to
something else.</p>
</li>
<li>
<p>Paths in <code>module = &quot;...&quot;</code> must currently start with <code>/</code>, or be rooted at the
crate root. It is intended to eventually support relative paths like <code>./</code> and
<code>../</code>, but it's currently believed that this requires more support in
the Rust <code>proc_macro</code> crate.</p>
</li>
</ul>
<p>As above, more detail about caveats can be found in <a href="https://github.com/rustwasm/rfcs/pull/6">RFC 6</a>.</p>
<h1><a class="header" href="#passing-rust-closures-to-imported-javascript-functions" id="passing-rust-closures-to-imported-javascript-functions">Passing Rust Closures to Imported JavaScript Functions</a></h1>
<p>The <code>#[wasm_bindgen]</code> attribute supports Rust closures being passed to
JavaScript in two variants:</p>
<ol>
<li>
<p>Stack-lifetime closures that should not be invoked by JavaScript again after
the imported JavaScript function that the closure was passed to returns.</p>
</li>
<li>
<p>Heap-allocated closures that can be invoked any number of times, but must be
explicitly deallocated when finished.</p>
</li>
</ol>
<h2><a class="header" href="#stack-lifetime-closures" id="stack-lifetime-closures">Stack-Lifetime Closures</a></h2>
<p>Closures with a stack lifetime are passed to JavaScript as either <code>&amp;Fn</code> or <code>&amp;mut FnMut</code> trait objects:</p>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
// Import JS functions that take closures
#[wasm_bindgen]
extern &quot;C&quot; {
fn takes_immutable_closure(f: &amp;Fn());
fn takes_mutable_closure(f: &amp;mut FnMut());
}
// Usage
takes_immutable_closure(&amp;|| {
// ...
});
let mut times_called = 0;
takes_mutable_closure(&amp;mut || {
times_called += 1;
});
#}</code></pre></pre>
<p><strong>Once these imported functions return, the closures that were given to them
will become invalidated, and any future attempts to call those closures from
JavaScript will raise an exception.</strong></p>
<p>Closures also support arguments and return values like exports do, for example:</p>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
#[wasm_bindgen]
extern &quot;C&quot; {
fn takes_closure_that_takes_int_and_returns_string(x: &amp;Fn(u32) -&gt; String);
}
takes_closure_that_takes_int_and_returns_string(&amp;|x: u32| -&gt; String {
format!(&quot;x is {}&quot;, x)
});
#}</code></pre></pre>
<h2><a class="header" href="#heap-allocated-closures" id="heap-allocated-closures">Heap-Allocated Closures</a></h2>
<p>Sometimes the discipline of stack-lifetime closures is not desired. For example,
you'd like to schedule a closure to be run on the next turn of the event loop in
JavaScript through <code>setTimeout</code>. For this, you want the imported function to
return but the JavaScript closure still needs to be valid!</p>
<p>For this scenario, you need the <code>Closure</code> type, which is defined in the
<code>wasm_bindgen</code> crate, exported in <code>wasm_bindgen::prelude</code>, and represents a
&quot;long lived&quot; closure.
The <code>Closure</code> type is currently behind a feature which needs to be enabled:</p>
<pre><code class="language-toml">[dependencies]
wasm-bindgen = {version = &quot;^0.2&quot;, features = [&quot;nightly&quot;]}
</code></pre>
<p>The validity of the JavaScript closure is tied to the lifetime of the <code>Closure</code>
in Rust. <strong>Once a <code>Closure</code> is dropped, it will deallocate its internal memory
and invalidate the corresponding JavaScript function so that any further
attempts to invoke it raise an exception.</strong></p>
<p>Like stack closures a <code>Closure</code> supports both <code>Fn</code> and <code>FnMut</code> closures, as well
as arguments and returns.</p>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
#[wasm_bindgen]
extern &quot;C&quot; {
fn setInterval(closure: &amp;Closure&lt;FnMut()&gt;, millis: u32) -&gt; f64;
fn cancelInterval(token: f64);
#[wasm_bindgen(js_namespace = console)]
fn log(s: &amp;str);
}
#[wasm_bindgen]
pub struct Interval {
closure: Closure&lt;FnMut()&gt;,
token: f64,
}
impl Interval {
pub fn new&lt;F: 'static&gt;(millis: u32, f: F) -&gt; Interval
where
F: FnMut()
{
// Construct a new closure.
let closure = Closure::new(f);
// Pass the closuer to JS, to run every n milliseconds.
let token = setInterval(&amp;closure, millis);
Interval { closure, token }
}
}
// When the Interval is destroyed, cancel its `setInterval` timer.
impl Drop for Interval {
fn drop(&amp;mut self) {
cancelInterval(self.token);
}
}
// Keep logging &quot;hello&quot; every second until the resulting `Interval` is dropped.
#[wasm_bindgen]
pub fn hello() -&gt; Interval {
Interval::new(1_000, || log(&quot;hello&quot;))
}
#}</code></pre></pre>
<h1><a class="header" href="#receiving-javascript-closures-in-exported-rust-functions" id="receiving-javascript-closures-in-exported-rust-functions">Receiving JavaScript Closures in Exported Rust Functions</a></h1>
<p>You can use the <code>js-sys</code> crate to access JavaScript's <code>Function</code> type, and
invoke that function via <code>Function.prototype.apply</code> and
<code>Function.prototype.call</code>.</p>
<p>For example, we can wrap a <code>Vec&lt;u32&gt;</code> in a new type, export it to JavaScript,
and invoke a JavaScript closure on each member of the <code>Vec</code>:</p>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
extern crate js_sys;
extern crate wasm_bindgen;
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
pub struct VecU32 {
xs: Vec&lt;u32&gt;,
}
#[wasm_bindgen]
impl VecU32 {
pub fn each(&amp;self, f: &amp;js_sys::Function) {
let this = JsValue::NULL;
for x in &amp;self.xs {
let x = JsValue::from(x);
let _ = f.call1(&amp;this, &amp;x);
}
}
}
#}</code></pre></pre>
<p>Since Rust has no function overloading, the <code>call#</code> method also requires a
number representing the amount of arguments passed to the JavaScript closure.</p>
<h1><a class="header" href="#working-with-a-js-promise-and-a-rust-future" id="working-with-a-js-promise-and-a-rust-future">Working with a JS <code>Promise</code> and a Rust <code>Future</code></a></h1>
<p>Many APIs on the web work with a <code>Promise</code>, such as an <code>async</code> function in JS.
Naturally you'll probably want to interoperate with them from Rust! To do that
you can use the <code>wasm-bindgen-futures</code> crate as well as Rust <code>async</code>
functions.</p>
<p>The first thing you might encounter is the need for working with a <code>Promise</code>.
For this you'll want to use <a href="https://docs.rs/js-sys/*/js_sys/struct.Promise.html"><code>js_sys::Promise</code></a>. Once you've got one of those
values you can convert that value to <code>wasm_bindgen_futures::JsFuture</code>. This type
implements the <code>std::future::Future</code> trait which allows naturally using it in an
<code>async</code> function. For example:</p>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
async fn get_from_js() -&gt; Result&lt;JsValue, JsValue&gt; {
let promise = js_sys::Promise::resolve(&amp;42.into());
let result = wasm_bindgen_futures::JsFuture::from(promise).await?;
Ok(result)
}
#}</code></pre></pre>
<p>Here we can see how converting a <code>Promise</code> to Rust creates a <code>impl Future&lt;Output = Result&lt;JsValue, JsValue&gt;&gt;</code>. This corresponds to <code>then</code> and <code>catch</code> in JS where
a successful promise becomes <code>Ok</code> and an erroneous promise becomes <code>Err</code>.</p>
<p>Next up you'll probably want to export a Rust function to JS that returns a
promise. To do this you can use an <code>async</code> function and <code>#[wasm_bindgen]</code>:</p>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
#[wasm_bindgen]
pub async fn foo() {
// ...
}
#}</code></pre></pre>
<p>When invoked from JS the <code>foo</code> function here will return a <code>Promise</code>, so you can
import this as:</p>
<pre><code class="language-js">import { foo } from &quot;my-module&quot;;
async function shim() {
const result = await foo();
// ...
}
</code></pre>
<h2><a class="header" href="#return-values-of-async-fn" id="return-values-of-async-fn">Return values of <code>async fn</code></a></h2>
<p>When using an <code>async fn</code> in Rust and exporting it to JS there's some
restrictions on the return type. The return value of an exported Rust function
will eventually become <code>Result&lt;JsValue, JsValue&gt;</code> where <code>Ok</code> turns into a
successfully resolved promise and <code>Err</code> is equivalent to throwing an exception.</p>
<p>The following types are supported as return types from an <code>async fn</code>:</p>
<ul>
<li><code>()</code> - turns into a successful <code>undefined</code> in JS</li>
<li><code>T: Into&lt;JsValue&gt;</code> - turns into a successful JS value</li>
<li><code>Result&lt;(), E: Into&lt;JsValue&gt;&gt;</code> - if <code>Ok(())</code> turns into a successful
<code>undefined</code> and otherwise turns into a failed promise with <code>E</code> converted to a
JS value</li>
<li><code>Result&lt;T: Into&lt;JsValue&gt;, E: Into&lt;JsValue&gt;&gt;</code> - like the previous case except
both data payloads are converted into a <code>JsValue</code>.</li>
</ul>
<p>Note that many types implement being converted into a <code>JsValue</code>, such as all
imported types via <code>#[wasm_bindgen]</code> (aka those in <code>js-sys</code> or <code>web-sys</code>),
primitives like <code>u32</code>, and all exported <code>#[wasm_bindgen]</code> types. In general,
you should be able to write code without having too many explicit conversions,
and the macro should take care of the rest!</p>
<h2><a class="header" href="#using-wasm-bindgen-futures" id="using-wasm-bindgen-futures">Using <code>wasm-bindgen-futures</code></a></h2>
<p>The <code>wasm-bindgen-futures</code> crate bridges the gap between JavaScript <code>Promise</code>s
and Rust <code>Future</code>s. Its <code>JsFuture</code> type provides conversion from a JavaScript
<code>Promise</code> into a Rust <code>Future</code>, and its <code>future_to_promise</code> function converts a
Rust <code>Future</code> into a JavaScript <code>Promise</code> and schedules it to be driven to
completion.</p>
<p>Learn more:</p>
<ul>
<li><a href="https://crates.io/crates/wasm-bindgen-futures"><code>wasm_bindgen_futures</code> on crates.io</a></li>
<li><a href="https://rustwasm.github.io/wasm-bindgen/api/wasm_bindgen_futures/"><code>wasm-bindgen-futures</code> API documentation and example usage</a></li>
</ul>
<h2><a class="header" href="#compatibility-with-versions-of-future" id="compatibility-with-versions-of-future">Compatibility with versions of <code>Future</code></a></h2>
<p>The current crate on crates.io, <code>wasm-bindgen-futures 0.4.*</code>, supports
<code>std::future::Future</code> and <code>async</code>/<code>await</code> in Rust. This typically requires Rust
1.39.0+ (as of this writing on 2019-09-05 it's the nightly channel of Rust).</p>
<p>If you're using the <code>Future</code> trait from the <code>futures</code> <code>0.1.*</code> crate then you'll
want to use the <code>0.3.*</code> track of <code>wasm-bindgen-futures</code> on crates.io.</p>
<h1><a class="header" href="#iterating-over-javascript-values" id="iterating-over-javascript-values">Iterating over JavaScript Values</a></h1>
<h2><a class="header" href="#methods-that-return-js_sysiterator" id="methods-that-return-js_sysiterator">Methods That Return <code>js_sys::Iterator</code></a></h2>
<p>Some JavaScript collections have methods for iterating over their values or
keys:</p>
<ul>
<li><a href="https://rustwasm.github.io/wasm-bindgen/api/js_sys/struct.Map.html#method.values"><code>Map::values</code></a></li>
<li><a href="https://rustwasm.github.io/wasm-bindgen/api/js_sys/struct.Set.html#method.keys"><code>Set::keys</code></a></li>
<li>etc...</li>
</ul>
<p>These methods return
<a href="https://rustwasm.github.io/wasm-bindgen/api/js_sys/struct.Iterator.html"><code>js_sys::Iterator</code></a>,
which is the Rust representation of a JavaScript object that has a <code>next</code> method
that either returns the next item in the iteration, notes that iteration has
completed, or throws an error. That is, <code>js_sys::Iterator</code> represents an object
that implements <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols">the duck-typed JavaScript iteration
protocol</a>.</p>
<p><code>js_sys::Iterator</code> can be converted into a Rust iterator either by reference
(into
<a href="https://rustwasm.github.io/wasm-bindgen/api/js_sys/struct.Iter.html"><code>js_sys::Iter&lt;'a&gt;</code></a>)
or by value (into
<a href="https://rustwasm.github.io/wasm-bindgen/api/js_sys/struct.IntoIter.html"><code>js_sys::IntoIter</code></a>). The
Rust iterator will yield items of type <code>Result&lt;JsValue&gt;</code>. If it yields an
<code>Ok(...)</code>, then the JS iterator protocol returned an element. If it yields an
<code>Err(...)</code>, then the JS iterator protocol threw an exception.</p>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
extern crate js_sys;
extern crate wasm_bindgen;
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
pub fn count_strings_in_set(set: &amp;js_sys::Set) -&gt; u32 {
let mut count = 0;
// Call `keys` to get an iterator over the set's elements. Because this is
// in a `for ... in ...` loop, Rust will automatically call its
// `IntoIterator` trait implementation to convert it into a Rust iterator.
for x in set.keys() {
// We know the built-in iterator for set elements won't throw
// exceptions, so just unwrap the element. If this was an untrusted
// iterator, we might want to explicitly handle the case where it throws
// an exception instead of returning a `{ value, done }` object.
let x = x.unwrap();
// If `x` is a string, increment our count of strings in the set!
if x.is_string() {
count += 1;
}
}
count
}
#}</code></pre></pre>
<h2><a class="header" href="#iterating-over-uanyu-javascript-object-that-implements-the-iterator-protocol" id="iterating-over-uanyu-javascript-object-that-implements-the-iterator-protocol">Iterating Over <u>Any</u> JavaScript Object that Implements the Iterator Protocol</a></h2>
<p>You could manually test for whether an object implements JS's duck-typed
iterator protocol, and if so, convert it into a <code>js_sys::Iterator</code> that you can
finally iterate over. You don't need to do this by-hand, however, since we
bundled this up as <a href="https://rustwasm.github.io/wasm-bindgen/api/js_sys/fn.try_iter.html">the <code>js_sys::try_iter</code>
function!</a></p>
<p>For example, we can write a function that collects the numbers from any JS
iterable and returns them as an <code>Array</code>:</p>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
extern crate js_sys;
extern crate wasm_bindgen;
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
pub fn collect_numbers(some_iterable: &amp;JsValue) -&gt; Result&lt;js_sys::Array, JsValue&gt; {
let nums = js_sys::Array::new();
let iterator = js_sys::try_iter(some_iterable)?.ok_or_else(|| {
&quot;need to pass iterable JS values!&quot;
})?;
for x in iterator {
// If the iterator's `next` method throws an error, propagate it
// up to the caller.
let x = x?;
// If `x` is a number, add it to our array of numbers!
if x.as_f64().is_some() {
nums.push(&amp;x);
}
}
Ok(nums)
}
#}</code></pre></pre>
<h1><a class="header" href="#serializing-and-deserializing-arbitrary-data-into-and-from-jsvalue-with-serde" id="serializing-and-deserializing-arbitrary-data-into-and-from-jsvalue-with-serde">Serializing and Deserializing Arbitrary Data Into and From <code>JsValue</code> with Serde</a></h1>
<p>It's possible to pass arbirtrary data from Rust to JavaScript by serializing it
to JSON with <a href="https://github.com/serde-rs/serde">Serde</a>. <code>wasm-bindgen</code> includes
the <code>JsValue</code> type, which streamlines serializing and deserializing.</p>
<h2><a class="header" href="#enable-the-serde-serialize-feature" id="enable-the-serde-serialize-feature">Enable the <code>&quot;serde-serialize&quot;</code> Feature</a></h2>
<p>To enable the <code>&quot;serde-serialize&quot;</code> feature, do two things in <code>Cargo.toml</code>:</p>
<ol>
<li>Add the <code>serde</code> and <code>serde_derive</code> crates to <code>[dependencies]</code>.</li>
<li>Add <code>features = [&quot;serde-serialize&quot;]</code> to the existing <code>wasm-bindgen</code>
dependency.</li>
</ol>
<pre><code class="language-toml">[dependencies]
serde = &quot;^1.0.59&quot;
serde_derive = &quot;^1.0.59&quot;
[dependencies.wasm-bindgen]
version = &quot;^0.2&quot;
features = [&quot;serde-serialize&quot;]
</code></pre>
<h2><a class="header" href="#import-serdes-custom-derive-macros" id="import-serdes-custom-derive-macros">Import Serde's Custom-Derive Macros</a></h2>
<p>In your top-level Rust file (e.g. <code>lib.rs</code> or <code>main.rs</code>), enable the <code>Serialize</code>
and <code>Deserialize</code> custom-derive macros:</p>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
#[macro_use]
extern crate serde_derive;
#}</code></pre></pre>
<h2><a class="header" href="#derive-the-serialize-and-deserialize-traits" id="derive-the-serialize-and-deserialize-traits">Derive the <code>Serialize</code> and <code>Deserialize</code> Traits</a></h2>
<p>Add <code>#[derive(Serialize, Deserialize)]</code> to your type. All of your type's
members must also be supported by Serde, i.e. their types must also implement
the <code>Serialize</code> and <code>Deserialize</code> traits.</p>
<p>For example, let's say we'd like to pass this <code>struct</code> to JavaScript; doing so
is not possible in <code>wasm-bindgen</code> normally due to the use of <code>HashMap</code>s, arrays,
and nested <code>Vec</code>s. None of those types are supported for sending across the wasm
ABI naively, but all of them implement Serde's <code>Serialize</code> and <code>Deserialize</code>.</p>
<p>Note that we do not need to use the <code>#[wasm_bindgen]</code> macro.</p>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
#[derive(Serialize)]
pub struct Example {
pub field1: HashMap&lt;u32, String&gt;,
pub field2: Vec&lt;Vec&lt;f32&gt;&gt;,
pub field3: [f32; 4],
}
#}</code></pre></pre>
<h2><a class="header" href="#send-it-to-javascript-with-jsvaluefrom_serde" id="send-it-to-javascript-with-jsvaluefrom_serde">Send it to JavaScript with <code>JsValue::from_serde</code></a></h2>
<p>Here's a function that will pass an <code>Example</code> to JavaScript by serializing it to
<code>JsValue</code>:</p>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
#[wasm_bindgen]
pub fn send_example_to_js() -&gt; JsValue {
let mut field1 = HashMap::new();
field1.insert(0, String::from(&quot;ex&quot;));
let example = Example {
field1,
field2: vec![vec![1., 2.], vec![3., 4.]],
field3: [1., 2., 3., 4.]
};
JsValue::from_serde(&amp;example).unwrap()
}
#}</code></pre></pre>
<h2><a class="header" href="#receive-it-from-javascript-with-jsvalueinto_serde" id="receive-it-from-javascript-with-jsvalueinto_serde">Receive it from JavaScript with <code>JsValue::into_serde</code></a></h2>
<p>Here's a function that will receive a <code>JsValue</code> parameter from JavaScript and
then deserialize an <code>Example</code> from it:</p>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
#[wasm_bindgen]
pub fn receive_example_from_js(val: &amp;JsValue) {
let example: Example = val.into_serde().unwrap();
...
}
#}</code></pre></pre>
<h2><a class="header" href="#javascript-usage" id="javascript-usage">JavaScript Usage</a></h2>
<p>In the <code>JsValue</code> that JavaScript gets, <code>field1</code> will be an <code>Object</code> (not a
JavaScript <code>Map</code>), <code>field2</code> will be a JavaScript <code>Array</code> whose members are
<code>Array</code>s of numbers, and <code>field3</code> will be an <code>Array</code> of numbers.</p>
<pre><code class="language-js">import { send_example_to_js, receive_example_from_js } from &quot;example&quot;;
// Get the example object from wasm.
let example = send_example_to_js();
// Add another &quot;Vec&quot; element to the end of the &quot;Vec&lt;Vec&lt;f32&gt;&gt;&quot;
example.field2.push([5,6]);
// Send the example object back to wasm.
receive_example_from_js(example);
</code></pre>
<h2><a class="header" href="#an-alternative-approach-serde-wasm-bindgen" id="an-alternative-approach-serde-wasm-bindgen">An Alternative Approach: <code>serde-wasm-bindgen</code></a></h2>
<p><a href="https://github.com/cloudflare/serde-wasm-bindgen">The <code>serde-wasm-bindgen</code>
crate</a> serializes and
deserializes Rust structures directly to <code>JsValue</code>s, without going through
temporary JSON stringification. This approach has both advantages and
disadvantages.</p>
<p>The primary advantage is smaller code size: going through JSON entrenches code
to stringify and parse floating point numbers, which is not a small amount of
code. It also supports more types than JSON does, such as <code>Map</code>, <code>Set</code>, and
array buffers.</p>
<p>There are two primary disadvantages. The first is that it is not always
compatible with the default JSON-based serialization. The second is that it
performs more calls back and forth between JS and Wasm, which has not been fully
optimized in all engines, meaning it can sometimes be a speed
regression. However, in other cases, it is a speed up over the JSON-based
stringification, so — as always — make sure to profile your own use
cases as necessary.</p>
<h1><a class="header" href="#accessing-properties-of-untyped-javascript-values" id="accessing-properties-of-untyped-javascript-values">Accessing Properties of Untyped JavaScript Values</a></h1>
<p>To read and write arbitrary properties from any untyped JavaScript value
regardless if it is an <code>instanceof</code> some JavaScript class or not, use <a href="https://docs.rs/js-sys/latest/js_sys/Reflect/index.html">the
<code>js_sys::Reflect</code> APIs</a>. These APIs are bindings to the
<a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Reflect">JavaScript builtin <code>Reflect</code> object</a> and its methods.</p>
<p>You might also benefit from <a href="reference/./working-with-duck-typed-interfaces.html">using duck-typed
interfaces</a> instead of working with
untyped values.</p>
<h2><a class="header" href="#reading-properties-with-js_sysreflectget" id="reading-properties-with-js_sysreflectget">Reading Properties with <code>js_sys::Reflect::get</code></a></h2>
<p><a href="https://docs.rs/js-sys/0.3.39/js_sys/Reflect/fn.get.html">API documentation for <code>js_sys::Reflect::get</code>.</a></p>
<p>A function that returns the value of a property.</p>
<h4><a class="header" href="#rust-usage" id="rust-usage">Rust Usage</a></h4>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
let value = js_sys::Reflect::get(&amp;target, &amp;property_key)?;
#}</code></pre></pre>
<h4><a class="header" href="#javascript-equivalent" id="javascript-equivalent">JavaScript Equivalent</a></h4>
<pre><code class="language-js">let value = target[property_key];
</code></pre>
<h2><a class="header" href="#writing-properties-with-js_sysreflectset" id="writing-properties-with-js_sysreflectset">Writing Properties with <code>js_sys::Reflect::set</code></a></h2>
<p><a href="https://docs.rs/js-sys/0.3.39/js_sys/Reflect/fn.set.html">API documentation for <code>js_sys::Reflect::set</code>.</a></p>
<p>A function that assigns a value to a property. Returns a boolean that is true if
the update was successful.</p>
<h4><a class="header" href="#rust-usage-1" id="rust-usage-1">Rust Usage</a></h4>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
js_sys::Reflect::set(&amp;target, &amp;property_key, &amp;value)?;
#}</code></pre></pre>
<h4><a class="header" href="#javascript-equivalent-1" id="javascript-equivalent-1">JavaScript Equivalent</a></h4>
<pre><code class="language-js">target[property_key] = value;
</code></pre>
<h2><a class="header" href="#determining-if-a-property-exists-with-js_sysreflecthas" id="determining-if-a-property-exists-with-js_sysreflecthas">Determining if a Property Exists with <code>js_sys::Reflect::has</code></a></h2>
<p><a href="https://docs.rs/js-sys/0.3.39/js_sys/Reflect/fn.has.html">API documentation for <code>js_sys::Reflect::has</code>.</a></p>
<p>The JavaScript <code>in</code> operator as function. Returns a boolean indicating whether
an own or inherited property exists on the target.</p>
<h4><a class="header" href="#rust-usage-2" id="rust-usage-2">Rust Usage</a></h4>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
if js_sys::Reflect::has(&amp;target, &amp;property_key)? {
// ...
} else {
// ...
}
#}</code></pre></pre>
<h4><a class="header" href="#javascript-equivalent-2" id="javascript-equivalent-2">JavaScript Equivalent</a></h4>
<pre><code class="language-js">if (property_key in target) {
// ...
} else {
// ...
}
</code></pre>
<h2><a class="header" href="#but-wait--theres-more" id="but-wait--theres-more">But wait — there's more!</a></h2>
<p>See <a href="https://docs.rs/js-sys/latest/js_sys/Reflect/index.html">the <code>js_sys::Reflect</code> API documentation</a> for the full
listing of JavaScript value reflection and introspection capabilities.</p>
<h1><a class="header" href="#working-with-duck-typed-interfaces" id="working-with-duck-typed-interfaces">Working with Duck-Typed Interfaces</a></h1>
<p>Liberal use of <a href="reference/./attributes/on-js-imports/structural.html">the <code>structural</code>
attribute</a> on imported methods,
getters, and setters allows you to define duck-typed interfaces. A duck-typed
interface is one where many different JavaScript objects that don't share the
same base class in their prototype chain and therefore are not <code>instanceof</code> the
same base can be used the same way.</p>
<h2><a class="header" href="#defining-a-duck-typed-interface-in-rust" id="defining-a-duck-typed-interface-in-rust">Defining a Duck-Typed Interface in Rust</a></h2>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
use wasm_bindgen::prelude::*;
/// Here is a duck-typed interface for any JavaScript object that has a `quack`
/// method.
///
/// Note that any attempts to check if an object is a `Quacks` with
/// `JsCast::is_instance_of` (i.e. the `instanceof` operator) will fail because
/// there is no JS class named `Quacks`.
#[wasm_bindgen]
extern &quot;C&quot; {
pub type Quacks;
#[wasm_bindgen(structural, method)]
pub fn quack(this: &amp;Quacks) -&gt; String;
}
/// Next, we can export a function that takes any object that quacks:
#[wasm_bindgen]
pub fn make_em_quack_to_this(duck: &amp;Quacks) {
let _s = duck.quack();
// ...
}
#}</code></pre></pre>
<h2><a class="header" href="#javascript-usage-1" id="javascript-usage-1">JavaScript Usage</a></h2>
<pre><code class="language-js">import { make_em_quack_to_this } from &quot;./rust_duck_typed_interfaces&quot;;
// All of these objects implement the `Quacks` interface!
const alex = {
quack: () =&gt; &quot;you're not wrong...&quot;
};
const ashley = {
quack: () =&gt; &quot;&lt;corgi.gif&gt;&quot;
};
const nick = {
quack: () =&gt; &quot;rappers I monkey-flip em with the funky rhythm I be kickin&quot;
};
// Get all our ducks in a row and call into wasm!
make_em_quack_to_this(alex);
make_em_quack_to_this(ashley);
make_em_quack_to_this(nick);
</code></pre>
<h1><a class="header" href="#the-wasm-bindgen-command-line-interface" id="the-wasm-bindgen-command-line-interface">The <code>wasm-bindgen</code> Command Line Interface</a></h1>
<p>The <code>wasm-bindgen</code> command line tool has a number of options available to it to
tweak the JavaScript that is generated. The most up-to-date set of flags can
always be listed via <code>wasm-bindgen --help</code>.</p>
<blockquote>
<p>Note: usually, one should use a <a href="https://github.com/rustwasm/wasm-pack"><code>wasm-pack</code>-based workflow</a> rather
than running the <code>wasm-bindgen</code> command line tool by hand.</p>
</blockquote>
<h2><a class="header" href="#installation" id="installation">Installation</a></h2>
<p>The recommend way to install the <code>wasm-bindgen</code> command line tool is with the
<code>wasm-pack</code> installer described
<a href="https://rustwasm.github.io/wasm-pack/installer/">here</a>. After installing
<code>wasm-pack</code>, you are ready to build project invoking <code>wasm-pack build</code>.
This command installs apropriate version of the <code>wasm-bindgen</code> command-line
tool. The version of <code>wasm-bindgen</code> installed by <code>wasm-pack</code> is not available
to be used directly via command line.</p>
<p>It is not recommended to install <code>wasm-bindgen-cli</code> as its version must match
<em>exactly</em> the version of <code>wasm-bindgen</code> that is specified in the project's
cargo.lock file. Using <code>wasm-pack</code> for building simplifies the build process
as <code>wasm-pack</code> ensures that the proper version of <code>wasm-bindgen</code> command-line
tool is used. That means that <code>wasm-pack</code> may install many different versions
of <code>wasm-bindgen</code>, but during the build <code>wasm-pack</code> will always make sure to
use the correct one.</p>
<p>Note: if, for any reason, you decide to use wasm-bindgen directly (this is
not recommended!) you will have to manually take care of using exactly the
same version of wasm-bindgen command-line tool (wasm-bindgen-cli) that
matches the version of wasm-bingden in cargo.lock.</p>
<h2><a class="header" href="#usage" id="usage">Usage</a></h2>
<pre><code>wasm-bindgen [options] ./target/wasm32-unknown-unknown/release/crate.wasm
</code></pre>
<h2><a class="header" href="#options" id="options">Options</a></h2>
<h3><a class="header" href="#--out-dir-dir" id="--out-dir-dir"><code>--out-dir DIR</code></a></h3>
<p>The target directory to emit the JavaScript bindings, TypeScript definitions,
processed <code>.wasm</code> binary, etc...</p>
<h3><a class="header" href="#--target" id="--target"><code>--target</code></a></h3>
<p>This flag indicates what flavor of output what <code>wasm-bindgen</code> should generate.
For example it could generate code to be loaded in a bundler like Webpack, a
native web page, or Node.js. For a full list of options to pass this flag, see
the section on <a href="reference/deployment.html">deployment</a></p>
<h3><a class="header" href="#--no-modules-global-var" id="--no-modules-global-var"><code>--no-modules-global VAR</code></a></h3>
<p>When <code>--target no-modules</code> is used this flag can indicate what the name of the
global to assign generated bindings to.</p>
<p>For more information about this see the section on <a href="reference/deployment.html">deployment</a></p>
<h3><a class="header" href="#--typescript" id="--typescript"><code>--typescript</code></a></h3>
<p>Output a TypeScript declaration file for the generated JavaScript bindings. This
is on by default.</p>
<h3><a class="header" href="#--no-typescript" id="--no-typescript"><code>--no-typescript</code></a></h3>
<p>By default, a <code>*.d.ts</code> TypeScript declaration file is generated for the
generated JavaScript bindings, but this flag will disable that.</p>
<h3><a class="header" href="#--omit-imports" id="--omit-imports"><code>--omit-imports</code></a></h3>
<p>When the <code>module</code> attribute is used with the <code>wasm-bindgen</code> macro, the code
generator will emit corresponding <code>import</code> or <code>require</code> statements in the header
section of the generated javascript. This flag causes those import statements to
be omitted. This is necessary for some use cases, such as generating javascript
which is intended to be used with Electron (with node integration disabled),
where the imports are instead handled through a separate preload script.</p>
<h3><a class="header" href="#--debug" id="--debug"><code>--debug</code></a></h3>
<p>Generates a bit more JS and wasm in &quot;debug mode&quot; to help catch programmer
errors, but this output isn't intended to be shipped to production.</p>
<h3><a class="header" href="#--no-demangle" id="--no-demangle"><code>--no-demangle</code></a></h3>
<p>When post-processing the <code>.wasm</code> binary, do not demangle Rust symbols in the
&quot;names&quot; custom section.</p>
<h3><a class="header" href="#--keep-debug" id="--keep-debug"><code>--keep-debug</code></a></h3>
<p>When post-processing the <code>.wasm</code> binary, do not strip DWARF debug info custom
sections.</p>
<h3><a class="header" href="#--browser" id="--browser"><code>--browser</code></a></h3>
<p>When generating bundler-compatible code (see the section on <a href="reference/deployment.html">deployment</a>) this
indicates that the bundled code is always intended to go into a browser so a few
checks for Node.js can be elided.</p>
<h1><a class="header" href="#optimizing-for-size-with-wasm-bindgen" id="optimizing-for-size-with-wasm-bindgen">Optimizing for Size with <code>wasm-bindgen</code></a></h1>
<p>The Rust and WebAssembly Working Group's <a href="https://rustwasm.github.io/book/game-of-life/introduction.html">Game of Life tutorial</a> has an
excellent section on <a href="https://rustwasm.github.io/book/game-of-life/code-size.html">shrinking wasm code size</a>, but there's a few
<code>wasm-bindgen</code>-specific items to mention as well!</p>
<p>First and foremost, <code>wasm-bindgen</code> is designed to be lightweight and a &quot;pay only
for what you use&quot; mentality. If you suspect that <code>wasm-bindgen</code> is bloating your
program that is a bug and we'd like to know about it! Please feel free to <a href="https://github.com/rustwasm/wasm-bindgen/issues/new">file
an issue</a>, even if it's a question!</p>
<h3><a class="header" href="#what-to-profile" id="what-to-profile">What to profile</a></h3>
<p>With <code>wasm-bindgen</code> there's a few different files to be measuring the size of.
The first of which is the output of the compiler itself, typically at
<code>target/wasm32-unknown-unknown/release/foo.wasm</code>. <strong>This file is not optimized
for size and you should not measure it.</strong> The output of the compiler when
linking with <code>wasm-bindgen</code> is by design larger than it needs to be, the
<code>wasm-bindgen</code> CLI tool will automatically strip all unneeded functionality out
of the binary.</p>
<p>This leaves us with two primary generated files to measure the size of:</p>
<ul>
<li>
<p><strong>Generated wasm</strong> - after running the <code>wasm-bindgen</code> CLI tool you'll get a
file in <code>--out-dir</code> that looks like <code>foo_bg.wasm</code>. This file is the final
fully-finished artifact from <code>wasm-bindgen</code>, and it reflects the size of the
app you'll be publishing. All the optimizations <a href="https://rustwasm.github.io/book/game-of-life/code-size.html">mentioned in the code size
tutorial</a> will help reduce the size of this binary, so feel free to go
crazy!</p>
</li>
<li>
<p><strong>Generated JS</strong> - the other file after running <code>wasm-bindgen</code> is a <code>foo.js</code>
file which is what's actually imported by other JS code. This file is already
generated to be as small as possible (not including unneeded functionality).
The JS, however, is not uglified or minified, but rather still human readable
and debuggable. It's expected that you'll run an uglifier or bundler of the JS
output to minimize it further in your application. If you spot a way we could
reduce the output JS size further (or make it more amenable to bundler
minification), please let us know!</p>
</li>
</ul>
<h3><a class="header" href="#example" id="example">Example</a></h3>
<p>As an example, the <code>wasm-bindgen</code> repository <a href="https://rustwasm.github.io/docs/wasm-bindgen/examples/add.html">contains an example</a>
about generating small wasm binaries and shows off how to generate a small wasm
file for adding two numbers.</p>
<h1><a class="header" href="#supported-rust-targets" id="supported-rust-targets">Supported Rust Targets</a></h1>
<blockquote>
<p><strong>Note</strong>: This section is about Rust target triples, not targets like node/web
workers/browsers. More information on that coming soon!</p>
</blockquote>
<p>The <code>wasm-bindgen</code> project is designed to target the <code>wasm32-unknown-unknown</code>
target in Rust. This target is a &quot;bare bones&quot; target for Rust which emits
WebAssembly as output. The standard library is largely inert as modules like
<code>std::fs</code> and <code>std::net</code> will simply return errors.</p>
<h2><a class="header" href="#non-wasm-targets" id="non-wasm-targets">Non-wasm targets</a></h2>
<p>Note that <code>wasm-bindgen</code> also aims to compile on all targets. This means that it
should be safe, if you like, to use <code>#[wasm_bindgen]</code> even when compiling for
Windows (for example). For example:</p>
<pre><pre class="playpen"><code class="language-rust">#[wasm_bindgen]
pub fn add(a: u32, b: u32) -&gt; u32 {
a + b
}
#[cfg(not(target_arch = &quot;wasm32&quot;))]
fn main() {
println!(&quot;1 + 2 = {}&quot;, add(1, 2));
}
</code></pre></pre>
<p>This program will compile and work on all platforms, not just
<code>wasm32-unknown-unknown</code>. Note that imported functions with <code>#[wasm_bindgen]</code>
will unconditionally panic on non-wasm targets. For example:</p>
<pre><pre class="playpen"><code class="language-rust">#[wasm_bindgen]
extern &quot;C&quot; {
#[wasm_bindgen(js_namespace = console)]
fn log(s: &amp;str);
}
fn main() {
log(&quot;hello!&quot;);
}
</code></pre></pre>
<p>This program will unconditionally panic on all platforms other than
<code>wasm32-unknown-unknown</code>.</p>
<p>For better compile times, however, you likely want to only use <code>#[wasm_bindgen]</code>
on the <code>wasm32-unknown-unknown</code> target. You can have a target-specific
dependency like so:</p>
<pre><code class="language-toml">[target.'cfg(target_arch = &quot;wasm32&quot;)'.dependencies]
wasm-bindgen = &quot;0.2&quot;
</code></pre>
<p>And in your code you can use:</p>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
#[cfg(target_arch = &quot;wasm32&quot;)]
#[wasm_bindgen]
pub fn only_on_the_wasm_target() {
// ...
}
#}</code></pre></pre>
<h2><a class="header" href="#other-web-targets" id="other-web-targets">Other Web Targets</a></h2>
<p>The <code>wasm-bindgen</code> target does not support the <code>wasm32-unknown-emscripten</code> nor
the <code>asmjs-unknown-emscripten</code> targets. There are currently no plans to support
these targets either. All annotations work like other platforms on the targets,
retaining exported functions and causing all imports to panic.</p>
<h1><a class="header" href="#supported-browsers" id="supported-browsers">Supported Browsers</a></h1>
<p>The output of <code>wasm-bindgen</code> includes a JS file, and as a result it's good to
know what browsers that file is expected to be used in! By default the output
uses ES modules which isn't implemented in all browsers today, but when using a
bundler (like Webpack) you should be able to produce output suitable for all
browsers.</p>
<p>Firefox, Chrome, Safari, and Edge browsers are all supported by
<code>wasm-bindgen</code>. If you find a problem in one of these browsers please <a href="https://github.com/rustwasm/wasm-bindgen/issues/new">report
it</a> as we'd like to fix the bug! If you find a bug in another browser we would
also like to be aware of it!</p>
<h2><a class="header" href="#caveats-1" id="caveats-1">Caveats</a></h2>
<ul>
<li>
<p><strong>IE 11</strong> - <code>wasm-bindgen</code> by default requires support for
<code>WebAssembly</code>, but no version of IE currently supports <code>WebAssembly</code>. You can
support IE by <a href="https://github.com/WebAssembly/binaryen">compiling wasm files to JS using <code>wasm2js</code></a> (you can <a href="reference/../examples/wasm2js.html">see
an example of doing this too</a>). Note
that at this time no bundler will do this by default, but we'd love to
document plugins which do this if you are aware of one!</p>
</li>
<li>
<p><strong>Edge</strong> - the <code>TextEncoder</code> and <code>TextDecoder</code> APIs are not currently
available in Edge which <code>wasm-bindgen</code> uses to encode/decode strings between
JS and Rust. You can polyfill this with at least one of two strategies:</p>
<ol>
<li>
<p>If using a bundler, you can likely configure the bundler to polyfill these
types by default. For example if you're using Webpack you can use the
<a href="https://webpack.js.org/plugins/provide-plugin/"><code>ProvidePlugin</code> interface</a> like so after also adding
<a href="https://www.npmjs.com/package/text-encoding"><code>text-encoding</code></a> to your <code>package.json</code></p>
<pre><code class="language-js">const webpack = require('webpack');
module.exports = {
plugins: [
new webpack.ProvidePlugin({
TextDecoder: ['text-encoding', 'TextDecoder'],
TextEncoder: ['text-encoding', 'TextEncoder']
})
]
// ... other configuration options
};
</code></pre>
<p><strong>Warning:</strong> doing this implies the polyfill will always be used,
even if native APIs are available. This has a very significant
performance impact (the polyfill was measured to be 100x slower in Chromium)!</p>
</li>
<li>
<p>If you're not using a bundler you can also include support manually by
adding a <code>&lt;script&gt;</code> tag which defines the <code>TextEncoder</code> and <code>TextDecoder</code>
globals. <a href="https://stackoverflow.com/questions/40662142/polyfill-for-textdecoder/46549188#46549188">This StackOverflow question</a> has some example usage and MDN
has a <a href="https://developer.mozilla.org/en-US/docs/Web/API/TextEncoder#Polyfill"><code>TextEncoder</code> polyfill implementation</a> to get you started
as well.</p>
</li>
</ol>
</li>
<li>
<p><strong>BigInt and <code>u64</code></strong> - currently the WebAssembly specification for the web
forbids the usage of 64-bit integers (Rust types <code>i64</code> and <code>u64</code>) in
exported/imported functions. When using <code>wasm-bindgen</code>, however, <code>u64</code> is
allowed! The reason for this is that it's translated to the <code>BigInt</code> type in
JS. The <code>BigInt</code> class, however, is only currently supported in Chrome 67+ and
Firefox 68+ (as of the time of this writing) and isn't supported in Edge or
Safari, for example. For more, up-to-date details, see <a href="https://caniuse.com/#feat=bigint"><code>BigInt</code> on Can I
use...</a>.</p>
</li>
</ul>
<p>If you find other incompatibilities please report them to us! We'd love to
either keep this list up-to-date or fix the underlying bugs :)</p>
<h1><a class="header" href="#supported-rust-types-and-their-javascript-representations" id="supported-rust-types-and-their-javascript-representations">Supported Rust Types and their JavaScript Representations</a></h1>
<p>This section provides an overview of all the types that <code>wasm-bindgen</code> can send
and receive across the WebAssembly ABI boundary, and how they translate into
JavaScript.</p>
<h1><a class="header" href="#imported-extern-whatever-javascript-types" id="imported-extern-whatever-javascript-types">Imported <code>extern Whatever;</code> JavaScript Types</a></h1>
<table><thead><tr><th align="center"><code>T</code> parameter</th><th align="center"><code>&amp;T</code> parameter</th><th align="center"><code>&amp;mut T</code> parameter</th><th align="center"><code>T</code> return value</th><th align="center"><code>Option&lt;T&gt;</code> parameter</th><th align="center"><code>Option&lt;T&gt;</code> return value</th><th align="center">JavaScript representation</th></tr></thead><tbody>
<tr><td align="center">Yes</td><td align="center">Yes</td><td align="center">No</td><td align="center">Yes</td><td align="center">Yes</td><td align="center">Yes</td><td align="center">Instances of the extant <code>Whatever</code> JavaScript class / prototype constructor</td></tr>
</tbody></table>
<h2><a class="header" href="#example-rust-usage" id="example-rust-usage">Example Rust Usage</a></h2>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
pub enum NumberEnum {
Foo = 0,
Bar = 1,
Qux = 2,
}
#[wasm_bindgen]
pub enum StringEnum {
Foo = &quot;foo&quot;,
Bar = &quot;bar&quot;,
Qux = &quot;qux&quot;,
}
#[wasm_bindgen]
pub struct Struct {
pub number: NumberEnum,
pub string: StringEnum,
}
#[wasm_bindgen]
extern &quot;C&quot; {
pub type SomeJsType;
}
#[wasm_bindgen]
pub fn imported_type_by_value(x: SomeJsType) {
/* ... */
}
#[wasm_bindgen]
pub fn imported_type_by_shared_ref(x: &amp;SomeJsType) {
/* ... */
}
#[wasm_bindgen]
pub fn return_imported_type() -&gt; SomeJsType {
unimplemented!()
}
#[wasm_bindgen]
pub fn take_option_imported_type(x: Option&lt;SomeJsType&gt;) {
/* ... */
}
#[wasm_bindgen]
pub fn return_option_imported_type() -&gt; Option&lt;SomeJsType&gt; {
unimplemented!()
}
#}</code></pre></pre>
<h2><a class="header" href="#example-javascript-usage" id="example-javascript-usage">Example JavaScript Usage</a></h2>
<pre><code class="language-js">import {
imported_type_by_value,
imported_type_by_shared_ref,
return_imported_type,
take_option_imported_type,
return_option_imported_type,
} from './guide_supported_types_examples';
imported_type_by_value(new SomeJsType());
imported_type_by_shared_ref(new SomeJsType());
let x = return_imported_type();
console.log(x instanceof SomeJsType); // true
take_option_imported_type(null);
take_option_imported_type(undefined);
take_option_imported_type(new SomeJsType());
let y = return_option_imported_type();
if (y == null) {
// ...
} else {
console.log(y instanceof SomeJsType); // true
}
</code></pre>
<h1><a class="header" href="#exported-struct-whatever-rust-types" id="exported-struct-whatever-rust-types">Exported <code>struct Whatever</code> Rust Types</a></h1>
<table><thead><tr><th align="center"><code>T</code> parameter</th><th align="center"><code>&amp;T</code> parameter</th><th align="center"><code>&amp;mut T</code> parameter</th><th align="center"><code>T</code> return value</th><th align="center"><code>Option&lt;T&gt;</code> parameter</th><th align="center"><code>Option&lt;T&gt;</code> return value</th><th align="center">JavaScript representation</th></tr></thead><tbody>
<tr><td align="center">Yes</td><td align="center">Yes</td><td align="center">Yes</td><td align="center">Yes</td><td align="center">No</td><td align="center">No</td><td align="center">Instances of a <code>wasm-bindgen</code>-generated JavaScript <code>class Whatever { ... }</code></td></tr>
</tbody></table>
<h2><a class="header" href="#example-rust-usage-1" id="example-rust-usage-1">Example Rust Usage</a></h2>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
pub struct ExportedNamedStruct {
pub inner: u32,
}
#[wasm_bindgen]
pub fn named_struct_by_value(x: ExportedNamedStruct) {}
#[wasm_bindgen]
pub fn named_struct_by_shared_ref(x: &amp;ExportedNamedStruct) {}
#[wasm_bindgen]
pub fn named_struct_by_exclusive_ref(x: &amp;mut ExportedNamedStruct) {}
#[wasm_bindgen]
pub fn return_named_struct(inner: u32) -&gt; ExportedNamedStruct {
ExportedNamedStruct { inner }
}
#[wasm_bindgen]
pub struct ExportedTupleStruct(pub u32, pub u32);
#[wasm_bindgen]
pub fn return_tuple_struct(x: u32, y: u32) -&gt; ExportedTupleStruct {
ExportedTupleStruct(x, y)
}
#}</code></pre></pre>
<h2><a class="header" href="#example-javascript-usage-1" id="example-javascript-usage-1">Example JavaScript Usage</a></h2>
<pre><code class="language-js">import {
ExportedNamedStruct,
named_struct_by_value,
named_struct_by_shared_ref,
named_struct_by_exclusive_ref,
return_named_struct,
ExportedTupleStruct,
return_tuple_struct
} from './guide_supported_types_examples';
let namedStruct = return_named_struct(42);
console.log(namedStruct instanceof ExportedNamedStruct); // true
console.log(namedStruct.inner); // 42
named_struct_by_value(namedStruct);
named_struct_by_shared_ref(namedStruct);
named_struct_by_exclusive_ref(namedStruct);
let tupleStruct = return_tuple_struct(10, 20);
console.log(tupleStruct instanceof ExportedTupleStruct); // true
console.log(tupleStruct[0], tupleStruct[1]); // 10, 20
</code></pre>
<h1><a class="header" href="#jsvalue" id="jsvalue"><code>JsValue</code></a></h1>
<table><thead><tr><th align="center"><code>T</code> parameter</th><th align="center"><code>&amp;T</code> parameter</th><th align="center"><code>&amp;mut T</code> parameter</th><th align="center"><code>T</code> return value</th><th align="center"><code>Option&lt;T&gt;</code> parameter</th><th align="center"><code>Option&lt;T&gt;</code> return value</th><th align="center">JavaScript representation</th></tr></thead><tbody>
<tr><td align="center">Yes</td><td align="center">Yes</td><td align="center">No</td><td align="center">Yes</td><td align="center">No</td><td align="center">No</td><td align="center">Any JavaScript value</td></tr>
</tbody></table>
<h2><a class="header" href="#example-rust-usage-2" id="example-rust-usage-2">Example Rust Usage</a></h2>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
pub fn take_js_value_by_value(x: JsValue) {}
#[wasm_bindgen]
pub fn take_js_value_by_shared_ref(x: &amp;JsValue) {}
#[wasm_bindgen]
pub fn return_js_value() -&gt; JsValue {
JsValue::NULL
}
#}</code></pre></pre>
<h2><a class="header" href="#example-javascript-usage-2" id="example-javascript-usage-2">Example JavaScript Usage</a></h2>
<pre><code class="language-js">import {
take_js_value_by_value,
take_js_value_by_shared_ref,
return_js_value,
} from './guide_supported_types_examples';
take_js_value_by_value(42);
take_js_value_by_shared_ref('hello');
let v = return_js_value();
</code></pre>
<h1><a class="header" href="#boxjsvalue" id="boxjsvalue"><code>Box&lt;[JsValue]&gt;</code></a></h1>
<table><thead><tr><th align="center"><code>T</code> parameter</th><th align="center"><code>&amp;T</code> parameter</th><th align="center"><code>&amp;mut T</code> parameter</th><th align="center"><code>T</code> return value</th><th align="center"><code>Option&lt;T&gt;</code> parameter</th><th align="center"><code>Option&lt;T&gt;</code> return value</th><th align="center">JavaScript representation</th></tr></thead><tbody>
<tr><td align="center">Yes</td><td align="center">No</td><td align="center">No</td><td align="center">Yes</td><td align="center">Yes</td><td align="center">Yes</td><td align="center">A JavaScript <code>Array</code> object</td></tr>
</tbody></table>
<h2><a class="header" href="#example-rust-usage-3" id="example-rust-usage-3">Example Rust Usage</a></h2>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
pub fn take_boxed_js_value_slice_by_value(x: Box&lt;[JsValue]&gt;) {}
#[wasm_bindgen]
pub fn return_boxed_js_value_slice() -&gt; Box&lt;[JsValue]&gt; {
vec![JsValue::NULL, JsValue::UNDEFINED].into_boxed_slice()
}
#[wasm_bindgen]
pub fn take_option_boxed_js_value_slice(x: Option&lt;Box&lt;[JsValue]&gt;&gt;) {}
#[wasm_bindgen]
pub fn return_option_boxed_js_value_slice() -&gt; Option&lt;Box&lt;[JsValue]&gt;&gt; {
None
}
#}</code></pre></pre>
<h2><a class="header" href="#example-javascript-usage-3" id="example-javascript-usage-3">Example JavaScript Usage</a></h2>
<pre><code class="language-js">import {
take_boxed_js_value_slice_by_value,
return_boxed_js_value_slice,
take_option_boxed_js_value_slice,
return_option_boxed_js_value_slice,
} from './guide_supported_types_examples';
take_boxed_js_value_slice_by_value([null, true, 2, {}, []]);
let values = return_boxed_js_value_slice();
console.log(values instanceof Array); // true
take_option_boxed_js_value_slice(null);
take_option_boxed_js_value_slice(undefined);
take_option_boxed_js_value_slice([1, 2, 3]);
let maybeValues = return_option_boxed_js_value_slice();
if (maybeValues == null) {
// ...
} else {
console.log(maybeValues instanceof Array); // true
}
</code></pre>
<h1><a class="header" href="#const-t-and-mut-t" id="const-t-and-mut-t"><code>*const T</code> and <code>*mut T</code></a></h1>
<table><thead><tr><th align="center"><code>T</code> parameter</th><th align="center"><code>&amp;T</code> parameter</th><th align="center"><code>&amp;mut T</code> parameter</th><th align="center"><code>T</code> return value</th><th align="center"><code>Option&lt;T&gt;</code> parameter</th><th align="center"><code>Option&lt;T&gt;</code> return value</th><th align="center">JavaScript representation</th></tr></thead><tbody>
<tr><td align="center">Yes</td><td align="center">No</td><td align="center">No</td><td align="center">Yes</td><td align="center">No</td><td align="center">No</td><td align="center">A JavaScript number value</td></tr>
</tbody></table>
<h2><a class="header" href="#example-rust-usage-4" id="example-rust-usage-4">Example Rust Usage</a></h2>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
use std::ptr;
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
pub fn take_pointer_by_value(x: *mut u8) {}
#[wasm_bindgen]
pub fn return_pointer() -&gt; *mut u8 {
ptr::null_mut()
}
#}</code></pre></pre>
<h2><a class="header" href="#example-javascript-usage-4" id="example-javascript-usage-4">Example JavaScript Usage</a></h2>
<pre><code class="language-js">import {
take_pointer_by_value,
return_pointer,
} from './guide_supported_types_examples';
import { memory } from './guide_supported_types_examples_bg';
let ptr = return_pointer();
let buf = new Uint8Array(memory.buffer);
let value = buf[ptr];
console.log(`The byte at the ${ptr} address is ${value}`);
take_pointer_by_value(ptr);
</code></pre>
<h1><a class="header" href="#numbers-u8-i8-u16-i16-u32-i32-u64-i64-isize-usize-f32-and-f64" id="numbers-u8-i8-u16-i16-u32-i32-u64-i64-isize-usize-f32-and-f64">Numbers: <code>u8</code>, <code>i8</code>, <code>u16</code>, <code>i16</code>, <code>u32</code>, <code>i32</code>, <code>u64</code>, <code>i64</code>, <code>isize</code>, <code>usize</code>, <code>f32</code>, and <code>f64</code></a></h1>
<table><thead><tr><th align="center"><code>T</code> parameter</th><th align="center"><code>&amp;T</code> parameter</th><th align="center"><code>&amp;mut T</code> parameter</th><th align="center"><code>T</code> return value</th><th align="center"><code>Option&lt;T&gt;</code> parameter</th><th align="center"><code>Option&lt;T&gt;</code> return value</th><th align="center">JavaScript representation</th></tr></thead><tbody>
<tr><td align="center">Yes</td><td align="center">No</td><td align="center">No</td><td align="center">Yes</td><td align="center">Yes</td><td align="center">Yes</td><td align="center">A JavaScript number value</td></tr>
</tbody></table>
<h2><a class="header" href="#example-rust-usage-5" id="example-rust-usage-5">Example Rust Usage</a></h2>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
pub fn take_number_by_value(x: u32) {}
#[wasm_bindgen]
pub fn return_number() -&gt; f64 {
42.0
}
#[wasm_bindgen]
pub fn take_option_number(x: Option&lt;u8&gt;) {}
#[wasm_bindgen]
pub fn return_option_number() -&gt; Option&lt;i16&gt; {
Some(-300)
}
#}</code></pre></pre>
<h2><a class="header" href="#example-javascript-usage-5" id="example-javascript-usage-5">Example JavaScript Usage</a></h2>
<pre><code class="language-js">import {
take_number_by_value,
return_number,
take_option_number,
return_option_number,
} from './guide_supported_types_examples';
take_number_by_value(42);
let x = return_number();
console.log(typeof x); // &quot;number&quot;
take_option_number(null);
take_option_number(undefined);
take_option_number(13);
let y = return_option_number();
if (y == null) {
// ...
} else {
console.log(typeof y); // &quot;number&quot;
}
</code></pre>
<h1><a class="header" href="#bool" id="bool"><code>bool</code></a></h1>
<table><thead><tr><th align="center"><code>T</code> parameter</th><th align="center"><code>&amp;T</code> parameter</th><th align="center"><code>&amp;mut T</code> parameter</th><th align="center"><code>T</code> return value</th><th align="center"><code>Option&lt;T&gt;</code> parameter</th><th align="center"><code>Option&lt;T&gt;</code> return value</th><th align="center">JavaScript representation</th></tr></thead><tbody>
<tr><td align="center">Yes</td><td align="center">No</td><td align="center">No</td><td align="center">Yes</td><td align="center">Yes</td><td align="center">Yes</td><td align="center">A JavaScript boolean value</td></tr>
</tbody></table>
<h2><a class="header" href="#example-rust-usage-6" id="example-rust-usage-6">Example Rust Usage</a></h2>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
pub fn take_bool_by_value(x: bool) {}
#[wasm_bindgen]
pub fn return_bool() -&gt; bool {
true
}
#[wasm_bindgen]
pub fn take_option_bool(x: Option&lt;bool&gt;) {}
#[wasm_bindgen]
pub fn return_option_bool() -&gt; Option&lt;bool&gt; {
Some(false)
}
#}</code></pre></pre>
<h2><a class="header" href="#example-javascript-usage-6" id="example-javascript-usage-6">Example JavaScript Usage</a></h2>
<pre><code class="language-js">import {
take_char_by_value,
return_char,
take_option_bool,
return_option_bool,
} from './guide_supported_types_examples';
take_bool_by_value(true);
let b = return_bool();
console.log(typeof b); // &quot;boolean&quot;
take_option_bool(null);
take_option_bool(undefined);
take_option_bool(true);
let c = return_option_bool();
if (c == null) {
// ...
} else {
console.log(typeof c); // &quot;boolean&quot;
}
</code></pre>
<h1><a class="header" href="#char" id="char"><code>char</code></a></h1>
<table><thead><tr><th align="center"><code>T</code> parameter</th><th align="center"><code>&amp;T</code> parameter</th><th align="center"><code>&amp;mut T</code> parameter</th><th align="center"><code>T</code> return value</th><th align="center"><code>Option&lt;T&gt;</code> parameter</th><th align="center"><code>Option&lt;T&gt;</code> return value</th><th align="center">JavaScript representation</th></tr></thead><tbody>
<tr><td align="center">Yes</td><td align="center">No</td><td align="center">No</td><td align="center">Yes</td><td align="center">No</td><td align="center">No</td><td align="center">A JavaScript string value</td></tr>
</tbody></table>
<h2><a class="header" href="#example-rust-usage-7" id="example-rust-usage-7">Example Rust Usage</a></h2>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
pub fn take_char_by_value(x: char) {}
#[wasm_bindgen]
pub fn return_char() -&gt; char {
'🚀'
}
#}</code></pre></pre>
<h2><a class="header" href="#example-javascript-usage-7" id="example-javascript-usage-7">Example JavaScript Usage</a></h2>
<pre><code class="language-js">import {
take_char_by_value,
return_char,
} from './guide_supported_types_examples';
take_char_by_value('a');
let c = return_char();
console.log(typeof c); // &quot;string&quot;
</code></pre>
<h1><a class="header" href="#str" id="str"><code>str</code></a></h1>
<table><thead><tr><th align="center"><code>T</code> parameter</th><th align="center"><code>&amp;T</code> parameter</th><th align="center"><code>&amp;mut T</code> parameter</th><th align="center"><code>T</code> return value</th><th align="center"><code>Option&lt;T&gt;</code> parameter</th><th align="center"><code>Option&lt;T&gt;</code> return value</th><th align="center">JavaScript representation</th></tr></thead><tbody>
<tr><td align="center">No</td><td align="center">Yes</td><td align="center">No</td><td align="center">No</td><td align="center">No</td><td align="center">No</td><td align="center">JavaScript string value</td></tr>
</tbody></table>
<p>Copies the string's contents back and forth between the JavaScript
garbage-collected heap and the Wasm linear memory with <code>TextDecoder</code> and
<code>TextEncoder</code>. If you don't want to perform this copy, and would rather work
with handles to JavaScript string values, use the <code>js_sys::JsString</code> type.</p>
<h2><a class="header" href="#example-rust-usage-8" id="example-rust-usage-8">Example Rust Usage</a></h2>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
pub fn take_str_by_shared_ref(x: &amp;str) {}
#}</code></pre></pre>
<h2><a class="header" href="#example-javascript-usage-8" id="example-javascript-usage-8">Example JavaScript Usage</a></h2>
<pre><code class="language-js">import {
take_str_by_shared_ref,
} from './guide_supported_types_examples';
take_str_by_shared_ref('hello');
</code></pre>
<h2><a class="header" href="#utf-16-vs-utf-8" id="utf-16-vs-utf-8">UTF-16 vs UTF-8</a></h2>
<p>Strings in JavaScript are encoded as UTF-16, but with one major exception: they
can contain unpaired surrogates. For some Unicode characters UTF-16 uses two
16-bit values. These are called &quot;surrogate pairs&quot; because they always come in
pairs. In JavaScript, it is possible for these surrogate pairs to be missing the
other half, creating an &quot;unpaired surrogate&quot;.</p>
<p>When passing a string from JavaScript to Rust, it uses the <code>TextEncoder</code> API to
convert from UTF-16 to UTF-8. This is normally perfectly fine... unless there
are unpaired surrogates. In that case it will replace the unpaired surrogates
with U+FFFD (<28>, the replacement character). That means the string in Rust is
now different from the string in JavaScript!</p>
<p>If you want to guarantee that the Rust string is the same as the JavaScript
string, you should instead use <code>js_sys::JsString</code> (which keeps the string in
JavaScript and doesn't copy it into Rust).</p>
<p>If you want to access the raw value of a JS string, you can use <code>JsString::iter</code>,
which returns an <code>Iterator&lt;Item = u16&gt;</code>. This perfectly preserves everything
(including unpaired surrogates), but it does not do any encoding (so you
have to do that yourself!).</p>
<p>If you simply want to ignore strings which contain unpaired surrogates, you can
use <code>JsString::is_valid_utf16</code> to test whether the string contains unpaired
surrogates or not.</p>
<h1><a class="header" href="#string" id="string"><code>String</code></a></h1>
<table><thead><tr><th align="center"><code>T</code> parameter</th><th align="center"><code>&amp;T</code> parameter</th><th align="center"><code>&amp;mut T</code> parameter</th><th align="center"><code>T</code> return value</th><th align="center"><code>Option&lt;T&gt;</code> parameter</th><th align="center"><code>Option&lt;T&gt;</code> return value</th><th align="center">JavaScript representation</th></tr></thead><tbody>
<tr><td align="center">Yes</td><td align="center">No</td><td align="center">No</td><td align="center">Yes</td><td align="center">Yes</td><td align="center">Yes</td><td align="center">JavaScript string value</td></tr>
</tbody></table>
<p>Copies the string's contents back and forth between the JavaScript
garbage-collected heap and the Wasm linear memory with <code>TextDecoder</code> and
<code>TextEncoder</code></p>
<blockquote>
<p><strong>Note</strong>: Be sure to check out the <a href="reference/types/str.html">documentation for <code>str</code></a> to
learn about some caveats when working with strings between JS and Rust.</p>
</blockquote>
<h2><a class="header" href="#example-rust-usage-9" id="example-rust-usage-9">Example Rust Usage</a></h2>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
pub fn take_string_by_value(x: String) {}
#[wasm_bindgen]
pub fn return_string() -&gt; String {
&quot;hello&quot;.into()
}
#[wasm_bindgen]
pub fn take_option_string(x: Option&lt;String&gt;) {}
#[wasm_bindgen]
pub fn return_option_string() -&gt; Option&lt;String&gt; {
None
}
#}</code></pre></pre>
<h2><a class="header" href="#example-javascript-usage-9" id="example-javascript-usage-9">Example JavaScript Usage</a></h2>
<pre><code class="language-js">import {
take_string_by_value,
return_string,
take_option_string,
return_option_string,
} from './guide_supported_types_examples';
take_string_by_value('hello');
let s = return_string();
console.log(typeof s); // &quot;string&quot;
take_option_string(null);
take_option_string(undefined);
take_option_string('hello');
let t = return_option_string();
if (t == null) {
// ...
} else {
console.log(typeof s); // &quot;string&quot;
}
</code></pre>
<h1><a class="header" href="#number-slices-u8-i8-u16-i16-u32-i32-u64-i64-f32-and-f64" id="number-slices-u8-i8-u16-i16-u32-i32-u64-i64-f32-and-f64">Number Slices: <code>[u8]</code>, <code>[i8]</code>, <code>[u16]</code>, <code>[i16]</code>, <code>[u32]</code>, <code>[i32]</code>, <code>[u64]</code>, <code>[i64]</code>, <code>[f32]</code>, and <code>[f64]</code></a></h1>
<table><thead><tr><th align="center"><code>T</code> parameter</th><th align="center"><code>&amp;T</code> parameter</th><th align="center"><code>&amp;mut T</code> parameter</th><th align="center"><code>T</code> return value</th><th align="center"><code>Option&lt;&amp;T&gt;</code> parameter</th><th align="center"><code>Option&lt;T&gt;</code> return value</th><th align="center">JavaScript representation</th></tr></thead><tbody>
<tr><td align="center">No</td><td align="center">Yes</td><td align="center">Yes</td><td align="center">No</td><td align="center">No</td><td align="center">No</td><td align="center">A JavaScript <code>TypedArray</code> view of the Wasm memory for the boxed slice of the appropriate type (<code>Int32Array</code>, <code>Uint8Array</code>, etc)</td></tr>
</tbody></table>
<h2><a class="header" href="#example-rust-usage-10" id="example-rust-usage-10">Example Rust Usage</a></h2>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
pub fn take_number_slice_by_shared_ref(x: &amp;[f64]) {}
#[wasm_bindgen]
pub fn take_number_slice_by_exclusive_ref(x: &amp;mut [u8]) {}
#}</code></pre></pre>
<h2><a class="header" href="#example-javascript-usage-10" id="example-javascript-usage-10">Example JavaScript Usage</a></h2>
<pre><code class="language-js">import {
take_number_slice_by_shared_ref,
take_number_slice_by_exclusive_ref,
} from './guide_supported_types_examples';
take_number_slice_by_shared_ref(new Float64Array(100));
take_number_slice_by_exclusive_ref(new Uint8Array(100));
</code></pre>
<h1><a class="header" href="#boxed-number-slices-boxu8-boxi8-boxu16-boxi16-boxu32-boxi32-boxu64-boxi64-boxf32-and-boxf64" id="boxed-number-slices-boxu8-boxi8-boxu16-boxi16-boxu32-boxi32-boxu64-boxi64-boxf32-and-boxf64">Boxed Number Slices: <code>Box&lt;[u8]&gt;</code>, <code>Box&lt;[i8]&gt;</code>, <code>Box&lt;[u16]&gt;</code>, <code>Box&lt;[i16]&gt;</code>, <code>Box&lt;[u32]&gt;</code>, <code>Box&lt;[i32]&gt;</code>, <code>Box&lt;[u64]&gt;</code>, <code>Box&lt;[i64]&gt;</code>, <code>Box&lt;[f32]&gt;</code>, and <code>Box&lt;[f64]&gt;</code></a></h1>
<table><thead><tr><th align="center"><code>T</code> parameter</th><th align="center"><code>&amp;T</code> parameter</th><th align="center"><code>&amp;mut T</code> parameter</th><th align="center"><code>T</code> return value</th><th align="center"><code>Option&lt;T&gt;</code> parameter</th><th align="center"><code>Option&lt;T&gt;</code> return value</th><th align="center">JavaScript representation</th></tr></thead><tbody>
<tr><td align="center">Yes</td><td align="center">No</td><td align="center">No</td><td align="center">Yes</td><td align="center">Yes</td><td align="center">Yes</td><td align="center">A JavaScript <code>TypedArray</code> of the appropriate type (<code>Int32Array</code>, <code>Uint8Array</code>, etc...)</td></tr>
</tbody></table>
<p>Note that the contents of the slice are copied into the JavaScript <code>TypedArray</code>
from the Wasm linear memory when returning a boxed slice to JavaScript, and vice
versa when receiving a JavaScript <code>TypedArray</code> as a boxed slice in Rust.</p>
<h2><a class="header" href="#example-rust-usage-11" id="example-rust-usage-11">Example Rust Usage</a></h2>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
pub fn take_boxed_number_slice_by_value(x: Box&lt;[f64]&gt;) {}
#[wasm_bindgen]
pub fn return_boxed_number_slice() -&gt; Box&lt;[u32]&gt; {
(0..42).collect::&lt;Vec&lt;u32&gt;&gt;().into_boxed_slice()
}
#[wasm_bindgen]
pub fn take_option_boxed_number_slice(x: Option&lt;Box&lt;[u8]&gt;&gt;) {}
#[wasm_bindgen]
pub fn return_option_boxed_number_slice() -&gt; Option&lt;Box&lt;[i32]&gt;&gt; {
None
}
#}</code></pre></pre>
<h2><a class="header" href="#example-javascript-usage-11" id="example-javascript-usage-11">Example JavaScript Usage</a></h2>
<pre><code class="language-js">import {
take_boxed_number_slice_by_value,
return_boxed_number_slice,
take_option_boxed_number_slice,
return_option_boxed_number_slice,
} from './guide_supported_types_examples';
take_boxed_number_slice_by_value(new Uint8Array(100));
let x = return_boxed_number_slice();
console.log(x instanceof Uint32Array); // true
take_option_boxed_number_slice(null);
take_option_boxed_number_slice(undefined);
take_option_boxed_number_slice(new Int16Array(256));
let y = return_option_boxed_number_slice();
if (y == null) {
// ...
} else {
console.log(x instanceof Int32Array); // true
}
</code></pre>
<h1><a class="header" href="#resultt-jsvalue" id="resultt-jsvalue"><code>Result&lt;T, JsValue&gt;</code></a></h1>
<table><thead><tr><th align="center"><code>T</code> parameter</th><th align="center"><code>&amp;T</code> parameter</th><th align="center"><code>&amp;mut T</code> parameter</th><th align="center"><code>T</code> return value</th><th align="center"><code>Option&lt;T&gt;</code> parameter</th><th align="center"><code>Option&lt;T&gt;</code> return value</th><th align="center">JavaScript representation</th></tr></thead><tbody>
<tr><td align="center">No</td><td align="center">No</td><td align="center">No</td><td align="center">No</td><td align="center">No</td><td align="center">Yes</td><td align="center">Same as <code>T</code>, or an exception</td></tr>
</tbody></table>
<p>The <code>Result</code> type can be returned from functions exported to JS as well as
closures in Rust. Only <code>Result&lt;T, JsValue&gt;</code> is supported where <code>T</code> can be
converted to JS. Whenever <code>Ok(val)</code> is encountered it's converted to JS and
handed off, and whenever <code>Err(error)</code> is encountered an exception is thrown in
JS with <code>error</code>.</p>
<p>You can use <code>Result</code> to enable handling of JS exceptions with <code>?</code> in Rust,
naturally propagating it upwards to the wasm boundary. Furthermore you can also
return custom types in Rust so long as they're all convertible to <code>JsValue</code>.</p>
<p>Note that if you import a JS function with <code>Result</code> you need
<code>#[wasm_bindgen(catch)]</code> to be annotated on the import (unlike exported
functions, which require no extra annotation). This may not be necessary in the
future though and it may work &quot;as is&quot;!.</p>
<h1><a class="header" href="#wasm_bindgen-attributes" id="wasm_bindgen-attributes"><code>#[wasm_bindgen]</code> Attributes</a></h1>
<p>The <code>#[wasm_bindgen]</code> macro supports a good amount of configuration for
controlling precisely how exports are exported, how imports are imported, and
what the generated JavaScript glue ends up looking like. This section is an
exhaustive reference of the possibilities!</p>
<h1><a class="header" href="#wasm_bindgen-on-javascript-imports" id="wasm_bindgen-on-javascript-imports"><code>#[wasm_bindgen]</code> on JavaScript Imports</a></h1>
<p>This section enumerates the attributes available for customizing bindings for
JavaScript functions and classes imported into Rust within an <code>extern &quot;C&quot; { ... }</code>
block.</p>
<h1><a class="header" href="#catch" id="catch"><code>catch</code></a></h1>
<p>The <code>catch</code> attribute allows catching a JavaScript exception. This can be
attached to any imported function or method, and the function must return a
<code>Result</code> where the <code>Err</code> payload is a <code>JsValue</code>:</p>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
#[wasm_bindgen]
extern &quot;C&quot; {
// `catch` on a standalone function.
#[wasm_bindgen(catch)]
fn foo() -&gt; Result&lt;(), JsValue&gt;;
// `catch` on a method.
type Zoidberg;
#[wasm_bindgen(catch, method)]
fn woop_woop_woop(this: &amp;Zoidberg) -&gt; Result&lt;u32, JsValue&gt;;
}
#}</code></pre></pre>
<p>If calling the imported function throws an exception, then <code>Err</code> will be
returned with the exception that was raised. Otherwise, <code>Ok</code> is returned with
the result of the function.</p>
<blockquote>
<p>By default <code>wasm-bindgen</code> will take no action when wasm calls a JS function
which ends up throwing an exception. The wasm spec right now doesn't support
stack unwinding and as a result Rust code <strong>will not execute destructors</strong>.
This can unfortunately cause memory leaks in Rust right now, but as soon as
wasm implements catching exceptions we'll be sure to add support as well!</p>
</blockquote>
<h1><a class="header" href="#constructor" id="constructor"><code>constructor</code></a></h1>
<p>The <code>constructor</code> attribute is used to indicate that the function being bound
should actually translate to calling the <code>new</code> operator in JavaScript. The final
argument must be a type that's imported from JavaScript, and it's what will get
used in the generated glue:</p>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
#[wasm_bindgen]
extern &quot;C&quot; {
type Shoes;
#[wasm_bindgen(constructor)]
fn new() -&gt; Shoes;
}
#}</code></pre></pre>
<p>This will attach a <code>new</code> static method to the <code>Shoes</code> type, and in JavaScript
when this method is called, it will be equivalent to <code>new Shoes()</code>.</p>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
// Become a cobbler; construct `new Shoes()`
let shoes = Shoes::new();
#}</code></pre></pre>
<h1><a class="header" href="#extends--class" id="extends--class"><code>extends = Class</code></a></h1>
<p>The <code>extends</code> attribute can be used to say that an imported type extends (in the
JS class hierarchy sense) another type. This will generate <code>AsRef</code>, <code>AsMut</code>, and
<code>From</code> impls for converting a type into another given that we statically know
the inheritance hierarchy:</p>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
#[wasm_bindgen]
extern &quot;C&quot; {
type Foo;
#[wasm_bindgen(extends = Foo)]
type Bar;
}
let x: &amp;Bar = ...;
let y: &amp;Foo = x.as_ref(); // zero cost cast
#}</code></pre></pre>
<p>The trait implementations generated for the above block are:</p>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
impl From&lt;Bar&gt; for Foo { ... }
impl AsRef&lt;Foo&gt; for Bar { ... }
impl AsMut&lt;Foo&gt; for Bar { ... }
#}</code></pre></pre>
<p>The <code>extends = ...</code> attribute can be specified multiple times for longer
inheritance chains, and <code>AsRef</code> and such impls will be generated for each of
the types.</p>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
#[wasm_bindgen]
extern &quot;C&quot; {
type Foo;
#[wasm_bindgen(extends = Foo)]
type Bar;
#[wasm_bindgen(extends = Foo, extends = Bar)]
type Baz;
}
let x: &amp;Baz = ...;
let y1: &amp;Bar = x.as_ref();
let y2: &amp;Foo = y1.as_ref();
#}</code></pre></pre>
<h1><a class="header" href="#getter-and-setter" id="getter-and-setter"><code>getter</code> and <code>setter</code></a></h1>
<p>These two attributes can be combined with <code>method</code> to indicate that this is a
getter or setter method. A <code>getter</code>-tagged function by default accesses the
JavaScript property with the same name as the getter function. A <code>setter</code>'s
function name is currently required to start with <code>set_</code> and the property it
accesses is the suffix after <code>set\_</code>.</p>
<p>Consider the following JavaScript class that has a getter and setter for the
<code>white_russians</code> property:</p>
<pre><code class="language-js">class TheDude {
get white_russians() {
...
}
set white_russians(val) {
...
}
}
</code></pre>
<p>We would import this with the following <code>#[wasm_bindgen]</code> attributes:</p>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
#[wasm_bindgen]
extern &quot;C&quot; {
type TheDude;
#[wasm_bindgen(method, getter)]
fn white_russians(this: &amp;TheDude) -&gt; u32;
#[wasm_bindgen(method, setter)]
fn set_white_russians(this: &amp;TheDude, val: u32);
}
#}</code></pre></pre>
<p>Here we're importing the <code>TheDude</code> type and defining the ability to access each
object's <code>white_russians</code> property. The first function here is a getter and will
be available in Rust as <code>the_dude.white_russians()</code>, and the latter is the
setter which is accessible as <code>the_dude.set_white_russians(2)</code>. Note that both
functions have a <code>this</code> argument as they're tagged with <code>method</code>.</p>
<p>Finally, you can also pass an argument to the <code>getter</code> and <code>setter</code>
properties to configure what property is accessed. When the property is
explicitly specified then there is no restriction on the method name. For
example the below is equivalent to the above:</p>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
#[wasm_bindgen]
extern &quot;C&quot; {
type TheDude;
#[wasm_bindgen(method, getter = white_russians)]
fn my_custom_getter_name(this: &amp;TheDude) -&gt; u32;
#[wasm_bindgen(method, setter = white_russians)]
fn my_custom_setter_name(this: &amp;TheDude, val: u32);
}
#}</code></pre></pre>
<p>Heads up! <code>getter</code> and <code>setter</code> functions are found on the constructor's
prototype chain once at load time, cached, and then the cached accessor is
invoked on each access. If you need to dynamically walk the prototype chain on
every access, add the <code>structural</code> attribute!</p>
<pre><code class="language-js">// This is the default function Rust will invoke on `the_dude.white_russians()`:
const white_russians = Object.getOwnPropertyDescriptor(
TheDude.prototype,
&quot;white_russians&quot;
).get;
// This is what you get by adding `structural`:
const white_russians = function(the_dude) {
return the_dude.white_russians;
};
</code></pre>
<h1><a class="header" href="#final" id="final"><code>final</code></a></h1>
<p>The <code>final</code> attribute is the converse of the <a href="reference/attributes/on-js-imports/structural.html"><code>structural</code>
attribute</a>. It configures how <code>wasm-bindgen</code> will generate JS
imports to call the imported function. Notably a function imported by <code>final</code>
never changes after it was imported, whereas a function imported by default (or
with <code>structural</code>) is subject to runtime lookup rules such as walking the
prototype chain of an object.</p>
<p>The <code>final</code> attribute is intended to be purely related to performance. It
ideally has no user-visible effect, and <code>structural</code> imports (the default)
should be able to transparently switch to <code>final</code> eventually.</p>
<p>The eventual performance aspect is that with the <a href="https://github.com/WebAssembly/host-bindings">host bindings
proposal</a> then <code>wasm-bindgen</code> will need to generate far fewer JS
function shims to import than it does today. For example, consider this import
today:</p>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
#[wasm_bindgen]
extern &quot;C&quot; {
type Foo;
#[wasm_bindgen(method)]
fn bar(this: &amp;Foo, argument: &amp;str) -&gt; JsValue;
}
#}</code></pre></pre>
<p><strong>Without the <code>final</code> attribute</strong> the generated JS looks like this:</p>
<pre><code class="language-js">// without `final`
export function __wbg_bar_a81456386e6b526f(arg0, arg1, arg2) {
let varg1 = getStringFromWasm(arg1, arg2);
return addHeapObject(getObject(arg0).bar(varg1));
}
</code></pre>
<p>We can see here that this JS function shim is required, but it's all relatively
self-contained. It does, however, execute the <code>bar</code> method in a duck-type-y
fashion in the sense that it never validates <code>getObject(arg0)</code> is of type <code>Foo</code>
to actually call the <code>Foo.prototype.bar</code> method.</p>
<p>If we instead, however, write this:</p>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
#[wasm_bindgen]
extern &quot;C&quot; {
type Foo;
#[wasm_bindgen(method, final)] // note the change here
fn bar(this: &amp;Foo, argument: &amp;str) -&gt; JsValue;
}
#}</code></pre></pre>
<p>it generates this JS glue (roughly):</p>
<pre><code class="language-js">const __wbg_bar_target = Foo.prototype.bar;
export function __wbg_bar_a81456386e6b526f(arg0, arg1, arg2) {
let varg1 = getStringFromWasm(arg1, arg2);
return addHeapObject(__wbg_bar_target.call(getObject(arg0), varg1));
}
</code></pre>
<p>The difference here is pretty subtle, but we can see how the function being
called is hoisted out of the generated shim and is bound to always be
<code>Foo.prototype.bar</code>. This then uses the <code>Function.call</code> method to invoke that
function with <code>getObject(arg0)</code> as the receiver.</p>
<p>But wait, there's still a JS function shim here even with <code>final</code>! That's true,
and this is simply a fact of future WebAssembly proposals not being implemented
yet. The semantics, though, match the future <a href="https://github.com/WebAssembly/host-bindings">host bindings
proposal</a> because the method being called is determined exactly
once, and it's located on the prototype chain rather than being resolved at
runtime when the function is called.</p>
<h2><a class="header" href="#interaction-with-future-proposals" id="interaction-with-future-proposals">Interaction with future proposals</a></h2>
<p>If you're curious to see how our JS function shim will be eliminated entirely,
let's take a look at the generated bindings. We're starting off with this:</p>
<pre><code class="language-js">const __wbg_bar_target = Foo.prototype.bar;
export function __wbg_bar_a81456386e6b526f(arg0, arg1, arg2) {
let varg1 = getStringFromWasm(arg1, arg2);
return addHeapObject(__wbg_bar_target.call(getObject(arg0), varg1));
}
</code></pre>
<p>... and once the <a href="https://github.com/WebAssembly/reference-types">reference types proposal</a> is implemented then
we won't need some of these pesky functions. That'll transform our generated JS
shim to look like:</p>
<pre><code class="language-js">const __wbg_bar_target = Foo.prototype.bar;
export function __wbg_bar_a81456386e6b526f(arg0, arg1, arg2) {
let varg1 = getStringFromWasm(arg1, arg2);
return __wbg_bar_target.call(arg0, varg1);
}
</code></pre>
<p>Getting better! Next up we need the host bindings proposal. Note that the
proposal is undergoing some changes right now so it's tough to link to reference
documentation, but it suffices to say that it'll empower us with at least two
different features.</p>
<p>First, host bindings promises to provide the concept of &quot;argument conversions&quot;.
The <code>arg1</code> and <code>arg2</code> values here are actually a pointer and a length to a utf-8
encoded string, and with host bindings we'll be able to annotate that this
import should take those two arguments and convert them to a JS string (that is,
the <em>host</em> should do this, the WebAssembly engine). Using that feature we can
futher trim this down to:</p>
<pre><code class="language-js">const __wbg_bar_target = Foo.prototype.bar;
export function __wbg_bar_a81456386e6b526f(arg0, varg1) {
return __wbg_bar_target.call(arg0, varg1);
}
</code></pre>
<p>And finally, the second promise of the host bindings proposal is that we can
flag a function call to indicate the first argument is the <code>this</code> binding of the
function call. Today the <code>this</code> value of all called imported functions is
<code>undefined</code>, and this flag (configured with host bindings) will indicate the
first argument here is actually the <code>this</code>.</p>
<p>With that in mind we can further transform this to:</p>
<pre><code class="language-js">export const __wbg_bar_a81456386e6b526f = Foo.prototype.bar;
</code></pre>
<p>and voila! We, with <a href="https://github.com/WebAssembly/reference-types">reference types</a> and <a href="https://github.com/WebAssembly/host-bindings">host
bindings</a>, now have no JS function shim at all necessary to call
the imported function. Additionally future wasm proposals to the ES module
system may also mean that don't even need the <code>export const ...</code> here too.</p>
<p>It's also worth pointing out that with all these wasm proposals implemented the
default way to import the <code>bar</code> function (aka <code>structural</code>) would generate a JS
function shim that looks like:</p>
<pre><code class="language-js">export function __wbg_bar_a81456386e6b526f(varg1) {
return this.bar(varg1);
}
</code></pre>
<p>where this import is still subject to runtime prototype chain lookups and such.</p>
<h1><a class="header" href="#indexing_getter-indexing_setter-and-indexing_deleter" id="indexing_getter-indexing_setter-and-indexing_deleter"><code>indexing_getter</code>, <code>indexing_setter</code>, and <code>indexing_deleter</code></a></h1>
<p>These three attributes indicate that a method is an dynamically intercepted
getter, setter, or deleter on the receiver object itself, rather than a direct
access of the receiver's properties. It is equivalent calling the Proxy handler
for the <code>obj[prop]</code> operation with some dynamic <code>prop</code> variable in JavaScript,
rather than a normal static property access like <code>obj.prop</code> on a normal
JavaScript <code>Object</code>.</p>
<p>This is useful for binding to <code>Proxy</code>s and some builtin DOM types that
dynamically intercept property accesses.</p>
<ul>
<li>
<p><code>indexing_getter</code> corresponds to <code>obj[prop]</code> operation in JavaScript. The
function annotated must have a <code>this</code> receiver parameter, a single parameter
that is used for indexing into the receiver (<code>prop</code>), and a return type.</p>
</li>
<li>
<p><code>indexing_setter</code> corresponds to the <code>obj[prop] = val</code> operation in
JavaScript. The function annotated must have a <code>this</code> receiver parameter, a
parameter for indexing into the receiver (<code>prop</code>), and a value parameter
(<code>val</code>).</p>
</li>
<li>
<p><code>indexing_deleter</code> corresponds to <code>delete obj[prop]</code> operation in
JavaScript. The function annotated must have a <code>this</code> receiver and a single
parameter for indexing into the receiver (<code>prop</code>).</p>
</li>
</ul>
<p>These must always be used in conjunction with the <code>structural</code> and <code>method</code>
flags.</p>
<p>For example, consider this JavaScript snippet that uses <code>Proxy</code>:</p>
<pre><code class="language-js">const foo = new Proxy({}, {
get(obj, prop) {
return prop in obj ? obj[prop] : prop.length;
},
set(obj, prop, value) {
obj[prop] = value;
},
deleteProperty(obj, prop) {
delete obj[prop];
},
});
foo.ten;
// 3
foo.ten = 10;
foo.ten;
// 10
delete foo.ten;
foo.ten;
// 3
</code></pre>
<p>To bind that in <code>wasm-bindgen</code> in Rust, we would use the <code>indexing_*</code> attributes
on methods:</p>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
#[wasm_bindgen]
extern &quot;C&quot; {
type Foo;
static foo: Foo;
#[wasm_bindgen(method, structural, indexing_getter)]
fn get(this: &amp;Foo, prop: &amp;str) -&gt; u32;
#[wasm_bindgen(method, structural, indexing_setter)]
fn set(this: &amp;Foo, prop: &amp;str, val: u32);
#[wasm_bindgen(method, structural, indexing_deleter)]
fn delete(this: &amp;Foo, prop: &amp;str);
}
assert_eq!(foo.get(&quot;ten&quot;), 3);
foo.set(&quot;ten&quot;, 10);
assert_eq!(foo.get(&quot;ten&quot;), 10);
foo.delete(&quot;ten&quot;);
assert_eq!(foo.get(&quot;ten&quot;), 3);
#}</code></pre></pre>
<h1><a class="header" href="#js_class--blah" id="js_class--blah"><code>js_class = &quot;Blah&quot;</code></a></h1>
<p>The <code>js_class</code> attribute can be used in conjunction with the <code>method</code> attribute
to bind methods of imported JavaScript classes that have been renamed on the
Rust side.</p>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
#[wasm_bindgen]
extern &quot;C&quot; {
// We don't want to import JS strings as `String`, since Rust already has a
// `String` type in its prelude, so rename it as `JsString`.
#[wasm_bindgen(js_name = String)]
type JsString;
// This is a method on the JavaScript &quot;String&quot; class, so specify that with
// the `js_class` attribute.
#[wasm_bindgen(method, js_class = &quot;String&quot;, js_name = charAt)]
fn char_at(this: &amp;JsString, index: u32) -&gt; JsString;
}
#}</code></pre></pre>
<h1><a class="header" href="#js_name--blah" id="js_name--blah"><code>js_name = blah</code></a></h1>
<p>The <code>js_name</code> attribute can be used to bind to a different function in
JavaScript than the identifier that's defined in Rust.</p>
<p>Most often, this is used to convert a camel-cased JavaScript identifier into a
snake-cased Rust identifier:</p>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
#[wasm_bindgen]
extern &quot;C&quot; {
#[wasm_bindgen(js_name = jsOftenUsesCamelCase)]
fn js_often_uses_camel_case() -&gt; u32;
}
#}</code></pre></pre>
<p>Sometimes, it is used to bind to JavaScript identifiers that are not valid Rust
identifiers, in which case <code>js_name = &quot;some string&quot;</code> is used instead of <code>js_name = ident</code>:</p>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
#[wasm_bindgen]
extern &quot;C&quot; {
#[wasm_bindgen(js_name = &quot;$$$&quot;)]
fn cash_money() -&gt; u32;
}
#}</code></pre></pre>
<p>However, you can also use <code>js_name</code> to define multiple signatures for
polymorphic JavaScript functions:</p>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
#[wasm_bindgen]
extern &quot;C&quot; {
#[wasm_bindgen(js_namespace = console, js_name = log)]
fn console_log_str(s: &amp;str);
#[wasm_bindgen(js_namespace = console, js_name = log)]
fn console_log_u32(n: u32);
#[wasm_bindgen(js_namespace = console, js_name = log)]
fn console_log_many(a: u32, b: &amp;JsValue);
}
#}</code></pre></pre>
<p>All of these functions will call <code>console.log</code> in JavaScript, but each
identifier will have only one signature in Rust.</p>
<p>Note that if you use <code>js_name</code> when importing a type you'll also need to use the
<a href="reference/attributes/on-js-imports/js_class.html"><code>js_class</code> attribute</a> when defining methods on the type:</p>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
#[wasm_bindgen]
extern &quot;C&quot; {
#[wasm_bindgen(js_name = String)]
type JsString;
#[wasm_bindgen(method, getter, js_class = &quot;String&quot;)]
pub fn length(this: &amp;JsString) -&gt; u32;
}
#}</code></pre></pre>
<h1><a class="header" href="#js_namespace--blah" id="js_namespace--blah"><code>js_namespace = blah</code></a></h1>
<p>This attribute indicates that the JavaScript type is accessed through the given
namespace. For example, the <code>WebAssembly.Module</code> APIs are all accessed through
the <code>WebAssembly</code> namespace. <code>js_namespace</code> can be applied to any import
(function or type) and whenever the generated JavaScript attempts to reference a
name (like a class or function name) it'll be accessed through this namespace.</p>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
#[wasm_bindgen]
extern &quot;C&quot; {
#[wasm_bindgen(js_namespace = console)]
fn log(s: &amp;str);
type Foo;
#[wasm_bindgen(constructor, js_namespace = Bar)]
fn new() -&gt; Foo;
}
log(&quot;hello, console!&quot;);
Foo::new();
#}</code></pre></pre>
<p>This is an example of how to bind namespaced items in Rust. The <code>log</code> and <code>Foo::new</code> functions will
be available in the Rust module and will be invoked as <code>console.log</code> and <code>new Bar.Foo</code> in
JavaScript.</p>
<p>It is also possible to access the JavaScript object under the nested namespace.
<code>js_namespace</code> also accepts the array of the string to specify the namespace.</p>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
#[wasm_bindgen]
extern &quot;C&quot; {
#[wasm_bindgen(js_namespace = [&quot;window&quot;, &quot;document&quot;])]
fn write(s: &amp;str);
}
write(&quot;hello, document!&quot;);
#}</code></pre></pre>
<p>This example shows how to bind <code>window.document.write</code> in Rust.</p>
<h1><a class="header" href="#method" id="method"><code>method</code></a></h1>
<p>The <code>method</code> attribute allows you to describe methods of imported JavaScript
objects. It is applied on a function that has <code>this</code> as its first parameter,
which is a shared reference to an imported JavaScript type.</p>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
#[wasm_bindgen]
extern &quot;C&quot; {
type Set;
#[wasm_bindgen(method)]
fn has(this: &amp;Set, element: &amp;JsValue) -&gt; bool;
}
#}</code></pre></pre>
<p>This generates a <code>has</code> method on <code>Set</code> in Rust, which invokes the
<code>Set.prototype.has</code> method in JavaScript.</p>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
let set: Set = ...;
let elem: JsValue = ...;
if set.has(&amp;elem) {
...
}
#}</code></pre></pre>
<h1><a class="header" href="#module--blah" id="module--blah"><code>module = &quot;blah&quot;</code></a></h1>
<p>The <code>module</code> attributes configures the module from which items are imported. For
example,</p>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
#[wasm_bindgen(module = &quot;wu/tang/clan&quot;)]
extern &quot;C&quot; {
type ThirtySixChambers;
}
#}</code></pre></pre>
<p>generates JavaScript import glue like:</p>
<pre><code class="language-js">import { ThirtySixChambers } from &quot;wu/tang/clan&quot;;
</code></pre>
<p>If a <code>module</code> attribute is not present, then the global scope is used
instead. For example,</p>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
#[wasm_bindgen]
extern &quot;C&quot; {
fn illmatic() -&gt; u32;
}
#}</code></pre></pre>
<p>generates JavaScript import glue like:</p>
<pre><code class="language-js">let illmatic = this.illmatic;
</code></pre>
<p>Note that if the string specified with <code>module</code> starts with <code>./</code>, <code>../</code>, or <code>/</code>
then it's interpreted as a path to a <a href="reference/attributes/on-js-imports/../../js-snippets.html">local JS snippet</a>.
If this doesn't work for your use case you might be interested in the
<a href="reference/attributes/on-js-imports/raw_module.html"><code>raw_module</code> attribute</a></p>
<h1><a class="header" href="#raw_module--blah" id="raw_module--blah"><code>raw_module = &quot;blah&quot;</code></a></h1>
<p>This attribute performs exactly the same purpose as the <a href="reference/attributes/on-js-imports/module.html"><code>module</code>
attribute</a> on JS imports, but it does not attempt to interpret
paths starting with <code>./</code>, <code>../</code>, or <code>/</code> as JS snippets. For example:</p>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
#[wasm_bindgen(raw_module = &quot;./some/js/file.js&quot;)]
extern &quot;C&quot; {
fn the_function();
}
#}</code></pre></pre>
<p>Note that if you use this attribute with a relative or absolute path, it's
likely up to the final bundler or project to assign meaning to that path. This
typically means that the JS file or module will be resolved relative to the
final location of the wasm file itself. That means that <code>raw_module</code> is likely
unsuitable for libraries on crates.io, but may be usable within end-user
applications.</p>
<h1><a class="header" href="#static_method_of--blah" id="static_method_of--blah"><code>static_method_of = Blah</code></a></h1>
<p>The <code>static_method_of</code> attribute allows one to specify that an imported function
is a static method of the given imported JavaScript class. For example, to bind
to JavaScript's <code>Date.now()</code> static method, one would use this attribute:</p>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
#[wasm_bindgen]
extern &quot;C&quot; {
type Date;
#[wasm_bindgen(static_method_of = Date)]
pub fn now() -&gt; f64;
}
#}</code></pre></pre>
<p>The <code>now</code> function becomes a static method of the imported type in the Rust
bindings as well:</p>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
let instant = Date::now();
#}</code></pre></pre>
<p>This is similar to the <code>js_namespace</code> attribute, but the usage from within Rust
is different since the method also becomes a static method of the imported type.
Additionally this attribute also specifies that the <code>this</code> parameter when
invoking the method is expected to be the JS class, e.g. always invoked as
<code>Date.now()</code> instead of <code>const x = Date.now; x()</code>.</p>
<h1><a class="header" href="#structural" id="structural"><code>structural</code></a></h1>
<blockquote>
<p><strong>Note</strong>: As of <a href="https://rustwasm.github.io/rfcs/005-structural-and-deref.html">RFC 5</a> this attribute is the default for all imported
functions. This attribute is largely ignored today and is only retained for
backwards compatibility and learning purposes.</p>
<p>The inverse of this attribute, <a href="reference/attributes/on-js-imports/final.html">the <code>final</code>
attribute</a> is more functionally interesting than
<code>structural</code> (as <code>structural</code> is simply the default)</p>
</blockquote>
<p>The <code>structural</code> flag can be added to <code>method</code> annotations, indicating that the
method being accessed (or property with getters/setters) should be accessed in a
structural, duck-type-y fashion. Rather than walking the constructor's prototype
chain once at load time and caching the property result, the prototype chain is
dynamically walked on every access.</p>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
#[wasm_bindgen]
extern &quot;C&quot; {
type Duck;
#[wasm_bindgen(method, structural)]
fn quack(this: &amp;Duck);
#[wasm_bindgen(method, getter, structural)]
fn is_swimming(this: &amp;Duck) -&gt; bool;
}
#}</code></pre></pre>
<p>The constructor for the type here, <code>Duck</code>, is not required to exist in
JavaScript (it's not referenced). Instead <code>wasm-bindgen</code> will generate shims
that will access the passed in JavaScript value's <code>quack</code> method or its
<code>is_swimming</code> property.</p>
<pre><code class="language-js">// Without `structural`, get the method directly off the prototype at load time:
const Duck_prototype_quack = Duck.prototype.quack;
function quack(duck) {
Duck_prototype_quack.call(duck);
}
// With `structural`, walk the prototype chain on every access:
function quack(duck) {
duck.quack();
}
</code></pre>
<h1><a class="header" href="#variadic-parameters" id="variadic-parameters">Variadic Parameters</a></h1>
<p>In javascript, both the types of function arguments, and the number of function arguments are
dynamic. For example</p>
<pre><code class="language-js">function sum(...rest) {
let i;
// the old way
let old_way = 0;
for (i=0; i&lt;arguments.length; i++) {
old_way += arguments[i];
}
// the new way
let new_way = 0;
for (i=0; i&lt;rest.length; i++) {
new_way += rest[i];
}
// both give the same answer
assert(old_way === new_way);
return new_way;
}
</code></pre>
<p>This function doesn't translate directly into rust, since we don't currently support variadic
arguments on the wasm target. To bind to it, we use a slice as the last argument, and annotate the
function as variadic:</p>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
#[wasm_bindgen]
extern &quot;C&quot; {
#[wasm_bindgen(variadic)]
fn sum(args: &amp;[i32]) -&gt; i32;
}
#}</code></pre></pre>
<p>when we call this function, the last argument will be expanded as the javascript expects.</p>
<h1><a class="header" href="#vendor-prefixed-apis" id="vendor-prefixed-apis">Vendor-prefixed APIs</a></h1>
<p>On the web new APIs often have vendor prefixes while they're in an experimental
state. For example the <code>AudioContext</code> API is known as <code>webkitAudioContext</code> in
Safari at the time of this writing. The <code>vendor_prefix</code> attribute indicates
these alternative names, which are used if the normal name isn't defined.</p>
<p>For example to use <code>AudioContext</code> you might do:</p>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
#[wasm_bindgen]
extern &quot;C&quot; {
#[wasm_bindgen(vendor_prefix = webkit)]
type AudioContext;
// methods on `AudioContext` ...
}
#}</code></pre></pre>
<p>Whenever <code>AudioContext</code> is used it'll use <code>AudioContext</code> if the global namespace
defines it or alternatively it'll fall back to <code>webkitAudioContext</code>.</p>
<p>Note that <code>vendor_prefix</code> cannot be used with <code>module = &quot;...&quot;</code> or
<code>js_namespace = ...</code>, so it's basically limited to web-platform APIs today.</p>
<h1><a class="header" href="#wasm_bindgen-on-rust-exports" id="wasm_bindgen-on-rust-exports"><code>#[wasm_bindgen]</code> on Rust Exports</a></h1>
<p>This section enumerates the attributes available for customizing bindings for
Rust functions and <code>struct</code>s exported to JavaScript.</p>
<h1><a class="header" href="#constructor-1" id="constructor-1"><code>constructor</code></a></h1>
<p>When attached to a Rust &quot;constructor&quot; it will make the generated JavaScript
bindings callable as <code>new Foo()</code>.</p>
<p>For example, consider this exported Rust type and <code>constructor</code> annotation:</p>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
#[wasm_bindgen]
pub struct Foo {
contents: u32,
}
#[wasm_bindgen]
impl Foo {
#[wasm_bindgen(constructor)]
pub fn new() -&gt; Foo {
Foo { contents: 0 }
}
pub fn get_contents(&amp;self) -&gt; u32 {
self.contents
}
}
#}</code></pre></pre>
<p>This can be used in JavaScript as:</p>
<pre><code class="language-js">import { Foo } from './my_module';
const f = new Foo();
console.log(f.get_contents());
</code></pre>
<h1><a class="header" href="#js_name--blah-1" id="js_name--blah-1"><code>js_name = Blah</code></a></h1>
<p>The <code>js_name</code> attribute can be used to export a different name in JS than what
something is named in Rust. It can be applied to both exported Rust functions
and types.</p>
<p>For example, this is often used to convert between Rust's snake-cased
identifiers into JavaScript's camel-cased identifiers:</p>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
#[wasm_bindgen(js_name = doTheThing)]
pub fn do_the_thing() -&gt; u32 {
42
}
#}</code></pre></pre>
<p>This can be used in JavaScript as:</p>
<pre><code class="language-js">import { doTheThing } from './my_module';
const x = doTheThing();
console.log(x);
</code></pre>
<p>Like imports, <code>js_name</code> can also be used to rename types exported to JS:</p>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
#[wasm_bindgen(js_name = Foo)]
pub struct JsFoo {
// ..
}
#}</code></pre></pre>
<p>to be accessed like:</p>
<pre><code class="language-js">import { Foo } from './my_module';
// ...
</code></pre>
<p>Note that attaching methods to the JS class <code>Foo</code> should be done via the
<a href="reference/attributes/on-rust-exports/js_class.html"><code>js_class</code> attribute</a>:</p>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
#[wasm_bindgen(js_name = Foo)]
pub struct JsFoo { /* ... */ }
#[wasm_bindgen(js_class = Foo)]
impl JsFoo {
// ...
}
#}</code></pre></pre>
<h1><a class="header" href="#readonly" id="readonly"><code>readonly</code></a></h1>
<p>When attached to a <code>pub</code> struct field this indicates that it's read-only from
JavaScript, and a setter will not be generated and exported to JavaScript.</p>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
#[wasm_bindgen]
pub fn make_foo() -&gt; Foo {
Foo {
first: 10,
second: 20,
}
}
#[wasm_bindgen]
pub struct Foo {
pub first: u32,
#[wasm_bindgen(readonly)]
pub second: u32,
}
#}</code></pre></pre>
<p>Here the <code>first</code> field will be both readable and writable from JS, but the
<code>second</code> field will be a <code>readonly</code> field in JS where the setter isn't
implemented and attempting to set it will throw an exception.</p>
<pre><code class="language-js">import { make_foo } from &quot;./my_module&quot;;
const foo = make_foo();
// Can both get and set `first`.
foo.first = 99;
console.log(foo.first);
// Can only get `second`.
console.log(foo.second);
</code></pre>
<h1><a class="header" href="#skip" id="skip"><code>skip</code></a></h1>
<p>When attached to a <code>pub</code> struct field this indicates that field will not be exposed to JavaScript,
and neither getter nor setter will be generated in ES6 class.</p>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
pub struct Foo {
pub bar: u32,
#[wasm_bindgen(skip)]
pub baz: u32,
}
#[wasm_bindgen]
impl Foo {
pub fn new() -&gt; Self {
Foo {
bar: 1,
baz: 2
}
}
}
#}</code></pre></pre>
<p>Here the <code>bar</code> field will be both readable and writable from JS, but the
<code>baz</code> field will be <code>undefined</code> in JS.</p>
<pre><code class="language-js">import('./pkg/').then(rust =&gt; {
let foo = rust.Foo.new();
// bar is accessible by getter
console.log(foo.bar);
// field marked with `skip` is undefined
console.log(foo.baz);
// you can shadow it
foo.baz = 45;
// so accessing by getter will return `45`
// but it won't affect real value in rust memory
console.log(foo.baz);
});
</code></pre>
<h1><a class="header" href="#start" id="start"><code>start</code></a></h1>
<p>When attached to a <code>pub</code> function this attribute will configure the <code>start</code>
section of the wasm executable to be emitted, executing the tagged function as
soon as the wasm module is instantiated.</p>
<pre><pre class="playpen"><code class="language-rust">#[wasm_bindgen(start)]
pub fn main() {
// executed automatically ...
}
</code></pre></pre>
<p>The <code>start</code> section of the wasm executable will be configured to execute the
<code>main</code> function here as soon as it can. Note that due to various practical
limitations today the start section of the executable may not literally point to
<code>main</code>, but the <code>main</code> function here should be started up automatically when the
wasm module is loaded.</p>
<p>There's a few caveats to be aware of when using the <code>start</code> attribute:</p>
<ul>
<li>The <code>start</code> function must take no arguments and must either return <code>()</code> or
<code>Result&lt;(), JsValue&gt;</code></li>
<li>Only one <code>start</code> function can be placed into a module, including its
dependencies. If more than one is specified then <code>wasm-bindgen</code> will fail when
the CLI is run. It's recommended that only applications use this attribute.</li>
<li>The <code>start</code> function will not be executed when testing.</li>
<li>If you're experimenting with WebAssembly threads, the <code>start</code> function is
executed <em>once per thread</em>, not once globally!</li>
<li>Note that the <code>start</code> function is relatively new, so if you find any bugs with
it, please feel free to report an issue!</li>
</ul>
<h1><a class="header" href="#typescript_custom_section" id="typescript_custom_section"><code>typescript_custom_section</code></a></h1>
<p>When added to a <code>const</code> <code>&amp;'static str</code>, it will append the contents of the
string to the <code>.d.ts</code> file exported by <code>wasm-bindgen-cli</code> (when the
<code>--typescript</code> flag is enabled).</p>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
#[wasm_bindgen(typescript_custom_section)]
const TS_APPEND_CONTENT: &amp;'static str = r#&quot;
export type Coords = { &quot;latitude&quot;: number, &quot;longitude&quot;: number, };
&quot;#;
#}</code></pre></pre>
<p>The primary target for this feature is for code generation. For example, you
can author a macro that allows you to export a TypeScript definition alongside
the definition of a struct or Rust type.</p>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
#[derive(MyTypescriptExport)]
struct Coords {
latitude: u32,
longitude: u32,
}
#}</code></pre></pre>
<p>The proc_derive_macro &quot;MyTypescriptExport&quot; can export its own
<code>#[wasm_bindgen(typescript_custom_section)]</code> section, which would then be
picked up by wasm-bindgen-cli. This would be equivalent to the contents of
the TS_APPEND_CONTENT string in the first example.</p>
<p>This feature allows plain data objects to be typechecked in Rust and in
TypeScript by outputing a type definition generated at compile time.</p>
<h1><a class="header" href="#getter-and-setter-1" id="getter-and-setter-1"><code>getter</code> and <code>setter</code></a></h1>
<p>The <code>getter</code> and <code>setter</code> attributes can be used in Rust <code>impl</code> blocks to define
properties in JS that act like getters and setters of a field. For example:</p>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
#[wasm_bindgen]
pub struct Baz {
field: i32,
}
#[wasm_bindgen]
impl Baz {
#[wasm_bindgen(constructor)]
pub fn new(field: i32) -&gt; Baz {
Baz { field }
}
#[wasm_bindgen(getter)]
pub fn field(&amp;self) -&gt; i32 {
self.field
}
#[wasm_bindgen(setter)]
pub fn set_field(&amp;mut self, field: i32) {
self.field = field;
}
}
#}</code></pre></pre>
<p>Can be combined in <code>JavaScript</code> like in this snippet:</p>
<pre><code class="language-js">const obj = new Baz(3);
assert.equal(obj.field, 3);
obj.field = 4;
assert.equal(obj.field, 4);
</code></pre>
<p>You can also configure the name of the property that is exported in JS like so:</p>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
#[wasm_bindgen]
impl Baz {
#[wasm_bindgen(getter = anotherName)]
pub fn field(&amp;self) -&gt; i32 {
self.field
}
#[wasm_bindgen(setter = anotherName)]
pub fn set_field(&amp;mut self, field: i32) {
self.field = field;
}
}
#}</code></pre></pre>
<p>Getters are expected to take no arguments other than <code>&amp;self</code> and return the
field's type. Setters are expected to take one argument other than <code>&amp;mut self</code>
(or <code>&amp;self</code>) and return no values.</p>
<p>The name for a <code>getter</code> is by default inferred from the function name it's
attached to. The default name for a <code>setter</code> is the function's name minus the
<code>set_</code> prefix, and if <code>set_</code> isn't a prefix of the function it's an error to not
provide the name explicitly.</p>
<h1><a class="header" href="#inspectable" id="inspectable"><code>inspectable</code></a></h1>
<p>By default, structs exported from Rust become JavaScript classes with a single <code>ptr</code> property. All other properties are implemented as getters, which are not displayed when calling <code>toJSON</code>.</p>
<p>The <code>inspectable</code> attribute can be used on Rust structs to provide a <code>toJSON</code> and <code>toString</code> implementation that display all readable fields. For example:</p>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
#[wasm_bindgen(inspectable)]
pub struct Baz {
pub field: i32,
private: i32,
}
#[wasm_bindgen]
impl Baz {
#[wasm_bindgen(constructor)]
pub fn new(field: i32) -&gt; Baz {
Baz { field, private: 13 }
}
}
#}</code></pre></pre>
<p>Provides the following behavior as in this JavaScript snippet:</p>
<pre><code class="language-js">const obj = new Baz(3);
assert.deepStrictEqual(obj.toJSON(), { field: 3 });
obj.field = 4;
assert.strictEqual(obj.toString(), '{&quot;field&quot;:4}');
</code></pre>
<p>One or both of these implementations can be overridden as desired. Note that the generated <code>toString</code> calls <code>toJSON</code> internally, so overriding <code>toJSON</code> will affect its output as a side effect.</p>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
#[wasm_bindgen]
impl Baz {
#[wasm_bindgen(js_name = toJSON)]
pub fn to_json(&amp;self) -&gt; i32 {
self.field
}
#[wasm_bindgen(js_name = toString)]
pub fn to_string(&amp;self) -&gt; String {
format!(&quot;Baz: {}&quot;, self.field)
}
}
#}</code></pre></pre>
<p>Note that the output of <code>console.log</code> will remain unchanged and display only the <code>ptr</code> field in browsers. It is recommended to call <code>toJSON</code> or <code>JSON.stringify</code> in these situations to aid with logging or debugging. Node.js does not suffer from this limitation, see the section below.</p>
<h2><a class="header" href="#inspectable-classes-in-nodejs" id="inspectable-classes-in-nodejs"><code>inspectable</code> Classes in Node.js</a></h2>
<p>When the <code>nodejs</code> target is used, an additional <code>[util.inspect.custom]</code> implementation is provided which calls <code>toJSON</code> internally. This method is used for <code>console.log</code> and similar functions to display all readable fields of the Rust struct.</p>
<h1><a class="header" href="#skip_typescript" id="skip_typescript"><code>skip_typescript</code></a></h1>
<p>By default, Rust exports exposed to JavaScript will generate TypeScript definitions (unless <code>--no-typescript</code> is used). The <code>skip_typescript</code> attribute can be used to disable type generation per function, enum, struct, or field. For example:</p>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
#[wasm_bindgen(skip_typescript)]
pub enum MyHiddenEnum {
One,
Two,
Three
}
#[wasm_bindgen]
pub struct MyPoint {
pub x: u32,
#[wasm_bindgen(skip_typescript)]
pub y: u32,
}
#[wasm_bindgen]
impl MyPoint {
#[wasm_bindgen(skip_typescript)]
pub fn stringify(&amp;self) -&gt; String {
format!(&quot;({}, {})&quot;, self.x, self.y)
}
}
#}</code></pre></pre>
<p>Will generate the following <code>.d.ts</code> file:</p>
<pre><code class="language-ts">/* tslint:disable */
/* eslint-disable */
export class MyPoint {
free(): void;
x: number;
}
</code></pre>
<p>When combined with <a href="reference/attributes/on-rust-exports/typescript_custom_section.html">the <code>typescript_custom_section</code> attribute</a>, this can be used to manually specify more specific function types instead of using the generated definitions.</p>
<h1><a class="header" href="#typescript_type" id="typescript_type">typescript_type</a></h1>
<p>The <code>typescript_type</code> allows us to use typescript declarations in <code>typescript_custom_section</code> as arguments for rust functions! For example:</p>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
#[wasm_bindgen(typescript_custom_section)]
const ITEXT_STYLE: &amp;'static str = r#&quot;
interface ITextStyle {
bold: boolean;
italic: boolean;
size: number;
}
&quot;#;
#[wasm_bindgen]
extern &quot;C&quot; {
#[wasm_bindgen(typescript_type = &quot;ITextStyle&quot;)]
pub type ITextStyle;
}
#[wasm_bindgen]
#[derive(Default)]
pub struct TextStyle {
pub bold: bool,
pub italic: bool,
pub size: i32,
}
#[wasm_bindgen]
impl TextStyle {
#[wasm_bindgen(constructor)]
pub fn new(_i: ITextStyle) -&gt; TextStyle {
// parse JsValue
TextStyle::default()
}
pub fn optional_new(_i: Option&lt;ITextStyle&gt;) -&gt; TextStyle {
// parse JsValueo
TextStyle::default()
}
}
#}</code></pre></pre>
<p>We can write our <code>typescript</code> code like: </p>
<pre><code class="language-ts">import { ITextStyle, TextStyle } from &quot;./my_awesome_module&quot;;
const style: TextStyle = new TextStyle({
bold: true,
italic: true,
size: 42,
});
const optional_style: TextStyle = TextStyle.optional_new();
</code></pre>
<h1><a class="header" href="#the-web-sys-crate" id="the-web-sys-crate">The <code>web-sys</code> Crate</a></h1>
<p><a href="https://crates.io/crates/web-sys">The <code>web-sys</code> crate</a> provides raw <code>wasm-bindgen</code> imports for all of the Web's
APIs. This includes:</p>
<ul>
<li><code>window.fetch</code></li>
<li><code>Node.prototype.appendChild</code></li>
<li>WebGL</li>
<li>WebAudio</li>
<li>and many more!</li>
</ul>
<p>It's sort of like the <code>libc</code> crate, but for the Web.</p>
<p>It does <em>not</em> include the JavaScript APIs that are guaranteed to exist in all
standards-compliant ECMAScript environments, such as <code>Array</code>, <code>Date</code>, and
<code>eval</code>. Bindings for these APIs can be found in <a href="https://crates.io/crates/js-sys">the <code>js-sys</code> crate</a>.</p>
<h2><a class="header" href="#api-documentation" id="api-documentation">API Documentation</a></h2>
<p><a href="https://rustwasm.github.io/wasm-bindgen/api/web_sys/"><strong>Read the <code>web-sys</code> API documentation here!</strong></a></p>
<h1><a class="header" href="#using-web-sys" id="using-web-sys">Using <code>web-sys</code></a></h1>
<h2><a class="header" href="#add-web-sys-as-a-dependency-to-your-cargotoml" id="add-web-sys-as-a-dependency-to-your-cargotoml">Add <code>web-sys</code> as a dependency to your <code>Cargo.toml</code></a></h2>
<pre><code class="language-toml">[dependencies]
wasm-bindgen = &quot;0.2&quot;
[dependencies.web-sys]
version = &quot;0.3&quot;
features = [
]
</code></pre>
<h2><a class="header" href="#enable-the-cargo-features-for-the-apis-youre-using" id="enable-the-cargo-features-for-the-apis-youre-using">Enable the cargo features for the APIs you're using</a></h2>
<p>To keep build times super speedy, <a href="web-sys/./cargo-features.html"><code>web-sys</code> gates each Web interface behind a
cargo feature</a>. Find the type or method you want to use
in the <a href="https://rustwasm.github.io/wasm-bindgen/api/web_sys/">API documentation</a>; it will list the features that must be enabled
to access that API.</p>
<p>For example, if we're looking for <a href="https://developer.mozilla.org/en-US/docs/Web/API/window/resizeTo">the <code>window.resizeTo</code>
function</a>, we would <a href="https://rustwasm.github.io/wasm-bindgen/api/web_sys/?search=resizeTo">search for <code>resizeTo</code> in the API
documentation</a>. We would find <a href="https://rustwasm.github.io/wasm-bindgen/api/web_sys/struct.Window.html#method.resize_to">the
<code>web_sys::Window::resize_to</code> function</a>, which requires the
<code>Window</code> feature. To get access to that function, we enable the <code>Window</code> feature
in <code>Cargo.toml</code>:</p>
<pre><code class="language-toml">[dependencies.web-sys]
version = &quot;0.3&quot;
features = [
&quot;Window&quot;
]
</code></pre>
<h2><a class="header" href="#call-the-method" id="call-the-method">Call the method!</a></h2>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
extern crate web_sys;
extern crate wasm_bindgen;
use wasm_bindgen::prelude::*;
use web_sys::Window;
#[wasm_bindgen]
pub fn make_the_window_small() {
// Resize the window to 500px by 500px.
let window = web_sys::window().unwrap();
window.resize_to(500, 500)
.expect(&quot;could not resize the window&quot;);
}
#}</code></pre></pre>
<h1><a class="header" href="#cargo-features-in-web-sys" id="cargo-features-in-web-sys">Cargo Features in <code>web-sys</code></a></h1>
<p>To keep <code>web-sys</code> building as fast as possible, there is a cargo feature for
every type defined in <code>web-sys</code>. To access that type, you must enable its
feature. To access a method, you must enable the feature for its <code>self</code> type and
the features for each of its argument types. In the <a href="https://rustwasm.github.io/wasm-bindgen/api/web_sys">API documentation</a>, every
method lists the features that are required to enable it.</p>
<p>For example, <a href="https://rustwasm.github.io/wasm-bindgen/api/web_sys/struct.WebGlRenderingContext.html#method.compile_shader">the <code>WebGlRenderingContext::compile_shader</code> function</a> requires these features:</p>
<ul>
<li><code>WebGlRenderingContext</code>, because that is the method's <code>self</code> type</li>
<li><code>WebGlShader</code>, because it takes an argument of that type</li>
</ul>
<h1><a class="header" href="#function-overloads" id="function-overloads">Function Overloads</a></h1>
<p>Many Web APIs are overloaded to take different types of arguments or to skip
arguments completely. <code>web-sys</code> contains multiple bindings for these functions
that each specialize to a particular overload and set of argument types.</p>
<p>For example, <a href="https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch">the <code>fetch</code> API</a> can be given a URL string, or a
<code>Request</code> object, and it might also optionally be given a <code>RequestInit</code> options
object. Therefore, we end up with these <code>web-sys</code> functions that all bind to the
<code>window.fetch</code> function:</p>
<ul>
<li><a href="https://rustwasm.github.io/wasm-bindgen/api/web_sys/struct.Window.html#method.fetch_with_str"><code>Window::fetch_with_str</code></a></li>
<li><a href="https://rustwasm.github.io/wasm-bindgen/api/web_sys/struct.Window.html#method.fetch_with_request"><code>Window::fetch_with_request</code></a></li>
<li><a href="https://rustwasm.github.io/wasm-bindgen/api/web_sys/struct.Window.html#method.fetch_with_str_and_init"><code>Window::fetch_with_str_and_init</code></a></li>
<li><a href="https://rustwasm.github.io/wasm-bindgen/api/web_sys/struct.Window.html#method.fetch_with_request_and_init"><code>Window::fetch_with_request_and_init</code></a></li>
</ul>
<p>Note that different overloads can use different interfaces, and therefore can
require different sets of cargo features to be enabled.</p>
<h1><a class="header" href="#type-translations-in-web-sys" id="type-translations-in-web-sys">Type Translations in <code>web-sys</code></a></h1>
<p>Most of the types specified in <a href="https://heycam.github.io/webidl/">WebIDL (the interface definition language for
all Web APIs)</a> have relatively straightforward translations into
<code>web-sys</code>, but it's worth calling out a few in particular:</p>
<ul>
<li>
<p><code>BufferSource</code> and <code>ArrayBufferView</code> - these two types show up in a number of
APIs that generally deal with a buffer of bytes. We bind them in <code>web-sys</code>
with two different types, <code>js_sys::Object</code> and <code>&amp;mut [u8]</code>. Using
<code>js_sys::Object</code> allows passing in arbitrary JS values which represent a view
of bytes (like any typed array object), and <code>&amp;mut [u8]</code> allows using a raw
slice in Rust. Unfortunately we must pessimistically assume that JS will
modify all slices as we don't currently have information of whether they're
modified or not.</p>
</li>
<li>
<p>Callbacks are all represented as <code>js_sys::Function</code>. This means that all
callbacks going through <code>web-sys</code> are a raw JS value. You can work with this
by either juggling actual <code>js_sys::Function</code> instances or you can create a
<code>Closure&lt;FnMut(...)&gt;</code>, extract the underlying <code>JsValue</code> with <code>as_ref</code>, and
then use <code>JsCast::unchecked_ref</code> to convert it to a <code>js_sys::Function</code>.</p>
</li>
</ul>
<h1><a class="header" href="#inheritance-in-web-sys" id="inheritance-in-web-sys">Inheritance in <code>web-sys</code></a></h1>
<p>Inheritance between JS classes is the bread and butter of how the DOM works on
the web, and as a result it's quite important for <code>web-sys</code> to provide access to
this inheritance hierarchy as well! There are few ways you can access the
inheritance hierarchy when using <code>web-sys</code>.</p>
<h3><a class="header" href="#accessing-parent-classes-using-deref" id="accessing-parent-classes-using-deref">Accessing parent classes using <code>Deref</code></a></h3>
<p>Like smart pointers in Rust, all types in <code>web_sys</code> implement <code>Deref</code> to their
parent JS class. This means, for example, if you have a <code>web_sys::Element</code> you
can create a <code>web_sys::Node</code> from that implicitly:</p>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
let element: &amp;Element = ...;
element.append_child(..); // call a method on `Node`
method_expecting_a_node(&amp;element); // coerce to `&amp;Node` implicitly
let node: &amp;Node = &amp;element; // explicitly coerce to `&amp;Node`
#}</code></pre></pre>
<p>Using <code>Deref</code> allows ergonomic transitioning up the inheritance hierarchy to the
parent class and beyond, giving you access to all the methods using the <code>.</code>
operator.</p>
<h3><a class="header" href="#accessing-parent-classes-using-asref" id="accessing-parent-classes-using-asref">Accessing parent classes using <code>AsRef</code></a></h3>
<p>In addition to <code>Deref</code>, the <code>AsRef</code> trait is implemented for all types in
<code>web_sys</code> for all types in the inheritance hierarchy. For example for the
<code>HtmlAnchorElement</code> type you'll find:</p>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
impl AsRef&lt;HtmlElement&gt; for HtmlAnchorElement
impl AsRef&lt;Element&gt; for HtmlAnchorElement
impl AsRef&lt;Node&gt; for HtmlAnchorElement
impl AsRef&lt;EventTarget&gt; for HtmlAnchorElement
impl AsRef&lt;Object&gt; for HtmlAnchorElement
impl AsRef&lt;JsValue&gt; for HtmlAnchorElement
#}</code></pre></pre>
<p>You can use <code>.as_ref()</code> to explicitly get a reference to any parent class from
from a type in <code>web_sys</code>. Note that because of the number of <code>AsRef</code>
implementations you'll likely need to have type inference guidance as well.</p>
<h3><a class="header" href="#accessing-child-clases-using-jscast" id="accessing-child-clases-using-jscast">Accessing child clases using <code>JsCast</code></a></h3>
<p>Finally the <code>wasm_bindgen::JsCast</code> trait can be used to implement all manner of
casts between types. It supports static unchecked casts between types as well as
dynamic runtime-checked casts (using <code>instanceof</code>) between types.</p>
<p>More documentation about this can be found <a href="https://docs.rs/wasm-bindgen/0.2/wasm_bindgen/trait.JsCast.html">on the trait itself</a></p>
<h1><a class="header" href="#unstable-apis" id="unstable-apis">Unstable APIs</a></h1>
<p>It's common for browsers to implement parts of a web API while the specification
for that API is still being written. The API may require frequent changes as the
specification continues to be developed, so the WebIDL is relatively unstable.</p>
<p>This causes some challenges for <code>web-sys</code> because it means <code>web-sys</code> would have
to make breaking API changes whenever the WebIDL changes. It also means that
previously published <code>web-sys</code> versions would be invalid, because the browser
API may have been changed to match the updated WebIDL.</p>
<p>To avoid frequent breaking changes for unstable APIs, <code>web-sys</code> hides all
unstable APIs through an attribute that looks like:</p>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
#[cfg(web_sys_unstable_apis)]
pub struct Foo;
#}</code></pre></pre>
<p>By hiding unstable APIs through an attribute, it's necessary for crates to
explicitly opt-in to these reduced stability guarantees in order to use these
APIs. Specifically, these APIs do not follow semver and may break whenever the
WebIDL changes.</p>
<p>Crates can opt-in to unstable APIs at compile-time by passing the <code>cfg</code> flag
<code>web_sys_unstable_apis</code>. Typically the <code>RUSTFLAGS</code> environment variable is used
to do this. For example:</p>
<pre><code class="language-bash">RUSTFLAGS=--cfg=web_sys_unstable_apis cargo run
</code></pre>
<h1><a class="header" href="#testing-on-wasm32-unknown-unknown-with-wasm-bindgen-test" id="testing-on-wasm32-unknown-unknown-with-wasm-bindgen-test">Testing on <code>wasm32-unknown-unknown</code> with <code>wasm-bindgen-test</code></a></h1>
<p>The <code>wasm-bindgen-test</code> crate is an experimental test harness for Rust programs
compiled to wasm using <code>wasm-bindgen</code> and the <code>wasm32-unknown-unknown</code>
target.</p>
<h2><a class="header" href="#goals" id="goals">Goals</a></h2>
<ul>
<li>
<p>Write tests for wasm as similar as possible to how you normally would write
<code>#[test]</code>-style unit tests for native targets.</p>
</li>
<li>
<p>Run the tests with the usual <code>cargo test</code> command but with an explicit wasm
target:</p>
<pre><code>cargo test --target wasm32-unknown-unknown
</code></pre>
</li>
</ul>
<h1><a class="header" href="#using-wasm-bindgen-test" id="using-wasm-bindgen-test">Using <code>wasm-bindgen-test</code></a></h1>
<h3><a class="header" href="#add-wasm-bindgen-test-to-your-cargotomls-dev-dependencies" id="add-wasm-bindgen-test-to-your-cargotomls-dev-dependencies">Add <code>wasm-bindgen-test</code> to Your <code>Cargo.toml</code>'s <code>[dev-dependencies]</code></a></h3>
<pre><code class="language-toml">[dev-dependencies]
wasm-bindgen-test = &quot;0.3.0&quot;
</code></pre>
<p>Note that the <code>0.3.0</code> track of <code>wasm-bindgen-test</code> supports Rust 1.39.0+, which
is currently the nightly channel (as of 2019-09-05). If you want support for
older compilers use the <code>0.2.*</code> track of <code>wasm-bindgen-test</code>.</p>
<h2><a class="header" href="#write-some-tests" id="write-some-tests">Write Some Tests</a></h2>
<p>Create a <code>$MY_CRATE/tests/wasm.rs</code> file:</p>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
extern crate wasm_bindgen_test;
use wasm_bindgen_test::*;
#[wasm_bindgen_test]
fn pass() {
assert_eq!(1, 1);
}
#[wasm_bindgen_test]
fn fail() {
assert_eq!(1, 2);
}
#}</code></pre></pre>
<p>Writing tests is the same as normal Rust <code>#[test]</code>s, except we are using the
<code>#[wasm_bindgen_test]</code> attribute.</p>
<p>One other difference is that the tests <strong>must</strong> be in the root of the crate, or
within a <code>pub mod</code>. Putting them inside a private module will not work.</p>
<h2><a class="header" href="#execute-your-tests" id="execute-your-tests">Execute Your Tests</a></h2>
<p>Run the tests with <code>wasm-pack test</code>. By default, the tests are generated to
target Node.js, but you can <a href="wasm-bindgen-test/./browsers.html">configure tests to run inside headless
browsers</a> as well.</p>
<pre><code class="language-shell">$ wasm-pack test --node
Finished dev [unoptimized + debuginfo] target(s) in 0.11s
Running /home/.../target/wasm32-unknown-unknown/debug/deps/wasm-4a309ffe6ad80503.wasm
running 2 tests
test wasm::pass ... ok
test wasm::fail ... FAILED
failures:
---- wasm::fail output ----
error output:
panicked at 'assertion failed: `(left == right)`
left: `1`,
right: `2`', crates/test/tests/wasm.rs:14:5
JS exception that was thrown:
RuntimeError: unreachable
at __rust_start_panic (wasm-function[1362]:33)
at rust_panic (wasm-function[1357]:30)
at std::panicking::rust_panic_with_hook::h56e5e464b0e7fc22 (wasm-function[1352]:444)
at std::panicking::continue_panic_fmt::had70ba48785b9a8f (wasm-function[1350]:122)
at std::panicking::begin_panic_fmt::h991e7d1ca9bf9c0c (wasm-function[1351]:95)
at wasm::fail::ha4c23c69dfa0eea9 (wasm-function[88]:477)
at core::ops::function::FnOnce::call_once::h633718dad359559a (wasm-function[21]:22)
at wasm_bindgen_test::__rt::Context::execute::h2f669104986475eb (wasm-function[13]:291)
at __wbg_test_fail_1 (wasm-function[87]:57)
at module.exports.__wbg_apply_2ba774592c5223a7 (/home/alex/code/wasm-bindgen/target/wasm32-unknown-unknown/wbg-tmp/wasm-4a309ffe6ad80503.js:61:66)
failures:
wasm::fail
test result: FAILED. 1 passed; 1 failed; 0 ignored
error: test failed, to rerun pass '--test wasm'
</code></pre>
<p>That's it!</p>
<hr />
<h2><a class="header" href="#appendix-using-wasm-bindgen-test-without-wasm-pack" id="appendix-using-wasm-bindgen-test-without-wasm-pack">Appendix: Using <code>wasm-bindgen-test</code> without <code>wasm-pack</code></a></h2>
<p><strong>⚠️ The recommended way to use <code>wasm-bindgen-test</code> is with <code>wasm-pack</code>, since it
will handle installing the test runner, installing a WebDriver client for your
browser, and informing <code>cargo</code> how to use the custom test runner.</strong> However, you
can also manage those tasks yourself, if you wish.</p>
<p>In addition to the steps above, you must also do the following.</p>
<h3><a class="header" href="#install-the-test-runner" id="install-the-test-runner">Install the Test Runner</a></h3>
<p>The test runner comes along with the main <code>wasm-bindgen</code> CLI tool. Make sure to
replace &quot;X.Y.Z&quot; with the same version of <code>wasm-bindgen</code> that you already have in
<code>Cargo.toml</code>!</p>
<pre><code class="language-shell">cargo install wasm-bindgen-cli --vers &quot;X.Y.Z&quot;
</code></pre>
<h3><a class="header" href="#configure-cargoconfig-to-use-the-test-runner" id="configure-cargoconfig-to-use-the-test-runner">Configure <code>.cargo/config</code> to use the Test Runner</a></h3>
<p>Add this to <code>$MY_CRATE/.cargo/config</code>:</p>
<pre><code class="language-toml">[target.wasm32-unknown-unknown]
runner = 'wasm-bindgen-test-runner'
</code></pre>
<h3><a class="header" href="#run-the-tests" id="run-the-tests">Run the Tests</a></h3>
<p>Run the tests by passing <code>--target wasm32-unknown-unknown</code> to <code>cargo test</code>:</p>
<pre><code>cargo test --target wasm32-unknown-unknown
</code></pre>
<h1><a class="header" href="#writing-asynchronous-tests" id="writing-asynchronous-tests">Writing Asynchronous Tests</a></h1>
<p>Not all tests can execute immediately and some may need to do &quot;blocking&quot; work
like fetching resources and/or other bits and pieces. To accommodate this
asynchronous tests are also supported through the <code>futures</code> and
<code>wasm-bindgen-futures</code> crates.</p>
<p>Writing an asynchronous test is pretty simple, just use an <code>async</code> function!
You'll also likely want to use the <code>wasm-bindgen-futures</code> crate to convert JS
promises to Rust futures.</p>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
use wasm_bindgen::prelude::*;
use wasm_bindgen_futures::JsFuture;
#[wasm_bindgen_test]
async fn my_async_test() {
// Create a promise that is ready on the next tick of the micro task queue.
let promise = js_sys::Promise::resolve(&amp;JsValue::from(42));
// Convert that promise into a future and make the test wait on it.
let x = JsFuture::from(promise).await.unwrap();
assert_eq!(x, 42);
}
#}</code></pre></pre>
<h2><a class="header" href="#rust-compiler-compatibility" id="rust-compiler-compatibility">Rust compiler compatibility</a></h2>
<p>Note that <code>async</code> functions are only supported in stable from Rust 1.39.0 and
beyond. As of the time of this writing (2019-09-05) this is the Nightly channel
of Rust.</p>
<p>If you're using the <code>futures</code> crate from crates.io in its 0.1 version then
you'll want to use the <code>0.3.*</code> version of <code>wasm-bindgen-futures</code> and the <code>0.2.8</code>
version of <code>wasm-bindgen-test</code>. In those modes you'll also need to use
<code>#[wasm_bindgen_test(async)]</code> instead of using an <code>async</code> function. In general
we'd recommend using the nightly version with <code>async</code> since the user experience
is much improved!</p>
<h1><a class="header" href="#testing-in-headless-browsers" id="testing-in-headless-browsers">Testing in Headless Browsers</a></h1>
<h2><a class="header" href="#configure-your-test-crate" id="configure-your-test-crate">Configure Your Test Crate</a></h2>
<p>Add this to the root of your test crate, e.g. <code>$MY_CRATE/tests/web.rs</code>:</p>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
use wasm_bindgen_test::wasm_bindgen_test_configure;
wasm_bindgen_test_configure!(run_in_browser);
#}</code></pre></pre>
<p>Note that although a particular test crate must target either headless browsers
or Node.js, you can have test suites for both Node.js and browsers for your
project by using multiple test crates. For example:</p>
<pre><code>$MY_CRATE/
`-- tests
|-- node.rs # The tests in this suite use the default Node.js.
`-- web.rs # The tests in this suite are configured for browsers.
</code></pre>
<h2><a class="header" href="#configuring-which-browser-is-used" id="configuring-which-browser-is-used">Configuring Which Browser is Used</a></h2>
<p>To control which browser is used for headless testing, use the appropriate flag
with <code>wasm-pack test</code>:</p>
<ul>
<li>
<p><code>wasm-pack test --chrome</code> — Run the tests in Chrome. This machine must
have Chrome installed.</p>
</li>
<li>
<p><code>wasm-pack test --firefox</code> — Run the tests in Firefox. This machine must
have Firefox installed.</p>
</li>
<li>
<p><code>wasm-pack test --safari</code> — Run the tests in Safari. This machine must
have Safari installed.</p>
</li>
</ul>
<p>If multiple browser flags are passed, the tests will be run under each browser.</p>
<h2><a class="header" href="#running-the-tests-in-the-headless-browser" id="running-the-tests-in-the-headless-browser">Running the Tests in the Headless Browser</a></h2>
<p>Once the tests are configured to run in a headless browser, just run <code>wasm-pack test</code> with the appropriate browser flags and <code>--headless</code>:</p>
<pre><code class="language-bash">wasm-pack test --headless --chrome --firefox --safari
</code></pre>
<h2><a class="header" href="#configuring-headless-browser-capabilities" id="configuring-headless-browser-capabilities">Configuring Headless Browser capabilities</a></h2>
<p>Add the file <code>webdriver.json</code> to the root of your crate. Each browser has own
section for capabilities. For example:</p>
<pre><code class="language-json">{
&quot;moz:firefoxOptions&quot;: {
&quot;prefs&quot;: {
&quot;media.navigator.streams.fake&quot;: true,
&quot;media.navigator.permission.disabled&quot;: true
},
&quot;args&quot;: []
},
&quot;goog:chromeOptions&quot;: {
&quot;args&quot;: [
&quot;--use-fake-device-for-media-stream&quot;,
&quot;--use-fake-ui-for-media-stream&quot;
]
}
}
</code></pre>
<p>Full list supported capabilities can be found:</p>
<ul>
<li>for Chrome - <a href="https://peter.sh/experiments/chromium-command-line-switches/">here</a></li>
<li>for Firefox - <a href="https://developer.mozilla.org/en-US/docs/Web/WebDriver/Capabilities/firefoxOptions">here</a></li>
</ul>
<p>Note that the <code>headless</code> argument is always enabled for both browsers.</p>
<h3><a class="header" href="#debugging-headless-browser-tests" id="debugging-headless-browser-tests">Debugging Headless Browser Tests</a></h3>
<p>Omitting the <code>--headless</code> flag will disable headless mode, and allow you to
debug failing tests in your browser's devtools.</p>
<hr />
<h2><a class="header" href="#appendix-testing-in-headless-browsers-without-wasm-pack" id="appendix-testing-in-headless-browsers-without-wasm-pack">Appendix: Testing in headless browsers without <code>wasm-pack</code></a></h2>
<p><strong>⚠️ The recommended way to use <code>wasm-bindgen-test</code> is with <code>wasm-pack</code>, since it
will handle installing the test runner, installing a WebDriver client for your
browser, and informing <code>cargo</code> how to use the custom test runner.</strong> However, you
can also manage those tasks yourself, if you wish.</p>
<h3><a class="header" href="#configuring-which-browser-is-used-1" id="configuring-which-browser-is-used-1">Configuring Which Browser is Used</a></h3>
<p>If one of the following environment variables is set, then the corresponding
WebDriver and browser will be used. If none of these environment variables are
set, then the <code>$PATH</code> is searched for a suitable WebDriver implementation.</p>
<h4><a class="header" href="#geckodriverpathtogeckodriver" id="geckodriverpathtogeckodriver"><code>GECKODRIVER=path/to/geckodriver</code></a></h4>
<p>Use Firefox for headless browser testing, and <code>geckodriver</code> as its
WebDriver.</p>
<p>The <code>firefox</code> binary must be on your <code>$PATH</code>.</p>
<p><a href="https://github.com/mozilla/geckodriver/releases">Get <code>geckodriver</code> here</a></p>
<h4><a class="header" href="#chromedriverpathtochromedriver" id="chromedriverpathtochromedriver"><code>CHROMEDRIVER=path/to/chromedriver</code></a></h4>
<p>Use Chrome for headless browser testing, and <code>chromedriver</code> as its
WebDriver.</p>
<p>The <code>chrome</code> binary must be on your <code>$PATH</code>.</p>
<p><a href="http://chromedriver.chromium.org/downloads">Get <code>chromedriver</code> here</a></p>
<h4><a class="header" href="#safaridriverpathtosafaridriver" id="safaridriverpathtosafaridriver"><code>SAFARIDRIVER=path/to/safaridriver</code></a></h4>
<p>Use Safari for headless browser testing, and <code>safaridriver</code> as its
WebDriver.</p>
<p>This is installed by default on Mac OS. It should be able to find your Safari
installation by default.</p>
<h3><a class="header" href="#running-the-tests-in-the-remote-headless-browser" id="running-the-tests-in-the-remote-headless-browser">Running the Tests in the Remote Headless Browser</a></h3>
<p>Tests can be run on a remote webdriver. To do this, the above environment
variables must be set as URL to the remote webdriver. For example:</p>
<pre><code>CHROMEDRIVER_REMOTE=http://remote.host/
</code></pre>
<h3><a class="header" href="#running-the-tests-in-the-headless-browser-1" id="running-the-tests-in-the-headless-browser-1">Running the Tests in the Headless Browser</a></h3>
<p>Once the tests are configured to run in a headless browser and the appropriate
environment variables are set, executing the tests for headless browsers is the
same as executing them for Node.js:</p>
<pre><code class="language-bash">cargo test --target wasm32-unknown-unknown
</code></pre>
<h4><a class="header" href="#debugging-headless-browser-tests-1" id="debugging-headless-browser-tests-1">Debugging Headless Browser Tests</a></h4>
<p>Set the <code>NO_HEADLESS=1</code> environment variable and the browser tests will not run
headless. Instead, the tests will start a local server that you can visit in
your Web browser of choices, and headless testing should not be used. You can
then use your browser's devtools to debug.</p>
<h1><a class="header" href="#setting-up-continuous-integration-with-wasm-bindgen-test" id="setting-up-continuous-integration-with-wasm-bindgen-test">Setting Up Continuous Integration with <code>wasm-bindgen-test</code></a></h1>
<p>This page contains example configurations for running <code>wasm-bindgen-test</code>-based
tests in various CI services.</p>
<p>Is your favorite CI service missing? <a href="https://github.com/rustwasm/wasm-bindgen">Send us a pull
request!</a></p>
<h2><a class="header" href="#travis-ci" id="travis-ci">Travis CI</a></h2>
<pre><code class="language-yaml">language: rust
rust : nightly
addons:
firefox: latest
chrome : stable
install:
- curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh
script:
# this will test the non wasm targets if your crate has those, otherwise remove this line.
#
- cargo test
- wasm-pack test --firefox --headless
- wasm-pack test --chrome --headless
</code></pre>
<h2><a class="header" href="#appveyor" id="appveyor">AppVeyor</a></h2>
<pre><code class="language-yaml">install:
- ps: Install-Product node 10
- appveyor-retry appveyor DownloadFile https://win.rustup.rs/ -FileName rustup-init.exe
- rustup-init.exe -y --default-host x86_64-pc-windows-msvc --default-toolchain nightly
- set PATH=%PATH%;C:\Users\appveyor\.cargo\bin
- rustc -V
- cargo -V
- rustup target add wasm32-unknown-unknown
- cargo install wasm-bindgen-cli
build: false
test_script:
# Test in Chrome. chromedriver is installed by default in appveyor.
- set CHROMEDRIVER=C:\Tools\WebDriver\chromedriver.exe
- cargo test --target wasm32-unknown-unknown
- set CHROMEDRIVER=
# Test in Firefox. geckodriver is also installed by default.
- set GECKODRIVER=C:\Tools\WebDriver\geckodriver.exe
- cargo test --target wasm32-unknown-unknown
</code></pre>
<h2><a class="header" href="#github-actions" id="github-actions">GitHub Actions</a></h2>
<pre><code class="language-yaml">on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Install
run: curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh
- run: cargo test
- run: wasm-pack test --headless --chrome
- run: wasm-pack test --headless --firefox
</code></pre>
<h1><a class="header" href="#contributing-to-wasm-bindgen" id="contributing-to-wasm-bindgen">Contributing to <code>wasm-bindgen</code></a></h1>
<p>This section contains instructions on how to get this project up and running for
development. You may want to browse the [unpublished guide documentation] for
<code>wasm-bindgen</code> as well as it may have more up-to-date information.</p>
<h2><a class="header" href="#prerequisites" id="prerequisites">Prerequisites</a></h2>
<ol>
<li>
<p>Rust. <a href="https://www.rust-lang.org/en-US/install.html">Install Rust</a>. Once Rust is installed, run</p>
<pre><code class="language-shell">rustup target add wasm32-unknown-unknown
</code></pre>
</li>
</ol>
<ol start="2">
<li>The tests for this project use Node. Make sure you have node &gt;= 10 installed,
as that is when WebAssembly support was introduced. <a href="https://nodejs.org/en/">Install Node</a>.</li>
</ol>
<h2><a class="header" href="#code-formatting" id="code-formatting">Code Formatting</a></h2>
<p>Although formatting rules are not mandatory, it is encouraged to run <code>cargo run</code> (<code>rustfmt</code>) with its default rules within a PR to maintain a more organized code base. If necessary, a PR with a single commit that formats the entire project is also welcome.</p>
<h1><a class="header" href="#running-wasm-bindgens-tests" id="running-wasm-bindgens-tests">Running <code>wasm-bindgen</code>'s Tests</a></h1>
<h2><a class="header" href="#wasm-tests-on-node-and-headless-browsers" id="wasm-tests-on-node-and-headless-browsers">Wasm Tests on Node and Headless Browsers</a></h2>
<p>These are the largest test suites, and most common to run in day to day
<code>wasm-bindgen</code> development. These tests are compiled to Wasm and then run in
Node.js or a headless browser via the WebDriver protocol.</p>
<pre><code class="language-bash">cargo test --target wasm32-unknown-unknown
</code></pre>
<p>See <a href="https://github.com/rustwasm/wasm-bindgen/blob/master/crates/test/README.md">the <code>wasm-bindgen-test</code> crate's
<code>README.md</code></a>
for details and configuring which headless browser is used.</p>
<h2><a class="header" href="#sanity-tests-for-wasm-bindgen-on-the-native-host-target" id="sanity-tests-for-wasm-bindgen-on-the-native-host-target">Sanity Tests for <code>wasm-bindgen</code> on the Native Host Target</a></h2>
<p>This small test suite just verifies that exported <code>wasm-bindgen</code> methods can
still be used on the native host's target.</p>
<pre><code>cargo test
</code></pre>
<h2><a class="header" href="#the-web-idl-frontends-tests" id="the-web-idl-frontends-tests">The Web IDL Frontend's Tests</a></h2>
<pre><code>cargo test -p webidl-tests --target wasm32-unknown-unknown
</code></pre>
<h2><a class="header" href="#the-macro-ui-tests" id="the-macro-ui-tests">The Macro UI Tests</a></h2>
<p>These tests assert that we have reasonable error messages that point to the
right source spans when the <code>#[wasm_bindgen]</code> proc-macro is misused.</p>
<pre><code>cargo test -p ui-tests
</code></pre>
<h2><a class="header" href="#the-js-sys-tests" id="the-js-sys-tests">The <code>js-sys</code> Tests</a></h2>
<p>See <a href="contributing/js-sys/testing.html">the <code>js-sys</code> testing page</a>.</p>
<h2><a class="header" href="#the-web-sys-tests" id="the-web-sys-tests">The <code>web-sys</code> Tests</a></h2>
<p>See <a href="contributing/web-sys/testing.html">the <code>web-sys</code> testing page</a>.</p>
<h1><a class="header" href="#design-of-wasm-bindgen" id="design-of-wasm-bindgen">Design of <code>wasm-bindgen</code></a></h1>
<p>This section is intended to be a deep-dive into how <code>wasm-bindgen</code> internally
works today, specifically for Rust. If you're reading this far in the future it
may no longer be up to date, but feel free to open an issue and we can try to
answer questions and/or update this!</p>
<h2><a class="header" href="#foundation-es-modules" id="foundation-es-modules">Foundation: ES Modules</a></h2>
<p>The first thing to know about <code>wasm-bindgen</code> is that it's fundamentally built on
the idea of ES Modules. In other words this tool takes an opinionated stance
that wasm files <em>should be viewed as ES modules</em>. This means that you can
<code>import</code> from a wasm file, use its <code>export</code>-ed functionality, etc, from normal
JS files.</p>
<p>Now unfortunately at the time of this writing the interface of wasm interop
isn't very rich. Wasm modules can only call functions or export functions that
deal exclusively with <code>i32</code>, <code>i64</code>, <code>f32</code>, and <code>f64</code>. Bummer!</p>
<p>That's where this project comes in. The goal of <code>wasm-bindgen</code> is to enhance the
&quot;ABI&quot; of wasm modules with richer types like classes, JS objects, Rust structs,
strings, etc. Keep in mind, though, that everything is based on ES Modules! This
means that the compiler is actually producing a &quot;broken&quot; wasm file of sorts. The
wasm file emitted by rustc, for example, does not have the interface we would
like to have. Instead it requires the <code>wasm-bindgen</code> tool to postprocess the
file, generating a <code>foo.js</code> and <code>foo_bg.wasm</code> file. The <code>foo.js</code> file is the
desired interface expressed in JS (classes, types, strings, etc) and the
<code>foo_bg.wasm</code> module is simply used as an implementation detail (it was
lightly modified from the original <code>foo.wasm</code> file).</p>
<p>As more features are stabilized in WebAssembly over time (like host bindings)
the JS file is expected to get smaller and smaller. It's unlikely to ever
disappear, but <code>wasm-bindgen</code> is designed to follow the WebAssembly spec and
proposals closely to optimize JS/Rust as much as possible.</p>
<h2><a class="header" href="#foundation-2-unintrusive-in-rust" id="foundation-2-unintrusive-in-rust">Foundation #2: Unintrusive in Rust</a></h2>
<p>On the more Rust-y side of things the <code>wasm-bindgen</code> crate is designed to
ideally have as minimal impact on a Rust crate as possible. Ideally a few
<code>#[wasm_bindgen]</code> attributes are annotated in key locations and otherwise you're
off to the races. The attribute strives to both not invent new syntax and work
with existing idioms today.</p>
<p>For example a library might exposed a function in normal Rust that looks like:</p>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
pub fn greet(name: &amp;str) -&gt; String {
// ...
}
#}</code></pre></pre>
<p>And with <code>#[wasm_bindgen]</code> all you need to do in exporting it to JS is:</p>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
#[wasm_bindgen]
pub fn greet(name: &amp;str) -&gt; String {
// ...
}
#}</code></pre></pre>
<p>Additionally the design here with minimal intervention in Rust should allow us
to easily take advantage of the upcoming <a href="https://github.com/WebAssembly/host-bindings">host bindings</a> proposal. Ideally
you'd simply upgrade <code>wasm-bindgen</code>-the-crate as well as your toolchain and
you're immediately getting raw access to host bindings! (this is still a bit of
a ways off though...)</p>
<h1><a class="header" href="#polyfill-for-js-objects-in-wasm" id="polyfill-for-js-objects-in-wasm">Polyfill for &quot;JS objects in wasm&quot;</a></h1>
<p>One of the main goals of <code>wasm-bindgen</code> is to allow working with and passing
around JS objects in wasm, but that's not allowed today! While indeed true,
that's where the polyfill comes in.</p>
<p>The question here is how we shoehorn JS objects into a <code>u32</code> for wasm to use.
The current strategy for this approach is to maintain a module-local variable
in the generated <code>foo.js</code> file: a <code>heap</code>.</p>
<h3><a class="header" href="#temporary-js-objects-on-the-stack" id="temporary-js-objects-on-the-stack">Temporary JS objects on the &quot;stack&quot;</a></h3>
<p>The first slots in the <code>heap</code> in <code>foo.js</code> are considered a stack. This stack,
like typical program execution stacks, grows down. JS objects are pushed on the
bottom of the stack, and their index in the stack is the identifier that's passed
to wasm. A stack pointer is maintained to figure out where the next item is
pushed.</p>
<p>JS objects are then only removed from the bottom of the stack as well. Removal
is simply storing null then incrementing a counter. Because of the &quot;stack-y&quot;
nature of this scheme it only works for when wasm doesn't hold onto a JS object
(aka it only gets a &quot;reference&quot; in Rust parlance).</p>
<p>Let's take a look at an example.</p>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
// foo.rs
#[wasm_bindgen]
pub fn foo(a: &amp;JsValue) {
// ...
}
#}</code></pre></pre>
<p>Here we're using the special <code>JsValue</code> type from the <code>wasm-bindgen</code> library
itself. Our exported function, <code>foo</code>, takes a <em>reference</em> to an object. This
notably means that it can't persist the object past the lifetime of this
function call.</p>
<p>Now what we actually want to generate is a JS module that looks like (in
TypeScript parlance)</p>
<pre><code class="language-ts">// foo.d.ts
export function foo(a: any);
</code></pre>
<p>and what we actually generate looks something like:</p>
<pre><code class="language-js">// foo.js
import * as wasm from './foo_bg';
const heap = new Array(32);
heap.push(undefined, null, true, false);
let stack_pointer = 32;
function addBorrowedObject(obj) {
stack_pointer -= 1;
heap[stack_pointer] = obj;
return stack_pointer;
}
export function foo(arg0) {
const idx0 = addBorrowedObject(arg0);
try {
wasm.foo(idx0);
} finally {
heap[stack_pointer++] = undefined;
}
}
</code></pre>
<p>Here we can see a few notable points of action:</p>
<ul>
<li>The wasm file was renamed to <code>foo_bg.wasm</code>, and we can see how the JS module
generated here is importing from the wasm file.</li>
<li>Next we can see our <code>heap</code> module variable which is to store all JS values
reference-able from wasm.</li>
<li>Our exported function <code>foo</code>, takes an arbitrary argument, <code>arg0</code>, which is
converted to an index with the <code>addBorrowedObject</code> object function. The index
is then passed to wasm so wasm can operate with it.</li>
<li>Finally, we have a <code>finally</code> which frees the stack slot as it's no longer
used, popping the value that was pushed at the start of the function.</li>
</ul>
<p>It's also helpful to dig into the Rust side of things to see what's going on
there! Let's take a look at the code that <code>#[wasm_bindgen]</code> generates in Rust:</p>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
// what the user wrote
pub fn foo(a: &amp;JsValue) {
// ...
}
#[export_name = &quot;foo&quot;]
pub extern &quot;C&quot; fn __wasm_bindgen_generated_foo(arg0: u32) {
let arg0 = unsafe {
ManuallyDrop::new(JsValue::__from_idx(arg0))
};
let arg0 = &amp;*arg0;
foo(arg0);
}
#}</code></pre></pre>
<p>And as with the JS, the notable points here are:</p>
<ul>
<li>The original function, <code>foo</code>, is unmodified in the output</li>
<li>A generated function here (with a unique name) is the one that's actually
exported from the wasm module</li>
<li>Our generated function takes an integer argument (our index) and then wraps it
in a <code>JsValue</code>. There's some trickery here that's not worth going into just
yet, but we'll see in a bit what's happening under the hood.</li>
</ul>
<h3><a class="header" href="#long-lived-js-objects" id="long-lived-js-objects">Long-lived JS objects</a></h3>
<p>The above strategy is useful when JS objects are only temporarily used in Rust,
for example only during one function call. Sometimes, though, objects may have a
dynamic lifetime or otherwise need to be stored on Rust's heap. To cope with
this there's a second half of management of JS objects, naturally corresponding
to the other side of the JS <code>heap</code> array.</p>
<p>JS Objects passed to wasm that are not references are assumed to have a dynamic
lifetime inside of the wasm module. As a result the strict push/pop of the stack
won't work and we need more permanent storage for the JS objects. To cope with
this we build our own &quot;slab allocator&quot; of sorts.</p>
<p>A picture (or code) is worth a thousand words so let's show what happens with an
example.</p>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
// foo.rs
#[wasm_bindgen]
pub fn foo(a: JsValue) {
// ...
}
#}</code></pre></pre>
<p>Note that the <code>&amp;</code> is missing in front of the <code>JsValue</code> we had before, and in
Rust parlance this means it's taking ownership of the JS value. The exported ES
module interface is the same as before, but the ownership mechanics are slightly
different. Let's see the generated JS's slab in action:</p>
<pre><code class="language-js">import * as wasm from './foo_bg'; // imports from wasm file
const heap = new Array(32);
heap.push(undefined, null, true, false);
let heap_next = 36;
function addHeapObject(obj) {
if (heap_next === heap.length)
heap.push(heap.length + 1);
const idx = heap_next;
heap_next = heap[idx];
heap[idx] = obj;
return idx;
}
export function foo(arg0) {
const idx0 = addHeapObject(arg0);
wasm.foo(idx0);
}
export function __wbindgen_object_drop_ref(idx) {
heap[idx ] = heap_next;
heap_next = idx;
}
</code></pre>
<p>Unlike before we're now calling <code>addHeapObject</code> on the argument to <code>foo</code> rather
than <code>addBorrowedObject</code>. This function will use <code>heap</code> and <code>heap_next</code> as a
slab allocator to acquire a slot to store the object, placing a structure there
once it's found. Note that this is going on the right-half of the array, unlike
the stack which resides on the left half. This discipline mirrors the stack/heap
in normal programs, roughly.</p>
<p>Another curious aspect of this generated module is the
<code>__wbindgen_object_drop_ref</code> function. This is one that's actually imported to
wasm rather than used in this module! This function is used to signal the end of
the lifetime of a <code>JsValue</code> in Rust, or in other words when it goes out of
scope. Otherwise though this function is largely just a general &quot;slab free&quot;
implementation.</p>
<p>And finally, let's take a look at the Rust generated again too:</p>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
// what the user wrote
pub fn foo(a: JsValue) {
// ...
}
#[export_name = &quot;foo&quot;]
pub extern &quot;C&quot; fn __wasm_bindgen_generated_foo(arg0: u32) {
let arg0 = unsafe {
JsValue::__from_idx(arg0)
};
foo(arg0);
}
#}</code></pre></pre>
<p>Ah that looks much more familiar! Not much interesting is happening here, so
let's move on to...</p>
<h3><a class="header" href="#anatomy-of-jsvalue" id="anatomy-of-jsvalue">Anatomy of <code>JsValue</code></a></h3>
<p>Currently the <code>JsValue</code> struct is actually quite simple in Rust, it's:</p>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
pub struct JsValue {
idx: u32,
}
// &quot;private&quot; constructors
impl Drop for JsValue {
fn drop(&amp;mut self) {
unsafe {
__wbindgen_object_drop_ref(self.idx);
}
}
}
#}</code></pre></pre>
<p>Or in other words it's a newtype wrapper around a <code>u32</code>, the index that we're
passed from wasm. The destructor here is where the <code>__wbindgen_object_drop_ref</code>
function is called to relinquish our reference count of the JS object, freeing
up our slot in the <code>slab</code> that we saw above.</p>
<p>If you'll recall as well, when we took <code>&amp;JsValue</code> above we generated a wrapper
of <code>ManuallyDrop</code> around the local binding, and that's because we wanted to
avoid invoking this destructor when the object comes from the stack.</p>
<h3><a class="header" href="#working-with-heap-in-reality" id="working-with-heap-in-reality">Working with <code>heap</code> in reality</a></h3>
<p>The above explanations are pretty close to what happens today, but in reality
there's a few differences especially around handling constant values like
<code>undefined</code>, <code>null</code>, etc. Be sure to check out the actual generated JS and the
generation code for the full details!</p>
<h1><a class="header" href="#exporting-a-function-to-js" id="exporting-a-function-to-js">Exporting a function to JS</a></h1>
<p>Alright now that we've got a good grasp on JS objects and how they're working,
let's take a look at another feature of <code>wasm-bindgen</code>: exporting functionality
with types that are richer than just numbers.</p>
<p>The basic idea around exporting functionality with more flavorful types is that
the wasm exports won't actually be called directly. Instead the generated
<code>foo.js</code> module will have shims for all exported functions in the wasm module.</p>
<p>The most interesting conversion here happens with strings so let's take a look
at that.</p>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
#[wasm_bindgen]
pub fn greet(a: &amp;str) -&gt; String {
format!(&quot;Hello, {}!&quot;, a)
}
#}</code></pre></pre>
<p>Here we'd like to define an ES module that looks like</p>
<pre><code class="language-ts">// foo.d.ts
export function greet(a: string): string;
</code></pre>
<p>To see what's going on, let's take a look at the generated shim</p>
<pre><code class="language-js">import * as wasm from './foo_bg';
function passStringToWasm(arg) {
const buf = new TextEncoder('utf-8').encode(arg);
const len = buf.length;
const ptr = wasm.__wbindgen_malloc(len);
let array = new Uint8Array(wasm.memory.buffer);
array.set(buf, ptr);
return [ptr, len];
}
function getStringFromWasm(ptr, len) {
const mem = new Uint8Array(wasm.memory.buffer);
const slice = mem.slice(ptr, ptr + len);
const ret = new TextDecoder('utf-8').decode(slice);
return ret;
}
export function greet(arg0) {
const [ptr0, len0] = passStringToWasm(arg0);
try {
const ret = wasm.greet(ptr0, len0);
const ptr = wasm.__wbindgen_boxed_str_ptr(ret);
const len = wasm.__wbindgen_boxed_str_len(ret);
const realRet = getStringFromWasm(ptr, len);
wasm.__wbindgen_boxed_str_free(ret);
return realRet;
} finally {
wasm.__wbindgen_free(ptr0, len0);
}
}
</code></pre>
<p>Phew, that's quite a lot! We can sort of see though if we look closely what's
happening:</p>
<ul>
<li>
<p>Strings are passed to wasm via two arguments, a pointer and a length. Right
now we have to copy the string onto the wasm heap which means we'll be using
<code>TextEncoder</code> to actually do the encoding. Once this is done we use an
internal function in <code>wasm-bindgen</code> to allocate space for the string to go,
and then we'll pass that ptr/length to wasm later on.</p>
</li>
<li>
<p>Returning strings from wasm is a little tricky as we need to return a ptr/len
pair, but wasm currently only supports one return value (multiple return values
<a href="https://github.com/WebAssembly/design/issues/1146">is being standardized</a>).
To work around this in the meantime, we're actually returning a pointer to a
ptr/len pair, and then using functions to access the various fields.</p>
</li>
<li>
<p>Some cleanup ends up happening in wasm. The <code>__wbindgen_boxed_str_free</code>
function is used to free the return value of <code>greet</code> after it's been decoded
onto the JS heap (using <code>TextDecoder</code>). The <code>__wbindgen_free</code> is then used to
free the space we allocated to pass the string argument once the function call
is done.</p>
</li>
</ul>
<p>Next let's take a look at the Rust side of things as well. Here we'll be looking
at a mostly abbreviated and/or &quot;simplified&quot; in the sense of this is what it
compiles down to:</p>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
pub extern &quot;C&quot; fn greet(a: &amp;str) -&gt; String {
format!(&quot;Hello, {}!&quot;, a)
}
#[export_name = &quot;greet&quot;]
pub extern &quot;C&quot; fn __wasm_bindgen_generated_greet(
arg0_ptr: *const u8,
arg0_len: usize,
) -&gt; *mut String {
let arg0 = unsafe {
let slice = ::std::slice::from_raw_parts(arg0_ptr, arg0_len);
::std::str::from_utf8_unchecked(slice)
};
let _ret = greet(arg0);
Box::into_raw(Box::new(_ret))
}
#}</code></pre></pre>
<p>Here we can see again that our <code>greet</code> function is unmodified and has a wrapper
to call it. This wrapper will take the ptr/len argument and convert it to a
string slice, while the return value is boxed up into just a pointer and is
then returned up to was for reading via the <code>__wbindgen_boxed_str_*</code> functions.</p>
<p>So in general exporting a function involves a shim both in JS and in Rust with
each side translating to or from wasm arguments to the native types of each
language. The <code>wasm-bindgen</code> tool manages hooking up all these shims while the
<code>#[wasm_bindgen]</code> macro takes care of the Rust shim as well.</p>
<p>Most arguments have a relatively clear way to convert them, bit if you've got
any questions just let me know!</p>
<h1><a class="header" href="#exporting-a-struct-to-js" id="exporting-a-struct-to-js">Exporting a struct to JS</a></h1>
<p>So far we've covered JS objects, importing functions, and exporting functions.
This has given us quite a rich base to build on so far, and that's great! We
sometimes, though, want to go even further and define a JS <code>class</code> in Rust. Or
in other words, we want to expose an object with methods from Rust to JS rather
than just importing/exporting free functions.</p>
<p>The <code>#[wasm_bindgen]</code> attribute can annotate both a <code>struct</code> and <code>impl</code> blocks
to allow:</p>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
#[wasm_bindgen]
pub struct Foo {
internal: i32,
}
#[wasm_bindgen]
impl Foo {
pub fn new(val: i32) -&gt; Foo {
Foo { internal: val }
}
pub fn get(&amp;self) -&gt; i32 {
self.internal
}
pub fn set(&amp;mut self, val: i32) {
self.internal = val;
}
}
#}</code></pre></pre>
<p>This is a typical Rust <code>struct</code> definition for a type with a constructor and a
few methods. Annotating the struct with <code>#[wasm_bindgen]</code> means that we'll
generate necessary trait impls to convert this type to/from the JS boundary. The
annotated <code>impl</code> block here means that the functions inside will also be made
available to JS through generated shims. If we take a look at the generated JS
code for this we'll see:</p>
<pre><code class="language-js">import * as wasm from './js_hello_world_bg';
export class Foo {
static __construct(ptr) {
return new Foo(ptr);
}
constructor(ptr) {
this.ptr = ptr;
}
free() {
const ptr = this.ptr;
this.ptr = 0;
wasm.__wbg_foo_free(ptr);
}
static new(arg0) {
const ret = wasm.foo_new(arg0);
return Foo.__construct(ret)
}
get() {
const ret = wasm.foo_get(this.ptr);
return ret;
}
set(arg0) {
const ret = wasm.foo_set(this.ptr, arg0);
return ret;
}
}
</code></pre>
<p>That's actually not much! We can see here though how we've translated from Rust
to JS:</p>
<ul>
<li>Associated functions in Rust (those without <code>self</code>) turn into <code>static</code>
functions in JS.</li>
<li>Methods in Rust turn into methods in wasm.</li>
<li>Manual memory management is exposed in JS as well. The <code>free</code> function is
required to be invoked to deallocate resources on the Rust side of things.</li>
</ul>
<p>To be able to use <code>new Foo()</code>, you'd need to annotate <code>new</code> as <code>#[wasm_bindgen(constructor)]</code>.</p>
<p>One important aspect to note here, though, is that once <code>free</code> is called the JS
object is &quot;neutered&quot; in that its internal pointer is nulled out. This means that
future usage of this object should trigger a panic in Rust.</p>
<p>The real trickery with these bindings ends up happening in Rust, however, so
let's take a look at that.</p>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
// original input to `#[wasm_bindgen]` omitted ...
#[export_name = &quot;foo_new&quot;]
pub extern &quot;C&quot; fn __wasm_bindgen_generated_Foo_new(arg0: i32) -&gt; u32
let ret = Foo::new(arg0);
Box::into_raw(Box::new(WasmRefCell::new(ret))) as u32
}
#[export_name = &quot;foo_get&quot;]
pub extern &quot;C&quot; fn __wasm_bindgen_generated_Foo_get(me: u32) -&gt; i32 {
let me = me as *mut WasmRefCell&lt;Foo&gt;;
wasm_bindgen::__rt::assert_not_null(me);
let me = unsafe { &amp;*me };
return me.borrow().get();
}
#[export_name = &quot;foo_set&quot;]
pub extern &quot;C&quot; fn __wasm_bindgen_generated_Foo_set(me: u32, arg1: i32) {
let me = me as *mut WasmRefCell&lt;Foo&gt;;
wasm_bindgen::__rt::assert_not_null(me);
let me = unsafe { &amp;*me };
me.borrow_mut().set(arg1);
}
#[no_mangle]
pub unsafe extern &quot;C&quot; fn __wbindgen_foo_free(me: u32) {
let me = me as *mut WasmRefCell&lt;Foo&gt;;
wasm_bindgen::__rt::assert_not_null(me);
(*me).borrow_mut(); // ensure no active borrows
drop(Box::from_raw(me));
}
#}</code></pre></pre>
<p>As with before this is cleaned up from the actual output but it's the same idea
as to what's going on! Here we can see a shim for each function as well as a
shim for deallocating an instance of <code>Foo</code>. Recall that the only valid wasm
types today are numbers, so we're required to shoehorn all of <code>Foo</code> into a
<code>u32</code>, which is currently done via <code>Box</code> (like <code>std::unique_ptr</code> in C++).
Note, though, that there's an extra layer here, <code>WasmRefCell</code>. This type is the
same as <a href="https://doc.rust-lang.org/std/cell/struct.RefCell.html"><code>RefCell</code></a> and can be mostly glossed over.</p>
<p>The purpose for this type, if you're interested though, is to uphold Rust's
guarantees about aliasing in a world where aliasing is rampant (JS).
Specifically the <code>&amp;Foo</code> type means that there can be as much aliasing as you'd
like, but crucially <code>&amp;mut Foo</code> means that it is the sole pointer to the data
(no other <code>&amp;Foo</code> to the same instance exists). The <a href="https://doc.rust-lang.org/std/cell/struct.RefCell.html"><code>RefCell</code></a> type in libstd
is a way of dynamically enforcing this at runtime (as opposed to compile time
where it usually happens). Baking in <code>WasmRefCell</code> is the same idea here,
adding runtime checks for aliasing which are typically happening at compile
time. This is currently a Rust-specific feature which isn't actually in the
<code>wasm-bindgen</code> tool itself, it's just in the Rust-generated code (aka the
<code>#[wasm_bindgen]</code> attribute).</p>
<h1><a class="header" href="#importing-a-function-from-js" id="importing-a-function-from-js">Importing a function from JS</a></h1>
<p>Now that we've exported some rich functionality to JS it's also time to import
some! The goal here is to basically implement JS <code>import</code> statements in Rust,
with fancy types and all.</p>
<p>First up, let's say we invert the function above and instead want to generate
greetings in JS but call it from Rust. We might have, for example:</p>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
#[wasm_bindgen(module = &quot;./greet&quot;)]
extern &quot;C&quot; {
fn greet(a: &amp;str) -&gt; String;
}
fn other_code() {
let greeting = greet(&quot;foo&quot;);
// ...
}
#}</code></pre></pre>
<p>The basic idea of imports is the same as exports in that we'll have shims in
both JS and Rust doing the necessary translation. Let's first see the JS shim in
action:</p>
<pre><code class="language-js">import * as wasm from './foo_bg';
import { greet } from './greet';
// ...
export function __wbg_f_greet(ptr0, len0, wasmretptr) {
const [retptr, retlen] = passStringToWasm(greet(getStringFromWasm(ptr0, len0)));
(new Uint32Array(wasm.memory.buffer))[wasmretptr / 4] = retlen;
return retptr;
}
</code></pre>
<p>The <code>getStringFromWasm</code> and <code>passStringToWasm</code> are the same as we saw before,
and like with <code>__wbindgen_object_drop_ref</code> far above we've got this weird export
from our module now! The <code>__wbg_f_greet</code> function is what's generated by
<code>wasm-bindgen</code> to actually get imported in the <code>foo.wasm</code> module.</p>
<p>The generated <code>foo.js</code> we see imports from the <code>./greet</code> module with the <code>greet</code>
name (was the function import in Rust said) and then the <code>__wbg_f_greet</code>
function is shimming that import.</p>
<p>There's some tricky ABI business going on here so let's take a look at the
generated Rust as well. Like before this is simplified from what's actually
generated.</p>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
extern &quot;C&quot; fn greet(a: &amp;str) -&gt; String {
extern &quot;C&quot; {
fn __wbg_f_greet(a_ptr: *const u8, a_len: usize, ret_len: *mut usize) -&gt; *mut u8;
}
unsafe {
let a_ptr = a.as_ptr();
let a_len = a.len();
let mut __ret_strlen = 0;
let mut __ret_strlen_ptr = &amp;mut __ret_strlen as *mut usize;
let _ret = __wbg_f_greet(a_ptr, a_len, __ret_strlen_ptr);
String::from_utf8_unchecked(
Vec::from_raw_parts(_ret, __ret_strlen, __ret_strlen)
)
}
}
#}</code></pre></pre>
<p>Here we can see that the <code>greet</code> function was generated but it's largely just a
shim around the <code>__wbg_f_greet</code> function that we're calling. The ptr/len pair
for the argument is passed as two arguments and for the return value we're
receiving one value (the length) indirectly while directly receiving the
returned pointer.</p>
<h1><a class="header" href="#importing-a-class-from-js" id="importing-a-class-from-js">Importing a class from JS</a></h1>
<p>Just like with functions after we've started exporting we'll also want to
import! Now that we've exported a <code>class</code> to JS we'll want to also be able to
import classes in Rust as well to invoke methods and such. Since JS classes are
in general just JS objects the bindings here will look pretty similar to the JS
object bindings describe above.</p>
<p>As usual though, let's dive into an example!</p>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
#[wasm_bindgen(module = &quot;./bar&quot;)]
extern &quot;C&quot; {
type Bar;
#[wasm_bindgen(constructor)]
fn new(arg: i32) -&gt; Bar;
#[wasm_bindgen(js_namespace = Bar)]
fn another_function() -&gt; i32;
#[wasm_bindgen(method)]
fn get(this: &amp;Bar) -&gt; i32;
#[wasm_bindgen(method)]
fn set(this: &amp;Bar, val: i32);
#[wasm_bindgen(method, getter)]
fn property(this: &amp;Bar) -&gt; i32;
#[wasm_bindgen(method, setter)]
fn set_property(this: &amp;Bar, val: i32);
}
fn run() {
let bar = Bar::new(Bar::another_function());
let x = bar.get();
bar.set(x + 3);
bar.set_property(bar.property() + 6);
}
#}</code></pre></pre>
<p>Unlike our previous imports, this one's a bit more chatty! Remember that one of
the goals of <code>wasm-bindgen</code> is to use native Rust syntax wherever possible, so
this is mostly intended to use the <code>#[wasm_bindgen]</code> attribute to interpret
what's written down in Rust. Now there's a few attribute annotations here, so
let's go through one-by-one:</p>
<ul>
<li><code>#[wasm_bindgen(module = &quot;./bar&quot;)]</code> - seen before with imports this is declare
where all the subsequent functionality is imported from. For example the <code>Bar</code>
type is going to be imported from the <code>./bar</code> module.</li>
<li><code>type Bar</code> - this is a declaration of JS class as a new type in Rust. This
means that a new type <code>Bar</code> is generated which is &quot;opaque&quot; but is represented
as internally containing a <code>JsValue</code>. We'll see more on this later.</li>
<li><code>#[wasm_bindgen(constructor)]</code> - this indicates that the binding's name isn't
actually used in JS but rather translates to <code>new Bar()</code>. The return value of
this function must be a bare type, like <code>Bar</code>.</li>
<li><code>#[wasm_bindgen(js_namespace = Bar)]</code> - this attribute indicates that the
function declaration is namespaced through the <code>Bar</code> class in JS.</li>
<li><code>#[wasm_bindgen(static_method_of = SomeJsClass)]</code> - this attribute is similar
to <code>js_namespace</code>, but instead of producing a free function, produces a static
method of <code>SomeJsClass</code>.</li>
<li><code>#[wasm_bindgen(method)]</code> - and finally, this attribute indicates that a
method call is going to happen. The first argument must be a JS struct, like
<code>Bar</code>, and the call in JS looks like <code>Bar.prototype.set.call(...)</code>.</li>
</ul>
<p>With all that in mind, let's take a look at the JS generated.</p>
<pre><code class="language-js">import * as wasm from './foo_bg';
import { Bar } from './bar';
// other support functions omitted...
export function __wbg_s_Bar_new() {
return addHeapObject(new Bar());
}
const another_function_shim = Bar.another_function;
export function __wbg_s_Bar_another_function() {
return another_function_shim();
}
const get_shim = Bar.prototype.get;
export function __wbg_s_Bar_get(ptr) {
return shim.call(getObject(ptr));
}
const set_shim = Bar.prototype.set;
export function __wbg_s_Bar_set(ptr, arg0) {
set_shim.call(getObject(ptr), arg0)
}
const property_shim = Object.getOwnPropertyDescriptor(Bar.prototype, 'property').get;
export function __wbg_s_Bar_property(ptr) {
return property_shim.call(getObject(ptr));
}
const set_property_shim = Object.getOwnPropertyDescriptor(Bar.prototype, 'property').set;
export function __wbg_s_Bar_set_property(ptr, arg0) {
set_property_shim.call(getObject(ptr), arg0)
}
</code></pre>
<p>Like when importing functions from JS we can see a bunch of shims are generated
for all the relevant functions. The <code>new</code> static function has the
<code>#[wasm_bindgen(constructor)]</code> attribute which means that instead of any
particular method it should actually invoke the <code>new</code> constructor instead (as
we see here). The static function <code>another_function</code>, however, is dispatched as
<code>Bar.another_function</code>.</p>
<p>The <code>get</code> and <code>set</code> functions are methods so they go through <code>Bar.prototype</code>,
and otherwise their first argument is implicitly the JS object itself which is
loaded through <code>getObject</code> like we saw earlier.</p>
<p>Some real meat starts to show up though on the Rust side of things, so let's
take a look:</p>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
pub struct Bar {
obj: JsValue,
}
impl Bar {
fn new() -&gt; Bar {
extern &quot;C&quot; {
fn __wbg_s_Bar_new() -&gt; u32;
}
unsafe {
let ret = __wbg_s_Bar_new();
Bar { obj: JsValue::__from_idx(ret) }
}
}
fn another_function() -&gt; i32 {
extern &quot;C&quot; {
fn __wbg_s_Bar_another_function() -&gt; i32;
}
unsafe {
__wbg_s_Bar_another_function()
}
}
fn get(&amp;self) -&gt; i32 {
extern &quot;C&quot; {
fn __wbg_s_Bar_get(ptr: u32) -&gt; i32;
}
unsafe {
let ptr = self.obj.__get_idx();
let ret = __wbg_s_Bar_get(ptr);
return ret
}
}
fn set(&amp;self, val: i32) {
extern &quot;C&quot; {
fn __wbg_s_Bar_set(ptr: u32, val: i32);
}
unsafe {
let ptr = self.obj.__get_idx();
__wbg_s_Bar_set(ptr, val);
}
}
fn property(&amp;self) -&gt; i32 {
extern &quot;C&quot; {
fn __wbg_s_Bar_property(ptr: u32) -&gt; i32;
}
unsafe {
let ptr = self.obj.__get_idx();
let ret = __wbg_s_Bar_property(ptr);
return ret
}
}
fn set_property(&amp;self, val: i32) {
extern &quot;C&quot; {
fn __wbg_s_Bar_set_property(ptr: u32, val: i32);
}
unsafe {
let ptr = self.obj.__get_idx();
__wbg_s_Bar_set_property(ptr, val);
}
}
}
impl WasmBoundary for Bar {
// ...
}
impl ToRefWasmBoundary for Bar {
// ...
}
#}</code></pre></pre>
<p>In Rust we're seeing that a new type, <code>Bar</code>, is generated for this import of a
class. The type <code>Bar</code> internally contains a <code>JsValue</code> as an instance of <code>Bar</code>
is meant to represent a JS object stored in our module's stack/slab. This then
works mostly the same way that we saw JS objects work in the beginning.</p>
<p>When calling <code>Bar::new</code> we'll get an index back which is wrapped up in <code>Bar</code>
(which is itself just a <code>u32</code> in memory when stripped down). Each function then
passes the index as the first argument and otherwise forwards everything along
in Rust.</p>
<h1><a class="header" href="#rust-type-conversions" id="rust-type-conversions">Rust Type conversions</a></h1>
<p>Previously we've been seeing mostly abridged versions of type conversions when
values enter Rust. Here we'll go into some more depth about how this is
implemented. There are two categories of traits for converting values, traits
for converting values from Rust to JS and traits for the other way around.</p>
<h2><a class="header" href="#from-rust-to-js" id="from-rust-to-js">From Rust to JS</a></h2>
<p>First up let's take a look at going from Rust to JS:</p>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
pub trait IntoWasmAbi: WasmDescribe {
type Abi: WasmAbi;
fn into_abi(self, extra: &amp;mut Stack) -&gt; Self::Abi;
}
#}</code></pre></pre>
<p>And that's it! This is actually the only trait needed currently for translating
a Rust value to a JS one. There's a few points here:</p>
<ul>
<li>We'll get to <code>WasmDescribe</code> later in this section</li>
<li>The associated type <code>Abi</code> is what will actually be generated as an argument to
the wasm export. The bound <code>WasmAbi</code> is only implemented for types like <code>u32</code>
and <code>f64</code>, those which can be placed on the boundary and transmitted
losslessly.</li>
<li>And finally we have the <code>into_abi</code> function, returning the <code>Abi</code> associated
type which will be actually passed to JS. There's also this <code>Stack</code> parameter,
however. Not all Rust values can be communicated in 32 bits to the <code>Stack</code>
parameter allows transmitting more data, explained in a moment.</li>
</ul>
<p>This trait is implemented for all types that can be converted to JS and is
unconditionally used during codegen. For example you'll often see <code>IntoWasmAbi for Foo</code> but also <code>IntoWasmAbi for &amp;'a Foo</code>.</p>
<p>The <code>IntoWasmAbi</code> trait is used in two locations. First it's used to convert
return values of Rust exported functions to JS. Second it's used to convert the
Rust arguments of JS functions imported to Rust.</p>
<h2><a class="header" href="#from-js-to-rust" id="from-js-to-rust">From JS to Rust</a></h2>
<p>Unfortunately the opposite direction from above, going from JS to Rust, is a bit
more complicated. Here we've got three traits:</p>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
pub trait FromWasmAbi: WasmDescribe {
type Abi: WasmAbi;
unsafe fn from_abi(js: Self::Abi, extra: &amp;mut Stack) -&gt; Self;
}
pub trait RefFromWasmAbi: WasmDescribe {
type Abi: WasmAbi;
type Anchor: Deref&lt;Target=Self&gt;;
unsafe fn ref_from_abi(js: Self::Abi, extra: &amp;mut Stack) -&gt; Self::Anchor;
}
pub trait RefMutFromWasmAbi: WasmDescribe {
type Abi: WasmAbi;
type Anchor: DerefMut&lt;Target=Self&gt;;
unsafe fn ref_mut_from_abi(js: Self::Abi, extra: &amp;mut Stack) -&gt; Self::Anchor;
}
#}</code></pre></pre>
<p>The <code>FromWasmAbi</code> is relatively straightforward, basically the opposite of
<code>IntoWasmAbi</code>. It takes the ABI argument (typically the same as
<code>IntoWasmAbi::Abi</code>) and then the auxiliary stack to produce an instance of
<code>Self</code>. This trait is implemented primarily for types that <em>don't</em> have internal
lifetimes or are references.</p>
<p>The latter two traits here are mostly the same, and are intended for generating
references (both shared and mutable references). They look almost the same as
<code>FromWasmAbi</code> except that they return an <code>Anchor</code> type which implements a
<code>Deref</code> trait rather than <code>Self</code>.</p>
<p>The <code>Ref*</code> traits allow having arguments in functions that are references rather
than bare types, for example <code>&amp;str</code>, <code>&amp;JsValue</code>, or <code>&amp;[u8]</code>. The <code>Anchor</code> here
is required to ensure that the lifetimes don't persist beyond one function call
and remain anonymous.</p>
<p>The <code>From*</code> family of traits are used for converting the Rust arguments in Rust
exported functions to JS. They are also used for the return value in JS
functions imported into Rust.</p>
<h2><a class="header" href="#global-stack" id="global-stack">Global stack</a></h2>
<p>Mentioned above not all Rust types will fit within 32 bits. While we can
communicate an <code>f64</code> we don't necessarily have the ability to use all the bits.
Types like <code>&amp;str</code> need to communicate two items, a pointer and a length (64
bits). Other types like <code>&amp;Closure&lt;Fn()&gt;</code> have even more information to
transmit.</p>
<p>As a result we need a method of communicating more data through the signatures
of functions. While we could add more arguments this is somewhat difficult to do
in the world of closures where code generation isn't quite as dynamic as a
procedural macro. Consequently a &quot;global stack&quot; is used to transmit extra
data for a function call.</p>
<p>The global stack is a fixed-sized static allocation in the wasm module. This
stack is temporary scratch space for any one function call from either JS to
Rust or Rust to JS. Both Rust and the JS shim generated have pointers to this
global stack and will read/write information from it.</p>
<p>Using this scheme whenever we want to pass <code>&amp;str</code> from JS to Rust we can pass
the pointer as the actual ABI argument and the length is then placed in the next
spot on the global stack.</p>
<p>The <code>Stack</code> argument to the conversion traits above looks like:</p>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
pub trait Stack {
fn push(&amp;mut self, bits: u32);
fn pop(&amp;mut self) -&gt; u32;
}
#}</code></pre></pre>
<p>A trait is used here to facilitate testing but typically the calls don't end up
being virtually dispatched at runtime.</p>
<h1><a class="header" href="#communicating-types-to-wasm-bindgen" id="communicating-types-to-wasm-bindgen">Communicating types to <code>wasm-bindgen</code></a></h1>
<p>The last aspect to talk about when converting Rust/JS types amongst one another
is how this information is actually communicated. The <code>#[wasm_bindgen]</code> macro is
running over the syntactical (unresolved) structure of the Rust code and is then
responsible for generating information that <code>wasm-bindgen</code> the CLI tool later
reads.</p>
<p>To accomplish this a slightly unconventional approach is taken. Static
information about the structure of the Rust code is serialized via JSON
(currently) to a custom section of the wasm executable. Other information, like
what the types actually are, unfortunately isn't known until later in the
compiler due to things like associated type projections and typedefs. It also
turns out that we want to convey &quot;rich&quot; types like <code>FnMut(String, Foo, &amp;JsValue)</code> to the <code>wasm-bindgen</code> CLI, and handling all this is pretty tricky!</p>
<p>To solve this issue the <code>#[wasm_bindgen]</code> macro generates <strong>executable
functions</strong> which &quot;describe the type signature of an import or export&quot;. These
executable functions are what the <code>WasmDescribe</code> trait is all about:</p>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
pub trait WasmDescribe {
fn describe();
}
#}</code></pre></pre>
<p>While deceptively simple this trait is actually quite important. When you write,
an export like this:</p>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
#[wasm_bindgen]
fn greet(a: &amp;str) {
// ...
}
#}</code></pre></pre>
<p>In addition to the shims we talked about above which JS generates the macro
<em>also</em> generates something like:</p>
<pre><code>#[no_mangle]
pub extern &quot;C&quot; fn __wbindgen_describe_greet() {
&lt;Fn(&amp;str)&gt;::describe();
}
</code></pre>
<p>Or in other words it generates invocations of <code>describe</code> functions. In doing so
the <code>__wbindgen_describe_greet</code> shim is a programmatic description of the type
layouts of an import/export. These are then executed when <code>wasm-bindgen</code> runs!
These executions rely on an import called <code>__wbindgen_describe</code> which passes one
<code>u32</code> to the host, and when called multiple times gives a <code>Vec&lt;u32&gt;</code>
effectively. This <code>Vec&lt;u32&gt;</code> can then be reparsed into an <code>enum Descriptor</code>
which fully describes a type.</p>
<p>All in all this is a bit roundabout but shouldn't have any impact on the
generated code or runtime at all. All these descriptor functions are pruned from
the emitted wasm file.</p>
<h1><a class="header" href="#js-sys" id="js-sys"><code>js-sys</code></a></h1>
<p>The <a href="https://crates.io/crates/js-sys"><code>js-sys</code> crate</a> provides raw bindings to all the global APIs
guaranteed to exist in every JavaScript environment by the ECMAScript standard,
and its source lives at <a href="https://github.com/rustwasm/wasm-bindgen/tree/master/crates/js-sys"><code>wasm-bindgen/crates/js-sys</code></a>. With the <code>js-sys</code>
crate, we can work with <code>Object</code>s, <code>Array</code>s, <code>Function</code>s, <code>Map</code>s, <code>Set</code>s,
etc... without writing the <code>#[wasm_bindgen]</code> imports by hand.</p>
<p>Documentation for the published version of this crate is available on
<a href="https://docs.rs/js-sys">docs.rs</a> but you can also check out the <a href="https://rustwasm.github.io/wasm-bindgen/api/js_sys/">master branch
documentation</a> for the crate.</p>
<p>For example, we can invoke JavaScript <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function"><code>Function</code></a> callbacks and
time how long they take to execute with <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/now"><code>Date.now()</code></a>, and we
don't need to write any JS imports ourselves:</p>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
extern crate js_sys;
extern crate wasm_bindgen;
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
pub fn timed(callback: &amp;js_sys::Function) -&gt; f64 {
let then = js_sys::Date::now();
callback.apply(JsValue::null(), &amp;js_sys::Array::new()).unwrap();
let now = js_sys::Date::now();
now - then
}
#}</code></pre></pre>
<p>The <code>js-sys</code> crate doesn't contain bindings to any Web APIs like
<a href="https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelectorAll"><code>document.querySelectorAll</code></a>. These will be part of the
<a href="https://crates.io/crates/web-sys"><code>web-sys</code></a> crate.</p>
<h1><a class="header" href="#testing" id="testing">Testing</a></h1>
<p>You can test the <code>js-sys</code> crate by running <code>cargo test --target wasm32-unknown-unknown</code> within the <code>crates/js-sys</code> directory in the
<code>wasm-bindgen</code> repository:</p>
<pre><code class="language-sh">cd wasm-bindgen/crates/js-sys
cargo test --target wasm32-unknown-unknown
</code></pre>
<p>These tests are largely executed in Node.js right now via the
<a href="contributing/js-sys/../../wasm-bindgen-test/index.html"><code>wasm-bindgen-test</code> framework</a></p>
<h1><a class="header" href="#adding-support-for-more-javascript-global-apis" id="adding-support-for-more-javascript-global-apis">Adding Support for More JavaScript Global APIs</a></h1>
<p>As of 2018-09-24 we've <a href="https://github.com/rustwasm/wasm-bindgen/issues/275">added all APIs</a> in the current ECMAScript
standard (yay!). To that end you'll hopefully not find a missing API, but if you
do please feel free to file an issue!</p>
<p>We currently add new APIs added to ECMAScript that are in <a href="https://tc39.github.io/process-document/">TC39 stage 4</a>
to this crate. If there's a new API in stage 4, feel free to file an issue as
well!</p>
<h3><a class="header" href="#instructions-for-adding-an-api" id="instructions-for-adding-an-api">Instructions for adding an API</a></h3>
<ul>
<li><input disabled="" type="checkbox"/>
<p>Find the <code>wasm-bindgen</code> issue for the API you'd like to add. If this
doesn't exist, feel free to open one! Afterwards be sure to comment on the
issue to avoid duplication of work.</p>
</li>
<li><input disabled="" type="checkbox"/>
<p>Open the <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects">MDN
page</a>
for the relevant JS API.</p>
</li>
<li><input disabled="" type="checkbox"/>
<p>Open <code>crates/js-sys/src/lib.rs</code> in your editor; this is the file where we
are implementing the bindings.</p>
</li>
<li><input disabled="" type="checkbox"/>
<p>Follow the instructions in the top of <code>crates/js-sys/src/lib.rs</code> about how
to add new bindings.</p>
</li>
<li><input disabled="" type="checkbox"/>
<p>Add a test for the new binding to <code>crates/js-sys/tests/wasm/MyType.rs</code></p>
</li>
<li><input disabled="" type="checkbox"/>
<p>Run the <a href="contributing/js-sys/testing.html">JS global API bindings tests</a></p>
</li>
<li><input disabled="" type="checkbox"/>
<p>Send a pull request!</p>
</li>
</ul>
<h1><a class="header" href="#web-sys" id="web-sys"><code>web-sys</code></a></h1>
<p>The <code>web-sys</code> crate provides raw bindings to all of the Web's APIs, and its
source lives at <code>wasm-bindgen/crates/web-sys</code>.</p>
<p>The <code>web-sys</code> crate is <strong>entirely</strong> mechanically generated inside <code>build.rs</code>
using <code>wasm-bindgen</code>'s WebIDL frontend and the WebIDL interface definitions for
Web APIs. This means that <code>web-sys</code> isn't always the most ergonomic crate to
use, but it's intended to provide verified and correct bindings to the web
platform, and then better interfaces can be iterated on crates.io!</p>
<p>Documentation for the published version of this crate is available on
<a href="https://docs.rs/web-sys">docs.rs</a> but you can also check out the <a href="https://rustwasm.github.io/wasm-bindgen/api/web_sys/">master branch
documentation</a> for the crate.</p>
<h1><a class="header" href="#web-sys-overview" id="web-sys-overview"><code>web-sys</code> Overview</a></h1>
<p>The <code>web-sys</code> crate has this file and directory layout:</p>
<pre><code class="language-text">.
├── build.rs
├── Cargo.toml
├── README.md
├── src
│ └── lib.rs
└── webidls
└── enabled
└── ...
</code></pre>
<h3><a class="header" href="#webidlsenabledwebidl" id="webidlsenabledwebidl"><code>webidls/enabled/*.webidl</code></a></h3>
<p>These are the WebIDL interfaces that we will actually generate bindings for (or
at least bindings for <em>some</em> of the things defined in these files).</p>
<h3><a class="header" href="#buildrs" id="buildrs"><code>build.rs</code></a></h3>
<p>The <code>build.rs</code> invokes <code>wasm-bindgen</code>'s WebIDL frontend on all the WebIDL files
in <code>webidls/enabled</code>. It writes the resulting bindings into the cargo build's
out directory.</p>
<h3><a class="header" href="#srclibrs-16" id="srclibrs-16"><code>src/lib.rs</code></a></h3>
<p>The only thing <code>src/lib.rs</code> does is include the bindings generated at compile
time in <code>build.rs</code>. Here is the whole <code>src/lib.rs</code> file:</p>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
//! Raw API bindings for Web APIs
//!
//! This is a procedurally generated crate from browser WebIDL which provides a
//! binding to all APIs that browser provide on the web.
//!
//! This crate by default contains very little when compiled as almost all of
//! its exposed APIs are gated by Cargo features. The exhaustive list of
//! features can be found in `crates/web-sys/Cargo.toml`, but the rule of thumb
//! for `web-sys` is that each type has its own cargo feature (named after the
//! type). Using an API requires enabling the features for all types used in the
//! API, and APIs should mention in the documentation what features they
//! require.
#![doc(html_root_url = &quot;https://docs.rs/web-sys/0.2&quot;)]
#![allow(deprecated)]
mod features;
pub use features::*;
/// Getter for the `Window` object
///
/// [MDN Documentation]
///
/// *This API requires the following crate features to be activated: `Window`*
///
/// [MDN Documentation]: https://developer.mozilla.org/en-US/docs/Web/API/Window
#[cfg(feature = &quot;Window&quot;)]
pub fn window() -&gt; Option&lt;Window&gt; {
use wasm_bindgen::JsCast;
js_sys::global().dyn_into::&lt;Window&gt;().ok()
}
#}</code></pre></pre>
<h3><a class="header" href="#cargo-features" id="cargo-features">Cargo features</a></h3>
<p>When compiled the crate is almost empty by default, which probably isn't what
you want! Due to the very large number of APIs, this crate uses features to
enable portions of its API to reduce compile times. The list of features in
<code>Cargo.toml</code> all correspond to types in the generated functions. Enabling a
feature enables that type. All methods should indicate what features need to be
activated to use the method.</p>
<h1><a class="header" href="#testing-1" id="testing-1">Testing</a></h1>
<p>You can test the <code>web-sys</code> crate by running <code>cargo test</code> within the
<code>crates/web-sys</code> directory in the <code>wasm-bindgen</code> repository:</p>
<pre><code class="language-sh">cd wasm-bindgen/crates/web-sys
cargo test --target wasm32-unknown-unknown --all-features
</code></pre>
<p>The Wasm tests all run within a headless browser. See <a href="https://github.com/rustwasm/wasm-bindgen/blob/master/crates/test/README.md">the <code>wasm-bindgen-test</code>
crate's
<code>README.md</code></a>
for details and configuring which headless browser is used.</p>
<h1><a class="header" href="#logging" id="logging">Logging</a></h1>
<p>The <code>wasm_bindgen_webidl</code> crate (used by <code>web-sys</code>'s <code>build.rs</code>) uses
<a href="https://crates.io/crates/env_logger"><code>env_logger</code></a> for logging, which can be enabled by setting the
<code>RUST_LOG=wasm_bindgen_webidl</code> environment variable while building the <code>web-sys</code>
crate.</p>
<p>Make sure to enable &quot;very verbose&quot; output during <code>cargo build</code> to see these logs
within <code>web-sys</code>'s build script output.</p>
<pre><code class="language-sh">cd crates/web-sys
RUST_LOG=wasm_bindgen_webidl cargo build -vv
</code></pre>
<p>If <code>wasm_bindgen_webidl</code> encounters WebIDL constructs that it doesn't know how
to translate into <code>wasm-bindgen</code> AST items, it will emit warn-level logs.</p>
<pre><code>WARN 2018-07-06T18:21:49Z: wasm_bindgen_webidl: Unsupported WebIDL interface: ...
</code></pre>
<h1><a class="header" href="#supporting-more-web-apis-in-web-sys" id="supporting-more-web-apis-in-web-sys">Supporting More Web APIs in <code>web-sys</code></a></h1>
<ol>
<li>
<p><input type="checkbox"/> Ensure that the <code>.webidl</code> file describing the
interface exists somewhere within the <code>crates/web-sys/webidls/enabled</code>
directory.</p>
<p>First, check to see whether we have the WebIDL definition file for
your API:</p>
<pre><code class="language-sh">grep -rn MyWebApi crates/web-sys/webidls
</code></pre>
<ul>
<li>
<p>If your interface is defined in a <code>.webidl</code> file that is inside the
<code>crates/web-sys/webidls/enabled</code> directory, skip to step (3).</p>
</li>
<li>
<p>If your interface isn't defined in any file yet, find the WebIDL definition
in the relevant standard and add it as a new <code>.webidl</code> file in
<code>crates/web-sys/webidls/enabled</code>. Make sure that it is a standard Web API!
We don't want to add non-standard APIs to this crate.</p>
</li>
<li>
<p>If your interface is defined in a <code>.webidl</code> file within any of the
<code>crates/web-sys/webidls/unavailable_*</code> directories, you need to move it into
<code>crates/web-sys/webidls/enabled</code>, e.g.:</p>
<pre><code class="language-sh">cd crates/web-sys
git mv webidls/unavailable_enum_ident/MyWebApi.webidl webidls/enabled/MyWebApi.webidl
</code></pre>
</li>
</ul>
</li>
<li>
<p><input type="checkbox"/> Verify that the <code>web-sys</code> crate still builds and
that its tests still pass with the new <code>.webidl</code> file enabled:</p>
<pre><code class="language-sh">cd crates/web-sys
cargo build
cargo test
</code></pre>
</li>
<li>
<p><input type="checkbox"/> Verify that bindings are being generated for your new
API by generating the documentation and searching for the new API in it:</p>
<pre><code class="language-sh">cd crates/web-sys
cargo doc --open
# search for the new API in the opened docs
</code></pre>
<ul>
<li>
<p><input type="checkbox"/> If the new API is <strong>not</strong> showing up in the docs,
rebuild the <code>web-sys</code> crate <a href="contributing/web-sys/logging.html">with logging enabled</a>
and look for warning messages that mention your new API. Figure out why
bindings weren't generated and then add support to <code>wasm_bindgen_webidl</code> for
whatever is needed to generate your API's bindings.</p>
<blockquote>
<p>You might find it helpful to view the generated rust bindings, to see if
they are what you would expect. The file will be located at
<code>target/wasm32-unknown-unknown/debug/build/web-sys-xxx/out/bindings.rs</code>,
where <code>xxx</code> is a combinations of numbers and letters that represents your
build. This file is pretty unintelligable until you run <code>rustfmt</code> on it, like
<code>rustfmt target/wasm32-unknown-unknown/debug/build/web-sys-xxx/out/bindings.rs</code>.</p>
</blockquote>
<blockquote>
<p>There are commented out lines in <code>web-sys/build.rs</code> that run rustfmt as part of
the build process, and this can be very helpful for debugging as any error
messages with inline code will display it in a readable format.</p>
</blockquote>
</li>
</ul>
</li>
<li>
<p><input type="checkbox"/> Add tests for as many of the features in the WebIDL file
as possible to <code>crates/web-sys/tests/all/</code>. See the
<a href="contributing/web-sys/testing.html"><code>web-sys</code> testing documentation</a> for details.</p>
<blockquote>
<p><strong>Note</strong>: Start here at <strong>4</strong> if the WebIDL has already been added but doesn't have
full test coverage, then go back to <strong>3</strong> if you find any problems.</p>
</blockquote>
</li>
<li>
<p><input type="checkbox"/> If all entities in the WebIDL file have full test coverage,
mark the WebIDL script in the <code>README.md</code> file as complete by changing <code>[ ]</code> to <code>[x]</code>.</p>
</li>
<li>
<p><input type="checkbox"/> Send a pull request! 😊</p>
</li>
</ol>
<h1><a class="header" href="#publishing-new-wasm-bindgen-releases" id="publishing-new-wasm-bindgen-releases">Publishing New <code>wasm-bindgen</code> Releases</a></h1>
<ol>
<li>
<p><input type="checkbox"/> Compile the <code>publish.rs</code> script:</p>
<pre><code>rustc publish.rs
</code></pre>
</li>
<li>
<p><input type="checkbox"/> Bump every crate's minor version:</p>
<pre><code># Make sure you are in the root of the wasm-bindgen repo!
./publish bump
</code></pre>
</li>
<li>
<p><input type="checkbox"/> Send a pull request for the version bump.</p>
</li>
<li>
<p><input type="checkbox"/> After the pull request's CI is green and it has been
merged, publish to cargo:</p>
<pre><code># Make sure you are in the root of the wasm-bindgen repo!
./publish publish
</code></pre>
</li>
</ol>
<h1><a class="header" href="#team" id="team">Team</a></h1>
<p><code>wasm-bindgen</code> follows the <a href="https://github.com/rustwasm/team/blob/master/GOVERNANCE.md#repositories"><code>rustwasm</code> organization's governance described
here</a>:</p>
<ul>
<li>
<p>All pull requests (including those made by a team member) must be approved by
at least one other team member.</p>
</li>
<li>
<p>Larger, more nuanced decisions about design, architecture, breaking changes,
trade offs, etc are made by team consensus.</p>
</li>
</ul>
<h2><a class="header" href="#members" id="members">Members</a></h2>
<style>
img {
max-width: 117px;
max-height: 117px;
}
</style>
<p>| <a href="https://github.com/alexcrichton"><img src="https://github.com/alexcrichton.png?size=117" alt="" /></a> | <a href="https://github.com/fitzgen"><img src="https://github.com/fitzgen.png?size=117" alt="" /></a> | <a href="https://github.com/spastorino"><img src="https://github.com/spastorino.png?size=117" alt="" /></a> | <a href="https://github.com/ohanar"><img src="https://github.com/ohanar.png?size=117" alt="" /></a> | <a href="https://github.com/jonathan-s"><img src="https://github.com/jonathan-s.png?size=117" alt="" /></a> |
|:---:|:---:|:---:|:---:|
| <a href="https://github.com/alexcrichton"><code>alexcrichton</code></a> | <a href="https://github.com/fitzgen"><code>fitzgen</code></a> | <a href="https://github.com/spastorino"><code>spastorino</code></a> | <a href="https://github.com/ohanar"><code>ohanar</code></a> | <a href="https://github.com/jonathan-s"><code>jonathan-s</code></a> |
| <a href="https://github.com/sendilkumarn"><img src="https://github.com/sendilkumarn.png?size=117" alt="" /></a> | <a href="https://github.com/belfz"><img src="https://github.com/belfz.png?size=117" alt="" /></a> | <a href="https://github.com/afdw"><img src="https://github.com/afdw.png?size=117" alt="" /></a> | | |
| <a href="https://github.com/sendilkumarn"><code>sendilkumarn</code></a> | <a href="https://github.com/belfz"><code>belfz</code></a> | <a href="https://github.com/afdw"><code>afdw</code></a> | | |</p>
</main>
<nav class="nav-wrapper" aria-label="Page navigation">
<!-- Mobile navigation buttons -->
<div style="clear: both"></div>
</nav>
</div>
</div>
<nav class="nav-wide-wrapper" aria-label="Page navigation">
</nav>
</div>
<script src="elasticlunr.min.js" type="text/javascript" charset="utf-8"></script>
<script src="mark.min.js" type="text/javascript" charset="utf-8"></script>
<script src="searcher.js" type="text/javascript" charset="utf-8"></script>
<script src="clipboard.min.js" type="text/javascript" charset="utf-8"></script>
<script src="highlight.js" type="text/javascript" charset="utf-8"></script>
<script src="book.js" type="text/javascript" charset="utf-8"></script>
<!-- Custom JS scripts -->
<script type="text/javascript">
window.addEventListener('load', function() {
window.setTimeout(window.print, 100);
});
</script>
</body>
</html>