Bug 958641 - De-holder nsIXPConnect::WrapNative. r=gabor
authorAndrew McCreight <continuation@gmail.com>
Wed, 01 Jul 2015 11:17:17 -0700
changeset 251008 44dd8a5ed9399209a004006073be991f389b32db
parent 251007 fe4679e180caf1a13fdafecfaf65ba67f4c247a7
child 251009 3a3dfde50685e918b2b66f5346d2cd74c6d8fe0a
push id28980
push usercbook@mozilla.com
push dateThu, 02 Jul 2015 13:44:32 +0000
treeherdermozilla-central@f1b3144fed94 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersgabor
bugs958641
milestone42.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 958641 - De-holder nsIXPConnect::WrapNative. r=gabor
dom/plugins/base/nsNPAPIPlugin.cpp
js/xpconnect/idl/nsIXPConnect.idl
js/xpconnect/loader/mozJSComponentLoader.cpp
js/xpconnect/src/XPCComponents.cpp
js/xpconnect/src/XPCJSID.cpp
js/xpconnect/src/XPCShellImpl.cpp
js/xpconnect/src/nsXPConnect.cpp
storage/mozStorageAsyncStatementJSHelper.cpp
storage/mozStorageStatementJSHelper.cpp
toolkit/components/places/PlaceInfo.cpp
widget/cocoa/nsMenuX.mm
xpfe/components/directory/nsDirectoryViewer.cpp
--- a/dom/plugins/base/nsNPAPIPlugin.cpp
+++ b/dom/plugins/base/nsNPAPIPlugin.cpp
@@ -1227,23 +1227,19 @@ NPObject*
   if (NS_WARN_IF(!jsapi.Init(doc->GetInnerWindow()))) {
     return nullptr;
   }
   JSContext* cx = jsapi.cx();
 
   nsCOMPtr<nsIXPConnect> xpc(do_GetService(nsIXPConnect::GetCID()));
   NS_ENSURE_TRUE(xpc, nullptr);
 
