Web IDL Bindings Update
June 12-13, 2019
Google, Mozilla
Agenda
Progress Since Last Time
Summary of Current Proposal
wasm module
function import
function export
function import
function export
Web API function
params
results
JS values
wasm JS API spec
Web IDL values
Web IDL spec: ECMAScript Binding
JS glue code
Web API callback
params
results
JS values
wasm JS API spec
JS glue code
Web IDL values
Web IDL spec: ECMAScript Binding
wasm module
function import
params
results
wasm module
function export
params
results
In the MVP, ...
... when calling wasm
... when calling a Web API
Web IDL Bindings "wrap" the core module
Web IDL Bindings
wasm module
function import
function export
Web API function
Web API callback
params
results
Web IDL values
params
results
Web IDL values
Incoming binding exprs
Outgoing binding exprs
With the proposal...
... when calling a Web API
function import
function export
wasm module
function import
params
results
wasm module
function export
params
results
... when calling wasm
dictionary TextEncoderEncodeIntoResult {
unsigned long long read;
unsigned long long written;
};
interface TextEncoder {
TextEncoderEncodeIntoResult� encodeInto(USVString source,� Uint8Array destination);
};
https://github.com/WebAssembly/webidl-bindings/blob/master/proposals/webidl-bindings/Explainer.md
Note on values and copying
Prototype Work
Standalone Polyfill Prototype
https://github.com/jgravelle-google/wasm-webidl-polyfill
Building a webIDL.js module, reads a custom section and fixes up import + export dicts at runtime
Goals:
Integration in the Rust+Wasm Toolchain
Right Now
Sources
rustc/llvm
wasm-bindgen
wasm-bindgen
✓ Optional anyref
✗ No webidl bindings
✗ No anyref
✗ No webidl bindings
* Non-standard bindings
section
Vision for the Future
Sources
wasm-bindgen as optional AOT polyfill
rustc/llvm
wasm-bindgen
wasm-bindgen
Incremental Goal
Sources
rustc/llvm
wasm-bindgen
optional AOT polyfill
wasm-bindgen
wasm-bindgen
✗ No anyref
✗ No webidl bindings
* Non-standard bindings section
WebGL Experiment
// repeated for 20,000 primitives
glUniform1f(uScale, uniformData[i].scale);
glUniform1f(uTime, uniformData[i].time);
glUniform1f(uOffsetX, uniformData[i].offsetX);
glUniform1f(uOffsetY, uniformData[i].offsetY);
glUniform1f(uScalar, uniformData[i].scalar);
glUniform1f(uScalarOffset, uniformData[i].scalarOffset);
glDrawArrays(GL_TRIANGLES, 0, 3);
Methods
--- WebAssembly code ---
kind: wasm function
compiler: TurboFan
Body (size = 96 = 72 + 24 padding)
Instructions (size = 64)
0 55 push rbp
1 4889e5 REX.W movq rbp,rsp
4 6a0a push 0xa
6 56 push rsi
7 4883ec10 REX.W subq rsp,0x10
b 488d7de0 REX.W leaq rdi,[rbp-0x20]
f 8907 movl [rdi],rax
11 c5fb114f04 vmovsd [rdi+0x4],xmm1
16 488b7617 REX.W movq rsi,[rsi+0x17]
1a 4989e2 REX.W movq r10,rsp
1d 4883ec08 REX.W subq rsp,0x8
21 4883e4f0 REX.W andq rsp,0xf0
25 4c891424 REX.W movq [rsp],r10
29 48b8d06c171301000000 REX.W movq rax,0x113176cd0
33 ffd0 call rax
35 488b2424 REX.W movq rsp,[rsp]
39 488be5 REX.W movq rsp,rbp
3c 5d pop rbp
3d c3 retl
3e 90 nop
3f 90 nop
--- WebAssembly code ---
kind: wasm-to-js
compiler: TurboFan
Body (size = 608 = 588 + 20 padding)
Instructions (size = 516)
0 55 push rbp
1 4889e5 REX.W movq rbp,rsp
4 6a0c push 0xc
6 488b7e0f REX.W movq rdi,[rsi+0xf]
a 488b7607 REX.W movq rsi,[rsi+0x7]
e 56 push rsi
f 4883ec48 REX.W subq rsp,0x48
13 488b9e9f000000 REX.W movq rbx,[rsi+0x9f]
1a 488b4e77 REX.W movq rcx,[rsi+0x77]
1e 4c8b467f REX.W movq r8,[rsi+0x7f]
22 4d8b80d8300000 REX.W movq r8,[r8+0x30d8]
29 41c70000000000 movl [r8],0x0
30 4c8b471f REX.W movq r8,[rdi+0x1f]
34 4c8b4b2f REX.W movq r9,[rbx+0x2f]
38 c57b2cd9 vcvttsd2si r11,xmm1
3c c5f957c0 vxorpd xmm0,xmm0,xmm0
40 c4c17b2ac3 vcvtlsi2sd xmm0,xmm0,r11
45 48897c2430 REX.W movq [rsp+0x30],rdi
4a 4889742440 REX.W movq [rsp+0x40],rsi
4f c5fb114c2420 vmovsd [rsp+0x20],xmm1
55 c5fb11542408 vmovsd [rsp+0x8],xmm2
5b 48895c2438 REX.W movq [rsp+0x38],rbx
60 48894c2418 REX.W movq [rsp+0x18],rcx
65 4c89442410 REX.W movq [rsp+0x10],r8
6a 4c894c2428 REX.W movq [rsp+0x28],r9
6f c5f92ec1 vucomisd xmm0,xmm1
73 0f8a19000000 jpe 0x251a417d5412 <+0x92>
79 0f8513000000 jnz 0x251a417d5412 <+0x92>
7f 4183fb00 cmpl r11,0x0
83 0f84cf000000 jz 0x251a417d54d8 <+0x158>
89 49c1e320 REX.W shlq r11, 32
8d e913000000 jmp 0x251a417d5425 <+0xa5>
92 e813fdffff call 0x251a417d512a ;; wasm stub: WasmAllocateHeapNumber
97 c5fb10442420 vmovsd xmm0,[rsp+0x20]
9d c5fb114007 vmovsd [rax+0x7],xmm0
a2 4c8bd8 REX.W movq r11,rax
a5 c5fb2c5c2408 vcvttsd2si rbx,[rsp+0x8]
ab c5f957c0 vxorpd xmm0,xmm0,xmm0
af c5fb2ac3 vcvtlsi2sd xmm0,xmm0,rbx
b3 4c895c2420 REX.W movq [rsp+0x20],r11
b8 c5f92e442408 vucomisd xmm0,[rsp+0x8]
be 0f8a18000000 jpe 0x251a417d545c <+0xdc>
c4 0f8512000000 jnz 0x251a417d545c <+0xdc>
ca 83fb00 cmpl rbx,0x0
cd 0f84e4000000 jz 0x251a417d5537 <+0x1b7>
d3 48c1e320 REX.W shlq rbx, 32
d7 e913000000 jmp 0x251a417d546f <+0xef>
dc e8c9fcffff call 0x251a417d512a ;; wasm stub: WasmAllocateHeapNumber
e1 c5fb10442408 vmovsd xmm0,[rsp+0x8]
e7 c5fb114007 vmovsd [rax+0x7],xmm0
ec 488bd8 REX.W movq rbx,rax
ef ff742428 push [rsp+0x28]
f3 ff742428 push [rsp+0x28]
f7 53 push rbx
f8 b802000000 movl rax,0x2
fd 488b7c2448 REX.W movq rdi,[rsp+0x48]
102 488b542430 REX.W movq rdx,[rsp+0x30]
107 488b742428 REX.W movq rsi,[rsp+0x28]
10c 488b4f2f REX.W movq rcx,[rdi+0x2f]
110 4883c13f REX.W addq rcx,0x3f
114 ffd1 call rcx
116 488b742438 REX.W movq rsi,[rsp+0x38]
11b e850fdffff call 0x251a417d51f0 ;; wasm stub: WasmToNumber
120 488bd8 REX.W movq rbx,rax
123 4883e301 REX.W andq rbx,0x1
127 0f85a9000000 jnz 0x251a417d5556 <+0x1d6>
12d 48c1e820 REX.W shrq rax, 32
131 c5f957c0 vxorpd xmm0,xmm0,xmm0
135 c5fb2ac0 vcvtlsi2sd xmm0,xmm0,rax
139 488b5c2440 REX.W movq rbx,[rsp+0x40]
13e 488b5b7f REX.W movq rbx,[rbx+0x7f]
142 488b9bd8300000 REX.W movq rbx,[rbx+0x30d8]
149 c70301000000 movl [rbx],0x1
14f c5f928c8 vmovapd xmm1,xmm0
153 488be5 REX.W movq rsp,rbp
156 5d pop rbp
157 c3 retl
158 660f3a16cb01 pextrd rbx,xmm1,1
15e 4c891c24 REX.W movq [rsp],r11
162 83fb00 cmpl rbx,0x0
165 0f8c28000000 jl 0x251a417d5513 <+0x193>
16b 488b5c2438 REX.W movq rbx,[rsp+0x38]
170 488b7c2430 REX.W movq rdi,[rsp+0x30]
175 4c8b4c2428 REX.W movq r9,[rsp+0x28]
17a 488b4c2418 REX.W movq rcx,[rsp+0x18]
17f 4c8b442410 REX.W movq r8,[rsp+0x10]
184 c5fb10542408 vmovsd xmm2,[rsp+0x8]
18a 4c8b1c24 REX.W movq r11,[rsp]
18e e9f6feffff jmp 0x251a417d5409 <+0x89>
193 488b5c2438 REX.W movq rbx,[rsp+0x38]
198 488b7c2430 REX.W movq rdi,[rsp+0x30]
19d 4c8b4c2428 REX.W movq r9,[rsp+0x28]
1a2 488b4c2418 REX.W movq rcx,[rsp+0x18]
1a7 4c8b442410 REX.W movq r8,[rsp+0x10]
1ac c5fb10542408 vmovsd xmm2,[rsp+0x8]
1b2 e9dbfeffff jmp 0x251a417d5412 <+0x92>
1b7 48891c24 REX.W movq [rsp],rbx
1bb 8b5c240c movl rbx,[rsp+0xc]
1bf 488b742440 REX.W movq rsi,[rsp+0x40]
1c4 83fb00 cmpl rbx,0x0
1c7 0f8c0fffffff jl 0x251a417d545c <+0xdc>
1cd 488b1c24 REX.W movq rbx,[rsp]
1d1 e9fdfeffff jmp 0x251a417d5453 <+0xd3>
1d6 488b742440 REX.W movq rsi,[rsp+0x40]
1db 48394677 REX.W cmpq [rsi+0x77],rax
1df 0f840a000000 jz 0x251a417d556f <+0x1ef>
1e5 c5fb104007 vmovsd xmm0,[rax+0x7]
1ea e94affffff jmp 0x251a417d54b9 <+0x139>
1ef c5f976c0 vpcmpeqd xmm0,xmm0,xmm0
1f3 c5f973f034 vpsllq xmm0,xmm0,52
1f8 c5f973d001 vpsrlq xmm0,xmm0,1
1fd e937ffffff jmp 0x251a417d54b9 <+0x139>
202 90 nop
203 90 nop
Safepoints (size = 72)
97 0011011110000 (sp -> fp)
e1 0011111110000 (sp -> fp)
116 0000000110000 (sp -> fp)
120 0000000010000 (sp -> fp)
RelocInfo (size = 7)
wasm stub call
wasm stub call
wasm stub call
--- End code ---
Results
Additional Uses Identified
WASI
🤯
... until Web IDL Bindings: int puts(DOMString str)
Kinds of WebAssembly Linking (of compiled code)
bar/src
foo/src
Static Linking
compile
compile
.a
.a
link
.wasm
Instance
Memory + Table
load
bar/src
foo/src
Dynamic Linking
load+link
Instance
Memory + Table
compile
compile
.wasm
.wasm
Instance
bar/src
foo/src
Shared-Nothing Linking
load+link
Instance
Memory + Table
compile
compile
.wasm
.wasm
Instance
Memory + Table
With ESM-integration in Node, what should packages contain?
bar/src
foo/src
Static Linking
compile
compile
.a
.a
link
.wasm
Instance
Memory + Table
load
bar/src
foo/src
Dynamic Linking
load+link
Instance
Memory + Table
compile
compile
.wasm
.wasm
Instance
bar/src
foo/src
"Shared-Nothing" Linking
load+link
Instance
Memory + Table
compile
compile
.wasm
.wasm
Instance
Memory + Table
?
at least
as a default
How do non-scalars get copied between memories?
How do non-scalars get copied between memories?
How do non-scalars get copied between memories?
A star (topology) is born
Web�IDL�values
Web
APIs
JS
wasm�module�A
WASI
wasm�module�B
Web IDL ECMAScript Binding �(Section 3 of Web IDL spec)
Binding Expressions (specified by A)
Binding Expressions (specified by B)
Identity function
Note: We're not attempting to solve the general "inter-language interoperability" problem here. We're sending immutable Web IDL values between parties, so languages are interoperable only insofar as they already are via Unix pipes (where reference values = file descriptors).
Note: Nowhere are we specifying a binary serialization format. (A host API could define one at a spoke, though.)
Is the center node really "Web IDL"?
Proposed spec factoring
wasm spec
unchanged
wasm ☃Bindings spec
new spec document defining:
☃Binding values + ☃Binding exprs + ☃Binding types
(symmetric to current Web IDL Bindings Explainer)
new cases in `read the imports`, `ToJSValue`, `ToWebAssemblyValue`
wasm JS API spec
Web IDL spec
new "WebAssembly Bindings" section, sibling to "ECMAScript Bindings".
WASI spec
Name not finalized
☃=
JS spec
unchanged
☃Binding Types rough sketch
reftype ::= ... all the core wasm reference types, including references to type imports
numtype ::= s8 | u8 | s16 | u16 | s32 | u32 | s64 | u64 | f32 | f64 // because signedness matters
bindingtype ::= // ↔ Web IDL type� reftype | // ↔ any, Interface, Promise, ...� numtype | // ↔ byte, octet, short, ...� string | // ↔ DOMString (need to think about USVString...)� bytes | // ↔ ArrayBuffer� numtype view | // ↔ Int8Array, Uint8Array, ...� bindingtype list | // ↔ Sequence� record{ (lbl: bindingtype)* } | // ↔ Dictionary� variant{ (lbl: bindingtype)* } | // ↔ Union, Enumeration� func(bindingtype* → bindingtype*) // ↔ Callback function
These look a lot like
wasm GC typedefs,
it might be elegant to unify... but labels (because dictionaries)
☃Binding Expressions sampler
s16
i32
i32
as
as
ref T
ref T
ref T
as
as
string
utf8-mem-str
alloc-utf8-mem-str $alloc $free
i32
i32
i32
i32
ref array u8
utf8-gc-str
ref array u8
alloc-utf8-gc-str
ref T
T=string
as
ref T
T=string
as
record {� x:string,
y:string�}
string
string
record
...
...
string
string
...
...
field "x"
field "y"
ref struct ...
as
ref struct ...
as
outgoing / lifting expression
incoming / lowering expression
wasm type
wasm type
binding�type
Refactored star(-ish) topology
Web
APIs
JS
wasm�module�A
WASI
wasm�module�B
Web IDL spec: ECMAScript Binding
☃Binding Expressions (specified by A)
☃Binding Expressions (specified by B)
Identity function
☃Binding�types
Web IDL
Web IDL spec: WebAssembly Binding
Frequently Asked Questions
Poll
Guidance from CG to do more work to refactor the Web IDL Bindings spec in the manner proposed (with future poll to actually accept refactoring).