Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(599)

Unified Diff: Source/core/dom/ContainerNode.cpp

Issue 418133003: Call insertedInto or removedFrom before childrenChanged (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Created 6 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: Source/core/dom/ContainerNode.cpp
diff --git a/Source/core/dom/ContainerNode.cpp b/Source/core/dom/ContainerNode.cpp
index 8964573589802af05f0155a52ba02ac8b493e9a8..e80732962d4221c928e6e49cecf2e14c82ea2477 100644
--- a/Source/core/dom/ContainerNode.cpp
+++ b/Source/core/dom/ContainerNode.cpp
@@ -303,6 +303,8 @@ void ContainerNode::parserInsertBefore(PassRefPtrWillBeRawPtr<Node> newChild, No
if (nextChild.previousSibling() == newChild || &nextChild == newChild) // nothing to do
return;
+ RefPtrWillBeRawPtr<Node> protect(this);
+
if (document() != newChild->document())
document().adoptNode(newChild.get(), ASSERT_NO_EXCEPTION);
@@ -312,10 +314,7 @@ void ContainerNode::parserInsertBefore(PassRefPtrWillBeRawPtr<Node> newChild, No
ChildListMutationScope(*this).childAdded(*newChild);
- ChildrenChange change = {ChildInserted, newChild->previousSibling(), &nextChild, ChildrenChangeSourceParser};
- childrenChanged(change);
-
- notifyNodeInserted(*newChild);
+ notifyNodeInserted(*newChild, ChildrenChangeSourceParser);
}
PassRefPtrWillBeRawPtr<Node> ContainerNode::replaceChild(PassRefPtrWillBeRawPtr<Node> newChild, PassRefPtrWillBeRawPtr<Node> oldChild, ExceptionState& exceptionState)
@@ -568,9 +567,9 @@ PassRefPtrWillBeRawPtr<Node> ContainerNode::removeChild(PassRefPtrWillBeRawPtr<N
Node* prev = child->previousSibling();
Node* next = child->nextSibling();
removeBetween(prev, next, *child);
+ notifyNodeRemoved(*child);
ChildrenChange change = {ChildRemoved, prev, next, ChildrenChangeSourceAPI};
childrenChanged(change);
- notifyNodeRemoved(*child);
}
dispatchSubtreeModifiedEvent();
return child;
@@ -617,8 +616,8 @@ void ContainerNode::parserRemoveChild(Node& oldChild)
removeBetween(prev, next, oldChild);
ChildrenChange change = {ChildRemoved, prev, next, ChildrenChangeSourceParser};
- childrenChanged(change);
notifyNodeRemoved(oldChild);
+ childrenChanged(change);
}
// this differs from other remove functions because it forcibly removes all the children,
@@ -653,24 +652,30 @@ void ContainerNode::removeChildren()
document().nodeChildrenWillBeRemoved(*this);
}
-
+ // FIXME: Remove this NodeVector. Right now WebPluginContainerImpl::m_element is a
+ // raw ptr which means the code below can drop the last ref to a plugin element and
+ // then the code in UpdateSuspendScope::performDeferredWidgetTreeOperations will
+ // try to destroy the plugin which will be a use-after-free. We should use a RefPtr
+ // in the WebPluginContainerImpl instead.
NodeVector removedChildren;
{
HTMLFrameOwnerElement::UpdateSuspendScope suspendWidgetHierarchyUpdates;
+
{
NoEventDispatchAssertion assertNoEventDispatch;
- removedChildren.reserveInitialCapacity(countChildren());
- while (m_firstChild) {
- removedChildren.append(m_firstChild);
- removeBetween(0, m_firstChild->nextSibling(), *m_firstChild);
+ ScriptForbiddenScope forbidScript;
+
+ removedChildren.reserveInitialCapacity(childNodeCount());
+
+ while (RefPtrWillBeRawPtr<Node> child = m_firstChild) {
+ removeBetween(0, child->nextSibling(), *child);
+ removedChildren.append(child.get());
+ notifyNodeRemoved(*child);
}
}
ChildrenChange change = {AllChildrenRemoved, nullptr, nullptr, ChildrenChangeSourceAPI};
childrenChanged(change);
-
- for (size_t i = 0; i < removedChildren.size(); ++i)
- notifyNodeRemoved(*removedChildren[i]);
}
dispatchSubtreeModifiedEvent();
@@ -748,11 +753,11 @@ void ContainerNode::parserAppendChild(PassRefPtrWillBeRawPtr<Node> newChild)
ASSERT(!newChild->isDocumentFragment());
ASSERT(!isHTMLTemplateElement(this));
+ RefPtrWillBeRawPtr<Node> protect(this);
adamk 2014/07/24 21:35:59 What's this about?
esprehn 2014/07/24 22:50:18 Nothing is protecting |this| in these parser metho
+
if (document() != newChild->document())
document().adoptNode(newChild.get(), ASSERT_NO_EXCEPTION);
- Node* last = m_lastChild;
-
{
NoEventDispatchAssertion assertNoEventDispatch;
ScriptForbiddenScope forbidScript;
@@ -763,12 +768,10 @@ void ContainerNode::parserAppendChild(PassRefPtrWillBeRawPtr<Node> newChild)
ChildListMutationScope(*this).childAdded(*newChild);
}
- ChildrenChange change = {ChildInserted, last, nullptr, ChildrenChangeSourceParser};
- childrenChanged(change);
- notifyNodeInserted(*newChild);
+ notifyNodeInserted(*newChild, ChildrenChangeSourceParser);
}
-void ContainerNode::notifyNodeInserted(Node& root)
+void ContainerNode::notifyNodeInserted(Node& root, ChildrenChangeSource source)
{
ASSERT(!NoEventDispatchAssertion::isEventDispatchForbidden());
@@ -780,6 +783,15 @@ void ContainerNode::notifyNodeInserted(Node& root)
NodeVector postInsertionNotificationTargets;
notifyNodeInsertedInternal(root, postInsertionNotificationTargets);
+ // ShadowRoots are not real children, we don't need to tell host that it's
adamk 2014/07/24 21:35:59 Why are you changing this behavior in this patch?
esprehn 2014/07/24 22:50:18 I'm not changing any behavior, I moved childrenCha
+ // 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()) {
+ ChildrenChange change = {ChildInserted, root.previousSibling(), root.nextSibling(), source};
+ childrenChanged(change);
+ }
+
for (size_t i = 0; i < postInsertionNotificationTargets.size(); ++i) {
Node* targetNode = postInsertionNotificationTargets[i].get();
if (targetNode->inDocument())
@@ -1191,9 +1203,6 @@ void ContainerNode::updateTreeAfterInsertion(Node& child)
ChildListMutationScope(*this).childAdded(child);
- ChildrenChange change = {ChildInserted, child.previousSibling(), child.nextSibling(), ChildrenChangeSourceAPI};
- childrenChanged(change);
-
notifyNodeInserted(child);
dispatchChildInsertionEvents(child);
« LayoutTests/fast/dom/script-remove-child-id-map.html ('K') | « Source/core/dom/ContainerNode.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698