Description
In GWT2 with JavaScriptObject it was possible to have exactly one subclass implement an interface - the compiler would detect this and where necessary devirtualize the calls and dispatch correctly to either plain java implementations or the single native implementation.
With JSO, there were two ways to implement these:
- provide a simple native java method which would use JSNI to invoke the true method
- provide an overlay method which would then call the appropriate native methods/properties
From the original design doc option 1 is still apparently possible in jsinterop-annotations assuming the interface itself can be modified to be marked as native ("A native @JsType
can only extend/implement native @JsType
s."), but option 2 is not possible at all ("A native @JsType
class can only have ... Final non-native JsOverlay methods that do not override any other methods").
In the context of GWT2 these limitations may not necessarily make sense, but with j2cl they clearly seem to, since the interface and implementation might be compiled separately, so generating the dispatch mechanism when the interface is transpiled would need to depend on knowing about the implementation.
Are there any suggested patterns to solve these sorts of issues? Ideas I've entertained and their downsides:
- Rewrite the interface to be marked as
@JsType(isNative=true)
and to only have declared members which 100% match the eventual JS implementation - this is not always possible when the interface comes from some upstream source (org.w3c.dom
,org.json
are some such examples where overlays can bridge the gap and let code share an interface). - "Monkeypatching" the underlying JS object solves the above by avoiding the need for overlays, but clearly adds its own level of ick
- Provide a java wrapper per native instance - clearly this adds a bit of runtime overhead, depending on how the interfaces are declared