// this differs from other remove functions because it forcibly removes all the children, // regardless of read-only status or event exceptions, e.g. void ContainerNode::removeChildren() { if (!m_firstChild) return; // The container node can be removed from event handlers. Ref<ContainerNode> protect(*this); // exclude this node when looking for removed focusedNode since only children will be removed document().removeFocusedNodeOfSubtree(this, true); #if ENABLE(FULLSCREEN_API) document().removeFullScreenElementOfSubtree(this, true); #endif // Do any prep work needed before actually starting to detach // and remove... e.g. stop loading frames, fire unload events. willRemoveChildren(*this); NodeVector removedChildren; { WidgetHierarchyUpdatesSuspensionScope suspendWidgetHierarchyUpdates; { NoEventDispatchAssertion assertNoEventDispatch; removedChildren.reserveInitialCapacity(countChildNodes()); while (RefPtr<Node> n = m_firstChild) { removedChildren.append(*m_firstChild); removeBetween(0, m_firstChild->nextSibling(), *m_firstChild); } } ChildChange change = { AllChildrenRemoved, nullptr, nullptr, ChildChangeSourceAPI }; childrenChanged(change); for (size_t i = 0; i < removedChildren.size(); ++i) ChildNodeRemovalNotifier(*this).notify(removedChildren[i].get()); } if (document().svgExtensions()) { Element* shadowHost = this->shadowHost(); if (!shadowHost || !shadowHost->hasTagName(SVGNames::useTag)) document().accessSVGExtensions()->rebuildElements(); } dispatchSubtreeModifiedEvent(); }
// this differs from other remove functions because it forcibly removes all the children, // regardless of read-only status or event exceptions, e.g. void ContainerNode::removeChildren() { if (!m_firstChild) return; // The container node can be removed from event handlers. RefPtr<ContainerNode> protect(this); // exclude this node when looking for removed focusedNode since only children will be removed document().removeFocusedNodeOfSubtree(this, true); #if ENABLE(FULLSCREEN_API) document().removeFullScreenElementOfSubtree(this, true); #endif // Do any prep work needed before actually starting to detach // and remove... e.g. stop loading frames, fire unload events. willRemoveChildren(protect.get()); NodeVector removedChildren; { WidgetHierarchyUpdatesSuspensionScope suspendWidgetHierarchyUpdates; { NoEventDispatchAssertion assertNoEventDispatch; removedChildren.reserveInitialCapacity(childNodeCount()); while (RefPtr<Node> n = m_firstChild) { removedChildren.append(m_firstChild); removeBetween(0, m_firstChild->nextSibling(), m_firstChild); } } childrenChanged(false, 0, 0, -static_cast<int>(removedChildren.size())); for (size_t i = 0; i < removedChildren.size(); ++i) ChildNodeRemovalNotifier(this).notify(removedChildren[i].get()); } dispatchSubtreeModifiedEvent(); }
// this differs from other remove functions because it forcibly removes all the children, // regardless of read-only status or event exceptions, e.g. void ContainerNode::removeChildren() { if (!m_firstChild) return; // The container node can be removed from event handlers. RefPtr<ContainerNode> protect(this); // exclude this node when looking for removed focusedNode since only children will be removed document()->removeFocusedNodeOfSubtree(this, true); #if ENABLE(FULLSCREEN_API) document()->removeFullScreenElementOfSubtree(this, true); #endif // Do any prep work needed before actually starting to detach // and remove... e.g. stop loading frames, fire unload events. willRemoveChildren(protect.get()); Vector<RefPtr<Node>, 10> removedChildren; { WidgetHierarchyUpdatesSuspensionScope suspendWidgetHierarchyUpdates; NoEventDispatchAssertion assertNoEventDispatch; removedChildren.reserveInitialCapacity(childNodeCount()); while (RefPtr<Node> n = m_firstChild) { Node* next = n->nextSibling(); // Remove the node from the tree before calling detach or removedFromDocument (4427024, 4129744). // removeChild() does this after calling detach(). There is no explanation for // this discrepancy between removeChild() and its optimized version removeChildren(). n->setPreviousSibling(0); n->setNextSibling(0); n->setParentOrHostNode(0); document()->adoptIfNeeded(n.get()); m_firstChild = next; if (n == m_lastChild) m_lastChild = 0; removedChildren.append(n.release()); } size_t removedChildrenCount = removedChildren.size(); size_t i; // Detach the nodes only after properly removed from the tree because // a. detaching requires a proper DOM tree (for counters and quotes for // example) and during the previous loop the next sibling still points to // the node being removed while the node being removed does not point back // and does not point to the same parent as its next sibling. // b. destroying Renderers of standalone nodes is sometimes faster. for (i = 0; i < removedChildrenCount; ++i) { Node* removedChild = removedChildren[i].get(); if (removedChild->attached()) removedChild->detach(); } childrenChanged(false, 0, 0, -static_cast<int>(removedChildrenCount)); for (i = 0; i < removedChildrenCount; ++i) ChildNodeRemovalNotifier(this).notify(removedChildren[i].get()); } dispatchSubtreeModifiedEvent(); }