Additional SingleJso fixes for tag interfaces.
Also changes how CastNormalizer selects Cast / instanceof methods for SingleJso types.
Patch by: bobv
Review by: spoon (TBR)
Verified by: macpherson
git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@5467 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JTypeOracle.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JTypeOracle.java
index 337b94f..48272af 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/JTypeOracle.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JTypeOracle.java
@@ -692,7 +692,15 @@
assert intr.getMethods().size() == 0
|| intr.getMethods().get(0).getName().equals("$clinit");
jsoSingleImpls.put(intr, program.getJavaScriptObject());
+
+ /*
+ * Pretend JSO had always implemented the tag interface. This helps
+ * simplify cast operations.
+ */
jsoType.addImplements(intr);
+ add(couldBeImplementedMap, intr, jsoType);
+ add(isImplementedMap, intr, jsoType);
+ add(implementsMap, jsoType, intr);
continue;
}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/CastNormalizer.java b/dev/core/src/com/google/gwt/dev/jjs/impl/CastNormalizer.java
index 1b7e41f..1319526 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/CastNormalizer.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/CastNormalizer.java
@@ -27,7 +27,6 @@
import com.google.gwt.dev.jjs.ast.JExpression;
import com.google.gwt.dev.jjs.ast.JInstanceOf;
import com.google.gwt.dev.jjs.ast.JIntLiteral;
-import com.google.gwt.dev.jjs.ast.JInterfaceType;
import com.google.gwt.dev.jjs.ast.JMethod;
import com.google.gwt.dev.jjs.ast.JMethodCall;
import com.google.gwt.dev.jjs.ast.JModVisitor;
@@ -412,12 +411,6 @@
*/
private class ReplaceTypeChecksVisitor extends JModVisitor {
- private final Set<JInterfaceType> dualImpls;
-
- public ReplaceTypeChecksVisitor(JProgram program) {
- dualImpls = program.typeOracle.getInterfacesWithJavaAndJsoImpls();
- }
-
@Override
public void endVisit(JCastOperation x, Context ctx) {
JExpression replaceExpr;
@@ -455,10 +448,10 @@
JMethod method;
boolean isJsoCast = program.isJavaScriptObject(toType);
if (isJsoCast) {
- // A cast to JSO
+ // A cast to a concrete JSO subtype
method = program.getIndexedMethod("Cast.dynamicCastJso");
- } else if (dualImpls.contains(toType)) {
- // A cast that may succeed when the object is a JSO
+ } else if (program.typeOracle.getSingleJsoImpls().containsKey(toType)) {
+ // An interface that should succeed when the object is a JSO
method = program.getIndexedMethod("Cast.dynamicCastAllowJso");
} else {
// A regular cast
@@ -569,11 +562,12 @@
ctx.replaceMe(eq);
} else {
JMethod method;
- boolean isJsoCast = program.isJavaScriptObject(toType);
- if (isJsoCast) {
- method = program.getIndexedMethod("Cast.instanceOfJso");
- } else if (dualImpls.contains(toType)) {
+ boolean isJsoCast = false;
+ if (program.typeOracle.getSingleJsoImpls().containsKey(toType)) {
method = program.getIndexedMethod("Cast.instanceOfOrJso");
+ } else if (program.isJavaScriptObject(toType)) {
+ isJsoCast = true;
+ method = program.getIndexedMethod("Cast.instanceOfJso");
} else {
method = program.getIndexedMethod("Cast.instanceOf");
}
@@ -618,7 +612,7 @@
assigner.computeTypeIds();
}
{
- ReplaceTypeChecksVisitor replacer = new ReplaceTypeChecksVisitor(program);
+ ReplaceTypeChecksVisitor replacer = new ReplaceTypeChecksVisitor();
replacer.accept(program);
}
}
diff --git a/user/test/com/google/gwt/dev/jjs/test/SingleJsoImplTest.java b/user/test/com/google/gwt/dev/jjs/test/SingleJsoImplTest.java
index 4847899..5b21b02 100644
--- a/user/test/com/google/gwt/dev/jjs/test/SingleJsoImplTest.java
+++ b/user/test/com/google/gwt/dev/jjs/test/SingleJsoImplTest.java
@@ -70,6 +70,13 @@
String foo();
}
+ interface CreatedWithCastToTag {
+ }
+
+ interface CreatedWithCastToTagSub extends CreatedWithCastToTag {
+ String foo();
+ }
+
interface Divider extends Multiplier {
int divide(int a, int b);
}
@@ -94,6 +101,12 @@
}
}
+ static class JavaCreatedWithCastToTag implements CreatedWithCastToTagSub {
+ public String foo() {
+ return "foo";
+ }
+ }
+
/**
* The extra declaration of implementing Multiplier should still be legal.
*/
@@ -213,6 +226,16 @@
}
}
+ static class JsoCreatedWithCastToTag extends JavaScriptObject implements
+ CreatedWithCastToTagSub {
+ protected JsoCreatedWithCastToTag() {
+ }
+
+ public final String foo() {
+ return "foo";
+ }
+ }
+
static class JsoDivider extends JsoMultiplier implements Divider, Tag {
protected JsoDivider() {
}
@@ -483,7 +506,16 @@
* compiler would assume there are types that implement the interface.
*/
public void testCreatedWithCast() {
- Object o = (CreatedWithCast) JavaScriptObject.createObject();
+ try {
+ Object a = (CreatedWithCast) JavaScriptObject.createObject();
+ } catch (ClassCastException e) {
+ fail("a");
+ }
+ try {
+ Object b = (CreatedWithCastToTag) JavaScriptObject.createObject();
+ } catch (ClassCastException e) {
+ fail("b");
+ }
}
public void testDualCase() {