static Node*
findFirstFocusableNode(Frame* frame, const IntRect* specificRect)
{
#if PLATFORM(WKC)
    CRASH_IF_STACK_OVERFLOW(WKC_STACK_MARGIN_DEFAULT);
#endif
    Node* node = frame->document()->firstChild();
    while (node) {
        if (!isNodeInSpecificRect(node, specificRect)) {
            node = node->traverseNextNode();
            continue;
        }
        if (node->isFrameOwnerElement()) {
            HTMLFrameOwnerElement* owner = static_cast<HTMLFrameOwnerElement*>(node);
            if (owner->contentFrame()) {
                node = findFirstFocusableNode(owner->contentFrame(), specificRect);
                if (node)
                    break;
                node = owner;
            }
        } else if (isScrollableContainerNode(node) && !node->renderer()->isTextArea()) {
            node = node->firstChild();
        }
        if (node->isFocusable() && !node->isFrameOwnerElement()) {
            break;
        }
        node = node->traverseNextNode();
    }

    if (node) {
        return node->isFocusable() ? node : 0;
    }
    return 0;
}
Example #2
0
bool DocumentStyleSheetCollection::testAddedStyleSheetRequiresStyleRecalc(StyleSheetContents* stylesheet)
{
    // See if all rules on the sheet are scoped to some specific ids or classes.
    // Then test if we actually have any of those in the tree at the moment.
    HashSet<AtomicStringImpl*> idScopes; 
    HashSet<AtomicStringImpl*> classScopes;
    if (!StyleResolver::determineStylesheetSelectorScopes(stylesheet, idScopes, classScopes))
        return true;
    // Invalidate the subtrees that match the scopes.
    Node* node = m_document->firstChild();
    while (node) {
        if (!node->isStyledElement()) {
            node = node->traverseNextNode();
            continue;
        }
        StyledElement* element = static_cast<StyledElement*>(node);
        if (SelectorChecker::elementMatchesSelectorScopes(element, idScopes, classScopes)) {
            element->setNeedsStyleRecalc();
            // The whole subtree is now invalidated, we can skip to the next sibling.
            node = node->traverseNextSibling();
            continue;
        }
        node = node->traverseNextNode();
    }
    return false;
}
Example #3
0
VisiblePosition endOfParagraph(const VisiblePosition &c)
{    
    if (c.isNull())
        return VisiblePosition();

    Position p = c.deepEquivalent();
    Node* startNode = p.node();

    if (isRenderedAsNonInlineTableImageOrHR(startNode))
        return lastDeepEditingPositionForNode(startNode);
    
    Node* startBlock = enclosingBlock(startNode);
    Node *stayInsideBlock = startBlock;
    
    Node *node = startNode;
    int offset = p.deprecatedEditingOffset();

    Node *n = startNode;
    while (n) {
        if (n->isContentEditable() != startNode->isContentEditable())
            break;
        RenderObject *r = n->renderer();
        if (!r) {
            n = n->traverseNextNode(stayInsideBlock);
            continue;
        }
        RenderStyle *style = r->style();
        if (style->visibility() != VISIBLE) {
            n = n->traverseNextNode(stayInsideBlock);
            continue;
        }
        
        if (r->isBR() || isBlock(n))
            break;
            
        // FIXME: We avoid returning a position where the renderer can't accept the caret.
        // We should probably do this in other cases such as startOfParagraph.
        if (r->isText() && r->caretMaxRenderedOffset() > 0) {
            int length = toRenderText(r)->textLength();
            if (style->preserveNewline()) {
                const UChar* chars = toRenderText(r)->characters();
                int o = n == startNode ? offset : 0;
                for (int i = o; i < length; ++i)
                    if (chars[i] == '\n')
                        return VisiblePosition(n, i, DOWNSTREAM);
            }
            node = n;
            offset = r->caretMaxOffset();
            n = n->traverseNextNode(stayInsideBlock);
        } else if (editingIgnoresContent(n) || isTableElement(n)) {
            node = n;
            offset = lastOffsetForEditing(n);
            n = n->traverseNextSibling(stayInsideBlock);
        } else
            n = n->traverseNextNode(stayInsideBlock);
    }

    return VisiblePosition(node, offset, DOWNSTREAM);
}
void writeRenderResources(TextStream& ts, Node* parent)
{
    ASSERT(parent);
    Node* node = parent;
    do {
        if (!node->isSVGElement())
            continue;
        SVGElement* svgElement = static_cast<SVGElement*>(node);
        if (!svgElement->isStyled())
            continue;

        SVGStyledElement* styled = static_cast<SVGStyledElement*>(svgElement);
        RefPtr<SVGResource> resource(styled->canvasResource());
        if (!resource)
            continue;

        String elementId = svgElement->getAttribute(svgElement->idAttributeName());
        // FIXME: These names are lies!
        if (resource->isPaintServer()) {
            RefPtr<SVGPaintServer> paintServer = WTF::static_pointer_cast<SVGPaintServer>(resource);
            ts << "KRenderingPaintServer {id=\"" << elementId << "\" " << *paintServer << "}" << "\n";
        } else
            ts << "KCanvasResource {id=\"" << elementId << "\" " << *resource << "}" << "\n";
    } while ((node = node->traverseNextNode(parent)));
}
Example #5
0
String stringValue(Node* node)
{
    switch (node->nodeType()) {
        case Node::ATTRIBUTE_NODE:
        case Node::PROCESSING_INSTRUCTION_NODE:
        case Node::COMMENT_NODE:
        case Node::TEXT_NODE:
        case Node::CDATA_SECTION_NODE:
        case Node::XPATH_NAMESPACE_NODE:
            return node->nodeValue();
        default:
            if (isRootDomNode(node) || node->nodeType() == Node::ELEMENT_NODE) {
                StringBuilder result;
                result.reserveCapacity(1024);

                for (Node* n = node->firstChild(); n; n = n->traverseNextNode(node)) {
                    if (n->isTextNode()) {
                        const String& nodeValue = n->nodeValue();
                        result.append(nodeValue);
                    }
                }

                return result.toString();
            }
    }
    
    return String();
}
JSValue toJS(ExecState* exec, JSDOMGlobalObject* globalObject, Document* document)
{
    if (!document)
        return jsNull();

    JSDOMWrapper* wrapper = getCachedWrapper(currentWorld(exec), document);
    if (wrapper)
        return wrapper;

    if (document->isHTMLDocument())
        wrapper = CREATE_DOM_WRAPPER(exec, globalObject, HTMLDocument, document);
#if ENABLE(SVG)
    else if (document->isSVGDocument())
        wrapper = CREATE_DOM_WRAPPER(exec, globalObject, SVGDocument, document);
#endif
    else
        wrapper = CREATE_DOM_WRAPPER(exec, globalObject, Document, document);

    // Make sure the document is kept around by the window object, and works right with the
    // back/forward cache.
    if (!document->frame()) {
        size_t nodeCount = 0;
        for (Node* n = document; n; n = n->traverseNextNode())
            nodeCount++;
        
        exec->heap()->reportExtraMemoryCost(nodeCount * sizeof(Node));
    }

    return wrapper;
}
Example #7
0
unsigned HTMLFormElement::formElementIndex(FormAssociatedElement* associatedElement)
{
    HTMLElement* element = toHTMLElement(associatedElement);
    // Treats separately the case where this element has the form attribute
    // for performance consideration.
    if (element->fastHasAttribute(formAttr))
        return formElementIndexWithFormAttribute(element);

    // Check for the special case where this element is the very last thing in
    // the form's tree of children; we don't want to walk the entire tree in that
    // common case that occurs during parsing; instead we'll just return a value
    // that says "add this form element to the end of the array".
    if (element->traverseNextNode(this)) {
        unsigned i = m_associatedElementsBeforeIndex;
        for (Node* node = this; node; node = node->traverseNextNode(this)) {
            if (node == element) {
                ++m_associatedElementsAfterIndex;
                return i;
            }
            if (node->isHTMLElement()
                    && (static_cast<Element*>(node)->isFormControlElement()
                        || node->hasTagName(objectTag))
                    && static_cast<HTMLElement*>(node)->form() == this)
                ++i;
        }
    }
    return m_associatedElementsAfterIndex++;
}
void HTMLFieldSetElement::refreshElementsIfNeeded() const
{
    uint64_t docVersion = document()->domTreeVersion();
    if (m_documentVersion == docVersion)
        return;

    m_documentVersion = docVersion;

    m_associatedElements.clear();

    for (Node* node = firstChild(); node; node = node->traverseNextNode(this)) {
        if (!node->isElementNode())
            continue;

        if (node->hasTagName(objectTag)) {
            m_associatedElements.append(static_cast<HTMLObjectElement*>(node));
            continue;
        }

        if (!toElement(node)->isFormControlElement())
            continue;

        m_associatedElements.append(static_cast<HTMLFormControlElement*>(node));
    }
}
Example #9
0
String RenderTextControl::text()
{
    if (!m_innerText)
        return "";
 
    Frame* frame = document()->frame();
    Text* compositionNode = frame ? frame->editor()->compositionNode() : 0;

    Vector<UChar> result;

    for (Node* n = m_innerText.get(); n; n = n->traverseNextNode(m_innerText.get())) {
        if (n->hasTagName(brTag))
            result.append(&newlineCharacter, 1);
        else if (n->isTextNode()) {
            Text* text = static_cast<Text*>(n);
            String data = text->data();
            unsigned length = data.length();
            if (text != compositionNode)
                result.append(data.characters(), length);
            else {
                unsigned compositionStart = min(frame->editor()->compositionStart(), length);
                unsigned compositionEnd = min(max(compositionStart, frame->editor()->compositionEnd()), length);
                result.append(data.characters(), compositionStart);
                result.append(data.characters() + compositionEnd, length - compositionEnd);
            }
        }
    }

    return finishText(result);
}
Example #10
0
String Frame::searchForLabelsAboveCell(RegularExpression* regExp, HTMLTableCellElement* cell, size_t* resultDistanceFromStartOfCell)
{
    HTMLTableCellElement* aboveCell = cell->cellAbove();
    if (aboveCell) {
        // search within the above cell we found for a match
        size_t lengthSearched = 0;    
        for (Node* n = aboveCell->firstChild(); n; n = n->traverseNextNode(aboveCell)) {
            if (n->isTextNode() && n->renderer() && n->renderer()->style()->visibility() == VISIBLE) {
                // For each text chunk, run the regexp
                String nodeString = n->nodeValue();
                int pos = regExp->searchRev(nodeString);
                if (pos >= 0) {
                    if (resultDistanceFromStartOfCell)
                        *resultDistanceFromStartOfCell = lengthSearched;
                    return nodeString.substring(pos, regExp->matchedLength());
                }
                lengthSearched += nodeString.length();
            }
        }
    }

    // Any reason in practice to search all cells in that are above cell?
    if (resultDistanceFromStartOfCell)
        *resultDistanceFromStartOfCell = notFound;
    return String();
}
Example #11
0
void DocumentMarkerController::clearDescriptionOnMarkersIntersectingRange(Range* range, DocumentMarker::MarkerTypes markerTypes)
{
    if (!possiblyHasMarkers(markerTypes))
        return;
    ASSERT(!m_markers.isEmpty());

    Node* startContainer = range->startContainer();
    Node* endContainer = range->endContainer();

    Node* pastLastNode = range->pastLastNode();
    for (Node* node = range->firstNode(); node != pastLastNode; node = node->traverseNextNode()) {
        unsigned startOffset = node == startContainer ? range->startOffset() : 0;
        unsigned endOffset = node == endContainer ? static_cast<unsigned>(range->endOffset()) : std::numeric_limits<unsigned>::max();
        MarkerList* list = m_markers.get(node);
        if (!list)
            continue;

        for (size_t i = 0; i < list->size(); ++i) {
            DocumentMarker& marker = list->at(i);

            // markers are returned in order, so stop if we are now past the specified range
            if (marker.startOffset() >= endOffset)
                break;

            // skip marker that is wrong type or before target
            if (marker.endOffset() <= startOffset || !markerTypes.contains(marker.type())) {
                i++;
                continue;
            }

            marker.clearDescription();
        }
    }
}
Example #12
0
PassRefPtr<StaticNodeList> createSelectorNodeList(PassRefPtr<Node> rootNode, CSSSelector* querySelector)
{
    Vector<RefPtr<Node> > nodes;
    Document* document = rootNode->document();
    AtomicString selectorValue = querySelector->m_value;

    if (!querySelector->next() && querySelector->m_match == CSSSelector::Id && !document->containsMultipleElementsWithId(selectorValue)) {
        Element* element = document->getElementById(selectorValue);
        if (element && (rootNode->isDocumentNode() || element->isDescendantOf(rootNode.get())))
            nodes.append(element);
    } else {
        CSSStyleSelector::SelectorChecker selectorChecker(document, !document->inCompatMode());
        
        for (Node* n = rootNode->firstChild(); n; n = n->traverseNextNode(rootNode.get())) {
            if (n->isElementNode()) {
                Element* element = static_cast<Element*>(n);
                for (CSSSelector* selector = querySelector; selector; selector = selector->next()) {
                    if (selectorChecker.checkSelector(selector, element)) {
                        nodes.append(n);
                        break;
                    }
                }
            }
        }
    }
    
    return StaticNodeList::adopt(nodes);
}
Example #13
0
inline Element* DocumentOrderedMap::get(AtomicStringImpl* key, const TreeScope* scope) const
{
    ASSERT(key);

    m_map.checkConsistency();

    Element* element = m_map.get(key);
    if (element)
        return element;

    if (m_duplicateCounts.contains(key)) {
        // We know there's at least one node that matches; iterate to find the first one.
        for (Node* node = scope->firstChild(); node; node = node->traverseNextNode()) {
            if (!node->isElementNode())
                continue;
            element = static_cast<Element*>(node);
            if (!keyMatches(key, element))
                continue;
            m_duplicateCounts.remove(key);
            m_map.set(key, element);
            return element;
        }
        ASSERT_NOT_REACHED();
    }

    return 0;
}
Example #14
0
bool DocumentMarkerController::hasMarkers(Range* range, DocumentMarker::MarkerTypes markerTypes)
{
    if (!possiblyHasMarkers(markerTypes))
        return false;
    ASSERT(!m_markers.isEmpty());

    Node* startContainer = range->startContainer();
    ASSERT(startContainer);
    Node* endContainer = range->endContainer();
    ASSERT(endContainer);

    Node* pastLastNode = range->pastLastNode();
    for (Node* node = range->firstNode(); node != pastLastNode; node = node->traverseNextNode()) {
        Vector<DocumentMarker*> markers = markersFor(node);
        Vector<DocumentMarker*>::const_iterator end = markers.end();
        for (Vector<DocumentMarker*>::const_iterator it = markers.begin(); it != end; ++it) {
            DocumentMarker* marker = *it;
            if (!markerTypes.contains(marker->type()))
                continue;
            if (node == startContainer && marker->endOffset() <= static_cast<unsigned>(range->startOffset()))
                continue;
            if (node == endContainer && marker->startOffset() >= static_cast<unsigned>(range->endOffset()))
                continue;
            return true;
        }
    }
    return false;
}
PassRefPtr<StaticNodeList> createSelectorNodeList(Node* rootNode, const CSSSelectorList& querySelectorList)
{
    Vector<RefPtr<Node> > nodes;
    Document* document = rootNode->document();
    CSSSelector* onlySelector = querySelectorList.hasOneSelector() ? querySelectorList.first() : 0;
    bool strictParsing = !document->inCompatMode();

    CSSStyleSelector::SelectorChecker selectorChecker(document, strictParsing);

    if (strictParsing && rootNode->inDocument() && onlySelector && onlySelector->m_match == CSSSelector::Id && !document->containsMultipleElementsWithId(onlySelector->m_value)) {
        Element* element = document->getElementById(onlySelector->m_value);
        if (element && (rootNode->isDocumentNode() || element->isDescendantOf(rootNode)) && selectorChecker.checkSelector(onlySelector, element))
            nodes.append(element);
    } else {
        for (Node* n = rootNode->firstChild(); n; n = n->traverseNextNode(rootNode)) {
            if (n->isElementNode()) {
                Element* element = static_cast<Element*>(n);
                for (CSSSelector* selector = querySelectorList.first(); selector; selector = CSSSelectorList::next(selector)) {
                    if (selectorChecker.checkSelector(selector, element)) {
                        nodes.append(n);
                        break;
                    }
                }
            }
        }
    }
    
    return StaticNodeList::adopt(nodes);
}
Example #16
0
void visibleTextQuads(const Range& range, Vector<FloatQuad>& quads, bool useSelectionHeight)
{
    // Range::textQuads includes hidden text, which we don't want.
    // To work around this, this is a copy of it which skips hidden elements.
    Node* startContainer = range.startContainer();
    Node* endContainer = range.endContainer();

    if (!startContainer || !endContainer)
        return;

    Node* stopNode = range.pastLastNode();
    for (Node* node = range.firstNode(); node != stopNode; node = node->traverseNextNode()) {
        RenderObject* r = node->renderer();
        if (!r || !r->isText())
            continue;

        if (r->style()->visibility() != VISIBLE)
            continue;

        RenderText* renderText = toRenderText(r);
        int startOffset = node == startContainer ? range.startOffset() : 0;
        int endOffset = node == endContainer ? range.endOffset() : std::numeric_limits<int>::max();
        renderText->absoluteQuadsForRange(quads, startOffset, endOffset, useSelectionHeight);
    }
}
Example #17
0
Node* FocusController::nextFocusableNode(TreeScope* scope, Node* start, KeyboardEvent* event)
{
    if (start) {
        // If a node is excluded from the normal tabbing cycle, the next focusable node is determined by tree order
        if (start->tabIndex() < 0) {
            for (Node* n = start->traverseNextNode(); n; n = n->traverseNextNode())
                if (n->isKeyboardFocusable(event) && n->tabIndex() >= 0)
                    return n;
        }

        // First try to find a node with the same tabindex as start that comes after start in the scope.
        if (Node* winner = nextNodeWithExactTabIndex(start->traverseNextNode(), start->tabIndex(), event))
            return winner;

        if (!start->tabIndex())
            // We've reached the last node in the document with a tabindex of 0. This is the end of the tabbing order.
            return 0;
    }

    // Look for the first node in the scope that:
    // 1) has the lowest tabindex that is higher than start's tabindex (or 0, if start is null), and
    // 2) comes first in the scope, if there's a tie.
    if (Node* winner = nextNodeWithGreaterTabIndex(scope, start ? start->tabIndex() : 0, event))
        return winner;

    // There are no nodes with a tabindex greater than start's tabindex,
    // so find the first node with a tabindex of 0.
    return nextNodeWithExactTabIndex(scope, 0, event);
}
static Position firstEditablePositionInNode(Node* node)
{
    ASSERT(node);
    Node* next = node;
    while (next && !next->rendererIsEditable())
        next = next->traverseNextNode(node);
    return next ? firstPositionInOrBeforeNode(next) : Position();
}
Example #19
0
static Node* nextNodeWithExactTabIndex(Node* start, int tabIndex, KeyboardEvent* event)
{
    // Search is inclusive of start
    for (Node* node = start; node; node = node->traverseNextNode())
        if (node->isKeyboardFocusable(event) && node->tabIndex() == tabIndex)
            return node;

    return 0;
}
Example #20
0
void SMILTimeContainer::updateDocumentOrderIndexes()
{
    unsigned timingElementCount = 0;
    for (Node* node = m_ownerSVGElement; node; node = node->traverseNextNode(m_ownerSVGElement)) {
        if (SVGSMILElement::isSMILElement(node))
            static_cast<SVGSMILElement*>(node)->setDocumentOrderIndex(timingElementCount++);
    }
    m_documentOrderIndexesDirty = false;
}
Example #21
0
bool ShadowRoot::hasInsertionPoint() const
{
    for (Node* n = firstChild(); n; n = n->traverseNextNode(this)) {
        if (isInsertionPoint(n))
            return true;
    }

    return false;
}
Example #22
0
bool ShadowRoot::hasContentElement() const
{
    for (Node* n = firstChild(); n; n = n->traverseNextNode(this)) {
        if (n->isContentElement())
            return true;
    }

    return false;
}
Example #23
0
void FocusController::findFocusableNodeInDirection(Node* outer, Node* focusedNode,
                                                   FocusDirection direction, KeyboardEvent* event,
                                                   FocusCandidate& closestFocusCandidate,
                                                   const FocusCandidate& candidateParent)
{
    ASSERT(outer);
    ASSERT(candidateParent.isNull()
        || candidateParent.node->hasTagName(frameTag)
        || candidateParent.node->hasTagName(iframeTag));

    // Walk all the child nodes and update closestFocusCandidate if we find a nearer node.
    Node* candidate = outer;
    while (candidate) {
        // Inner documents case.

        if (candidate->isFrameOwnerElement())
            deepFindFocusableNodeInDirection(candidate, focusedNode, direction, event, closestFocusCandidate);
        else if (candidate != focusedNode && candidate->isKeyboardFocusable(event)) {
            FocusCandidate currentFocusCandidate(candidate);

            // Get distance and alignment from current candidate.
            distanceDataForNode(direction, focusedNode, currentFocusCandidate);

            // Bail out if distance is maximum.
            if (currentFocusCandidate.distance == maxDistance()) {
                candidate = candidate->traverseNextNode(outer->parent());
                continue;
            }

            // If candidateParent is not null, it means that we are in a recursive call
            // from deepFineFocusableNodeInDirection (i.e. processing an element in an iframe),
            // and holds the distance and alignment data of the iframe element itself.
            if (!candidateParent.isNull()) {
                currentFocusCandidate.parentAlignment = candidateParent.alignment;
                currentFocusCandidate.parentDistance = candidateParent.distance;
            }

            updateFocusCandidateIfCloser(focusedNode, currentFocusCandidate, closestFocusCandidate);
        }

        candidate = candidate->traverseNextNode(outer->parent());
    }
}
Example #24
0
void HTMLFieldSetElement::disabledAttributeChanged()
{
    // This element must be updated before the style of nodes in its subtree gets recalculated.
    HTMLFormControlElement::disabledAttributeChanged();

    for (Node* currentNode = this; currentNode; currentNode = currentNode->traverseNextNode(this)) {
        if (currentNode && currentNode->isElementNode() && toElement(currentNode)->isFormControlElement())
            static_cast<HTMLFormControlElement*>(currentNode)->setNeedsStyleRecalc();
    }
}
Example #25
0
Element* HTMLNameCollection::virtualItemAfter(unsigned& offsetInArray, Element* previous) const
{
    ASSERT_UNUSED(offsetInArray, !offsetInArray);
    ASSERT(previous != base());

    Node* current;
    if (!previous)
        current = base()->firstChild();
    else
        current = previous->traverseNextNode(base());

    for (; current; current = current->traverseNextNode(base())) {
        if (!current->isElementNode())
            continue;
        Element* e = static_cast<Element*>(current);
        switch (type()) {
            case WindowNamedItems:
                // find only images, forms, applets, embeds and objects by name, 
                // but anything by id
                if (e->hasTagName(imgTag) ||
                    e->hasTagName(formTag) ||
                    e->hasTagName(appletTag) ||
                    e->hasTagName(embedTag) ||
                    e->hasTagName(objectTag))
                    if (e->getNameAttribute() == m_name)
                        return e;
                if (e->getIdAttribute() == m_name)
                    return e;
                break;
            case DocumentNamedItems:
                // find images, forms, applets, embeds, objects and iframes by name, 
                // applets and object by id, and images by id but only if they have
                // a name attribute (this very strange rule matches IE)
                if (e->hasTagName(formTag) || e->hasTagName(embedTag) || e->hasTagName(iframeTag)) {
                    if (e->getNameAttribute() == m_name)
                        return e;
                } else if (e->hasTagName(appletTag)) {
                    if (e->getNameAttribute() == m_name || e->getIdAttribute() == m_name)
                        return e;
                } else if (e->hasTagName(objectTag)) {
                    if ((e->getNameAttribute() == m_name || e->getIdAttribute() == m_name)
                            && static_cast<HTMLObjectElement*>(e)->isDocNamedItem())
                        return e;
                } else if (e->hasTagName(imgTag)) {
                    if (e->getNameAttribute() == m_name || (e->getIdAttribute() == m_name && e->hasName()))
                        return e;
                }
                break;
        default:
            ASSERT_NOT_REACHED();
        }
    }

    return 0;
}
Example #26
0
void JSNode::mark()
{
    ASSERT(!marked());

    Node* node = m_impl.get();

    // Nodes in the document are kept alive by JSDocument::mark,
    // so we have no special responsibilities and can just call the base class here.
    if (node->inDocument()) {
        // But if the document isn't marked we have to mark it to ensure that
        // nodes reachable from this one are also marked
        if (Document* doc = node->ownerDocument())
            if (DOMObject* docWrapper = getCachedDOMObjectWrapper(*Heap::heap(this)->globalData(), doc))
                if (!docWrapper->marked())
                    docWrapper->mark();
        DOMObject::mark();
        return;
    }

    // This is a node outside the document, so find the root of the tree it is in,
    // and start marking from there.
    Node* root = node;
    for (Node* current = m_impl.get(); current; current = current->parentNode())
        root = current;

    // If we're already marking this tree, then we can simply mark this wrapper
    // by calling the base class; our caller is iterating the tree.
    if (root->inSubtreeMark()) {
        DOMObject::mark();
        return;
    }

    // Mark the whole tree; use the global set of roots to avoid reentering.
    root->setInSubtreeMark(true);
    for (Node* nodeToMark = root; nodeToMark; nodeToMark = nodeToMark->traverseNextNode()) {
        JSNode* wrapper = getCachedDOMNodeWrapper(m_impl->document(), nodeToMark);
        if (wrapper) {
            if (!wrapper->marked())
                wrapper->mark();
        } else if (nodeToMark == node) {
            // This is the case where the map from the document to wrappers has
            // been cleared out, but a wrapper is being marked. For now, we'll
            // let the rest of the tree of wrappers get collected, because we have
            // no good way of finding them. Later we should test behavior of other
            // browsers and see if we need to preserve other wrappers in this case.
            if (!marked())
                mark();
        }
    }
    root->setInSubtreeMark(false);

    // Double check that we actually ended up marked. This assert caught problems in the past.
    ASSERT(marked());
}
bool ShadowRoot::hasContentElement() const
{
    for (Node* n = firstChild(); n; n = n->traverseNextNode(this)) {
        // FIXME: This should be replaced with tag-name checking once <content> is ready.
        // See also http://webkit.org/b/56973
        if (n->isShadowBoundary())
            return true;
    }

    return false;
}
void RenderTextControl::setInnerTextStyle(PassRefPtr<RenderStyle> style)
{
    if (m_innerText) {
        RefPtr<RenderStyle> textStyle = style;
        m_innerText->renderer()->setStyle(textStyle);
        for (Node* n = m_innerText->firstChild(); n; n = n->traverseNextNode(m_innerText.get())) {
            if (n->renderer())
                n->renderer()->setStyle(textStyle);
        }
    }
}
Example #29
0
static bool hasARenderedDescendant(Node* node, Node* excludedNode)
{
    for (Node* n = node->firstChild(); n;) {
        if (n == excludedNode) {
            n = n->traverseNextSibling(node);
            continue;
        }
        if (n->renderer())
            return true;
        n = n->traverseNextNode(node);
    }
    return false;
}
Example #30
0
static Node* nextNodeWithGreaterTabIndex(Node* start, int tabIndex, KeyboardEvent* event)
{
    // Search is inclusive of start
    int winningTabIndex = std::numeric_limits<short>::max() + 1;
    Node* winner = 0;
    for (Node* n = start; n; n = n->traverseNextNode())
        if (n->isKeyboardFocusable(event) && n->tabIndex() > tabIndex && n->tabIndex() < winningTabIndex) {
            winner = n;
            winningTabIndex = n->tabIndex();
        }

    return winner;
}