Modified: trunk/Source/WebCore/dom/ChildListMutationScope.cpp (113479 => 113480)
--- trunk/Source/WebCore/dom/ChildListMutationScope.cpp 2012-04-06 19:28:29 UTC (rev 113479)
+++ trunk/Source/WebCore/dom/ChildListMutationScope.cpp 2012-04-06 19:37:20 UTC (rev 113480)
@@ -55,14 +55,14 @@
MutationAccumulator(PassRefPtr<Node>, PassOwnPtr<MutationObserverInterestGroup> observers);
~MutationAccumulator();
- void childrenAdded(const NodeVector&);
+ void childAdded(PassRefPtr<Node>);
void willRemoveChild(PassRefPtr<Node>);
void enqueueMutationRecord();
private:
void clear();
bool isEmpty();
- bool areAddedNodesInOrder(const NodeVector&);
+ bool isAddedNodeInOrder(Node*);
bool isRemovedNodeInOrder(Node*);
RefPtr<Node> m_target;
@@ -87,27 +87,26 @@
ASSERT(isEmpty());
}
-inline bool ChildListMutationScope::MutationAccumulator::areAddedNodesInOrder(const NodeVector& children)
+inline bool ChildListMutationScope::MutationAccumulator::isAddedNodeInOrder(Node* child)
{
- return isEmpty() || (m_lastAdded == children.first()->previousSibling() && m_nextSibling == children.last()->nextSibling());
+ return isEmpty() || (m_lastAdded == child->previousSibling() && m_nextSibling == child->nextSibling());
}
-void ChildListMutationScope::MutationAccumulator::childrenAdded(const NodeVector& children)
+void ChildListMutationScope::MutationAccumulator::childAdded(PassRefPtr<Node> prpChild)
{
- ASSERT(!children.isEmpty());
+ RefPtr<Node> child = prpChild;
- if (!areAddedNodesInOrder(children)) {
- ASSERT_NOT_REACHED();
+ ASSERT(isAddedNodeInOrder(child.get()));
+ if (!isAddedNodeInOrder(child.get()))
enqueueMutationRecord();
- }
if (isEmpty()) {
- m_previousSibling = children.first()->previousSibling();
- m_nextSibling = children.last()->nextSibling();
+ m_previousSibling = child->previousSibling();
+ m_nextSibling = child->nextSibling();
}
- m_addedNodes.append(children);
- m_lastAdded = children.last();
+ m_addedNodes.append(child);
+ m_lastAdded = child;
}
inline bool ChildListMutationScope::MutationAccumulator::isRemovedNodeInOrder(Node* child)
@@ -189,14 +188,14 @@
return s_instance;
}
-void ChildListMutationScope::MutationAccumulationRouter::childrenAdded(Node* target, const NodeVector& children)
+void ChildListMutationScope::MutationAccumulationRouter::childAdded(Node* target, Node* child)
{
HashMap<Node*, OwnPtr<ChildListMutationScope::MutationAccumulator> >::iterator iter = m_accumulations.find(target);
ASSERT(iter != m_accumulations.end());
if (iter == m_accumulations.end() || !iter->second)
return;
- iter->second->childrenAdded(children);
+ iter->second->childAdded(child);
}
void ChildListMutationScope::MutationAccumulationRouter::willRemoveChild(Node* target, Node* child)
Modified: trunk/Source/WebCore/dom/ChildListMutationScope.h (113479 => 113480)
--- trunk/Source/WebCore/dom/ChildListMutationScope.h 2012-04-06 19:28:29 UTC (rev 113479)
+++ trunk/Source/WebCore/dom/ChildListMutationScope.h 2012-04-06 19:37:20 UTC (rev 113480)
@@ -33,7 +33,6 @@
#if ENABLE(MUTATION_OBSERVERS)
-#include "ContainerNode.h"
#include "Document.h"
#include "Node.h"
#include "WebKitMutationObserver.h"
@@ -59,10 +58,10 @@
MutationAccumulationRouter::instance()->decrementScopingLevel(m_target);
}
- void childrenAdded(const NodeVector& children)
+ void childAdded(Node* child)
{
if (m_target)
- MutationAccumulationRouter::instance()->childrenAdded(m_target, children);
+ MutationAccumulationRouter::instance()->childAdded(m_target, child);
}
void willRemoveChild(Node* child)
@@ -84,7 +83,7 @@
void incrementScopingLevel(Node*);
void decrementScopingLevel(Node*);
- void childrenAdded(Node* target, const NodeVector& children);
+ void childAdded(Node* target, Node* child);
void willRemoveChild(Node* target, Node* child);
private:
Modified: trunk/Source/WebCore/dom/ContainerNode.cpp (113479 => 113480)
--- trunk/Source/WebCore/dom/ContainerNode.cpp 2012-04-06 19:28:29 UTC (rev 113479)
+++ trunk/Source/WebCore/dom/ContainerNode.cpp 2012-04-06 19:37:20 UTC (rev 113480)
@@ -50,7 +50,7 @@
static void notifyChildInserted(Node*);
static void dispatchChildInsertionEvents(Node*);
static void dispatchChildRemovalEvents(Node*);
-static void notifyChildrenInserted(PassRefPtr<ContainerNode>, const NodeVector&, bool shouldLazyAttach);
+static void updateTreeAfterInsertion(ContainerNode*, Node*, bool shouldLazyAttach);
typedef pair<RefPtr<Node>, unsigned> CallbackParameters;
typedef pair<NodeCallback, CallbackParameters> CallbackInfo;
@@ -121,7 +121,7 @@
// If it is, it can be deleted as a side effect of sending mutation events.
ASSERT(refCount() || parentOrHostNode());
- RefPtr<ContainerNode> protect(this);
+ RefPtr<Node> protect(this);
ec = 0;
@@ -152,33 +152,34 @@
if (targets.isEmpty())
return true;
- // Due to arbitrary code running in response to a DOM mutation event it's
- // possible that "next" is no longer a child of "this".
- if (next->parentNode() != this)
- return true;
-
#if ENABLE(INSPECTOR)
InspectorInstrumentation::willInsertDOMNode(document(), this);
#endif
- forbidEventDispatch();
- for (size_t i = 0; i < targets.size(); ++i) {
- Node* child = targets[i].get();
+#if ENABLE(MUTATION_OBSERVERS)
+ ChildListMutationScope mutation(this);
+#endif
+ for (NodeVector::const_iterator it = targets.begin(); it != targets.end(); ++it) {
+ Node* child = it->get();
+
// Due to arbitrary code running in response to a DOM mutation event it's
- // possible that "child" has been inserted elsewhere.
- if (child->parentNode()) {
- targets.resize(i);
+ // possible that "next" is no longer a child of "this".
+ // It's also possible that "child" has been inserted elsewhere.
+ // In either of those cases, we'll just stop.
+ if (next->parentNode() != this)
break;
- }
+ if (child->parentNode())
+ break;
treeScope()->adoptIfNeeded(child);
insertBeforeCommon(next.get(), child);
+
+ updateTreeAfterInsertion(this, child, shouldLazyAttach);
}
- allowEventDispatch();
- notifyChildrenInserted(protect.release(), targets, shouldLazyAttach);
+ dispatchSubtreeModifiedEvent();
return true;
}
@@ -239,7 +240,7 @@
// If it is, it can be deleted as a side effect of sending mutation events.
ASSERT(refCount() || parentOrHostNode());
- RefPtr<ContainerNode> protect(this);
+ RefPtr<Node> protect(this);
ec = 0;
@@ -277,36 +278,37 @@
if (ec)
return false;
- // Due to arbitrary code running in response to a DOM mutation event it's
- // possible that "next" is no longer a child of "this".
- if (next && next->parentNode() != this)
- return true;
-
#if ENABLE(INSPECTOR)
InspectorInstrumentation::willInsertDOMNode(document(), this);
#endif
- forbidEventDispatch();
- for (size_t i = 0; i < targets.size(); ++i) {
- Node* child = targets[i].get();
+ // Add the new child(ren)
+ for (NodeVector::const_iterator it = targets.begin(); it != targets.end(); ++it) {
+ Node* child = it->get();
// Due to arbitrary code running in response to a DOM mutation event it's
- // possible that "child" has been inserted elsewhere.
- if (child->parentNode()) {
- targets.resize(i);
+ // possible that "next" is no longer a child of "this".
+ // It's also possible that "child" has been inserted elsewhere.
+ // In either of those cases, we'll just stop.
+ if (next && next->parentNode() != this)
break;
- }
+ if (child->parentNode())
+ break;
treeScope()->adoptIfNeeded(child);
+ // Add child before "next".
+ forbidEventDispatch();
if (next)
insertBeforeCommon(next.get(), child);
else
appendChildToContainer(child, this);
+ allowEventDispatch();
+
+ updateTreeAfterInsertion(this, child, shouldLazyAttach);
}
- allowEventDispatch();
- notifyChildrenInserted(protect.release(), targets, shouldLazyAttach);
+ dispatchSubtreeModifiedEvent();
return true;
}
@@ -560,25 +562,31 @@
InspectorInstrumentation::willInsertDOMNode(document(), this);
#endif
- forbidEventDispatch();
- for (size_t i = 0; i < targets.size(); ++i) {
- Node* child = targets[i].get();
+#if ENABLE(MUTATION_OBSERVERS)
+ ChildListMutationScope mutation(this);
+#endif
+ // Now actually add the child(ren)
+ for (NodeVector::const_iterator it = targets.begin(); it != targets.end(); ++it) {
+ Node* child = it->get();
+
// If the child has a parent again, just stop what we're doing, because
// that means someone is doing something with DOM mutation -- can't re-parent
// a child that already has a parent.
- if (child->parentNode()) {
- targets.resize(i);
+ if (child->parentNode())
break;
- }
treeScope()->adoptIfNeeded(child);
+ // Append child to the end of the list
+ forbidEventDispatch();
appendChildToContainer(child, this);
+ allowEventDispatch();
+
+ updateTreeAfterInsertion(this, child, shouldLazyAttach);
}
- allowEventDispatch();
- notifyChildrenInserted(protect.release(), targets, shouldLazyAttach);
+ dispatchSubtreeModifiedEvent();
return true;
}
@@ -1029,6 +1037,13 @@
RefPtr<Node> c = child;
RefPtr<Document> document = child->document();
+#if ENABLE(MUTATION_OBSERVERS)
+ if (c->parentNode()) {
+ ChildListMutationScope mutation(c->parentNode());
+ mutation.childAdded(c.get());
+ }
+#endif
+
if (c->parentNode() && document->hasListenerType(Document::DOMNODEINSERTED_LISTENER))
c->dispatchScopedEvent(MutationEvent::create(eventNames().DOMNodeInsertedEvent, true, c->parentNode()));
@@ -1072,36 +1087,25 @@
}
}
-static void notifyChildrenInserted(PassRefPtr<ContainerNode> parent, const NodeVector& children, bool shouldLazyAttach)
+static void updateTreeAfterInsertion(ContainerNode* parent, Node* child, bool shouldLazyAttach)
{
- if (children.isEmpty())
- return;
+ ASSERT(parent->refCount());
+ ASSERT(child->refCount());
-#if ENABLE(MUTATION_OBSERVERS)
- ChildListMutationScope(parent.get()).childrenAdded(children);
-#endif
+ parent->childrenChanged(false, child->previousSibling(), child->nextSibling(), 1);
- parent->childrenChanged(false, children.first()->previousSibling(), children.last()->nextSibling(), children.size());
+ notifyChildInserted(child);
- for (size_t i = 0; i < children.size(); ++i) {
- Node* child = children[i].get();
- notifyChildInserted(child);
-
- // FIXME: Attachment should be the first operation in this function, but some code
- // (for example, HTMLFormControlElement's autofocus support) requires this ordering.
- if (parent->attached() && !child->attached() && child->parentNode() == parent) {
- if (shouldLazyAttach)
- child->lazyAttach();
- else
- child->attach();
- }
-
- // Now that the child is attached to the render tree, dispatch
- // the relevant mutation events.
- dispatchChildInsertionEvents(child);
+ // FIXME: Attachment should be the first operation in this function, but some code
+ // (for example, HTMLFormControlElement's autofocus support) requires this ordering.
+ if (parent->attached() && !child->attached() && child->parentNode() == parent) {
+ if (shouldLazyAttach)
+ child->lazyAttach();
+ else
+ child->attach();
}
- parent->dispatchSubtreeModifiedEvent();
+ dispatchChildInsertionEvents(child);
}
} // namespace WebCore