| Index: Source/core/dom/ContainerNode.cpp
|
| diff --git a/Source/core/dom/ContainerNode.cpp b/Source/core/dom/ContainerNode.cpp
|
| index 427e089656ad09e4104b4bd8a2f08822764e1101..366598a9ce6a8220762d91d88a5d7cfb667cfcad 100644
|
| --- a/Source/core/dom/ContainerNode.cpp
|
| +++ b/Source/core/dom/ContainerNode.cpp
|
| @@ -36,11 +36,15 @@
|
| #include "core/dom/NodeRareData.h"
|
| #include "core/dom/NodeRenderStyle.h"
|
| #include "core/dom/NodeTraversal.h"
|
| +#include "core/dom/ScriptForbiddenScope.h"
|
| #include "core/dom/SelectorQuery.h"
|
| +#include "core/dom/shadow/ElementShadow.h"
|
| +#include "core/dom/shadow/ShadowRoot.h"
|
| #include "core/events/MutationEvent.h"
|
| #include "core/html/HTMLCollection.h"
|
| #include "core/html/HTMLFrameOwnerElement.h"
|
| #include "core/html/RadioNodeList.h"
|
| +#include "core/inspector/InspectorInstrumentation.h"
|
| #include "core/rendering/InlineTextBox.h"
|
| #include "core/rendering/RenderText.h"
|
| #include "core/rendering/RenderTheme.h"
|
| @@ -289,7 +293,7 @@ void ContainerNode::parserInsertBefore(PassRefPtr<Node> newChild, Node& nextChil
|
|
|
| childrenChanged(true, newChild->previousSibling(), &nextChild, 1);
|
|
|
| - ChildNodeInsertionNotifier(*this).notify(*newChild);
|
| + notifyNodeInserted(*newChild);
|
| }
|
|
|
| void ContainerNode::replaceChild(PassRefPtr<Node> newChild, Node* oldChild, ExceptionState& exceptionState)
|
| @@ -466,7 +470,7 @@ void ContainerNode::removeChild(Node* oldChild, ExceptionState& exceptionState)
|
| Node* next = child->nextSibling();
|
| removeBetween(prev, next, *child);
|
| childrenChanged(false, prev, next, -1);
|
| - ChildNodeRemovalNotifier(*this).notify(*child);
|
| + notifyNodeRemoved(*child);
|
| }
|
| dispatchSubtreeModifiedEvent();
|
| }
|
| @@ -512,7 +516,7 @@ void ContainerNode::parserRemoveChild(Node& oldChild)
|
| removeBetween(prev, next, oldChild);
|
|
|
| childrenChanged(true, prev, next, -1);
|
| - ChildNodeRemovalNotifier(*this).notify(oldChild);
|
| + notifyNodeRemoved(oldChild);
|
| }
|
|
|
| // this differs from other remove functions because it forcibly removes all the children,
|
| @@ -563,7 +567,7 @@ void ContainerNode::removeChildren()
|
| childrenChanged(false, 0, 0, -static_cast<int>(removedChildren.size()));
|
|
|
| for (size_t i = 0; i < removedChildren.size(); ++i)
|
| - ChildNodeRemovalNotifier(*this).notify(*removedChildren[i]);
|
| + notifyNodeRemoved(*removedChildren[i]);
|
| }
|
|
|
| dispatchSubtreeModifiedEvent();
|
| @@ -650,7 +654,65 @@ void ContainerNode::parserAppendChild(PassRefPtr<Node> newChild)
|
| ChildListMutationScope(*this).childAdded(*newChild);
|
|
|
| childrenChanged(true, last, 0, 1);
|
| - ChildNodeInsertionNotifier(*this).notify(*newChild);
|
| + notifyNodeInserted(*newChild);
|
| +}
|
| +
|
| +void ContainerNode::notifyNodeInserted(Node& root)
|
| +{
|
| + ASSERT(!NoEventDispatchAssertion::isEventDispatchForbidden());
|
| +
|
| + InspectorInstrumentation::didInsertDOMNode(&root);
|
| +
|
| + RefPtr<Node> protectDocument(root.document());
|
| + RefPtr<Node> protectNode(root);
|
| +
|
| + NodeVector postInsertionNotificationTargets;
|
| +
|
| + {
|
| + NoEventDispatchAssertion assertNoEventDispatch;
|
| + ScriptForbiddenScope forbidScript;
|
| + notifyNodeInsertedInternal(root, postInsertionNotificationTargets);
|
| + }
|
| +
|
| + for (size_t i = 0; i < postInsertionNotificationTargets.size(); ++i) {
|
| + Node* targetNode = postInsertionNotificationTargets[i].get();
|
| + if (targetNode->inDocument())
|
| + targetNode->didNotifySubtreeInsertionsToDocument();
|
| + }
|
| +}
|
| +
|
| +void ContainerNode::notifyNodeInsertedInternal(Node& root, NodeVector& postInsertionNotificationTargets)
|
| +{
|
| + for (Node* node = &root; node; node = NodeTraversal::next(*node, &root)) {
|
| + // As an optimization we don't notify leaf nodes when when inserting
|
| + // into detached subtrees.
|
| + if (!inDocument() && !node->isContainerNode())
|
| + continue;
|
| + if (Node::InsertionShouldCallDidNotifySubtreeInsertions == node->insertedInto(this))
|
| + postInsertionNotificationTargets.append(node);
|
| + for (ShadowRoot* shadowRoot = node->youngestShadowRoot(); shadowRoot; shadowRoot = shadowRoot->olderShadowRoot())
|
| + notifyNodeInsertedInternal(*shadowRoot, postInsertionNotificationTargets);
|
| + }
|
| +}
|
| +
|
| +void ContainerNode::notifyNodeRemoved(Node& root)
|
| +{
|
| + ScriptForbiddenScope forbidScript;
|
| + NoEventDispatchAssertion assertNoEventDispatch;
|
| +
|
| + Document& document = root.document();
|
| + for (Node* node = &root; node; node = NodeTraversal::next(*node, &root)) {
|
| + // As an optimization we skip notifying Text nodes and other leaf nodes
|
| + // of removal when they're not in the Document tree since the virtual
|
| + // call to removedFrom is not needed.
|
| + if (!node->inDocument() && !node->isContainerNode())
|
| + continue;
|
| + if (document.cssTarget() == node)
|
| + document.setCSSTarget(0);
|
| + node->removedFrom(this);
|
| + for (ShadowRoot* shadowRoot = node->youngestShadowRoot(); shadowRoot; shadowRoot = shadowRoot->olderShadowRoot())
|
| + notifyNodeRemoved(*shadowRoot);
|
| + }
|
| }
|
|
|
| void ContainerNode::attach(const AttachContext& context)
|
| @@ -1021,7 +1083,7 @@ void ContainerNode::updateTreeAfterInsertion(Node& child)
|
|
|
| childrenChanged(false, child.previousSibling(), child.nextSibling(), 1);
|
|
|
| - ChildNodeInsertionNotifier(*this).notify(child);
|
| + notifyNodeInserted(child);
|
|
|
| dispatchChildInsertionEvents(child);
|
| }
|
|
|