This repo holds some sample / test code for the development of the WebAssembly Interface Types Proposal. Its purpose is to iterate on the proposal by letting us experiment with running code.
Individual demos live in folders. Given a folder named Foo:
- Foo/Foo_base.wat : Wasm code
- Foo/Foo_interface.wat : Interface annotations
- Foo/Foo.js : JS code to load and run Foo demo
Top-level scripts:
- webIDL.js : runtime polyfill, reads custom section and interprets it
- idl_custom_binary.py : script to parse @interface declarations from .wat and build the "interface-types" custom section
- Makefile : rules to build .wasm files from .wats
By convention, Interface Types are capitalized, where Wasm types are not (e.g. Int vs i32)
Type | Encoding | Description |
---|---|---|
Int |
0x7fff | integer number |
Float |
0x7ffe | floating-point number |
Any |
0x7ffd | opaque reference |
String |
0x7ffc | string data |
Instruction | Opcode | Immediates | Signature | Description |
---|---|---|---|---|
arg.get |
0x00 | param-index | [] -> [ty(param)] | Access the function's arguments |
call |
0x01 | import-index | sig(import) | Call a function import (Interface types) |
call-export |
0x02 | export-name | sig(export) | Call a function export (Wasm types) |
read-utf8 |
0x03 | [i32, i32] -> [String] | Read a string out of memory, given a pointer + length | |
write-utf8 |
0x04 | export-name | [String] -> [i32, i32] | Write a string into memory, return pointer + length |
as-wasm |
0x05 | wasm-type | [interfaceTy(wasm)] -> [wasm] | Cast an Interface type to a Wasm type |
as-interface |
0x06 | interface-type | [wasmTy(interface)] -> [interface] | Cast a Wasm type to an Interface type |
table-ref-add |
0x07 | [Any] -> [i32] | Add a reference to a table, returns an index for that reference | |
table-ref-get |
0x08 | [i32] -> [Any] | Given an index, return the reference associated | |
call-method |
0x09 | import-index | sig(import) | Call a function import, with the first argument bound as the this parameter |
make-record |
0x0a | type-index | fields(record) -> [record] | Creates a record object of a given type |
get-field |
0x0c | type, field-index | [record] -> [field(record)] | Gets a field value from a record object |
const |
0x0d | type, value | [] -> [type] | Pushes a constant value. Really only i32 at the moment |
fold-seq |
0x0e | import-index | [Seq] + sig(import) -> result(import) | Calls a function on every element of a sequence, carrying an accumulator value across |
add |
0x0f | type | [T, T] -> [T] | Add two numbers together |
mem-to-seq |
0x10 | type, memory-name | [i32, i32] -> [Seq] | Loads a pointer+length into a sequence |
load |
0x11 | type, memory-name | [i32] -> [T] | Loads a scalar value from memory |
seq.new |
0x12 | |||
list.push |
0x13 | |||
repeat-until |
0x14 | |||
seq-to-mem |
0x15 | |||
store |
0x16 |
repeat-until
takes two functions, a continuation predicate, and a next-step
predicate. Given an $cond
of type [b] -> [i32]
, and a $iter
of type
[a, b] -> [a, b]
, then the whole expression repeat-until $cond $iter
has
type [a, b] -> [a]
, where a
is an accumulator, and b
is a state parameter.
The current binary format in this repo is a placeholder format. In the future it should align with the proposed binary format.
There are five subsections:
- Exported function declarations
- Type declarations
- Imported function declarations
- Adapter functions
- Forwarded exports
leb_u32(x)
is an unsigned LEB with value no larger than a 32 bit number.
string(x)
is the length of the string x (leb_u32-encoded), followed by the
bytes of the string.
The bindings are represented as a custom section with the name
interface-types
. Custom sections follow a standard preamble:
0x00 ;; section ID, 0=custom
leb_u32(size) ;; size of the section
string("interface-types") ;; name of the section
Exported functions are declared here with a signature. This is redundant information, but makes polyfilling more convenient because we don't need to parse the whole wasm module to determine exported function signatures.
TODO: more
TODO
TODO
TODO
Makes use of the following V8 flags:
--experimental-wasm-anyref
Run on command line: node --experimental-wasm-anyref [.js file]
In Chrome: chrome --js-flags="--experimental-wasm-anyref"