-  nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
+  JS::RootedObject obj(cx);
   xpc->WrapNative(cx, ::JS::CurrentGlobalOrNull(cx), element,
-                  NS_GET_IID(nsIDOMElement),
-                  getter_AddRefs(holder));
-  NS_ENSURE_TRUE(holder, nullptr);
-
-  JS::Rooted<JSObject*> obj(cx, holder->GetJSObject());
+                  NS_GET_IID(nsIDOMElement), obj.address());
   NS_ENSURE_TRUE(obj, nullptr);
 
   return nsJSObjWrapper::GetNewOrUsed(npp, cx, obj);
 }
 
 NPIdentifier
 _getstringidentifier(const NPUTF8* name)
 {
--- a/js/xpconnect/idl/nsIXPConnect.idl
+++ b/js/xpconnect/idl/nsIXPConnect.idl
@@ -261,17 +261,17 @@ interface nsIXPCFunctionThisTranslator :
 %{ C++
 // For use with the service manager
 // {CB6593E0-F9B2-11d2-BDD6-000064657374}
 #define NS_XPCONNECT_CID \
 { 0xcb6593e0, 0xf9b2, 0x11d2, \
     { 0xbd, 0xd6, 0x0, 0x0, 0x64, 0x65, 0x73, 0x74 } }
 %}
 
-[noscript, uuid(241fbefa-89dc-42b2-b180-08167d4b351b)]
+[noscript, uuid(8bc1230e-036b-4749-8763-768ed65df143)]
 interface nsIXPConnect : nsISupports
 {
 %{ C++
   NS_DEFINE_STATIC_CID_ACCESSOR(NS_XPCONNECT_CID)
 %}
 
     /**
      * Creates a new global object using the given aCOMObj as the global
@@ -298,23 +298,16 @@ interface nsIXPConnect : nsISupports
 
     const uint32_t INIT_JS_STANDARD_CLASSES  = 1 << 0;
     const uint32_t DONT_FIRE_ONNEWGLOBALHOOK = 1 << 1;
     const uint32_t OMIT_COMPONENTS_OBJECT    = 1 << 2;
 
     /**
     * wrapNative will create a new JSObject or return an existing one.
     *
-    * The JSObject is returned inside a refcounted nsIXPConnectJSObjectHolder.
-    * As long as this holder is held the JSObject will be protected from
-    * collection by JavaScript's garbage collector. It is a good idea to
-    * transfer the JSObject to some equally protected place before releasing
-    * the holder (i.e. use JS_SetProperty to make this object a property of
-    * some other JSObject).
-    *
     * This method now correctly deals with cases where the passed in xpcom
     * object already has an associated JSObject for the cases:
     *  1) The xpcom object has already been wrapped for use in the same scope
     *     as an nsIXPConnectWrappedNative.
     *  2) The xpcom object is in fact a nsIXPConnectWrappedJS and thus already
     *     has an underlying JSObject.
     *
     * It *might* be possible to QueryInterface the nsIXPConnectJSObjectHolder
@@ -327,23 +320,32 @@ interface nsIXPConnect : nsISupports
     * Returns:
     *    success:
     *       NS_OK
     *    failure:
     *       NS_ERROR_XPC_BAD_CONVERT_NATIVE
     *       NS_ERROR_XPC_CANT_GET_JSOBJECT_OF_DOM_OBJECT
     *       NS_ERROR_FAILURE
     */
-    nsIXPConnectJSObjectHolder
+    JSObjectPtr
     wrapNative(in JSContextPtr aJSContext,
                in JSObjectPtr  aScope,
                in nsISupports  aCOMObj,
                in nsIIDRef     aIID);
 
     /**
+     * Same as wrapNative, but it returns the JSObject in an nsIXPConnectJSObjectHolder.
+     */
+    nsIXPConnectJSObjectHolder
+    wrapNativeHolder(in JSContextPtr aJSContext,
+                     in JSObjectPtr  aScope,
+                     in nsISupports  aCOMObj,
+                     in nsIIDRef     aIID);
+
+    /**
      * Same as wrapNative, but it returns the JSObject in aVal. C++ callers
      * 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).
--- a/js/xpconnect/loader/mozJSComponentLoader.cpp
+++ b/js/xpconnect/loader/mozJSComponentLoader.cpp
@@ -579,23 +579,21 @@ mozJSComponentLoader::PrepareObjectForLo
     if (NS_SUCCEEDED(rv)) {
         fileURL->GetFile(getter_AddRefs(testFile));
     }
 
     if (testFile) {
         *aRealFile = true;
 
         if (XRE_GetProcessType() == GeckoProcessType_Default) {
-            nsCOMPtr<nsIXPConnectJSObjectHolder> locationHolder;
+            RootedObject locationObj(aCx);
             rv = xpc->WrapNative(aCx, obj, aComponentFile,
                                  NS_GET_IID(nsIFile),
-                                 getter_AddRefs(locationHolder));
+                                 locationObj.address());
             NS_ENSURE_SUCCESS(rv, nullptr);
-
-            RootedObject locationObj(aCx, locationHolder->GetJSObject());
             NS_ENSURE_TRUE(locationObj, nullptr);
 
             if (!JS_DefineProperty(aCx, obj, "__LOCATION__", locationObj, 0))
                 return nullptr;
         }
     }
 
     nsAutoCString nativePath;
--- a/js/xpconnect/src/XPCComponents.cpp
+++ b/js/xpconnect/src/XPCComponents.cpp
@@ -302,25 +302,22 @@ nsXPCComponents_Interfaces::Resolve(nsIX
         }
         if (!info)
             return NS_OK;
 
         nsCOMPtr<nsIJSIID> nsid = nsJSIID::NewID(info);
 
         if (nsid) {
             nsXPConnect* xpc = nsXPConnect::XPConnect();
-            nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
+            RootedObject idobj(cx);
             if (NS_SUCCEEDED(xpc->WrapNative(cx, obj,
                                              static_cast<nsIJSIID*>(nsid),
                                              NS_GET_IID(nsIJSIID),
-                                             getter_AddRefs(holder)))) {
-                RootedObject idobj(cx);
-                if (holder &&
-                    // Assign, not compare
-                    (idobj = holder->GetJSObject())) {
+                                             idobj.address()))) {
+                if (idobj) {
                     *resolvedp = true;
                     *_retval = JS_DefinePropertyById(cx, obj, id, idobj,
                                                      JSPROP_ENUMERATE |
                                                      JSPROP_READONLY |
                                                      JSPROP_PERMANENT |
                                                      JSPROP_RESOLVING);
                 }
             }
@@ -540,25 +537,22 @@ nsXPCComponents_InterfacesByID::Resolve(
             return NS_OK;
 
         nsCOMPtr<nsIJSIID> nsid = nsJSIID::NewID(info);
 
         if (!nsid)
             return NS_ERROR_OUT_OF_MEMORY;
 
         nsXPConnect* xpc = nsXPConnect::XPConnect();
-        nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
+        RootedObject idobj(cx);
         if (NS_SUCCEEDED(xpc->WrapNative(cx, obj,
                                          static_cast<nsIJSIID*>(nsid),
-                                            NS_GET_IID(nsIJSIID),
-                                            getter_AddRefs(holder)))) {
-            RootedObject idobj(cx);
-            if (holder &&
-                // Assign, not compare
-                (idobj = holder->GetJSObject())) {
+                                         NS_GET_IID(nsIJSIID),
+                                         idobj.address()))) {
+            if (idobj) {
                 *resolvedp = true;
                 *_retval =
                     JS_DefinePropertyById(cx, obj, id, idobj,
                                           JSPROP_ENUMERATE |
                                           JSPROP_READONLY |
                                           JSPROP_PERMANENT |
                                           JSPROP_RESOLVING);
             }
@@ -760,25 +754,22 @@ nsXPCComponents_Classes::Resolve(nsIXPCo
 
     JSAutoByteString name;
     if (JSID_IS_STRING(id) &&
         name.encodeLatin1(cx, JSID_TO_STRING(id)) &&
         name.ptr()[0] != '{') { // we only allow contractids here
         nsCOMPtr<nsIJSCID> nsid = nsJSCID::NewID(name.ptr());
         if (nsid) {
             nsXPConnect* xpc = nsXPConnect::XPConnect();
-            nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
+            RootedObject idobj(cx);
             if (NS_SUCCEEDED(xpc->WrapNative(cx, obj,
                                              static_cast<nsIJSCID*>(nsid),
                                              NS_GET_IID(nsIJSCID),
-                                             getter_AddRefs(holder)))) {
-                RootedObject idobj(cx);
-                if (holder &&
-                    // Assign, not compare
-                        (idobj = holder->GetJSObject())) {
+                                             idobj.address()))) {
+                if (idobj) {
                     *resolvedp = true;
                     *_retval = JS_DefinePropertyById(cx, obj, id, idobj,
                                                      JSPROP_ENUMERATE |
                                                      JSPROP_READONLY |
                                                      JSPROP_PERMANENT |
                                                      JSPROP_RESOLVING);
                 }
             }
@@ -999,25 +990,22 @@ nsXPCComponents_ClassesByID::Resolve(nsI
     JSAutoByteString name;
     RootedString str(cx, JSID_TO_STRING(id));
     if (name.encodeLatin1(cx, str) && name.ptr()[0] == '{' &&
         IsRegisteredCLSID(name.ptr())) // we only allow canonical CLSIDs here
     {
         nsCOMPtr<nsIJSCID> nsid = nsJSCID::NewID(name.ptr());
         if (nsid) {
             nsXPConnect* xpc = nsXPConnect::XPConnect();
-            nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
+            RootedObject idobj(cx);
             if (NS_SUCCEEDED(xpc->WrapNative(cx, obj,
                                              static_cast<nsIJSCID*>(nsid),
                                              NS_GET_IID(nsIJSCID),
-                                             getter_AddRefs(holder)))) {
-                RootedObject idobj(cx);
-                if (holder &&
-                    // Assign, not compare
-                    (idobj = holder->GetJSObject())) {
+                                             idobj.address()))) {
+                if (idobj) {
                     *resolvedp = true;
                     *_retval = JS_DefinePropertyById(cx, obj, id, idobj,
                                                      JSPROP_ENUMERATE |
                                                      JSPROP_READONLY |
                                                      JSPROP_PERMANENT |
                                                      JSPROP_RESOLVING);
                 }
             }
@@ -1758,23 +1746,18 @@ nsXPCComponents_Exception::CallOrConstru
         return ThrowAndFail(NS_ERROR_XPC_BAD_CONVERT_JS, cx, _retval);
 
     nsCOMPtr<nsIException> e = new Exception(nsCString(parser.eMsg),
                                              parser.eResult,
                                              EmptyCString(),
                                              parser.eStack,
                                              parser.eData);
 
-    nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
     RootedObject newObj(cx);
-
-    if (NS_FAILED(xpc->WrapNative(cx, obj, e, NS_GET_IID(nsIXPCException),
-                                  getter_AddRefs(holder))) || !holder ||
-        // Assign, not compare
-        !(newObj = holder->GetJSObject())) {
+    if (NS_FAILED(xpc->WrapNative(cx, obj, e, NS_GET_IID(nsIXPCException), newObj.address())) || !newObj) {
         return ThrowAndFail(NS_ERROR_XPC_CANT_CREATE_WN, cx, _retval);
     }
 
     args.rval().setObject(*newObj);
     return NS_OK;
 }
 
 /* bool hasInstance (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in jsval val, out bool bp); */
@@ -2006,29 +1989,21 @@ nsresult
 nsXPCConstructor::CallOrConstruct(nsIXPConnectWrappedNative* wrapper,JSContext* cx,
                                   HandleObject obj, const CallArgs& args, bool* _retval)
 {
     nsXPConnect* xpc = nsXPConnect::XPConnect();
 
     // security check not required because we are going to call through the
     // code which is reflected into JS which will do that for us later.
 
-    nsCOMPtr<nsIXPConnectJSObjectHolder> cidHolder;
-    nsCOMPtr<nsIXPConnectJSObjectHolder> iidHolder;
     RootedObject cidObj(cx);
     RootedObject iidObj(cx);
 
-    if (NS_FAILED(xpc->WrapNative(cx, obj, mClassID, NS_GET_IID(nsIJSCID),
-                                  getter_AddRefs(cidHolder))) || !cidHolder ||
-        // Assign, not compare
-        !(cidObj = cidHolder->GetJSObject()) ||
-        NS_FAILED(xpc->WrapNative(cx, obj, mInterfaceID, NS_GET_IID(nsIJSIID),
-                                  getter_AddRefs(iidHolder))) || !iidHolder ||
-        // Assign, not compare
-        !(iidObj = iidHolder->GetJSObject())) {
+    if (NS_FAILED(xpc->WrapNative(cx, obj, mClassID, NS_GET_IID(nsIJSCID), cidObj.address())) || !cidObj ||
+        NS_FAILED(xpc->WrapNative(cx, obj, mInterfaceID, NS_GET_IID(nsIJSIID), iidObj.address())) || !iidObj) {
         return ThrowAndFail(NS_ERROR_XPC_CANT_CREATE_WN, cx, _retval);
     }
 
     JS::Rooted<JS::Value> arg(cx, ObjectValue(*iidObj));
     RootedValue rval(cx);
     if (!JS_CallFunctionName(cx, cidObj, "createInstance", JS::HandleValueArray(arg), &rval) ||
         rval.isPrimitive()) {
         // createInstance will have thrown an exception
@@ -2255,29 +2230,26 @@ nsXPCComponents_Constructor::CallOrConst
             return ThrowAndFail(NS_ERROR_XPC_BAD_CONVERT_JS, cx, _retval);
     }
 
     if (args.length() >= 2) {
         // args[1] is an iid name string
         // XXXjband support passing "Components.interfaces.foo"?
 
         nsCOMPtr<nsIXPCComponents_Interfaces> ifaces;
-        nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
         RootedObject ifacesObj(cx);
 
         // we do the lookup by asking the Components.interfaces object
         // for the property with this name - i.e. we let its caching of these
         // nsIJSIID objects work for us.
 
         if (NS_FAILED(comp->GetInterfaces(getter_AddRefs(ifaces))) ||
             NS_FAILED(xpc->WrapNative(cx, obj, ifaces,
                                       NS_GET_IID(nsIXPCComponents_Interfaces),
-                                      getter_AddRefs(holder))) || !holder ||
-            // Assign, not compare
-            !(ifacesObj = holder->GetJSObject())) {
+                                      ifacesObj.address())) || !ifacesObj) {
             return ThrowAndFail(NS_ERROR_XPC_UNEXPECTED, cx, _retval);
         }
 
         RootedString str(cx, ToString(cx, args[1]));
         RootedId id(cx);
         if (!str || !JS_StringToId(cx, str, &id))
             return ThrowAndFail(NS_ERROR_XPC_BAD_CONVERT_JS, cx, _retval);
 
@@ -2307,25 +2279,22 @@ nsXPCComponents_Constructor::CallOrConst
         // argv[0] is a contractid name string
         // XXXjband support passing "Components.classes.foo"?
 
         // we do the lookup by asking the Components.classes object
         // for the property with this name - i.e. we let its caching of these
         // nsIJSCID objects work for us.
 
         nsCOMPtr<nsIXPCComponents_Classes> classes;
-        nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
         RootedObject classesObj(cx);
 
         if (NS_FAILED(comp->GetClasses(getter_AddRefs(classes))) ||
             NS_FAILED(xpc->WrapNative(cx, obj, classes,
                                       NS_GET_IID(nsIXPCComponents_Classes),
-                                      getter_AddRefs(holder))) || !holder ||
-            // Assign, not compare
-            !(classesObj = holder->GetJSObject())) {
+                                      classesObj.address())) || !classesObj) {
             return ThrowAndFail(NS_ERROR_XPC_UNEXPECTED, cx, _retval);
         }
 
         RootedString str(cx, ToString(cx, args[0]));
         RootedId id(cx);
         if (!str || !JS_StringToId(cx, str, &id))
             return ThrowAndFail(NS_ERROR_XPC_BAD_CONVERT_JS, cx, _retval);
 
@@ -2337,23 +2306,19 @@ nsXPCComponents_Constructor::CallOrConst
         if (NS_FAILED(xpc->GetWrappedNativeOfJSObject(cx, val.toObjectOrNull(),
                                                       getter_AddRefs(wn))) || !wn ||
             !(cClassID = do_QueryWrappedNative(wn))) {
             return ThrowAndFail(NS_ERROR_XPC_UNEXPECTED, cx, _retval);
         }
     }
 
     nsCOMPtr<nsIXPCConstructor> ctor = new nsXPCConstructor(cClassID, cInterfaceID, cInitializer);
-    nsCOMPtr<nsIXPConnectJSObjectHolder> holder2;
     RootedObject newObj(cx);
 
-    if (NS_FAILED(xpc->WrapNative(cx, obj, ctor, NS_GET_IID(nsIXPCConstructor),
-                                  getter_AddRefs(holder2))) || !holder2 ||
-        // Assign, not compare
-        !(newObj = holder2->GetJSObject())) {
+    if (NS_FAILED(xpc->WrapNative(cx, obj, ctor, NS_GET_IID(nsIXPCConstructor), newObj.address())) || !newObj) {
         return ThrowAndFail(NS_ERROR_XPC_CANT_CREATE_WN, cx, _retval);
     }
 
     args.rval().setObject(*newObj);
     return NS_OK;
 }
 
 /* bool hasInstance (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in jsval val, out bool bp); */
--- a/js/xpconnect/src/XPCJSID.cpp
+++ b/js/xpconnect/src/XPCJSID.cpp
@@ -761,24 +761,18 @@ JSObject*
 xpc_NewIDObject(JSContext* cx, HandleObject jsobj, const nsID& aID)
 {
     RootedObject obj(cx);
 
     nsCOMPtr<nsIJSID> iid = nsJSID::NewID(aID);
     if (iid) {
         nsXPConnect* xpc = nsXPConnect::XPConnect();
         if (xpc) {
-            nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
-            nsresult rv = xpc->WrapNative(cx, jsobj,
-                                          static_cast<nsISupports*>(iid),
-                                          NS_GET_IID(nsIJSID),
-                                          getter_AddRefs(holder));
-            if (NS_SUCCEEDED(rv) && holder) {
-                obj = holder->GetJSObject();
-            }
+            xpc->WrapNative(cx, jsobj, static_cast<nsISupports*>(iid),
+                            NS_GET_IID(nsIJSID), obj.address());
         }
     }
     return obj;
 }
 
 // note: returned pointer is only valid while |obj| remains alive!
 const nsID*
 xpc_JSObjectToID(JSContext* cx, JSObject* obj)
--- a/js/xpconnect/src/XPCShellImpl.cpp
+++ b/js/xpconnect/src/XPCShellImpl.cpp
@@ -169,30 +169,26 @@ GetLocationProperty(JSContext* cx, unsig
             nsAutoString absolutePath(*gWorkingDirectory);
             absolutePath.Append(filenameString);
 
             rv = NS_NewLocalFile(absolutePath,
                                  false, getter_AddRefs(location));
         }
 
         if (location) {
-            nsCOMPtr<nsIXPConnectJSObjectHolder> locationHolder;
-
             bool symlink;
             // don't normalize symlinks, because that's kind of confusing
             if (NS_SUCCEEDED(location->IsSymlink(&symlink)) &&
                 !symlink)
                 location->Normalize();
+            RootedObject locationObj(cx);
             rv = xpc->WrapNative(cx, &args.thisv().toObject(), location,
-                                 NS_GET_IID(nsIFile),
-                                 getter_AddRefs(locationHolder));
-
-            if (NS_SUCCEEDED(rv) &&
-                locationHolder->GetJSObject()) {
-                args.rval().setObject(*locationHolder->GetJSObject());
+                                 NS_GET_IID(nsIFile), locationObj.address());
+            if (NS_SUCCEEDED(rv) && locationObj) {
+                args.rval().setObject(*locationObj);
             }
         }
     }
 
     return true;
 #endif
 }
 
--- a/js/xpconnect/src/nsXPConnect.cpp
+++ b/js/xpconnect/src/nsXPConnect.cpp
@@ -487,36 +487,62 @@ NativeInterface2JSObject(HandleObject aS
         return rv;
 
     MOZ_ASSERT(aAllowWrapping || !xpc::WrapperFactory::IsXrayWrapper(&aVal.toObject()),
                "Shouldn't be returning a xray wrapper here");
 
     return NS_OK;
 }
 
-/* nsIXPConnectJSObjectHolder wrapNative (in JSContextPtr aJSContext, in JSObjectPtr aScope, in nsISupports aCOMObj, in nsIIDRef aIID); */
+/* JSObjectPtr wrapNative (in JSContextPtr aJSContext, in JSObjectPtr aScope, in nsISupports aCOMObj, in nsIIDRef aIID); */
 NS_IMETHODIMP
 nsXPConnect::WrapNative(JSContext * aJSContext,
                         JSObject * aScopeArg,
                         nsISupports* aCOMObj,
                         const nsIID & aIID,
-                        nsIXPConnectJSObjectHolder** aHolder)
+                        JSObject** aRetVal)
+{
+    MOZ_ASSERT(aJSContext, "bad param");
+    MOZ_ASSERT(aScopeArg, "bad param");
+    MOZ_ASSERT(aCOMObj, "bad param");
+
+    RootedObject aScope(aJSContext, aScopeArg);
+    RootedValue v(aJSContext);
+    nsresult rv = NativeInterface2JSObject(aScope, aCOMObj, nullptr, &aIID,
+                                           true, &v, nullptr);
+    if (NS_FAILED(rv))
+        return rv;
+
+    if (!v.isObjectOrNull())
+        return NS_ERROR_FAILURE;
+
+    *aRetVal = v.toObjectOrNull();
+    return NS_OK;
+}
+
+/* nsIXPConnectJSObjectHolder wrapNativeHolder(in JSContextPtr aJSContext, in JSObjectPtr aScope, in nsISupports aCOMObj, in nsIIDRef aIID); */
+NS_IMETHODIMP
+nsXPConnect::WrapNativeHolder(JSContext * aJSContext,
+                              JSObject * aScopeArg,
+                              nsISupports* aCOMObj,
+                              const nsIID & aIID,
+                              nsIXPConnectJSObjectHolder **aHolder)
 {
     MOZ_ASSERT(aHolder, "bad param");
     MOZ_ASSERT(aJSContext, "bad param");
     MOZ_ASSERT(aScopeArg, "bad param");
     MOZ_ASSERT(aCOMObj, "bad param");
 
     RootedObject aScope(aJSContext, aScopeArg);
     RootedValue v(aJSContext);
     return NativeInterface2JSObject(aScope, aCOMObj, nullptr, &aIID,
                                     true, &v, aHolder);
 }
 
