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

wasm: browser compatibility policy #28360

Open
neelance opened this issue Oct 24, 2018 · 26 comments

Comments

@neelance
Copy link
Member

commented Oct 24, 2018

I would like to propose a discussion on how we want to handle browser compatibility. There are several features being worked on: https://github.com/WebAssembly/proposals When do we want to use them? Do we want to offer backwards-compatibility?

Here are my own thoughts, open for debate:

(1) Go's support for WebAssembly is experimental and it should stay experimental at least until WebAssembly itself is fully standardized (right now the main spec is still in "Phase 2 - Proposed Spec Text Available").

(2) The WebAssembly project itself has no clear answer yet on how feature tests and backwards compatibility should work, see https://webassembly.org/docs/feature-test/

(3) Modern browsers (except Safari) have auto-update mechanisms, so staying with the latest version shouldn't be an issue for most users.

Due to (1), (2) and (3) I would opt for no backwards compatibility as long as Go's support for WebAssembly is experimental.

New WebAssembly features can be adopted as soon as they are marked as "standardized" and are supported by the latest stable Chrome, Firefox, Edge and Safari (on desktop).

@neelance

This comment has been minimized.

Copy link
Member Author

commented Oct 24, 2018

@neelance neelance changed the title wasm: Browser compatibility policy wasm: browser compatibility policy Oct 24, 2018

@bradfitz

This comment has been minimized.

Copy link
Member

commented Oct 24, 2018

This bug is a little abstract, so this answer is somewhat vague, but:

I'm fine with treating experimental things as experimental, but we should start trying to minimize how often we break users for doing basic things using just the base "MVP WebAssembly" bits. It sounds like everybody's cool with the syscall/js.NewCallback change, but that's the sort of change we shouldn't be making every release.

For experimental new features of WebAssembly, I'd prefer them to be opt-in somehow with associated "This is super experimental!" documentation on the opt-in switch, at least where possible. At least document the state of the compatibility policy in, say, the syscall/js package comment and/or release notes.

@neelance

This comment has been minimized.

Copy link
Member Author

commented Oct 24, 2018

Yes, I agree that we should aim for keeping the API stable. This issue however was mainly about browser compatibility.

The features in question wouldn't add new API, but improve performance or reduce output size. Some examples:

  • a builtin memcpy operation
  • other operations that currently require a slow workaround
  • advanced memory operations so we don't have to request 1 GB of memory at startup
  • support for threads

Here are some options we have:

  • Not use the new features, stay with the MVP features. (This would mean suboptimal performance.)
  • Add compiler flags to choose which features to use. (Go usually avoids compiler flags.)
  • Output multiple wasm binaries using different feature sets.
  • Build a special decoder that can polyfill unsupported features at load time. (This will probably be the best solution at some point, but is also complicated and will likely be tackled by the WebAssembly project itself.)
  • No backwards compatibility for now.

Given these options I would prefer to not have backwards compatibility right now and as soon as feature testing is possible I would add some warning mechanism that tells the user to upgrade the browser.

@myitcv

This comment has been minimized.

Copy link
Member

commented Oct 24, 2018

I'm guessing we don't want to use different values of GOOS here? GOOS=chrome etc...

@neelance

This comment has been minimized.

Copy link
Member Author

commented Oct 24, 2018

I'm guessing we don't want to use different values of GOOS here? GOOS=chrome etc...

More GOOS or GOARCH values are cumbersome. Having just one for chrome wouldn't be enough, you would need to target browser versions or generations, e.g. wasm-10-2018.

@bradfitz

This comment has been minimized.

Copy link
Member

commented Oct 24, 2018

Let's use memcpy as an example:

Even without an official feature detection API, can we try to use it in runtime init & catch a fault & set a bool about whether to use it? We do that elsewhere in the runtime for other platforms.

Likewise with other stuff.

If we really can't feature detect at all, I'd say we shoudn't use stuff by default until it's in all the major browser's stable releases.

Worst case we could add a GOWASM environment variable like GOARM, GO386, GOMIPS, etc.

@theclapp

This comment has been minimized.

Copy link
Contributor

commented Oct 24, 2018

Add compiler flags to choose which features to use. (Go usually avoids compiler flags.)

Do you mean actual compiler flags like -a or -n, or build tags?

Of course, I imagine build tags would suffer from the same issue as GOOS mentioned previously: "Having just one for chrome wouldn't be enough, you would need to target browser versions or generations". But even so, it seems like build tags might allow more flexibility than compiler flags.

@bcmills bcmills added this to the Unreleased milestone Oct 24, 2018

@bcmills bcmills added the DevExp label Oct 24, 2018

@agnivade

This comment has been minimized.

Copy link
Member

commented Oct 24, 2018

can we try to use it in runtime init & catch a fault & set a bool about whether to use it? We do that elsewhere in the runtime for other platforms.

I think the issue is that the entire wasm code is validated AOT. As explained here (https://webassembly.org/docs/feature-test/) -

Since some WebAssembly features add operators and all WebAssembly code in a module is validated ahead-of-time, the usual JavaScript feature detection pattern:

if (foo)
    foo();
else
    alternativeToFoo();
won’t work in WebAssembly (if foo isn’t supported, foo() will fail to validate).

I would recommend against more flags or environment variables. Given that wasm is a fast moving platform and it is much easier to upgrade browsers than operating systems.

Not use the new features, stay with the MVP features. (This would mean suboptimal performance.)

Perhaps we can delay new features by one release, so that we give enough time for everybody to catch up to the latest browser version ?

@neelance

This comment has been minimized.

Copy link
Member Author

commented Oct 24, 2018

can we try to use it in runtime init & catch a fault & set a bool about whether to use it? We do that elsewhere in the runtime for other platforms.

I think the issue is that the entire wasm code is validated AOT.

Right. The WebAssembly loader will reject the binary if there are any unsupported operations. The runtime init will not be executed. Currently the only way to do feature detection is to try to load a wasm binary and if it fails then load a different binary.

If we really can't feature detect at all, I'd say we shoudn't use stuff by default until it's in all the major browser's stable releases.

In my first post I suggested "New WebAssembly features can be adopted as soon as they are marked as "standardized" and are supported by the latest stable Chrome, Firefox, Edge and Safari (on desktop)." @bradfitz This is exactly what you mean, isn't it?

Perhaps we can delay new features by one release, so that we give enough time for everybody to catch up to the latest browser version ?

Sounds like a good idea. Maybe 2 or 3 months after the feature has been released?

@bradfitz

This comment has been minimized.

Copy link
Member

commented Oct 24, 2018

In my first post I suggested "New WebAssembly features can be adopted as soon as they are marked as "standardized" and are supported by the latest stable Chrome, Firefox, Edge and Safari (on desktop)." @bradfitz This is exactly what you mean, isn't it?

Yeah.

But if you want to do better earlier, I think it'd be fine to use a GOWASM environment variable to opt-in to newer features that aren't as widely available.

The default should be to produce a binary that works everywhere, but if you want to use something more experimental that only works on one browser, GOWASM=threads,foo,bar seems fine to me at least.

@djhworld

This comment has been minimized.

Copy link

commented Oct 25, 2018

New WebAssembly features can be adopted as soon as they are marked as "standardized"

I think this should be the gate to decide whether to implement, rather than relying on the release train of the browsers.

I agree with @bradfitz though to maybe put the bleeding edge stuff behind some flags.

On the flipside that's getting back to the bad old days of "best ran on X browser!" badges, but that's not a Go problem 😄

@marwan-at-work

This comment has been minimized.

Copy link
Contributor

commented Nov 26, 2018

One reason to include new WASM features, and not wait 2-3 months, is that users of such features can give feedback on how Go interacts with them so that things are tuned/fixed by the time they are standardized.

@justinclift

This comment has been minimized.

Copy link

commented Nov 26, 2018

Yep, there are definitely people around in the Go Community who are chomping at the bit to try out the new browser Wasm capabilities, such as threads. Giving us the ability to try these bleeding edge things does help. 😄

@andreas-jonsson

This comment has been minimized.

Copy link

commented Mar 19, 2019

@neelance Do you know what would be needed/changed in the runtime to make threads a reality? (What are the challenges?)

Perhaps support could be added gradually first focus on atomic instructions and the bulk mem-ops...

Btw. Do we need bulk memory operations for threads in Go since the runtime only needs a pool of threads. (GOMAXPROCS) So re-initializing the data-segment would perhaps be okey?

Can I help in any way?

@neelance

This comment has been minimized.

Copy link
Member Author

commented Mar 19, 2019

I haven't yet started to look into threads and no concrete plans either. I think I'll wait until the proposal gets to phase 3: https://github.com/WebAssembly/proposals

How are bulk memory operations related to threads?

@bradfitz

This comment has been minimized.

Copy link
Member

commented Mar 19, 2019

By request from @neelance, let me restate my proposed policy from my earlier comment (#28360 (comment)) more clearly:

I think the Go default wasm output should be something that runs on the latest stable releases of Chrome, Edge, Safari, Firefox, iOS Safari, and Android Browser.

That is, WebAssembly should work by default "everywhere", where everywhere means those 6 browsers.

Anything that's either:

a) not supported by those 6 browsers,
b) not yet standardized by WebAssembly

