WebAssembly / interface-types

Other
641 stars 57 forks source link

Binding operators for pass-through functionality? #23

Open lars-t-hansen opened 5 years ago

lars-t-hansen commented 5 years ago

The current proposal allows WebIDL functions to be invoked on WebIDL values transparently and efficiently constructed from wasm linear memory, but what if what's in hand is a ref.host that has meaning when it's passed to a WebIDL function? Obvious cases are JS strings and views that flow into wasm from the host via anyref parameters and globals, and that are intended to be opaque to wasm. (Not a security matter, just engineering.). Should there be eg a js-str or perhaps better host-str operator like there is a utf8-str operator?

lars-t-hansen commented 5 years ago

Come to think of it, also dictionaries constructed from host-dict objects (ie JS objects in the JS setting).

lukewagner commented 5 years ago

The operator to use to pass a wasm reference type that doesn't need any sort of "interesting" coercion/construction (other than possibly a checked cast) is as, so you could use as webidl-type=DOMString to bind an anyref to a DOMString. And with type imports, one could import DOMString (somehow... strings are a bit tricky because they don't have constructors) and thus pass a (ref $DOMStringTypeImport) to as, thereby eliminating the essential downcast.

Dictionaries are an interesting case, because what we'd ultimately want to efficiently call the underlying browser-C++ function is the dictionary's fields as a fixed set of scalars, so if we pass a dictionary by reference type, we'd need the stub generator to destructure the dictionary, but wasm could do that just as well, passing the fields as scalars (as shown in the examples in the explainer), and thus laziness biases me towards not considering dictionaries "trivial" enough to be allowed as the target type of as.

jgravelle-google commented 5 years ago

Though I think we should support using WebIDL as a unified call-to-arbitrary-JS API. And for passing an arbitrary JS object, using as webidl-type=any should result in a wasm anyref. My understanding is this should work for nearly everything, though not any more efficiently than without the WebIDL binding section. If we do know more about the structure of the JS dictionary, we can use a more explicit binding than as.

@lukewagner, I'm confused about your explanation of dictionaries not being trivial enough to convert with as. I believe you're thinking of the case where we have a wasm anyref that we want to pass out to a known browser API with a pre-generated WebIDL signature? And you're saying that that would need extra work in the generated stub to handle, which we could do in wasm. If that's the case then in my head what this means is that we have a mismatch on the binding type vs the real type of the API, which should fall back to convert-via-js-api-plus-warning. So my confusion is the wording of dictionaries not being trivial enough to be "allowed" as a target of as, do you mean "not allowed to be passed efficiently" or do you mean "validation error if present" (though saying it out loud, I don't think the latter is actually possible? Unless I'm misunderstanding what a Dictionary is in this context?)

lukewagner commented 5 years ago

@jgravelle-google That's a great point/question: what happens if the binding uses an as conversion from anyref to any, and the actual imported Web IDL function type takes a Dictionary parameter? My suggestion above is that any is not compatible with Dictionary (because fundamentally this would require the wasm binding stub to perform JS-style destructuring of, well, anything, and so I think you're right: we can let this case be handled by fallback to the ECMAScript bindings which would Just Work (when the anyref value quacks like a dictionary duck).