michael@0: /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* vim: set ts=8 sts=2 et sw=2 tw=80: */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include "nsWrapperCacheInlines.h" michael@0: michael@0: #include "jsproxy.h" michael@0: #include "mozilla/dom/DOMJSProxyHandler.h" michael@0: #include "mozilla/HoldDropJSObjects.h" michael@0: #include "nsCycleCollectionTraversalCallback.h" michael@0: #include "nsCycleCollector.h" michael@0: michael@0: using namespace mozilla; michael@0: using namespace mozilla::dom; michael@0: michael@0: /* static */ void michael@0: nsWrapperCache::HoldJSObjects(void* aScriptObjectHolder, michael@0: nsScriptObjectTracer* aTracer) michael@0: { michael@0: cyclecollector::HoldJSObjectsImpl(aScriptObjectHolder, aTracer); michael@0: } michael@0: michael@0: void michael@0: nsWrapperCache::ReleaseWrapper(void* aScriptObjectHolder) michael@0: { michael@0: if (PreservingWrapper()) { michael@0: // PreserveWrapper puts new DOM bindings in the JS holders hash, but they michael@0: // can also be in the DOM expando hash, so we need to try to remove them michael@0: // from both here. michael@0: JSObject* obj = GetWrapperPreserveColor(); michael@0: if (IsDOMBinding() && obj && js::IsProxy(obj)) { michael@0: DOMProxyHandler::GetAndClearExpandoObject(obj); michael@0: } michael@0: SetPreservingWrapper(false); michael@0: cyclecollector::DropJSObjectsImpl(aScriptObjectHolder); michael@0: } michael@0: } michael@0: michael@0: #ifdef DEBUG michael@0: michael@0: class DebugWrapperTraversalCallback : public nsCycleCollectionTraversalCallback michael@0: { michael@0: public: michael@0: DebugWrapperTraversalCallback(void* aWrapper) michael@0: : mFound(false) michael@0: , mWrapper(aWrapper) michael@0: { michael@0: mFlags = WANT_ALL_TRACES; michael@0: } michael@0: michael@0: NS_IMETHOD_(void) DescribeRefCountedNode(nsrefcnt aRefCount, michael@0: const char* aObjName) michael@0: { michael@0: } michael@0: NS_IMETHOD_(void) DescribeGCedNode(bool aIsMarked, michael@0: const char* aObjName, michael@0: uint64_t aCompartmentAddress) michael@0: { michael@0: } michael@0: michael@0: NS_IMETHOD_(void) NoteJSChild(void* aChild) michael@0: { michael@0: if (aChild == mWrapper) { michael@0: mFound = true; michael@0: } michael@0: } michael@0: NS_IMETHOD_(void) NoteXPCOMChild(nsISupports* aChild) michael@0: { michael@0: } michael@0: NS_IMETHOD_(void) NoteNativeChild(void* aChild, michael@0: nsCycleCollectionParticipant* aHelper) michael@0: { michael@0: } michael@0: michael@0: NS_IMETHOD_(void) NoteNextEdgeName(const char* aName) michael@0: { michael@0: } michael@0: michael@0: bool mFound; michael@0: michael@0: private: michael@0: void* mWrapper; michael@0: }; michael@0: michael@0: static void michael@0: DebugWrapperTraceCallback(void* aP, const char* aName, void* aClosure) michael@0: { michael@0: DebugWrapperTraversalCallback* callback = michael@0: static_cast(aClosure); michael@0: callback->NoteJSChild(aP); michael@0: } michael@0: michael@0: void michael@0: nsWrapperCache::CheckCCWrapperTraversal(void* aScriptObjectHolder, michael@0: nsScriptObjectTracer* aTracer) michael@0: { michael@0: JSObject* wrapper = GetWrapper(); michael@0: if (!wrapper) { michael@0: return; michael@0: } michael@0: michael@0: DebugWrapperTraversalCallback callback(wrapper); michael@0: michael@0: aTracer->Traverse(aScriptObjectHolder, callback); michael@0: MOZ_ASSERT(callback.mFound, michael@0: "Cycle collection participant didn't traverse to preserved " michael@0: "wrapper! This will probably crash."); michael@0: michael@0: callback.mFound = false; michael@0: aTracer->Trace(aScriptObjectHolder, michael@0: TraceCallbackFunc(DebugWrapperTraceCallback), &callback); michael@0: MOZ_ASSERT(callback.mFound, michael@0: "Cycle collection participant didn't trace preserved wrapper! " michael@0: "This will probably crash."); michael@0: } michael@0: michael@0: #endif // DEBUG