.... should be behind a GOWASM=foo flag, since we can't really feature detect on webassembly at runtime.

@neelance

This comment has been minimized.

Copy link
Member Author

commented Mar 19, 2019

Okay, this is the same as I was proposing, except that you list more browsers.

To clarify: For Safari, iOS Safari and Android Browser, how exactly do we define "latest stable release"? New versions of these browsers are sometimes bound to OS upgrades.

@neelance

This comment has been minimized.

Copy link
Member Author

commented Mar 19, 2019

Based on https://go-review.googlesource.com/c/build/+/168060/1#message-869955fa1d2b803f63e4aa2b3ed0de87af2b5d9b I think we need to add:

c) not yet supported by the Node.js LTS release that gets shipped by Debian.

@bradfitz

This comment has been minimized.

Copy link
Member

commented Mar 19, 2019

To clarify: For Safari, iOS Safari and Android Browser, how exactly do we define "latest stable release"? New versions of these browsers are sometimes bound to OS upgrades.

Good point about Safari. For iOS, latest iOS is fine. That doesn't work quite as well for desktop, but I'm fine also saying latest macOS only there.

For Android Browser: that's evergreen these days, no?

c) not yet supported by the Node.js LTS release that gets shipped by Debian.

I'd soften that to say whatever Debian-provided stable-backports package exists. Currently that's:

https://packages.debian.org/stretch-backports/nodejs (8.11.1)

@neelance

This comment has been minimized.

Copy link
Member Author

commented Mar 19, 2019

For Android Browser: that's evergreen these days, no?

Could be, I'm not sure.

I'd soften that to say whatever Debian-provided stable-backports package exists.

This does not seem like a good choice to me. Reasons:

  • The backport does not seem properly maintained. Version 8.11.1 got released on 2018-03-29, but the latest 8.x release is 8.15.1 released on 2019-02-28. So the backported version is missing 3 security releases and countless bugfixes.
  • The current "active LTS" version of Node.js is 10.x, version 8.x is in "maintenance LTS" mode.
  • The latest Node.js 8.x, which is 8.15.1, ships with V8 6.2.414, which is the same as Chome 62 used, released on 2017-10-17. This seems pretty old.

So if this would be our requirement, then the browser requirements probably wouldn't matter any more.

@bradfitz

This comment has been minimized.

Copy link
Member

commented Mar 19, 2019

Would using latest active LTS be sufficient for you? Otherwise let's just ignore nodejs for our wasm policy reasons. Nodejs people with a few servers can update. Millions of end users with browsers is harder.

@neelance

This comment has been minimized.

Copy link
Member Author

commented Mar 20, 2019

Let's maybe postpone the decision until the other requirements are met and then we can see how much Node.js is behind.

@andreas-jonsson

This comment has been minimized.

Copy link

commented Mar 20, 2019

I haven't yet started to look into threads and no concrete plans either. I think I'll wait until the proposal gets to phase 3: https://github.com/WebAssembly/proposals

How are bulk memory operations related to threads?

Okey. Sorry. I thought the tread proposal for for wasm was at a much later state of development since it seemed to be supported in at least some browsers.

I think conditional segment initialization is part of that proposal. I guess something like that would be necessary to avoid initializing memory twice?

As a reference, this was a nice read about the subject.

@neelance

This comment has been minimized.

Copy link
Member Author

commented Mar 21, 2019

As a reference, this was a nice read about the subject.

Thanks, this is a good overview.

@bradfitz

This comment has been minimized.

Copy link
Member

commented May 2, 2019

We just updated our builders from nodejs v8.11.1 to nodejs v12.1.0 for #31282

But I continue to believe that Linux distros' current version of nodejs doesn't matter at all. Our WebAssembly version policy should be based solely on browsers.

@neelance

This comment has been minimized.

Copy link
Member Author

commented Aug 15, 2019

I did some testing of the current feature support:

  signext satconv
Node.js 10 (LTS) with flag with flag
Node.js 12.8.0 (current) yes yes
Chrome 76 yes yes
Chrome Mobile 75 yes yes
Firefox 68.0.2 yes yes
Edge 18 yes yes
Safari 12.1.1 no no
Safari Tech Preview 13.1 no no

It seems like Apple is not interested in supporting new WebAssembly features, even the Safari Tech Preview has no support.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
10 participants
You can’t perform that action at this time.