Index: Source/core/dom/ContainerNode.cpp |
diff --git a/Source/core/dom/ContainerNode.cpp b/Source/core/dom/ContainerNode.cpp |
index 6ac1cbedb08ff2497b700a66eb89f391dd953afd..fed648dbb0002f7a4a4f906e439df3f33500c162 100644 |
--- a/Source/core/dom/ContainerNode.cpp |
+++ b/Source/core/dom/ContainerNode.cpp |
@@ -278,8 +278,6 @@ void ContainerNode::parserInsertBefore(PassRefPtrWillBeRawPtr<Node> newChild, No |
ASSERT(!newChild->isDocumentFragment()); |
ASSERT(!isHTMLTemplateElement(this)); |
- RefPtrWillBeRawPtr<Node> protect(this); |
- |
if (nextChild.previousSibling() == newChild || &nextChild == newChild) // nothing to do |
return; |
@@ -292,7 +290,9 @@ void ContainerNode::parserInsertBefore(PassRefPtrWillBeRawPtr<Node> newChild, No |
ChildListMutationScope(*this).childAdded(*newChild); |
- notifyNodeInserted(*newChild, InsertedByParser); |
+ childrenChanged(true, newChild->previousSibling(), &nextChild, 1); |
+ |
+ notifyNodeInserted(*newChild); |
} |
void ContainerNode::replaceChild(PassRefPtrWillBeRawPtr<Node> newChild, Node* oldChild, ExceptionState& exceptionState) |
@@ -469,8 +469,8 @@ void ContainerNode::removeChild(Node* oldChild, ExceptionState& exceptionState) |
Node* prev = child->previousSibling(); |
Node* next = child->nextSibling(); |
removeBetween(prev, next, *child); |
- notifyNodeRemoved(*child); |
childrenChanged(false, prev, next, -1); |
+ notifyNodeRemoved(*child); |
} |
dispatchSubtreeModifiedEvent(); |
} |
@@ -505,8 +505,6 @@ void ContainerNode::parserRemoveChild(Node& oldChild) |
ASSERT(oldChild.parentNode() == this); |
ASSERT(!oldChild.isDocumentFragment()); |
- ScriptForbiddenScope forbidScript; |
- |
Node* prev = oldChild.previousSibling(); |
Node* next = oldChild.nextSibling(); |
@@ -516,8 +514,9 @@ void ContainerNode::parserRemoveChild(Node& oldChild) |
oldChild.notifyMutationObserversNodeWillDetach(); |
removeBetween(prev, next, oldChild); |
- notifyNodeRemoved(oldChild); |
+ |
childrenChanged(true, prev, next, -1); |
+ notifyNodeRemoved(oldChild); |
} |
// this differs from other remove functions because it forcibly removes all the children, |
@@ -552,25 +551,23 @@ void ContainerNode::removeChildren() |
document().nodeChildrenWillBeRemoved(*this); |
} |
+ |
+ NodeVector removedChildren; |
{ |
HTMLFrameOwnerElement::UpdateSuspendScope suspendWidgetHierarchyUpdates; |
- ScriptForbiddenScope forbidScript; |
- |
- // FIXME: We can't have a top level NoEventDispatchAssertion since |
- // SVGElement::invalidateInstances() is called inside ::childrenChanged |
- // and will stamp out new <use> shadow trees which mutates the DOM and |
- // hits the event dispatching assert in ::notifyNodeInserted. We should |
- // figure out how to make ths work async. |
- |
- int childCount = 0; |
- while (RefPtrWillBeRawPtr<Node> child = m_firstChild) { |
+ { |
NoEventDispatchAssertion assertNoEventDispatch; |
- ++childCount; |
- removeBetween(0, child->nextSibling(), *child); |
- notifyNodeRemoved(*child); |
+ removedChildren.reserveInitialCapacity(countChildren()); |
+ while (m_firstChild) { |
+ removedChildren.append(m_firstChild); |
+ removeBetween(0, m_firstChild->nextSibling(), *m_firstChild); |
+ } |
} |
- childrenChanged(false, 0, 0, -childCount); |
+ childrenChanged(false, 0, 0, -static_cast<int>(removedChildren.size())); |
+ |
+ for (size_t i = 0; i < removedChildren.size(); ++i) |
+ notifyNodeRemoved(*removedChildren[i]); |
} |
dispatchSubtreeModifiedEvent(); |
@@ -641,11 +638,11 @@ void ContainerNode::parserAppendChild(PassRefPtrWillBeRawPtr<Node> newChild) |
ASSERT(!newChild->isDocumentFragment()); |
ASSERT(!isHTMLTemplateElement(this)); |
- RefPtrWillBeRawPtr<Node> protect(this); |
- |
if (document() != newChild->document()) |
document().adoptNode(newChild.get(), ASSERT_NO_EXCEPTION); |
+ Node* last = m_lastChild; |
+ |
{ |
NoEventDispatchAssertion assertNoEventDispatch; |
ScriptForbiddenScope forbidScript; |
@@ -657,10 +654,11 @@ void ContainerNode::parserAppendChild(PassRefPtrWillBeRawPtr<Node> newChild) |
ChildListMutationScope(*this).childAdded(*newChild); |
} |
- notifyNodeInserted(*newChild, InsertedByParser); |
+ childrenChanged(true, last, 0, 1); |
+ notifyNodeInserted(*newChild); |
} |
-void ContainerNode::notifyNodeInserted(Node& root, InsertionSourceType source) |
+void ContainerNode::notifyNodeInserted(Node& root) |
{ |
ASSERT(!NoEventDispatchAssertion::isEventDispatchForbidden()); |
@@ -672,13 +670,6 @@ void ContainerNode::notifyNodeInserted(Node& root, InsertionSourceType source) |
NodeVector postInsertionNotificationTargets; |
notifyNodeInsertedInternal(root, postInsertionNotificationTargets); |
- // ShadowRoots are not real children, we don't need to tell host that it's |
- // children changed when one is added. |
- // FIXME: We should have a separate code path for ShadowRoot since it only |
- // needs to call insertedInto and the rest of this logic is not needed. |
- if (!root.isShadowRoot()) |
- childrenChanged(source == InsertedByParser, root.previousSibling(), root.nextSibling(), 1); |
- |
for (size_t i = 0; i < postInsertionNotificationTargets.size(); ++i) { |
Node* targetNode = postInsertionNotificationTargets[i].get(); |
if (targetNode->inDocument()) |
@@ -1090,6 +1081,8 @@ void ContainerNode::updateTreeAfterInsertion(Node& child) |
ChildListMutationScope(*this).childAdded(child); |
+ childrenChanged(false, child.previousSibling(), child.nextSibling(), 1); |
+ |
notifyNodeInserted(child); |
dispatchChildInsertionEvents(child); |