1# `final`
2
3The `final` attribute is the converse of the [`structural`
4attribute](structural.html). It configures how `wasm-bindgen` will generate JS
5imports to call the imported function. Notably a function imported by `final`
6never changes after it was imported, whereas a function imported by default (or
7with `structural`) is subject to runtime lookup rules such as walking the
8prototype chain of an object. Note that `final` is not suitable for accessing
9data descriptor properties of JS objects; to accomplish this, use the `structural`
10attribute.
11
12[host-bindings]: https://github.com/WebAssembly/host-bindings
13[reference-types]: https://github.com/WebAssembly/reference-types
14
15The `final` attribute is intended to be purely related to performance. It
16ideally has no user-visible effect, and `structural` imports (the default)
17should be able to transparently switch to `final` eventually.
18
19The eventual performance aspect is that with the [host bindings
20proposal][host-bindings] then `wasm-bindgen` will need to generate far fewer JS
21function shims to import than it does today. For example, consider this import
22today:
23
24```rust
25#[wasm_bindgen]
26extern "C" {
27    type Foo;
28    #[wasm_bindgen(method)]
29    fn bar(this: &Foo, argument: &str) -> JsValue;
30}
31```
32
33**Without the `final` attribute** the generated JS looks like this:
34
35```js
36// without `final`
37export function __wbg_bar_a81456386e6b526f(arg0, arg1, arg2) {
38    let varg1 = getStringFromWasm(arg1, arg2);
39    return addHeapObject(getObject(arg0).bar(varg1));
40}
41```
42
43We can see here that this JS function shim is required, but it's all relatively
44self-contained. It does, however, execute the `bar` method in a duck-type-y
45fashion in the sense that it never validates `getObject(arg0)` is of type `Foo`
46to actually call the `Foo.prototype.bar` method.
47
48If we instead, however, write this:
49
50```rust
51#[wasm_bindgen]
52extern "C" {
53    type Foo;
54    #[wasm_bindgen(method, final)] // note the change here
55    fn bar(this: &Foo, argument: &str) -> JsValue;
56}
57```
58
59it generates this JS glue (roughly):
60
61```js
62const __wbg_bar_target = Foo.prototype.bar;
63
64export function __wbg_bar_a81456386e6b526f(arg0, arg1, arg2) {
65    let varg1 = getStringFromWasm(arg1, arg2);
66    return addHeapObject(__wbg_bar_target.call(getObject(arg0), varg1));
67}
68```
69
70The difference here is pretty subtle, but we can see how the function being
71called is hoisted out of the generated shim and is bound to always be
72`Foo.prototype.bar`. This then uses the `Function.call` method to invoke that
73function with `getObject(arg0)` as the receiver.
74
75But wait, there's still a JS function shim here even with `final`! That's true,
76and this is simply a fact of future WebAssembly proposals not being implemented
77yet. The semantics, though, match the future [host bindings
78proposal][host-bindings] because the method being called is determined exactly
79once, and it's located on the prototype chain rather than being resolved at
80runtime when the function is called.
81
82## Interaction with future proposals
83
84If you're curious to see how our JS function shim will be eliminated entirely,
85let's take a look at the generated bindings. We're starting off with this:
86
87```js
88const __wbg_bar_target = Foo.prototype.bar;
89
90export function __wbg_bar_a81456386e6b526f(arg0, arg1, arg2) {
91    let varg1 = getStringFromWasm(arg1, arg2);
92    return addHeapObject(__wbg_bar_target.call(getObject(arg0), varg1));
93}
94```
95
96... and once the [reference types proposal][reference-types] is implemented then
97we won't need some of these pesky functions. That'll transform our generated JS
98shim to look like:
99
100```js
101const __wbg_bar_target = Foo.prototype.bar;
102
103export function __wbg_bar_a81456386e6b526f(arg0, arg1, arg2) {
104    let varg1 = getStringFromWasm(arg1, arg2);
105    return __wbg_bar_target.call(arg0, varg1);
106}
107```
108
109Getting better! Next up we need the host bindings proposal. Note that the
110proposal is undergoing some changes right now so it's tough to link to reference
111documentation, but it suffices to say that it'll empower us with at least two
112different features.
113
114First, host bindings promises to provide the concept of "argument conversions".
115The `arg1` and `arg2` values here are actually a pointer and a length to a utf-8
116encoded string, and with host bindings we'll be able to annotate that this
117import should take those two arguments and convert them to a JS string (that is,
118the *host* should do this, the WebAssembly engine). Using that feature we can
119futher trim this down to:
120
121```js
122const __wbg_bar_target = Foo.prototype.bar;
123
124export function __wbg_bar_a81456386e6b526f(arg0, varg1) {
125    return __wbg_bar_target.call(arg0, varg1);
126}
127```
128
129And finally, the second promise of the host bindings proposal is that we can
130flag a function call to indicate the first argument is the `this` binding of the
131function call. Today the `this` value of all called imported functions is
132`undefined`, and this flag (configured with host bindings) will indicate the
133first argument here is actually the `this`.
134
135With that in mind we can further transform this to:
136
137```js
138export const __wbg_bar_a81456386e6b526f = Foo.prototype.bar;
139```
140
141and voila! We, with [reference types][reference-types] and [host
142bindings][host-bindings], now have no JS function shim at all necessary to call
143the imported function. Additionally future wasm proposals to the ES module
144system may also mean that don't even need the `export const ...` here too.
145
146It's also worth pointing out that with all these wasm proposals implemented the
147default way to import the `bar` function (aka `structural`) would generate a JS
148function shim that looks like:
149
150```js
151export function __wbg_bar_a81456386e6b526f(varg1) {
152    return this.bar(varg1);
153}
154```
155
156where this import is still subject to runtime prototype chain lookups and such.
157