-/* void wrapNativeToJSVal (in JSContextPtr aJSContext, in JSObjectPtr aScope, in nsISupports aCOMObj, in nsIIDPtr aIID, out jsval aVal, out nsIXPConnectJSObjectHolder aHolder); */
+/* void wrapNativeToJSVal (in JSContextPtr aJSContext, in JSObjectPtr aScope, in nsISupports aCOMObj, in nsIIDPtr aIID, out jsval aVal); */
 NS_IMETHODIMP
 nsXPConnect::WrapNativeToJSVal(JSContext* aJSContext,
                                JSObject* aScopeArg,
                                nsISupports* aCOMObj,
                                nsWrapperCache* aCache,
                                const nsIID* aIID,
                                bool aAllowWrapping,
                                MutableHandleValue aVal)
--- a/storage/mozStorageAsyncStatementJSHelper.cpp
+++ b/storage/mozStorageAsyncStatementJSHelper.cpp
@@ -43,17 +43,17 @@ AsyncStatementJSHelper::getParams(AsyncS
   if (!aStatement->mStatementParamsHolder) {
     nsCOMPtr<mozIStorageStatementParams> params =
       new AsyncStatementParams(aStatement);
     NS_ENSURE_TRUE(params, NS_ERROR_OUT_OF_MEMORY);
 
     JS::RootedObject scope(aCtx, aScopeObj);
     nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
     nsCOMPtr<nsIXPConnect> xpc(Service::getXPConnect());
-    rv = xpc->WrapNative(
+    rv = xpc->WrapNativeHolder(
       aCtx,
       ::JS_GetGlobalForObject(aCtx, scope),
       params,
       NS_GET_IID(mozIStorageStatementParams),
       getter_AddRefs(holder)
     );
     NS_ENSURE_SUCCESS(rv, rv);
     nsRefPtr<AsyncStatementParamsHolder> paramsHolder =
--- a/storage/mozStorageStatementJSHelper.cpp
+++ b/storage/mozStorageStatementJSHelper.cpp
@@ -96,17 +96,17 @@ StatementJSHelper::getRow(Statement *aSt
 
   if (!aStatement->mStatementRowHolder) {
     JS::RootedObject scope(aCtx, aScopeObj);
     nsCOMPtr<mozIStorageStatementRow> row(new StatementRow(aStatement));
     NS_ENSURE_TRUE(row, NS_ERROR_OUT_OF_MEMORY);
 
     nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
     nsCOMPtr<nsIXPConnect> xpc(Service::getXPConnect());
-    rv = xpc->WrapNative(
+    rv = xpc->WrapNativeHolder(
       aCtx,
       ::JS_GetGlobalForObject(aCtx, scope),
       row,
       NS_GET_IID(mozIStorageStatementRow),
       getter_AddRefs(holder)
     );
     NS_ENSURE_SUCCESS(rv, rv);
     nsRefPtr<StatementRowHolder> rowHolder = new StatementRowHolder(holder);
@@ -141,17 +141,17 @@ StatementJSHelper::getParams(Statement *
   if (!aStatement->mStatementParamsHolder) {
     JS::RootedObject scope(aCtx, aScopeObj);
     nsCOMPtr<mozIStorageStatementParams> params =
       new StatementParams(aStatement);
     NS_ENSURE_TRUE(params, NS_ERROR_OUT_OF_MEMORY);
 
     nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
     nsCOMPtr<nsIXPConnect> xpc(Service::getXPConnect());
-    rv = xpc->WrapNative(
+    rv = xpc->WrapNativeHolder(
       aCtx,
       ::JS_GetGlobalForObject(aCtx, scope),
       params,
       NS_GET_IID(mozIStorageStatementParams),
       getter_AddRefs(holder)
     );
     NS_ENSURE_SUCCESS(rv, rv);
     nsRefPtr<StatementParamsHolder> paramsHolder =
--- a/toolkit/components/places/PlaceInfo.cpp
+++ b/toolkit/components/places/PlaceInfo.cpp
@@ -105,23 +105,21 @@ PlaceInfo::GetVisits(JSContext* aContext
   NS_ENSURE_TRUE(visits, NS_ERROR_OUT_OF_MEMORY);
 
   JS::Rooted<JSObject*> global(aContext, JS::CurrentGlobalOrNull(aContext));
   NS_ENSURE_TRUE(global, NS_ERROR_UNEXPECTED);
 
   nsCOMPtr<nsIXPConnect> xpc = mozilla::services::GetXPConnect();
 
   for (VisitsArray::size_type idx = 0; idx < mVisits.Length(); idx++) {
-    nsCOMPtr<nsIXPConnectJSObjectHolder> wrapper;
+    JS::RootedObject jsobj(aContext);
     nsresult rv = xpc->WrapNative(aContext, global, mVisits[idx],
                                   NS_GET_IID(mozIVisitInfo),
-                                  getter_AddRefs(wrapper));
+                                  jsobj.address());
     NS_ENSURE_SUCCESS(rv, rv);
-
-    JS::Rooted<JSObject*> jsobj(aContext, wrapper->GetJSObject());
     NS_ENSURE_STATE(jsobj);
 
     bool rc = JS_DefineElement(aContext, visits, idx, jsobj, JSPROP_ENUMERATE);
     NS_ENSURE_TRUE(rc, NS_ERROR_UNEXPECTED);
   }
 
   _visits.setObject(*visits);
   return NS_OK;
--- a/widget/cocoa/nsMenuX.mm
+++ b/widget/cocoa/nsMenuX.mm
@@ -413,21 +413,22 @@ void nsMenuX::MenuConstruct()
     nsresult rv;
     nsCOMPtr<nsIXPConnect> xpconnect =
       do_GetService(nsIXPConnect::GetCID(), &rv);
     if (NS_SUCCEEDED(rv)) {
       nsIDocument* ownerDoc = menuPopup->OwnerDoc();
       dom::AutoJSAPI jsapi;
       if (ownerDoc && jsapi.Init(ownerDoc->GetInnerWindow())) {
         JSContext* cx = jsapi.cx();
+        JS::RootedObject ignoredObj(cx);
         nsCOMPtr<nsIXPConnectJSObjectHolder> wrapper;
         xpconnect->WrapNative(cx, JS::CurrentGlobalOrNull(cx), menuPopup,
-                              NS_GET_IID(nsISupports), getter_AddRefs(wrapper));
+                              NS_GET_IID(nsISupports), ignoredObj.address());
         mXBLAttached = true;
-      } 
+      }
     }
   }
 
   // Iterate over the kids
   uint32_t count = menuPopup->GetChildCount();
   for (uint32_t i = 0; i < count; i++) {
     nsIContent *child = menuPopup->GetChildAt(i);
     if (child) {
--- a/xpfe/components/directory/nsDirectoryViewer.cpp
+++ b/xpfe/components/directory/nsDirectoryViewer.cpp
@@ -234,27 +234,26 @@ nsHTTPIndex::OnStartRequest(nsIRequest *
 
     JS::Rooted<JSObject*> global(cx, JS::CurrentGlobalOrNull(cx));
 
     // Using XPConnect, wrap the HTTP index object...
     static NS_DEFINE_CID(kXPConnectCID, NS_XPCONNECT_CID);
     nsCOMPtr<nsIXPConnect> xpc(do_GetService(kXPConnectCID, &rv));
     if (NS_FAILED(rv)) return rv;
 
-    nsCOMPtr<nsIXPConnectJSObjectHolder> wrapper;
+    JS::Rooted<JSObject*> jsobj(cx);
     rv = xpc->WrapNative(cx,
                          global,
                          static_cast<nsIHTTPIndex*>(this),
                          NS_GET_IID(nsIHTTPIndex),
-                         getter_AddRefs(wrapper));
+                         jsobj.address());
 
     NS_ASSERTION(NS_SUCCEEDED(rv), "unable to xpconnect-wrap http-index");
     if (NS_FAILED(rv)) return rv;
 
-    JS::Rooted<JSObject*> jsobj(cx, wrapper->GetJSObject());
     NS_ASSERTION(jsobj,
                  "unable to get jsobj from xpconnect wrapper");
     if (!jsobj) return NS_ERROR_UNEXPECTED;
 
     JS::Rooted<JS::Value> jslistener(cx, JS::ObjectValue(*jsobj));
 
     // ...and stuff it into the global context
     bool ok = JS_SetProperty(cx, global, "HTTPIndex", jslistener);