Example #1
0
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);
    }
}
Example #3
0
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());
}
Example #5
0
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));
    }
}
Example #6
0
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;
}
Example #7
0
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();
}
Example #8
0
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;
    }
}
Example #9
0
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;
}
Example #10
0
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;
}
Example #11
0
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();
}
Example #13
0
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);
}
Example #15
0
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();
}
Example #17
0
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();
}
Example #18
0
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();
}
Example #20
0
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);
    }
}
Example #21
0
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);
}
Example #22
0
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);
}
Example #23
0
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;
}
Example #24
0
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;
}
Example #25
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;
    }
}
Example #26
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;
}
Example #27
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();
}
Example #28
0
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));
    }
}
Example #29
0
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>();
    }
}
Example #30
0
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;
}