Revision: 6216 Author: b...@google.com Date: Fri Sep 25 11:27:03 2009 Log: Fix compiler and hosted-mode crash caused by virtual overrides in SingleJsoImpl types.
Patch by: bobv Review by: scottb http://code.google.com/p/google-web-toolkit/source/detail?r=6216 Modified: /trunk/dev/core/src/com/google/gwt/dev/jjs/ast/JTypeOracle.java /trunk/dev/core/src/com/google/gwt/dev/jjs/impl/JavaScriptObjectNormalizer.java /trunk/dev/core/src/com/google/gwt/dev/shell/CompilingClassLoader.java /trunk/user/test/com/google/gwt/dev/jjs/test/singlejso/TypeHierarchyTest.java ======================================= --- /trunk/dev/core/src/com/google/gwt/dev/jjs/ast/JTypeOracle.java Tue Jul 21 18:31:48 2009 +++ /trunk/dev/core/src/com/google/gwt/dev/jjs/ast/JTypeOracle.java Fri Sep 25 11:27:03 2009 @@ -448,7 +448,6 @@ } } } - jsoSubType.clearImplements(); } } ======================================= --- /trunk/dev/core/src/com/google/gwt/dev/jjs/impl/JavaScriptObjectNormalizer.java Tue Jul 21 18:30:12 2009 +++ /trunk/dev/core/src/com/google/gwt/dev/jjs/impl/JavaScriptObjectNormalizer.java Fri Sep 25 11:27:03 2009 @@ -177,13 +177,21 @@ private JMethod findConcreteImplementation(JMethod method, JClassType concreteType) { - for (JMethod m : concreteType.getMethods()) { - if (program.typeOracle.getAllOverrides(m).contains(method)) { - if (!m.isAbstract()) { - return m; + /* + * Search supertypes for virtual overrides via subclass. See the javadoc + * on JTypeOracle.getAllVirtualOverrides for an example. + */ + while (concreteType != null) { + for (JMethod m : concreteType.getMethods()) { + if (program.typeOracle.getAllOverrides(m).contains(method)) { + if (!m.isAbstract()) { + return m; + } } } - } + concreteType = concreteType.getSuperClass(); + } + return null; } ======================================= --- /trunk/dev/core/src/com/google/gwt/dev/shell/CompilingClassLoader.java Fri Jul 31 13:43:46 2009 +++ /trunk/dev/core/src/com/google/gwt/dev/shell/CompilingClassLoader.java Fri Sep 25 11:27:03 2009 @@ -36,9 +36,9 @@ import com.google.gwt.dev.shell.rewrite.HostedModeClassRewriter; import com.google.gwt.dev.shell.rewrite.HostedModeClassRewriter.InstanceMethodOracle; import com.google.gwt.dev.util.JsniRef; -import com.google.gwt.dev.util.Name.SourceOrBinaryName; -import com.google.gwt.dev.util.Name.InternalName; import com.google.gwt.dev.util.Util; +import com.google.gwt.dev.util.Name.InternalName; +import com.google.gwt.dev.util.Name.SourceOrBinaryName; import com.google.gwt.util.tools.Utility; import org.apache.commons.collections.map.AbstractReferenceMap; @@ -910,6 +910,21 @@ */ String mangledName = getBinaryName(type).replace('.', '_') + "_" + m.getName(); + + JType[] parameterTypes = new JType[m.getParameters().length]; + for (int i = 0; i < parameterTypes.length; i++) { + parameterTypes[i] = m.getParameters()[i].getType(); + } + + /* + * Handle virtual overrides by finding the method that we would normally + * invoke and using its declaring class as the dispatch target. + */ + while (implementingType.findMethod(m.getName(), parameterTypes) == null) { + implementingType = implementingType.getSuperclass(); + } + assert implementingType != null : "Unable to find virtual override for " + + m.toString(); /* * Cook up the a pseudo-method declaration for the concrete type. This @@ -921,9 +936,9 @@ */ String decl = getBinaryOrPrimitiveName(m.getReturnType()) + " " + m.getName() + "$ (" + getBinaryOrPrimitiveName(implementingType); - for (JParameter p : m.getParameters()) { + for (JType paramType : parameterTypes) { decl += ","; - decl += getBinaryOrPrimitiveName(p.getType()); + decl += getBinaryOrPrimitiveName(paramType); } decl += ")"; ======================================= --- /trunk/user/test/com/google/gwt/dev/jjs/test/singlejso/TypeHierarchyTest.java Mon Jul 20 14:25:19 2009 +++ /trunk/user/test/com/google/gwt/dev/jjs/test/singlejso/TypeHierarchyTest.java Fri Sep 25 11:27:03 2009 @@ -22,6 +22,16 @@ * Tests SingleJso semantics in non-trivial type hierarchies. */ public class TypeHierarchyTest extends GWTTestCase { + + /** + * Used with PlainJso and PlainJsoWithInterface to mix interfaces into + * existing base classes. + */ + interface Arrayish { + int getLength(); + + JavaScriptObject getObject(int i); + } /** * The bottom type for a non-trivial diamond-shaped inheritance pattern. @@ -58,6 +68,35 @@ */ interface IDiamond2B extends IDiamond1 { } + + /** + * This is a base class that is used to test adding interfaces to a JSO via a + * subclass. + */ + static class PlainJso extends JavaScriptObject { + protected PlainJso() { + } + + public final native int getLength()/*-{ + return this.length; + }-*/; + + public final native JavaScriptObject getObject(int i) /*-{ + return this[i]; + }-*/; + } + + /** + * We'll mix in an interface into PlainJso. + */ + static class PlainJsoWithInterface extends PlainJso implements Arrayish { + public static PlainJsoWithInterface create() { + return JavaScriptObject.createArray().cast(); + } + + protected PlainJsoWithInterface() { + } + } @Override public String getModuleName() { @@ -107,4 +146,10 @@ IDiamond2B d2b = DiamondImpl.create(); assertEquals(42, d2b.size()); } -} + + public void testVirtualOverrides() { + Arrayish array = PlainJsoWithInterface.create(); + assertEquals(0, array.getLength()); + assertNull(array.getObject(0)); + } +} --~--~---------~--~----~------------~-------~--~----~ http://groups.google.com/group/Google-Web-Toolkit-Contributors -~----------~----~----~----~------~----~------~--~---