Chromium Code Reviews| Index: Source/core/dom/ContainerNode.cpp |
| diff --git a/Source/core/dom/ContainerNode.cpp b/Source/core/dom/ContainerNode.cpp |
| index 116d4763b1d45869f3c32854046cf486c73ebbad..a7d245ac234d45795d5052214f5e02bef8bcfb44 100644 |
| --- a/Source/core/dom/ContainerNode.cpp |
| +++ b/Source/core/dom/ContainerNode.cpp |
| @@ -278,6 +278,8 @@ void ContainerNode::parserInsertBefore(PassRefPtr<Node> newChild, Node& nextChil |
| ASSERT(!newChild->isDocumentFragment()); |
| ASSERT(!isHTMLTemplateElement(this)); |
| + RefPtr<Node> protect(this); |
| + |
| if (nextChild.previousSibling() == newChild || nextChild == newChild) // nothing to do |
| return; |
| @@ -290,9 +292,7 @@ void ContainerNode::parserInsertBefore(PassRefPtr<Node> newChild, Node& nextChil |
| ChildListMutationScope(*this).childAdded(*newChild); |
| - childrenChanged(true, newChild->previousSibling(), &nextChild, 1); |
| - |
| - notifyNodeInserted(*newChild); |
| + notifyNodeInserted(*newChild, true); |
| } |
| void ContainerNode::replaceChild(PassRefPtr<Node> newChild, Node* oldChild, ExceptionState& exceptionState) |
| @@ -468,8 +468,8 @@ void ContainerNode::removeChild(Node* oldChild, ExceptionState& exceptionState) |
| Node* prev = child->previousSibling(); |
| Node* next = child->nextSibling(); |
| removeBetween(prev, next, *child); |
| - childrenChanged(false, prev, next, -1); |
| notifyNodeRemoved(*child); |
| + childrenChanged(false, prev, next, -1); |
| } |
| dispatchSubtreeModifiedEvent(); |
| } |
| @@ -504,6 +504,10 @@ void ContainerNode::parserRemoveChild(Node& oldChild) |
| ASSERT(oldChild.parentNode() == this); |
| ASSERT(!oldChild.isDocumentFragment()); |
| + ScriptForbiddenScope forbidScript; |
| + |
| + RefPtr<Node> protect(this); |
|
ojan
2014/06/04 00:38:46
Don't need this if script can't execute.
|
| + |
| Node* prev = oldChild.previousSibling(); |
| Node* next = oldChild.nextSibling(); |
| @@ -513,9 +517,8 @@ void ContainerNode::parserRemoveChild(Node& oldChild) |
| oldChild.notifyMutationObserversNodeWillDetach(); |
| removeBetween(prev, next, oldChild); |
| - |
| - childrenChanged(true, prev, next, -1); |
| notifyNodeRemoved(oldChild); |
| + childrenChanged(true, prev, next, -1); |
| } |
| // this differs from other remove functions because it forcibly removes all the children, |
| @@ -550,23 +553,25 @@ 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 (RefPtr<Node> child = m_firstChild) { |
| NoEventDispatchAssertion assertNoEventDispatch; |
| - removedChildren.reserveInitialCapacity(countChildren()); |
| - while (m_firstChild) { |
| - removedChildren.append(m_firstChild); |
| - removeBetween(0, m_firstChild->nextSibling(), *m_firstChild); |
| - } |
| + ++childCount; |
| + removeBetween(0, child->nextSibling(), *child); |
| + notifyNodeRemoved(*child); |
| } |
| - childrenChanged(false, 0, 0, -static_cast<int>(removedChildren.size())); |
| - |
| - for (size_t i = 0; i < removedChildren.size(); ++i) |
| - notifyNodeRemoved(*removedChildren[i]); |
| + childrenChanged(false, 0, 0, -childCount); |
| } |
| dispatchSubtreeModifiedEvent(); |
| @@ -637,11 +642,11 @@ void ContainerNode::parserAppendChild(PassRefPtr<Node> newChild) |
| ASSERT(!newChild->isDocumentFragment()); |
| ASSERT(!isHTMLTemplateElement(this)); |
| + RefPtr<Node> protect(this); |
| + |
| if (document() != newChild->document()) |
| document().adoptNode(newChild.get(), ASSERT_NO_EXCEPTION); |
| - Node* last = m_lastChild; |
| - |
| { |
| NoEventDispatchAssertion assertNoEventDispatch; |
| ScriptForbiddenScope forbidScript; |
| @@ -653,22 +658,26 @@ void ContainerNode::parserAppendChild(PassRefPtr<Node> newChild) |
| ChildListMutationScope(*this).childAdded(*newChild); |
| } |
| - childrenChanged(true, last, 0, 1); |
| - notifyNodeInserted(*newChild); |
| + notifyNodeInserted(*newChild, true); |
|
ojan
2014/06/04 00:38:46
Bool arguments!!
|
| } |
| -void ContainerNode::notifyNodeInserted(Node& root) |
| +void ContainerNode::notifyNodeInserted(Node& root, bool createdByParser) |
| { |
| ASSERT(!NoEventDispatchAssertion::isEventDispatchForbidden()); |
| InspectorInstrumentation::didInsertDOMNode(&root); |
| RefPtr<Node> protect(this); |
| - RefPtr<Node> protectNode(root); |
| + RefPtr<Node> protectRoot(root); |
| 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. |
| + if (!root.isShadowRoot()) |
|
ojan
2014/06/04 00:38:46
As per discussion in person, this is a little goof
|
| + childrenChanged(createdByParser, root.previousSibling(), root.nextSibling(), 1); |
| + |
| for (size_t i = 0; i < postInsertionNotificationTargets.size(); ++i) { |
| Node* targetNode = postInsertionNotificationTargets[i].get(); |
| if (targetNode->inDocument()) |
| @@ -1079,8 +1088,6 @@ void ContainerNode::updateTreeAfterInsertion(Node& child) |
| ChildListMutationScope(*this).childAdded(child); |
| - childrenChanged(false, child.previousSibling(), child.nextSibling(), 1); |
| - |
| notifyNodeInserted(child); |
| dispatchChildInsertionEvents(child); |