Make sure that enums exposed with JsInterop are not ordinalized.
Change-Id: I831168f18d4f6450e5cf424e872fb9fc767b62c0
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/EnumOrdinalizer.java b/dev/core/src/com/google/gwt/dev/jjs/impl/EnumOrdinalizer.java
index dbd4349..51ce69a 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/EnumOrdinalizer.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/EnumOrdinalizer.java
@@ -326,16 +326,17 @@
@Override
public void endVisit(JClassType x, Context ctx) {
// keep track of all enum classes visited
- JEnumType maybeEnum = x.isEnumOrSubclass();
- if (maybeEnum == null) {
+ JEnumType enumClass = x.isEnumOrSubclass();
+ if (enumClass == null) {
return;
}
- enumsVisited.add(maybeEnum);
+ enumsVisited.add(enumClass);
// don't need to re-ordinalize a previously ordinalized enum
- if (maybeEnum.isOrdinalized()) {
- addToBlackList(maybeEnum, x.getSourceInfo());
+ if (enumClass.isOrdinalized()
+ || enumClass.canBeReferencedExternally()) {
+ addToBlackList(enumClass, x.getSourceInfo());
}
}
diff --git a/dev/core/test/com/google/gwt/dev/jjs/JavaAstConstructor.java b/dev/core/test/com/google/gwt/dev/jjs/JavaAstConstructor.java
index 7e5f7bc..6eb0415 100644
--- a/dev/core/test/com/google/gwt/dev/jjs/JavaAstConstructor.java
+++ b/dev/core/test/com/google/gwt/dev/jjs/JavaAstConstructor.java
@@ -192,7 +192,8 @@
"package java.lang;",
"import java.io.Serializable;",
"import com.google.gwt.core.client.JavaScriptObject;",
- "public abstract class Enum<E extends Enum<E>> implements Serializable {",
+ "import jsinterop.annotations.JsType;",
+ "@JsType public abstract class Enum<E extends Enum<E>> implements Serializable {",
" public static native <T extends Enum<T>> T valueOf(Class<T> enumType,",
" String name) /*-{ return enumType + name; }-*/;",
" public static native <T extends Enum<T>> T valueOf(JavaScriptObject enumType,",
diff --git a/dev/core/test/com/google/gwt/dev/jjs/impl/EnumOrdinalizerTest.java b/dev/core/test/com/google/gwt/dev/jjs/impl/EnumOrdinalizerTest.java
index d80f771..95e1b77 100644
--- a/dev/core/test/com/google/gwt/dev/jjs/impl/EnumOrdinalizerTest.java
+++ b/dev/core/test/com/google/gwt/dev/jjs/impl/EnumOrdinalizerTest.java
@@ -538,6 +538,32 @@
assertAllEnumOrdinalizedReferencesReplaced(result.getOptimizedProgram(), tracker);
}
+ public void testNotOrdinalizableJsTypeEnum()
+ throws UnableToCompleteException {
+ setupJsTypeEnums();
+ addSnippetClassDecl(
+ "public static JsFruit instanceFruit;",
+ "public static JsCustom instanceCustom;");
+ Result result = optimize("void",
+ "instanceFruit = JsFruit.JSAPPLE;",
+ "instanceCustom = JsCustom.VALUE1;");
+
+ EnumOrdinalizer.Tracker tracker = EnumOrdinalizer.getTracker();
+ assertTrue(tracker.isVisited("test.EntryPoint$JsFruit"));
+ assertFalse(tracker.isOrdinalized("test.EntryPoint$JsFruit"));
+
+ assertTrue(tracker.isVisited("test.EntryPoint$JsCustom"));
+ assertFalse(tracker.isOrdinalized("test.EntryPoint$JsCustom"));
+
+ assertAllEnumOrdinalizedReferencesReplaced(result.getOptimizedProgram(), tracker);
+ }
+
+ private void setupJsTypeEnums() {
+ addSnippetImport("jsinterop.annotations.JsType");
+ addSnippetClassDecl("@JsType public enum JsFruit {JSAPPLE, JSORANGE}");
+ addSnippetClassDecl("@JsType public enum JsCustom {VALUE0, VALUE1 {} }");
+ }
+
public void testNotOrdinalizableJsniFieldRef()
throws UnableToCompleteException {
setupFruitEnum();
diff --git a/user/test/com/google/gwt/core/interop/JsTypeTest.java b/user/test/com/google/gwt/core/interop/JsTypeTest.java
index dc1ea1c..8fd9ddd 100644
--- a/user/test/com/google/gwt/core/interop/JsTypeTest.java
+++ b/user/test/com/google/gwt/core/interop/JsTypeTest.java
@@ -79,6 +79,32 @@
assertEquals(10, concreteJsTypeSubclass.publicSubclassMethod());
}
+ @JsType
+ enum JsTypeEnum {
+ JSVALUE0,
+ JSVALUE1;
+ }
+
+ public void testJsTypeEnum() {
+ JsTypeEnum value = JsTypeEnum.JSVALUE1;
+
+ assertEquals(value.ordinal(), ((TestAccessor) this).callJsTypeEmumOrdinalMethod(value));
+ }
+
+ // Obscure the call with an alias so that the call is not detected by EnumOrdinalizer.
+ @JsType(isNative = true)
+ private interface TestAccessor {
+ @JsMethod
+ // Receive the JsType enum as its own type so that it is not seen as an upcast by
+ // EnumOrdinalizer, but actually dispach to a method that takes Object.
+ int callJsTypeEmumOrdinalMethod(JsTypeEnum value);
+ }
+
+ @JsMethod
+ private int callJsTypeEmumOrdinalMethod(Object value) {
+ return callIntFunction(value, "ordinal");
+ }
+
public void testConcreteJsTypeNoTypeTightenField() {
// If we type-tighten, java side will see no calls and think that field could only AImpl1.
ConcreteJsType concreteJsType = new ConcreteJsType();