Chromium Code Reviews| Index: third_party/WebKit/Source/core/dom/ContainerNode.cpp |
| diff --git a/third_party/WebKit/Source/core/dom/ContainerNode.cpp b/third_party/WebKit/Source/core/dom/ContainerNode.cpp |
| index 207659d70f65cfdf3da66036ac30f8ba15cce0d2..a0e874a314b9761c50faf43deb44540d829dc37a 100644 |
| --- a/third_party/WebKit/Source/core/dom/ContainerNode.cpp |
| +++ b/third_party/WebKit/Source/core/dom/ContainerNode.cpp |
| @@ -266,8 +266,6 @@ class ContainerNode::AdoptAndAppendChild { |
| Node* ContainerNode::insertBefore(Node* newChild, |
| Node* refChild, |
| ExceptionState& exceptionState) { |
| - // https://dom.spec.whatwg.org/#concept-node-pre-insert |
| - |
| // insertBefore(node, 0) is equivalent to appendChild(node) |
| if (!refChild) |
| return appendChild(newChild, exceptionState); |
| @@ -286,12 +284,9 @@ Node* ContainerNode::insertBefore(Node* newChild, |
| return nullptr; |
| } |
| - // 3. If reference child is node, set it to node’s next sibling. |
| - if (refChild == newChild) { |
| - refChild = newChild->nextSibling(); |
| - if (!refChild) |
| - return appendChild(newChild, exceptionState); |
| - } |
| + // Nothing to do. |
| + if (refChild->previousSibling() == newChild || refChild == newChild) |
| + return newChild; |
| NodeVector targets; |
| if (!collectChildrenAndRemoveFromOldParentWithCheck( |
| @@ -396,7 +391,8 @@ void ContainerNode::parserInsertBefore(Node* newChild, Node& nextChild) { |
| Node* ContainerNode::replaceChild(Node* newChild, |
| Node* oldChild, |
| ExceptionState& exceptionState) { |
| - // https://dom.spec.whatwg.org/#concept-node-replace |
| + if (oldChild == newChild) // Nothing to do. |
| + return oldChild; |
| if (!oldChild) { |
| exceptionState.throwDOMException(NotFoundError, |
| @@ -416,23 +412,17 @@ Node* ContainerNode::replaceChild(Node* newChild, |
| } |
| ChildListMutationScope mutation(*this); |
| - // 7. Let reference child be child’s next sibling. |
| Node* next = oldChild->nextSibling(); |
| - // 8. If reference child is node, set it to node’s next sibling. |
| - if (next == newChild) |
| - next = newChild->nextSibling(); |
| - |
| - // TODO(tkent): According to the specification, we should remove |newChild| |
| - // from its parent here, and create a separated mutation record for it. |
| - // Refer to imported/wpt/dom/nodes/MutationObserver-childList.html. |
| - // 12. If child’s parent is not null, run these substeps: |
| - // 1. Set removedNodes to a list solely containing child. |
| - // 2. Remove child from its parent with the suppress observers flag set. |
| + // Remove the node we're replacing. |
| removeChild(oldChild, exceptionState); |
| if (exceptionState.hadException()) |
| return nullptr; |
| + if (next && (next->previousSibling() == newChild || |
| + next == newChild)) // nothing to do |
| + return oldChild; |
| + |
| // Does this one more time because removeChild() fires a MutationEvent. |
| if (!checkAcceptChild(newChild, oldChild, exceptionState)) |
| return oldChild; |
| @@ -659,6 +649,9 @@ Node* ContainerNode::appendChild(Node* newChild, |
| return newChild; |
| DCHECK(newChild); |
| + if (newChild == m_lastChild) // nothing to do |
| + return newChild; |
| + |
| NodeVector targets; |
| if (!collectChildrenAndRemoveFromOldParentWithCheck( |
| nullptr, nullptr, *newChild, targets, exceptionState)) |
| @@ -766,10 +759,6 @@ void ContainerNode::attachLayoutTree(const AttachContext& context) { |
| childrenContext.resolvedStyle = nullptr; |
| for (Node* child = firstChild(); child; child = child->nextSibling()) { |
| -#if DCHECK_IS_ON() |
| - DCHECK(child->needsAttach() || |
| - childAttachedAllowedWhenAttachingChildren(this)); |
|
esprehn
2017/02/13 22:19:41
Lets add this back?
nainar
2017/02/14 03:42:08
Done.
|
| -#endif |
| if (child->needsAttach()) |
| child->attachLayoutTree(childrenContext); |
| } |
| @@ -1280,7 +1269,6 @@ void ContainerNode::setRestyleFlag(DynamicRestyleFlags mask) { |
| void ContainerNode::recalcDescendantStyles(StyleRecalcChange change) { |
| DCHECK(document().inStyleRecalc()); |
| DCHECK(change >= UpdatePseudoElements || childNeedsStyleRecalc()); |
| - DCHECK(!needsStyleRecalc()); |
|
esprehn
2017/02/13 22:19:41
ditto
nainar
2017/02/14 03:42:08
This information isn't true anymore. We are retain
|
| // This loop is deliberately backwards because we use insertBefore in the |
| // layout tree, and want to avoid a potentially n^2 loop to find the insertion |
| @@ -1305,6 +1293,25 @@ void ContainerNode::recalcDescendantStyles(StyleRecalcChange change) { |
| } |
| } |
| +void ContainerNode::rebuildChildrenLayoutTrees() { |
| + DCHECK(!needsReattachLayoutTree()); |
| + |
| + for (Node* child = lastChild(); child; child = child->previousSibling()) { |
| + if (child->needsReattachLayoutTree() || |
| + child->childNeedsReattachLayoutTree()) { |
| + if (child->isTextNode()) |
| + toText(child)->rebuildTextLayoutTree(); |
| + else if (child->isElementNode()) |
| + toElement(child)->rebuildLayoutTree(); |
| + } |
| + } |
| + clearNeedsStyleRecalc(); |
| + // This is done in ContainerNode::attachLayoutTree but will never be cleared |
| + // if we don't enter ContainerNode::attachLayoutTree so we do it here. |
| + clearChildNeedsStyleRecalc(); |
| + clearChildNeedsReattachLayoutTree(); |
| +} |
| + |
| void ContainerNode::checkForSiblingStyleChanges(SiblingCheckType changeType, |
| Element* changedElement, |
| Node* nodeBeforeChange, |