Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / core / dom / ChildListMutationScope.cpp
index cce9f6b..de35f9a 100644 (file)
 #include "wtf/HashMap.h"
 #include "wtf/StdLibExtras.h"
 
-namespace WebCore {
+namespace blink {
 
-typedef HashMap<Node*, ChildListMutationAccumulator*> AccumulatorMap;
+// The accumulator map is used to make sure that there is only one mutation
+// accumulator for a given node even if there are multiple ChildListMutationScopes
+// on the stack. The map is always empty when there are no ChildListMutationScopes
+// on the stack.
+typedef WillBeHeapHashMap<RawPtrWillBeMember<Node>, RawPtrWillBeMember<ChildListMutationAccumulator> > AccumulatorMap;
 
 static AccumulatorMap& accumulatorMap()
 {
-    DEFINE_STATIC_LOCAL(AccumulatorMap, map, ());
-    return map;
+    DEFINE_STATIC_LOCAL(OwnPtrWillBePersistent<AccumulatorMap>, map, (adoptPtrWillBeNoop(new AccumulatorMap())));
+    return *map;
 }
 
-ChildListMutationAccumulator::ChildListMutationAccumulator(PassRefPtr<Node> target, PassOwnPtrWillBeRawPtr<MutationObserverInterestGroup> observers)
+ChildListMutationAccumulator::ChildListMutationAccumulator(PassRefPtrWillBeRawPtr<Node> target, PassOwnPtrWillBeRawPtr<MutationObserverInterestGroup> observers)
     : m_target(target)
-    , m_lastAdded(0)
+    , m_lastAdded(nullptr)
     , m_observers(observers)
+    , m_mutationScopes(0)
 {
 }
 
-ChildListMutationAccumulator::~ChildListMutationAccumulator()
+void ChildListMutationAccumulator::leaveMutationScope()
 {
-    if (!isEmpty())
-        enqueueMutationRecord();
-    accumulatorMap().remove(m_target.get());
+    ASSERT(m_mutationScopes > 0);
+    if (!--m_mutationScopes) {
+        if (!isEmpty())
+            enqueueMutationRecord();
+        accumulatorMap().remove(m_target.get());
+    }
 }
 
-PassRefPtr<ChildListMutationAccumulator> ChildListMutationAccumulator::getOrCreate(Node& target)
+DEFINE_EMPTY_DESTRUCTOR_WILL_BE_REMOVED(ChildListMutationAccumulator);
+
+PassRefPtrWillBeRawPtr<ChildListMutationAccumulator> ChildListMutationAccumulator::getOrCreate(Node& target)
 {
-    AccumulatorMap::AddResult result = accumulatorMap().add(&target, 0);
-    RefPtr<ChildListMutationAccumulator> accumulator;
+    AccumulatorMap::AddResult result = accumulatorMap().add(&target, nullptr);
+    RefPtrWillBeRawPtr<ChildListMutationAccumulator> accumulator;
     if (!result.isNewEntry)
         accumulator = result.storedValue->value;
     else {
-        accumulator = adoptRef(new ChildListMutationAccumulator(PassRefPtr<Node>(target), MutationObserverInterestGroup::createForChildListMutation(target)));
+        accumulator = adoptRefWillBeNoop(new ChildListMutationAccumulator(PassRefPtrWillBeRawPtr<Node>(target), MutationObserverInterestGroup::createForChildListMutation(target)));
         result.storedValue->value = accumulator.get();
     }
     return accumulator.release();
@@ -79,11 +89,11 @@ inline bool ChildListMutationAccumulator::isAddedNodeInOrder(Node* child)
     return isEmpty() || (m_lastAdded == child->previousSibling() && m_nextSibling == child->nextSibling());
 }
 
-void ChildListMutationAccumulator::childAdded(PassRefPtr<Node> prpChild)
+void ChildListMutationAccumulator::childAdded(PassRefPtrWillBeRawPtr<Node> prpChild)
 {
     ASSERT(hasObservers());
 
-    RefPtr<Node> child = prpChild;
+    RefPtrWillBeRawPtr<Node> child = prpChild;
 
     if (!isAddedNodeInOrder(child.get()))
         enqueueMutationRecord();
@@ -102,11 +112,11 @@ inline bool ChildListMutationAccumulator::isRemovedNodeInOrder(Node* child)
     return isEmpty() || m_nextSibling == child;
 }
 
-void ChildListMutationAccumulator::willRemoveChild(PassRefPtr<Node> prpChild)
+void ChildListMutationAccumulator::willRemoveChild(PassRefPtrWillBeRawPtr<Node> prpChild)
 {
     ASSERT(hasObservers());
 
-    RefPtr<Node> child = prpChild;
+    RefPtrWillBeRawPtr<Node> child = prpChild;
 
     if (!m_addedNodes.isEmpty() || !isRemovedNodeInOrder(child.get()))
         enqueueMutationRecord();
@@ -126,18 +136,18 @@ void ChildListMutationAccumulator::enqueueMutationRecord()
     ASSERT(hasObservers());
     ASSERT(!isEmpty());
 
-    RefPtr<NodeList> addedNodes = StaticNodeList::adopt(m_addedNodes);
-    RefPtr<NodeList> removedNodes = StaticNodeList::adopt(m_removedNodes);
+    RefPtrWillBeRawPtr<StaticNodeList> addedNodes = StaticNodeList::adopt(m_addedNodes);
+    RefPtrWillBeRawPtr<StaticNodeList> removedNodes = StaticNodeList::adopt(m_removedNodes);
     RefPtrWillBeRawPtr<MutationRecord> record = MutationRecord::createChildList(m_target, addedNodes.release(), removedNodes.release(), m_previousSibling.release(), m_nextSibling.release());
     m_observers->enqueueMutationRecord(record.release());
-    m_lastAdded = 0;
+    m_lastAdded = nullptr;
     ASSERT(isEmpty());
 }
 
 bool ChildListMutationAccumulator::isEmpty()
 {
     bool result = m_removedNodes.isEmpty() && m_addedNodes.isEmpty();
-#ifndef NDEBUG
+#if ENABLE(ASSERT)
     if (result) {
         ASSERT(!m_previousSibling);
         ASSERT(!m_nextSibling);
@@ -147,4 +157,15 @@ bool ChildListMutationAccumulator::isEmpty()
     return result;
 }
 
-} // namespace WebCore
+void ChildListMutationAccumulator::trace(Visitor* visitor)
+{
+    visitor->trace(m_target);
+    visitor->trace(m_removedNodes);
+    visitor->trace(m_addedNodes);
+    visitor->trace(m_previousSibling);
+    visitor->trace(m_nextSibling);
+    visitor->trace(m_lastAdded);
+    visitor->trace(m_observers);
+}
+
+} // namespace blink