Bug 863767 - GC: Rooting for XPCCallContext r=bholley
authorJon Coppeard <jcoppeard@mozilla.com>
Sat, 20 Apr 2013 09:52:56 +0100
changeset 140532 cbf65101089e22dbffaaabd654b1e4ed7ed8837e
parent 140531 aa442c0ebfb229e8cce48d2726faba742f79b489
child 140533 5b9533763879f4ed20932573e1ba24beb18d39a0
push id2579
push userakeybl@mozilla.com
push dateMon, 24 Jun 2013 18:52:47 +0000
treeherdermozilla-beta@b69b7de8a05a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbholley
bugs863767
milestone23.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 863767 - GC: Rooting for XPCCallContext r=bholley
js/xpconnect/src/XPCCallContext.cpp
js/xpconnect/src/XPCJSID.cpp
js/xpconnect/src/XPCWrappedJSClass.cpp
js/xpconnect/src/XPCWrappedNativeJSOps.cpp
js/xpconnect/src/xpcprivate.h
js/xpconnect/wrappers/XrayWrapper.cpp
--- a/js/xpconnect/src/XPCCallContext.cpp
+++ b/js/xpconnect/src/XPCCallContext.cpp
@@ -8,111 +8,110 @@
 
 #include "mozilla/Util.h"
 #include "AccessCheck.h"
 
 #include "xpcprivate.h"
 
 using namespace mozilla;
 using namespace xpc;
+using namespace JS;
 
 XPCCallContext::XPCCallContext(XPCContext::LangType callerLanguage,
-                               JSContext* cx    /* = nullptr    */,
-                               JSObject* obj    /* = nullptr    */,
-                               JSObject* funobj /* = nullptr    */,
-                               jsid name        /* = JSID_VOID */,
-                               unsigned argc    /* = NO_ARGS   */,
-                               jsval *argv      /* = nullptr    */,
-                               jsval *rval      /* = nullptr    */)
+                               JSContext* cx       /* = GetDefaultJSContext() */,
+                               HandleObject obj    /* = nullptr               */,
+                               HandleObject funobj /* = nullptr               */,
+                               HandleId name       /* = JSID_VOID             */,
+                               unsigned argc       /* = NO_ARGS               */,
+                               jsval *argv         /* = nullptr               */,
+                               jsval *rval         /* = nullptr               */)
     :   mState(INIT_FAILED),
         mXPC(nsXPConnect::GetXPConnect()),
         mXPCContext(nullptr),
         mJSContext(cx),
         mContextPopRequired(false),
         mDestroyJSContextInDestructor(false),
         mCallerLanguage(callerLanguage),
-        mScopeForNewJSObjects(xpc_GetSafeJSContext()),
-        mFlattenedJSObject(xpc_GetSafeJSContext()),
+        mScopeForNewJSObjects(cx),
+        mFlattenedJSObject(cx),
         mWrapper(nullptr),
         mTearOff(nullptr),
-        mName(xpc_GetSafeJSContext())
+        mName(cx)
 {
+    MOZ_ASSERT(cx);
     Init(callerLanguage, callerLanguage == NATIVE_CALLER, obj, funobj,
          INIT_SHOULD_LOOKUP_WRAPPER, name, argc, argv, rval);
 }
 
 XPCCallContext::XPCCallContext(XPCContext::LangType callerLanguage,
                                JSContext* cx,
                                JSBool callBeginRequest,
-                               JSObject* obj,
-                               JSObject* flattenedJSObject,
+                               HandleObject obj,
+                               HandleObject flattenedJSObject,
                                XPCWrappedNative* wrapper,
                                XPCWrappedNativeTearOff* tearOff)
     :   mState(INIT_FAILED),
         mXPC(nsXPConnect::GetXPConnect()),
         mXPCContext(nullptr),
         mJSContext(cx),
         mContextPopRequired(false),
         mDestroyJSContextInDestructor(false),
         mCallerLanguage(callerLanguage),
-        mScopeForNewJSObjects(xpc_GetSafeJSContext()),
-        mFlattenedJSObject(xpc_GetSafeJSContext(), flattenedJSObject),
+        mScopeForNewJSObjects(cx),
+        mFlattenedJSObject(cx, flattenedJSObject),
         mWrapper(wrapper),
         mTearOff(tearOff),
