fix bug 59751 and bug 84600. This adds an AutoMarkingPtr scheme to protect partially built objects from gc. Also make sure we don't allow JS object to implement non-scriptable interfaces. r=dbradley sr=brendan a=drivers

git-svn-id: svn://10.0.0.236/trunk@97027 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
jband%netscape.com 2001-06-13 01:22:32 +00:00
parent af67a36bda
commit 36346e8f41
15 changed files with 277 additions and 57 deletions

View File

@ -591,8 +591,8 @@ nsXPConnect::GetWrappedNativeOfNativeObject(JSContext * aJSContext,
if(!scope)
return UnexpectedFailure(NS_ERROR_FAILURE);
XPCNativeInterface* iface =
XPCNativeInterface::GetNewOrUsed(ccx, &aIID);
AutoMarkingNativeInterfacePtr iface(ccx);
iface = XPCNativeInterface::GetNewOrUsed(ccx, &aIID);
if(!iface)
return NS_ERROR_FAILURE;
@ -899,9 +899,9 @@ nsXPConnect::GetWrappedNativePrototype(JSContext * aJSContext,
XPCNativeScriptableCreateInfo sciProto;
XPCWrappedNative::GatherProtoScriptableCreateInfo(aClassInfo, &sciProto);
XPCWrappedNativeProto* proto =
XPCWrappedNativeProto::GetNewOrUsed(ccx, scope, aClassInfo,
&sciProto, JS_FALSE);
AutoMarkingWrappedNativeProtoPtr proto(ccx);
proto = XPCWrappedNativeProto::GetNewOrUsed(ccx, scope, aClassInfo,
&sciProto, JS_FALSE);
if(!proto)
return UnexpectedFailure(NS_ERROR_FAILURE);

View File

@ -1731,9 +1731,8 @@ nsXPCComponents::AttachNewComponentsObject(XPCCallContext& ccx,
nsCOMPtr<nsIXPCComponents> cholder(components);
// XXX this should not be needed when we get a nsIClassInfo
XPCNativeInterface* iface =
XPCNativeInterface::GetNewOrUsed(ccx, &NS_GET_IID(nsIXPCComponents));
AutoMarkingNativeInterfacePtr iface(ccx);
iface = XPCNativeInterface::GetNewOrUsed(ccx, &NS_GET_IID(nsIXPCComponents));
if(!iface)
return JS_FALSE;

View File

@ -785,8 +785,8 @@ XPCConvert::NativeInterface2JSObject(XPCCallContext& ccx,
if(!xpcscope)
return JS_FALSE;
XPCNativeInterface* iface =
XPCNativeInterface::GetNewOrUsed(ccx, iid);
AutoMarkingNativeInterfacePtr iface(ccx);
iface = XPCNativeInterface::GetNewOrUsed(ccx, iid);
if(!iface)
return JS_FALSE;
@ -827,7 +827,6 @@ XPCConvert::JSObject2NativeInterface(XPCCallContext& ccx,
nsISupports* iface;
if(!aOuter)
{
// Note that if we have a non-null aOuter then it means that we are

View File

@ -85,4 +85,6 @@ class nsXPCComponents_Exception;
class nsXPCComponents_Constructor;
class nsXPCConstructor;
class AutoMarkingPtr;
#endif /* xpcforwards_h___ */

View File

@ -190,6 +190,12 @@ XPCCallContext::GetSet() const
return mSet;
}
inline JSBool
XPCCallContext::CanGetInterface() const
{
return mState >= HAVE_NAME;
}
inline XPCNativeInterface*
XPCCallContext::GetInterface() const
{

View File

@ -494,8 +494,8 @@ nsJSIID::NewResolve(nsIXPConnectWrappedNative *wrapper,
{
XPCCallContext ccx(JS_CALLER, cx);
XPCNativeInterface* iface =
XPCNativeInterface::GetNewOrUsed(ccx, mDetails.GetID());
AutoMarkingNativeInterfacePtr iface(ccx);
iface = XPCNativeInterface::GetNewOrUsed(ccx, mDetails.GetID());
if(!iface)
return NS_OK;
@ -532,8 +532,8 @@ nsJSIID::Enumerate(nsIXPConnectWrappedNative *wrapper,
XPCCallContext ccx(JS_CALLER, cx);
XPCNativeInterface* iface =
XPCNativeInterface::GetNewOrUsed(ccx, mDetails.GetID());
AutoMarkingNativeInterfacePtr iface(ccx);
iface = XPCNativeInterface::GetNewOrUsed(ccx, mDetails.GetID());
if(!iface)
return NS_OK;
@ -591,8 +591,8 @@ nsJSIID::HasInstance(nsIXPConnectWrappedNative *wrapper,
// Otherwise, we'll end up Querying the native object to be sure.
XPCCallContext ccx(JS_CALLER, cx);
XPCNativeInterface* iface =
XPCNativeInterface::GetNewOrUsed(ccx, mDetails.GetID());
AutoMarkingNativeInterfacePtr iface(ccx);
iface = XPCNativeInterface::GetNewOrUsed(ccx, mDetails.GetID());
if(iface && other_wrapper->FindTearOff(ccx, iface))
*bp = JS_TRUE;

View File

@ -224,6 +224,27 @@ JSBool XPCJSRuntime::GCCallback(JSContext *cx, JSGCStatus status)
{
NS_ASSERTION(!self->mDoingFinalization, "bad state");
// Skip this part if XPConnect is shutting down. We get into
// bad locking problems with the thread iteration otherwise.
if(!self->GetXPConnect()->IsShuttingDown())
{
PRLock* threadLock = XPCPerThreadData::GetLock();
if(threadLock)
{ // scoped lock
nsAutoLock lock(threadLock);
XPCPerThreadData* iterp = nsnull;
XPCPerThreadData* thread;
while(nsnull != (thread =
XPCPerThreadData::IterateThreads(&iterp)))
{
// Mark those AutoMarkingPtr lists!
thread->MarkAutoRootsBeforeJSFinalize(cx);
}
}
}
dyingWrappedJSArray = &self->mWrappedJSToReleaseArray;
{
XPCLock* lock = self->GetMainThreadOnlyGC() ?
@ -242,7 +263,10 @@ JSBool XPCJSRuntime::GCCallback(JSContext *cx, JSGCStatus status)
Enumerate(WrappedJSDyingJSObjectFinder, &data);
}
// Do cleanup in NativeInterfaces
// Do cleanup in NativeInterfaces. This part just finds
// member cloned function objects that are about to be
// collected. It does not deal with collection of interfaces or
// sets at this point.
CX_AND_XPCRT_Data data = {cx, self};
self->mIID2NativeInterfaceMap->
@ -293,9 +317,12 @@ JSBool XPCJSRuntime::GCCallback(JSContext *cx, JSGCStatus status)
while(nsnull != (thread =
XPCPerThreadData::IterateThreads(&iterp)))
{
// Mark those AutoMarkingPtr lists!
thread->MarkAutoRootsAfterJSFinalize();
XPCCallContext* ccxp = thread->GetCallContext();
while(ccxp)
{
{
// Deal with the strictness of callcontext that
// complains if you ask for a set when
// it is in a state where the set could not
@ -306,6 +333,12 @@ JSBool XPCJSRuntime::GCCallback(JSContext *cx, JSGCStatus status)
if(set)
set->Mark();
}
if(ccxp->CanGetInterface())
{
XPCNativeInterface* iface = ccxp->GetInterface();
if(iface)
iface->Mark();
}
ccxp = ccxp->GetPrevCallContext();
}
}
@ -601,16 +634,25 @@ XPCJSRuntime::~XPCJSRuntime()
if(mThisTranslatorMap)
{
#ifdef XPC_DUMP_AT_SHUTDOWN
uint32 count = mThisTranslatorMap->Count();
if(count)
printf("deleting XPCJSRuntime with %d live ThisTranslator\n", (int)count);
#endif
delete mThisTranslatorMap;
}
#ifdef XPC_CHECK_WRAPPERS_AT_SHUTDOWN
if(DEBUG_WrappedNativeHashtable)
{
int LiveWrapperCount = 0;
JS_DHashTableEnumerate(DEBUG_WrappedNativeHashtable,
DEBUG_WrapperChecker, &LiveWrapperCount);
if(LiveWrapperCount)
printf("deleting XPCJSRuntime with %d live XPCWrappedNative (found in wrapper check)\n", (int)LiveWrapperCount);
JS_DHashTableDestroy(DEBUG_WrappedNativeHashtable);
#endif
delete mThisTranslatorMap;
}
#endif
if(mNativeScriptableSharedMap)
{

View File

@ -598,7 +598,7 @@ XPCNativeScriptableSharedMap::GetNewOrUsed(JSUint32 flags,
return JS_FALSE;
shared->PopulateJSClass();
}
si->GetScriptableShared(shared);
si->SetScriptableShared(shared);
return JS_TRUE;
}

View File

@ -675,7 +675,6 @@ private:
LangType mCallingLangType;
};
/***************************************************************************/
#define NATIVE_CALLER XPCContext::LANG_NATIVE
@ -741,6 +740,7 @@ public:
inline XPCNativeScriptableInfo* GetScriptableInfo() const ;
inline JSBool CanGetSet() const ;
inline XPCNativeSet* GetSet() const ;
inline JSBool CanGetInterface() const ;
inline XPCNativeInterface* GetInterface() const ;
inline XPCNativeMember* GetMember() const ;
inline JSBool HasInterfaceAndMember() const ;
@ -810,6 +810,9 @@ private:
JSBool mContextPopRequired;
XPCContext::LangType mCallerLanguage;
// ctor does not necessarily init the following. BEWARE!
XPCContext::LangType mPrevCallerLanguage;
XPCCallContext* mPrevCallContext;
@ -1088,6 +1091,9 @@ public:
JSBool IsMarked() const
{return 0 != (mMemberCount & XPC_NATIVE_IFACE_MARK_FLAG);}
// NOP. This is just here to make the AutoMarkingPtr code compile.
inline void MarkBeforeJSFinalize(JSContext*) {};
static void DestroyInstance(JSContext* cx, XPCJSRuntime* rt,
XPCNativeInterface* inst);
@ -1210,6 +1216,10 @@ public:
#define XPC_NATIVE_SET_MARK_FLAG ((PRUint16)JS_BIT(15)) // only high bit of 16 is set
inline void Mark();
// NOP. This is just here to make the AutoMarkingPtr code compile.
inline void MarkBeforeJSFinalize(JSContext*) {};
private:
void MarkSelfOnly() {mInterfaceCount |= XPC_NATIVE_SET_MARK_FLAG;}
public:
@ -1378,7 +1388,9 @@ public:
SetCallback(nsIXPCScriptable* s) {mCallback = s;}
void
GetScriptableShared(XPCNativeScriptableShared* shared) {mShared = shared;}
SetScriptableShared(XPCNativeScriptableShared* shared) {mShared = shared;}
void Mark() {if(mShared) mShared->Mark();}
protected:
XPCNativeScriptableInfo(nsIXPCScriptable* scriptable = nsnull,
@ -1499,9 +1511,16 @@ public:
void DebugDump(PRInt16 depth);
// This is called in the 'early' phase by AutoMarkingWrappedNativeProtoPtr.
// 'early' meaning after JSGC_MARK_END and before JSGC_FINALIZE_END.
// At this point in time we can still mark JSObjects in the JS gc heap.
void MarkBeforeJSFinalize(JSContext* cx)
{if(mJSProtoObject)
JS_MarkGCThing(cx, mJSProtoObject,
"XPCWrappedNativeProto::mJSProtoObject", nsnull);}
void Mark() const
{mSet->Mark();
if(mScriptableInfo) mScriptableInfo->GetScriptableShared()->Mark();}
{mSet->Mark();
if(mScriptableInfo) mScriptableInfo->Mark();}
#ifdef DEBUG
void ASSERT_SetNotMarked() const {mSet->ASSERT_NotMarked();}
@ -1641,7 +1660,7 @@ public:
GetProto() const {return HasProto() ? mMaybeProto : nsnull;}
XPCWrappedNativeScope*
GetScope() const { return HasProto() ?
GetScope() const {return HasProto() ?
mMaybeProto->GetScope() : UnTagScope(mMaybeScope);}
nsISupports*
@ -1764,9 +1783,12 @@ public:
void
Mark() const
{mSet->Mark();
if(mScriptableInfo) mScriptableInfo->GetScriptableShared()->Mark();
if(mScriptableInfo) mScriptableInfo->Mark();
if(HasProto()) mMaybeProto->Mark();}
// NOP. This is just here to make the AutoMarkingPtr code compile.
inline void MarkBeforeJSFinalize(JSContext*) {};
#ifdef DEBUG
void ASSERT_SetsNotMarked() const
{mSet->ASSERT_NotMarked();
@ -2530,6 +2552,11 @@ public:
void ClearRecentContext()
{mMostRecentJSContext = nsnull; mMostRecentXPCContext = nsnull;}
AutoMarkingPtr** GetAutoRootsAdr() {return &mAutoRoots;}
void MarkAutoRootsBeforeJSFinalize(JSContext* cx);
void MarkAutoRootsAfterJSFinalize();
#ifdef XPC_CHECK_WRAPPER_THREADSAFETY
JSUint32 IncrementWrappedNativeThreadsafetyReportDepth()
{return ++mWrappedNativeThreadsafetyReportDepth;}
@ -2553,6 +2580,8 @@ private:
nsIExceptionManager* mExceptionManager;
nsIException* mException;
JSBool mExceptionManagerNotAvailable;
AutoMarkingPtr* mAutoRoots;
#ifdef XPC_CHECK_WRAPPER_THREADSAFETY
JSUint32 mWrappedNativeThreadsafetyReportDepth;
#endif
@ -2823,6 +2852,88 @@ private:
jsval mCheck;
};
/***************************************************************************/
// AutoMarkingPtr is the base class for the various AutoMarking pointer types
// below. This system allows us to temporarily protect instances of our garbage
// collected types after they are constructed but before they are safely
// attached to other rooted objects.
// This base class has pure virtual support for marking.
class AutoMarkingPtr
{
public:
AutoMarkingPtr(XPCCallContext& ccx)
: mNext(nsnull), mTLS(ccx.GetThreadData()) {Link();}
virtual ~AutoMarkingPtr() {Unlink();}
void Link()
{if(!mTLS) return;
AutoMarkingPtr** list = mTLS->GetAutoRootsAdr();
mNext = *list; *list = this;}
void Unlink()
{if(!mTLS) return;
AutoMarkingPtr** cur = mTLS->GetAutoRootsAdr();
while(*cur != this) {
NS_ASSERTION(*cur, "This object not in list!");
cur = &(*cur)->mNext;
}
*cur = mNext;
mTLS = nsnull;
}
virtual void MarkBeforeJSFinalize(JSContext* cx) = 0;
virtual void MarkAfterJSFinalize() = 0;
protected:
AutoMarkingPtr* mNext;
XPCPerThreadData* mTLS;
};
// More joy of macros...
#define DEFINE_AUTO_MARKING_PTR_TYPE(class_, type_) \
class class_ : public AutoMarkingPtr \
{ \
public: \
class_ (XPCCallContext& ccx, type_ * ptr = nsnull) \
: AutoMarkingPtr(ccx), mPtr(ptr) {} \
virtual ~ class_ () {} \
\
virtual void MarkBeforeJSFinalize(JSContext* cx) \
{if(mPtr) mPtr->MarkBeforeJSFinalize(cx); \
if(mNext) mNext->MarkBeforeJSFinalize(cx);} \
\
virtual void MarkAfterJSFinalize() \
{if(mPtr) mPtr->Mark(); \
if(mNext) mNext->MarkAfterJSFinalize();} \
\
type_ * get() const {return mPtr;} \
operator type_ *() const {return mPtr;} \
type_ * operator->() const {return mPtr;} \
\
class_ & operator =(type_ * p) \
{mPtr = p; return *this;} \
\
protected: \
type_ * mPtr; \
};
// Use the macro above to define our AutoMarking types...
DEFINE_AUTO_MARKING_PTR_TYPE(AutoMarkingNativeInterfacePtr, XPCNativeInterface)
DEFINE_AUTO_MARKING_PTR_TYPE(AutoMarkingNativeSetPtr, XPCNativeSet)
DEFINE_AUTO_MARKING_PTR_TYPE(AutoMarkingWrappedNativePtr, XPCWrappedNative)
DEFINE_AUTO_MARKING_PTR_TYPE(AutoMarkingWrappedNativeProtoPtr, XPCWrappedNativeProto)
// Note: It looked like I would need one of these AutoMarkingPtr types for
// XPCNativeScriptableInfo in order to manage marking its
// XPCNativeScriptableShared member during construction. But AFAICT we build
// these and bind them to rooted things so immediately that this just is not
// needed.
/***************************************************************************/
// Inlines use the above - include last.

View File

@ -346,7 +346,8 @@ XPCPerThreadData::XPCPerThreadData()
mMostRecentXPCContext(nsnull),
mExceptionManager(nsnull),
mException(nsnull),
mExceptionManagerNotAvailable(JS_FALSE)
mExceptionManagerNotAvailable(JS_FALSE),
mAutoRoots(nsnull)
#ifdef XPC_CHECK_WRAPPER_THREADSAFETY
, mWrappedNativeThreadsafetyReportDepth(0)
#endif
@ -362,6 +363,8 @@ XPCPerThreadData::XPCPerThreadData()
void
XPCPerThreadData::Cleanup()
{
while(mAutoRoots)
mAutoRoots->Unlink();
NS_IF_RELEASE(mExceptionManager);
NS_IF_RELEASE(mException);
delete mJSContextStack;
@ -411,6 +414,18 @@ xpc_ThreadDataDtorCB(void* ptr)
delete data;
}
void XPCPerThreadData::MarkAutoRootsBeforeJSFinalize(JSContext* cx)
{
if(mAutoRoots)
mAutoRoots->MarkBeforeJSFinalize(cx);
}
void XPCPerThreadData::MarkAutoRootsAfterJSFinalize()
{
if(mAutoRoots)
mAutoRoots->MarkAfterJSFinalize();
}
// static
XPCPerThreadData*
XPCPerThreadData::GetData()
@ -513,4 +528,3 @@ XPCPerThreadData::IterateThreads(XPCPerThreadData** iteratorp)
*iteratorp = (*iteratorp == nsnull) ? gThreads : (*iteratorp)->mNextThread;
return *iteratorp;
}

View File

@ -102,7 +102,9 @@ nsXPCWrappedJSClass::GetNewOrUsed(XPCCallContext& ccx, REFNSIID aIID,
nsCOMPtr<nsIInterfaceInfo> info;
if(NS_SUCCEEDED(iimgr->GetInfoForIID(&aIID, getter_AddRefs(info))))
{
if(nsXPConnect::IsISupportsDescendant(info))
PRBool canScript;
if(NS_SUCCEEDED(info->IsScriptable(&canScript)) && canScript &&
nsXPConnect::IsISupportsDescendant(info))
{
clazz = new nsXPCWrappedJSClass(ccx, aIID, info);
if(!clazz->mDescriptors)
@ -198,6 +200,25 @@ nsXPCWrappedJSClass::CallQueryInterfaceOnJSObject(XPCCallContext& ccx,
if(!OBJ_GET_PROPERTY(cx, jsobj, funid, &fun) || JSVAL_IS_PRIMITIVE(fun))
return nsnull;
// Ensure that we are asking for a scriptable interface.
// We so often ask for nsISupports that we can short-circuit the test...
if(!aIID.Equals(NS_GET_IID(nsISupports)))
{
nsCOMPtr<nsIInterfaceInfoManager> iimgr;
nsXPConnect::GetInterfaceInfoManager(getter_AddRefs(iimgr));
if(!iimgr)
return nsnull;
nsCOMPtr<nsIInterfaceInfo> info;
iimgr->GetInfoForIID(&aIID, getter_AddRefs(info));
if(!info)
return nsnull;
PRBool canScript;
if(NS_FAILED(info->IsScriptable(&canScript)) || !canScript)
return nsnull;
}
// OK, it looks like we'll be calling into JS code.
DoPreScriptEvaluated(cx);
// XXX we should install an error reporter that will sent reports to

View File

@ -74,6 +74,8 @@ static void DEBUG_TrackNewWrapper(XPCWrappedNative* wrapper)
#ifdef XPC_CHECK_WRAPPERS_AT_SHUTDOWN
if(wrapper->GetRuntime())
wrapper->GetRuntime()->DEBUG_AddWrappedNative(wrapper);
else
NS_ERROR("failed to add wrapper");
#endif
#ifdef XPC_TRACK_WRAPPER_STATS
DEBUG_TotalWrappedNativeCount++;
@ -103,6 +105,8 @@ static void DEBUG_TrackDeleteWrapper(XPCWrappedNative* wrapper)
#ifdef XPC_CHECK_WRAPPERS_AT_SHUTDOWN
if(wrapper->GetRuntime())
wrapper->GetRuntime()->DEBUG_RemoveWrappedNative(wrapper);
else
NS_ERROR("failed to remove wrapper");
#endif
#ifdef XPC_TRACK_WRAPPER_STATS
DEBUG_TotalLiveWrappedNativeCount--;
@ -210,13 +214,19 @@ XPCWrappedNative::GetNewOrUsed(XPCCallContext& ccx,
}
XPCLock* mapLock = Scope->GetRuntime()->GetMapLock();
XPCWrappedNative* wrapper;
// We use an AutoMarkingPtr here because it is possible for JS gc to happen
// after we have Init'd the wrapper but *before* we add it to the hashtable.
// This would cause the mSet to get collected and we'd later crash. I've
// *seen* this happen.
AutoMarkingWrappedNativePtr wrapper(ccx);
Native2WrappedNativeMap* map = Scope->GetWrappedNativeMap();
{ // scoped lock
XPCAutoLock lock(mapLock);
wrapper = map->Find(identity);
NS_IF_ADDREF(wrapper);
if(wrapper)
wrapper->AddRef();
}
if(wrapper)
@ -282,7 +292,8 @@ XPCWrappedNative::GetNewOrUsed(XPCCallContext& ccx,
{ // scoped lock
XPCAutoLock lock(mapLock);
wrapper = map->Find(identity);
NS_IF_ADDREF(wrapper);
if(wrapper)
wrapper->AddRef();
}
if(wrapper)
@ -299,7 +310,7 @@ XPCWrappedNative::GetNewOrUsed(XPCCallContext& ccx,
}
}
XPCWrappedNativeProto* proto = nsnull;
AutoMarkingWrappedNativeProtoPtr proto(ccx);
// If there is nsIClassInfo then we use a wrapper that needs a prototype.
@ -319,8 +330,8 @@ XPCWrappedNative::GetNewOrUsed(XPCCallContext& ccx,
}
else
{
XPCNativeSet* set =
XPCNativeSet::GetNewOrUsed(ccx, nsnull, Interface, 0);
AutoMarkingNativeSetPtr set(ccx);
set = XPCNativeSet::GetNewOrUsed(ccx, nsnull, Interface, 0);
if(!set)
return NS_ERROR_FAILURE;
@ -979,8 +990,8 @@ XPCWrappedNative::ReparentWrapperIfFound(XPCCallContext& ccx,
{
// Oh, so now we need to move the wrapper to a different scope.
XPCWrappedNativeProto* oldProto = nsnull;
XPCWrappedNativeProto* newProto = nsnull;
AutoMarkingWrappedNativeProtoPtr oldProto(ccx);
AutoMarkingWrappedNativeProtoPtr newProto(ccx);
if(wrapper->HasProto())
{
@ -1175,9 +1186,9 @@ XPCWrappedNative::ExtendSet(XPCCallContext& ccx, XPCNativeInterface* aInterface)
if(!mSet->HasInterface(aInterface))
{
XPCNativeSet* newSet =
XPCNativeSet::GetNewOrUsed(ccx, mSet, aInterface,
mSet->GetInterfaceCount());
AutoMarkingNativeSetPtr newSet(ccx);
newSet = XPCNativeSet::GetNewOrUsed(ccx, mSet, aInterface,
mSet->GetInterfaceCount());
if(!newSet)
return JS_FALSE;

View File

@ -171,8 +171,8 @@ XPCNativeMember::Resolve(XPCCallContext& ccx, XPCNativeInterface* iface)
XPCNativeInterface*
XPCNativeInterface::GetNewOrUsed(XPCCallContext& ccx, const nsIID* iid)
{
AutoMarkingNativeInterfacePtr iface(ccx);
XPCJSRuntime* rt = ccx.GetRuntime();
XPCNativeInterface* iface;
IID2NativeInterfaceMap* map = rt->GetIID2NativeInterfaceMap();
if(!map)
@ -222,7 +222,7 @@ XPCNativeInterface::GetNewOrUsed(XPCCallContext& ccx, const nsIID* iid)
XPCNativeInterface*
XPCNativeInterface::GetNewOrUsed(XPCCallContext& ccx, nsIInterfaceInfo* info)
{
XPCNativeInterface* iface;
AutoMarkingNativeInterfacePtr iface(ccx);
const nsIID* iid;
if(NS_FAILED(info->GetIIDShared(&iid)) || !iid)
@ -502,9 +502,10 @@ XPCNativeInterface::DebugDump(PRInt16 depth)
XPCNativeSet*
XPCNativeSet::GetNewOrUsed(XPCCallContext& ccx, const nsIID* iid)
{
XPCNativeSet* set;
AutoMarkingNativeSetPtr set(ccx);
XPCNativeInterface* iface = XPCNativeInterface::GetNewOrUsed(ccx, iid);
AutoMarkingNativeInterfacePtr iface(ccx);
iface = XPCNativeInterface::GetNewOrUsed(ccx, iid);
if(!iface)
return nsnull;
@ -523,7 +524,9 @@ XPCNativeSet::GetNewOrUsed(XPCCallContext& ccx, const nsIID* iid)
if(set)
return set;
set = NewInstance(ccx, &iface, 1);
// hacky way to get a XPCNativeInterface** using the AutoPtr
XPCNativeInterface* temp[] = {iface};
set = NewInstance(ccx, temp, 1);
if(!set)
return nsnull;
@ -550,7 +553,7 @@ XPCNativeSet::GetNewOrUsed(XPCCallContext& ccx, const nsIID* iid)
XPCNativeSet*
XPCNativeSet::GetNewOrUsed(XPCCallContext& ccx, nsIClassInfo* classInfo)
{
XPCNativeSet* set;
AutoMarkingNativeSetPtr set(ccx);
XPCJSRuntime* rt = ccx.GetRuntime();
ClassInfo2NativeSetMap* map = rt->GetClassInfo2NativeSetMap();
@ -598,8 +601,8 @@ XPCNativeSet::GetNewOrUsed(XPCCallContext& ccx, nsIClassInfo* classInfo)
{
nsIID* iid = *(currentIID++);
XPCNativeInterface* iface =
XPCNativeInterface::GetNewOrUsed(ccx, iid);
AutoMarkingNativeInterfacePtr iface(ccx);
iface = XPCNativeInterface::GetNewOrUsed(ccx, iid);
if(!iface)
{
@ -670,7 +673,7 @@ XPCNativeSet::GetNewOrUsed(XPCCallContext& ccx,
XPCNativeInterface* newInterface,
PRUint16 position)
{
XPCNativeSet* set;
AutoMarkingNativeSetPtr set(ccx);
XPCJSRuntime* rt = ccx.GetRuntime();
NativeSetMap* map = rt->GetNativeSetMap();
if(!map)

View File

@ -200,8 +200,9 @@ XPC_WN_DoubleWrappedGetter(JSContext *cx, JSObject *obj,
nsIXPCSecurityManager::HOOK_GET_PROPERTY);
if(sm)
{
XPCNativeInterface* iface = XPCNativeInterface::
GetNewOrUsed(ccx, &NS_GET_IID(nsIXPCWrappedJSObjectGetter));
AutoMarkingNativeInterfacePtr iface(ccx);
iface = XPCNativeInterface::
GetNewOrUsed(ccx, &NS_GET_IID(nsIXPCWrappedJSObjectGetter));
if(iface)
{
@ -315,14 +316,15 @@ DefinePropertyIfFound(XPCCallContext& ccx,
if(wrapperToReflectInterfaceNames)
{
AutoMarkingNativeInterfacePtr iface2(ccx);
XPCWrappedNativeTearOff* to;
JSObject* jso;
if(JSVAL_IS_STRING(idval) &&
nsnull != (name = JS_GetStringBytes(JSVAL_TO_STRING(idval))) &&
nsnull != (iface = XPCNativeInterface::GetNewOrUsed(ccx, name)) &&
(iface2 = XPCNativeInterface::GetNewOrUsed(ccx, name), iface2) &&
nsnull != (to = wrapperToReflectInterfaceNames->
FindTearOff(ccx, iface, JS_TRUE)) &&
FindTearOff(ccx, iface2, JS_TRUE)) &&
nsnull != (jso = to->GetJSObject()))
{
@ -641,6 +643,15 @@ MarkScopeJSObjects(JSContext *cx, XPCWrappedNativeScope* scope, void *arg)
static void
MarkForValidWrapper(JSContext *cx, XPCWrappedNative* wrapper, void *arg)
{
// NOTE: It might be nice to also do the wrapper->Mark() call here too.
// That call marks the wrapper's and wrapper's proto's interface sets.
// We currently do that in the GC callback code. The reason we don't do that
// here is because the bits used in that marking do unpleasant things to the
// member counts in the interface and interface set objects. Those counts
// are used in the DealWithDyingGCThings calls that are part of this JS GC
// marking phase. By doing these calls later during our GC callback we
// avoid that problem. Arguably this could be changed. But it ain't broke.
if(wrapper->HasProto())
{
JSObject* obj = wrapper->GetProto()->GetJSProtoObject();

View File

@ -157,7 +157,7 @@ XPCWrappedNativeProto::GetNewOrUsed(XPCCallContext& ccx,
NS_ASSERTION(Scope, "bad param");
NS_ASSERTION(ClassInfo, "bad param");
XPCWrappedNativeProto* proto;
AutoMarkingWrappedNativeProtoPtr proto(ccx);
ClassInfo2WrappedNativeProtoMap* map;
XPCLock* lock;
JSBool shared;
@ -196,7 +196,8 @@ XPCWrappedNativeProto::GetNewOrUsed(XPCCallContext& ccx,
}
}
XPCNativeSet* set = XPCNativeSet::GetNewOrUsed(ccx, ClassInfo);
AutoMarkingNativeSetPtr set(ccx);
set = XPCNativeSet::GetNewOrUsed(ccx, ClassInfo);
if(!set)
return nsnull;