Repository navigation
Multiple inheritance in the native component is ignored with RnWinRT. #212
Description
Activity
For a quick reference on behavior and functionality, interfaces have two important functions in WinRT that are relevant here:
QueryInterfaceandGetIids.QueryInterfaceis how you get a pointer to a particular interface that a type supports, andGetIidsis how a type "advertises" which interfaces it supports. In general, these two sets of interfaces - which Interfaces/IIDsQueryInterfacesupports and returns success/a valid pointer back for, as well as which IIDs are included in the list returned fromGetIids- should be the same (there's an exception where interfaces can support an interface, but not advertise it; these are typically referred to as "cloaked" interfaces, but this is not really relevant to this discussion). WinRT does not have proper interface inheritance. Therefore, although your idl definesINative2as deriving fromINative1, it really doesn't and instead only derives fromIInspectable. Therefore, in order to call functions on theINative1interface, consuming code would need to callQueryInterfacewithINative1's IID, get back a pointer to the interface, and then call the function.RnWinRT doesn't really deal with types in this way - the developer does not indicate which interface it wishes to invoke a particular function on. Instead, it relies on the
GetIidsfunction to get a list of supported interfaces on a per-object basis. Therefore, if you are seeing that you are able to invoke functions onINative1in non-JavaScript code (i.e. the code callsQueryInterface, which succeeds), but are unable to invoke the same functions on the same objects using RnWinRT (i.e.GetIidsdoes not advertise the interface), then there's a bug in your component. The type'sQueryInterfacemethod responds to bothINative1as well asINative2, whereas itsGetIidsonly advertisesINative2.That all said, interface requirements (which may "appear" to be like inheritance in idl definitions) do persist into the metadata (and I'm now slightly curious how Chakra handled this situation). So, in theory, we could modify each interface definition to have an additional array of required interfaces and then merge those into the
m_interfacesarray when constructing an object instance. I'm not a fan of that, however. This means more data, which means more binary bloat, and more runtime overhead to either de-duplicate interfaces on construction of an object interface, or to just add them all and then redundantly enumerate the same interfaces when looking for functions/properties. It seems much simpler and much more desirable for types to just behave as they are supposed to and advertise all interfaces that they support.
A native component I'm trying to reuse for React Native migration has multiple inheritance. A simplified code is like the following.
With this setup, only
method2()is projected to JavaScript, andmethod1()is unavailable. The following code is not traversing up the inheritance chain but only looking through the direct parents. ☹