js-types
js-types copied to clipboard
consider adding flag to the WebAssembly.Function that passes first argument as JS receiver
At the moment, the JS API specifies that, when calling a host function, undefined
is always passed as the receiver. With the addition of externref
, it would otherwise be possible to directly call built-in functions without an intermediate JS glue code function, so it's unfortunate to require a glue code function of the form:
function foo_called_from_wasm(receiver, arg1, arg2) {
foo.call(receiver, arg1, arg2);
}
when calling a method (which is almost every function defined by Web IDL).
As an explicit, configurable way to coerce a JS (including Web IDL) function into a wasm function, I think WebAssembly.Function
gives us a nice potential solution to this problem: add an optional dictionary parameter with an optional method
field (default false
) that indicates that the first wasm parameter should be rerouted to the receiver, as in the glue code above. So, for example, you could convert the DOM appendChild
method into something wasm could call via:
new WebAssembly.Function({parameters:["externref", "externref"]}, Node.prototype.appendChild, {method:true});
An aesthetic question is whether "method:true" (or whatever that property should be named) should be merged with the first parameter. It'd look nice, but technically this first parameter is supposed to be describing a wasm function type, so I'm guessing "no".
That sounds great, but is there any particular reason that it has to be the first parameter?
Could it be left to the code author to decide which parameter is the JS this
value?
Maybe a number instead?
const func = new WebAssembly.Function({ parameters: [ "externref", "externref" ] }, Node.prototype.appendChild, { this: 1 });
// starting at 0; 1 is the second parameter
func(child, this_element);
const func2 = new WebAssembly.Function({ parameters: [ "externref", "externref" ] }, Node.prototype.appendChild, { this: 2 });
// RangeError: function only has 2 parameters, index 2 is out of bounds
I'm personally more interested in calling Wasm functions by passing JS this
values to them.
Ex:
// (func (export "wasm_func") (param $this externref) (param $x i32)...
const object = { method: wasm_func };
object.method(10); // wasm_func(object, 10)
It is already doable with JS without glue code and in theory could be easily optimized by VMs(by unwrapping BoundFunctionExoticObject
of import)
new WebAssembly.Function({parameters:["externref", "externref"]}, Function.prototype.call.bind(Node.prototype.appendChild));