Skip to content
This repository was archived by the owner on Aug 17, 2022. It is now read-only.

Instanceof / Upcast equivalent #4

Closed
magcius opened this issue Nov 11, 2017 · 8 comments
Closed

Instanceof / Upcast equivalent #4

magcius opened this issue Nov 11, 2017 · 8 comments

Comments

@magcius
Copy link

magcius commented Nov 11, 2017

Host bindings, DOM in particular, use subclasses a lot. We would need some ability to do type discrimination. For instance, if I were to receive a DOMEvent object, I would likely want to be able to determine that this is DOMMouseEvent, and be able to call DOMMouseEvent-y things on it.

The details on runtime typechecking in the current proposal are vague (it just says "Throw TypeError (as now) if the wrong type is stored in a Table." but does not elaborate on what "the wrong type" means). Assuming that this is a strict 1:1 type-check, we would need some way to do runtime type discrimination, and a way to cast from one type to another.

Possible idea: a CAST instruction which takes two table indexes src and dest. The instruction checks src instanceof TableType(dest). If the check passes, 1 is pushed to the stack and the object's address copied into dest, so it exists in both tables. Otherwise, 0 is pushed to the stack. Cleanup for both src and dest is left to native code.

A variant of the instruction which takes a table index and a typeidx might also be entertained, in case of if (foo instanceof Type) checks that have no need to access the resulting casted object.

@magcius
Copy link
Author

magcius commented Nov 11, 2017

For cases where there is a limited number of host-provided subclasses (e.g. DOMEvent -> DOMMouseEvent), this is implementable in the binding itself (e.g. some host-provided DOMMouseEvent* DOMEvent_as_DOMMouseEvent(DOMEvent*) import generated from WebIDL)

This wouldn't solve cases with union types like HTMLCanvasElement::getContext, but that's already a pretty nasty stretch for WebIDL's type system.

@rossberg
Copy link
Member

You seem to suggest adding a JS-specific instruction to Wasm itself. That it is not an option, because Wasm has to remain independent of embeddings. The only option is to import a respective helper from the environment. The host binding framework might provide some aid for doing that.

@annevk
Copy link
Member

annevk commented Nov 13, 2017

For the kind of checks IDL does you don't want instanceof btw, you need brand checks as only those work across globals (see also whatwg/webidl#97).

@magcius
Copy link
Author

magcius commented Nov 13, 2017

I don't think there's anything JS-specific about casting host objects from one kind to another. Perhaps my choice of instanceof wording was poor, but there needs to exist some mechanism to translate DOMEvent* to DOMMouseEvent* and back. My preference is for this be runtime-checkable but we could simply make it trap instead on invalid cast.

If the solution is to generate host functions for every single type pair, that's fine, even if I think it's a bit strange.

@lukewagner
Copy link
Member

lukewagner commented Nov 14, 2017

We have definitely talked about a dynamic cast operator in the context of wasm GC types. If host types (like DOMEvent and DOMMouseEvent) are described as type imports (as previously discussed), then this could mostly fall out for free of the GC feature. Whether a cast from or to a host-type succeeds would, of course, be host defined (just like calling a host import).

However, with just the host binding feature, we don't have first-class reference types. We have talked (in CG meetings, not yet in this proposal) of having a copy_elem opcode which copies from one table element into another (in a same or different table); this is just a basic necessity. If we dropped the restriction that the source/dest tables had to have the exact same element type, that would imply a host-defined check, symmetric to the abovementioned dynamic cast operator.

@magcius
Copy link
Author

magcius commented Nov 15, 2017

That works for me. I would also like to propose some way of testing this at runtime. Assuming there are no implicit conversions in copy_elem, a can_copy_elem opcode that takes the same arguments and returns 1 if the equivalent copy_elem can be made and 0 otherwise would be a nice addition.

@lukewagner
Copy link
Member

Hmm, interesting. Right, because if a failed conversion traps, and traps are "expensive", a non-trapping query makes sense.

@pchickey
Copy link
Collaborator

Closing as out-of-date: these concepts don't map to the current proposal, which has evolved a lot since this issue was opened.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants