Bug 860777 - Part 1 - Root XPCWrappedJSClass.cpp r=bholley

--HG--
extra : rebase_source : bc2545f609d958549e3df3524dd543330362611c
This commit is contained in:
Jon Coppeard 2013-04-12 10:50:43 +01:00
Родитель 650580da78
Коммит f1d4899b54
2 изменённых файлов: 54 добавлений и 46 удалений

Просмотреть файл

@ -18,12 +18,14 @@
#include "jsapi.h" #include "jsapi.h"
using namespace xpc; using namespace xpc;
using namespace JS;
NS_IMPL_THREADSAFE_ISUPPORTS1(nsXPCWrappedJSClass, nsIXPCWrappedJSClass) NS_IMPL_THREADSAFE_ISUPPORTS1(nsXPCWrappedJSClass, nsIXPCWrappedJSClass)
// the value of this variable is never used - we use its address as a sentinel // the value of this variable is never used - we use its address as a sentinel
static uint32_t zero_methods_descriptor; static uint32_t zero_methods_descriptor;
bool AutoScriptEvaluate::StartEvaluating(JSObject *scope, JSErrorReporter errorReporter) bool AutoScriptEvaluate::StartEvaluating(HandleObject scope, JSErrorReporter errorReporter)
{ {
NS_PRECONDITION(!mEvaluated, "AutoScriptEvaluate::Evaluate should only be called once"); NS_PRECONDITION(!mEvaluated, "AutoScriptEvaluate::Evaluate should only be called once");
@ -198,15 +200,16 @@ nsXPCWrappedJSClass::~nsXPCWrappedJSClass()
JSObject* JSObject*
nsXPCWrappedJSClass::CallQueryInterfaceOnJSObject(JSContext* cx, nsXPCWrappedJSClass::CallQueryInterfaceOnJSObject(JSContext* cx,
JSObject* jsobj, JSObject* jsobjArg,
REFNSIID aIID) REFNSIID aIID)
{ {
RootedObject jsobj(cx, jsobjArg);
JSObject* id; JSObject* id;
jsval retval; RootedValue retval(cx);
JSObject* retObj; RootedObject retObj(cx);
JSBool success = false; JSBool success = false;
jsid funid; jsid funid;
jsval fun; RootedValue fun(cx);
// Don't call the actual function on a content object. We'll determine // Don't call the actual function on a content object. We'll determine
// whether or not a content object is capable of implementing the // whether or not a content object is capable of implementing the
@ -226,7 +229,7 @@ nsXPCWrappedJSClass::CallQueryInterfaceOnJSObject(JSContext* cx,
// check upfront for the existence of the function property // check upfront for the existence of the function property
funid = mRuntime->GetStringID(XPCJSRuntime::IDX_QUERY_INTERFACE); funid = mRuntime->GetStringID(XPCJSRuntime::IDX_QUERY_INTERFACE);
if (!JS_GetPropertyById(cx, jsobj, funid, &fun) || JSVAL_IS_PRIMITIVE(fun)) if (!JS_GetPropertyById(cx, jsobj, funid, fun.address()) || JSVAL_IS_PRIMITIVE(fun))
return nullptr; return nullptr;
// protect fun so that we're sure it's alive when we call it // protect fun so that we're sure it's alive when we call it
@ -259,7 +262,7 @@ nsXPCWrappedJSClass::CallQueryInterfaceOnJSObject(JSContext* cx,
JS_SetOptions(cx, JS_GetOptions(cx) | JSOPTION_DONT_REPORT_UNCAUGHT); JS_SetOptions(cx, JS_GetOptions(cx) | JSOPTION_DONT_REPORT_UNCAUGHT);
jsval args[1] = {OBJECT_TO_JSVAL(id)}; jsval args[1] = {OBJECT_TO_JSVAL(id)};
success = JS_CallFunctionValue(cx, jsobj, fun, 1, args, &retval); success = JS_CallFunctionValue(cx, jsobj, fun, 1, args, retval.address());
JS_SetOptions(cx, oldOpts); JS_SetOptions(cx, oldOpts);
@ -267,10 +270,10 @@ nsXPCWrappedJSClass::CallQueryInterfaceOnJSObject(JSContext* cx,
NS_ASSERTION(JS_IsExceptionPending(cx), NS_ASSERTION(JS_IsExceptionPending(cx),
"JS failed without setting an exception!"); "JS failed without setting an exception!");
jsval jsexception = JSVAL_NULL; RootedValue jsexception(cx, NullValue());
AUTO_MARK_JSVAL(cx, &jsexception); AUTO_MARK_JSVAL(cx, jsexception.address());
if (JS_GetPendingException(cx, &jsexception)) { if (JS_GetPendingException(cx, jsexception.address())) {
nsresult rv; nsresult rv;
if (jsexception.isObject()) { if (jsexception.isObject()) {
// XPConnect may have constructed an object to represent a // XPConnect may have constructed an object to represent a
@ -313,9 +316,9 @@ nsXPCWrappedJSClass::CallQueryInterfaceOnJSObject(JSContext* cx,
} }
if (success) if (success)
success = JS_ValueToObject(cx, retval, &retObj); success = JS_ValueToObject(cx, retval, retObj.address());
return success ? retObj : nullptr; return success ? retObj.get() : nullptr;
} }
/***************************************************************************/ /***************************************************************************/
@ -328,9 +331,9 @@ GetNamedPropertyAsVariantRaw(XPCCallContext& ccx,
nsresult* pErr) nsresult* pErr)
{ {
nsXPTType type = nsXPTType((uint8_t)TD_INTERFACE_TYPE); nsXPTType type = nsXPTType((uint8_t)TD_INTERFACE_TYPE);
jsval val; RootedValue val(ccx);
return JS_GetPropertyById(ccx, aJSObj, aName, &val) && return JS_GetPropertyById(ccx, aJSObj, aName, val.address()) &&
// Note that this always takes the T_INTERFACE path through // Note that this always takes the T_INTERFACE path through
// JSData2Native, so the value passed for useAllocator // JSData2Native, so the value passed for useAllocator
// doesn't really matter. We pass true for consistency. // doesn't really matter. We pass true for consistency.
@ -341,13 +344,14 @@ GetNamedPropertyAsVariantRaw(XPCCallContext& ccx,
// static // static
nsresult nsresult
nsXPCWrappedJSClass::GetNamedPropertyAsVariant(XPCCallContext& ccx, nsXPCWrappedJSClass::GetNamedPropertyAsVariant(XPCCallContext& ccx,
JSObject* aJSObj, JSObject* aJSObjArg,
const nsAString& aName, const nsAString& aName,
nsIVariant** aResult) nsIVariant** aResult)
{ {
JSContext* cx = ccx.GetJSContext(); JSContext* cx = ccx.GetJSContext();
RootedObject aJSObj(cx, aJSObjArg);
JSBool ok; JSBool ok;
jsid id; RootedId id(cx);
nsresult rv = NS_ERROR_FAILURE; nsresult rv = NS_ERROR_FAILURE;
AutoScriptEvaluate scriptEval(cx); AutoScriptEvaluate scriptEval(cx);
@ -363,8 +367,8 @@ nsXPCWrappedJSClass::GetNamedPropertyAsVariant(XPCCallContext& ccx,
if (buf) if (buf)
buf->AddRef(); buf->AddRef();
ok = JS_ValueToId(cx, jsstr, &id) && ok = JS_ValueToId(cx, jsstr, id.address()) &&
GetNamedPropertyAsVariantRaw(ccx, aJSObj, id, aResult, &rv); GetNamedPropertyAsVariantRaw(ccx, aJSObj, id, aResult, &rv);
return ok ? NS_OK : NS_FAILED(rv) ? rv : NS_ERROR_FAILURE; return ok ? NS_OK : NS_FAILED(rv) ? rv : NS_ERROR_FAILURE;
} }
@ -374,22 +378,24 @@ nsXPCWrappedJSClass::GetNamedPropertyAsVariant(XPCCallContext& ccx,
// static // static
nsresult nsresult
nsXPCWrappedJSClass::BuildPropertyEnumerator(XPCCallContext& ccx, nsXPCWrappedJSClass::BuildPropertyEnumerator(XPCCallContext& ccx,
JSObject* aJSObj, JSObject* aJSObjArg,
nsISimpleEnumerator** aEnumerate) nsISimpleEnumerator** aEnumerate)
{ {
JSContext* cx = ccx.GetJSContext(); JSContext* cx = ccx.GetJSContext();
RootedObject aJSObj(cx, aJSObjArg);
AutoScriptEvaluate scriptEval(cx); AutoScriptEvaluate scriptEval(cx);
if (!scriptEval.StartEvaluating(aJSObj)) if (!scriptEval.StartEvaluating(aJSObj))
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
JS::AutoIdArray idArray(cx, JS_Enumerate(cx, aJSObj)); AutoIdArray idArray(cx, JS_Enumerate(cx, aJSObj));
if (!idArray) if (!idArray)
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
nsCOMArray<nsIProperty> propertyArray(idArray.length()); nsCOMArray<nsIProperty> propertyArray(idArray.length());
RootedId idName(cx);
for (size_t i = 0; i < idArray.length(); i++) { for (size_t i = 0; i < idArray.length(); i++) {
jsid idName = idArray[i]; idName = idArray[i];
nsCOMPtr<nsIVariant> value; nsCOMPtr<nsIVariant> value;
nsresult rv; nsresult rv;
@ -494,7 +500,7 @@ nsXPCWrappedJSClass::IsWrappedJS(nsISupports* aPtr)
// NB: This returns null unless there's nothing on the JSContext stack. // NB: This returns null unless there's nothing on the JSContext stack.
static JSContext * static JSContext *
GetContextFromObject(JSObject *obj) GetContextFromObject(JSObject *objArg)
{ {
// Don't stomp over a running context. // Don't stomp over a running context.
XPCJSContextStack* stack = XPCJSRuntime::Get()->GetJSContextStack(); XPCJSContextStack* stack = XPCJSRuntime::Get()->GetJSContextStack();
@ -507,6 +513,7 @@ GetContextFromObject(JSObject *obj)
if (!ccx.IsValid()) if (!ccx.IsValid())
return nullptr; return nullptr;
RootedObject obj(ccx, objArg);
JSAutoCompartment ac(ccx, obj); JSAutoCompartment ac(ccx, obj);
XPCWrappedNativeScope* scope = GetObjectScope(obj); XPCWrappedNativeScope* scope = GetObjectScope(obj);
XPCContext *xpcc = scope->GetContext(); XPCContext *xpcc = scope->GetContext();
@ -687,7 +694,7 @@ nsXPCWrappedJSClass::DelegatedQueryInterface(nsXPCWrappedJS* self,
if (!secMan) if (!secMan)
return NS_NOINTERFACE; return NS_NOINTERFACE;
JSObject *selfObj = self->GetJSObject(); RootedObject selfObj(ccx, self->GetJSObject());
nsCOMPtr<nsIPrincipal> objPrin; nsCOMPtr<nsIPrincipal> objPrin;
nsresult rv = secMan->GetObjectPrincipal(ccx, selfObj, nsresult rv = secMan->GetObjectPrincipal(ccx, selfObj,
getter_AddRefs(objPrin)); getter_AddRefs(objPrin));
@ -746,8 +753,9 @@ nsXPCWrappedJSClass::DelegatedQueryInterface(nsXPCWrappedJS* self,
} }
JSObject* JSObject*
nsXPCWrappedJSClass::GetRootJSObject(JSContext* cx, JSObject* aJSObj) nsXPCWrappedJSClass::GetRootJSObject(JSContext* cx, JSObject* aJSObjArg)
{ {
RootedObject aJSObj(cx, aJSObjArg);
JSObject* result = CallQueryInterfaceOnJSObject(cx, aJSObj, JSObject* result = CallQueryInterfaceOnJSObject(cx, aJSObj,
NS_GET_IID(nsISupports)); NS_GET_IID(nsISupports));
if (!result) if (!result)
@ -1127,7 +1135,6 @@ nsXPCWrappedJSClass::CallMethod(nsXPCWrappedJS* wrapper, uint16_t methodIndex,
nsID param_iid; nsID param_iid;
const nsXPTMethodInfo* info = static_cast<const nsXPTMethodInfo*>(info_); const nsXPTMethodInfo* info = static_cast<const nsXPTMethodInfo*>(info_);
const char* name = info->name; const char* name = info->name;
jsval fval;
JSBool foundDependentParam; JSBool foundDependentParam;
// Make sure not to set the callee on ccx until after we've gone through // Make sure not to set the callee on ccx until after we've gone through
@ -1156,13 +1163,14 @@ nsXPCWrappedJSClass::CallMethod(nsXPCWrappedJS* wrapper, uint16_t methodIndex,
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
} }
JSObject *obj = wrapper->GetJSObject(); RootedValue fval(cx);
JSObject *thisObj = obj; RootedObject obj(cx, wrapper->GetJSObject());
RootedObject thisObj(cx, obj);
JSAutoCompartment ac(cx, obj); JSAutoCompartment ac(cx, obj);
ccx.SetScopeForNewJSObjects(obj); ccx.SetScopeForNewJSObjects(obj);
JS::AutoValueVector args(cx); AutoValueVector args(cx);
AutoScriptEvaluate scriptEval(cx); AutoScriptEvaluate scriptEval(cx);
// XXX ASSUMES that retval is last arg. The xpidl compiler ensures this. // XXX ASSUMES that retval is last arg. The xpidl compiler ensures this.
@ -1236,24 +1244,24 @@ nsXPCWrappedJSClass::CallMethod(nsXPCWrappedJS* wrapper, uint16_t methodIndex,
goto pre_call_clean_up; goto pre_call_clean_up;
} }
if (newThis) { if (newThis) {
jsval v; RootedValue v(cx);
xpcObjectHelper helper(newThis); xpcObjectHelper helper(newThis);
JSBool ok = JSBool ok =
XPCConvert::NativeInterface2JSObject( XPCConvert::NativeInterface2JSObject(
ccx, &v, nullptr, helper, nullptr, ccx, v.address(), nullptr, helper, nullptr,
nullptr, false, nullptr); nullptr, false, nullptr);
if (!ok) { if (!ok) {
goto pre_call_clean_up; goto pre_call_clean_up;
} }
thisObj = JSVAL_TO_OBJECT(v); thisObj = JSVAL_TO_OBJECT(v);
if (!JS_WrapObject(cx, &thisObj)) if (!JS_WrapObject(cx, thisObj.address()))
goto pre_call_clean_up; goto pre_call_clean_up;
} }
} }
} }
} }
} }
} else if (!JS_GetMethod(cx, obj, name, &thisObj, &fval)) { } else if (!JS_GetMethod(cx, obj, name, thisObj.address(), fval.address())) {
// XXX We really want to factor out the error reporting better and // XXX We really want to factor out the error reporting better and
// specifically report the failure to find a function with this name. // specifically report the failure to find a function with this name.
// This is what we do below if the property is found but is not a // This is what we do below if the property is found but is not a
@ -1283,8 +1291,8 @@ nsXPCWrappedJSClass::CallMethod(nsXPCWrappedJS* wrapper, uint16_t methodIndex,
nsXPTType datum_type; nsXPTType datum_type;
uint32_t array_count; uint32_t array_count;
bool isArray = type.IsArray(); bool isArray = type.IsArray();
jsval val = JSVAL_NULL; RootedValue val(cx, JSVAL_NULL);
AUTO_MARK_JSVAL(ccx, &val); AUTO_MARK_JSVAL(ccx, val.address());
bool isSizedString = isArray ? bool isSizedString = isArray ?
false : false :
type.TagPart() == nsXPTType::T_PSTRING_SIZE_IS || type.TagPart() == nsXPTType::T_PSTRING_SIZE_IS ||
@ -1326,19 +1334,19 @@ nsXPCWrappedJSClass::CallMethod(nsXPCWrappedJS* wrapper, uint16_t methodIndex,
if (isArray) { if (isArray) {
XPCLazyCallContext lccx(ccx); XPCLazyCallContext lccx(ccx);
if (!XPCConvert::NativeArray2JS(lccx, &val, if (!XPCConvert::NativeArray2JS(lccx, val.address(),
(const void**)&pv->val, (const void**)&pv->val,
datum_type, &param_iid, datum_type, &param_iid,
array_count, nullptr)) array_count, nullptr))
goto pre_call_clean_up; goto pre_call_clean_up;
} else if (isSizedString) { } else if (isSizedString) {
if (!XPCConvert::NativeStringWithSize2JS(ccx, &val, if (!XPCConvert::NativeStringWithSize2JS(ccx, val.address(),
(const void*)&pv->val, (const void*)&pv->val,
datum_type, datum_type,
array_count, nullptr)) array_count, nullptr))
goto pre_call_clean_up; goto pre_call_clean_up;
} else { } else {
if (!XPCConvert::NativeData2JS(ccx, &val, &pv->val, type, if (!XPCConvert::NativeData2JS(ccx, val.address(), &pv->val, type,
&param_iid, nullptr)) &param_iid, nullptr))
goto pre_call_clean_up; goto pre_call_clean_up;
} }
@ -1346,7 +1354,7 @@ nsXPCWrappedJSClass::CallMethod(nsXPCWrappedJS* wrapper, uint16_t methodIndex,
if (param.IsOut() || param.IsDipper()) { if (param.IsOut() || param.IsDipper()) {
// create an 'out' object // create an 'out' object
JSObject* out_obj = NewOutObject(cx, obj); RootedObject out_obj(cx, NewOutObject(cx, obj));
if (!out_obj) { if (!out_obj) {
retval = NS_ERROR_OUT_OF_MEMORY; retval = NS_ERROR_OUT_OF_MEMORY;
goto pre_call_clean_up; goto pre_call_clean_up;
@ -1355,7 +1363,7 @@ nsXPCWrappedJSClass::CallMethod(nsXPCWrappedJS* wrapper, uint16_t methodIndex,
if (param.IsIn()) { if (param.IsIn()) {
if (!JS_SetPropertyById(cx, out_obj, if (!JS_SetPropertyById(cx, out_obj,
mRuntime->GetStringID(XPCJSRuntime::IDX_VALUE), mRuntime->GetStringID(XPCJSRuntime::IDX_VALUE),
&val)) { val.address())) {
goto pre_call_clean_up; goto pre_call_clean_up;
} }
} }
@ -1418,7 +1426,7 @@ pre_call_clean_up:
JS_ClearPendingException(cx); JS_ClearPendingException(cx);
jsval rval; RootedValue rval(cx);
if (XPT_MD_IS_GETTER(info->flags)) { if (XPT_MD_IS_GETTER(info->flags)) {
success = JS_GetProperty(cx, obj, name, argv); success = JS_GetProperty(cx, obj, name, argv);
rval = *argv; rval = *argv;
@ -1430,7 +1438,7 @@ pre_call_clean_up:
uint32_t oldOpts = JS_GetOptions(cx); uint32_t oldOpts = JS_GetOptions(cx);
JS_SetOptions(cx, oldOpts | JSOPTION_DONT_REPORT_UNCAUGHT); JS_SetOptions(cx, oldOpts | JSOPTION_DONT_REPORT_UNCAUGHT);
success = JS_CallFunctionValue(cx, thisObj, fval, argc, argv, &rval); success = JS_CallFunctionValue(cx, thisObj, fval, argc, argv, rval.address());
JS_SetOptions(cx, oldOpts); JS_SetOptions(cx, oldOpts);
} else { } else {
@ -1490,7 +1498,7 @@ pre_call_clean_up:
continue; continue;
} }
jsval val; RootedValue val(cx);
uint8_t type_tag = type.TagPart(); uint8_t type_tag = type.TagPart();
nsXPTCMiniVariant* pv; nsXPTCMiniVariant* pv;
@ -1504,7 +1512,7 @@ pre_call_clean_up:
else if (JSVAL_IS_PRIMITIVE(argv[i]) || else if (JSVAL_IS_PRIMITIVE(argv[i]) ||
!JS_GetPropertyById(cx, JSVAL_TO_OBJECT(argv[i]), !JS_GetPropertyById(cx, JSVAL_TO_OBJECT(argv[i]),
mRuntime->GetStringID(XPCJSRuntime::IDX_VALUE), mRuntime->GetStringID(XPCJSRuntime::IDX_VALUE),
&val)) val.address()))
break; break;
// setup allocator and/or iid // setup allocator and/or iid
@ -1532,7 +1540,7 @@ pre_call_clean_up:
if (!type.IsDependent()) if (!type.IsDependent())
continue; continue;
jsval val; RootedValue val(cx);
nsXPTCMiniVariant* pv; nsXPTCMiniVariant* pv;
nsXPTType datum_type; nsXPTType datum_type;
uint32_t array_count; uint32_t array_count;
@ -1548,7 +1556,7 @@ pre_call_clean_up:
val = rval; val = rval;
else if (!JS_GetPropertyById(cx, JSVAL_TO_OBJECT(argv[i]), else if (!JS_GetPropertyById(cx, JSVAL_TO_OBJECT(argv[i]),
mRuntime->GetStringID(XPCJSRuntime::IDX_VALUE), mRuntime->GetStringID(XPCJSRuntime::IDX_VALUE),
&val)) val.address()))
break; break;
// setup allocator and/or iid // setup allocator and/or iid

Просмотреть файл

@ -3813,7 +3813,7 @@ public:
* @param errorReporter the error reporter callback function to set * @param errorReporter the error reporter callback function to set
*/ */
bool StartEvaluating(JSObject *scope, JSErrorReporter errorReporter = nullptr); bool StartEvaluating(JS::HandleObject scope, JSErrorReporter errorReporter = nullptr);
/** /**
* Does the post script evaluation and resets the error reporter * Does the post script evaluation and resets the error reporter