Allow general initializer in @JsOverlay static fields.
Change-Id: If78bcea9baf62683fe10f022e7c1c647582030a3
diff --git a/dev/core/src/com/google/gwt/dev/javac/testing/impl/JavaResourceBase.java b/dev/core/src/com/google/gwt/dev/javac/testing/impl/JavaResourceBase.java
index bcd3a93..37d7e7a 100644
--- a/dev/core/src/com/google/gwt/dev/javac/testing/impl/JavaResourceBase.java
+++ b/dev/core/src/com/google/gwt/dev/javac/testing/impl/JavaResourceBase.java
@@ -377,46 +377,52 @@
public static final MockJavaResource JSTYPE =
createMockJavaResource("jsinterop.annotations.JsType",
"package jsinterop.annotations;",
- "public @interface JsType {\n",
- " String namespace() default \"\";\n",
- " String name() default \"\";\n",
- " boolean isNative() default false;\n" +
+ "public @interface JsType {",
+ " String namespace() default \"\";",
+ " String name() default \"\";",
+ " boolean isNative() default false;",
"}"
);
public static final MockJavaResource JSCONSTRUCTOR =
createMockJavaResource("jsinterop.annotations.JsConstructor",
"package jsinterop.annotations;",
- "public @interface JsConstructor {\n",
+ "public @interface JsConstructor {",
+ "}");
+ public static final MockJavaResource JSPACKAGE =
+ createMockJavaResource("jsinterop.annotations.JsPackage",
+ "package jsinterop.annotations;",
+ "public @interface JsPackage {",
+ " String GLOBAL = \"<global>\";",
+ " String namespace();",
"}");
public static final MockJavaResource JSPROPERTY =
createMockJavaResource("jsinterop.annotations.JsProperty",
"package jsinterop.annotations;",
- "public @interface JsProperty {\n",
- " String namespace() default \"\";\n",
- " String name() default \"\";\n",
+ "public @interface JsProperty {",
+ " String namespace() default \"\";",
+ " String name() default \"\";",
"}");
public static final MockJavaResource JSMETHOD =
createMockJavaResource("jsinterop.annotations.JsMethod",
"package jsinterop.annotations;",
"public @interface JsMethod {\n",
- " String namespace() default \"\";\n",
- " String name() default \"\";\n",
+ " String namespace() default \"\";",
+ " String name() default \"\";",
"}");
public static final MockJavaResource JSIGNORE =
createMockJavaResource("jsinterop.annotations.JsIgnore",
"package jsinterop.annotations;",
- "public @interface JsIgnore {\n",
+ "public @interface JsIgnore {",
"}");
public static final MockJavaResource JSFUNCTION =
createMockJavaResource("jsinterop.annotations.JsFunction",
"package jsinterop.annotations;",
- "public @interface JsFunction {\n",
+ "public @interface JsFunction {",
"}");
-
public static final MockJavaResource JSOVERLAY =
createMockJavaResource("jsinterop.annotations.JsOverlay",
"package jsinterop.annotations;",
- "public @interface JsOverlay {\n",
+ "public @interface JsOverlay {",
"}");
public static MockJavaResource[] getStandardResources() {
@@ -426,8 +432,8 @@
ERROR, FUNCTIONALINTERFACE, FLOAT, INTEGER, IS_SERIALIZABLE, JAVASCRIPTEXCEPTION,
JAVASCRIPTOBJECT, LIST, LONG, MAP, NO_CLASS_DEF_FOUND_ERROR, NUMBER, OBJECT,
RUNTIME_EXCEPTION, SERIALIZABLE, SHORT, STRING, STRING_BUILDER, SUPPRESS_WARNINGS, SYSTEM,
- THROWABLE, SPECIALIZE_METHOD, JSTYPE, JSCONSTRUCTOR, JSPROPERTY, JSMETHOD, JSIGNORE,
- JSFUNCTION, JSOVERLAY};
+ THROWABLE, SPECIALIZE_METHOD, JSTYPE, JSCONSTRUCTOR, JSPACKAGE, JSPROPERTY, JSMETHOD,
+ JSIGNORE, JSFUNCTION, JSOVERLAY};
}
/**
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JDeclaredType.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JDeclaredType.java
index 4d26cec..29d8d15 100755
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/JDeclaredType.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JDeclaredType.java
@@ -271,7 +271,7 @@
* superclass, or <code>null</code> if this class has no static initializer.
*/
public final JDeclaredType getClinitTarget() {
- if (isJsNative() || isJsFunction()) {
+ if (isJsFunction()) {
return null;
}
return clinitTarget;
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JField.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JField.java
index be6caaa..4851be5 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/JField.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JField.java
@@ -160,12 +160,12 @@
@Override
public boolean isJsInteropEntryPoint() {
- return exported && isStatic() && !isJsNative();
+ return exported && isStatic() && !isJsNative() && !isJsOverlay();
}
@Override
public boolean canBeReferencedExternally() {
- return exported;
+ return exported && !isJsNative();
}
@Override
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JMethod.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JMethod.java
index d9f155b..250e7f8 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/JMethod.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JMethod.java
@@ -72,11 +72,16 @@
@Override
public boolean isJsInteropEntryPoint() {
- return exported && !needsDynamicDispatch() && !isJsNative();
+ return exported && !needsDynamicDispatch() && !isJsNative() && !isJsOverlay();
}
@Override
public boolean canBeReferencedExternally() {
+ if (isJsOverlay() || (!needsDynamicDispatch() && isJsNative())) {
+ // JsOverlays, native constructors and native static methods can not be referenced
+ // externally
+ return false;
+ }
for (JMethod method : getOverriddenMethodsIncludingSelf()) {
if (method.exported || method.isJsFunctionMethod()) {
return true;
@@ -244,7 +249,8 @@
@Override
public boolean isJsOverlay() {
- return isJsOverlay || getEnclosingType().isJsoType();
+ return isJsOverlay || getEnclosingType().isJsoType() ||
+ getEnclosingType().isJsNative() && JProgram.isClinit(this);
}
public void setSyntheticAccidentalOverride() {
@@ -310,7 +316,7 @@
}
public boolean isJsMethodVarargs() {
- if (getParams().isEmpty() || !canBeReferencedExternally()) {
+ if (getParams().isEmpty() || !(canBeReferencedExternally() || canBeImplementedExternally())) {
return false;
}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/JsInteropRestrictionChecker.java b/dev/core/src/com/google/gwt/dev/jjs/impl/JsInteropRestrictionChecker.java
index 9846181..06c84e1 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/JsInteropRestrictionChecker.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/JsInteropRestrictionChecker.java
@@ -284,9 +284,10 @@
if (member instanceof JField) {
JField field = (JField) member;
- if (!field.isCompileTimeConstant()) {
+ if (field.needsDynamicDispatch()) {
logError(
- member, "JsOverlay field '%s' can only be a compile time constant.", methodDescription);
+ member, "JsOverlay field '%s' can only be static.",
+ methodDescription);
}
return;
}
diff --git a/dev/core/test/com/google/gwt/dev/jjs/impl/JsInteropRestrictionCheckerTest.java b/dev/core/test/com/google/gwt/dev/jjs/impl/JsInteropRestrictionCheckerTest.java
index 3634fe5..723c155 100644
--- a/dev/core/test/com/google/gwt/dev/jjs/impl/JsInteropRestrictionCheckerTest.java
+++ b/dev/core/test/com/google/gwt/dev/jjs/impl/JsInteropRestrictionCheckerTest.java
@@ -1483,21 +1483,31 @@
"Line 9: JsOverlay method 'void EntryPoint.Buggy.m()' cannot override a supertype method.");
}
- public void testJsOverlayOnNonFinalMethodAndNonCompileTimeConstantFieldFails() {
+ public void testJsOverlayOnNonFinalMethodAndInstanceFieldFails() {
addSnippetImport("jsinterop.annotations.JsType");
addSnippetImport("jsinterop.annotations.JsOverlay");
addSnippetClassDecl(
"@JsType(isNative=true) public static class Buggy {",
- " @JsOverlay public static int f1 = 2;",
" @JsOverlay public final int f2 = 2;",
" @JsOverlay public void m() { }",
"}");
assertBuggyFails(
"Line 5: Native JsType 'EntryPoint.Buggy' cannot have initializer.",
- "Line 6: JsOverlay field 'int EntryPoint.Buggy.f1' can only be a compile time constant.",
- "Line 7: JsOverlay field 'int EntryPoint.Buggy.f2' can only be a compile time constant.",
- "Line 8: JsOverlay method 'void EntryPoint.Buggy.m()' cannot be non-final nor native.");
+ "Line 6: JsOverlay field 'int EntryPoint.Buggy.f2' can only be static.",
+ "Line 7: JsOverlay method 'void EntryPoint.Buggy.m()' cannot be non-final nor native.");
+ }
+
+ public void testJsOverlayWithStaticInitializerSucceeds() throws Exception {
+ addSnippetImport("jsinterop.annotations.JsType");
+ addSnippetImport("jsinterop.annotations.JsOverlay");
+ addSnippetClassDecl(
+ "@JsType(isNative=true) public static class Buggy {",
+ " @JsOverlay public final static Object f1 = new Object();",
+ " @JsOverlay public static int f2 = 2;",
+ "}");
+
+ assertBuggySucceeds();
}
public void testJsOverlayOnNativeMethodFails() {
diff --git a/user/test-super/com/google/gwt/dev/jjs/super/com/google/gwt/dev/jjs/test/Java8Test.java b/user/test-super/com/google/gwt/dev/jjs/super/com/google/gwt/dev/jjs/test/Java8Test.java
index 66a5adb..8195c77 100644
--- a/user/test-super/com/google/gwt/dev/jjs/super/com/google/gwt/dev/jjs/test/Java8Test.java
+++ b/user/test-super/com/google/gwt/dev/jjs/super/com/google/gwt/dev/jjs/test/Java8Test.java
@@ -23,6 +23,10 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
+
+import jsinterop.annotations.JsOverlay;
+import jsinterop.annotations.JsType;
+
/**
* Tests Java 8 features. It is super sourced so that gwt can be compiles under Java 7.
*
@@ -1284,4 +1288,63 @@
private void assertContentsInOrder(Iterable<String> contents, String... elements) {
assertEquals(Arrays.asList(elements).toString(), contents.toString());
}
+
+ @JsType(isNative = true)
+ interface NativeJsTypeInterfaceWithStaticInitializationAndFieldAccess {
+ @JsOverlay
+ Object object = new Integer(3);
+ }
+
+ @JsType(isNative = true)
+ interface NativeJsTypeInterfaceWithStaticInitializationAndStaticOverlayMethod {
+ @JsOverlay
+ Object object = new Integer(4);
+
+ @JsOverlay
+ static Object getObject() {
+ return object;
+ }
+ }
+
+// TODO(rluble): uncomment when we allow @JsOverlay methods to be default methods of
+// interfaces
+// @JsType(isNative = true)
+// interface NativeJsTypeInterfaceWithStaticInitializationAndInstanceOverlayMethod {
+// @JsOverlay
+// Object object = new Integer(5);
+//
+// @JsOverlay
+// default Object getObject() {
+// return object;
+// }
+// }
+//
+// private native NativeJsTypeInterfaceWithStaticInitializationAndInstanceOverlayMethod
+// createNativeJsTypeInterfaceWithStaticInitializationAndInstanceOverlayMethod() /*-{
+// return {};
+// }-*/;
+
+ @JsType(isNative = true)
+ interface NativeJsTypeInterfaceWithStaticInitialization {
+ @JsOverlay
+ Object object = new Integer(6);
+ }
+
+ @JsType(isNative = true)
+ interface NativeJsTypeInterfaceWithComplexStaticInitialization {
+ @JsOverlay
+ Object object = (Integer) (((int) NativeJsTypeInterfaceWithStaticInitialization.object) + 1);
+ }
+
+ public void testNativeJsTypeWithStaticIntializer() {
+ assertEquals(3, NativeJsTypeInterfaceWithStaticInitializationAndFieldAccess.object);
+ assertEquals(
+ 4, NativeJsTypeInterfaceWithStaticInitializationAndStaticOverlayMethod.getObject());
+// TODO(rluble): uncomment when we allow @JsOverlay methods to be default methods of
+// interfaces
+// assertEquals(new Integer(5),
+// createNativeJsTypeInterfaceWithStaticInitializationAndInstanceOverlayMethod()
+// .getObject());
+ assertEquals(7, NativeJsTypeInterfaceWithComplexStaticInitialization.object);
+ }
}
diff --git a/user/test/com/google/gwt/core/interop/JsPropertyTest.java b/user/test/com/google/gwt/core/interop/JsPropertyTest.java
index 875c11b..dbf9b25 100644
--- a/user/test/com/google/gwt/core/interop/JsPropertyTest.java
+++ b/user/test/com/google/gwt/core/interop/JsPropertyTest.java
@@ -245,11 +245,11 @@
void setX(int x);
}
- static class MyNativeNativeJsTypeTypeInterfaceSubclassNeedingBridge
- extends AccidentaImplementer implements MyNativeJsTypeInterface {
+ static class MyNativeJsTypeInterfaceImplementorNeedingBridge
+ extends AccidentalImplementer implements MyNativeJsTypeInterface {
}
- static abstract class AccidentaImplementer {
+ static abstract class AccidentalImplementer {
private int x;
public int getX() {
@@ -266,25 +266,25 @@
}
public void testJsPropertyBridges() {
- MyNativeJsTypeInterface object = new MyNativeNativeJsTypeTypeInterfaceSubclassNeedingBridge();
+ MyNativeJsTypeInterface object = new MyNativeJsTypeInterfaceImplementorNeedingBridge();
object.setX(3);
assertEquals(3 + 150, object.getX());
- assertEquals(3 + SET_X, ((AccidentaImplementer) object).x);
+ assertEquals(3 + SET_X, ((AccidentalImplementer) object).x);
- AccidentaImplementer accidentaImplementer = (AccidentaImplementer) object;
+ AccidentalImplementer accidentalImplementer = (AccidentalImplementer) object;
- accidentaImplementer.setX(3);
- assertEquals(3 + 150, accidentaImplementer.getX());
+ accidentalImplementer.setX(3);
+ assertEquals(3 + 150, accidentalImplementer.getX());
assertEquals(3 + 150, getProperty(object, "x"));
- assertEquals(3 + SET_X, accidentaImplementer.x);
+ assertEquals(3 + SET_X, accidentalImplementer.x);
setProperty(object, "x", 4);
- assertEquals(4 + 150, accidentaImplementer.getX());
+ assertEquals(4 + 150, accidentalImplementer.getX());
assertEquals(4 + 150, getProperty(object, "x"));
- assertEquals(4 + SET_X, accidentaImplementer.x);
+ assertEquals(4 + SET_X, accidentalImplementer.x);
- assertEquals(3 + 4 + SET_X, accidentaImplementer.sum(3));
+ assertEquals(3 + 4 + SET_X, accidentalImplementer.sum(3));
}
static class MyNativeJsTypeInterfaceImplNeedingBridgeSubclassed
diff --git a/user/test/com/google/gwt/core/interop/JsTypeTest.java b/user/test/com/google/gwt/core/interop/JsTypeTest.java
index 8378c66..1377ed8 100644
--- a/user/test/com/google/gwt/core/interop/JsTypeTest.java
+++ b/user/test/com/google/gwt/core/interop/JsTypeTest.java
@@ -23,10 +23,8 @@
import java.util.Iterator;
-import javaemul.internal.annotations.DoNotInline;
import jsinterop.annotations.JsFunction;
import jsinterop.annotations.JsMethod;
-import jsinterop.annotations.JsOverlay;
import jsinterop.annotations.JsPackage;
import jsinterop.annotations.JsProperty;
import jsinterop.annotations.JsType;
@@ -479,42 +477,6 @@
assertSame(3, ((JsFunctionInterface) nativeJsFunction()).m());
}
- private static native void setProperty(Object object, String name, int value) /*-{
- object[name] = value;
- }-*/;
-
- @JsType(isNative = true, namespace = GLOBAL, name = "Object")
- static class NativeJsTypeWithOverlay {
-
- @JsOverlay
- public static final int x = 2;
-
- public static native String[] keys(Object o);
-
- @JsOverlay @DoNotInline
- public static final boolean hasM(Object obj) {
- return keys(obj)[0].equals("m");
- }
-
- public native boolean hasOwnProperty(String name);
-
- @JsOverlay @DoNotInline
- public final boolean hasM() {
- return hasOwnProperty("m");
- }
- }
-
- private native NativeJsTypeWithOverlay createNativeJsTypeWithOverlay() /*-{
- return { m: function() { return 6; } };
- }-*/;
-
- public void testNativeJsTypeWithOverlay() {
- NativeJsTypeWithOverlay object = createNativeJsTypeWithOverlay();
- assertTrue(object.hasM());
- assertTrue(NativeJsTypeWithOverlay.hasM(object));
- assertEquals(2, NativeJsTypeWithOverlay.x);
- }
-
@JsType
static abstract class SomeAbstractClass {
public abstract SomeAbstractClass m();
diff --git a/user/test/com/google/gwt/core/interop/NativeJsTypeTest.java b/user/test/com/google/gwt/core/interop/NativeJsTypeTest.java
index 3dd9382..b96a6eb 100644
--- a/user/test/com/google/gwt/core/interop/NativeJsTypeTest.java
+++ b/user/test/com/google/gwt/core/interop/NativeJsTypeTest.java
@@ -15,9 +15,14 @@
*/
package com.google.gwt.core.interop;
+import static jsinterop.annotations.JsPackage.GLOBAL;
+
import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.junit.client.GWTTestCase;
+import javaemul.internal.annotations.DoNotInline;
+import jsinterop.annotations.JsOverlay;
+import jsinterop.annotations.JsPackage;
import jsinterop.annotations.JsType;
/**
@@ -81,4 +86,72 @@
private static native Object createNativeArray() /*-{
return [];
}-*/;
+
+ @JsType(isNative = true, namespace = GLOBAL, name = "Object")
+ static class NativeJsTypeWithOverlay {
+
+ @JsOverlay
+ public static final int x = 2;
+
+ public static native String[] keys(Object o);
+
+ @JsOverlay @DoNotInline
+ public static final boolean hasM(Object obj) {
+ return keys(obj)[0].equals("m");
+ }
+
+ public native boolean hasOwnProperty(String name);
+
+ @JsOverlay @DoNotInline
+ public final boolean hasM() {
+ return hasOwnProperty("m");
+ }
+ }
+
+ private native NativeJsTypeWithOverlay createNativeJsTypeWithOverlay() /*-{
+ return { m: function() { return 6; } };
+ }-*/;
+
+ public void testNativeJsTypeWithOverlay() {
+ NativeJsTypeWithOverlay object = createNativeJsTypeWithOverlay();
+ assertTrue(object.hasM());
+ assertTrue(NativeJsTypeWithOverlay.hasM(object));
+ assertEquals(2, NativeJsTypeWithOverlay.x);
+ }
+
+ @JsType(isNative = true)
+ static class NativeJsTypeWithStaticInitializationAndFieldAccess {
+ @JsOverlay
+ public static Object object = new Integer(3);
+ }
+
+ @JsType(isNative = true)
+ static class NativeJsTypeWithStaticInitializationAndStaticOverlayMethod {
+ @JsOverlay
+ public static Object object = new Integer(4);
+
+ @JsOverlay
+ public static Object getObject() {
+ return object;
+ }
+ }
+
+ @JsType(isNative = true, namespace = JsPackage.GLOBAL, name = "Object")
+ static class NativeJsTypeWithStaticInitializationAndInstanceOverlayMethod {
+ @JsOverlay
+ public static Object object = new Integer(5);
+
+ @JsOverlay
+ public final Object getObject() {
+ return object;
+ }
+ }
+
+ public void testNativeJsTypeWithStaticIntializer() {
+ assertEquals(new Integer(3), NativeJsTypeWithStaticInitializationAndFieldAccess.object);
+ assertEquals(
+ new Integer(4), NativeJsTypeWithStaticInitializationAndStaticOverlayMethod.getObject());
+ assertEquals(new Integer(5),
+ new NativeJsTypeWithStaticInitializationAndInstanceOverlayMethod().getObject());
+ }
}
diff --git a/user/test/com/google/gwt/dev/jjs/test/Java8Test.java b/user/test/com/google/gwt/dev/jjs/test/Java8Test.java
index c892a15..d1ff194 100644
--- a/user/test/com/google/gwt/dev/jjs/test/Java8Test.java
+++ b/user/test/com/google/gwt/dev/jjs/test/Java8Test.java
@@ -260,6 +260,10 @@
assertFalse(isGwtSourceLevel8());
}
+ public void testNativeJsTypeWithStaticIntializer() {
+ assertFalse(isGwtSourceLevel8());
+ }
+
private boolean isGwtSourceLevel8() {
return JUnitShell.getCompilerOptions().getSourceLevel().compareTo(SourceLevel.JAVA8) >= 0;
}