PassRefPtr<Text> Text::replaceWholeText(const String& newText, ExceptionCode&) { // Remove all adjacent text nodes, and replace the contents of this one. // Protect startText and endText against mutation event handlers removing the last ref RefPtr<Text> startText = const_cast<Text*>(earliestLogicallyAdjacentTextNode(this)); RefPtr<Text> endText = const_cast<Text*>(latestLogicallyAdjacentTextNode(this)); RefPtr<Text> protectedThis(this); // Mutation event handlers could cause our last ref to go away ContainerNode* parent = parentNode(); // Protect against mutation handlers moving this node during traversal ExceptionCode ignored = 0; for (RefPtr<Node> n = startText; n && n != this && n->isTextNode() && n->parentNode() == parent;) { RefPtr<Node> nodeToRemove(n.release()); n = nodeToRemove->nextSibling(); parent->removeChild(nodeToRemove.get(), ignored); } if (this != endText) { Node* onePastEndText = endText->nextSibling(); for (RefPtr<Node> n = nextSibling(); n && n != onePastEndText && n->isTextNode() && n->parentNode() == parent;) { RefPtr<Node> nodeToRemove(n.release()); n = nodeToRemove->nextSibling(); parent->removeChild(nodeToRemove.get(), ignored); } } if (newText.isEmpty()) { if (parent && parentNode() == parent) parent->removeChild(this, ignored); return 0; } setData(newText, ignored); return protectedThis.release(); }
static void swapInNodePreservingAttributesAndChildren(HTMLElement* newNode, HTMLElement* nodeToReplace) { ASSERT(nodeToReplace->inDocument()); ExceptionCode ec = 0; ContainerNode* parentNode = nodeToReplace->parentNode(); parentNode->insertBefore(newNode, nodeToReplace, ec); ASSERT(!ec); RefPtr<Node> nextChild; for (Node* child = nodeToReplace->firstChild(); child; child = nextChild.get()) { nextChild = child->nextSibling(); newNode->appendChild(child, ec); ASSERT(!ec); } newNode->attributes()->setAttributes(*nodeToReplace->attributes()); parentNode->removeChild(nodeToReplace, ec); ASSERT(!ec); }