Bug 999297 - Simplify xpc::HasInstance. r=bz
authorBobby Holley <bobbyholley@gmail.com>
Thu, 01 May 2014 11:03:11 -0700
changeset 181228 d92c11752f44d1e9704f837a678ee218f9254620
parent 181227 660ddfb69dc52596869d62368b2194acac1d440a
child 181229 aaff0e8f5af2b100c377ac0f96711a9591acfe88
push id42987
push userbobbyholley@gmail.com
push dateThu, 01 May 2014 18:03:27 +0000
treeherdermozilla-inbound@d92c11752f44 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbz
bugs999297
milestone32.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 999297 - Simplify xpc::HasInstance. r=bz
js/xpconnect/src/XPCJSID.cpp
js/xpconnect/src/XPCWrappedNative.cpp
js/xpconnect/src/xpcprivate.h
--- a/js/xpconnect/src/XPCJSID.cpp
+++ b/js/xpconnect/src/XPCJSID.cpp
@@ -488,55 +488,34 @@ nsresult
 xpc::HasInstance(JSContext *cx, HandleObject objArg, const nsID *iid, bool *bp)
 {
     *bp = false;
 
     RootedObject obj(cx, FindObjectForHasInstance(cx, objArg));
     if (!obj)
         return NS_OK;
 
-    if (IsDOMObject(obj)) {
-        // Not all DOM objects implement nsISupports. But if they don't,
-        // there's nothing to do in this HasInstance hook.
-        nsISupports *identity = UnwrapDOMObjectToISupports(obj);
-        if (!identity)
-            return NS_OK;;
-        nsCOMPtr<nsISupports> supp;
-        identity->QueryInterface(*iid, getter_AddRefs(supp));
-        *bp = supp;
-        return NS_OK;
-    }
-
     if (mozilla::jsipc::JavaScriptParent::IsCPOW(obj))
         return mozilla::jsipc::JavaScriptParent::InstanceOf(obj, iid, bp);
 
-    MOZ_ASSERT(IS_WN_REFLECTOR(obj));
-    XPCWrappedNative* other_wrapper = XPCWrappedNative::Get(obj);
-    if (!other_wrapper)
+    nsISupports *identity = UnwrapReflectorToISupports(obj);
+    if (!identity)
         return NS_OK;
 
-    // We'll trust the interface set of the wrapper if this is known
-    // to be an interface that the objects *expects* to be able to
-    // handle.
-    if (other_wrapper->HasInterfaceNoQI(*iid)) {
-        *bp = true;
-        return NS_OK;
-    }
+    nsCOMPtr<nsISupports> supp;
+    identity->QueryInterface(*iid, getter_AddRefs(supp));
+    *bp = supp;
 
-    // Otherwise, we'll end up Querying the native object to be sure.
-    XPCCallContext ccx(JS_CALLER, cx);
-
-    AutoMarkingNativeInterfacePtr iface(ccx);
-    iface = XPCNativeInterface::GetNewOrUsed(iid);
-
-    nsresult findResult = NS_OK;
-    if (iface && other_wrapper->FindTearOff(iface, false, &findResult))
-        *bp = true;
-    if (NS_FAILED(findResult) && findResult != NS_ERROR_NO_INTERFACE)
-        return findResult;
+    // Our old HasInstance implementation operated by invoking FindTearOff on
+    // XPCWrappedNatives, and various bits of chrome JS came to depend on
+    // |instanceof| doing an implicit QI if it succeeds. Do a drive-by QI to
+    // preserve that behavior. This is just a compatibility hack, so we don't
+    // really care if it fails.
+    if (IS_WN_REFLECTOR(obj))
+        (void) XPCWrappedNative::Get(obj)->FindTearOff(*iid);
 
     return NS_OK;
 }
 
 /* bool hasInstance (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in jsval val, out bool bp); */
 NS_IMETHODIMP
 nsJSIID::HasInstance(nsIXPConnectWrappedNative *wrapper,
                      JSContext *cx, JSObject * /* unused */,
--- a/js/xpconnect/src/XPCWrappedNative.cpp
+++ b/js/xpconnect/src/XPCWrappedNative.cpp
@@ -1426,16 +1426,24 @@ XPCWrappedNative::FindTearOff(XPCNativeI
             to = nullptr;
     }
 
     if (pError)
         *pError = rv;
     return to;
 }
 
+XPCWrappedNativeTearOff*
+XPCWrappedNative::FindTearOff(const nsIID& iid) {
+    AutoJSContext cx;
+    AutoMarkingNativeInterfacePtr iface(cx);
+    iface = XPCNativeInterface::GetNewOrUsed(&iid);
+    return iface ? FindTearOff(iface) : nullptr;
+}
+
 nsresult
 XPCWrappedNative::InitTearOff(XPCWrappedNativeTearOff* aTearOff,
                               XPCNativeInterface* aInterface,
                               bool needJSObject)
 {
     AutoJSContext cx;
 
     // Determine if the object really does this interface...
--- a/js/xpconnect/src/xpcprivate.h
+++ b/js/xpconnect/src/xpcprivate.h
@@ -2088,16 +2088,18 @@ public:
         {return CallMethod(ccx, CALL_SETTER);}
 
     inline bool HasInterfaceNoQI(const nsIID& iid);
 
     XPCWrappedNativeTearOff* LocateTearOff(XPCNativeInterface* aInterface);
     XPCWrappedNativeTearOff* FindTearOff(XPCNativeInterface* aInterface,
                                          bool needJSObject = false,
                                          nsresult* pError = nullptr);
+    XPCWrappedNativeTearOff* FindTearOff(const nsIID& iid);
+
     void Mark() const
     {
         mSet->Mark();
         if (mScriptableInfo) mScriptableInfo->Mark();
         if (HasProto()) GetProto()->Mark();
     }
 
     // Yes, we *do* need to mark the mScriptableInfo in both cases.