Fix for bug 510677 (Avoid XPCCallContext for WrapNativeToJSVal). r/sr=jst.
authorPeter Van der Beken <peterv@propagandism.org>
Fri, 14 Aug 2009 21:00:24 +0200
changeset 31981 988751ff1485ef52627baa2b517f5d8aa6815e46
parent 31980 9ec39c794e63f190be0e7c218c8c9d7723bc9a9b
child 31982 7937d2b42712645953fb2dbfdf12fc1f276eae64
push idunknown
push userunknown
push dateunknown
bugs510677
milestone1.9.3a1pre
Fix for bug 510677 (Avoid XPCCallContext for WrapNativeToJSVal). r/sr=jst.
content/base/public/nsContentUtils.h
content/base/src/nsContentUtils.cpp
content/events/src/nsEventListenerManager.cpp
content/html/content/src/nsHTMLScriptElement.cpp
content/xbl/src/nsXBLBinding.cpp
content/xbl/src/nsXBLProtoImpl.cpp
content/xbl/src/nsXBLProtoImplMethod.cpp
content/xul/templates/src/nsXULTemplateBuilder.cpp
dom/base/nsDOMClassInfo.cpp
dom/base/nsDOMClassInfo.h
dom/base/nsGlobalWindow.cpp
dom/base/nsJSEnvironment.cpp
dom/src/threads/nsDOMWorker.cpp
js/src/xpconnect/idl/nsIXPConnect.idl
js/src/xpconnect/src/nsXPConnect.cpp
layout/build/nsLayoutStatics.h
--- a/content/base/public/nsContentUtils.h
+++ b/content/base/public/nsContentUtils.h
@@ -103,16 +103,17 @@ class nsIPref;
 struct JSRuntime;
 class nsICaseConversion;
 class nsIUGenCategory;
 class nsIWidget;
 class nsIDragSession;
 class nsPIDOMWindow;
 class nsPIDOMEventTarget;
 class nsIPresShell;
+class nsIXPConnectJSObjectHolder;
 #ifdef MOZ_XTF
 class nsIXTFService;
 #endif
 #ifdef IBMBIDI
 class nsIBidiKeyboard;
 #endif
 class nsIMIMEHeaderParam;
 
@@ -1461,16 +1462,35 @@ public:
   GetDocumentFromScriptContext(nsIScriptContext *aScriptContext);
 
   /**
    * The method checks whether the caller can access native anonymous content.
    * If there is no JS in the stack or privileged JS is running, this
    * method returns PR_TRUE, otherwise PR_FALSE.
    */
   static PRBool CanAccessNativeAnon();
