Fix compiler crash due to accidental override in native JsType. Bug: #9379 Bug-Link: https://github.com/gwtproject/gwt/issues/9379 Change-Id: I56319552d6a5cc58b3af93fe2d78c5093a226e34
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/JjsUtils.java b/dev/core/src/com/google/gwt/dev/jjs/impl/JjsUtils.java index 59dc479..425d876 100644 --- a/dev/core/src/com/google/gwt/dev/jjs/impl/JjsUtils.java +++ b/dev/core/src/com/google/gwt/dev/jjs/impl/JjsUtils.java
@@ -154,15 +154,22 @@ /** * Creates a synthetic forwarding stub in {@code type} with the same signature as - * {@code superTypeMethod} that dispatchs to that method.. + * {@code superTypeMethod} that dispatchs to that method. */ public static JMethod createForwardingMethod(JDeclaredType type, JMethod methodToDelegateTo) { JMethod forwardingMethod = createEmptyMethodFromExample(type, methodToDelegateTo, false); forwardingMethod.setForwarding(); - if (methodToDelegateTo.isJsOverlay() && type.isJsNative()) { - forwardingMethod.isJsOverlay(); + if (type.isJsNative()) { + if (methodToDelegateTo.isJsNative()) { + // Accidental override of native methods on native JsTypes are done by just redeclaring the + // native method. + return forwardingMethod; + } + // Otherwise the forwarding method is an overlay method with a proper body. + forwardingMethod.setJsOverlay(); + forwardingMethod.setBody(new JMethodBody(methodToDelegateTo.getSourceInfo())); } // Create the forwarding body.
diff --git a/user/test/com/google/gwt/core/interop/NativeJsTypeTest.java b/user/test/com/google/gwt/core/interop/NativeJsTypeTest.java index 2dc6762..2529d6e 100644 --- a/user/test/com/google/gwt/core/interop/NativeJsTypeTest.java +++ b/user/test/com/google/gwt/core/interop/NativeJsTypeTest.java
@@ -382,4 +382,42 @@ public void testUnreferencedNativeArrayInstanceOf() { assertTrue(createArray() instanceof UnreferencedNativeType[]); } + + @JsType(isNative = true, namespace = JsPackage.GLOBAL, name = "Object") + interface NativeInterface { + void add(String element); + } + + @JsType(isNative = true, namespace = JsPackage.GLOBAL, name = "Object") + static class NativeSuperClass { + public native void add(String element); + public native boolean remove(String element); + } + + @JsType(isNative = true, namespace = JsPackage.GLOBAL, name = "Object") + static class NativeSubClassAccidentalOverride + extends NativeSuperClass implements NativeInterface { + } + + public native NativeSubClassAccidentalOverride createNativeSubclass() /*-{ + return { + add: + function(e) { + this[0] = e; + }, + remove: + function(e) { + var ret = this[0] == e; + this[0] = undefined; + return ret; + } + }; + }-*/; + + public void testForwaringMethodsOnNativeClasses() { + NativeSubClassAccidentalOverride subClass = createNativeSubclass(); + subClass.add("Hi"); + assertTrue(subClass.remove("Hi")); + assertFalse(subClass.remove("Hi")); + } }