| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) | 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) |
| 3 * (C) 1999 Antti Koivisto (koivisto@kde.org) | 3 * (C) 1999 Antti Koivisto (koivisto@kde.org) |
| 4 * (C) 2001 Dirk Mueller (mueller@kde.org) | 4 * (C) 2001 Dirk Mueller (mueller@kde.org) |
| 5 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2013 Apple Inc. All rights
reserved. | 5 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2013 Apple Inc. All rights
reserved. |
| 6 * | 6 * |
| 7 * This library is free software; you can redistribute it and/or | 7 * This library is free software; you can redistribute it and/or |
| 8 * modify it under the terms of the GNU Library General Public | 8 * modify it under the terms of the GNU Library General Public |
| 9 * License as published by the Free Software Foundation; either | 9 * License as published by the Free Software Foundation; either |
| 10 * version 2 of the License, or (at your option) any later version. | 10 * version 2 of the License, or (at your option) any later version. |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 71 return; | 71 return; |
| 72 } | 72 } |
| 73 nodes.append(&node); | 73 nodes.append(&node); |
| 74 if (ContainerNode* oldParent = node.parentNode()) | 74 if (ContainerNode* oldParent = node.parentNode()) |
| 75 oldParent->removeChild(&node, exceptionState); | 75 oldParent->removeChild(&node, exceptionState); |
| 76 } | 76 } |
| 77 | 77 |
| 78 #if !ENABLE(OILPAN) | 78 #if !ENABLE(OILPAN) |
| 79 void ContainerNode::removeDetachedChildren() | 79 void ContainerNode::removeDetachedChildren() |
| 80 { | 80 { |
| 81 ASSERT(!connectedSubframeCount()); | 81 DCHECK(!connectedSubframeCount()); |
| 82 ASSERT(needsAttach()); | 82 DCHECK(needsAttach()); |
| 83 removeDetachedChildrenInContainer(*this); | 83 removeDetachedChildrenInContainer(*this); |
| 84 } | 84 } |
| 85 #endif | 85 #endif |
| 86 | 86 |
| 87 void ContainerNode::parserTakeAllChildrenFrom(ContainerNode& oldParent) | 87 void ContainerNode::parserTakeAllChildrenFrom(ContainerNode& oldParent) |
| 88 { | 88 { |
| 89 while (RawPtr<Node> child = oldParent.firstChild()) { | 89 while (RawPtr<Node> child = oldParent.firstChild()) { |
| 90 // Explicitly remove since appending can fail, but this loop shouldn't b
e infinite. | 90 // Explicitly remove since appending can fail, but this loop shouldn't b
e infinite. |
| 91 oldParent.parserRemoveChild(*child); | 91 oldParent.parserRemoveChild(*child); |
| 92 parserAppendChild(child.get()); | 92 parserAppendChild(child.get()); |
| 93 } | 93 } |
| 94 } | 94 } |
| 95 | 95 |
| 96 ContainerNode::~ContainerNode() | 96 ContainerNode::~ContainerNode() |
| 97 { | 97 { |
| 98 ASSERT(needsAttach()); | 98 DCHECK(needsAttach()); |
| 99 #if !ENABLE(OILPAN) | 99 #if !ENABLE(OILPAN) |
| 100 willBeDeletedFromDocument(); | 100 willBeDeletedFromDocument(); |
| 101 removeDetachedChildren(); | 101 removeDetachedChildren(); |
| 102 #endif | 102 #endif |
| 103 } | 103 } |
| 104 | 104 |
| 105 bool ContainerNode::isChildTypeAllowed(const Node& child) const | 105 bool ContainerNode::isChildTypeAllowed(const Node& child) const |
| 106 { | 106 { |
| 107 if (!child.isDocumentFragment()) | 107 if (!child.isDocumentFragment()) |
| 108 return childTypeAllowed(child.getNodeType()); | 108 return childTypeAllowed(child.getNodeType()); |
| (...skipping 15 matching lines...) Expand all Loading... |
| 124 bool ContainerNode::checkAcceptChild(const Node* newChild, const Node* oldChild,
ExceptionState& exceptionState) const | 124 bool ContainerNode::checkAcceptChild(const Node* newChild, const Node* oldChild,
ExceptionState& exceptionState) const |
| 125 { | 125 { |
| 126 // Not mentioned in spec: throw NotFoundError if newChild is null | 126 // Not mentioned in spec: throw NotFoundError if newChild is null |
| 127 if (!newChild) { | 127 if (!newChild) { |
| 128 exceptionState.throwDOMException(NotFoundError, "The new child element i
s null."); | 128 exceptionState.throwDOMException(NotFoundError, "The new child element i
s null."); |
| 129 return false; | 129 return false; |
| 130 } | 130 } |
| 131 | 131 |
| 132 // Use common case fast path if possible. | 132 // Use common case fast path if possible. |
| 133 if ((newChild->isElementNode() || newChild->isTextNode()) && isElementNode()
) { | 133 if ((newChild->isElementNode() || newChild->isTextNode()) && isElementNode()
) { |
| 134 ASSERT(isChildTypeAllowed(*newChild)); | 134 DCHECK(isChildTypeAllowed(*newChild)); |
| 135 if (containsConsideringHostElements(*newChild)) { | 135 if (containsConsideringHostElements(*newChild)) { |
| 136 exceptionState.throwDOMException(HierarchyRequestError, "The new chi
ld element contains the parent."); | 136 exceptionState.throwDOMException(HierarchyRequestError, "The new chi
ld element contains the parent."); |
| 137 return false; | 137 return false; |
| 138 } | 138 } |
| 139 return true; | 139 return true; |
| 140 } | 140 } |
| 141 | 141 |
| 142 // This should never happen, but also protect release builds from tree corru
ption. | 142 // This should never happen, but also protect release builds from tree corru
ption. |
| 143 ASSERT(!newChild->isPseudoElement()); | 143 DCHECK(!newChild->isPseudoElement()); |
| 144 if (newChild->isPseudoElement()) { | 144 if (newChild->isPseudoElement()) { |
| 145 exceptionState.throwDOMException(HierarchyRequestError, "The new child e
lement is a pseudo-element."); | 145 exceptionState.throwDOMException(HierarchyRequestError, "The new child e
lement is a pseudo-element."); |
| 146 return false; | 146 return false; |
| 147 } | 147 } |
| 148 | 148 |
| 149 return checkAcceptChildGuaranteedNodeTypes(*newChild, oldChild, exceptionSta
te); | 149 return checkAcceptChildGuaranteedNodeTypes(*newChild, oldChild, exceptionSta
te); |
| 150 } | 150 } |
| 151 | 151 |
| 152 bool ContainerNode::checkAcceptChildGuaranteedNodeTypes(const Node& newChild, co
nst Node* oldChild, ExceptionState& exceptionState) const | 152 bool ContainerNode::checkAcceptChildGuaranteedNodeTypes(const Node& newChild, co
nst Node* oldChild, ExceptionState& exceptionState) const |
| 153 { | 153 { |
| 154 if (isDocumentNode()) | 154 if (isDocumentNode()) |
| 155 return toDocument(this)->canAcceptChild(newChild, oldChild, exceptionSta
te); | 155 return toDocument(this)->canAcceptChild(newChild, oldChild, exceptionSta
te); |
| 156 if (newChild.containsIncludingHostElements(*this)) { | 156 if (newChild.containsIncludingHostElements(*this)) { |
| 157 exceptionState.throwDOMException(HierarchyRequestError, "The new child e
lement contains the parent."); | 157 exceptionState.throwDOMException(HierarchyRequestError, "The new child e
lement contains the parent."); |
| 158 return false; | 158 return false; |
| 159 } | 159 } |
| 160 if (!isChildTypeAllowed(newChild)) { | 160 if (!isChildTypeAllowed(newChild)) { |
| 161 exceptionState.throwDOMException(HierarchyRequestError, "Nodes of type '
" + newChild.nodeName() + "' may not be inserted inside nodes of type '" + nodeN
ame() + "'."); | 161 exceptionState.throwDOMException(HierarchyRequestError, "Nodes of type '
" + newChild.nodeName() + "' may not be inserted inside nodes of type '" + nodeN
ame() + "'."); |
| 162 return false; | 162 return false; |
| 163 } | 163 } |
| 164 return true; | 164 return true; |
| 165 } | 165 } |
| 166 | 166 |
| 167 RawPtr<Node> ContainerNode::insertBefore(RawPtr<Node> newChild, Node* refChild,
ExceptionState& exceptionState) | 167 RawPtr<Node> ContainerNode::insertBefore(RawPtr<Node> newChild, Node* refChild,
ExceptionState& exceptionState) |
| 168 { | 168 { |
| 169 #if !ENABLE(OILPAN) | 169 #if !ENABLE(OILPAN) |
| 170 // Check that this node is not "floating". | 170 // Check that this node is not "floating". |
| 171 // If it is, it can be deleted as a side effect of sending mutation events. | 171 // If it is, it can be deleted as a side effect of sending mutation events. |
| 172 ASSERT(refCount() || parentOrShadowHostNode()); | 172 DCHECK(refCount() || parentOrShadowHostNode()); |
| 173 #endif | 173 #endif |
| 174 | 174 |
| 175 RawPtr<Node> protect(this); | 175 RawPtr<Node> protect(this); |
| 176 | 176 |
| 177 // insertBefore(node, 0) is equivalent to appendChild(node) | 177 // insertBefore(node, 0) is equivalent to appendChild(node) |
| 178 if (!refChild) { | 178 if (!refChild) { |
| 179 return appendChild(newChild, exceptionState); | 179 return appendChild(newChild, exceptionState); |
| 180 } | 180 } |
| 181 | 181 |
| 182 // Make sure adding the new child is OK. | 182 // Make sure adding the new child is OK. |
| 183 if (!checkAcceptChild(newChild.get(), 0, exceptionState)) { | 183 if (!checkAcceptChild(newChild.get(), 0, exceptionState)) { |
| 184 if (exceptionState.hadException()) | 184 if (exceptionState.hadException()) |
| 185 return nullptr; | 185 return nullptr; |
| 186 return newChild; | 186 return newChild; |
| 187 } | 187 } |
| 188 ASSERT(newChild); | 188 DCHECK(newChild); |
| 189 | 189 |
| 190 // NotFoundError: Raised if refChild is not a child of this node | 190 // NotFoundError: Raised if refChild is not a child of this node |
| 191 if (refChild->parentNode() != this) { | 191 if (refChild->parentNode() != this) { |
| 192 exceptionState.throwDOMException(NotFoundError, "The node before which t
he new node is to be inserted is not a child of this node."); | 192 exceptionState.throwDOMException(NotFoundError, "The node before which t
he new node is to be inserted is not a child of this node."); |
| 193 return nullptr; | 193 return nullptr; |
| 194 } | 194 } |
| 195 | 195 |
| 196 // Nothing to do. | 196 // Nothing to do. |
| 197 if (refChild->previousSibling() == newChild || refChild == newChild) | 197 if (refChild->previousSibling() == newChild || refChild == newChild) |
| 198 return newChild; | 198 return newChild; |
| (...skipping 11 matching lines...) Expand all Loading... |
| 210 if (!checkAcceptChildGuaranteedNodeTypes(*newChild, nullptr, exceptionState)
) { | 210 if (!checkAcceptChildGuaranteedNodeTypes(*newChild, nullptr, exceptionState)
) { |
| 211 if (exceptionState.hadException()) | 211 if (exceptionState.hadException()) |
| 212 return nullptr; | 212 return nullptr; |
| 213 return newChild; | 213 return newChild; |
| 214 } | 214 } |
| 215 | 215 |
| 216 InspectorInstrumentation::willInsertDOMNode(this); | 216 InspectorInstrumentation::willInsertDOMNode(this); |
| 217 | 217 |
| 218 ChildListMutationScope mutation(*this); | 218 ChildListMutationScope mutation(*this); |
| 219 for (const auto& targetNode : targets) { | 219 for (const auto& targetNode : targets) { |
| 220 ASSERT(targetNode); | 220 DCHECK(targetNode); |
| 221 Node& child = *targetNode; | 221 Node& child = *targetNode; |
| 222 | 222 |
| 223 // Due to arbitrary code running in response to a DOM mutation event it'
s | 223 // Due to arbitrary code running in response to a DOM mutation event it'
s |
| 224 // possible that "next" is no longer a child of "this". | 224 // possible that "next" is no longer a child of "this". |
| 225 // It's also possible that "child" has been inserted elsewhere. | 225 // It's also possible that "child" has been inserted elsewhere. |
| 226 // In either of those cases, we'll just stop. | 226 // In either of those cases, we'll just stop. |
| 227 if (next->parentNode() != this) | 227 if (next->parentNode() != this) |
| 228 break; | 228 break; |
| 229 if (child.parentNode()) | 229 if (child.parentNode()) |
| 230 break; | 230 break; |
| (...skipping 12 matching lines...) Expand all Loading... |
| 243 dispatchSubtreeModifiedEvent(); | 243 dispatchSubtreeModifiedEvent(); |
| 244 | 244 |
| 245 return newChild; | 245 return newChild; |
| 246 } | 246 } |
| 247 | 247 |
| 248 void ContainerNode::insertBeforeCommon(Node& nextChild, Node& newChild) | 248 void ContainerNode::insertBeforeCommon(Node& nextChild, Node& newChild) |
| 249 { | 249 { |
| 250 EventDispatchForbiddenScope assertNoEventDispatch; | 250 EventDispatchForbiddenScope assertNoEventDispatch; |
| 251 ScriptForbiddenScope forbidScript; | 251 ScriptForbiddenScope forbidScript; |
| 252 | 252 |
| 253 ASSERT(!newChild.parentNode()); // Use insertBefore if you need to handle re
parenting (and want DOM mutation events). | 253 DCHECK(!newChild.parentNode()); // Use insertBefore if you need to handle re
parenting (and want DOM mutation events). |
| 254 ASSERT(!newChild.nextSibling()); | 254 DCHECK(!newChild.nextSibling()); |
| 255 ASSERT(!newChild.previousSibling()); | 255 DCHECK(!newChild.previousSibling()); |
| 256 ASSERT(!newChild.isShadowRoot()); | 256 DCHECK(!newChild.isShadowRoot()); |
| 257 | 257 |
| 258 Node* prev = nextChild.previousSibling(); | 258 Node* prev = nextChild.previousSibling(); |
| 259 ASSERT(m_lastChild != prev); | 259 DCHECK_NE(m_lastChild, prev); |
| 260 nextChild.setPreviousSibling(&newChild); | 260 nextChild.setPreviousSibling(&newChild); |
| 261 if (prev) { | 261 if (prev) { |
| 262 ASSERT(firstChild() != nextChild); | 262 DCHECK_NE(firstChild(), nextChild); |
| 263 ASSERT(prev->nextSibling() == nextChild); | 263 DCHECK_EQ(prev->nextSibling(), nextChild); |
| 264 prev->setNextSibling(&newChild); | 264 prev->setNextSibling(&newChild); |
| 265 } else { | 265 } else { |
| 266 ASSERT(firstChild() == nextChild); | 266 DCHECK(firstChild() == nextChild); |
| 267 m_firstChild = &newChild; | 267 m_firstChild = &newChild; |
| 268 } | 268 } |
| 269 newChild.setParentOrShadowHostNode(this); | 269 newChild.setParentOrShadowHostNode(this); |
| 270 newChild.setPreviousSibling(prev); | 270 newChild.setPreviousSibling(prev); |
| 271 newChild.setNextSibling(&nextChild); | 271 newChild.setNextSibling(&nextChild); |
| 272 } | 272 } |
| 273 | 273 |
| 274 void ContainerNode::appendChildCommon(Node& child) | 274 void ContainerNode::appendChildCommon(Node& child) |
| 275 { | 275 { |
| 276 child.setParentOrShadowHostNode(this); | 276 child.setParentOrShadowHostNode(this); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 289 { | 289 { |
| 290 if (!isDocumentNode()) | 290 if (!isDocumentNode()) |
| 291 return true; | 291 return true; |
| 292 // TODO(esprehn): Are there other conditions where the parser can create | 292 // TODO(esprehn): Are there other conditions where the parser can create |
| 293 // invalid trees? | 293 // invalid trees? |
| 294 return toDocument(*this).canAcceptChild(newChild, nullptr, IGNORE_EXCEPTION)
; | 294 return toDocument(*this).canAcceptChild(newChild, nullptr, IGNORE_EXCEPTION)
; |
| 295 } | 295 } |
| 296 | 296 |
| 297 void ContainerNode::parserInsertBefore(RawPtr<Node> newChild, Node& nextChild) | 297 void ContainerNode::parserInsertBefore(RawPtr<Node> newChild, Node& nextChild) |
| 298 { | 298 { |
| 299 ASSERT(newChild); | 299 DCHECK(newChild); |
| 300 ASSERT(nextChild.parentNode() == this); | 300 DCHECK_EQ(nextChild.parentNode(), this); |
| 301 ASSERT(!newChild->isDocumentFragment()); | 301 DCHECK(!newChild->isDocumentFragment()); |
| 302 ASSERT(!isHTMLTemplateElement(this)); | 302 DCHECK(!isHTMLTemplateElement(this)); |
| 303 | 303 |
| 304 if (nextChild.previousSibling() == newChild || &nextChild == newChild) // no
thing to do | 304 if (nextChild.previousSibling() == newChild || &nextChild == newChild) // no
thing to do |
| 305 return; | 305 return; |
| 306 | 306 |
| 307 if (!checkParserAcceptChild(*newChild)) | 307 if (!checkParserAcceptChild(*newChild)) |
| 308 return; | 308 return; |
| 309 | 309 |
| 310 RawPtr<Node> protect(this); | 310 RawPtr<Node> protect(this); |
| 311 | 311 |
| 312 // FIXME: parserRemoveChild can run script which could then insert the | 312 // FIXME: parserRemoveChild can run script which could then insert the |
| 313 // newChild back into the page. Loop until the child is actually removed. | 313 // newChild back into the page. Loop until the child is actually removed. |
| 314 // See: fast/parser/execute-script-during-adoption-agency-removal.html | 314 // See: fast/parser/execute-script-during-adoption-agency-removal.html |
| 315 while (RawPtr<ContainerNode> parent = newChild->parentNode()) | 315 while (RawPtr<ContainerNode> parent = newChild->parentNode()) |
| 316 parent->parserRemoveChild(*newChild); | 316 parent->parserRemoveChild(*newChild); |
| 317 | 317 |
| 318 if (nextChild.parentNode() != this) | 318 if (nextChild.parentNode() != this) |
| 319 return; | 319 return; |
| 320 | 320 |
| 321 if (document() != newChild->document()) | 321 if (document() != newChild->document()) |
| 322 document().adoptNode(newChild.get(), ASSERT_NO_EXCEPTION); | 322 document().adoptNode(newChild.get(), ASSERT_NO_EXCEPTION); |
| 323 | 323 |
| 324 { | 324 { |
| 325 EventDispatchForbiddenScope assertNoEventDispatch; | 325 EventDispatchForbiddenScope assertNoEventDispatch; |
| 326 ScriptForbiddenScope forbidScript; | 326 ScriptForbiddenScope forbidScript; |
| 327 | 327 |
| 328 treeScope().adoptIfNeeded(*newChild); | 328 treeScope().adoptIfNeeded(*newChild); |
| 329 insertBeforeCommon(nextChild, *newChild); | 329 insertBeforeCommon(nextChild, *newChild); |
| 330 ASSERT(newChild->connectedSubframeCount() == 0); | 330 DCHECK_EQ(newChild->connectedSubframeCount(), 0u); |
| 331 ChildListMutationScope(*this).childAdded(*newChild); | 331 ChildListMutationScope(*this).childAdded(*newChild); |
| 332 } | 332 } |
| 333 | 333 |
| 334 notifyNodeInserted(*newChild, ChildrenChangeSourceParser); | 334 notifyNodeInserted(*newChild, ChildrenChangeSourceParser); |
| 335 } | 335 } |
| 336 | 336 |
| 337 RawPtr<Node> ContainerNode::replaceChild(RawPtr<Node> newChild, RawPtr<Node> old
Child, ExceptionState& exceptionState) | 337 RawPtr<Node> ContainerNode::replaceChild(RawPtr<Node> newChild, RawPtr<Node> old
Child, ExceptionState& exceptionState) |
| 338 { | 338 { |
| 339 #if !ENABLE(OILPAN) | 339 #if !ENABLE(OILPAN) |
| 340 // Check that this node is not "floating". | 340 // Check that this node is not "floating". |
| 341 // If it is, it can be deleted as a side effect of sending mutation events. | 341 // If it is, it can be deleted as a side effect of sending mutation events. |
| 342 ASSERT(refCount() || parentOrShadowHostNode()); | 342 DCHECK(refCount() || parentOrShadowHostNode()); |
| 343 #endif | 343 #endif |
| 344 | 344 |
| 345 RawPtr<Node> protect(this); | 345 RawPtr<Node> protect(this); |
| 346 | 346 |
| 347 if (oldChild == newChild) // Nothing to do. | 347 if (oldChild == newChild) // Nothing to do. |
| 348 return oldChild; | 348 return oldChild; |
| 349 | 349 |
| 350 if (!oldChild) { | 350 if (!oldChild) { |
| 351 exceptionState.throwDOMException(NotFoundError, "The node to be replaced
is null."); | 351 exceptionState.throwDOMException(NotFoundError, "The node to be replaced
is null."); |
| 352 return nullptr; | 352 return nullptr; |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 395 if (!checkAcceptChild(newChild.get(), child.get(), exceptionState)) { | 395 if (!checkAcceptChild(newChild.get(), child.get(), exceptionState)) { |
| 396 if (exceptionState.hadException()) | 396 if (exceptionState.hadException()) |
| 397 return nullptr; | 397 return nullptr; |
| 398 return child; | 398 return child; |
| 399 } | 399 } |
| 400 | 400 |
| 401 InspectorInstrumentation::willInsertDOMNode(this); | 401 InspectorInstrumentation::willInsertDOMNode(this); |
| 402 | 402 |
| 403 // Add the new child(ren). | 403 // Add the new child(ren). |
| 404 for (const auto& targetNode : targets) { | 404 for (const auto& targetNode : targets) { |
| 405 ASSERT(targetNode); | 405 DCHECK(targetNode); |
| 406 Node& child = *targetNode; | 406 Node& child = *targetNode; |
| 407 | 407 |
| 408 // Due to arbitrary code running in response to a DOM mutation event it'
s | 408 // Due to arbitrary code running in response to a DOM mutation event it'
s |
| 409 // possible that "next" is no longer a child of "this". | 409 // possible that "next" is no longer a child of "this". |
| 410 // It's also possible that "child" has been inserted elsewhere. | 410 // It's also possible that "child" has been inserted elsewhere. |
| 411 // In either of those cases, we'll just stop. | 411 // In either of those cases, we'll just stop. |
| 412 if (next && next->parentNode() != this) | 412 if (next && next->parentNode() != this) |
| 413 break; | 413 break; |
| 414 if (child.parentNode()) | 414 if (child.parentNode()) |
| 415 break; | 415 break; |
| (...skipping 11 matching lines...) Expand all Loading... |
| 427 | 427 |
| 428 updateTreeAfterInsertion(child); | 428 updateTreeAfterInsertion(child); |
| 429 } | 429 } |
| 430 | 430 |
| 431 dispatchSubtreeModifiedEvent(); | 431 dispatchSubtreeModifiedEvent(); |
| 432 return child; | 432 return child; |
| 433 } | 433 } |
| 434 | 434 |
| 435 void ContainerNode::willRemoveChild(Node& child) | 435 void ContainerNode::willRemoveChild(Node& child) |
| 436 { | 436 { |
| 437 ASSERT(child.parentNode() == this); | 437 DCHECK_EQ(child.parentNode(), this); |
| 438 ChildListMutationScope(*this).willRemoveChild(child); | 438 ChildListMutationScope(*this).willRemoveChild(child); |
| 439 child.notifyMutationObserversNodeWillDetach(); | 439 child.notifyMutationObserversNodeWillDetach(); |
| 440 dispatchChildRemovalEvents(child); | 440 dispatchChildRemovalEvents(child); |
| 441 ChildFrameDisconnector(child).disconnect(); | 441 ChildFrameDisconnector(child).disconnect(); |
| 442 if (document() != child.document()) { | 442 if (document() != child.document()) { |
| 443 // |child| was moved another document by DOM mutation event handler. | 443 // |child| was moved another document by DOM mutation event handler. |
| 444 return; | 444 return; |
| 445 } | 445 } |
| 446 | 446 |
| 447 // |nodeWillBeRemoved()| must be run after |ChildFrameDisconnector|, because | 447 // |nodeWillBeRemoved()| must be run after |ChildFrameDisconnector|, because |
| 448 // |ChildFrameDisconnector| can run script which may cause state that is to | 448 // |ChildFrameDisconnector| can run script which may cause state that is to |
| 449 // be invalidated by removing the node. | 449 // be invalidated by removing the node. |
| 450 ScriptForbiddenScope scriptForbiddenScope; | 450 ScriptForbiddenScope scriptForbiddenScope; |
| 451 EventDispatchForbiddenScope assertNoEventDispatch; | 451 EventDispatchForbiddenScope assertNoEventDispatch; |
| 452 // e.g. mutation event listener can create a new range. | 452 // e.g. mutation event listener can create a new range. |
| 453 document().nodeWillBeRemoved(child); | 453 document().nodeWillBeRemoved(child); |
| 454 } | 454 } |
| 455 | 455 |
| 456 void ContainerNode::willRemoveChildren() | 456 void ContainerNode::willRemoveChildren() |
| 457 { | 457 { |
| 458 NodeVector children; | 458 NodeVector children; |
| 459 getChildNodes(*this, children); | 459 getChildNodes(*this, children); |
| 460 | 460 |
| 461 ChildListMutationScope mutation(*this); | 461 ChildListMutationScope mutation(*this); |
| 462 for (const auto& node : children) { | 462 for (const auto& node : children) { |
| 463 ASSERT(node); | 463 DCHECK(node); |
| 464 Node& child = *node; | 464 Node& child = *node; |
| 465 mutation.willRemoveChild(child); | 465 mutation.willRemoveChild(child); |
| 466 child.notifyMutationObserversNodeWillDetach(); | 466 child.notifyMutationObserversNodeWillDetach(); |
| 467 dispatchChildRemovalEvents(child); | 467 dispatchChildRemovalEvents(child); |
| 468 } | 468 } |
| 469 | 469 |
| 470 ChildFrameDisconnector(*this).disconnect(ChildFrameDisconnector::Descendants
Only); | 470 ChildFrameDisconnector(*this).disconnect(ChildFrameDisconnector::Descendants
Only); |
| 471 } | 471 } |
| 472 | 472 |
| 473 #if !ENABLE(OILPAN) | 473 #if !ENABLE(OILPAN) |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 545 visitor->trace(m_firstChild); | 545 visitor->trace(m_firstChild); |
| 546 visitor->trace(m_lastChild); | 546 visitor->trace(m_lastChild); |
| 547 Node::trace(visitor); | 547 Node::trace(visitor); |
| 548 } | 548 } |
| 549 | 549 |
| 550 RawPtr<Node> ContainerNode::removeChild(RawPtr<Node> oldChild, ExceptionState& e
xceptionState) | 550 RawPtr<Node> ContainerNode::removeChild(RawPtr<Node> oldChild, ExceptionState& e
xceptionState) |
| 551 { | 551 { |
| 552 #if !ENABLE(OILPAN) | 552 #if !ENABLE(OILPAN) |
| 553 // Check that this node is not "floating". | 553 // Check that this node is not "floating". |
| 554 // If it is, it can be deleted as a side effect of sending mutation events. | 554 // If it is, it can be deleted as a side effect of sending mutation events. |
| 555 ASSERT(refCount() || parentOrShadowHostNode()); | 555 DCHECK(refCount() || parentOrShadowHostNode()); |
| 556 #endif | 556 #endif |
| 557 | 557 |
| 558 RawPtr<Node> protect(this); | 558 RawPtr<Node> protect(this); |
| 559 | 559 |
| 560 // NotFoundError: Raised if oldChild is not a child of this node. | 560 // NotFoundError: Raised if oldChild is not a child of this node. |
| 561 // FIXME: We should never really get PseudoElements in here, but editing wil
l sometimes | 561 // FIXME: We should never really get PseudoElements in here, but editing wil
l sometimes |
| 562 // attempt to remove them still. We should fix that and enable this ASSERT. | 562 // attempt to remove them still. We should fix that and enable this ASSERT. |
| 563 // ASSERT(!oldChild->isPseudoElement()) | 563 // DCHECK(!oldChild->isPseudoElement()) |
| 564 if (!oldChild || oldChild->parentNode() != this || oldChild->isPseudoElement
()) { | 564 if (!oldChild || oldChild->parentNode() != this || oldChild->isPseudoElement
()) { |
| 565 exceptionState.throwDOMException(NotFoundError, "The node to be removed
is not a child of this node."); | 565 exceptionState.throwDOMException(NotFoundError, "The node to be removed
is not a child of this node."); |
| 566 return nullptr; | 566 return nullptr; |
| 567 } | 567 } |
| 568 | 568 |
| 569 RawPtr<Node> child = oldChild; | 569 RawPtr<Node> child = oldChild; |
| 570 | 570 |
| 571 document().removeFocusedElementOfSubtree(child.get()); | 571 document().removeFocusedElementOfSubtree(child.get()); |
| 572 | 572 |
| 573 // Events fired when blurring currently focused node might have moved this | 573 // Events fired when blurring currently focused node might have moved this |
| (...skipping 22 matching lines...) Expand all Loading... |
| 596 childrenChanged(ChildrenChange::forRemoval(*child, prev, next, ChildrenC
hangeSourceAPI)); | 596 childrenChanged(ChildrenChange::forRemoval(*child, prev, next, ChildrenC
hangeSourceAPI)); |
| 597 } | 597 } |
| 598 dispatchSubtreeModifiedEvent(); | 598 dispatchSubtreeModifiedEvent(); |
| 599 return child; | 599 return child; |
| 600 } | 600 } |
| 601 | 601 |
| 602 void ContainerNode::removeBetween(Node* previousChild, Node* nextChild, Node& ol
dChild) | 602 void ContainerNode::removeBetween(Node* previousChild, Node* nextChild, Node& ol
dChild) |
| 603 { | 603 { |
| 604 EventDispatchForbiddenScope assertNoEventDispatch; | 604 EventDispatchForbiddenScope assertNoEventDispatch; |
| 605 | 605 |
| 606 ASSERT(oldChild.parentNode() == this); | 606 DCHECK_EQ(oldChild.parentNode(), this); |
| 607 | 607 |
| 608 AttachContext context; | 608 AttachContext context; |
| 609 context.clearInvalidation = true; | 609 context.clearInvalidation = true; |
| 610 if (!oldChild.needsAttach()) | 610 if (!oldChild.needsAttach()) |
| 611 oldChild.detach(context); | 611 oldChild.detach(context); |
| 612 | 612 |
| 613 if (nextChild) | 613 if (nextChild) |
| 614 nextChild->setPreviousSibling(previousChild); | 614 nextChild->setPreviousSibling(previousChild); |
| 615 if (previousChild) | 615 if (previousChild) |
| 616 previousChild->setNextSibling(nextChild); | 616 previousChild->setNextSibling(nextChild); |
| 617 if (m_firstChild == &oldChild) | 617 if (m_firstChild == &oldChild) |
| 618 m_firstChild = nextChild; | 618 m_firstChild = nextChild; |
| 619 if (m_lastChild == &oldChild) | 619 if (m_lastChild == &oldChild) |
| 620 m_lastChild = previousChild; | 620 m_lastChild = previousChild; |
| 621 | 621 |
| 622 oldChild.setPreviousSibling(nullptr); | 622 oldChild.setPreviousSibling(nullptr); |
| 623 oldChild.setNextSibling(nullptr); | 623 oldChild.setNextSibling(nullptr); |
| 624 oldChild.setParentOrShadowHostNode(nullptr); | 624 oldChild.setParentOrShadowHostNode(nullptr); |
| 625 | 625 |
| 626 document().adoptIfNeeded(oldChild); | 626 document().adoptIfNeeded(oldChild); |
| 627 } | 627 } |
| 628 | 628 |
| 629 void ContainerNode::parserRemoveChild(Node& oldChild) | 629 void ContainerNode::parserRemoveChild(Node& oldChild) |
| 630 { | 630 { |
| 631 ASSERT(oldChild.parentNode() == this); | 631 DCHECK_EQ(oldChild.parentNode(), this); |
| 632 ASSERT(!oldChild.isDocumentFragment()); | 632 DCHECK(!oldChild.isDocumentFragment()); |
| 633 | 633 |
| 634 // This may cause arbitrary Javascript execution via onunload handlers. | 634 // This may cause arbitrary Javascript execution via onunload handlers. |
| 635 if (oldChild.connectedSubframeCount()) | 635 if (oldChild.connectedSubframeCount()) |
| 636 ChildFrameDisconnector(oldChild).disconnect(); | 636 ChildFrameDisconnector(oldChild).disconnect(); |
| 637 | 637 |
| 638 if (oldChild.parentNode() != this) | 638 if (oldChild.parentNode() != this) |
| 639 return; | 639 return; |
| 640 | 640 |
| 641 ChildListMutationScope(*this).willRemoveChild(oldChild); | 641 ChildListMutationScope(*this).willRemoveChild(oldChild); |
| 642 oldChild.notifyMutationObserversNodeWillDetach(); | 642 oldChild.notifyMutationObserversNodeWillDetach(); |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 716 dispatchSubtreeModifiedEvent(); | 716 dispatchSubtreeModifiedEvent(); |
| 717 } | 717 } |
| 718 | 718 |
| 719 RawPtr<Node> ContainerNode::appendChild(RawPtr<Node> newChild, ExceptionState& e
xceptionState) | 719 RawPtr<Node> ContainerNode::appendChild(RawPtr<Node> newChild, ExceptionState& e
xceptionState) |
| 720 { | 720 { |
| 721 RawPtr<ContainerNode> protect(this); | 721 RawPtr<ContainerNode> protect(this); |
| 722 | 722 |
| 723 #if !ENABLE(OILPAN) | 723 #if !ENABLE(OILPAN) |
| 724 // Check that this node is not "floating". | 724 // Check that this node is not "floating". |
| 725 // If it is, it can be deleted as a side effect of sending mutation events. | 725 // If it is, it can be deleted as a side effect of sending mutation events. |
| 726 ASSERT(refCount() || parentOrShadowHostNode()); | 726 DCHECK(refCount() || parentOrShadowHostNode()); |
| 727 #endif | 727 #endif |
| 728 | 728 |
| 729 // Make sure adding the new child is ok | 729 // Make sure adding the new child is ok |
| 730 if (!checkAcceptChild(newChild.get(), 0, exceptionState)) { | 730 if (!checkAcceptChild(newChild.get(), 0, exceptionState)) { |
| 731 if (exceptionState.hadException()) | 731 if (exceptionState.hadException()) |
| 732 return nullptr; | 732 return nullptr; |
| 733 return newChild; | 733 return newChild; |
| 734 } | 734 } |
| 735 ASSERT(newChild); | 735 DCHECK(newChild); |
| 736 | 736 |
| 737 if (newChild == m_lastChild) // nothing to do | 737 if (newChild == m_lastChild) // nothing to do |
| 738 return newChild; | 738 return newChild; |
| 739 | 739 |
| 740 NodeVector targets; | 740 NodeVector targets; |
| 741 collectChildrenAndRemoveFromOldParent(*newChild, targets, exceptionState); | 741 collectChildrenAndRemoveFromOldParent(*newChild, targets, exceptionState); |
| 742 if (exceptionState.hadException()) | 742 if (exceptionState.hadException()) |
| 743 return nullptr; | 743 return nullptr; |
| 744 | 744 |
| 745 if (targets.isEmpty()) | 745 if (targets.isEmpty()) |
| 746 return newChild; | 746 return newChild; |
| 747 | 747 |
| 748 // We need this extra check because collectChildrenAndRemoveFromOldParent()
can fire mutation events. | 748 // We need this extra check because collectChildrenAndRemoveFromOldParent()
can fire mutation events. |
| 749 if (!checkAcceptChildGuaranteedNodeTypes(*newChild, nullptr, exceptionState)
) { | 749 if (!checkAcceptChildGuaranteedNodeTypes(*newChild, nullptr, exceptionState)
) { |
| 750 if (exceptionState.hadException()) | 750 if (exceptionState.hadException()) |
| 751 return nullptr; | 751 return nullptr; |
| 752 return newChild; | 752 return newChild; |
| 753 } | 753 } |
| 754 | 754 |
| 755 InspectorInstrumentation::willInsertDOMNode(this); | 755 InspectorInstrumentation::willInsertDOMNode(this); |
| 756 | 756 |
| 757 // Now actually add the child(ren). | 757 // Now actually add the child(ren). |
| 758 ChildListMutationScope mutation(*this); | 758 ChildListMutationScope mutation(*this); |
| 759 for (const auto& targetNode : targets) { | 759 for (const auto& targetNode : targets) { |
| 760 ASSERT(targetNode); | 760 DCHECK(targetNode); |
| 761 Node& child = *targetNode; | 761 Node& child = *targetNode; |
| 762 | 762 |
| 763 // If the child has a parent again, just stop what we're doing, because | 763 // If the child has a parent again, just stop what we're doing, because |
| 764 // that means someone is doing something with DOM mutation -- can't re-p
arent | 764 // that means someone is doing something with DOM mutation -- can't re-p
arent |
| 765 // a child that already has a parent. | 765 // a child that already has a parent. |
| 766 if (child.parentNode()) | 766 if (child.parentNode()) |
| 767 break; | 767 break; |
| 768 | 768 |
| 769 { | 769 { |
| 770 EventDispatchForbiddenScope assertNoEventDispatch; | 770 EventDispatchForbiddenScope assertNoEventDispatch; |
| 771 ScriptForbiddenScope forbidScript; | 771 ScriptForbiddenScope forbidScript; |
| 772 | 772 |
| 773 treeScope().adoptIfNeeded(child); | 773 treeScope().adoptIfNeeded(child); |
| 774 appendChildCommon(child); | 774 appendChildCommon(child); |
| 775 } | 775 } |
| 776 | 776 |
| 777 updateTreeAfterInsertion(child); | 777 updateTreeAfterInsertion(child); |
| 778 } | 778 } |
| 779 | 779 |
| 780 dispatchSubtreeModifiedEvent(); | 780 dispatchSubtreeModifiedEvent(); |
| 781 return newChild; | 781 return newChild; |
| 782 } | 782 } |
| 783 | 783 |
| 784 void ContainerNode::parserAppendChild(RawPtr<Node> newChild) | 784 void ContainerNode::parserAppendChild(RawPtr<Node> newChild) |
| 785 { | 785 { |
| 786 ASSERT(newChild); | 786 DCHECK(newChild); |
| 787 ASSERT(!newChild->isDocumentFragment()); | 787 DCHECK(!newChild->isDocumentFragment()); |
| 788 ASSERT(!isHTMLTemplateElement(this)); | 788 DCHECK(!isHTMLTemplateElement(this)); |
| 789 | 789 |
| 790 if (!checkParserAcceptChild(*newChild)) | 790 if (!checkParserAcceptChild(*newChild)) |
| 791 return; | 791 return; |
| 792 | 792 |
| 793 RawPtr<Node> protect(this); | 793 RawPtr<Node> protect(this); |
| 794 | 794 |
| 795 // FIXME: parserRemoveChild can run script which could then insert the | 795 // FIXME: parserRemoveChild can run script which could then insert the |
| 796 // newChild back into the page. Loop until the child is actually removed. | 796 // newChild back into the page. Loop until the child is actually removed. |
| 797 // See: fast/parser/execute-script-during-adoption-agency-removal.html | 797 // See: fast/parser/execute-script-during-adoption-agency-removal.html |
| 798 while (RawPtr<ContainerNode> parent = newChild->parentNode()) | 798 while (RawPtr<ContainerNode> parent = newChild->parentNode()) |
| 799 parent->parserRemoveChild(*newChild); | 799 parent->parserRemoveChild(*newChild); |
| 800 | 800 |
| 801 if (document() != newChild->document()) | 801 if (document() != newChild->document()) |
| 802 document().adoptNode(newChild.get(), ASSERT_NO_EXCEPTION); | 802 document().adoptNode(newChild.get(), ASSERT_NO_EXCEPTION); |
| 803 | 803 |
| 804 { | 804 { |
| 805 EventDispatchForbiddenScope assertNoEventDispatch; | 805 EventDispatchForbiddenScope assertNoEventDispatch; |
| 806 ScriptForbiddenScope forbidScript; | 806 ScriptForbiddenScope forbidScript; |
| 807 | 807 |
| 808 treeScope().adoptIfNeeded(*newChild); | 808 treeScope().adoptIfNeeded(*newChild); |
| 809 appendChildCommon(*newChild); | 809 appendChildCommon(*newChild); |
| 810 ASSERT(newChild->connectedSubframeCount() == 0); | 810 DCHECK_EQ(newChild->connectedSubframeCount(), 0u); |
| 811 ChildListMutationScope(*this).childAdded(*newChild); | 811 ChildListMutationScope(*this).childAdded(*newChild); |
| 812 } | 812 } |
| 813 | 813 |
| 814 notifyNodeInserted(*newChild, ChildrenChangeSourceParser); | 814 notifyNodeInserted(*newChild, ChildrenChangeSourceParser); |
| 815 } | 815 } |
| 816 | 816 |
| 817 void ContainerNode::notifyNodeInserted(Node& root, ChildrenChangeSource source) | 817 void ContainerNode::notifyNodeInserted(Node& root, ChildrenChangeSource source) |
| 818 { | 818 { |
| 819 ASSERT(!EventDispatchForbiddenScope::isEventDispatchForbidden()); | 819 #if DCHECK_IS_ON() |
| 820 ASSERT(!root.isShadowRoot()); | 820 DCHECK(!EventDispatchForbiddenScope::isEventDispatchForbidden()); |
| 821 #endif |
| 822 DCHECK(!root.isShadowRoot()); |
| 821 | 823 |
| 822 InspectorInstrumentation::didInsertDOMNode(&root); | 824 InspectorInstrumentation::didInsertDOMNode(&root); |
| 823 | 825 |
| 824 RawPtr<Node> protect(this); | 826 RawPtr<Node> protect(this); |
| 825 RawPtr<Node> protectNode(root); | 827 RawPtr<Node> protectNode(root); |
| 826 | 828 |
| 827 NodeVector postInsertionNotificationTargets; | 829 NodeVector postInsertionNotificationTargets; |
| 828 notifyNodeInsertedInternal(root, postInsertionNotificationTargets); | 830 notifyNodeInsertedInternal(root, postInsertionNotificationTargets); |
| 829 | 831 |
| 830 childrenChanged(ChildrenChange::forInsertion(root, source)); | 832 childrenChanged(ChildrenChange::forInsertion(root, source)); |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 868 notifyNodeRemoved(*shadowRoot); | 870 notifyNodeRemoved(*shadowRoot); |
| 869 } | 871 } |
| 870 } | 872 } |
| 871 | 873 |
| 872 void ContainerNode::attach(const AttachContext& context) | 874 void ContainerNode::attach(const AttachContext& context) |
| 873 { | 875 { |
| 874 AttachContext childrenContext(context); | 876 AttachContext childrenContext(context); |
| 875 childrenContext.resolvedStyle = nullptr; | 877 childrenContext.resolvedStyle = nullptr; |
| 876 | 878 |
| 877 for (Node* child = firstChild(); child; child = child->nextSibling()) { | 879 for (Node* child = firstChild(); child; child = child->nextSibling()) { |
| 878 ASSERT(child->needsAttach() || childAttachedAllowedWhenAttachingChildren
(this)); | 880 #if DCHECK_IS_ON() |
| 881 DCHECK(child->needsAttach() || childAttachedAllowedWhenAttachingChildren
(this)); |
| 882 #endif |
| 879 if (child->needsAttach()) | 883 if (child->needsAttach()) |
| 880 child->attach(childrenContext); | 884 child->attach(childrenContext); |
| 881 } | 885 } |
| 882 | 886 |
| 883 clearChildNeedsStyleRecalc(); | 887 clearChildNeedsStyleRecalc(); |
| 884 Node::attach(context); | 888 Node::attach(context); |
| 885 } | 889 } |
| 886 | 890 |
| 887 void ContainerNode::detach(const AttachContext& context) | 891 void ContainerNode::detach(const AttachContext& context) |
| 888 { | 892 { |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 940 LayoutObject* next = nullptr; | 944 LayoutObject* next = nullptr; |
| 941 while (!next && o->parent()) { | 945 while (!next && o->parent()) { |
| 942 o = o->parent(); | 946 o = o->parent(); |
| 943 next = o->nextSibling(); | 947 next = o->nextSibling(); |
| 944 } | 948 } |
| 945 o = next; | 949 o = next; |
| 946 | 950 |
| 947 if (!o) | 951 if (!o) |
| 948 break; | 952 break; |
| 949 } | 953 } |
| 950 ASSERT(o); | 954 DCHECK(o); |
| 951 | 955 |
| 952 if (!o->isInline() || o->isAtomicInlineLevel()) { | 956 if (!o->isInline() || o->isAtomicInlineLevel()) { |
| 953 point = o->localToAbsolute(FloatPoint(), UseTransforms); | 957 point = o->localToAbsolute(FloatPoint(), UseTransforms); |
| 954 return true; | 958 return true; |
| 955 } | 959 } |
| 956 | 960 |
| 957 if (p->node() && p->node() == this && o->isText() && !o->isBR() && !toLa
youtText(o)->hasTextBoxes()) { | 961 if (p->node() && p->node() == this && o->isText() && !o->isBR() && !toLa
youtText(o)->hasTextBoxes()) { |
| 958 // Do nothing - skip unrendered whitespace that is a child or next s
ibling of the anchor. | 962 // Do nothing - skip unrendered whitespace that is a child or next s
ibling of the anchor. |
| 959 // FIXME: This fails to skip a whitespace sibling when there was als
o a whitespace child (because p has moved). | 963 // FIXME: This fails to skip a whitespace sibling when there was als
o a whitespace child (because p has moved). |
| 960 } else if ((o->isText() && !o->isBR()) || o->isAtomicInlineLevel()) { | 964 } else if ((o->isText() && !o->isBR()) || o->isAtomicInlineLevel()) { |
| 961 point = FloatPoint(); | 965 point = FloatPoint(); |
| 962 if (o->isText()) { | 966 if (o->isText()) { |
| 963 if (toLayoutText(o)->firstTextBox()) | 967 if (toLayoutText(o)->firstTextBox()) |
| 964 point.move(toLayoutText(o)->linesBoundingBox().x(), toLayout
Text(o)->firstTextBox()->root().lineTop().toFloat()); | 968 point.move(toLayoutText(o)->linesBoundingBox().x(), toLayout
Text(o)->firstTextBox()->root().lineTop().toFloat()); |
| 965 point = o->localToAbsolute(point, UseTransforms); | 969 point = o->localToAbsolute(point, UseTransforms); |
| 966 } else { | 970 } else { |
| 967 ASSERT(o->isBox()); | 971 DCHECK(o->isBox()); |
| 968 LayoutBox* box = toLayoutBox(o); | 972 LayoutBox* box = toLayoutBox(o); |
| 969 point.moveBy(box->location()); | 973 point.moveBy(box->location()); |
| 970 point = o->container()->localToAbsolute(point, UseTransforms); | 974 point = o->container()->localToAbsolute(point, UseTransforms); |
| 971 } | 975 } |
| 972 return true; | 976 return true; |
| 973 } | 977 } |
| 974 } | 978 } |
| 975 | 979 |
| 976 // If the target doesn't have any children or siblings that could be used to
calculate the scroll position, we must be | 980 // If the target doesn't have any children or siblings that could be used to
calculate the scroll position, we must be |
| 977 // at the end of the document. Scroll to the bottom. FIXME: who said anythin
g about scrolling? | 981 // at the end of the document. Scroll to the bottom. FIXME: who said anythin
g about scrolling? |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1039 if (o == layoutObject()) { | 1043 if (o == layoutObject()) { |
| 1040 return false; | 1044 return false; |
| 1041 } | 1045 } |
| 1042 o = o->parent(); | 1046 o = o->parent(); |
| 1043 if (!o) | 1047 if (!o) |
| 1044 return false; | 1048 return false; |
| 1045 prev = o->previousSibling(); | 1049 prev = o->previousSibling(); |
| 1046 } | 1050 } |
| 1047 o = prev; | 1051 o = prev; |
| 1048 } | 1052 } |
| 1049 ASSERT(o); | 1053 DCHECK(o); |
| 1050 if (o->isText() || o->isAtomicInlineLevel()) { | 1054 if (o->isText() || o->isAtomicInlineLevel()) { |
| 1051 point = FloatPoint(); | 1055 point = FloatPoint(); |
| 1052 if (o->isText()) { | 1056 if (o->isText()) { |
| 1053 LayoutText* text = toLayoutText(o); | 1057 LayoutText* text = toLayoutText(o); |
| 1054 IntRect linesBox = text->linesBoundingBox(); | 1058 IntRect linesBox = text->linesBoundingBox(); |
| 1055 if (!linesBox.maxX() && !linesBox.maxY()) | 1059 if (!linesBox.maxX() && !linesBox.maxY()) |
| 1056 continue; | 1060 continue; |
| 1057 point.moveBy(linesBox.maxXMaxYCorner()); | 1061 point.moveBy(linesBox.maxXMaxYCorner()); |
| 1058 point = o->localToAbsolute(point, UseTransforms); | 1062 point = o->localToAbsolute(point, UseTransforms); |
| 1059 } else { | 1063 } else { |
| (...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1232 | 1236 |
| 1233 NthIndexCache nthIndexCache(document()); | 1237 NthIndexCache nthIndexCache(document()); |
| 1234 return selectorQuery->queryAll(*this); | 1238 return selectorQuery->queryAll(*this); |
| 1235 } | 1239 } |
| 1236 | 1240 |
| 1237 static void dispatchChildInsertionEvents(Node& child) | 1241 static void dispatchChildInsertionEvents(Node& child) |
| 1238 { | 1242 { |
| 1239 if (child.isInShadowTree()) | 1243 if (child.isInShadowTree()) |
| 1240 return; | 1244 return; |
| 1241 | 1245 |
| 1242 ASSERT(!EventDispatchForbiddenScope::isEventDispatchForbidden()); | 1246 #if DCHECK_IS_ON() |
| 1247 DCHECK(!EventDispatchForbiddenScope::isEventDispatchForbidden()); |
| 1248 #endif |
| 1243 | 1249 |
| 1244 RawPtr<Node> c(child); | 1250 RawPtr<Node> c(child); |
| 1245 RawPtr<Document> document(child.document()); | 1251 RawPtr<Document> document(child.document()); |
| 1246 | 1252 |
| 1247 if (c->parentNode() && document->hasListenerType(Document::DOMNODEINSERTED_L
ISTENER)) | 1253 if (c->parentNode() && document->hasListenerType(Document::DOMNODEINSERTED_L
ISTENER)) |
| 1248 c->dispatchScopedEvent(MutationEvent::create(EventTypeNames::DOMNodeInse
rted, true, c->parentNode())); | 1254 c->dispatchScopedEvent(MutationEvent::create(EventTypeNames::DOMNodeInse
rted, true, c->parentNode())); |
| 1249 | 1255 |
| 1250 // dispatch the DOMNodeInsertedIntoDocument event to all descendants | 1256 // dispatch the DOMNodeInsertedIntoDocument event to all descendants |
| 1251 if (c->inShadowIncludingDocument() && document->hasListenerType(Document::DO
MNODEINSERTEDINTODOCUMENT_LISTENER)) { | 1257 if (c->inShadowIncludingDocument() && document->hasListenerType(Document::DO
MNODEINSERTEDINTODOCUMENT_LISTENER)) { |
| 1252 for (; c; c = NodeTraversal::next(*c, &child)) | 1258 for (; c; c = NodeTraversal::next(*c, &child)) |
| 1253 c->dispatchScopedEvent(MutationEvent::create(EventTypeNames::DOMNode
InsertedIntoDocument, false)); | 1259 c->dispatchScopedEvent(MutationEvent::create(EventTypeNames::DOMNode
InsertedIntoDocument, false)); |
| 1254 } | 1260 } |
| 1255 } | 1261 } |
| 1256 | 1262 |
| 1257 static void dispatchChildRemovalEvents(Node& child) | 1263 static void dispatchChildRemovalEvents(Node& child) |
| 1258 { | 1264 { |
| 1259 if (child.isInShadowTree()) { | 1265 if (child.isInShadowTree()) { |
| 1260 InspectorInstrumentation::willRemoveDOMNode(&child); | 1266 InspectorInstrumentation::willRemoveDOMNode(&child); |
| 1261 return; | 1267 return; |
| 1262 } | 1268 } |
| 1263 | 1269 |
| 1264 ASSERT(!EventDispatchForbiddenScope::isEventDispatchForbidden()); | 1270 #if DCHECK_IS_ON() |
| 1271 DCHECK(!EventDispatchForbiddenScope::isEventDispatchForbidden()); |
| 1272 #endif |
| 1265 | 1273 |
| 1266 InspectorInstrumentation::willRemoveDOMNode(&child); | 1274 InspectorInstrumentation::willRemoveDOMNode(&child); |
| 1267 | 1275 |
| 1268 RawPtr<Node> c(child); | 1276 RawPtr<Node> c(child); |
| 1269 RawPtr<Document> document(child.document()); | 1277 RawPtr<Document> document(child.document()); |
| 1270 | 1278 |
| 1271 // Dispatch pre-removal mutation events. | 1279 // Dispatch pre-removal mutation events. |
| 1272 if (c->parentNode() && document->hasListenerType(Document::DOMNODEREMOVED_LI
STENER)) { | 1280 if (c->parentNode() && document->hasListenerType(Document::DOMNODEREMOVED_LI
STENER)) { |
| 1273 NodeChildRemovalTracker scope(child); | 1281 NodeChildRemovalTracker scope(child); |
| 1274 c->dispatchScopedEvent(MutationEvent::create(EventTypeNames::DOMNodeRemo
ved, true, c->parentNode())); | 1282 c->dispatchScopedEvent(MutationEvent::create(EventTypeNames::DOMNodeRemo
ved, true, c->parentNode())); |
| 1275 } | 1283 } |
| 1276 | 1284 |
| 1277 // Dispatch the DOMNodeRemovedFromDocument event to all descendants. | 1285 // Dispatch the DOMNodeRemovedFromDocument event to all descendants. |
| 1278 if (c->inShadowIncludingDocument() && document->hasListenerType(Document::DO
MNODEREMOVEDFROMDOCUMENT_LISTENER)) { | 1286 if (c->inShadowIncludingDocument() && document->hasListenerType(Document::DO
MNODEREMOVEDFROMDOCUMENT_LISTENER)) { |
| 1279 NodeChildRemovalTracker scope(child); | 1287 NodeChildRemovalTracker scope(child); |
| 1280 for (; c; c = NodeTraversal::next(*c, &child)) | 1288 for (; c; c = NodeTraversal::next(*c, &child)) |
| 1281 c->dispatchScopedEvent(MutationEvent::create(EventTypeNames::DOMNode
RemovedFromDocument, false)); | 1289 c->dispatchScopedEvent(MutationEvent::create(EventTypeNames::DOMNode
RemovedFromDocument, false)); |
| 1282 } | 1290 } |
| 1283 } | 1291 } |
| 1284 | 1292 |
| 1285 void ContainerNode::updateTreeAfterInsertion(Node& child) | 1293 void ContainerNode::updateTreeAfterInsertion(Node& child) |
| 1286 { | 1294 { |
| 1287 #if !ENABLE(OILPAN) | 1295 #if !ENABLE(OILPAN) |
| 1288 ASSERT(refCount()); | 1296 DCHECK(refCount()); |
| 1289 ASSERT(child.refCount()); | 1297 DCHECK(child.refCount()); |
| 1290 #endif | 1298 #endif |
| 1291 | 1299 |
| 1292 ChildListMutationScope(*this).childAdded(child); | 1300 ChildListMutationScope(*this).childAdded(child); |
| 1293 | 1301 |
| 1294 notifyNodeInserted(child); | 1302 notifyNodeInserted(child); |
| 1295 | 1303 |
| 1296 dispatchChildInsertionEvents(child); | 1304 dispatchChildInsertionEvents(child); |
| 1297 } | 1305 } |
| 1298 | 1306 |
| 1299 bool ContainerNode::hasRestyleFlagInternal(DynamicRestyleFlags mask) const | 1307 bool ContainerNode::hasRestyleFlagInternal(DynamicRestyleFlags mask) const |
| 1300 { | 1308 { |
| 1301 return rareData()->hasRestyleFlag(mask); | 1309 return rareData()->hasRestyleFlag(mask); |
| 1302 } | 1310 } |
| 1303 | 1311 |
| 1304 bool ContainerNode::hasRestyleFlagsInternal() const | 1312 bool ContainerNode::hasRestyleFlagsInternal() const |
| 1305 { | 1313 { |
| 1306 return rareData()->hasRestyleFlags(); | 1314 return rareData()->hasRestyleFlags(); |
| 1307 } | 1315 } |
| 1308 | 1316 |
| 1309 void ContainerNode::setRestyleFlag(DynamicRestyleFlags mask) | 1317 void ContainerNode::setRestyleFlag(DynamicRestyleFlags mask) |
| 1310 { | 1318 { |
| 1311 ASSERT(isElementNode() || isShadowRoot()); | 1319 DCHECK(isElementNode() || isShadowRoot()); |
| 1312 ensureRareData().setRestyleFlag(mask); | 1320 ensureRareData().setRestyleFlag(mask); |
| 1313 } | 1321 } |
| 1314 | 1322 |
| 1315 void ContainerNode::recalcChildStyle(StyleRecalcChange change) | 1323 void ContainerNode::recalcChildStyle(StyleRecalcChange change) |
| 1316 { | 1324 { |
| 1317 ASSERT(document().inStyleRecalc()); | 1325 DCHECK(document().inStyleRecalc()); |
| 1318 ASSERT(change >= UpdatePseudoElements || childNeedsStyleRecalc()); | 1326 DCHECK(change >= UpdatePseudoElements || childNeedsStyleRecalc()); |
| 1319 ASSERT(!needsStyleRecalc()); | 1327 DCHECK(!needsStyleRecalc()); |
| 1320 | 1328 |
| 1321 // This loop is deliberately backwards because we use insertBefore in the la
yout tree, and want to avoid | 1329 // This loop is deliberately backwards because we use insertBefore in the la
yout tree, and want to avoid |
| 1322 // a potentially n^2 loop to find the insertion point while resolving style.
Having us start from the last | 1330 // a potentially n^2 loop to find the insertion point while resolving style.
Having us start from the last |
| 1323 // child and work our way back means in the common case, we'll find the inse
rtion point in O(1) time. | 1331 // child and work our way back means in the common case, we'll find the inse
rtion point in O(1) time. |
| 1324 // See crbug.com/288225 | 1332 // See crbug.com/288225 |
| 1325 StyleResolver& styleResolver = document().ensureStyleResolver(); | 1333 StyleResolver& styleResolver = document().ensureStyleResolver(); |
| 1326 Text* lastTextNode = nullptr; | 1334 Text* lastTextNode = nullptr; |
| 1327 for (Node* child = lastChild(); child; child = child->previousSibling()) { | 1335 for (Node* child = lastChild(); child; child = child->previousSibling()) { |
| 1328 if (child->isTextNode()) { | 1336 if (child->isTextNode()) { |
| 1329 toText(child)->recalcTextStyle(change, lastTextNode); | 1337 toText(child)->recalcTextStyle(change, lastTextNode); |
| (...skipping 26 matching lines...) Expand all Loading... |
| 1356 if (((childrenAffectedByForwardPositionalRules() || childrenAffectedByIndire
ctAdjacentRules()) && nodeAfterChange) | 1364 if (((childrenAffectedByForwardPositionalRules() || childrenAffectedByIndire
ctAdjacentRules()) && nodeAfterChange) |
| 1357 || (childrenAffectedByBackwardPositionalRules() && nodeBeforeChange)) { | 1365 || (childrenAffectedByBackwardPositionalRules() && nodeBeforeChange)) { |
| 1358 setNeedsStyleRecalc(SubtreeStyleChange, StyleChangeReasonForTracing::cre
ate(StyleChangeReason::SiblingSelector)); | 1366 setNeedsStyleRecalc(SubtreeStyleChange, StyleChangeReasonForTracing::cre
ate(StyleChangeReason::SiblingSelector)); |
| 1359 return; | 1367 return; |
| 1360 } | 1368 } |
| 1361 | 1369 |
| 1362 // :first-child. In the parser callback case, we don't have to check anythin
g, since we were right the first time. | 1370 // :first-child. In the parser callback case, we don't have to check anythin
g, since we were right the first time. |
| 1363 // In the DOM case, we only need to do something if |afterChange| is not 0. | 1371 // In the DOM case, we only need to do something if |afterChange| is not 0. |
| 1364 // |afterChange| is 0 in the parser case, so it works out that we'll skip th
is block. | 1372 // |afterChange| is 0 in the parser case, so it works out that we'll skip th
is block. |
| 1365 if (childrenAffectedByFirstChildRules() && nodeAfterChange) { | 1373 if (childrenAffectedByFirstChildRules() && nodeAfterChange) { |
| 1366 ASSERT(changeType != FinishedParsingChildren); | 1374 DCHECK_NE(changeType, FinishedParsingChildren); |
| 1367 // Find our new first child element. | 1375 // Find our new first child element. |
| 1368 Element* firstChildElement = ElementTraversal::firstChild(*this); | 1376 Element* firstChildElement = ElementTraversal::firstChild(*this); |
| 1369 | 1377 |
| 1370 // Find the first element after the change. | 1378 // Find the first element after the change. |
| 1371 Element* elementAfterChange = nodeAfterChange->isElementNode() ? toEleme
nt(nodeAfterChange) : ElementTraversal::nextSibling(*nodeAfterChange); | 1379 Element* elementAfterChange = nodeAfterChange->isElementNode() ? toEleme
nt(nodeAfterChange) : ElementTraversal::nextSibling(*nodeAfterChange); |
| 1372 | 1380 |
| 1373 // This is the element insertion as first child element case. | 1381 // This is the element insertion as first child element case. |
| 1374 if (changeType == SiblingElementInserted && elementAfterChange && firstC
hildElement != elementAfterChange | 1382 if (changeType == SiblingElementInserted && elementAfterChange && firstC
hildElement != elementAfterChange |
| 1375 && (!nodeBeforeChange || !nodeBeforeChange->isElementNode()) && elem
entAfterChange->affectedByFirstChildRules()) { | 1383 && (!nodeBeforeChange || !nodeBeforeChange->isElementNode()) && elem
entAfterChange->affectedByFirstChildRules()) { |
| 1376 elementAfterChange->setNeedsStyleRecalc(SubtreeStyleChange, StyleCha
ngeReasonForTracing::create(StyleChangeReason::SiblingSelector)); | 1384 elementAfterChange->setNeedsStyleRecalc(SubtreeStyleChange, StyleCha
ngeReasonForTracing::create(StyleChangeReason::SiblingSelector)); |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1459 | 1467 |
| 1460 // Takes an AtomicString in argument because it is common for elements to share
the same set of class names. | 1468 // Takes an AtomicString in argument because it is common for elements to share
the same set of class names. |
| 1461 // Therefore, the ClassNodeList factory function expects an AtomicString type. | 1469 // Therefore, the ClassNodeList factory function expects an AtomicString type. |
| 1462 RawPtr<ClassCollection> ContainerNode::getElementsByClassName(const AtomicString
& classNames) | 1470 RawPtr<ClassCollection> ContainerNode::getElementsByClassName(const AtomicString
& classNames) |
| 1463 { | 1471 { |
| 1464 return ensureCachedCollection<ClassCollection>(ClassCollectionType, classNam
es); | 1472 return ensureCachedCollection<ClassCollection>(ClassCollectionType, classNam
es); |
| 1465 } | 1473 } |
| 1466 | 1474 |
| 1467 RawPtr<RadioNodeList> ContainerNode::radioNodeList(const AtomicString& name, boo
l onlyMatchImgElements) | 1475 RawPtr<RadioNodeList> ContainerNode::radioNodeList(const AtomicString& name, boo
l onlyMatchImgElements) |
| 1468 { | 1476 { |
| 1469 ASSERT(isHTMLFormElement(this) || isHTMLFieldSetElement(this)); | 1477 DCHECK(isHTMLFormElement(this) || isHTMLFieldSetElement(this)); |
| 1470 CollectionType type = onlyMatchImgElements ? RadioImgNodeListType : RadioNod
eListType; | 1478 CollectionType type = onlyMatchImgElements ? RadioImgNodeListType : RadioNod
eListType; |
| 1471 return ensureCachedCollection<RadioNodeList>(type, name); | 1479 return ensureCachedCollection<RadioNodeList>(type, name); |
| 1472 } | 1480 } |
| 1473 | 1481 |
| 1474 Element* ContainerNode::getElementById(const AtomicString& id) const | 1482 Element* ContainerNode::getElementById(const AtomicString& id) const |
| 1475 { | 1483 { |
| 1476 if (isInTreeScope()) { | 1484 if (isInTreeScope()) { |
| 1477 // Fast path if we are in a tree scope: call getElementById() on tree sc
ope | 1485 // Fast path if we are in a tree scope: call getElementById() on tree sc
ope |
| 1478 // and check if the matching element is in our subtree. | 1486 // and check if the matching element is in our subtree. |
| 1479 Element* element = treeScope().getElementById(id); | 1487 Element* element = treeScope().getElementById(id); |
| 1480 if (!element) | 1488 if (!element) |
| 1481 return nullptr; | 1489 return nullptr; |
| 1482 if (element->isDescendantOf(this)) | 1490 if (element->isDescendantOf(this)) |
| 1483 return element; | 1491 return element; |
| 1484 } | 1492 } |
| 1485 | 1493 |
| 1486 // Fall back to traversing our subtree. In case of duplicate ids, the first
element found will be returned. | 1494 // Fall back to traversing our subtree. In case of duplicate ids, the first
element found will be returned. |
| 1487 for (Element& element : ElementTraversal::descendantsOf(*this)) { | 1495 for (Element& element : ElementTraversal::descendantsOf(*this)) { |
| 1488 if (element.getIdAttribute() == id) | 1496 if (element.getIdAttribute() == id) |
| 1489 return &element; | 1497 return &element; |
| 1490 } | 1498 } |
| 1491 return nullptr; | 1499 return nullptr; |
| 1492 } | 1500 } |
| 1493 | 1501 |
| 1494 NodeListsNodeData& ContainerNode::ensureNodeLists() | 1502 NodeListsNodeData& ContainerNode::ensureNodeLists() |
| 1495 { | 1503 { |
| 1496 return ensureRareData().ensureNodeLists(); | 1504 return ensureRareData().ensureNodeLists(); |
| 1497 } | 1505 } |
| 1498 | 1506 |
| 1499 #if ENABLE(ASSERT) | 1507 #if DCHECK_IS_ON() |
| 1500 bool childAttachedAllowedWhenAttachingChildren(ContainerNode* node) | 1508 bool childAttachedAllowedWhenAttachingChildren(ContainerNode* node) |
| 1501 { | 1509 { |
| 1502 if (node->isShadowRoot()) | 1510 if (node->isShadowRoot()) |
| 1503 return true; | 1511 return true; |
| 1504 | 1512 |
| 1505 if (node->isInsertionPoint()) | 1513 if (node->isInsertionPoint()) |
| 1506 return true; | 1514 return true; |
| 1507 | 1515 |
| 1508 if (isHTMLSlotElement(node)) | 1516 if (isHTMLSlotElement(node)) |
| 1509 return true; | 1517 return true; |
| 1510 | 1518 |
| 1511 if (node->isElementNode() && toElement(node)->shadow()) | 1519 if (node->isElementNode() && toElement(node)->shadow()) |
| 1512 return true; | 1520 return true; |
| 1513 | 1521 |
| 1514 return false; | 1522 return false; |
| 1515 } | 1523 } |
| 1516 #endif | 1524 #endif |
| 1517 | 1525 |
| 1518 } // namespace blink | 1526 } // namespace blink |
| OLD | NEW |