-        mName(xpc_GetSafeJSContext())
+        mName(cx)
 {
-    Init(callerLanguage, callBeginRequest, obj, nullptr,
-         WRAPPER_PASSED_TO_CONSTRUCTOR, JSID_VOID, NO_ARGS,
+    MOZ_ASSERT(cx);
+    Init(callerLanguage, callBeginRequest, obj, NullPtr(),
+         WRAPPER_PASSED_TO_CONSTRUCTOR, JSID_VOIDHANDLE, NO_ARGS,
          nullptr, nullptr);
 }
 
 #define IS_TEAROFF_CLASS(clazz) ((clazz) == &XPC_WN_Tearoff_JSClass)
 
+
+// static
+JSContext *
+XPCCallContext::GetDefaultJSContext()
+{
+    // This is slightly questionable. If called without an explicit
+    // JSContext (generally a call to a wrappedJS) we will use the JSContext
+    // on the top of the JSContext stack - if there is one - *before*
+    // falling back on the safe JSContext.
+    // This is good AND bad because it makes calls from JS -> native -> JS
+    // have JS stack 'continuity' for purposes of stack traces etc.
+    // Note: this *is* what the pre-XPCCallContext xpconnect did too.
+
+    XPCJSContextStack* stack = XPCJSRuntime::Get()->GetJSContextStack();
+    JSContext *topJSContext = stack->Peek();
+
+    return topJSContext ? topJSContext : stack->GetSafeJSContext();
+}
+
 void
 XPCCallContext::Init(XPCContext::LangType callerLanguage,
                      JSBool callBeginRequest,
-                     JSObject* obj,
-                     JSObject* funobj,
+                     HandleObject obj,
+                     HandleObject funobj,
                      WrapperInitOptions wrapperInitOptions,
-                     jsid name,
+                     HandleId name,
                      unsigned argc,
                      jsval *argv,
                      jsval *rval)
 {
+    NS_ASSERTION(mJSContext, "No JSContext supplied to XPCCallContext");
+
     if (!mXPC)
         return;
 
     XPCJSContextStack* stack = XPCJSRuntime::Get()->GetJSContextStack();
-
-    if (!stack) {
-        // If we don't have a stack we're probably in shutdown.
-        mJSContext = nullptr;
-        return;
-    }
-
     JSContext *topJSContext = stack->Peek();
 
-    if (!mJSContext) {
-        // This is slightly questionable. If called without an explicit
-        // JSContext (generally a call to a wrappedJS) we will use the JSContext
-        // on the top of the JSContext stack - if there is one - *before*
-        // falling back on the safe JSContext.
-        // This is good AND bad because it makes calls from JS -> native -> JS
-        // have JS stack 'continuity' for purposes of stack traces etc.
-        // Note: this *is* what the pre-XPCCallContext xpconnect did too.
-
-        if (topJSContext) {
-            mJSContext = topJSContext;
-        } else {
-            mJSContext = stack->GetSafeJSContext();
-            if (!mJSContext)
-                return;
-        }
-    }
-
     if (topJSContext != mJSContext) {
         if (!stack->Push(mJSContext)) {
             NS_ERROR("bad!");
             return;
         }
         mContextPopRequired = true;
     }
 
@@ -199,25 +198,25 @@ XPCCallContext::SetName(jsid name)
 {
     CHECK_STATE(HAVE_OBJECT);
 
     mName = name;
 
     if (mTearOff) {
         mSet = nullptr;
         mInterface = mTearOff->GetInterface();
-        mMember = mInterface->FindMember(name);
+        mMember = mInterface->FindMember(mName);
         mStaticMemberIsLocal = true;
         if (mMember && !mMember->IsConstant())
             mMethodIndex = mMember->GetIndex();
     } else {
         mSet = mWrapper ? mWrapper->GetSet() : nullptr;
 
         if (mSet &&
-            mSet->FindMember(name, &mMember, &mInterface,
+            mSet->FindMember(mName, &mMember, &mInterface,
                              mWrapper->HasProto() ?
                              mWrapper->GetProto()->GetSet() :
                              nullptr,
                              &mStaticMemberIsLocal)) {
             if (mMember && !mMember->IsConstant())
                 mMethodIndex = mMember->GetIndex();
         } else {
             mMember = nullptr;
@@ -454,19 +453,18 @@ XPCLazyCallContext::AssertContextIsTopOf
     XPCJSContextStack* stack = XPCJSRuntime::Get()->GetJSContextStack();
 
     JSContext *topJSContext = stack->Peek();
     NS_ASSERTION(cx == topJSContext, "wrong context on XPCJSContextStack!");
 }
 #endif
 
 XPCWrappedNative*
-XPCCallContext::UnwrapThisIfAllowed(JSObject *object, JSObject *fun, unsigned argc)
+XPCCallContext::UnwrapThisIfAllowed(HandleObject obj, HandleObject fun, unsigned argc)
 {
-    JS::Rooted<JSObject *> obj(mJSContext, object);
     // We should only get here for objects that aren't safe to unwrap.
     MOZ_ASSERT(!js::CheckedUnwrap(obj));
     MOZ_ASSERT(js::IsObjectInContextCompartment(obj, mJSContext));
 
     // We can't do anything here without a function.
     if (!fun)
         return nullptr;
 
@@ -477,17 +475,17 @@ XPCCallContext::UnwrapThisIfAllowed(JSOb
     // unfortunately our access checks are based on the object class name and
     // property name. So we cheat a little bit here - we verify that the object
     // does indeed implement the method's Interface, and then just check that we
     // can successfully access property with method's name from the object.
 
     // First, get the XPCWN out of the underlying object. We should have a wrapper
     // here, potentially an outer window proxy, and then an XPCWN.
     MOZ_ASSERT(js::IsWrapper(obj));
-    JSObject *unwrapped = js::UncheckedUnwrap(obj, /* stopAtOuter = */ false);
+    RootedObject unwrapped(mJSContext, js::UncheckedUnwrap(obj, /* stopAtOuter = */ false));
     MOZ_ASSERT(unwrapped == JS_ObjectToInnerObject(mJSContext, js::Wrapper::wrappedObject(obj)));
 
     // Make sure we have an XPCWN, and grab it.
     MOZ_ASSERT(!IS_SLIM_WRAPPER(unwrapped), "security wrapping morphs slim wrappers");
     if (!IS_WRAPPER_CLASS(js::GetObjectClass(unwrapped)))
         return nullptr;
     XPCWrappedNative *wn = (XPCWrappedNative*)js::GetObjectPrivate(unwrapped);
 
--- a/js/xpconnect/src/XPCJSID.cpp
+++ b/js/xpconnect/src/XPCJSID.cpp
@@ -832,19 +832,18 @@ nsJSCID::Construct(nsIXPConnectWrappedNa
                    bool *_retval)
 {
     RootedObject obj(cx, objArg);
     XPCJSRuntime* rt = nsXPConnect::GetRuntimeInstance();
     if (!rt)
         return NS_ERROR_FAILURE;
 
     // 'push' a call context and call on it
-    XPCCallContext ccx(JS_CALLER, cx, obj, nullptr,
-                       rt->GetStringID(XPCJSRuntime::IDX_CREATE_INSTANCE),
-                       argc, argv, vp);
+    RootedId name(cx, rt->GetStringID(XPCJSRuntime::IDX_CREATE_INSTANCE));
+    XPCCallContext ccx(JS_CALLER, cx, obj, NullPtr(), name, argc, argv, vp);
 
     *_retval = XPCWrappedNative::CallMethod(ccx);
     return NS_OK;
 }
 
 /* bool hasInstance (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in jsval val, out bool bp); */
 NS_IMETHODIMP
 nsJSCID::HasInstance(nsIXPConnectWrappedNative *wrapper,
--- a/js/xpconnect/src/XPCWrappedJSClass.cpp
+++ b/js/xpconnect/src/XPCWrappedJSClass.cpp
@@ -620,16 +620,18 @@ nsXPCWrappedJSClass::DelegatedQueryInter
 
     // We can't have a cached wrapper.
     if (aIID.Equals(NS_GET_IID(nsWrapperCache))) {
         *aInstancePtr = nullptr;
         return NS_NOINTERFACE;
     }
 
     JSContext *context = GetContextFromObject(self->GetJSObject());
+    if (!context)
+        context = XPCCallContext::GetDefaultJSContext();
     XPCCallContext ccx(NATIVE_CALLER, context);
     if (!ccx.IsValid()) {
         *aInstancePtr = nullptr;
         return NS_NOINTERFACE;
     }
 
     // We support nsISupportsWeakReference iff the root wrapped JSObject
     // claims to support it in its QueryInterface implementation.
@@ -1137,16 +1139,18 @@ nsXPCWrappedJSClass::CallMethod(nsXPCWra
     const char* name = info->name;
     JSBool foundDependentParam;
 
     // Make sure not to set the callee on ccx until after we've gone through
     // the whole nsIXPCFunctionThisTranslator bit.  That code uses ccx to
     // convert natives to JSObjects, but we do NOT plan to pass those JSObjects
     // to our real callee.
     JSContext *context = GetContextFromObject(wrapper->GetJSObject());
+    if (!context)
+        context = XPCCallContext::GetDefaultJSContext();
     XPCCallContext ccx(NATIVE_CALLER, context);
     if (!ccx.IsValid())
         return retval;
 
     XPCContext *xpcc = ccx.GetXPCContext();
     JSContext *cx = xpc_UnmarkGrayContext(ccx.GetJSContext());
 
     if (!cx || !xpcc || !IsReflectable(methodIndex))
--- a/js/xpconnect/src/XPCWrappedNativeJSOps.cpp
+++ b/js/xpconnect/src/XPCWrappedNativeJSOps.cpp
@@ -72,33 +72,33 @@ ToStringGuts(XPCCallContext& ccx)
     return true;
 }
 
 /***************************************************************************/
 
 static JSBool
 XPC_WN_Shared_ToString(JSContext *cx, unsigned argc, jsval *vp)
 {
-    JSObject *obj = JS_THIS_OBJECT(cx, vp);
+    RootedObject obj(cx, JS_THIS_OBJECT(cx, vp));
     if (!obj)
         return false;
 
     if (IS_SLIM_WRAPPER(obj)) {
         XPCNativeScriptableInfo *si =
             GetSlimWrapperProto(obj)->GetScriptableInfo();
 #ifdef DEBUG
 #  define FMT_ADDR " @ 0x%p"
 #  define FMT_STR(str) str
 #  define PARAM_ADDR(w) , w
 #else
 #  define FMT_ADDR ""
 #  define FMT_STR(str)
 #  define PARAM_ADDR(w)
 #endif
-        char *sz = JS_smprintf("[object %s" FMT_ADDR FMT_STR(" (native") FMT_ADDR FMT_STR(")") "]", si->GetJSClass()->name PARAM_ADDR(obj) PARAM_ADDR(xpc_GetJSPrivate(obj)));
+        char *sz = JS_smprintf("[object %s" FMT_ADDR FMT_STR(" (native") FMT_ADDR FMT_STR(")") "]", si->GetJSClass()->name PARAM_ADDR(obj.get()) PARAM_ADDR(xpc_GetJSPrivate(obj)));
         if (!sz)
             return false;
 
         JSString* str = JS_NewStringCopyZ(cx, sz);
         JS_smprintf_free(sz);
         if (!str)
             return false;
 
@@ -468,17 +468,17 @@ DefinePropertyIfFound(XPCCallContext& cc
 }
 
 /***************************************************************************/
 /***************************************************************************/
 
 static JSBool
 XPC_WN_OnlyIWrite_AddPropertyStub(JSContext *cx, JSHandleObject obj, JSHandleId id, JSMutableHandleValue vp)
 {
-    XPCCallContext ccx(JS_CALLER, cx, obj, nullptr, id);
+    XPCCallContext ccx(JS_CALLER, cx, obj, NullPtr(), id);
     XPCWrappedNative* wrapper = ccx.GetWrapper();
     THROW_AND_RETURN_IF_BAD_WRAPPER(cx, wrapper);
 
     // Allow only XPConnect to add/set the property
     if (ccx.GetResolveName() == id)
         return true;
 
     return Throw(NS_ERROR_XPC_CANT_MODIFY_PROP_ON_WN, cx);
@@ -696,17 +696,17 @@ XPC_WN_NoHelper_Trace(JSTracer *trc, JSO
 {
     MarkWrappedNative(trc, obj);
 }
 
 static JSBool
 XPC_WN_NoHelper_Resolve(JSContext *cx, JSHandleObject obj, JSHandleId id)
 {
     MORPH_SLIM_WRAPPER(cx, obj);
-    XPCCallContext ccx(JS_CALLER, cx, obj, nullptr, id);
+    XPCCallContext ccx(JS_CALLER, cx, obj, NullPtr(), id);
     XPCWrappedNative* wrapper = ccx.GetWrapper();
     THROW_AND_RETURN_IF_BAD_WRAPPER(cx, wrapper);
 
     XPCNativeSet* set = ccx.GetSet();
     if (!set)
         return true;
 
     // Don't resolve properties that are on our prototype.
@@ -957,17 +957,17 @@ XPC_WN_Helper_CheckAccess(JSContext *cx,
 }
 
 static JSBool
 XPC_WN_Helper_Call(JSContext *cx, unsigned argc, jsval *vp)
 {
     // N.B. we want obj to be the callee, not JS_THIS(cx, vp)
     RootedObject obj(cx, JSVAL_TO_OBJECT(JS_CALLEE(cx, vp)));
 
-    XPCCallContext ccx(JS_CALLER, cx, obj, nullptr, JSID_VOID,
+    XPCCallContext ccx(JS_CALLER, cx, obj, NullPtr(), JSID_VOIDHANDLE,
                        argc, JS_ARGV(cx, vp), vp);
     if (!ccx.IsValid())
         return false;
 
     MOZ_ASSERT(obj == ccx.GetFlattenedJSObject());
 
     SLIM_LOG_WILL_MORPH(cx, obj);
     PRE_HELPER_STUB_NO_SLIM
@@ -977,17 +977,17 @@ XPC_WN_Helper_Call(JSContext *cx, unsign
 
 static JSBool
 XPC_WN_Helper_Construct(JSContext *cx, unsigned argc, jsval *vp)
 {
     RootedObject obj(cx, JSVAL_TO_OBJECT(JS_CALLEE(cx, vp)));
     if (!obj)
         return false;
 
-    XPCCallContext ccx(JS_CALLER, cx, obj, nullptr, JSID_VOID,
+    XPCCallContext ccx(JS_CALLER, cx, obj, NullPtr(), JSID_VOIDHANDLE,
                        argc, JS_ARGV(cx, vp), vp);
     if (!ccx.IsValid())
         return false;
 
     MOZ_ASSERT(obj == ccx.GetFlattenedJSObject());
 
     SLIM_LOG_WILL_MORPH(cx, obj);
     PRE_HELPER_STUB_NO_SLIM
@@ -1467,17 +1467,18 @@ XPC_WN_CallMethod(JSContext *cx, unsigne
         const char *funname = !funid ? "" : bytes.encodeLatin1(cx, funid) ? bytes.ptr() : "<error>";
         SLIM_LOG_WILL_MORPH_FOR_PROP(cx, obj, funname);
     }
 #endif
     if (IS_SLIM_WRAPPER(obj) && !MorphSlimWrapper(cx, obj))
         return Throw(NS_ERROR_XPC_BAD_OP_ON_WN_PROTO, cx);
 
     obj = FixUpThisIfBroken(obj, funobj);
-    XPCCallContext ccx(JS_CALLER, cx, obj, funobj, JSID_VOID, argc, JS_ARGV(cx, vp), vp);
+    XPCCallContext ccx(JS_CALLER, cx, obj, funobj, JSID_VOIDHANDLE, argc,
+                       JS_ARGV(cx, vp), vp);
     XPCWrappedNative* wrapper = ccx.GetWrapper();
     THROW_AND_RETURN_IF_BAD_WRAPPER(cx, wrapper);
 
     XPCNativeInterface* iface;
     XPCNativeMember*    member;
 
     if (!XPCNativeMember::GetCallInfo(funobj, &iface, &member))
         return Throw(NS_ERROR_XPC_CANT_GET_METHOD_INFO, cx);
@@ -1506,17 +1507,18 @@ XPC_WN_GetterSetter(JSContext *cx, unsig
         SLIM_LOG_WILL_MORPH_FOR_PROP(cx, obj, funname);
     }
 #endif
     if (IS_SLIM_WRAPPER(obj) && !MorphSlimWrapper(cx, obj))
         return Throw(NS_ERROR_XPC_BAD_OP_ON_WN_PROTO, cx);
 
 
     obj = FixUpThisIfBroken(obj, funobj);
-    XPCCallContext ccx(JS_CALLER, cx, obj, funobj, JSID_VOID, argc, JS_ARGV(cx, vp), vp);
+    XPCCallContext ccx(JS_CALLER, cx, obj, funobj, JSID_VOIDHANDLE, argc,
+                       JS_ARGV(cx, vp), vp);
     XPCWrappedNative* wrapper = ccx.GetWrapper();
     THROW_AND_RETURN_IF_BAD_WRAPPER(cx, wrapper);
 
     XPCNativeInterface* iface;
     XPCNativeMember*    member;
 
     if (!XPCNativeMember::GetCallInfo(funobj, &iface, &member))
         return Throw(NS_ERROR_XPC_CANT_GET_METHOD_INFO, cx);
--- a/js/xpconnect/src/xpcprivate.h
+++ b/js/xpconnect/src/xpcprivate.h
@@ -1134,24 +1134,26 @@ public:
     NS_IMETHOD GetArgvPtr(jsval **aResult);
     NS_IMETHOD GetCalleeInterface(nsIInterfaceInfo **aResult);
     NS_IMETHOD GetCalleeClassInfo(nsIClassInfo **aResult);
     NS_IMETHOD GetPreviousCallContext(nsAXPCNativeCallContext **aResult);
     NS_IMETHOD GetLanguage(uint16_t *aResult);
 
     enum {NO_ARGS = (unsigned) -1};
 
+    static JSContext* GetDefaultJSContext();
+
     XPCCallContext(XPCContext::LangType callerLanguage,
-                   JSContext* cx    = nullptr,
-                   JSObject* obj    = nullptr,
-                   JSObject* funobj = nullptr,
-                   jsid id          = JSID_VOID,
-                   unsigned argc    = NO_ARGS,
-                   jsval *argv      = nullptr,
-                   jsval *rval      = nullptr);
+                   JSContext* cx           = GetDefaultJSContext(),
+                   JS::HandleObject obj    = JS::NullPtr(),
+                   JS::HandleObject funobj = JS::NullPtr(),
+                   JS::HandleId id         = JS::JSID_VOIDHANDLE,
+                   unsigned argc           = NO_ARGS,
+                   jsval *argv             = nullptr,
+                   jsval *rval             = nullptr);
 
     virtual ~XPCCallContext();
 
     inline JSBool                       IsValid() const ;
 
     inline nsXPConnect*                 GetXPConnect() const ;
     inline XPCJSRuntime*                GetRuntime() const ;
     inline XPCContext*                  GetXPCContext() const ;
@@ -1223,37 +1225,37 @@ private:
     // no copy ctor or assignment allowed
     XPCCallContext(const XPCCallContext& r); // not implemented
     XPCCallContext& operator= (const XPCCallContext& r); // not implemented
 
     friend class XPCLazyCallContext;
     XPCCallContext(XPCContext::LangType callerLanguage,
                    JSContext* cx,
                    JSBool callBeginRequest,
-                   JSObject* obj,
-                   JSObject* flattenedJSObject,
+                   JS::HandleObject obj,
+                   JS::HandleObject flattenedJSObject,
                    XPCWrappedNative* wn,
                    XPCWrappedNativeTearOff* tearoff);
 
     enum WrapperInitOptions {
         WRAPPER_PASSED_TO_CONSTRUCTOR,
         INIT_SHOULD_LOOKUP_WRAPPER
     };
 
     void Init(XPCContext::LangType callerLanguage,
               JSBool callBeginRequest,
-              JSObject* obj,
-              JSObject* funobj,
+              JS::HandleObject obj,
+              JS::HandleObject funobj,
               WrapperInitOptions wrapperInitOptions,
-              jsid name,
+              JS::HandleId name,
               unsigned argc,
               jsval *argv,
               jsval *rval);
 
-    XPCWrappedNative* UnwrapThisIfAllowed(JSObject *obj, JSObject *fun,
+    XPCWrappedNative* UnwrapThisIfAllowed(JS::HandleObject obj, JS::HandleObject fun,
                                           unsigned argc);
 
 private:
     // posible values for mState
     enum State {
         INIT_FAILED,
         SYSTEM_SHUTDOWN,
         HAVE_CONTEXT,
@@ -1394,22 +1396,24 @@ public:
             return mCcx->GetFlattenedJSObject();
 
         return xpc_UnmarkGrayObject(mFlattenedJSObject);
     }
     XPCCallContext &GetXPCCallContext()
     {
         if (!mCcx) {
             XPCCallContext *data = mData.addr();
+            xpc_UnmarkGrayObject(mObj);
+            xpc_UnmarkGrayObject(mFlattenedJSObject);
             mCcxToDestroy = mCcx =
                 new (data) XPCCallContext(mCallerLanguage, mCx,
                                           mCallBeginRequest == CALL_BEGINREQUEST,
-                                           xpc_UnmarkGrayObject(mObj),
-                                           xpc_UnmarkGrayObject(mFlattenedJSObject),
-                                           mWrapper,
+                                          mObj,
+                                          mFlattenedJSObject,
+                                          mWrapper,
                                           mTearOff);
             if (!mCcx->IsValid()) {
                 NS_ERROR("This is not supposed to fail!");
             }
         }
 
         return *mCcx;
     }
--- a/js/xpconnect/wrappers/XrayWrapper.cpp
+++ b/js/xpconnect/wrappers/XrayWrapper.cpp
@@ -751,17 +751,18 @@ XPCWrappedNativeXrayTraits::resolveNativ
         desc->setter = NULL;
         desc->shortid = 0;
         return true;
     }
 
     desc->obj = NULL;
 
     // This will do verification and the method lookup for us.
-    XPCCallContext ccx(JS_CALLER, cx, getTargetObject(wrapper), nullptr, id);
+    RootedObject target(cx, getTargetObject(wrapper));
+    XPCCallContext ccx(JS_CALLER, cx, target, NullPtr(), id);
 
     // There are no native numeric properties, so we can shortcut here. We will
     // not find the property. However we want to support non shadowing dom
     // specific collection properties like window.frames, so we still have to
     // check for those.
     if (!JSID_IS_STRING(id)) {
         /* Not found */
         return resolveDOMCollectionProperty(cx, wrapper, holder, id, desc, flags);
@@ -1110,18 +1111,18 @@ XPCWrappedNativeXrayTraits::createHolder
 
 bool
 XPCWrappedNativeXrayTraits::call(JSContext *cx, HandleObject wrapper,
                                  const JS::CallArgs &args)
 {
     // Run the resolve hook of the wrapped native.
     XPCWrappedNative *wn = getWN(wrapper);
     if (NATIVE_HAS_FLAG(wn, WantCall)) {
-        XPCCallContext ccx(JS_CALLER, cx, wrapper, nullptr, JSID_VOID, args.length(), args.array(),
-                           args.rval().address());
+        XPCCallContext ccx(JS_CALLER, cx, wrapper, NullPtr(), JSID_VOIDHANDLE, args.length(),
+                           args.array(), args.rval().address());
         if (!ccx.IsValid())
             return false;
         bool ok = true;
         nsresult rv = wn->GetScriptableInfo()->GetCallback()->Call(
             wn, cx, wrapper, args.length(), args.array(), args.rval().address(), &ok);
         if (NS_FAILED(rv)) {
             if (ok)
                 XPCThrower::Throw(rv, cx);
@@ -1135,18 +1136,18 @@ XPCWrappedNativeXrayTraits::call(JSConte
 
 bool
 XPCWrappedNativeXrayTraits::construct(JSContext *cx, HandleObject wrapper,
                                       const JS::CallArgs &args)
 {
     // Run the resolve hook of the wrapped native.
     XPCWrappedNative *wn = getWN(wrapper);
     if (NATIVE_HAS_FLAG(wn, WantConstruct)) {
-        XPCCallContext ccx(JS_CALLER, cx, wrapper, nullptr, JSID_VOID, args.length(), args.array(),
-                           args.rval().address());
+        XPCCallContext ccx(JS_CALLER, cx, wrapper, NullPtr(), JSID_VOIDHANDLE, args.length(),
+                           args.array(), args.rval().address());
         if (!ccx.IsValid())
             return false;
         bool ok = true;
         nsresult rv = wn->GetScriptableInfo()->GetCallback()->Construct(
             wn, cx, wrapper, args.length(), args.array(), args.rval().address(), &ok);
         if (NS_FAILED(rv)) {
             if (ok)
                 XPCThrower::Throw(rv, cx);