+
+  static nsresult WrapNative(JSContext *cx, JSObject *scope,
+                             nsISupports *native, const nsIID* aIID, jsval *vp,
+                             // If non-null aHolder will keep the jsval alive
+                             // while there's a ref to it
+                             nsIXPConnectJSObjectHolder** aHolder = nsnull,
+                             PRBool aAllowWrapping = PR_FALSE);
+
+  // Same as the WrapNative above, but use this one if aIID is nsISupports' IID.
+  static nsresult WrapNative(JSContext *cx, JSObject *scope,
+                             nsISupports *native,  jsval *vp,
+                             // If non-null aHolder will keep the jsval alive
+                             // while there's a ref to it
+                             nsIXPConnectJSObjectHolder** aHolder = nsnull,
+                             PRBool aAllowWrapping = PR_FALSE)
+  {
+    return WrapNative(cx, scope, native, nsnull, vp, aHolder, aAllowWrapping);
+  }
+
 private:
 
   static PRBool InitializeEventTable();
 
   static nsresult doReparentContentWrapper(nsIContent *aChild,
                                            JSContext *cx,
                                            JSObject *aOldGlobal,
                                            JSObject *aNewGlobal,
--- a/content/base/src/nsContentUtils.cpp
+++ b/content/base/src/nsContentUtils.cpp
@@ -161,16 +161,17 @@ static NS_DEFINE_CID(kXTFServiceCID, NS_
 #include "nsIChromeRegistry.h"
 #include "nsIMIMEHeaderParam.h"
 #include "nsIDOMXULCommandEvent.h"
 #include "nsIDOMAbstractView.h"
 #include "nsIDOMDragEvent.h"
 #include "nsDOMDataTransfer.h"
 #include "nsHtml5Module.h"
 #include "nsPresContext.h"
+#include "nsLayoutStatics.h"
 
 #ifdef IBMBIDI
 #include "nsIBidiKeyboard.h"
 #endif
 #include "nsCycleCollectionParticipant.h"
 
 // for ReportToConsole
 #include "nsIStringBundle.h"
@@ -5087,8 +5088,48 @@ nsContentUtils::DispatchXULCommand(nsICo
     return aShell->HandleDOMEventWithTarget(aTarget, event, &status);
   }
 
   nsCOMPtr<nsIDOMEventTarget> target = do_QueryInterface(aTarget);
   NS_ENSURE_STATE(target);
   PRBool dummy;
   return target->DispatchEvent(event, &dummy);
 }
+
+// static
+nsresult
+nsContentUtils::WrapNative(JSContext *cx, JSObject *scope, nsISupports *native,
+                           const nsIID* aIID, jsval *vp,
+                           nsIXPConnectJSObjectHolder **aHolder,
+                           PRBool aAllowWrapping)
+{
+  if (!native) {
+    NS_ASSERTION(!aHolder || !*aHolder, "*aHolder should be null!");
+
+    *vp = JSVAL_NULL;
+
+    return NS_OK;
+  }
+
+  NS_ENSURE_TRUE(sXPConnect && sThreadJSContextStack, NS_ERROR_UNEXPECTED);
+
+  // Keep sXPConnect and sThreadJSContextStack alive.
+  nsLayoutStaticsRef layoutStaticsRef;
+
+  JSContext *topJSContext;
+  nsresult rv = sThreadJSContextStack->Peek(&topJSContext);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  PRBool push = topJSContext != cx;
+  if (push) {
+    rv = sThreadJSContextStack->Push(cx);
+    NS_ENSURE_SUCCESS(rv, rv);
+  }
+
+  rv = sXPConnect->WrapNativeToJSVal(cx, scope, native, aIID, aAllowWrapping,
+                                     vp, aHolder);
+
+  if (push) {
+    sThreadJSContextStack->Pop(nsnull);
+  }
+
+  return rv;
+}
--- a/content/events/src/nsEventListenerManager.cpp
+++ b/content/events/src/nsEventListenerManager.cpp
@@ -827,27 +827,23 @@ nsEventListenerManager::RegisterScriptEv
     if (sAddListenerID == JSVAL_VOID) {
       JSAutoRequest ar(cx);
       sAddListenerID =
         STRING_TO_JSVAL(::JS_InternString(cx, "addEventListener"));
     }
 
     if (aContext->GetScriptTypeID() == nsIProgrammingLanguage::JAVASCRIPT) {
         nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
-        rv = nsContentUtils::XPConnect()->
-          WrapNative(cx, (JSObject *)aScope, aObject, NS_GET_IID(nsISupports),
-                     getter_AddRefs(holder));
+        jsval v;
+        rv = nsContentUtils::WrapNative(cx, (JSObject *)aScope, aObject, &v,
+                                        getter_AddRefs(holder));
         NS_ENSURE_SUCCESS(rv, rv);
-        JSObject *jsobj = nsnull;
       
-        rv = holder->GetJSObject(&jsobj);
-        NS_ENSURE_SUCCESS(rv, rv);
-
         rv = nsContentUtils::GetSecurityManager()->
-          CheckPropertyAccess(cx, jsobj,
+          CheckPropertyAccess(cx, JSVAL_TO_OBJECT(v),
                               "EventTarget",
                               sAddListenerID,
                               nsIXPCSecurityManager::ACCESS_SET_PROPERTY);
         if (NS_FAILED(rv)) {
           // XXX set pending exception on the native call context?
           return rv;
         }
     } else {
--- a/content/html/content/src/nsHTMLScriptElement.cpp
+++ b/content/html/content/src/nsHTMLScriptElement.cpp
@@ -219,32 +219,23 @@ nsHTMLScriptEventHandler::Invoke(nsISupp
   }
   // Fail if is no script context is available...
   if (!scriptContext) {
     return NS_ERROR_FAILURE;
   }
 
   // wrap the target object...
   JSContext *cx = (JSContext *)scriptContext->GetNativeContext();
-  JSObject *scriptObject = nsnull;
   JSObject *scope = sgo->GetGlobalJSObject();
 
   nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
-  nsContentUtils::XPConnect()->WrapNative(cx, scope,
-                                          aTargetObject,
-                                          NS_GET_IID(nsISupports),
-                                          getter_AddRefs(holder));
-  if (holder) {
-    holder->GetJSObject(&scriptObject);
-  }
-
-  // Fail if wrapping the native object failed...
-  if (!scriptObject) {
-    return NS_ERROR_FAILURE;
-  }
+  jsval v;
+  rv = nsContentUtils::WrapNative(cx, scope, aTargetObject, &v,
+                                  getter_AddRefs(holder));
+  NS_ENSURE_SUCCESS(rv, rv);
 
   // Build up the array of argument names...
   //
   // Since this array is temporary (and const) the 'argument name' strings
   // are NOT copied.  Instead each element points into the underlying buffer
   // of the corresponding element in the mArgNames array...
   //
   // Remember, this is the number of arguments to compile the function with...
@@ -272,17 +263,17 @@ nsHTMLScriptEventHandler::Invoke(nsISupp
 
   // Null terminate for good luck ;-)
   args[i] = nsnull;
 
   // Compile the event handler script...
   void* funcObject = nsnull;
   NS_NAMED_LITERAL_CSTRING(funcName, "anonymous");
 
-  rv = scriptContext->CompileFunction(scriptObject,
+  rv = scriptContext->CompileFunction(JSVAL_TO_OBJECT(v),
                                       funcName,   // method name
                                       argc,       // no of arguments
                                       args,       // argument names
                                       scriptBody, // script text
                                       nsnull,     // XXX: URL
                                       lineNumber, // line no (for errors)
                                       JSVERSION_DEFAULT, // Default for now?
                                       PR_FALSE,   // shared ?
--- a/content/xbl/src/nsXBLBinding.cpp
+++ b/content/xbl/src/nsXBLBinding.cpp
@@ -1084,27 +1084,25 @@ nsXBLBinding::ChangeDocument(nsIDocument
           nsCOMPtr<nsIScriptContext> context = global->GetContext();
           if (context) {
             JSContext *cx = (JSContext *)context->GetNativeContext();
  
             nsCxPusher pusher;
             pusher.Push(cx);
 
             nsCOMPtr<nsIXPConnectJSObjectHolder> wrapper;
-            nsresult rv = nsContentUtils::XPConnect()->
-              WrapNative(cx, global->GetGlobalJSObject(),
-                         mBoundElement, NS_GET_IID(nsISupports),
-                         getter_AddRefs(wrapper));
+            jsval v;
+            nsresult rv =
+              nsContentUtils::WrapNative(cx, global->GetGlobalJSObject(),
+                                         mBoundElement, &v,
+                                         getter_AddRefs(wrapper));
             if (NS_FAILED(rv))
               return;
 
-            JSObject* scriptObject = nsnull;
-            rv = wrapper->GetJSObject(&scriptObject);
-            if (NS_FAILED(rv))
-              return;
+            JSObject* scriptObject = JSVAL_TO_OBJECT(v);
 
             // XXX Stay in sync! What if a layered binding has an
             // <interface>?!
             // XXXbz what does that comment mean, really?  It seems to date
             // back to when there was such a thing as an <interface>, whever
             // that was...
 
             // Find the right prototype.
--- a/content/xbl/src/nsXBLProtoImpl.cpp
+++ b/content/xbl/src/nsXBLProtoImpl.cpp
@@ -126,30 +126,26 @@ nsXBLProtoImpl::InitTargetObjects(nsXBLP
     return NS_ERROR_UNEXPECTED;
   }
 
   // Because our prototype implementation has a class, we need to build up a corresponding
   // class for the concrete implementation in the bound document.
   JSContext* jscontext = (JSContext*)aContext->GetNativeContext();
   JSObject* global = sgo->GetGlobalJSObject();
   nsCOMPtr<nsIXPConnectJSObjectHolder> wrapper;
-  rv = nsContentUtils::XPConnect()->WrapNative(jscontext, global,
-                                               aBoundElement,
-                                               NS_GET_IID(nsISupports),
-                                               getter_AddRefs(wrapper));
-  NS_ENSURE_SUCCESS(rv, rv);
-  JSObject * object = nsnull;
-  rv = wrapper->GetJSObject(&object);
+  jsval v;
+  rv = nsContentUtils::WrapNative(jscontext, global, aBoundElement, &v,
+                                  getter_AddRefs(wrapper));
   NS_ENSURE_SUCCESS(rv, rv);
 
   // All of the above code was just obtaining the bound element's script object and its immediate
   // concrete base class.  We need to alter the object so that our concrete class is interposed
   // between the object and its base class.  We become the new base class of the object, and the
   // object's old base class becomes the new class' base class.
-  rv = aBinding->InitClass(mClassName, jscontext, global, object,
+  rv = aBinding->InitClass(mClassName, jscontext, global, JSVAL_TO_OBJECT(v),
                            aTargetClassObject);
   if (NS_FAILED(rv))
     return rv;
 
   nsContentUtils::PreserveWrapper(aBoundElement, aBoundElement);
 
   wrapper.swap(*aScriptObjectHolder);
   
--- a/content/xbl/src/nsXBLProtoImplMethod.cpp
+++ b/content/xbl/src/nsXBLProtoImplMethod.cpp
@@ -290,26 +290,23 @@ nsXBLProtoImplAnonymousMethod::Execute(n
     return NS_OK;
   }
   
   JSContext* cx = (JSContext*) context->GetNativeContext();
 
   JSObject* globalObject = global->GetGlobalJSObject();
 
   nsCOMPtr<nsIXPConnectJSObjectHolder> wrapper;
+  jsval v;
   nsresult rv =
-    nsContentUtils::XPConnect()->WrapNative(cx, globalObject,
-                                            aBoundElement,
-                                            NS_GET_IID(nsISupports),
-                                            getter_AddRefs(wrapper));
+    nsContentUtils::WrapNative(cx, globalObject, aBoundElement, &v,
+                               getter_AddRefs(wrapper));
   NS_ENSURE_SUCCESS(rv, rv);
 
-  JSObject* thisObject;
-  rv = wrapper->GetJSObject(&thisObject);
-  NS_ENSURE_SUCCESS(rv, rv);
+  JSObject* thisObject = JSVAL_TO_OBJECT(v);
 
   JSAutoRequest ar(cx);
 
   // Clone the function object, using thisObject as the parent so "this" is in
   // the scope chain of the resulting function (for backwards compat to the
   // days when this was an event handler).
   JSObject* method = ::JS_CloneFunctionObject(cx, mJSMethodObject, thisObject);
   if (!method)
--- a/content/xul/templates/src/nsXULTemplateBuilder.cpp
+++ b/content/xul/templates/src/nsXULTemplateBuilder.cpp
@@ -1392,63 +1392,50 @@ nsXULTemplateBuilder::InitHTMLTemplateRo
 
     JSContext* jscontext = reinterpret_cast<JSContext*>(context->GetNativeContext());
     NS_ASSERTION(context != nsnull, "no jscontext");
     if (! jscontext)
         return NS_ERROR_UNEXPECTED;
 
     JSAutoRequest ar(jscontext);
 
-    nsIXPConnect *xpc = nsContentUtils::XPConnect();
-
-    JSObject* jselement = nsnull;
-
+    jsval v;
     nsCOMPtr<nsIXPConnectJSObjectHolder> wrapper;
-    rv = xpc->WrapNative(jscontext, scope, mRoot, NS_GET_IID(nsIDOMElement),
-                         getter_AddRefs(wrapper));
+    rv = nsContentUtils::WrapNative(jscontext, scope, mRoot,
+                                    &NS_GET_IID(nsIDOMElement), &v,
+                                    getter_AddRefs(wrapper));
     NS_ENSURE_SUCCESS(rv, rv);
 
-    rv = wrapper->GetJSObject(&jselement);
-    NS_ENSURE_SUCCESS(rv, rv);
+    JSObject* jselement = JSVAL_TO_OBJECT(v);
 
     if (mDB) {
         // database
-        rv = xpc->WrapNative(jscontext, scope, mDB,
-                             NS_GET_IID(nsIRDFCompositeDataSource),
-                             getter_AddRefs(wrapper));
+        jsval jsdatabase;
+        rv = nsContentUtils::WrapNative(jscontext, scope, mDB,
+                                        &NS_GET_IID(nsIRDFCompositeDataSource),
+                                        &jsdatabase, getter_AddRefs(wrapper));
         NS_ENSURE_SUCCESS(rv, rv);
 
-        JSObject* jsobj;
-        rv = wrapper->GetJSObject(&jsobj);
-        NS_ENSURE_SUCCESS(rv, rv);
-
-        jsval jsdatabase = OBJECT_TO_JSVAL(jsobj);
-
         PRBool ok;
         ok = JS_SetProperty(jscontext, jselement, "database", &jsdatabase);
         NS_ASSERTION(ok, "unable to set database property");
         if (! ok)
             return NS_ERROR_FAILURE;
     }
 
     {
         // builder
+        jsval jsbuilder;
         nsCOMPtr<nsIXPConnectJSObjectHolder> wrapper;
-        rv = xpc->WrapNative(jscontext, jselement,
-                             static_cast<nsIXULTemplateBuilder*>(this),
-                             NS_GET_IID(nsIXULTemplateBuilder),
-                             getter_AddRefs(wrapper));
+        rv = nsContentUtils::WrapNative(jscontext, jselement,
+                                        static_cast<nsIXULTemplateBuilder*>(this),
+                                        &NS_GET_IID(nsIXULTemplateBuilder),
+                                        &jsbuilder, getter_AddRefs(wrapper));
         NS_ENSURE_SUCCESS(rv, rv);
 
-        JSObject* jsobj;
-        rv = wrapper->GetJSObject(&jsobj);
-        NS_ENSURE_SUCCESS(rv, rv);
-
-        jsval jsbuilder = OBJECT_TO_JSVAL(jsobj);
-
         PRBool ok;
         ok = JS_SetProperty(jscontext, jselement, "builder", &jsbuilder);
         if (! ok)
             return NS_ERROR_FAILURE;
     }
 
     return NS_OK;
 }
--- a/dom/base/nsDOMClassInfo.cpp
+++ b/dom/base/nsDOMClassInfo.cpp
@@ -1643,37 +1643,16 @@ nsDOMClassInfo::DefineStaticJSVals(JSCon
   SET_JSVAL_TO_STRING(sOncut_id,           cx, "oncut");
   SET_JSVAL_TO_STRING(sOnpaste_id,         cx, "onpaste");
   SET_JSVAL_TO_STRING(sJava_id,            cx, "java");
   SET_JSVAL_TO_STRING(sPackages_id,        cx, "Packages");
 
   return NS_OK;
 }
 
-// static
-nsresult
-nsDOMClassInfo::WrapNative(JSContext *cx, JSObject *scope, nsISupports *native,
-                           const nsIID* aIID, PRBool aAllowWrapping, jsval *vp,
-                           nsIXPConnectJSObjectHolder **aHolder)
-{
-  if (!native) {
-    NS_ASSERTION(!aHolder || !*aHolder, "*aHolder should be null!");
-
-    *vp = JSVAL_NULL;
-
-    return NS_OK;
-  }
-
-  NS_ENSURE_TRUE(sXPConnect, NS_ERROR_UNEXPECTED);
-
-  return sXPConnect->WrapNativeToJSVal(cx, ::JS_GetGlobalForObject(cx, scope),
-                                       native, aIID, aAllowWrapping, vp,
-                                       aHolder);
-}
-
 static nsresult
 CreateExceptionFromResult(JSContext *cx, nsresult aResult)
 {
   nsCOMPtr<nsIExceptionService> xs =
     do_GetService(NS_EXCEPTIONSERVICE_CONTRACTID);
   if (!xs) {
     return NS_ERROR_FAILURE;
   }
--- a/dom/base/nsDOMClassInfo.h
+++ b/dom/base/nsDOMClassInfo.h
@@ -43,16 +43,17 @@
 #include "nsIDOMClassInfo.h"
 #include "nsIXPCScriptable.h"
 #include "jsapi.h"
 #include "jsobj.h"
 #include "nsIScriptSecurityManager.h"
 #include "nsIScriptContext.h"
 #include "nsDOMJSUtils.h" // for GetScriptContextFromJSContext
 #include "nsIScriptGlobalObject.h"
+#include "nsContentUtils.h"
 
 class nsIDOMWindow;
 class nsIDOMNSHTMLOptionCollection;
 class nsIPluginInstance;
 class nsIForm;
 class nsIDOMNodeList;
 class nsIDOMDocument;
 class nsIHTMLDocument;
@@ -132,17 +133,21 @@ public:
     return new nsDOMClassInfo(aData);
   }
 
   static nsresult WrapNative(JSContext *cx, JSObject *scope,
                              nsISupports *native, const nsIID* aIID,
                              PRBool aAllowWrapping, jsval *vp,
                              // If non-null aHolder will keep the jsval alive
                              // while there's a ref to it
-                             nsIXPConnectJSObjectHolder** aHolder = nsnull);
+                             nsIXPConnectJSObjectHolder** aHolder = nsnull)
+  {
+    return nsContentUtils::WrapNative(cx, scope, native, aIID, vp, aHolder,
+                                      aAllowWrapping);
+  }
 
   // Same as the WrapNative above, but use this one if aIID is nsISupports' IID.
   static nsresult WrapNative(JSContext *cx, JSObject *scope,
                              nsISupports *native, PRBool aAllowWrapping,
                              jsval *vp,
                              // If non-null aHolder will keep the jsval alive
                              // while there's a ref to it
                              nsIXPConnectJSObjectHolder** aHolder = nsnull)
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -1674,16 +1674,17 @@ nsGlobalWindow::SetNewDocument(nsIDocume
 
     nsGlobalWindow *currentInner = GetCurrentInnerWindowInternal();
 
     nsRefPtr<nsGlobalWindow> newInnerWindow;
 
     nsCOMPtr<nsIDOMChromeWindow> thisChrome =
       do_QueryInterface(static_cast<nsIDOMWindow *>(this));
     nsCOMPtr<nsIXPConnectJSObjectHolder> navigatorHolder;
+    jsval nav;
 
     PRBool isChrome = PR_FALSE;
 
     nsCxPusher cxPusher;
     if (!cxPusher.Push(cx)) {
       return NS_ERROR_FAILURE;
     }
 
@@ -1752,19 +1753,19 @@ nsGlobalWindow::SetNewDocument(nsIDocume
         if (mNavigator && !aState) {
           // Hold on to the navigator wrapper so that we can set
           // window.navigator in the new window to point to the same
           // object (assuming we didn't change origins etc). See bug
           // 163645 for more on why we need this.
 
           nsIDOMNavigator* navigator =
             static_cast<nsIDOMNavigator*>(mNavigator.get());
-          xpc->WrapNative(cx, currentInner->mJSObject, navigator,
-                          NS_GET_IID(nsIDOMNavigator),
-                          getter_AddRefs(navigatorHolder));
+          nsContentUtils::WrapNative(cx, currentInner->mJSObject, navigator,
+                                     &NS_GET_IID(nsIDOMNavigator), &nav,
+                                     getter_AddRefs(navigatorHolder));
         }
       }
 
       if (!aState) {
         // This is redundant if we're restoring from a previous inner window.
         nsIScriptGlobalObject *sgo =
           (nsIScriptGlobalObject *)newInnerWindow.get();
 
@@ -1978,34 +1979,33 @@ nsGlobalWindow::SetNewDocument(nsIDocume
             // Initialize DOM classes etc on the inner window.
             void *glob = newInnerWindow->mScriptGlobals[NS_STID_INDEX(st_id)];
             rv = this_ctx->InitClasses(glob);
             NS_ENSURE_SUCCESS(rv, rv);
 
             if (navigatorHolder &&
                 st_id == nsIProgrammingLanguage::JAVASCRIPT) {
               // Restore window.navigator onto the new inner window.
-              JSObject *nav;
               JSAutoRequest ar(cx);
-              navigatorHolder->GetJSObject(&nav);
 
               ::JS_DefineProperty(cx, newInnerWindow->mJSObject, "navigator",
-                                  OBJECT_TO_JSVAL(nav), nsnull, nsnull,
+                                  nav, nsnull, nsnull,
                                   JSPROP_ENUMERATE | JSPROP_PERMANENT |
                                   JSPROP_READONLY);
 
               // The Navigator's prototype object keeps a reference to the
               // window in which it was first created and can thus cause that
               // window to stay alive for too long. Reparenting it here allows
               // the window to be collected sooner.
               nsIDOMNavigator* navigator =
                 static_cast<nsIDOMNavigator*>(mNavigator);
 
               xpc->
-                ReparentWrappedNativeIfFound(cx, nav, newInnerWindow->mJSObject,
+                ReparentWrappedNativeIfFound(cx, JSVAL_TO_OBJECT(nav),
+                                             newInnerWindow->mJSObject,
                                              navigator,
                                              getter_AddRefs(navigatorHolder));
             }
           }
         }
       }
 
       if (mArguments) {
--- a/dom/base/nsJSEnvironment.cpp
+++ b/dom/base/nsJSEnvironment.cpp
@@ -1888,22 +1888,17 @@ nsJSContext::JSObjectFromInterface(nsISu
       return NS_OK;
   }
 
   // Get the jsobject associated with this target
   // We don't wrap here because we trust the JS engine to wrap the target
   // later.
   nsresult rv;
   jsval v;
-  rv = nsContentUtils::XPConnect()->WrapNativeToJSVal(mContext,
-                                                      (JSObject *)aScope,
-                                                      aTarget,
-                                                      &NS_GET_IID(nsISupports),
-                                                      PR_FALSE,
-                                                      &v, nsnull);
+  rv = nsContentUtils::WrapNative(mContext, (JSObject *)aScope, aTarget, &v);
   NS_ENSURE_SUCCESS(rv, rv);
 
 #ifdef NS_DEBUG
   nsCOMPtr<nsISupports> targetSupp = do_QueryInterface(aTarget);
   nsCOMPtr<nsISupports> native =
     nsContentUtils::XPConnect()->GetNativeOfWrapper(mContext,
                                                     JSVAL_TO_OBJECT(v));
   NS_ASSERTION(native == targetSupp, "Native should be the target!");
@@ -2546,19 +2541,19 @@ nsJSContext::InitContext(nsIScriptGlobal
     // our XPCWrappedNativeScope. Perhaps XPConnect should have a more
     // targeted API?
     rv = xpc->InitClasses(mContext, global);
     NS_ENSURE_SUCCESS(rv, rv);
 
     nsCOMPtr<nsIClassInfo> ci(do_QueryInterface(aGlobalObject));
 
     if (ci) {
-      rv = xpc->WrapNative(mContext, global, aGlobalObject,
-                           NS_GET_IID(nsISupports),
-                           getter_AddRefs(holder));
+      jsval v;
+      rv = nsContentUtils::WrapNative(mContext, global, aGlobalObject, &v,
+                                      getter_AddRefs(holder));
       NS_ENSURE_SUCCESS(rv, rv);
 
       nsCOMPtr<nsIXPConnectWrappedNative> wrapper(do_QueryInterface(holder));
       NS_ENSURE_TRUE(wrapper, NS_ERROR_FAILURE);
 
       rv = wrapper->RefreshPrototype();
       NS_ENSURE_SUCCESS(rv, rv);
     }
@@ -2694,25 +2689,21 @@ nsJSContext::ConvertSupportsTojsvals(nsI
 #ifdef NS_DEBUG
           // but first, check its not another nsISupportsPrimitive, as
           // these are now deprecated for use with script contexts.
           nsCOMPtr<nsISupportsPrimitive> prim(do_QueryInterface(arg));
           NS_ASSERTION(prim == nsnull,
                        "Don't pass nsISupportsPrimitives - use nsIVariant!");
 #endif
           nsCOMPtr<nsIXPConnectJSObjectHolder> wrapper;
-          rv = xpc->WrapNative(mContext, (JSObject *)aScope, arg,
-                               NS_GET_IID(nsISupports),
-                               getter_AddRefs(wrapper));
+          jsval v;
+          rv = nsContentUtils::WrapNative(mContext, (JSObject *)aScope, arg,
+                                          &v, getter_AddRefs(wrapper));
           if (NS_SUCCEEDED(rv)) {
-            JSObject *obj;
-            rv = wrapper->GetJSObject(&obj);
-            if (NS_SUCCEEDED(rv)) {
-              *thisval = OBJECT_TO_JSVAL(obj);
-            }
+            *thisval = v;
           }
         }
       }
     }
   } else {
     nsCOMPtr<nsIVariant> variant(do_QueryInterface(aArgs));
     if (variant)
       rv = xpc->VariantToJS(mContext, (JSObject *)aScope, variant, argv);
@@ -2901,30 +2892,24 @@ nsJSContext::AddSupportsPrimitiveTojsval
       nsIID *iid = nsnull;
 
       p->GetData(getter_AddRefs(data));
       p->GetDataIID(&iid);
       NS_ENSURE_TRUE(iid, NS_ERROR_UNEXPECTED);
 
       AutoFree iidGuard(iid); // Free iid upon destruction.
 
-      nsresult rv;
-      nsCOMPtr<nsIXPConnect> xpc(do_GetService(nsIXPConnect::GetCID(), &rv));
+      nsCOMPtr<nsIXPConnectJSObjectHolder> wrapper;
+      jsval v;
+      nsresult rv = nsContentUtils::WrapNative(cx, ::JS_GetGlobalObject(cx),
+                                               data, iid, &v,
+                                               getter_AddRefs(wrapper));
       NS_ENSURE_SUCCESS(rv, rv);
 
-      nsCOMPtr<nsIXPConnectJSObjectHolder> wrapper;
-      rv = xpc->WrapNative(cx, ::JS_GetGlobalObject(cx), data,
-                           *iid, getter_AddRefs(wrapper));
-      NS_ENSURE_SUCCESS(rv, rv);
-
-      JSObject *obj;
-      rv = wrapper->GetJSObject(&obj);
-      NS_ENSURE_SUCCESS(rv, rv);
-
-      *aArgv = OBJECT_TO_JSVAL(obj);
+      *aArgv = v;
 
       break;
     }
     case nsISupportsPrimitive::TYPE_ID :
     case nsISupportsPrimitive::TYPE_PRUINT64 :
     case nsISupportsPrimitive::TYPE_PRINT64 :
     case nsISupportsPrimitive::TYPE_PRTIME :
     case nsISupportsPrimitive::TYPE_VOID : {
--- a/dom/src/threads/nsDOMWorker.cpp
+++ b/dom/src/threads/nsDOMWorker.cpp
@@ -305,34 +305,27 @@ nsDOMWorkerFunctions::NewXMLHttpRequest(
   }
 
   rv = worker->AddFeature(xhr, aCx);
   if (NS_FAILED(rv)) {
     JS_ReportOutOfMemory(aCx);
     return JS_FALSE;
   }
 
-  nsIXPConnect* xpc = nsContentUtils::XPConnect();
-
   nsCOMPtr<nsIXPConnectJSObjectHolder> xhrWrapped;
-  rv = xpc->WrapNative(aCx, aObj, static_cast<nsIXMLHttpRequest*>(xhr),
-                       NS_GET_IID(nsISupports), getter_AddRefs(xhrWrapped));
+  jsval v;
+  rv = nsContentUtils::WrapNative(aCx, aObj,
+                                  static_cast<nsIXMLHttpRequest*>(xhr), &v,
+                                  getter_AddRefs(xhrWrapped));
   if (NS_FAILED(rv)) {
     JS_ReportError(aCx, "Failed to wrap XMLHttpRequest!");
     return JS_FALSE;
   }
 
-  JSObject* xhrJSObj;
-  rv = xhrWrapped->GetJSObject(&xhrJSObj);
-  if (NS_FAILED(rv)) {
-    JS_ReportError(aCx, "Failed to get JSObject from wrapper!");
-    return JS_FALSE;
-  }
-
-  *aRval = OBJECT_TO_JSVAL(xhrJSObj);
+  *aRval = v;
   return JS_TRUE;
 }
 
 JSBool
 nsDOMWorkerFunctions::NewWorker(JSContext* aCx,
                                 JSObject* aObj,
                                 uintN aArgc,
                                 jsval* aArgv,
@@ -372,34 +365,26 @@ nsDOMWorkerFunctions::NewWorker(JSContex
   }
 
   nsresult rv = newWorker->InitializeInternal(owner, aCx, aObj, aArgc, aArgv);
   if (NS_FAILED(rv)) {
     JS_ReportError(aCx, "Couldn't initialize new worker!");
     return JS_FALSE;
   }
 
-  nsIXPConnect* xpc = nsContentUtils::XPConnect();
-
   nsCOMPtr<nsIXPConnectJSObjectHolder> workerWrapped;
-  rv = xpc->WrapNative(aCx, aObj, static_cast<nsIWorker*>(newWorker),
-                       NS_GET_IID(nsISupports), getter_AddRefs(workerWrapped));
+  jsval v;
+  rv = nsContentUtils::WrapNative(aCx, aObj, static_cast<nsIWorker*>(newWorker),
+                                  &v, getter_AddRefs(workerWrapped));
   if (NS_FAILED(rv)) {
     JS_ReportError(aCx, "Failed to wrap new worker!");
     return JS_FALSE;
   }
 
-  JSObject* workerJSObj;
-  rv = workerWrapped->GetJSObject(&workerJSObj);
-  if (NS_FAILED(rv)) {
-    JS_ReportError(aCx, "Failed to get JSObject from wrapper!");
-    return JS_FALSE;
-  }
-
-  *aRval = OBJECT_TO_JSVAL(workerJSObj);
+  *aRval = v;
   return JS_TRUE;
 }
 
 JSFunctionSpec gDOMWorkerFunctions[] = {
   { "dump",                  nsDOMWorkerFunctions::Dump,              1, 0, 0 },
   { "setTimeout",            nsDOMWorkerFunctions::SetTimeout,        1, 0, 0 },
   { "clearTimeout",          nsDOMWorkerFunctions::KillTimeout,       1, 0, 0 },
   { "setInterval",           nsDOMWorkerFunctions::SetInterval,       1, 0, 0 },
@@ -1209,22 +1194,21 @@ nsDOMWorker::InitializeInternal(nsIScrip
   mScriptURL.Assign(nsDependentJSString(str));
   NS_ENSURE_FALSE(mScriptURL.IsEmpty(), NS_ERROR_INVALID_ARG);
 
   mLock = nsAutoLock::NewLock("nsDOMWorker::mLock");
   NS_ENSURE_TRUE(mLock, NS_ERROR_OUT_OF_MEMORY);
 
   NS_ASSERTION(!mGlobal, "Already got a global?!");
 
-  nsIXPConnect* xpc = nsContentUtils::XPConnect();
-
   nsCOMPtr<nsIXPConnectJSObjectHolder> thisWrapped;
-  nsresult rv = xpc->WrapNative(aCx, aObj, static_cast<nsIWorker*>(this),
-                                NS_GET_IID(nsISupports),
-                                getter_AddRefs(thisWrapped));
+  jsval v;
+  nsresult rv = nsContentUtils::WrapNative(aCx, aObj,
+                                           static_cast<nsIWorker*>(this), &v,
+                                           getter_AddRefs(thisWrapped));
   NS_ENSURE_SUCCESS(rv, rv);
 
   NS_ASSERTION(mWrappedNative, "Post-create hook should have set this!");
 
   mKillTimer = do_CreateInstance(NS_TIMER_CONTRACTID, &rv);
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsCOMPtr<nsIThread> mainThread;
--- a/js/src/xpconnect/idl/nsIXPConnect.idl
+++ b/js/src/xpconnect/idl/nsIXPConnect.idl
@@ -462,16 +462,19 @@ interface nsIXPConnect : nsISupports
      * can pass in null for the aHolder argument, but in that case they must
      * ensure that aVal is rooted.
      * aIID may be null, it means the same as passing in
      * &NS_GET_IID(nsISupports) but when passing in null certain shortcuts
      * can be taken because we know without comparing IIDs that the caller is
      * asking for an nsISupports wrapper.
      * If aAllowWrapper, then the returned value will be wrapped in the proper
      * type of security wrapper on top of the XPCWrappedNative (if needed).
+     * This method doesn't push aJSContext on the context stack, so the caller
+     * is required to push it if the top of the context stack is not equal to
+     * aJSContext.
      */
     void
     wrapNativeToJSVal(in JSContextPtr aJSContext,
                       in JSObjectPtr  aScope,
                       in nsISupports  aCOMObj,
                       in nsIIDPtr     aIID,
                       in boolean      aAllowWrapper,
                       out JSVal       aVal,
--- a/js/src/xpconnect/src/nsXPConnect.cpp
+++ b/js/src/xpconnect/src/nsXPConnect.cpp
@@ -1192,29 +1192,61 @@ nsXPConnect::InitClassesWithNewWrappedGl
             return UnexpectedFailure(NS_ERROR_FAILURE);
     }
 
     NS_ADDREF(*_retval = holder);
 
     return NS_OK;
 }
 
+static nsresult
+NativeInterface2JSObject(XPCLazyCallContext & lccx,
+                         JSObject * aScope,
+                         nsISupports *aCOMObj,
+                         const nsIID * aIID,
+                         PRBool aAllowWrapping,
+                         jsval *aVal,
+                         nsIXPConnectJSObjectHolder **aHolder)
+{
+    nsresult rv;
+    if(!XPCConvert::NativeInterface2JSObject(lccx, aVal, aHolder, aCOMObj, aIID,
+                                             nsnull, nsnull, aScope,
+                                             aAllowWrapping, OBJ_IS_NOT_GLOBAL,
+                                             &rv))
+        return rv;
+
+#ifdef DEBUG
+    NS_ASSERTION(!XPCNativeWrapper::IsNativeWrapper(JSVAL_TO_OBJECT(*aVal)),
+                 "Shouldn't be returning a native wrapper here");
+#endif
+    
+    return NS_OK;
+}
+
 /* nsIXPConnectJSObjectHolder wrapNative (in JSContextPtr aJSContext, in JSObjectPtr aScope, in nsISupports aCOMObj, in nsIIDRef aIID); */
 NS_IMETHODIMP
 nsXPConnect::WrapNative(JSContext * aJSContext,
                         JSObject * aScope,
                         nsISupports *aCOMObj,
                         const nsIID & aIID,
                         nsIXPConnectJSObjectHolder **aHolder)
 {
     NS_ASSERTION(aHolder, "bad param");
+    NS_ASSERTION(aJSContext, "bad param");
+    NS_ASSERTION(aScope, "bad param");
+    NS_ASSERTION(aCOMObj, "bad param");
+
+    XPCCallContext ccx(NATIVE_CALLER, aJSContext);
+    if(!ccx.IsValid())
+        return UnexpectedFailure(NS_ERROR_FAILURE);
+    XPCLazyCallContext lccx(ccx);
 
     jsval v;
-    return WrapNativeToJSVal(aJSContext, aScope, aCOMObj, &aIID, PR_FALSE,
-                             &v, aHolder);
+    return NativeInterface2JSObject(lccx, aScope, aCOMObj, &aIID, PR_FALSE, &v,
+                                    aHolder);
 }
 
 /* void wrapNativeToJSVal (in JSContextPtr aJSContext, in JSObjectPtr aScope, in nsISupports aCOMObj, in nsIIDPtr aIID, out JSVal aVal, out nsIXPConnectJSObjectHolder aHolder); */
 NS_IMETHODIMP
 nsXPConnect::WrapNativeToJSVal(JSContext * aJSContext,
                                JSObject * aScope,
                                nsISupports *aCOMObj,
                                const nsIID * aIID,
@@ -1224,33 +1256,20 @@ nsXPConnect::WrapNativeToJSVal(JSContext
 {
     NS_ASSERTION(aJSContext, "bad param");
     NS_ASSERTION(aScope, "bad param");
     NS_ASSERTION(aCOMObj, "bad param");
 
     if(aHolder)
         *aHolder = nsnull;
 
-    XPCCallContext ccx(NATIVE_CALLER, aJSContext);
-    if(!ccx.IsValid())
-        return UnexpectedFailure(NS_ERROR_FAILURE);
-    XPCLazyCallContext lccx(ccx);
-
-    nsresult rv;
-    if(!XPCConvert::NativeInterface2JSObject(ccx, aVal, aHolder, aCOMObj, aIID,
-                                             nsnull, nsnull, aScope, aAllowWrapping,
-                                             OBJ_IS_NOT_GLOBAL, &rv))
-        return rv;
-
-#ifdef DEBUG
-    NS_ASSERTION(!XPCNativeWrapper::IsNativeWrapper(JSVAL_TO_OBJECT(*aVal)),
-                 "Shouldn't be returning a native wrapper here");
-#endif
-    
-    return NS_OK;
+    XPCLazyCallContext lccx(NATIVE_CALLER, aJSContext);
+
+    return NativeInterface2JSObject(lccx, aScope, aCOMObj, aIID, aAllowWrapping,
+                                    aVal, aHolder);
 }
 
 /* void wrapJS (in JSContextPtr aJSContext, in JSObjectPtr aJSObj, in nsIIDRef aIID, [iid_is (aIID), retval] out nsQIResult result); */
 NS_IMETHODIMP
 nsXPConnect::WrapJS(JSContext * aJSContext,
                     JSObject * aJSObj,
                     const nsIID & aIID,
                     void * *result)
--- a/layout/build/nsLayoutStatics.h
+++ b/layout/build/nsLayoutStatics.h
@@ -56,9 +56,22 @@ public:
 
 private:
   // not to be called!
   nsLayoutStatics();
 
   static void Shutdown();
 };
 
+class nsLayoutStaticsRef
+{
+public:
+  nsLayoutStaticsRef()
+  {
+    nsLayoutStatics::AddRef();
+  }
+  ~nsLayoutStaticsRef()
+  {
+    nsLayoutStatics::Release();
+  }
+};
+
 #endif // nsLayoutStatics_h__