mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-17 23:35:34 +00:00
Bug 863767 - GC: Rooting for XPCCallContext r=bholley
This commit is contained in:
parent
6b41db971f
commit
7b2f5e54d8
@ -13,15 +13,16 @@
|
||||
|
||||
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),
|
||||
@ -29,12 +30,13 @@ XPCCallContext::XPCCallContext(XPCContext::LangType callerLanguage,
|
||||
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);
|
||||
}
|
||||
@ -42,8 +44,8 @@ XPCCallContext::XPCCallContext(XPCContext::LangType callerLanguage,
|
||||
XPCCallContext::XPCCallContext(XPCContext::LangType callerLanguage,
|
||||
JSContext* cx,
|
||||
JSBool callBeginRequest,
|
||||
JSObject* obj,
|
||||
JSObject* flattenedJSObject,
|
||||
HandleObject obj,
|
||||
HandleObject flattenedJSObject,
|
||||
XPCWrappedNative* wrapper,
|
||||
XPCWrappedNativeTearOff* tearOff)
|
||||
: mState(INIT_FAILED),
|
||||
@ -53,61 +55,58 @@ XPCCallContext::XPCCallContext(XPCContext::LangType callerLanguage,
|
||||
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!");
|
||||
@ -204,7 +203,7 @@ XPCCallContext::SetName(jsid 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();
|
||||
@ -212,7 +211,7 @@ XPCCallContext::SetName(jsid name)
|
||||
mSet = mWrapper ? mWrapper->GetSet() : nullptr;
|
||||
|
||||
if (mSet &&
|
||||
mSet->FindMember(name, &mMember, &mInterface,
|
||||
mSet->FindMember(mName, &mMember, &mInterface,
|
||||
mWrapper->HasProto() ?
|
||||
mWrapper->GetProto()->GetSet() :
|
||||
nullptr,
|
||||
@ -459,9 +458,8 @@ XPCLazyCallContext::AssertContextIsTopOfStack(JSContext* cx)
|
||||
#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));
|
||||
@ -482,7 +480,7 @@ XPCCallContext::UnwrapThisIfAllowed(JSObject *object, JSObject *fun, unsigned ar
|
||||
// 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.
|
||||
|
@ -837,9 +837,8 @@ nsJSCID::Construct(nsIXPConnectWrappedNative *wrapper,
|
||||
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;
|
||||
|
@ -625,6 +625,8 @@ nsXPCWrappedJSClass::DelegatedQueryInterface(nsXPCWrappedJS* self,
|
||||
}
|
||||
|
||||
JSContext *context = GetContextFromObject(self->GetJSObject());
|
||||
if (!context)
|
||||
context = XPCCallContext::GetDefaultJSContext();
|
||||
XPCCallContext ccx(NATIVE_CALLER, context);
|
||||
if (!ccx.IsValid()) {
|
||||
*aInstancePtr = nullptr;
|
||||
@ -1142,6 +1144,8 @@ nsXPCWrappedJSClass::CallMethod(nsXPCWrappedJS* wrapper, uint16_t methodIndex,
|
||||
// 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;
|
||||
|
@ -77,7 +77,7 @@ ToStringGuts(XPCCallContext& ccx)
|
||||
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;
|
||||
|
||||
@ -93,7 +93,7 @@ XPC_WN_Shared_ToString(JSContext *cx, unsigned argc, jsval *vp)
|
||||
# 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;
|
||||
|
||||
@ -473,7 +473,7 @@ DefinePropertyIfFound(XPCCallContext& ccx,
|
||||
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);
|
||||
|
||||
@ -701,7 +701,7 @@ 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);
|
||||
|
||||
@ -962,7 +962,7 @@ 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;
|
||||
@ -982,7 +982,7 @@ XPC_WN_Helper_Construct(JSContext *cx, unsigned argc, jsval *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;
|
||||
@ -1472,7 +1472,8 @@ XPC_WN_CallMethod(JSContext *cx, unsigned argc, jsval *vp)
|
||||
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);
|
||||
|
||||
@ -1511,7 +1512,8 @@ XPC_WN_GetterSetter(JSContext *cx, unsigned argc, jsval *vp)
|
||||
|
||||
|
||||
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);
|
||||
|
||||
|
@ -1139,14 +1139,16 @@ public:
|
||||
|
||||
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();
|
||||
|
||||
@ -1228,8 +1230,8 @@ private:
|
||||
XPCCallContext(XPCContext::LangType callerLanguage,
|
||||
JSContext* cx,
|
||||
JSBool callBeginRequest,
|
||||
JSObject* obj,
|
||||
JSObject* flattenedJSObject,
|
||||
JS::HandleObject obj,
|
||||
JS::HandleObject flattenedJSObject,
|
||||
XPCWrappedNative* wn,
|
||||
XPCWrappedNativeTearOff* tearoff);
|
||||
|
||||
@ -1240,15 +1242,15 @@ private:
|
||||
|
||||
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:
|
||||
@ -1399,12 +1401,14 @@ public:
|
||||
{
|
||||
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!");
|
||||
|
@ -756,7 +756,8 @@ XPCWrappedNativeXrayTraits::resolveNativeProperty(JSContext *cx, HandleObject wr
|
||||
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
|
||||
@ -1115,8 +1116,8 @@ XPCWrappedNativeXrayTraits::call(JSContext *cx, HandleObject wrapper,
|
||||
// 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;
|
||||
@ -1140,8 +1141,8 @@ XPCWrappedNativeXrayTraits::construct(JSContext *cx, HandleObject wrapper,
|
||||
// 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;
|
||||
|
Loading…
Reference in New Issue
Block a user