Revision: 9542
Author: knor...@google.com
Date: Thu Jan 13 15:08:15 2011
Log: Fixes a bug in JavaScriptObject support in DevMode that prevents
dispatching
through an interface to a method defined in a super-interface. The change
also includes a new test to serve as a regression test.
Review at http://gwt-code-reviews.appspot.com/1287801
Review by: bobv, scottb, cromwellian
http://code.google.com/p/google-web-toolkit/source/detail?r=9542
Modified:
/trunk/dev/core/src/com/google/gwt/dev/shell/rewrite/RewriteSingleJsoImplDispatches.java
/trunk/user/test/com/google/gwt/dev/jjs/test/singlejso/TypeHierarchyTest.java
=======================================
---
/trunk/dev/core/src/com/google/gwt/dev/shell/rewrite/RewriteSingleJsoImplDispatches.java
Wed Dec 1 12:10:45 2010
+++
/trunk/dev/core/src/com/google/gwt/dev/shell/rewrite/RewriteSingleJsoImplDispatches.java
Thu Jan 13 15:08:15 2011
@@ -34,8 +34,8 @@
import java.util.List;
import java.util.Map;
import java.util.Set;
-import java.util.SortedMap;
-import java.util.TreeMap;
+import java.util.SortedSet;
+import java.util.TreeSet;
/**
* Effects the renaming of {@code @SingleJsoImpl} methods from their
original
@@ -181,9 +181,9 @@
* may be referenced via a more specific interface.
*/
if (inSingleJsoImplInterfaceType) {
- for (Map.Entry<String, List<Method>> entry :
toImplement(currentTypeName).entrySet()) {
- for (Method method : entry.getValue()) {
- writeEmptyMethod(entry.getKey(), method);
+ for (String mangledName : toImplement(currentTypeName)) {
+ for (Method method : jsoData.getDeclarations(mangledName)) {
+ writeEmptyMethod(mangledName, method);
}
}
}
@@ -265,29 +265,23 @@
* Given a resource name of a class, find all mangled method names that
must
* be implemented.
*/
- private SortedMap<String, List<Method>> toImplement(String typeName) {
+ private SortedSet<String> toImplement(String typeName) {
String name = typeName.replace('/', '_');
String prefix = name + "_";
String suffix = name + "`";
- SortedMap<String, List<Method>> toReturn = new TreeMap<String,
List<Method>>();
-
+ SortedSet<String> toReturn = new TreeSet<String>();
for (String mangledName : jsoData.getMangledNames().subSet(prefix,
suffix)) {
- toReturn.put(mangledName, jsoData.getImplementations(mangledName));
- }
- toReturn.keySet().removeAll(implementedMethods);
+ if (!implementedMethods.contains(mangledName)) {
+ toReturn.add(mangledName);
+ }
+ }
return toReturn;
}
-
- private void writeEmptyMethod(String mangledMethodName, Method method) {
- assert method.getArgumentTypes().length > 0;
- // Remove the first argument, which would be the implementing JSO type
- String descriptor = "("
- + method.getDescriptor().substring(
- 1 + method.getArgumentTypes()[0].getDescriptor().length());
-
- // Create the stub method entry in the interface
+
+ private void writeEmptyMethod(String mangledMethodName, Method
declMethod) {
MethodVisitor mv = super.visitMethod(Opcodes.ACC_PUBLIC
- | Opcodes.ACC_ABSTRACT, mangledMethodName, descriptor, null, null);
+ | Opcodes.ACC_ABSTRACT, mangledMethodName,
declMethod.getDescriptor(),
+ null, null);
mv.visitEnd();
}
@@ -303,20 +297,14 @@
* semantics of the dispatches that would make a common implementation
far
* more awkward than the duplication of code.
*/
- for (Map.Entry<String, List<Method>> entry :
toImplement(stubIntr).entrySet()) {
- for (Method method : entry.getValue()) {
- String mangledName = entry.getKey();
-
- String descriptor = "("
- + method.getDescriptor().substring(
- 1 + method.getArgumentTypes()[0].getDescriptor().length());
- String localName = method.getName().substring(0,
- method.getName().length() - 1);
- Method toCall = new Method(localName, descriptor);
+ for (String mangledName : toImplement(stubIntr)) {
+ for (Method method : jsoData.getDeclarations(mangledName)) {
+
+ Method toCall = new Method(method.getName(),
method.getDescriptor());
// Must not be final
MethodVisitor mv = super.visitMethod(Opcodes.ACC_PUBLIC
- | Opcodes.ACC_SYNTHETIC, mangledName, descriptor, null, null);
+ | Opcodes.ACC_SYNTHETIC, mangledName, method.getDescriptor(),
null, null);
if (mv != null) {
mv.visitCode();
=======================================
---
/trunk/user/test/com/google/gwt/dev/jjs/test/singlejso/TypeHierarchyTest.java
Sun Oct 18 11:48:45 2009
+++
/trunk/user/test/com/google/gwt/dev/jjs/test/singlejso/TypeHierarchyTest.java
Thu Jan 13 15:08:15 2011
@@ -122,6 +122,45 @@
*/
static class Wide {
}
+
+ private interface Element extends Node {
+ }
+
+ private static class JvmNode implements Node {
+ @Override
+ public JvmNode appendChild(Node node) {
+ return (JvmNode)node;
+ }
+ }
+
+ private final static class JvmElement extends JvmNode implements Element
{
+ static Element create() {
+ return new JvmElement();
+ }
+ }
+
+ private final static class JsElement extends JsNode implements Element {
+ static Element create() {
+ return (Element) JavaScriptObject.createObject();
+ }
+
+ protected JsElement() {
+ }
+ }
+
+ private static class JsNode extends JavaScriptObject implements Node {
+ @Override
+ public final native JsNode appendChild(Node node) /*-{
+ return node;
+ }-*/;
+
+ protected JsNode() {
+ }
+ }
+
+ private interface Node {
+ Node appendChild(Node node);
+ }
@Override
public String getModuleName() {
@@ -149,7 +188,7 @@
IA b2 = new B2();
assertEquals("B2", b2.whoAmI());
}
-
+
public void testCase3() {
IA a = A.create();
assertEquals("A", a.whoAmI());
@@ -171,6 +210,17 @@
IDiamond2B d2b = DiamondImpl.create();
assertEquals(42, d2b.size());
}
+
+ /**
+ * Tests that dispatches through a hierarchy of interfaces works
properly.
+ */
+ public void testInterfaceHierarchyDispatch() {
+ Element jsElement = JsElement.create();
+ assertEquals(jsElement, jsElement.appendChild(jsElement));
+
+ Element jvmElement = JvmElement.create();
+ assertEquals(jvmElement, jvmElement.appendChild(jvmElement));
+ }
public void testVirtualOverrides() {
Arrayish array = PlainJsoWithInterface.create();
--
http://groups.google.com/group/Google-Web-Toolkit-Contributors