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