threads icon indicating copy to clipboard operation
threads copied to clipboard

Potential web compatibility issue with exports of globals

Open littledan opened this issue 8 years ago • 18 comments

From Globals.md, in the WebAssembly.Instance constructor

  1. if e is a global instance g with global_type gt:
    1. Return a new WebAssembly.Global with [[Global]] set to g and [[GlobalType]] set to gt.

Does this apply even for existing, immutable globals? It seems like if a website is using the global values with WebAssembly now, this would change how they would have to use it, resulting in a potential compatibility issue. Or am I understanding this wrong?

One workaround would be to expose constants as their value, and expose mutable globals as a WebAssembly.Global. This could still allow constant WebAssembly.Global objects to be constructed and used as imports.

littledan avatar Oct 20 '17 12:10 littledan

Yeah, there is a potential compatibility risk here, but I think it's low, and decided having uniformity is nicer. I believe we came to the same conclusion at a CG meeting as well, let me see if I can find it.

edit: can't seem to find it. Perhaps someone else knows where this was discussed (or am I imagining it?)

binji avatar Oct 20 '17 17:10 binji

Is the expectation then that no one is using global exports? Maybe they could just be omitted for now so that no one starts depending on them, until browsers are ready to ship threads.

littledan avatar Oct 22 '17 10:10 littledan

The hope was that the existing usage would be covered by the @@toPrimitive hook, and most users won't care that they're getting a different object under the hood. I also doubt that many people are using global exports. But admittedly, we haven't looked into this.

binji avatar Oct 22 '17 16:10 binji

I know this is sort of ugly, but if we want uniformity of API on the one side and compatibility on the other, could we solve this with a flag on the export s.t. if the flag is set we get a WebAssembly.Global instance and if the flag is not set we get the value? For mutable globals it could(*) be an error if the flag is not set.

The flag might actually have to show up as a new external_kind that can only be used with a Global definition (not with global imports). Kind=3 would be renamed as 'Global value', Kind=4 might be 'Global cell'.

For that matter, could/should this distinction be made to apply to imports in some way? If the flag is not set, the import has to be a value, as before; if it is set, the import has to be a cell.

(*) Logically that's not necessary, you'd just get a snapshot of the value of the global, as you in a sense do for immutable globals.

lars-t-hansen avatar Nov 23 '17 13:11 lars-t-hansen

A flag in the wasm binary format?

littledan avatar Nov 24 '17 07:11 littledan

Yes, in the binary format. It's possible something would then also be needed in the textual format to express exporting immutable globals as WebAsssembly.Global, say, (global (export "g" box) i32 (i32.const 37)).

lars-t-hansen avatar Nov 24 '17 07:11 lars-t-hansen

Since this is solely a JS side matter, the only suitable place to add such information would be the JS host binding section. But is it really necessary?

rossberg avatar Nov 24 '17 08:11 rossberg

I don't see the need for something in the binary format. If web compatibility is a concern that isn't considered to be handled by @@toPrimitive, what would be the disadvantage of exporting immutable globals as they are (bare Numbers) and exporting mutable globals as WebAssembly.Global objects?

littledan avatar Nov 26 '17 09:11 littledan

@rossberg I understand the layering issue that it's better to keep it in the host binding section, but to give the uniformity that @lars-t-hansen is looking for, how would you handle it purely there? A specialized custom section for this purpose?

littledan avatar Nov 26 '17 09:11 littledan

to give the uniformity that @lars-t-hansen is looking for,

Personally I don't care a whit about uniformity, I merely wrote down a thought in response to the preceding discussion, which had cast doubt on whether uniformity (as designed in the proposal) was compatible with the web.

lars-t-hansen avatar Nov 26 '17 12:11 lars-t-hansen

Yeah, I was pushing for uniformity mostly because I didn't think it would be an issue. But if it is (or if we think it may be, and aren't sure) then I think it's OK to just do what you said @littledan: bare numbers for immutable globals and WebAssembly.Global for mutable globals.

binji avatar Nov 26 '17 20:11 binji

Personally, I value the uniformity and think the @@toPrimitive solution is a good idea and the compatibility risk is pretty low at this early stage. I think we should try to do it, as in ship the "breaking" change ASAP, see if it breaks anything in practice and go the non-uniform backwards-compatible route otherwise.

lukewagner avatar Nov 27 '17 18:11 lukewagner

If we want to rip the bandaid off as fast as possible, should we make the change to WebAssembly.Global objects now, even before threads are shipped?

littledan avatar Nov 27 '17 21:11 littledan

That's a good idea. It might be worth bringing up at the CG how this would go through the phases, considering it's a JS facing change only.

binji avatar Nov 27 '17 21:11 binji

We discussed this at the Nov 28 CG. Some notes:

  • It's useful to have WebAssembly.Global for immutable globals, since we may not be able to express the type in JS but we still may want to wire up between two wasm instances (for i64 or maybe some future type).
  • You'll have to specify at creation whether a WebAssembly.Global is mutable
  • An immutable global cannot be imported as mutable, nor a mutable global imported as immutable

As for the breaking change, @lukewagner will look into testing this with Firefox nightly

binji avatar Nov 28 '17 18:11 binji

I've implemented enough of the breaking change in Firefox to experiment with this. Specifically: there is a WebAssembly.Global type that can represent globals (only immutable, for now); the instance's export object contains instances of WebAssembly.Global instead of the exported globals' values; and the import descriptor can hold either raw values or WebAssembly.Global objects. With this change, a small number of test cases had to be updated, but both Tanks and Zen Garden run as they should.

So now I guess we need to figure out whether/when we can ship this on the Nightly channel to see if anyone complains about altered functionality...

lars-t-hansen avatar Jan 11 '18 08:01 lars-t-hansen

Patches on https://bugzil.la/1412238, work in progress.

lars-t-hansen avatar Jan 11 '18 08:01 lars-t-hansen

Landed. See forked bug for more.

lars-t-hansen avatar Jan 26 '18 08:01 lars-t-hansen