Change the JsInterop bridge direction.
Earlier we were forwarding jsmethod at the first place it was exposed:
parent.prototype.m = function() { return this.m_obfuscated() };
This caused a code regression in Closure based apps as Closure fail
to prune anything due to missing type information. This basically left
an alias bride method for every jsmethod.
I changed the implementation so that the direction is reversed.
So we generate methods with pretty js names and then create a bridge
from obfuscated name only if
- method override a non-jsmethod
- there is no parent who created such bridge.
Change-Id: I3ae2b023c8406abe42dcb2acc1a1271a873364e9
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JMethod.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JMethod.java
index d01a2f0..ed39c7c 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/JMethod.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JMethod.java
@@ -107,10 +107,10 @@
}
private boolean isJsInterfaceMethod() {
- return isInterFaceMethod() && enclosingType.isJsType();
+ return isInterfaceMethod() && enclosingType.isJsType();
}
- private boolean isInterFaceMethod() {
+ private boolean isInterfaceMethod() {
return enclosingType instanceof JInterfaceType;
}
@@ -157,26 +157,25 @@
}
/**
- * Returns {@code true} if this method is the first method in the method hierarchy that exposes a
- * JsMethod inside a class.
+ * Returns {@code true} if this method is the first JsMethod in the method hierarchy that exposes
+ * an existing non-JsMethod inside a class.
*/
- public boolean exposesJsMethod() {
- if (isInterFaceMethod()) {
+ public boolean exposesNonJsMethod() {
+ if (isInterfaceMethod() || !isOrOverridesJsMethod()) {
return false;
}
- boolean isJsMethod = jsName != null;
- for (JMethod override : getOverriddenMethods()) {
- if (override.jsName == null) {
- continue;
+ boolean hasNonJsMethodParent = false;
+ for (JMethod overriddenMethod : overriddenMethods) {
+ if (!overriddenMethod.isOrOverridesJsMethod()) {
+ hasNonJsMethodParent = true;
}
- isJsMethod = true;
- if (!override.isInterFaceMethod()) {
+ if (overriddenMethod.exposesNonJsMethod()) {
return false; // some other method already exposed this method.
}
}
- return isJsMethod;
+ return hasNonJsMethodParent;
}
public boolean isOrOverridesJsMethod() {
@@ -484,7 +483,7 @@
boolean hasPackageVisibleParent = false;
for (JMethod overriddenMethod : overriddenMethods) {
- if (overriddenMethod.isInterFaceMethod()) {
+ if (overriddenMethod.isInterfaceMethod()) {
continue;
}
if (!overriddenMethod.isPackagePrivate()) {
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaScriptAST.java b/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaScriptAST.java
index fce135d..833c070 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaScriptAST.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaScriptAST.java
@@ -558,7 +558,11 @@
} else if (x.isPackagePrivate()) {
polyName = interfaceScope.declareName(mangleNameForPackagePrivatePoly(x), name);
} else {
- polyName = interfaceScope.declareName(mangleNameForPoly(x), name);
+ boolean isJsMethod = x.isOrOverridesJsMethod() && !x.isJsPropertyAccessor();
+ polyName =
+ isJsMethod
+ ? interfaceScope.declareUnobfuscatableName(x.getJsName())
+ : interfaceScope.declareName(mangleNameForPoly(x));
}
polymorphicNames.put(x, polyName);
}
@@ -1380,7 +1384,7 @@
private JsExpression dispatchToInstanceMethod(
JsExpression instance, JMethod method, List<JsExpression> args, SourceInfo sourceInfo) {
JsNameRef reference =
- method.isOrOverridesJsMethod()
+ method.isJsPropertyAccessor()
? new JsNameRef(sourceInfo, method.getJsName())
: polymorphicNames.get(method).makeRef(sourceInfo);
reference.setQualifier(instance);
@@ -2633,9 +2637,9 @@
generateVTableAssignment(globalStmts, method, polymorphicNames.get(method), rhs);
}
- if (method.exposesJsMethod()) {
- JsName jsName = interfaceScope.declareUnobfuscatableName(method.getJsName());
- generateVTableAlias(globalStmts, method, jsName);
+ if (method.exposesNonJsMethod()) {
+ JsName internalMangledName = interfaceScope.declareName(mangleNameForPoly(method));
+ generateVTableAlias(globalStmts, method, internalMangledName);
}
if (method.exposesPackagePrivateMethod()) {
diff --git a/user/test/com/google/gwt/core/client/interop/ConcreteJsType.java b/user/test/com/google/gwt/core/client/interop/ConcreteJsType.java
index ba5c362..74c89e4 100644
--- a/user/test/com/google/gwt/core/client/interop/ConcreteJsType.java
+++ b/user/test/com/google/gwt/core/client/interop/ConcreteJsType.java
@@ -26,6 +26,10 @@
return 10;
}
+ public int publicMethodAlsoExposedAsNonJsMethod() {
+ return 100;
+ }
+
public static void publicStaticMethod() {
}
diff --git a/user/test/com/google/gwt/core/client/interop/ConcreteJsTypeJsSubclass.java b/user/test/com/google/gwt/core/client/interop/ConcreteJsTypeJsSubclass.java
new file mode 100644
index 0000000..9e89e41
--- /dev/null
+++ b/user/test/com/google/gwt/core/client/interop/ConcreteJsTypeJsSubclass.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2015 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.core.client.interop;
+
+import com.google.gwt.core.client.js.JsType;
+
+/**
+ * This test class exposes parent jsmethod as non-jsmethod.
+ */
+@JsType
+class ConcreteJsTypeJsSubclass extends ConcreteJsType implements SubclassInterface {
+}
+
+interface SubclassInterface {
+ int publicMethodAlsoExposedAsNonJsMethod();
+}
diff --git a/user/test/com/google/gwt/core/client/interop/JsTypeTest.java b/user/test/com/google/gwt/core/client/interop/JsTypeTest.java
index edaf15c..3c6fe94 100644
--- a/user/test/com/google/gwt/core/client/interop/JsTypeTest.java
+++ b/user/test/com/google/gwt/core/client/interop/JsTypeTest.java
@@ -137,6 +137,16 @@
// RevealedOverrideSubType defines no functions itself, it only inherits them, but it still
// exports run() because it implements the @JsType interface JsTypeRunnable.
assertTrue(hasField(revealedOverrideSubType, "run"));
+
+ ConcreteJsTypeJsSubclass subclass = new ConcreteJsTypeJsSubclass();
+ assertEquals(100, subclass.publicMethodAlsoExposedAsNonJsMethod());
+ SubclassInterface subclassInterface = alwaysTrue() ? subclass : new SubclassInterface() {
+ @Override
+ public int publicMethodAlsoExposedAsNonJsMethod() {
+ return 0;
+ }
+ };
+ assertEquals(100, subclassInterface.publicMethodAlsoExposedAsNonJsMethod());
}
public void testConcreteNativeType() {