-
Notifications
You must be signed in to change notification settings - Fork 74
No room to specify JS/embedder-specific prototype #211
Comments
In JS engines the prototype is stored as part of the hidden class/map/shape of an object. That corresponds rather directly to an RTT from the proposal, and they are in fact implemented as such e.g. in V8. So the canonical way to customise the prototype would be that the JS API provides a way to create custom RTTs and the Wasm module imports them. Potentially, the prototypes of Wasm-created objects could be fixed-from-inception, or the API could provide a way to mark them as such. But that would be rather alien to JS. No such mechanism exists elsewhere in JS for user objects (e.g., for ES6 classes), so the Wasm API seems like the wrong place to invent it. We may wish that instance prototypes were immutable by default, but JS is what it is, and engines have learnt to cope. You might not be aware that they already have extensive mechanisms to dynamically optimise for the absence of prototype mutation, and those apply to JS and Wasm-created objects alike. |
I haven't followed the GC proposal all that closely in quite some time, including the JS reflection, but when I worked on the Typed Objects companion proposal a few years back we settled on exactly this. |
I think this question (generalized to "what about the prototype?") is one aspect of the bigger question "what should the JS API for WasmGC look like?", which I consider a very open question. (We have MVP-JS.md, but IIUC everyone agrees that that's far from final, and we don't know what a closer-to-final version of that might look like.) I think on a very high level, there are two possible paths we could take: Regarding our strategy:
|
Thanks for all the responses above! @jakobkummerow What are you doing currently? (I understand that it's temporary; I'm just curious what it is at the moment and how the teams currently targeting the prototype are utilizing it for JS interop.) |
The current behavior of our prototype is that you can pass WasmGC structs/arrays to JS, where they will show up as opaque (empty-looking, as if it were We have also (slowly...) started exploring a prototype implementation of the basics of true interaction, where it will be possible to read/write struct/array fields as Edit to add: the teams targeting the prototype have said that for now they're mostly happy with using numeric Wasm types on the boundary. They're also interested in strings, but that's a whole separate discussion. |
Thanks for the update! I'm glad to hear y'all are looking into the wrapper-free approach, given that the research on efficient interop suggests wrappers can be quite problematic for performance. Regarding the edit, it sounds like the teams aren't looking into JS interop (yet) then. |
Actually, there are two separate questions: what prototypes Wasm objects start out with, and to what extent they are mutable. A null prototype could still be mutable. |
At Igalia we're concerned about the cost at the Wasm/JS boundary to constructing new wrapper objects (whether in the engine or in the toolchain), and so we'd like to investigate ways that Wasm GC structs can be directly represented to JavaScript without additional allocations. If this object will be used directly, the question in this issue of fixed vs mutable prototype seems quite relevant. From Ross:
From Till:
Speaking of Typed Objects, @syg, @littledan and others are in the early stages of developing a JS proposal on fixed-shape objects that would address some of the same goals (i.e., have a fixed prototype) while also enabling concurrent uses of such objects. However, it's not clear whether fields in such fixed-shape objects should have dynamically-enforced types, or just be untyped. Either way, the thought was that such fixed-shape objects would have immutable prototypes from the time they are created. There's a hope that such fixed-shape objects would correspond, at some level, to the way that Wasm GC structs are exposed at the JS API level, including the fixed prototype property (e.g., via the "way for applications to specify a custom prototype" mentioned earlier in the thread). Wasm GC structs may be more expressive (e.g., dynamically enforcing field types), but it would be great to align in other ways where possible, to reduce implementation burden for engines implementing the Wasm/JS API, and to provide a uniform mental model for JS developers who may use both fixed-shape objects and the JS representation of Wasm GC objects. |
Ah, good point on immutability of the prototype being useful for parallelism/concurrency! In prior discussions, similar concerns have been raised about supporting multithread-safe runtimes of Java and the like in wasm, wherein it's often important (for memory safety) that various aspects of v-tables and other runtime structures are immutable after initialization has completed (the "build and freeze" pattern). |
These concerns are resolved by the "no-frills" JS interop proposal (#279) we've settled on for the MVP. |
It would be good for GC objects be "immutable prototype exotic objects" in JS, i.e. the prototype is fixed. That enables a bunch of JS-side optimization (regardless of whether the prototype's contents are specified on the wasm side or the JS side) and builds in a (from what I understand) increasingly common defensive programming pattern (
Object.preventExtensions
was added in ES5 for this). However, there seems to be no way for a wasm program to indicate whichstruct
allocations are related, i.e. should have the same prototype. How is this being done or supposed to be done, or is the expectation that wasm objects will have mutable prototypes that need to be set by JS-side code each time they cross into JS?The text was updated successfully, but these errors were encountered: