Fix for bug 517196 (The JSClass of wrappers shouldn't change when morphing from slim to XPCWrappedNative). r=mrbkap.

--HG--
extra : rebase_source : 4f7978e3ed1335fc4f58478afc038fb63576581b
This commit is contained in:
Peter Van der Beken 2009-09-18 12:43:48 +02:00
Родитель 72d461b556
Коммит f93aeceb40
11 изменённых файлов: 197 добавлений и 186 удалений

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

@ -108,7 +108,6 @@ PRBool nsScriptSecurityManager::sStrictFileOriginPolicy = PR_TRUE;
// natives, to avoid having to QI to nsIXPConnectWrappedNative all the
// time when doing security checks.
static JSEqualityOp sXPCWrappedNativeEqualityOps;
static JSEqualityOp sXPCSlimWrapperEqualityOps;
///////////////////////////
@ -2408,8 +2407,7 @@ nsScriptSecurityManager::doGetObjectPrincipal(JSObject *aObj
(jsClass->flags & JSCLASS_IS_EXTENDED) ?
reinterpret_cast<const JSExtendedClass*>(jsClass)->equality :
nsnull;
if (op == sXPCWrappedNativeEqualityOps ||
op == sXPCSlimWrapperEqualityOps) {
if (op == sXPCWrappedNativeEqualityOps) {
result = sXPConnect->GetPrincipal(aObj,
#ifdef DEBUG
aAllowShortCircuit
@ -3407,8 +3405,7 @@ nsresult nsScriptSecurityManager::Init()
JS_SetRuntimeSecurityCallbacks(sRuntime, &securityCallbacks);
NS_ASSERTION(!oldcallbacks, "Someone else set security callbacks!");
sXPConnect->GetXPCWrappedNativeJSClassInfo(&sXPCWrappedNativeEqualityOps,
&sXPCSlimWrapperEqualityOps);
sXPConnect->GetXPCWrappedNativeJSClassInfo(&sXPCWrappedNativeEqualityOps);
return NS_OK;
}

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

@ -394,7 +394,7 @@ interface nsIXPCFunctionThisTranslator : nsISupports
{ 0xbd, 0xd6, 0x0, 0x0, 0x64, 0x65, 0x73, 0x74 } }
%}
[uuid(c29f5d27-21b1-4b87-8282-d724d535ef7b)]
[uuid(44d52d63-6575-4b09-a29f-e6708203fa9d)]
interface nsIXPConnect : nsISupports
{
%{ C++
@ -782,8 +782,7 @@ interface nsIXPConnect : nsISupports
* a pointer to a nsIXPConnectWrappedNative or to the native in their
* private date. See IS_WRAPPER_CLASS in xpcprivate.h for details.
*/
void GetXPCWrappedNativeJSClassInfo(out JSEqualityOp equality1,
out JSEqualityOp equality2);
void GetXPCWrappedNativeJSClassInfo(out JSEqualityOp equality);
/**
* Whether or not XPConnect should report all JS exceptions when returning

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

@ -415,8 +415,8 @@ XPC_COW_RewrapForChrome(JSContext *cx, JSObject *wrapperObj, jsval *vp)
}
XPCWrappedNative *wn;
if (IS_WRAPPER_CLASS(STOBJ_GET_CLASS(obj)) &&
(wn = XPCWrappedNative::GetWrappedNativeOfJSObject(cx, obj)) &&
if (IS_WN_WRAPPER(obj) &&
(wn = (XPCWrappedNative*)xpc_GetJSPrivate(obj)) &&
!nsXPCWrappedJSClass::IsWrappedJS(wn->Native())) {
// Return an explicit XPCNativeWrapper in case "chrome" code happens to be
// XBL code cloned into an untrusted context.

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

@ -733,7 +733,7 @@ nsXPConnect::Traverse(void *p, nsCycleCollectionTraversalCallback &cb)
(XPCWrappedNative*)xpc_GetJSPrivate(STOBJ_GET_PARENT(obj));
dontTraverse = WrapperIsNotMainThreadOnly(wrapper);
}
else if(IS_WRAPPER_CLASS(clazz))
else if(IS_WRAPPER_CLASS(clazz) && IS_WN_WRAPPER_OBJECT(obj))
{
XPCWrappedNative *wrapper = (XPCWrappedNative*)xpc_GetJSPrivate(obj);
dontTraverse = WrapperIsNotMainThreadOnly(wrapper);
@ -1345,16 +1345,13 @@ nsXPConnect::GetWrappedNativeOfJSObject(JSContext * aJSContext,
return UnexpectedFailure(NS_ERROR_FAILURE);
SLIM_LOG_WILL_MORPH(aJSContext, aJSObj);
if(!IS_SLIM_WRAPPER(aJSObj) || MorphSlimWrapper(aJSContext, aJSObj))
nsIXPConnectWrappedNative* wrapper =
XPCWrappedNative::GetAndMorphWrappedNativeOfJSObject(aJSContext, aJSObj);
if(wrapper)
{
nsIXPConnectWrappedNative* wrapper =
XPCWrappedNative::GetWrappedNativeOfJSObject(aJSContext, aJSObj);
if(wrapper)
{
NS_ADDREF(wrapper);
*_retval = wrapper;
return NS_OK;
}
NS_ADDREF(wrapper);
*_retval = wrapper;
return NS_OK;
}
// else...
@ -1990,16 +1987,14 @@ nsXPConnect::EvalInSandboxObject(const nsAString& source, JSContext *cx,
#endif /* XPCONNECT_STANDALONE */
}
/* void GetXPCWrappedNativeJSClassInfo(out JSEqualityOp equality1, JSEqualityOp *equality2); */
/* void GetXPCWrappedNativeJSClassInfo(out JSEqualityOp equality); */
NS_IMETHODIMP
nsXPConnect::GetXPCWrappedNativeJSClassInfo(JSEqualityOp *equality1,
JSEqualityOp *equality2)
nsXPConnect::GetXPCWrappedNativeJSClassInfo(JSEqualityOp *equality)
{
// Expose the equality pointer used by IS_WRAPPER_CLASS(). If that macro
// ever changes, this function needs to stay in sync.
*equality1 = &XPC_WN_Equality;
*equality2 = &XPC_SWN_Equality;
*equality = &XPC_WN_Equality;
return NS_OK;
}
@ -2404,23 +2399,24 @@ nsXPConnect::GetWrapperForObject(JSContext* aJSContext,
JSAutoRequest ar(aJSContext);
XPCWrappedNativeScope *objectscope;
XPCWrappedNative *wrapper = nsnull;
if(IS_SLIM_WRAPPER(aObject))
JSObject* obj2;
XPCWrappedNative *wrapper =
XPCWrappedNative::GetWrappedNativeOfJSObject(aJSContext, aObject,
nsnull, &obj2);
if(wrapper)
{
objectscope = GetSlimWrapperProto(aObject)->GetScope();
objectscope = wrapper->GetScope();
}
else if(obj2)
{
objectscope = GetSlimWrapperProto(obj2)->GetScope();
}
else
{
wrapper =
XPCWrappedNative::GetWrappedNativeOfJSObject(aJSContext, aObject);
if(!wrapper)
{
// Couldn't get the wrapped native (maybe a prototype?) so just return
// the original object.
*_retval = OBJECT_TO_JSVAL(aObject);
return NS_OK;
}
objectscope = wrapper->GetScope();
// Couldn't get the wrapped native (maybe a prototype?) so just return
// the original object.
*_retval = OBJECT_TO_JSVAL(aObject);
return NS_OK;
}
XPCWrappedNativeScope *xpcscope =
@ -2648,10 +2644,10 @@ nsXPConnect::SetSafeJSContext(JSContext * aSafeJSContext)
nsIPrincipal*
nsXPConnect::GetPrincipal(JSObject* obj, PRBool allowShortCircuit) const
{
NS_ASSERTION(IS_WRAPPER_CLASS(STOBJ_GET_CLASS(obj)) || IS_SLIM_WRAPPER(obj),
NS_ASSERTION(IS_WRAPPER_CLASS(STOBJ_GET_CLASS(obj)),
"What kind of wrapper is this?");
if(IS_WRAPPER_CLASS(STOBJ_GET_CLASS(obj)))
if(IS_WN_WRAPPER_OBJECT(obj))
{
XPCWrappedNative *xpcWrapper =
(XPCWrappedNative *)xpc_GetJSPrivate(obj);

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

@ -1126,7 +1126,7 @@ XPCConvert::NativeInterface2JSObject(XPCLazyCallContext& lccx,
{
tryConstructSlimWrapper = PR_TRUE;
}
else if(!IS_WRAPPER_CLASS(STOBJ_GET_CLASS(flat)))
else if(IS_SLIM_WRAPPER_OBJECT(flat))
{
JSObject* global = JS_GetGlobalForObject(cx, flat);
if(global == xpcscope->GetGlobalJSObject())
@ -1185,6 +1185,9 @@ XPCConvert::NativeInterface2JSObject(XPCLazyCallContext& lccx,
}
}
NS_ASSERTION(!flat || IS_WRAPPER_CLASS(STOBJ_GET_CLASS(flat)),
"What kind of wrapper is this?");
nsresult rv;
XPCWrappedNative* wrapper;
nsRefPtr<XPCWrappedNative> strongWrapper;
@ -1200,7 +1203,7 @@ XPCConvert::NativeInterface2JSObject(XPCLazyCallContext& lccx,
wrapper = strongWrapper;
}
else if(IS_WRAPPER_CLASS(STOBJ_GET_CLASS(flat)))
else if(IS_WN_WRAPPER_OBJECT(flat))
{
wrapper = static_cast<XPCWrappedNative*>(xpc_GetJSPrivate(flat));

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

@ -943,22 +943,17 @@ nsJSCID::HasInstance(nsIXPConnectWrappedNative *wrapper,
NS_ASSERTION(obj, "when is an object not an object?");
nsIClassInfo* ci;
if(IS_SLIM_WRAPPER(obj))
{
ci = GetSlimWrapperProto(obj)->GetClassInfo();
}
else
{
// is this really a native xpcom object with a wrapper?
XPCWrappedNative* other_wrapper =
XPCWrappedNative::GetWrappedNativeOfJSObject(cx, obj);
// is this really a native xpcom object with a wrapper?
JSObject* obj2;
XPCWrappedNative* other_wrapper =
XPCWrappedNative::GetWrappedNativeOfJSObject(cx, obj, nsnull, &obj2);
if(!other_wrapper)
return NS_OK;
if(!obj2)
return NS_OK;
ci = other_wrapper->GetClassInfo();
}
nsIClassInfo* ci = other_wrapper ?
other_wrapper->GetClassInfo() :
GetSlimWrapperProto(obj2)->GetClassInfo();
// We consider CID equality to be the thing that matters here.
// This is perhaps debatable.

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

@ -265,17 +265,6 @@ extern const char XPC_XPCONNECT_CONTRACTID[];
#define WRAPPER_SLOTS (JSCLASS_HAS_PRIVATE | JSCLASS_HAS_RESERVED_SLOTS(1))
// NOTE!!!
//
// If this ever changes,
// nsScriptSecurityManager::doGetObjectPrincipal() *must* be updated
// also!
//
// NOTE!!!
#define IS_WRAPPER_CLASS(clazz) \
(((clazz)->flags & JSCLASS_IS_EXTENDED) && \
reinterpret_cast<JSExtendedClass*>(clazz)->equality == XPC_WN_Equality)
/***************************************************************************/
// Auto locking support class...
@ -1354,6 +1343,47 @@ xpc_InitWrappedNativeJSOps();
(clazz) == &XPC_WN_ModsAllowed_WithCall_Proto_JSClass || \
(clazz) == &XPC_WN_ModsAllowed_NoCall_Proto_JSClass)
// NOTE!!!
//
// If this ever changes,
// nsScriptSecurityManager::doGetObjectPrincipal() *must* be updated
// also!
//
// NOTE!!!
#define IS_WRAPPER_CLASS(clazz) \
(((clazz)->flags & JSCLASS_IS_EXTENDED) && \
reinterpret_cast<JSExtendedClass*>(clazz)->equality == XPC_WN_Equality)
inline JSBool
DebugCheckWrapperClass(JSObject* obj)
{
NS_ASSERTION(IS_WRAPPER_CLASS(STOBJ_GET_CLASS(obj)),
"Forgot to check if this is a wrapper?");
return JS_TRUE;
}
// If IS_WRAPPER_CLASS for the JSClass of an object is true, the object can be
// a slim wrapper, holding a native in its private slot, or a wrappednative
// wrapper, holding the XPCWrappedNative in its private slot. A slim wrapper
// also holds a pointer to its XPCWrappedNativeProto in a reserved slot, we can
// check that slot for a non-void value to distinguish between the two.
// Only use these macros if IS_WRAPPER_CLASS(STOBJ_GET_CLASS(obj)) is true.
#define IS_WN_WRAPPER_OBJECT(obj) \
(DebugCheckWrapperClass(obj) && \
JSVAL_IS_VOID(STOBJ_GET_SLOT(obj, JSSLOT_START(STOBJ_GET_CLASS(obj)))))
#define IS_SLIM_WRAPPER_OBJECT(obj) \
(DebugCheckWrapperClass(obj) && \
!JSVAL_IS_VOID(STOBJ_GET_SLOT(obj, JSSLOT_START(STOBJ_GET_CLASS(obj)))))
// Use these macros if IS_WRAPPER_CLASS(STOBJ_GET_CLASS(obj)) might be false.
// Avoid calling them if IS_WRAPPER_CLASS(STOBJ_GET_CLASS(obj)) can only be
// true, as we'd do a redundant call to IS_WRAPPER_CLASS.
#define IS_WN_WRAPPER(obj) \
(IS_WRAPPER_CLASS(STOBJ_GET_CLASS(obj)) && IS_WN_WRAPPER_OBJECT(obj))
#define IS_SLIM_WRAPPER(obj) \
(IS_WRAPPER_CLASS(STOBJ_GET_CLASS(obj)) && IS_SLIM_WRAPPER_OBJECT(obj))
// Comes from xpcwrappednativeops.cpp
extern void
xpc_TraceForValidWrapper(JSTracer *trc, XPCWrappedNative* wrapper);
@ -1907,14 +1937,13 @@ public:
const XPCNativeScriptableFlags& GetFlags() const {return mFlags;}
JSClass* GetJSClass() {return &mJSClass.base;}
JSClass* GetSlimJSClass()
{return &mSlimJSClass.base;}
{if(mCanBeSlim) return GetJSClass(); return nsnull;}
XPCNativeScriptableShared(JSUint32 aFlags = 0, char* aName = nsnull)
: mFlags(aFlags)
: mFlags(aFlags),
mCanBeSlim(JS_FALSE)
{memset(&mJSClass, 0, sizeof(mJSClass));
mJSClass.base.name = aName; // take ownership
memset(&mSlimJSClass, 0, sizeof(mSlimJSClass));
mSlimJSClass.base.name = aName; // take ownership
MOZ_COUNT_CTOR(XPCNativeScriptableShared);}
~XPCNativeScriptableShared()
@ -1934,7 +1963,7 @@ public:
private:
XPCNativeScriptableFlags mFlags;
JSExtendedClass mJSClass;
JSExtendedClass mSlimJSClass;
JSBool mCanBeSlim;
};
/***************************************************************************/
@ -2201,13 +2230,6 @@ private:
};
extern void XPC_SWN_Finalize(JSContext *cx, JSObject *obj);
extern JSBool XPC_SWN_Equality(JSContext *cx, JSObject *obj, jsval v,
JSBool *bp);
#define IS_SLIM_WRAPPER_CLASS(clazz) ((clazz)->finalize == XPC_SWN_Finalize)
#define IS_SLIM_WRAPPER(obj) IS_SLIM_WRAPPER_CLASS(STOBJ_GET_CLASS(obj))
extern JSBool ConstructSlimWrapper(XPCCallContext &ccx, nsISupports *p,
nsWrapperCache *cache,
XPCWrappedNativeScope* xpcScope,
@ -2459,6 +2481,9 @@ public:
XPCNativeInterface* Interface,
XPCWrappedNative** wrapper);
// If pobj2 is not null and *pobj2 is not null after the call and the return
// value is null, then *pobj2 points to an object for which
// IS_SLIM_WRAPPER_OBJECT is true.
static XPCWrappedNative*
GetWrappedNativeOfJSObject(JSContext* cx, JSObject* obj,
JSObject* funobj = nsnull,

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

@ -504,8 +504,7 @@ GetMemberInfo(JSObject *obj,
*ifaceName = "Unknown";
NS_ASSERTION(IS_WRAPPER_CLASS(STOBJ_GET_CLASS(obj)) ||
STOBJ_GET_CLASS(obj) == &XPC_WN_Tearoff_JSClass ||
IS_SLIM_WRAPPER(obj),
STOBJ_GET_CLASS(obj) == &XPC_WN_Tearoff_JSClass,
"obj must be a wrapper");
XPCWrappedNativeProto *proto;
if(IS_SLIM_WRAPPER(obj))
@ -900,15 +899,6 @@ xpc_qsUnwrapArgImpl(JSContext *cx,
}
JSObject *src = JSVAL_TO_OBJECT(v);
if(IS_SLIM_WRAPPER(src))
{
nsISupports *iface = static_cast<nsISupports*>(xpc_GetJSPrivate(src));
if(NS_FAILED(getNative(iface, GetOffsetsFromSlimWrapper(src),
src, iid, ppArg, ppArgRef, vp)))
return NS_ERROR_XPC_BAD_CONVERT_JS;
return NS_OK;
}
JSObject *inner = nsnull;
if(XPCWrapper::IsSecurityWrapper(src))
{
@ -918,8 +908,10 @@ xpc_qsUnwrapArgImpl(JSContext *cx,
}
// From XPCConvert::JSObject2NativeInterface
JSObject* obj2;
XPCWrappedNative* wrappedNative =
XPCWrappedNative::GetWrappedNativeOfJSObject(cx, inner ? inner : src);
XPCWrappedNative::GetWrappedNativeOfJSObject(cx, inner ? inner : src,
nsnull, &obj2);
nsISupports *iface;
if(wrappedNative)
{
@ -929,6 +921,14 @@ xpc_qsUnwrapArgImpl(JSContext *cx,
return NS_ERROR_XPC_BAD_CONVERT_JS;
return NS_OK;
}
if(obj2)
{
iface = static_cast<nsISupports*>(xpc_GetJSPrivate(obj2));
if(NS_FAILED(getNative(iface, GetOffsetsFromSlimWrapper(obj2),
obj2, iid, ppArg, ppArgRef, vp)))
return NS_ERROR_XPC_BAD_CONVERT_JS;
return NS_OK;
}
// else...
// Slow path.

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

@ -465,7 +465,7 @@ XPCWrappedNative::GetNewOrUsed(XPCCallContext& ccx,
JSObject *cached = cache->GetWrapper();
if(cached)
{
if(IS_SLIM_WRAPPER(cached))
if(IS_SLIM_WRAPPER_OBJECT(cached))
{
nsRefPtr<XPCWrappedNative> morphed;
if(!XPCWrappedNative::Morph(ccx, cached, Interface, cache,
@ -784,7 +784,7 @@ XPCWrappedNative::GetUsedOnly(XPCCallContext& ccx,
if(cache)
{
JSObject *flat = cache->GetWrapper();
if(flat && IS_SLIM_WRAPPER(flat) && !MorphSlimWrapper(ccx, flat))
if(flat && IS_SLIM_WRAPPER_OBJECT(flat) && !MorphSlimWrapper(ccx, flat))
return NS_ERROR_FAILURE;
wrapper = flat ?
@ -1144,22 +1144,13 @@ XPCWrappedNative::Init(XPCCallContext& ccx,
JSBool
XPCWrappedNative::Init(XPCCallContext &ccx, JSObject *existingJSObject)
{
mScriptableInfo = GetProto()->GetScriptableInfo();
JSClass* jsclazz = mScriptableInfo->GetJSClass();
// Morph the existing object.
#ifdef DEBUG
JSObject* protoJSObject = GetProto()->GetJSProtoObject();
NS_ASSERTION(protoJSObject->map->ops == jsclazz->getObjectOps(ccx, jsclazz),
"Ugh, we can't deal with that!");
#endif
if(!JS_SetReservedSlot(ccx, existingJSObject, 0, JSVAL_VOID))
return JS_FALSE;
mScriptableInfo = GetProto()->GetScriptableInfo();
mFlatJSObject = existingJSObject;
// Make sure we preserve any flags borrowing bits in classword.
mFlatJSObject->classword ^= (jsuword)OBJ_GET_CLASS(ccx, mFlatJSObject);
mFlatJSObject->classword |= (jsuword)jsclazz;
SLIM_LOG(("----- %i morphed slim wrapper (mFlatJSObject: %p, %p)\n",
++sMorphedSlimWrappers, mFlatJSObject,
static_cast<nsISupports*>(xpc_GetJSPrivate(mFlatJSObject))));
@ -1461,7 +1452,7 @@ XPCWrappedNative::ReparentWrapperIfFound(XPCCallContext& ccx,
if(cache)
{
flat = cache->GetWrapper();
if(flat && !IS_SLIM_WRAPPER(flat))
if(flat && !IS_SLIM_WRAPPER_OBJECT(flat))
wrapper = static_cast<XPCWrappedNative*>(xpc_GetJSPrivate(flat));
}
@ -1653,10 +1644,6 @@ XPCWrappedNative::GetWrappedNativeOfJSObject(JSContext* cx,
if(proto)
protoClassInfo = proto->GetClassInfo();
}
else if(IS_SLIM_WRAPPER_CLASS(funObjParentClass))
{
NS_ERROR("function object has slim wrapper!");
}
else if(IS_WRAPPER_CLASS(funObjParentClass))
{
cur = funObjParent;
@ -1681,32 +1668,25 @@ XPCWrappedNative::GetWrappedNativeOfJSObject(JSContext* cx,
JSClass* clazz;
clazz = STOBJ_GET_CLASS(cur);
if(IS_SLIM_WRAPPER_CLASS(clazz))
if(IS_WRAPPER_CLASS(clazz))
{
return_wrapper:
JSBool isWN = IS_WN_WRAPPER_OBJECT(cur);
XPCWrappedNative* wrapper =
isWN ? (XPCWrappedNative*) xpc_GetJSPrivate(cur) : nsnull;
if(proto)
{
XPCWrappedNativeProto* wrapper_proto =
GetSlimWrapperProto(cur);
isWN ? wrapper->GetProto() : GetSlimWrapperProto(cur);
XPCWrappedNativeScope* wrapper_scope =
wrapper_proto ? wrapper_proto->GetScope() :
wrapper->GetScope();
if(proto != wrapper_proto &&
(proto->GetScope() != wrapper_proto->GetScope() ||
(proto->GetScope() != wrapper_scope ||
!protoClassInfo || !wrapper_proto ||
protoClassInfo != wrapper_proto->GetClassInfo()))
continue;
}
if(pobj2)
*pobj2 = cur;
return nsnull;
}
if(IS_WRAPPER_CLASS(clazz))
{
return_wrapper:
XPCWrappedNative* wrapper =
(XPCWrappedNative*) xpc_GetJSPrivate(cur);
if(proto && proto != wrapper->GetProto() &&
(proto->GetScope() != wrapper->GetScope() ||
!protoClassInfo || !wrapper->GetProto() ||
protoClassInfo != wrapper->GetProto()->GetClassInfo()))
continue;
if(pobj2)
*pobj2 = cur;
return wrapper;
@ -3827,13 +3807,14 @@ ConstructSlimWrapper(XPCCallContext &ccx, nsISupports *p, nsWrapperCache *cache,
XPCNativeScriptableInfo* si = xpcproto->GetScriptableInfo();
JSClass* jsclazz = si->GetSlimJSClass();
if(!jsclazz->addProperty)
if(!jsclazz)
return JS_FALSE;
wrapper = xpc_NewSystemInheritingJSObject(ccx, jsclazz,
xpcproto->GetJSProtoObject(),
parent);
if(!JS_SetPrivate(ccx, wrapper, identityObj) ||
if(!wrapper ||
!JS_SetPrivate(ccx, wrapper, identityObj) ||
!JS_SetReservedSlot(ccx, wrapper, 0, PRIVATE_TO_JSVAL(xpcproto.get())))
return JS_FALSE;

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

@ -679,13 +679,30 @@ XPC_WN_Shared_Enumerate(JSContext *cx, JSObject *obj)
/***************************************************************************/
#ifdef DEBUG_slimwrappers
static PRUint32 sFinalizedSlimWrappers;
#endif
static void
XPC_WN_NoHelper_Finalize(JSContext *cx, JSObject *obj)
{
XPCWrappedNative* p = (XPCWrappedNative*) xpc_GetJSPrivate(obj);
nsISupports* p = static_cast<nsISupports*>(xpc_GetJSPrivate(obj));
if(!p)
return;
p->FlatJSObjectFinalized(cx);
if(IS_SLIM_WRAPPER_OBJECT(obj))
{
SLIM_LOG(("----- %i finalized slim wrapper (%p, %p)\n",
++sFinalizedSlimWrappers, obj, p));
nsWrapperCache* cache;
CallQueryInterface(p, &cache);
cache->ClearWrapper();
NS_RELEASE(p);
return;
}
static_cast<XPCWrappedNative*>(p)->FlatJSObjectFinalized(cx);
}
static void
@ -746,11 +763,20 @@ xpc_TraceForValidWrapper(JSTracer *trc, XPCWrappedNative* wrapper)
static void
XPC_WN_Shared_Trace(JSTracer *trc, JSObject *obj)
{
JSObject *obj2;
XPCWrappedNative* wrapper =
XPCWrappedNative::GetWrappedNativeOfJSObject(trc->context, obj);
XPCWrappedNative::GetWrappedNativeOfJSObject(trc->context, obj, nsnull,
&obj2);
if(wrapper && wrapper->IsValid())
xpc_TraceForValidWrapper(trc, wrapper);
if(wrapper)
{
if(wrapper->IsValid())
xpc_TraceForValidWrapper(trc, wrapper);
}
else if(obj2)
{
GetSlimWrapperProto(obj2)->TraceJS(trc);
}
}
static JSBool
@ -807,8 +833,16 @@ XPC_WN_Equality(JSContext *cx, JSObject *obj, jsval v, JSBool *bp)
{
*bp = JS_FALSE;
JSObject *obj2;
XPCWrappedNative *wrapper =
XPCWrappedNative::GetAndMorphWrappedNativeOfJSObject(cx, obj);
XPCWrappedNative::GetWrappedNativeOfJSObject(cx, obj, nsnull, &obj2);
if(!wrapper && obj2)
{
*bp = !JSVAL_IS_PRIMITIVE(v) && (JSVAL_TO_OBJECT(v) == obj2);
return JS_TRUE;
}
THROW_AND_RETURN_IF_BAD_WRAPPER(cx, wrapper);
XPCNativeScriptableInfo* si = wrapper->GetScriptableInfo();
@ -1096,7 +1130,20 @@ XPC_WN_Helper_HasInstance(JSContext *cx, JSObject *obj, jsval v, JSBool *bp)
static void
XPC_WN_Helper_Finalize(JSContext *cx, JSObject *obj)
{
XPCWrappedNative* wrapper = (XPCWrappedNative*) xpc_GetJSPrivate(obj);
nsISupports* p = static_cast<nsISupports*>(xpc_GetJSPrivate(obj));
if(IS_SLIM_WRAPPER(obj))
{
SLIM_LOG(("----- %i finalized slim wrapper (%p, %p)\n",
++sFinalizedSlimWrappers, obj, p));
nsWrapperCache* cache;
CallQueryInterface(p, &cache);
cache->ClearWrapper();
NS_RELEASE(p);
return;
}
XPCWrappedNative* wrapper = (XPCWrappedNative*)p;
if(!wrapper)
return;
wrapper->GetScriptableCallback()->Finalize(wrapper, cx, obj);
@ -1106,12 +1153,20 @@ XPC_WN_Helper_Finalize(JSContext *cx, JSObject *obj)
static void
XPC_WN_Helper_Trace(JSTracer *trc, JSObject *obj)
{
JSObject *obj2;
XPCWrappedNative* wrapper =
XPCWrappedNative::GetWrappedNativeOfJSObject(trc->context, obj);
if(wrapper && wrapper->IsValid())
XPCWrappedNative::GetWrappedNativeOfJSObject(trc->context, obj, nsnull, &obj2);
if(wrapper)
{
wrapper->GetScriptableCallback()->Trace(wrapper, trc, obj);
xpc_TraceForValidWrapper(trc, wrapper);
if(wrapper->IsValid())
{
wrapper->GetScriptableCallback()->Trace(wrapper, trc, obj);
xpc_TraceForValidWrapper(trc, wrapper);
}
}
else if(obj2)
{
GetSlimWrapperProto(obj2)->TraceJS(trc);
}
}
@ -1271,8 +1326,6 @@ static JSBool
XPC_WN_JSOp_Enumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op,
jsval *statep, jsid *idp)
{
MORPH_SLIM_WRAPPER(cx, obj);
JSClass *clazz = STOBJ_GET_CLASS(obj);
if(!IS_WRAPPER_CLASS(clazz) || clazz == &XPC_WN_NoHelper_JSClass.base)
{
@ -1283,6 +1336,8 @@ XPC_WN_JSOp_Enumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op,
return js_ObjectOps.enumerate(cx, obj, enum_op, statep, idp);
}
MORPH_SLIM_WRAPPER(cx, obj);
XPCCallContext ccx(JS_CALLER, cx, obj);
XPCWrappedNative* wrapper = ccx.GetWrapper();
THROW_AND_RETURN_IF_BAD_WRAPPER(cx, wrapper);
@ -1511,40 +1566,6 @@ JSBool xpc_InitWrappedNativeJSOps()
/***************************************************************************/
static void
XPC_SWN_Trace(JSTracer *trc, JSObject *obj)
{
GetSlimWrapperProto(obj)->TraceJS(trc);
}
#ifdef DEBUG_slimwrappers
static PRUint32 sFinalizedSlimWrappers;
#endif
void
XPC_SWN_Finalize(JSContext *cx, JSObject *obj)
{
nsISupports* p = static_cast<nsISupports*>(xpc_GetJSPrivate(obj));
SLIM_LOG(("----- %i finalized slim wrapper (%p, %p)\n",
++sFinalizedSlimWrappers, obj, p));
nsWrapperCache* cache;
CallQueryInterface(p, &cache);
cache->ClearWrapper();
NS_RELEASE(p);
}
JSBool
XPC_SWN_Equality(JSContext *cx, JSObject *obj, jsval v, JSBool *bp)
{
*bp = !JSVAL_IS_PRIMITIVE(v) && (JSVAL_TO_OBJECT(v) == obj);
return JS_TRUE;
}
/***************************************************************************/
// static
XPCNativeScriptableInfo*
XPCNativeScriptableInfo::Construct(XPCCallContext& ccx,
@ -1696,13 +1717,7 @@ XPCNativeScriptableShared::PopulateJSClass(JSBool isGlobal)
if(!(mFlags & (nsIXPCScriptable::WANT_OUTER_OBJECT |
nsIXPCScriptable::WANT_INNER_OBJECT)))
{
memcpy(&mSlimJSClass, &mJSClass, sizeof(mJSClass));
mSlimJSClass.base.finalize = XPC_SWN_Finalize;
mSlimJSClass.base.mark = JS_CLASS_TRACE(XPC_SWN_Trace);
mSlimJSClass.equality = XPC_SWN_Equality;
}
mCanBeSlim = JS_TRUE;
}
/***************************************************************************/

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

@ -720,12 +720,12 @@ GetScopeOfObject(JSObject* obj)
{
nsISupports* supports;
JSClass* clazz = STOBJ_GET_CLASS(obj);
JSBool isWrapper = IS_WRAPPER_CLASS(clazz);
if(IS_SLIM_WRAPPER_CLASS(clazz))
if(isWrapper && IS_SLIM_WRAPPER_OBJECT(obj))
return GetSlimWrapperProto(obj)->GetScope();
if(!IS_WRAPPER_CLASS(clazz) ||
!(supports = (nsISupports*) xpc_GetJSPrivate(obj)))
if(!isWrapper || !(supports = (nsISupports*) xpc_GetJSPrivate(obj)))
{
#ifdef DEBUG
{