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 · 47 comments
Open

wasm: browser compatibility policy #28360

neelance opened this issue Oct 24, 2018 · 47 comments
Labels
arch-wasm WebAssembly issues DevExp anything around developer experience
Milestone

Comments

@neelance
Copy link
Member

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
Copy link
Member Author

/cc @bradfitz @myitcv @dennwc @theclapp

@neelance neelance changed the title wasm: Browser compatibility policy wasm: browser compatibility policy Oct 24, 2018
@bradfitz
Copy link
Contributor

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
Copy link
Member Author

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
Copy link
Member

myitcv commented Oct 24, 2018

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

@neelance
Copy link
Member Author

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
Copy link
Contributor

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
Copy link
Contributor

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 anything around developer experience label Oct 24, 2018
@agnivade
Copy link
Contributor

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
Copy link
Member Author

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
Copy link
Contributor

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
Copy link

djhworld 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
Copy link
Contributor

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
Copy link

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
Copy link

@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
Copy link
Member Author

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
Copy link
Contributor

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
Copy link
Member Author

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
Copy link
Member Author

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
Copy link
Contributor

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
Copy link
Member Author

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
Copy link
Contributor

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
Copy link
Member Author

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
Copy link

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
Copy link
Member Author

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

Thanks, this is a good overview.

@neelance
Copy link
Member Author

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

@hajimehoshi
Copy link
Member

hajimehoshi commented Sep 2, 2020

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

Now WebAssembly is versioned 1.0, is this issue still valid?

@neelance
Copy link
Member Author

There is now a table that shows which browsers/engines support which WebAssembly features: https://webassembly.org/roadmap/

Unfortunately Safari is still showing no effort at all to keep up with the evolution of WebAssembly. I am not sure what to do... Would it be reasonable to drop support for Safari?

@advanderveer
Copy link

advanderveer commented Oct 11, 2020

There is now a table that shows which browsers/engines support which WebAssembly features: https://webassembly.org/roadmap/

Unfortunately Safari is still showing no effort at all to keep up with the evolution of WebAssembly. I am not sure what to do... Would it be reasonable to drop support for Safari?

I hope that decisions is not made lightly, Safari has almost a 17% market share according to these metrics. Maybe it is worth asking the WASM group how they are dealing with this and are in the know on how Safari's roadmap looks like (at least roughly)? Also, maybe it is worth investigating how other languages (Rust, C#) are dealing with Safari as a target for WASM improvements

I'm not a an expert and don't know what the 'signext' and 'satconv' features bring to the table. But maybe it can be left up to the developer to decide if they want to drop Safari support for those features?

@neelance
Copy link
Member Author

I hope that decisions is not made lightly

Just collecting data and feedback at the moment.

Safari has almost a 17% market share according to these metrics

Yes, this is why I am quite hesitant. However, I asked for feedback on the Gophers Slack and got 13 upvotes and zero downvotes for removing Safari, see https://gophers.slack.com/archives/C4GU6CHSQ/p1601418152003700.

Maybe it is worth asking the WASM group

Good idea. Feel free to do so if you find a proper place for asking. It fits the situation that on https://webassembly.org/community/feedback/ there are links for V8, Firefox and Edge, but not for Safari.

