| 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);
|
|
|