wasm-bindgen/contributing/design/importing-js-struct.html

451 lines
33 KiB
HTML

<!DOCTYPE HTML>
<html lang="en" class="sidebar-visible no-js">
<head>
<!-- Book generated using mdBook -->
<meta charset="UTF-8">
<title>Importing a class from JS - The `wasm-bindgen` Guide</title>
<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" class="active"><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="#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>
</main>
<nav class="nav-wrapper" aria-label="Page navigation">
<!-- Mobile navigation buttons -->
<a rel="prev" href="../../contributing/design/importing-js.html" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
<i class="fa fa-angle-left"></i>
</a>
<a rel="next" href="../../contributing/design/rust-type-conversions.html" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
<i class="fa fa-angle-right"></i>
</a>
<div style="clear: both"></div>
</nav>
</div>
</div>
<nav class="nav-wide-wrapper" aria-label="Page navigation">
<a href="../../contributing/design/importing-js.html" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
<i class="fa fa-angle-left"></i>
</a>
<a href="../../contributing/design/rust-type-conversions.html" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
<i class="fa fa-angle-right"></i>
</a>
</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 -->
</body>
</html>