Skip to content

Commit

Permalink
Fix incorrect casting optimization for native JsTypes.
Browse files Browse the repository at this point in the history
Change-Id: I19ccf553cc854f5d826e871a7fffed95bb78ab8e
  • Loading branch information
gkdn committed Oct 6, 2015
1 parent 94e4597 commit 6834a6f
Show file tree
Hide file tree
Showing 2 changed files with 15 additions and 8 deletions.
8 changes: 6 additions & 2 deletions dev/core/src/com/google/gwt/dev/jjs/ast/JTypeOracle.java
Expand Up @@ -413,16 +413,20 @@ public boolean canBeJavaScriptObject(JType type) {
}

/**
* True if the type is a JSO or interface implemented by JSO or a JsType without prototype.
* True if the type can be casted across different Java types that are unrelated.
*/
public boolean canCrossCastLikeJso(JType type) {
return canBeJavaScriptObject(type) || isNonNativeJsTypeInterface(type);
return canBeJavaScriptObject(type) || isNativeJsType(type) || isNonNativeJsTypeInterface(type);
}

public boolean isNonNativeJsTypeInterface(JType type) {
return type.isJsType() && type instanceof JInterfaceType && !type.isJsNative();
}

private boolean isNativeJsType(JType type) {
return type.isJsNative() && type instanceof JClassType;
}

public boolean castFailsTrivially(JReferenceType fromType, JReferenceType toType) {
if (!fromType.canBeNull() && toType.isNullType()) {
// Cannot cast non-nullable to null
Expand Down
15 changes: 9 additions & 6 deletions user/test/com/google/gwt/core/client/interop/JsTypeTest.java
Expand Up @@ -214,26 +214,29 @@ private static native MyJsInterfaceWithProtectedNames createMyJsInterfaceWithPro
}-*/;

public void testCasts() {
MyJsInterfaceWithPrototype myClass;
Object myClass;
assertNotNull(myClass = (ElementLikeJsInterface) createMyJsInterface());
assertNotNull(myClass = (MyJsInterfaceWithPrototype) createMyJsInterface());
assertNotNull(myClass = (HTMLElement) createNativeButton());

try {
assertNotNull(myClass = (MyJsInterfaceWithPrototype) createNativeButton());
assertNotNull(myClass = (HTMLElement) createMyJsInterface());
fail();
} catch (ClassCastException cce) {
// Expected.
}

ElementLikeJsInterface button;
// JsTypes without prototypes can cross-cast like JSOs
assertNotNull(button = (ElementLikeJsInterface) createMyJsInterface());
// Test cross cast for native types
Object nativeButton1 = (HTMLElement) createNativeButton();
Object nativeButton2 = (HTMLAnotherElement) nativeButton1;

/*
* If the optimizations are turned on, it is possible for the compiler to dead-strip the
* variables since they are not used. Therefore the casts could potentially be stripped.
*/
assertNotNull(myClass);
assertNotNull(button);
assertNotNull(nativeButton1);
assertNotNull(nativeButton2);
}

public void testInstanceOf_jsoWithProto() {
Expand Down

0 comments on commit 6834a6f

Please sign in to comment.