Fixes issue #1281; linux hosted mode was crashing sometimes during 
JS_SetReservedSlot(). There might have also been an unrelated issue with 
storing stale JSContext*'s inside of JsRootedValues.

- Keeps a static stack of JSContext*'s instead of storing them; this is 
safe to do because the JS engine is always higher on the call stack than 
any client-side Java code (including gwtOnLoad).
- Protects newborns that could sometimes be insta-gc'd within 
JsValueMoz._setWrappedJavaObject() and _setWrappedFunction().
- Reorganized some functions into more appropriate cpp files.

Patch by: jat, scottb
Review by: scottb, jat :)



git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@1268 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/jni/linux/ExternalWrapper.cpp b/jni/linux/ExternalWrapper.cpp
index eff2802..d13d8b1 100644
--- a/jni/linux/ExternalWrapper.cpp
+++ b/jni/linux/ExternalWrapper.cpp
@@ -41,6 +41,7 @@
 {
   Tracer tracer("gwtOnLoad");
   tracer.log("context=%08x", unsigned(cx));
+  JsRootedValue::ContextManager context(cx);
   JsRootedValue::ensureRuntime(cx);
   if (argc < 2) {
     tracer.setFail("less than 2 args");
@@ -120,6 +121,7 @@
     JSObject *obj, jsval id, jsval *vp)
 {
   Tracer tracer("gwt_external_getProperty");
+  JsRootedValue::ContextManager context(cx);
   if (*vp != JSVAL_VOID)
     return JS_TRUE;
 
@@ -166,10 +168,13 @@
 
 static void JS_DLL_CALLBACK gwt_external_finalize(JSContext *cx, JSObject *obj)
 {
+  // We don't need to push a context if all we do is DeleteGlobalRef
+  Tracer tracer("gwt_external_finalize", obj);
   jobject externalObject = NS_REINTERPRET_CAST(jobject, JS_GetPrivate(cx, obj));
-  if (externalObject)
+  if (externalObject) {
     savedJNIEnv->DeleteGlobalRef(externalObject);
-  JS_FinalizeStub(cx,obj);
+  }
+  JS_FinalizeStub(cx, obj);
 }
 
 static JSBool JS_DLL_CALLBACK gwt_external_setProperty(JSContext *cx,
@@ -201,7 +206,14 @@
     tracer.setFail("null script object pointer");
     return NS_ERROR_INVALID_POINTER;
   }
-  if (!mScriptObject) {
+  if (!jsWindowExternalObject) {
+    JSContext* cx = NS_REINTERPRET_CAST(JSContext*,
+        aContext->GetNativeContext());
+    if (!cx) {
+      tracer.setFail("can't get JSContext");
+      return NS_ERROR_UNEXPECTED;
+    }
+    JsRootedValue::ContextManager context(cx);
     *aScriptObject = 0;
 
     nsIScriptGlobalObject* globalObject = aContext->GetGlobalObject();
@@ -239,12 +251,6 @@
       tracer.setFail("can't get GlobalRef for external object");
       return NS_ERROR_UNEXPECTED;
     }
-    JSContext* cx = NS_REINTERPRET_CAST(JSContext*,
-        aContext->GetNativeContext());
-    if (!cx) {
-      tracer.setFail("can't get JSContext");
-      return NS_ERROR_UNEXPECTED;
-    }
     JSObject* newObj = JS_NewObject(cx, &gwt_external_class, 0,
         globalObject->GetGlobalJSObject());
     if (!newObj) {
@@ -262,16 +268,16 @@
       tracer.setFail("can't define gwtOnLoad function on JavaScript object");
       return NS_ERROR_UNEXPECTED;
     }
-    mScriptObject = newObj;
+    jsWindowExternalObject = newObj;
   }
 
-  *aScriptObject = mScriptObject;
+  *aScriptObject = jsWindowExternalObject;
   return NS_OK;
 }
 
 NS_IMETHODIMP ExternalWrapper::SetScriptObject(void* aScriptObject)
 {
-    mScriptObject = aScriptObject;
+    jsWindowExternalObject = aScriptObject;
     return NS_OK;
 }