WebAssembly / interface-types

Other
641 stars 57 forks source link

How to polyfill this proposal in JS? #58

Open alexcrichton opened 4 years ago

alexcrichton commented 4 years ago

This is intended to extract an explicit discussion point about polyfilling this proposal today. A good bit of discussion about this happened in https://github.com/WebAssembly/webidl-bindings/issues/25 already which led to https://github.com/WebAssembly/webidl-bindings/pull/26, and then this question is also coming up in https://github.com/WebAssembly/webidl-bindings/issues/57.

I think it's worth discussing what a JS polyfill for this proposal would look like and how it's envisioned to work. Much of the discussion so far seems to be centered around using existing WebAssembly APIs to inspect the module, extract custom sections, etc. This in turn was the motivation for #26 where you can't use WebAssembly to access functions by index, only by name. This is in turn starting to be considered as a design constraint for ideas like #57.

I would like to propose, however, that such a polyfill probably isn't suitable for this proposal at this time. This proposal currently depends on a number of distinct WebAssembly proposals that aren't yet stable:

(and this list may grow over time!)

This means that if you want to write a polyfill for this proposal today you won't be able to use existing WebAssembly JS APIs since any module using the above features will fail validation. My conclusion is that for a polyfill right-this-red-hot-second we'll need to have something much more intrusive which actually rewrites the bytes of the original WebAssembly file. (this is what wasm-bindgen does)

Thinking about this from a different angle I think that if we want to be able to polyfill this proposal today it's not sufficient to try to engineer the proposal so a shim only has to use WebAssembly JS APIs. Eventually I think this will probably be enabled, but it's not clear when all of the above proposals will land support in browser WebAssembly APIs.

jgravelle-google commented 4 years ago

I'd been operating under the assumption that we didn't need to make sure this was polyfillable today with JS APIs, just that it would be polyfillable with JS before landing. The core issue I think is one of "today".

My model had been, "using JS APIs that require no more dependencies than the proposal itself requires." So, given that the proposal has a dependency on multi-value and anyref, a JS polyfill can assume multi-value and anyref.

I think that's a reasonable way to limit the design of the feature itself; @lukewagner has said we don't want to add any capabilities that are impossible without this proposal, and a good way to validate that is to have a JS polyfill. That implies though that the JS polyfill would have access to the same set of dependencies of the proposal itself.

I'm not sure that such a polyfill is the most useful thing for developers to build against though. Another goal for a polyfill is to have something we can build against today, to get users before we have the fully-realized proposal.

Phrased this way I think a strategy is clear: two polyfills with separate goals. One to validate and iterate on the design, and one for real users. One implemented with JS APIs, and wasm-bindgen (or some similarly-intrusive tool).

Another strategy, I think that you were implying, is to challenge the assumption that we don't want to introduce new functionality here. I don't have as solid a picture in my of head of why that needs to be true, aside from giving a simpler mental model of what this proposal is and what it does. By not adding new functionality we're able to clearly define this proposal as being about ergonomics and performance, doing things we already could, but more conveniently, portably, and efficiently. Note that even with those limitations, I think the ergo+perf wins are sufficiently interesting. Are there interesting things we're leaving off the table by restricting ourselves to a polyfillable design?

fgmccabe commented 4 years ago

Well I thought that is did not actually have multivalues

On Fri, Aug 16, 2019 at 5:13 PM Jacob Gravelle notifications@github.com wrote:

I'd been operating under the assumption that we didn't need to make sure this was polyfillable today with JS APIs, just that it would be polyfillable with JS before landing. The core issue I think is one of "today".

My model had been, "using JS APIs that require no more dependencies than the proposal itself requires." So, given that the proposal has a dependency on multi-value and anyref, a JS polyfill can assume multi-value and anyref.

I think that's a reasonable way to limit the design of the feature itself; @lukewagner https://github.com/lukewagner has said we don't want to add any capabilities that are impossible without this proposal, and a good way to validate that is to have a JS polyfill. That implies though that the JS polyfill would have access to the same set of dependencies of the proposal itself.

I'm not sure that such a polyfill is the most useful thing for developers to build against though. Another goal for a polyfill is to have something we can build against today, to get users before we have the fully-realized proposal.

Phrased this way I think a strategy is clear: two polyfills with separate goals. One to validate and iterate on the design, and one for real users. One implemented with JS APIs, and wasm-bindgen (or some similarly-intrusive tool).

Another strategy, I think that you were implying, is to challenge the assumption that we don't want to introduce new functionality here. I don't have as solid a picture in my of head of why that needs to be true, aside from giving a simpler mental model of what this proposal is and what it does. By not adding new functionality we're able to clearly define this proposal as being about ergonomics and performance, doing things we already could, but more conveniently, portably, and efficiently. Note that even with those limitations, I think the ergo+perf wins are sufficiently interesting. Are there interesting things we're leaving off the table by restricting ourselves to a polyfillable design?

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/WebAssembly/webidl-bindings/issues/58?email_source=notifications&email_token=AAQAXUHCXBATHVTJIQB7EQ3QE47CJA5CNFSM4IMIRWAKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOD4P64UQ#issuecomment-522186322, or mute the thread https://github.com/notifications/unsubscribe-auth/AAQAXUAHCBRKU24RTTRZOJTQE47CJANCNFSM4IMIRWAA .

-- Francis McCabe SWE

alexcrichton commented 4 years ago

@jgravelle-google ah yeah those are some good points! This can also be construed as a question in terms of when we expect the polyfill to work, where a polyfill working today necessitates intrusive changes but a polyfill "tomorrow" means that the current design constraints fit nicely (e.g. using strings instead of indices).

FWIW I don't have a ton of experience with new web standards so this may be the case already (assuming that a polyfill isn't necessarily useful from day one but eventually the polyfill can be run), but the framing you mentioned of having two polyfills for both now and later seems pretty reasonable to me! I think it makes sense in that case to go ahead and design for the future polyfill rather than a today polyfill.

Are there interesting things we're leaving off the table by restricting ourselves to a polyfillable design?

AFAIK the strings-vs-indices is the only one so far, but it in theory could have large-ish ramifications if we start having something like a string subsection for interning. Otherwise though it's probably just something good to keep an eye out for!