Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

consider adding flag to the WebAssembly.Function that passes first argument as JS receiver #21

Open
lukewagner opened this issue Sep 30, 2020 · 2 comments

Comments

@lukewagner
Copy link
Member

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".

@ghost
Copy link

ghost commented Jan 18, 2021

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)

@SPY
Copy link
Collaborator

SPY commented Oct 19, 2023

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));

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants
@SPY @lukewagner and others