PassRefPtr<ChildType> HTMLConstructionSite::attach(ContainerNode* rawParent, PassRefPtr<ChildType> prpChild) { RefPtr<ChildType> child = prpChild; RefPtr<ContainerNode> parent = rawParent; // FIXME: It's confusing that HTMLConstructionSite::attach does the magic // redirection to the foster parent but HTMLConstructionSite::attachAtSite // doesn't. It feels like we're missing a concept somehow. if (shouldFosterParent()) { fosterParent(child.get()); ASSERT(child->attached() || !child->parentNode() || !child->parentNode()->attached()); return child.release(); } // Add as a sibling of the parent if we have reached the maximum depth allowed. if (m_openElements.stackDepth() > m_maximumDOMTreeDepth) parent = parent->parentNode(); parent->parserAddChild(child); // An event handler (DOM Mutation, beforeload, et al.) could have removed // the child, in which case we shouldn't try attaching it. if (!child->parentNode()) return child.release(); if (parent->attached() && !child->attached()) child->attach(); return child.release(); }
void OutdentBlockCommand::outdentSiblings(PassRefPtr<Node> prpFirstSibling, PassRefPtr<Node> prpLastSibling, Node* indentBlock) { ASSERT(indentBlock); if (!prpFirstSibling) { ASSERT(!prpLastSibling); ASSERT(!indentBlock->firstChild()); removeNode(indentBlock); return; } ASSERT(prpFirstSibling->isDescendantOf(indentBlock)); ASSERT(prpFirstSibling->parentNode() == prpLastSibling->parentNode()); RefPtr<Node> firstSibling = prpFirstSibling; RefPtr<Node> lastSibling = prpLastSibling; lastSibling = splitEnd(indentBlock, lastSibling); indentBlock = lastSibling->parentNode(); firstSibling = splitStart(indentBlock, firstSibling); ASSERT(firstSibling->parentNode() == indentBlock); RefPtr<Node> current = firstSibling; RefPtr<Node> end = lastSibling->nextSibling(); while (current != end) { RefPtr<Node> next = current->nextSibling(); removeNode(current); insertNodeBefore(current, indentBlock); current = next; } if (!hasVisibleChildren(indentBlock)) { removeNode(indentBlock); } }
bool ContainerNode::removeChild(Node* oldChild, ExceptionCode& ec) { // Check that this node is not "floating". // If it is, it can be deleted as a side effect of sending mutation events. ASSERT(refCount() || parentOrShadowHostNode()); RefPtr<Node> protect(this); ec = 0; // NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly. if (isReadOnlyNode()) { ec = NO_MODIFICATION_ALLOWED_ERR; return false; } // NOT_FOUND_ERR: Raised if oldChild is not a child of this node. if (!oldChild || oldChild->parentNode() != this) { ec = NOT_FOUND_ERR; return false; } RefPtr<Node> child = oldChild; document().removeFocusedNodeOfSubtree(child.get()); #if ENABLE(FULLSCREEN_API) document().removeFullScreenElementOfSubtree(child.get()); #endif // Events fired when blurring currently focused node might have moved this // child into a different parent. if (child->parentNode() != this) { ec = NOT_FOUND_ERR; return false; } willRemoveChild(child.get()); // Mutation events might have moved this child into a different parent. if (child->parentNode() != this) { ec = NOT_FOUND_ERR; return false; } { WidgetHierarchyUpdatesSuspensionScope suspendWidgetHierarchyUpdates; Node* prev = child->previousSibling(); Node* next = child->nextSibling(); removeBetween(prev, next, child.get()); childrenChanged(false, prev, next, -1); ChildNodeRemovalNotifier(this).notify(child.get()); } dispatchSubtreeModifiedEvent(); return child; }
TEST_F(DocumentMarkerControllerTest, NodeWillBeRemovedMarkedByRemoveAncestor) { setBodyInnerHTML("<b><i>foo</i></b>"); { RefPtr<Element> parent = toElement(document().body()->firstChild()->firstChild()); markNodeContents(parent); EXPECT_EQ(1u, markerController().markers().size()); parent->parentNode()->parentNode()->removeChild(parent->parentNode()); } // No more reference to marked node. EXPECT_EQ(0u, markerController().markers().size()); }
static void dispatchChildRemovalEvents(Node* child) { if (child->isInShadowTree()) { InspectorInstrumentation::willRemoveDOMNode(&child->document(), child); return; } ASSERT(!NoEventDispatchAssertion::isEventDispatchForbidden()); willCreatePossiblyOrphanedTreeByRemoval(child); InspectorInstrumentation::willRemoveDOMNode(&child->document(), child); RefPtr<Node> c = child; RefPtr<Document> document = &child->document(); // dispatch pre-removal mutation events if (c->parentNode() && document->hasListenerType(Document::DOMNODEREMOVED_LISTENER)) c->dispatchScopedEvent(MutationEvent::create(eventNames().DOMNodeRemovedEvent, true, c->parentNode())); // dispatch the DOMNodeRemovedFromDocument event to all descendants if (c->inDocument() && document->hasListenerType(Document::DOMNODEREMOVEDFROMDOCUMENT_LISTENER)) { for (; c; c = NodeTraversal::next(c.get(), child)) c->dispatchScopedEvent(MutationEvent::create(eventNames().DOMNodeRemovedFromDocumentEvent, false)); } }
bool DOMPatchSupport::removeChildAndMoveToNew(Digest* oldDigest, ExceptionCode& ec) { RefPtr<Node> oldNode = oldDigest->m_node; if (!m_domEditor->removeChild(oldNode->parentNode(), oldNode.get(), ec)) return false; // Diff works within levels. In order not to lose the node identity when user // prepends his HTML with "<div>" (i.e. all nodes are shifted to the next nested level), // prior to dropping the original node on the floor, check whether new DOM has a digest // with matching sha1. If it does, replace it with the original DOM chunk. Chances are // high that it will get merged back into the original DOM during the further patching. UnusedNodesMap::iterator it = m_unusedNodesMap.find(oldDigest->m_sha1); if (it != m_unusedNodesMap.end()) { Digest* newDigest = it->second; Node* newNode = newDigest->m_node; if (!m_domEditor->replaceChild(newNode->parentNode(), oldNode, newNode, ec)) return false; newDigest->m_node = oldNode.get(); markNodeAsUsed(newDigest); return true; } for (size_t i = 0; i < oldDigest->m_children.size(); ++i) { if (!removeChildAndMoveToNew(oldDigest->m_children[i].get(), ec)) return false; } return true; }
PassRefPtr<ChildType> HTMLConstructionSite::attach(ContainerNode* parent, PassRefPtr<ChildType> prpChild) { RefPtr<ChildType> child = prpChild; // FIXME: It's confusing that HTMLConstructionSite::attach does the magic // redirection to the foster parent but HTMLConstructionSite::attachAtSite // doesn't. It feels like we're missing a concept somehow. if (shouldFosterParent()) { fosterParent(child.get()); ASSERT(child->attached() || !child->parent() || !child->parent()->attached()); return child.release(); } parent->parserAddChild(child); // An event handler (DOM Mutation, beforeload, et al.) could have removed // the child, in which case we shouldn't try attaching it. if (!child->parentNode()) return child.release(); // It's slightly unfortunate that we need to hold a reference to child // here to call attach(). We should investigate whether we can rely on // |parent| to hold a ref at this point. In the common case (at least // for elements), however, we'll get to use this ref in the stack of // open elements. if (parent->attached() && !child->attached()) child->attach(); return child.release(); }
template<TreeWalker::SiblingTraversalType type> Node* TreeWalker::traverseSiblings() { RefPtr<Node> node = m_current; if (node == root()) return nullptr; auto isNext = type == SiblingTraversalType::Next; while (true) { for (RefPtr<Node> sibling = isNext ? node->nextSibling() : node->previousSibling(); sibling; ) { short acceptNodeResult = acceptNode(sibling.get()); if (acceptNodeResult == NodeFilter::FILTER_ACCEPT) { m_current = WTFMove(sibling); return m_current.get(); } node = sibling; sibling = isNext ? sibling->firstChild() : sibling->lastChild(); if (acceptNodeResult == NodeFilter::FILTER_REJECT || !sibling) sibling = isNext ? node->nextSibling() : node->previousSibling(); } node = node->parentNode(); if (!node || node == root()) return nullptr; short acceptNodeResult = acceptNode(node.get()); if (acceptNodeResult == NodeFilter::FILTER_ACCEPT) return nullptr; } }
Node* TreeWalker::previousNode() { RefPtr<Node> node = m_current; while (node != root()) { while (Node* previousSibling = node->previousSibling()) { node = previousSibling; short acceptNodeResult = acceptNode(node.get()); if (acceptNodeResult == NodeFilter::FILTER_REJECT) continue; while (Node* lastChild = node->lastChild()) { node = lastChild; acceptNodeResult = acceptNode(node.get()); if (acceptNodeResult == NodeFilter::FILTER_REJECT) break; } if (acceptNodeResult == NodeFilter::FILTER_ACCEPT) { m_current = node.release(); return m_current.get(); } } if (node == root()) return nullptr; ContainerNode* parent = node->parentNode(); if (!parent) return nullptr; node = parent; short acceptNodeResult = acceptNode(node.get()); if (acceptNodeResult == NodeFilter::FILTER_ACCEPT) return setCurrent(WTFMove(node)); } return nullptr; }
Node* TreeWalker::lastChild() { for (RefPtr<Node> node = m_current->lastChild(); node; ) { short acceptNodeResult = acceptNode(node.get()); switch (acceptNodeResult) { case NodeFilter::FILTER_ACCEPT: m_current = node.release(); return m_current.get(); case NodeFilter::FILTER_SKIP: if (node->lastChild()) { node = node->lastChild(); continue; } break; case NodeFilter::FILTER_REJECT: break; } do { if (node->previousSibling()) { node = node->previousSibling(); break; } ContainerNode* parent = node->parentNode(); if (!parent || parent == root() || parent == m_current) return nullptr; node = parent; } while (node); } return nullptr; }
Node* TreeWalker::firstChild(ScriptState* state) { for (RefPtr<Node> node = m_current->firstChild(); node; ) { short acceptNodeResult = acceptNode(state, node.get()); if (state && state->hadException()) return 0; switch (acceptNodeResult) { case NodeFilter::FILTER_ACCEPT: m_current = node.release(); return m_current.get(); case NodeFilter::FILTER_SKIP: if (node->firstChild()) { node = node->firstChild(); continue; } break; case NodeFilter::FILTER_REJECT: break; } do { if (node->nextSibling()) { node = node->nextSibling(); break; } ContainerNode* parent = node->parentNode(); if (!parent || parent == root() || parent == m_current) return 0; node = parent; } while (node); } return 0; }
// This function is a workaround for moveParagraph's tendency to strip blockquotes. It updates lastBlockquote to point to the // correct level for the current paragraph, and returns a pointer to a placeholder br where the insertion should be performed. PassRefPtr<Element> IndentOutdentCommand::prepareBlockquoteLevelForInsertion(VisiblePosition& currentParagraph, RefPtr<Element>& lastBlockquote) { int currentBlockquoteLevel = 0; int lastBlockquoteLevel = 0; Node* node = currentParagraph.deepEquivalent().node(); while ((node = enclosingNodeOfType(Position(node->parentNode(), 0), &isIndentBlockquote))) currentBlockquoteLevel++; node = lastBlockquote.get(); while ((node = enclosingNodeOfType(Position(node->parentNode(), 0), &isIndentBlockquote))) lastBlockquoteLevel++; while (currentBlockquoteLevel > lastBlockquoteLevel) { RefPtr<Element> newBlockquote = createIndentBlockquoteElement(document()); appendNode(newBlockquote, lastBlockquote); lastBlockquote = newBlockquote; lastBlockquoteLevel++; } while (currentBlockquoteLevel < lastBlockquoteLevel) { lastBlockquote = static_cast<Element*>(enclosingNodeOfType(Position(lastBlockquote->parentNode(), 0), isIndentBlockquote)); lastBlockquoteLevel--; } RefPtr<Element> placeholder = createBreakElement(document()); appendNode(placeholder, lastBlockquote); // Add another br before the placeholder if it collapsed. VisiblePosition visiblePos(Position(placeholder.get(), 0)); if (!isStartOfParagraph(visiblePos)) insertNodeBefore(createBreakElement(document()), placeholder); return placeholder.release(); }
RefPtr<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 RefPtr<ContainerNode> parent = parentNode(); // Protect against mutation handlers moving this node during traversal 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(), IGNORE_EXCEPTION); } 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(), IGNORE_EXCEPTION); } } if (newText.isEmpty()) { if (parent && parentNode() == parent) parent->removeChild(this, IGNORE_EXCEPTION); return 0; } setData(newText, IGNORE_EXCEPTION); return protectedThis.release(); }
void DeleteSelectionCommand::removeNode(PassRefPtr<Node> node) { if (!node) return; if (m_startRoot != m_endRoot && !(node->isDescendantOf(m_startRoot.get()) && node->isDescendantOf(m_endRoot.get()))) { // If a node is not in both the start and end editable roots, remove it only if its inside an editable region. if (!node->parentNode()->rendererIsEditable()) { // Don't remove non-editable atomic nodes. if (!node->firstChild()) return; // Search this non-editable region for editable regions to empty. RefPtr<Node> child = node->firstChild(); while (child) { RefPtr<Node> nextChild = child->nextSibling(); removeNode(child.get()); // Bail if nextChild is no longer node's child. if (nextChild && nextChild->parentNode() != node) return; child = nextChild; } // Don't remove editable regions that are inside non-editable ones, just clear them. return; } } if (isTableStructureNode(node.get()) || node == node->rootEditableElement()) { // Do not remove an element of table structure; remove its contents. // Likewise for the root editable element. Node* child = node->firstChild(); while (child) { Node* remove = child; child = child->nextSibling(); removeNode(remove); } // Make sure empty cell has some height, if a placeholder can be inserted. document()->updateLayoutIgnorePendingStylesheets(); RenderObject *r = node->renderer(); if (r && r->isTableCell() && toRenderTableCell(r)->contentHeight() <= 0) { Position firstEditablePosition = firstEditablePositionInNode(node.get()); if (firstEditablePosition.isNotNull()) insertBlockPlaceholder(firstEditablePosition); } return; } if (node == m_startBlock && !isEndOfBlock(VisiblePosition(firstPositionInNode(m_startBlock.get())).previous())) m_needPlaceholder = true; else if (node == m_endBlock && !isStartOfBlock(VisiblePosition(lastPositionInNode(m_startBlock.get())).next())) m_needPlaceholder = true; // FIXME: Update the endpoints of the range being deleted. updatePositionForNodeRemoval(m_endingPosition, node.get()); updatePositionForNodeRemoval(m_leadingWhitespace, node.get()); updatePositionForNodeRemoval(m_trailingWhitespace, node.get()); CompositeEditCommand::removeNode(node); }
Node* TreeWalker::firstChild(JSValue*& exception) { exception = 0; for (RefPtr<Node> node = m_current->firstChild(); node; ) { short acceptNodeResult = acceptNode(node.get(), exception); if (exception) return 0; switch (acceptNodeResult) { case NodeFilter::FILTER_ACCEPT: m_current = node.release(); return m_current.get(); case NodeFilter::FILTER_SKIP: if (node->firstChild()) { node = node->firstChild(); continue; } break; case NodeFilter::FILTER_REJECT: break; } do { if (node->nextSibling()) { node = node->nextSibling(); break; } Node* parent = node->parentNode(); if (!parent || parent == root() || parent == m_current) return 0; node = parent; } while (node); } return 0; }
PassRefPtr<Node> OutdentBlockCommand::splitStart(Node* ancestor, PassRefPtr<Node> prpChild) { ASSERT(prpChild->isDescendantOf(ancestor)); RefPtr<Node> child = prpChild; while (child != ancestor) { RefPtr<Node> previous = previousRenderedSiblingExcludingWhitespace(child.get()); if (previous) splitElement(toElement(child->parentNode()), previous->nextSibling()); child = child->parentNode(); } child = child->firstChild(); return child.release(); }
bool DOMSelection::containsNode(Node* n, bool allowPartial) const { if (!m_frame) return false; FrameSelection& selection = m_frame->selection(); if (!n || m_frame->document() != &n->document() || selection.isNone()) return false; RefPtr<Node> node = n; RefPtr<Range> selectedRange = selection.selection().toNormalizedRange(); ContainerNode* parentNode = node->parentNode(); if (!parentNode || !parentNode->inDocument()) return false; unsigned nodeIndex = node->nodeIndex(); ExceptionCode ec = 0; bool nodeFullySelected = Range::compareBoundaryPoints(parentNode, nodeIndex, selectedRange->startContainer(), selectedRange->startOffset(), ec) >= 0 && !ec && Range::compareBoundaryPoints(parentNode, nodeIndex + 1, selectedRange->endContainer(), selectedRange->endOffset(), ec) <= 0 && !ec; ASSERT(!ec); if (nodeFullySelected) return true; bool nodeFullyUnselected = (Range::compareBoundaryPoints(parentNode, nodeIndex, selectedRange->endContainer(), selectedRange->endOffset(), ec) > 0 && !ec) || (Range::compareBoundaryPoints(parentNode, nodeIndex + 1, selectedRange->startContainer(), selectedRange->startOffset(), ec) < 0 && !ec); ASSERT(!ec); if (nodeFullyUnselected) return false; return allowPartial || node->isTextNode(); }
PassRefPtr<HTMLElement> HTMLTableElement::insertRow(int index, ExceptionCode& ec) { if (index < -1) { ec = INDEX_SIZE_ERR; return 0; } Ref<HTMLTableElement> protectFromMutationEvents(*this); RefPtr<HTMLTableRowElement> lastRow = 0; RefPtr<HTMLTableRowElement> row = 0; if (index == -1) lastRow = HTMLTableRowsCollection::lastRow(this); else { for (int i = 0; i <= index; ++i) { row = HTMLTableRowsCollection::rowAfter(this, lastRow.get()); if (!row) { if (i != index) { ec = INDEX_SIZE_ERR; return 0; } break; } lastRow = row; } } RefPtr<ContainerNode> parent; if (lastRow) parent = row ? row->parentNode() : lastRow->parentNode(); else { parent = lastBody(); if (!parent) { RefPtr<HTMLTableSectionElement> newBody = HTMLTableSectionElement::create(tbodyTag, document()); RefPtr<HTMLTableRowElement> newRow = HTMLTableRowElement::create(document()); newBody->appendChild(newRow, ec); appendChild(newBody.release(), ec); return newRow.release(); } } RefPtr<HTMLTableRowElement> newRow = HTMLTableRowElement::create(document()); parent->insertBefore(newRow, row.get(), ec); return newRow.release(); }
PassRefPtr<Node> OutdentBlockCommand::splitEnd(Node* ancestor, PassRefPtr<Node> prpChild) { ASSERT(prpChild->isDescendantOf(ancestor)); RefPtr<Node> child = prpChild; bool reachedAncestor = false; while (!reachedAncestor) { reachedAncestor = child->parentNode() == ancestor; RefPtr<Node> next = nextRenderedSiblingExcludingWhitespace(child.get()); if (next) splitElement(toElement(child->parentNode()), next); child = child->parentNode(); } child = child->lastChild(); return child.release(); }
static void trimFragment(DocumentFragment* fragment, Node* nodeBeforeContext, Node* nodeAfterContext) { RefPtr<Node> next; for (RefPtr<Node> node = fragment->firstChild(); node; node = next) { if (nodeBeforeContext->isDescendantOf(node.get())) { next = NodeTraversal::next(node.get()); continue; } next = NodeTraversal::nextSkippingChildren(node.get()); ASSERT(!node->contains(nodeAfterContext)); node->parentNode()->removeChild(node.get(), ASSERT_NO_EXCEPTION); if (nodeBeforeContext == node) break; } ASSERT(nodeAfterContext->parentNode()); for (RefPtr<Node> node = nodeAfterContext; node; node = next) { next = NodeTraversal::nextSkippingChildren(node.get()); node->parentNode()->removeChild(node.get(), ASSERT_NO_EXCEPTION); } }
void mergeWithNextTextNode(Text* textNode, ExceptionState& exceptionState) { ASSERT(textNode); Node* next = textNode->nextSibling(); if (!next || !next->isTextNode()) return; RefPtr<Text> textNext = toText(next); textNode->appendData(textNext->data()); if (textNext->parentNode()) // Might have been removed by mutation event. textNext->remove(exceptionState); }
static void mergeWithNextTextNode(PassRefPtr<Node> node, ExceptionState& es) { ASSERT(node && node->isTextNode()); Node* next = node->nextSibling(); if (!next || !next->isTextNode()) return; RefPtr<Text> textNode = toText(node.get()); RefPtr<Text> textNext = toText(next); textNode->appendData(textNext->data()); if (textNext->parentNode()) // Might have been removed by mutation event. textNext->remove(es); }
Node* TreeWalker::parentNode() { RefPtr<Node> node = m_current; while (node != root()) { node = node->parentNode(); if (!node) return nullptr; short acceptNodeResult = acceptNode(node.get()); if (acceptNodeResult == NodeFilter::FILTER_ACCEPT) return setCurrent(WTFMove(node)); } return nullptr; }
Node* TreeWalker::parentNode(ScriptState* state) { RefPtr<Node> node = m_current; while (node != root()) { node = node->parentNode(); if (!node) return 0; short acceptNodeResult = acceptNode(state, node.get()); if (state && state->hadException()) return 0; if (acceptNodeResult == NodeFilter::FILTER_ACCEPT) return setCurrent(node.release()); } return 0; }
void SVGElement::sendSVGLoadEventIfPossible(bool sendParentLoadEvents) { RefPtr<SVGElement> currentTarget = this; while (currentTarget && currentTarget->haveLoadedRequiredResources()) { RefPtr<Node> parent; if (sendParentLoadEvents) parent = currentTarget->parentNode(); // save the next parent to dispatch too incase dispatching the event changes the tree if (hasLoadListener(currentTarget.get())) { RefPtr<Event> event = Event::create(eventNames().loadEvent, false, false); event->setTarget(currentTarget); currentTarget->dispatchGenericEvent(event.release()); } currentTarget = (parent && parent->isSVGElement()) ? static_pointer_cast<SVGElement>(parent) : 0; } }
Node* TreeWalker::parentNode(JSValue*& exception) { exception = 0; RefPtr<Node> node = m_current; while (node != root()) { node = node->parentNode(); if (!node) return 0; short acceptNodeResult = acceptNode(node.get(), exception); if (exception) return 0; if (acceptNodeResult == NodeFilter::FILTER_ACCEPT) return setCurrent(node.release()); } return 0; }
void HTMLConstructionSite::attachAtSite(const AttachmentSite& site, PassRefPtr<Node> prpChild) { // FIXME: It's unfortunate that we need to hold a reference to child // here to call attach(). We should investigate whether we can rely on // |site.parent| to hold a ref at this point. RefPtr<Node> child = prpChild; if (site.nextChild) site.parent->parserInsertBefore(child, site.nextChild); else site.parent->parserAddChild(child); // JavaScript run from beforeload (or DOM Mutation or event handlers) // might have removed the child, in which case we should not attach it. if (child->parentNode() && site.parent->attached() && !child->attached()) child->attach(); }
static void dispatchChildInsertionEvents(Node* child) { if (child->isInShadowTree()) return; ASSERT(!NoEventDispatchAssertion::isEventDispatchForbidden()); RefPtr<Node> c = child; RefPtr<Document> document = child->document(); if (c->parentNode() && document->hasListenerType(Document::DOMNODEINSERTED_LISTENER)) c->dispatchScopedEvent(MutationEvent::create(eventNames().DOMNodeInsertedEvent, true, c->parentNode())); // dispatch the DOMNodeInsertedIntoDocument event to all descendants if (c->inDocument() && document->hasListenerType(Document::DOMNODEINSERTEDINTODOCUMENT_LISTENER)) { for (; c; c = NodeTraversal::next(c.get(), child)) c->dispatchScopedEvent(MutationEvent::create(eventNames().DOMNodeInsertedIntoDocumentEvent, false)); } }
void SVGElement::sendSVGLoadEventIfPossible(bool sendParentLoadEvents) { kDebug() << "send svg load event" << endl; RefPtr<SVGElement> currentTarget = this; kDebug() << currentTarget << currentTarget->haveLoadedRequiredResources() << endl; while (currentTarget && currentTarget->haveLoadedRequiredResources()) { RefPtr<Node> parent; if (sendParentLoadEvents) parent = currentTarget->parentNode(); // save the next parent to dispatch too incase dispatching the event changes the tree kDebug() << hasLoadListener(currentTarget.get()) << endl; if (hasLoadListener(currentTarget.get())) { //Event* event = new Event(EventImpl::LOAD_EVENT, true/*false*/, false); //event->setTarget(currentTarget.get()); //ExceptionCode ignored = 0; //dispatchGenericEvent(/*currentTarget.get(), */event, ignored/*, false*/); dispatchHTMLEvent(EventImpl::LOAD_EVENT, false, false); } currentTarget = (parent && parent->isSVGElement()) ? static_pointer_cast<SVGElement>(parent) : RefPtr<SVGElement>(); } }
Node* TreeWalker::previousNode(JSValue*& exception) { exception = 0; RefPtr<Node> node = m_current; while (node != root()) { while (Node* previousSibling = node->previousSibling()) { node = previousSibling; short acceptNodeResult = acceptNode(node.get(), exception); if (exception) return 0; if (acceptNodeResult == NodeFilter::FILTER_REJECT) continue; while (Node* lastChild = node->lastChild()) { node = lastChild; acceptNodeResult = acceptNode(node.get(), exception); if (exception) return 0; if (acceptNodeResult == NodeFilter::FILTER_ACCEPT) continue; } if (acceptNodeResult == NodeFilter::FILTER_ACCEPT) { m_current = node.release(); return m_current.get(); } } if (node == root()) return 0; Node* parent = node->parentNode(); if (!parent) return 0; node = parent; short acceptNodeResult = acceptNode(node.get(), exception); if (exception) return 0; if (acceptNodeResult == NodeFilter::FILTER_ACCEPT) return setCurrent(node.release()); } return 0; }