NOTE: This is a
- reference DOM and other Web API objects directly from WebAssembly code;
- efficiently allocate and manipulate GC objects directly from WebAssembly code.
The following document is a high-level sketch of one approach for implementing the above goals. Consider the contents incomplete and expect change over time.
Opaque reference types
The first feature is to extend module imports to allow modules to import opaque reference types. "Opaque" means that the reference type itself has no structural content and does not, e.g., define any methods or fields. Once imported, an opaque reference type can be used in the signature of other imported functions. Thus, the point of an opaque reference type is to be passed to and returned from exported functions.
Reference types are allowed to be used as the types of locals, parameters
and return types. Additionally, references would be allowed as operands to
operators that treat their values as black boxes (
dynamic_cast operator would be added to allow checked
casting from any opaque reference type to any other opaque reference type.
Whether the cast succeeds is up to the host environment; WebAssembly itself
will define no a priori subtyping relationship.
For reasons of safety and limiting nondeterminism, imported opaque reference types would not be able to be loaded from or stored to linear memory where they could otherwise be arbitrarily aliased as integers. Instead, a new set of operators would be added for allocating, deallocating, loading and storing from integer-indexed cells that could hold references and were not aliasable by linear memory.
Using opaque reference types,
js module providing:
- an exported
stringopaque reference type and exported functions to allocate, query length, and index
- an exported
objectopaque reference type and exported functions that correspond with the ES5 meta-object protocol including the ability to
- further exported opaque reference types for symbols and value types (including SIMD);
- an exported
valueopaque reference type with exported functions for constructing
values from integers, floats,
strings, etc and with exported functions for querying the type of a
valueand extracting the abovementioned payload types.
Since a browser's WebAssembly engine would have full knowledge of the
builtin module, it should be able to optimize string/object accesses as well as
- WebIDL interfaces (like WebGLRenderingContextBase or WebGLTexture) would map to exported opaque reference types;
- methods of WebIDL interfaces would map to exported functions where the
receiver was translated into an explicit argument and WebIDL value
types were mapped to appropriate value types
would translate to
void (WebGLRenderingContextBase, int32, WebGLTexture?)).
This high-level description glosses over many important details about WebIDL:
- a signature declaration composed of language-independent data types (like IEEE754 doubles and floats);
- a set of basic wellformedness checks that are executed on the arguments of the signature declared in (1); and
(1) and (2) of the WebIDL spec are meaningful to WebAssembly, but (3) would effectively be skipped.
Another important issue is mapping WebIDL values types that aren't simple primitive types:
- The same goes for sequence types.
- Enumeration types could be mapped to canonical integers.
- Union types could be handled in multiple ways. One option is to treat the union type itself as an importable opaque reference type (when all the elements are themselves reference types). Another option is to introduce an overload of each signature for each element of the union type such that all calls passed a single element type and the full Union Type was never explicitly represented in WebAssembly.
- Callback function types
could map to a
(function pointer, environment pointer)closure pair.
In contrast to opaque reference types, a second feature would be to allow direct GC allocation and field access from WebAssembly code through non-opaque reference types.
There is a lot of the design left to consider for this feature, but a few points of tentative agreement are:
- To avoid baking in a single language's object model, define low-level GC primitives (viz., structs and arrays) and allow the source language compiler to build up features like virtual dispatch and access control.
- GC struct and array types would have associated struct/array reference types that were similar to and symmetric with opaque reference types (just not opaque).
- The GC heap would be semantically distinct from linear memory and thus the fields of GC objects could safely hold reference types (unlike linear memory).