maybe it is worth investigating how other languages (Rust, C#) are dealing with Safari

I've looked into Rust and it seems that at the moment it still supports Safari.

I'm not a an expert and don't know what the 'signext' and 'satconv' features bring to the table.

This is not about signext and satconv. These can be toggled with a flag quite easily. With reference types or theads it would be much harder to support two modes at the same time.

@advanderveer
Copy link

Thank you for the quick response and hopefully it didn't feel like I was coming in too hot! I am just really hoping for Go to become a stable medium for targeting the web on all platforms and all browsers. Heck, i've even put a lot of effort into getting Go wasm to run on IE11. I basically stumbled upon this thread by accident and felt a bit disheartened that the decision to drop Safari was even on the table.

Of course I'm just a single voice on the internet and other's usecase may vary so - indeed - it is a good idea to gather more feedback. But I do believe that it needs a wider audience than just the Gopher slack. With your permission I will post a link to this discussion on the Golang subreddit and the golang-dev google groups.

The other side of the discussion is having overview of what is gained when Safari support is dropped. You mention Threads, maybe there are other important features. As my memory serves there is also an open issue to reduce the WASM filesize that requires browser advancements.

Good idea. Feel free to do so if you find a proper place for asking.

I was actually hoping that you in your official capacity as a maintainer for Go's WASM would have communications with the web assembly group in some sort of way. It's unlikely that I would get any insights in the Safari roadmap.

@neelance
Copy link
Member Author

Thank you for the quick response and hopefully it didn't feel like I was coming in too hot!

All good. 👍

i've even put a lot of effort into getting Go wasm to run on IE11.

Wow, nice! Couldn't we use this as a fallback for Safari, too?

With your permission I will post a link to this discussion on the Golang subreddit and the golang-dev google groups.

Sure, go ahead. Maybe golang-nuts instead of golang-dev, though.

The other side of the discussion is having overview of what is gained when Safari support is dropped.

I'll write a message to this thread as soon as it actively prevents me from starting to work on some feature.

As my memory serves there is also an open issue to reduce the WASM filesize that requires browser advancements.

That would probably be https://github.com/WebAssembly/funclets. Unfortunately the proposal is stalled because of politics (it would be very hard for V8 to support it).

I was actually hoping that you in your official capacity as a maintainer for Go's WASM would have communications with the web assembly group in some sort of way.

Nope, I have not.

@Splizard
Copy link

Splizard commented Oct 25, 2020

Would it be reasonable to drop support for Safari?

Keep in mind that Safari is the only way to target IOS.

@advanderveer
Copy link

@neelance Btw, I've posted the link to this thread on Reddit and Golang nuts yesterday.

@comaldave
Copy link

I am inclined to suggest that when a dev is preparing a marketing tool such as a website, they should target as wide of an audience as possible. Dropping Safari or IE11 is not prudent at this time as they are significant in the market though not primary.

Output multiple wasm binaries using different feature sets. Splash page detects browser capabilities and deploys appropriate solutions. Let the user decide if they want to use IOS, IE11, or upgrade. Give devs a standard app IPL to handle the alternatives. Do not ask the programmers if they want to drop Safari, they are not stakeholders, and do not ask the marketing guys who do make the decisions or you will end up using JavaScript.

In principle, be inclusive and serve the entire browser community, then optimize using new features using whatever implementation may be the most appropriate use of advanced technology.

@neelance
Copy link
Member Author

neelance commented Oct 27, 2020

@comaldave I have seen this position several times now. It seems like it is not clear that the options are not "less support" vs. "more support". Since it is mostly me working on WebAssembly and carrying legacy support is a lot of work, the options are more along "less support" vs. "no progress on WebAssembly for Go at all". I am working on this for free in my spare time and if I don't feel like putting in the effort for legacy support, then I won't do it. I am not trying to force some conclusion, I just want to point out my position and why I initially started this discussion. There is always a tradeoff.

@comaldave
Copy link

comaldave commented Oct 27, 2020 via email

@hajimehoshi
Copy link
Member

Safari will support threads! https://webkit.org/blog/11648/new-webkit-features-in-safari-14-1/

@skimhugo
Copy link

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?

@neelance According to this issue:WebAssembly/threads#163, the thread spec may never be stage 3..But it seems all browsers support this feature: https://webassembly.org/roadmap/

@neelance
Copy link
Member Author

From WebAssembly/threads#163:

the only thing missing for phase 3 is the test suite. The reason that is tricky is that the current test suite has no concept of threads, so there is some design work necessary to figure out how to extend it properly. That's what the conversation above is about.

Unfortunately (or fortunately?) there hasn't been much motivation to push on this because threads have already been shipped in all the major browsers.

This is such a strange situation. "Use threads, they are awesome enough so everyone has implemented them, but no one bothers enough to get them into the official standard." We have standardised almost everything on the web and new standards emerge regularly. There seem to be enough people that care about standards and push them forward. Where are they with regards to WebAssembly? Did they get lost?

Sorry for the rambling. With regards to Go and Wasm threads I guess a good way forward would be for someone to open a Go proposal for adding them, despite the situation with the standard. Then we can have an informed decision process.

@neelance
Copy link
Member Author

Wasm 2.0 is in the making. I'll try to give an overview:

Sign extension instructions

Go supports this with GOWASM set to signext. We should remove the opt-in after some other feature forced us to drop backwards-compatibility anyways.

Non-trapping float-to-int conversions

Go supports this with GOWASM set to satconv. We should remove the opt-in after some other feature forced us to drop backwards-compatibility anyways.

Multiple values

Useful for calls that use the Wasm ABI, e.g. WASI. Internally Go uses its own ABI, putting parameters and return values on the stack (linear memory) instead of using Wasm parameters and return values. One could consider to switch to the Wasm ABI in general, but this would be a huge effort and it would definitely need a decision on a Go proposal first, because I am not sure that the Go compiler team would be happy about adding such complexity.

Reference types & Table instructions

I think we could already use this to make the JS interop a bit simpler. The full potential will probably only unlocked by future Wasm proposals that have not been standardised yet.

Bulk memory and table instructions

We could definitely use these ops to speed up some memory operations that currently use loops. However, on its own it is probably not significant enough to justify dropping backwards-compatibility, so we would need to use a new GOWASM flag.

Vector instructions

I don't know much about SIMD. And Safari does not support them yet.

@ntindle
Copy link

ntindle commented Oct 9, 2022

[…] With regards to Go and Wasm threads I guess a good way forward would be for someone to open a Go proposal for adding them, despite the situation with the standard. Then we can have an informed decision process.

I would love to kick this process off. I believe this is the correct location? https://github.com/golang/proposal

@ianlancetaylor
Copy link
Contributor

@ntindle For the proposal process see https://go.dev/s/proposal (which may go to the same link, I'm not sure offhand).

@ntindle
Copy link

ntindle commented Oct 18, 2022

@neelance ^ this is the proposal. Let me know if you’d like any changes.

@gopherbot
Copy link

Change https://go.dev/cl/444935 mentions this issue: runtime: add wasm bulk memory operations

@neelance
Copy link
Member Author

I have looked at the state of things again. Seems like Safari is finally catching up: Safari 15 supports most of the Wasm 2.0 features.

However, since Safari is not really an evergreen browser, the older Safari versions still have some usage.

@bradfitz wrote above:

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.

There seems to be an option to compile Wasm to plain JS, so we could argue that if you are interested in backwards compatibility, then using this tool for producing a fallback is necessary anyways for browsers that don't support Wasm at all.

My conclusion would be that it is now the time to drop backwards-compatibility for Safari before version 15 (and equivalent other browsers/runtimes).

@ntindle
Copy link

ntindle commented Oct 26, 2022

@neelance ^ this is the proposal. Let me know if you’d like any changes.

The proposal was closed due to not containing an implementation design (though the proposals page explicitly says that’s not required).

Now that phase 3 is merged, what’s the next steps?

gopherbot pushed a commit that referenced this issue Oct 27, 2022
The existing implementation uses loops to implement bulk memory
operations such as memcpy and memclr. Now that bulk memory operations
have been standardized and are implemented in all major browsers and
engines (see https://webassembly.org/roadmap/), we should use them
to improve performance.

Updates #28360

Change-Id: I28df0e0350287d5e7e1d1c09a4064ea1054e7575
Reviewed-on: https://go-review.googlesource.com/c/go/+/444935
Reviewed-by: Cherry Mui <cherryyz@google.com>
Reviewed-by: Keith Randall <khr@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Run-TryBot: Richard Musiol <neelance@gmail.com>
Reviewed-by: David Chase <drchase@google.com>
Auto-Submit: Richard Musiol <neelance@gmail.com>
Reviewed-by: Richard Musiol <neelance@gmail.com>
romaindoumenc pushed a commit to TroutSoftware/go that referenced this issue Nov 3, 2022
The existing implementation uses loops to implement bulk memory
operations such as memcpy and memclr. Now that bulk memory operations
have been standardized and are implemented in all major browsers and
engines (see https://webassembly.org/roadmap/), we should use them
to improve performance.

Updates golang#28360

Change-Id: I28df0e0350287d5e7e1d1c09a4064ea1054e7575
Reviewed-on: https://go-review.googlesource.com/c/go/+/444935
Reviewed-by: Cherry Mui <cherryyz@google.com>
Reviewed-by: Keith Randall <khr@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Run-TryBot: Richard Musiol <neelance@gmail.com>
Reviewed-by: David Chase <drchase@google.com>
Auto-Submit: Richard Musiol <neelance@gmail.com>
Reviewed-by: Richard Musiol <neelance@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
arch-wasm WebAssembly issues DevExp anything around developer experience
Projects
None yet
Development

No branches or pull requests