Fix a ClassCircularityError caused by a supertype having a JSNI reference to a subtype.
Patch by: bobv
Reported by: schuck
Review by: rjrjr (desk), scottb (TBR)
Verified by: dhanji
git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@4304 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/dev/core/src/com/google/gwt/dev/shell/CompilingClassLoader.java b/dev/core/src/com/google/gwt/dev/shell/CompilingClassLoader.java
index 4eb38c1..2a85fd9 100644
--- a/dev/core/src/com/google/gwt/dev/shell/CompilingClassLoader.java
+++ b/dev/core/src/com/google/gwt/dev/shell/CompilingClassLoader.java
@@ -618,6 +618,21 @@
throw new ClassNotFoundException(className);
}
+ /*
+ * Prevent reentrant problems where classes that need to be injected have
+ * circular dependencies on one another via JSNI and inheritance. This check
+ * ensures that a class's supertype can refer to the subtype (static
+ * members, etc) via JSNI references by ensuring that the Class for the
+ * subtype will have been defined before injecting the JSNI for the
+ * supertype.
+ */
+ boolean localInjection;
+ if (!isInjectingClass) {
+ localInjection = isInjectingClass = true;
+ } else {
+ localInjection = false;
+ }
+
Class<?> newClass = defineClass(className, classBytes, 0, classBytes.length);
if (className.equals(JavaScriptHost.class.getName())) {
javaScriptHostClass = newClass;
@@ -638,13 +653,8 @@
}
}
- /*
- * Prevent reentrant problems where classes that need to be injected have
- * circular dependencies on one another.
- */
- if (!isInjectingClass) {
+ if (localInjection) {
try {
- isInjectingClass = true;
/*
* Can't use an iterator here because calling injectJsniFor may cause
* additional entries to be added.
diff --git a/user/test/com/google/gwt/dev/jjs/test/JsoTest.java b/user/test/com/google/gwt/dev/jjs/test/JsoTest.java
index c5a4a1b..151379a 100644
--- a/user/test/com/google/gwt/dev/jjs/test/JsoTest.java
+++ b/user/test/com/google/gwt/dev/jjs/test/JsoTest.java
@@ -52,6 +52,13 @@
public static native String staticNative() /*-{
return "nativeFoo";
}-*/;
+
+ /**
+ * Ensure that a supertype can refer to members of a subtype.
+ */
+ public static native String staticNativeToSub() /*-{
+ return @com.google.gwt.dev.jjs.test.JsoTest.FooSub::staticValueSub()();
+ }-*/;
public static String staticValue() {
return "Foo" + field;
@@ -70,6 +77,10 @@
}
static class FooSub extends Foo {
+ static String staticValueSub() {
+ return "FooSub";
+ }
+
protected FooSub() {
}
@@ -608,6 +619,7 @@
assertEquals(3, Foo.field--);
assertEquals("Foo2", Foo.staticValue());
assertEquals("nativeFoo", Foo.staticNative());
+ assertEquals("FooSub", Foo.staticNativeToSub());
Bar.field = 10;
assertEquals(11, ++Bar.field);