js-types icon indicating copy to clipboard operation
js-types copied to clipboard

Review implementability of WebAssembly.Function

Open Ms2ger opened this issue 4 years ago • 11 comments

The snippet

interface Function : global.Function {
  static FunctionType type(Function func);
};

is not valid WebIDL, and I don't see a clear way to make it so.

Note that it's already possible (though a little tedious) to create a host function from a JS function:

function host_function(f, { parameters, results }) {
  const builder = new WasmModuleBuilder();
  const functionIndex = builder.addImport("module", "imported", { params: parameters, results });
  builder.addExport("exportedFunction", functionIndex);
  const buffer = builder.toBuffer();

  const module = new WebAssembly.Module(buffer);
  const instance = new WebAssembly.Instance(module, {
    "module": {
      "imported": f,
    }
  });

  return instance.exports.exportedFunction;
}

We could easily introduce this coercion in Table#set() as well, without necessarily introducing this new type.

Ms2ger avatar Apr 15 '20 13:04 Ms2ger

Thanks for bringing this up. The main motivation for adding the WebAssembly.Function constructor is to avoid the overhead of creating a module and an instance just for wrapping a host function for adding it to a WebAssembly.Table. Using this constructor is significantly faster at least in v8.

I am not sure what the original intention of inheriting from global.Function was. Maybe we can just drop that?

backes avatar Jun 30 '20 16:06 backes

Well, it has the prototype and properties of a regular function, i.e., is a subclass. If WebIDL has no way to describe that then we have to invent our own. :)

rossberg avatar Jun 30 '20 16:06 rossberg

@Ms2ger, we cannot build the conversion into Table#set, because it doesn't know the intended function type.

rossberg avatar Jun 30 '20 16:06 rossberg

Well, it has the prototype and properties of a regular function, i.e., is a subclass. If WebIDL has no way to describe that then we have to invent our own. :)

What is the intended effect then? Do we want typeof (new WebAssembly.Function([...])) to return "function"? I am not sure JS folks would sign off on that...

backes avatar Jun 30 '20 16:06 backes

What is the intended effect then? Do we want typeof (new WebAssembly.Function([...])) to return "function"?

I'd expect the answer to that to be "yes".

I am not sure JS folks would sign off on that...

Can you say more about why that would be the case? These are functions, and can be used in all the places functions can be used. Function can (in somewhat annoying ways, but still) be subclassed in JS right now, and instances of these subclasses have exactly this typeof behavior. See the code snippet in this SO question.

tschneidereit avatar Jun 30 '20 17:06 tschneidereit

What is the intended effect then? Do we want typeof (new WebAssembly.Function([...])) to return "function"?

Absolutely yes. In addition to what @tschneidereit said, that is what you get today for a Wasm exported function. Clearly that shouldn't change all of a sudden.

rossberg avatar Jul 01 '20 04:07 rossberg

Ah, I didn't know that it's possible in JS to subclass Function. In that case I agree that this is what we want. Weird that this is not expressible in WebIDL.

backes avatar Jul 01 '20 11:07 backes

@Ms2ger can you clarify what exactly the problem with the original snippet is? Is it that global.Function does not exist in WebIDL?

backes avatar Jul 01 '20 11:07 backes

That's certainly the first issue, yes.

Ms2ger avatar Jul 01 '20 11:07 Ms2ger

See whatwg/webidl#937 for the existing issue against WebIDL asking how to specify this.

ajklein avatar Oct 11 '23 10:10 ajklein

As I understand TC39 JSFunction interface could be reference in the same fashion as ArrayBuffer interface introduced in the spec. I overlooked this approach initially, but it looks right to me now. Implemented it in #45.

SPY avatar Oct 16 '23 08:10 SPY