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);