Пример #1
0
void SelectorDataList::executeForTraverseRoots(const SelectorData& selector, SimpleElementListType& traverseRoots, MatchTraverseRootState matchTraverseRoots, ContainerNode& rootNode, typename SelectorQueryTrait::OutputType& output) const
{
    if (traverseRoots.isEmpty())
        return;

    if (matchTraverseRoots) {
        while (!traverseRoots.isEmpty()) {
            Element& element = *traverseRoots.next();
            if (selectorMatches(selector, element, rootNode)) {
                SelectorQueryTrait::appendElement(output, element);
                if (SelectorQueryTrait::shouldOnlyMatchFirstElement)
                    return;
            }
        }
        return;
    }

    while (!traverseRoots.isEmpty()) {
        Element& traverseRoot = *traverseRoots.next();
        for (Element* element = ElementTraversal::firstWithin(traverseRoot); element; element = ElementTraversal::next(*element, &traverseRoot)) {
            if (selectorMatches(selector, *element, rootNode)) {
                SelectorQueryTrait::appendElement(output, *element);
                if (SelectorQueryTrait::shouldOnlyMatchFirstElement)
                    return;
            }
        }
    }
}
Пример #2
0
void SelectorDataList::execute(ContainerNode& rootNode, typename SelectorQueryTrait::OutputType& output) const
{
    if (!canUseFastQuery(rootNode)) {
        if (m_needsUpdatedDistribution)
            rootNode.updateDistribution();
        if (m_crossesTreeBoundary) {
            executeSlowTraversingShadowTree<SelectorQueryTrait>(rootNode, output);
        } else {
            executeSlow<SelectorQueryTrait>(rootNode, output);
        }
        return;
    }

    ASSERT(m_selectors.size() == 1);

    const CSSSelector& selector = *m_selectors[0];
    const CSSSelector& firstSelector = selector;

    // Fast path for querySelector*('#id'), querySelector*('tag#id').
    if (const CSSSelector* idSelector = selectorForIdLookup(firstSelector)) {
        const AtomicString& idToMatch = idSelector->value();
        if (rootNode.treeScope().containsMultipleElementsWithId(idToMatch)) {
            const WillBeHeapVector<RawPtrWillBeMember<Element>>& elements = rootNode.treeScope().getAllElementsById(idToMatch);
            size_t count = elements.size();
            for (size_t i = 0; i < count; ++i) {
                Element& element = *elements[i];
                if (!(isTreeScopeRoot(rootNode) || element.isDescendantOf(&rootNode)))
                    continue;
                if (selectorMatches(selector, element, rootNode)) {
                    SelectorQueryTrait::appendElement(output, element);
                    if (SelectorQueryTrait::shouldOnlyMatchFirstElement)
                        return;
                }
            }
            return;
        }
        Element* element = rootNode.treeScope().getElementById(idToMatch);
        if (!element || !(isTreeScopeRoot(rootNode) || element->isDescendantOf(&rootNode)))
            return;
        if (selectorMatches(selector, *element, rootNode))
            SelectorQueryTrait::appendElement(output, *element);
        return;
    }

    if (!firstSelector.tagHistory()) {
        // Fast path for querySelector*('.foo'), and querySelector*('div').
        switch (firstSelector.match()) {
        case CSSSelector::Class:
            collectElementsByClassName<SelectorQueryTrait>(rootNode, firstSelector.value(), output);
            return;
        case CSSSelector::Tag:
            collectElementsByTagName<SelectorQueryTrait>(rootNode, firstSelector.tagQName(), output);
            return;
        default:
            break; // If we need another fast path, add here.
        }
    }

    findTraverseRootsAndExecute<SelectorQueryTrait>(rootNode, output);
}
Пример #3
0
ALWAYS_INLINE void SelectorDataList::executeFastPathForIdSelector(const Node* rootNode, const SelectorData& selectorData, const CSSSelector* idSelector, typename SelectorQueryTrait::OutputType& output) const
{
    ASSERT(m_selectors.size() == 1);
    ASSERT(idSelector);

    const AtomicString& idToMatch = idSelector->value();
    if (UNLIKELY(rootNode->treeScope()->containsMultipleElementsWithId(idToMatch))) {
        const Vector<Element*>* elements = rootNode->treeScope()->getAllElementsById(idToMatch);
        ASSERT(elements);
        size_t count = elements->size();
        bool rootNodeIsTreeScopeRoot = isTreeScopeRoot(rootNode);
        for (size_t i = 0; i < count; ++i) {
            Element* element = elements->at(i);
            if ((rootNodeIsTreeScopeRoot || element->isDescendantOf(rootNode)) && selectorMatches(selectorData, element, rootNode)) {
                SelectorQueryTrait::appendOutputForElement(output, element);
                if (SelectorQueryTrait::shouldOnlyMatchFirstElement)
                    return;
            }
        }
        return;
    }

    Element* element = rootNode->treeScope()->getElementById(idToMatch);
    if (!element || !(isTreeScopeRoot(rootNode) || element->isDescendantOf(rootNode)))
        return;
    if (selectorMatches(selectorData, element, rootNode))
        SelectorQueryTrait::appendOutputForElement(output, element);
}
Пример #4
0
ALWAYS_INLINE void SelectorDataList::executeFastPathForIdSelector(const Node* rootNode, const SelectorData& selectorData, const CSSSelector* idSelector, Vector<RefPtr<Node> >& matchedElements) const
{
    ASSERT(m_selectors.size() == 1);
    ASSERT(idSelector);
    const AtomicString& idToMatch = idSelector->value();
    if (UNLIKELY(rootNode->treeScope()->containsMultipleElementsWithId(idToMatch))) {
        const Vector<Element*>* elements = rootNode->treeScope()->getAllElementsById(idToMatch);
        ASSERT(elements);
        size_t count = elements->size();
        bool rootNodeIsTreeScopeRoot = isTreeScopeRoot(rootNode);
        for (size_t i = 0; i < count; ++i) {
            Element* element = elements->at(i);
            if ((rootNodeIsTreeScopeRoot || element->isDescendantOf(rootNode)) && selectorMatches(selectorData, element, rootNode)) {
                matchedElements.append(element);
                if (firstMatchOnly)
                    return;
            }
        }
        return;
    }
    Element* element = rootNode->treeScope()->getElementById(idToMatch);
    if (!element || !(isTreeScopeRoot(rootNode) || element->isDescendantOf(rootNode)))
        return;
    if (selectorMatches(selectorData, element, rootNode))
        matchedElements.append(element);
}
void SelectorDataList::executeQueryAll(Node* rootNode, Vector<RefPtr<Node> >& matchedElements) const
{
    if (!canUseFastQuery(rootNode))
        return executeSlowQueryAll(rootNode, matchedElements);

    ASSERT(m_selectors.size() == 1);
    ASSERT(m_selectors[0].selector);

    const CSSSelector* firstSelector = m_selectors[0].selector;

    if (!firstSelector->tagHistory()) {
        // Fast path for querySelectorAll('#id'), querySelectorAl('.foo'), and querySelectorAll('div').
        switch (firstSelector->m_match) {
        case CSSSelector::Id:
            {
                if (rootNode->document()->containsMultipleElementsWithId(firstSelector->value()))
                    break;

                // Just the same as getElementById.
                Element* element = rootNode->treeScope()->getElementById(firstSelector->value());
                if (element && (isTreeScopeRoot(rootNode) || element->isDescendantOf(rootNode)))
                    matchedElements.append(element);
                return;
            }
        case CSSSelector::Class:
            return collectElementsByClassName(rootNode, firstSelector->value(), matchedElements);
        case CSSSelector::Tag:
            return collectElementsByTagName(rootNode, firstSelector->tagQName(), matchedElements);
        default:
            break; // If we need another fast path, add here.
        }
    }

    bool matchTraverseRoots;
    OwnPtr<SimpleNodeList> traverseRoots = findTraverseRoots(rootNode, matchTraverseRoots);
    if (traverseRoots->isEmpty())
        return;

    const SelectorData& selector = m_selectors[0];
    if (matchTraverseRoots) {
        while (!traverseRoots->isEmpty()) {
            Node* node = traverseRoots->next();
            Element* element = toElement(node);
            if (selectorMatches(selector, element, rootNode))
                matchedElements.append(element);
        }
        return;
    }

    while (!traverseRoots->isEmpty()) {
        Node* traverseRoot = traverseRoots->next();
        for (Element* element = ElementTraversal::firstWithin(traverseRoot); element; element = ElementTraversal::next(element, traverseRoot)) {
            if (selectorMatches(selector, element, rootNode))
                matchedElements.append(element);
        }
    }
}
Пример #6
0
void SelectorDataList::execute(ContainerNode& rootNode, typename SelectorQueryTrait::OutputType& output) const
{
    if (!canUseFastQuery(rootNode)) {
        executeSlow<SelectorQueryTrait>(rootNode, output);
        return;
    }

    ASSERT(m_selectors.size() == 1);

    const SelectorData& selector = m_selectors[0];
    const CSSSelector& firstSelector = selector.selector;

    // Fast path for querySelector*('#id'), querySelector*('tag#id').
    if (const CSSSelector* idSelector = selectorForIdLookup(firstSelector)) {
        const AtomicString& idToMatch = idSelector->value();
        Element* singleMatchingElement = 0;
        if (rootNode.treeScope().getNumberOfElementsWithId(idToMatch, singleMatchingElement) > 1) {
            const Vector<Element*>& elements = rootNode.treeScope().getAllElementsById(idToMatch);
            size_t count = elements.size();
            for (size_t i = 0; i < count; ++i) {
                Element& element = *elements[i];
                if (!(isTreeScopeRoot(rootNode) || element.isDescendantOf(&rootNode)))
                    continue;
                if (selectorMatches(selector, element, rootNode)) {
                    SelectorQueryTrait::appendElement(output, element);
                    if (SelectorQueryTrait::shouldOnlyMatchFirstElement)
                        return;
                }
            }
            return;
        }

        if (!singleMatchingElement || !(isTreeScopeRoot(rootNode) || singleMatchingElement->isDescendantOf(&rootNode)))
            return;
        if (selectorMatches(selector, *singleMatchingElement, rootNode))
            SelectorQueryTrait::appendElement(output, *singleMatchingElement);
        return;
    }

    if (!firstSelector.tagHistory()) {
        // Fast path for querySelector*('.foo'), and querySelector*('div').
        switch (firstSelector.m_match) {
        case CSSSelector::Class:
            collectElementsByClassName<SelectorQueryTrait>(rootNode, firstSelector.value(), output);
            return;
        case CSSSelector::Tag:
            collectElementsByTagName<SelectorQueryTrait>(rootNode, firstSelector.tagQName(), output);
            return;
        default:
            break; // If we need another fast path, add here.
        }
    }

    findTraverseRootsAndExecute<SelectorQueryTrait>(rootNode, output);
}
Пример #7
0
void SelectorDataList::execute(Node* rootNode, Vector<RefPtr<Node> >& matchedElements) const
{
    if (const CSSSelector* idSelector = selectorForIdLookup(rootNode)) {
        ASSERT(m_selectors.size() == 1);
        const AtomicString& idToMatch = idSelector->value();
        if (UNLIKELY(rootNode->treeScope()->containsMultipleElementsWithId(idToMatch))) {
            const Vector<Element*>* elements = rootNode->treeScope()->getAllElementsById(idToMatch);
            ASSERT(elements);
            size_t count = elements->size();
            for (size_t i = 0; i < count; ++i) {
                Element* element = elements->at(i);
                if (selectorMatches(m_selectors[0], element, rootNode)) {
                    matchedElements.append(element);
                    if (firstMatchOnly)
                        return;
                }
            }
            return;
        }
        Element* element = rootNode->treeScope()->getElementById(idToMatch);
        if (!element || !(isTreeScopeRoot(rootNode) || element->isDescendantOf(rootNode)))
            return;
        if (selectorMatches(m_selectors[0], element, rootNode))
            matchedElements.append(element);
        return;
    }

    unsigned selectorCount = m_selectors.size();
    if (selectorCount == 1) {
        const SelectorData& selector = m_selectors[0];
        for (Element* element = ElementTraversal::firstWithin(rootNode); element; element = ElementTraversal::next(element, rootNode)) {
            if (selectorMatches(selector, element, rootNode)) {
                matchedElements.append(element);
                if (firstMatchOnly)
                    return;
            }
        }
        return;
    }
    for (Element* element = ElementTraversal::firstWithin(rootNode); element; element = ElementTraversal::next(element, rootNode)) {
        for (unsigned i = 0; i < selectorCount; ++i) {
            if (selectorMatches(m_selectors[i], element, rootNode)) {
                matchedElements.append(element);
                if (firstMatchOnly)
                    return;
                break;
            }
        }
    }
}
Element* SelectorDataList::executeQueryFirst(Node* rootNode) const
{
    if (!canUseFastQuery(rootNode))
        return executeSlowQueryFirst(rootNode);


    const CSSSelector* selector = m_selectors[0].selector;
    ASSERT(selector);

    if (!selector->tagHistory()) {
        // Fast path for querySelector('#id'), querySelector('.foo'), and querySelector('div').
        // Many web developers uses querySelector with these simple selectors.
        switch (selector->m_match) {
        case CSSSelector::Id:
            {
                if (rootNode->document()->containsMultipleElementsWithId(selector->value()))
                    break;
                Element* element = rootNode->treeScope()->getElementById(selector->value());
                return element && (isTreeScopeRoot(rootNode) || element->isDescendantOf(rootNode)) ? element : 0;
            }
        case CSSSelector::Class:
            return findElementByClassName(rootNode, selector->value());
        case CSSSelector::Tag:
            return findElementByTagName(rootNode, selector->tagQName());
        default:
            break; // If we need another fast path, add here.
        }
    }

    bool matchTraverseRoot;
    Node* traverseRootNode = findTraverseRoot(rootNode, matchTraverseRoot);
    if (!traverseRootNode)
        return 0;
    if (matchTraverseRoot) {
        ASSERT(m_selectors.size() == 1);
        ASSERT(traverseRootNode->isElementNode());
        Element* element = toElement(traverseRootNode);
        return selectorMatches(m_selectors[0], element, rootNode) ? element : 0;
    }

    for (Element* element = ElementTraversal::firstWithin(traverseRootNode); element; element = ElementTraversal::next(element, traverseRootNode)) {
        if (selectorMatches(m_selectors[0], element, rootNode))
            return element;
    }
    return 0;
}
Пример #9
0
bool SelectorDataList::matches(Element& targetElement) const
{
    for (auto& selctor : m_selectors) {
        if (selectorMatches(selctor, targetElement, targetElement))
            return true;
    }
    return false;
}
Пример #10
0
bool SelectorDataList::matches(Element& targetElement) const
{
    unsigned selectorCount = m_selectors.size();
    for (unsigned i = 0; i < selectorCount; ++i) {
        if (selectorMatches(m_selectors[i], targetElement, targetElement))
            return true;
    }
    return false;
}
Element* SelectorDataList::executeSlowQueryFirst(Node* rootNode) const
{
    for (Element* element = ElementTraversal::firstWithin(rootNode); element; element = ElementTraversal::next(element, rootNode)) {
        for (unsigned i = 0; i < m_selectors.size(); ++i) {
            if (selectorMatches(m_selectors[i], element, rootNode))
                return element;
        }
    }
    return 0;
}
Пример #12
0
bool SelectorDataList::selectorListMatches(ContainerNode& rootNode, Element& element, typename SelectorQueryTrait::OutputType& output) const
{
    for (unsigned i = 0; i < m_selectors.size(); ++i) {
        if (selectorMatches(*m_selectors[i], element, rootNode)) {
            SelectorQueryTrait::appendElement(output, element);
            return true;
        }
    }
    return false;
}
Пример #13
0
void SelectorDataList::executeForTraverseRoot(const CSSSelector& selector, ContainerNode* traverseRoot, MatchTraverseRootState matchTraverseRoot, ContainerNode& rootNode, typename SelectorQueryTrait::OutputType& output) const
{
    if (!traverseRoot)
        return;

    if (matchTraverseRoot) {
        if (selectorMatches(selector, toElement(*traverseRoot), rootNode))
            SelectorQueryTrait::appendElement(output, toElement(*traverseRoot));
        return;
    }

    for (Element& element : ElementTraversal::descendantsOf(*traverseRoot)) {
        if (selectorMatches(selector, element, rootNode)) {
            SelectorQueryTrait::appendElement(output, element);
            if (SelectorQueryTrait::shouldOnlyMatchFirstElement)
                return;
        }
    }
}
Пример #14
0
void SelectorDataList::executeForTraverseRoot(const SelectorData& selector, ContainerNode* traverseRoot, MatchTraverseRootState matchTraverseRoot, ContainerNode& rootNode, typename SelectorQueryTrait::OutputType& output) const
{
    if (!traverseRoot)
        return;

    if (matchTraverseRoot) {
        if (selectorMatches(selector, toElement(*traverseRoot), rootNode))
            SelectorQueryTrait::appendElement(output, toElement(*traverseRoot));
        return;
    }

    for (Element* element = ElementTraversal::firstWithin(*traverseRoot); element; element = ElementTraversal::next(*element, traverseRoot)) {
        if (selectorMatches(selector, *element, rootNode)) {
            SelectorQueryTrait::appendElement(output, *element);
            if (SelectorQueryTrait::shouldOnlyMatchFirstElement)
                return;
        }
    }
}
void SelectorDataList::executeSlowQueryAll(Node* rootNode, Vector<RefPtr<Node> >& matchedElements) const
{
    for (Element* element = ElementTraversal::firstWithin(rootNode); element; element = ElementTraversal::next(element, rootNode)) {
        for (unsigned i = 0; i < m_selectors.size(); ++i) {
            if (selectorMatches(m_selectors[i], element, rootNode)) {
                matchedElements.append(element);
                break;
            }
        }
    }
}
Пример #16
0
ALWAYS_INLINE void SelectorDataList::executeSingleSelectorData(const Node* rootNode, const SelectorData& selectorData, Vector<RefPtr<Node> >& matchedElements) const
{
    ASSERT(m_selectors.size() == 1);

    for (Element* element = ElementTraversal::firstWithin(rootNode); element; element = ElementTraversal::next(element, rootNode)) {
        if (selectorMatches(selectorData, element, rootNode)) {
            matchedElements.append(element);
            if (firstMatchOnly)
                return;
        }
    }
}
Пример #17
0
ALWAYS_INLINE void SelectorDataList::executeSingleSelectorData(const ContainerNode& rootNode, const SelectorData& selectorData, typename SelectorQueryTrait::OutputType& output) const
{
    ASSERT(m_selectors.size() == 1);

    for (auto& element : elementDescendants(const_cast<ContainerNode&>(rootNode))) {
        if (selectorMatches(selectorData, element, rootNode)) {
            SelectorQueryTrait::appendOutputForElement(output, &element);
            if (SelectorQueryTrait::shouldOnlyMatchFirstElement)
                return;
        }
    }
}
Пример #18
0
ALWAYS_INLINE void SelectorDataList::executeSingleSelectorData(const Node* rootNode, const SelectorData& selectorData, typename SelectorQueryTrait::OutputType& output) const
{
    ASSERT(m_selectors.size() == 1);

    for (Element* element = ElementTraversal::firstWithin(rootNode); element; element = ElementTraversal::next(element, rootNode)) {
        if (selectorMatches(selectorData, element, rootNode)) {
            SelectorQueryTrait::appendOutputForElement(output, element);
            if (SelectorQueryTrait::shouldOnlyMatchFirstElement)
                return;
        }
    }
}
Пример #19
0
void SelectorDataList::execute(Node* rootNode, Vector<RefPtr<Node> >& matchedElements) const
{
    if (canUseIdLookup(rootNode)) {
        ASSERT(m_selectors.size() == 1);
        const CSSSelector* selector = m_selectors[0].selector;
        Element* element = rootNode->treeScope()->getElementById(selector->value());
        if (!element || !(isTreeScopeRoot(rootNode) || element->isDescendantOf(rootNode)))
            return;
        if (selectorMatches(m_selectors[0], element, rootNode))
            matchedElements.append(element);
        return;
    }

    unsigned selectorCount = m_selectors.size();

    Node* n = rootNode->firstChild();
    while (n) {
        if (n->isElementNode()) {
            Element* element = toElement(n);
            for (unsigned i = 0; i < selectorCount; ++i) {
                if (selectorMatches(m_selectors[i], element, rootNode)) {
                    matchedElements.append(element);
                    if (firstMatchOnly)
                        return;
                    break;
                }
            }
            if (element->firstChild()) {
                n = element->firstChild();
                continue;
            }
        }
        while (!n->nextSibling()) {
            n = n->parentNode();
            if (n == rootNode)
                return;
        }
        n = n->nextSibling();
    }
}
Пример #20
0
void SelectorDataList::executeSlow(ContainerNode& rootNode, typename SelectorQueryTrait::OutputType& output) const
{
    for (Element* element = ElementTraversal::firstWithin(rootNode); element; element = ElementTraversal::next(*element, &rootNode)) {
        for (unsigned i = 0; i < m_selectors.size(); ++i) {
            if (selectorMatches(m_selectors[i], *element, rootNode)) {
                SelectorQueryTrait::appendElement(output, *element);
                if (SelectorQueryTrait::shouldOnlyMatchFirstElement)
                    return;
                break;
            }
        }
    }
}
Пример #21
0
bool SelectorDataList::matches(Element& targetElement) const
{
    if (m_needsUpdatedDistribution)
        targetElement.updateDistribution();

    unsigned selectorCount = m_selectors.size();
    for (unsigned i = 0; i < selectorCount; ++i) {
        if (selectorMatches(*m_selectors[i], targetElement, targetElement))
            return true;
    }

    return false;
}
Пример #22
0
ALWAYS_INLINE void SelectorDataList::executeSingleMultiSelectorData(const ContainerNode& rootNode, typename SelectorQueryTrait::OutputType& output) const
{
    for (auto& element : elementDescendants(const_cast<ContainerNode&>(rootNode))) {
        for (auto& selector : m_selectors) {
            if (selectorMatches(selector, element, rootNode)) {
                SelectorQueryTrait::appendOutputForElement(output, &element);
                if (SelectorQueryTrait::shouldOnlyMatchFirstElement)
                    return;
                break;
            }
        }
    }
}
Пример #23
0
void SelectorDataList::execute(Node* rootNode, Vector<RefPtr<Node> >& matchedElements) const
{
    std::pair<bool, Node*> traverseRoot = findTraverseRoot(rootNode);
    if (!traverseRoot.second)
        return;
    Node* traverseRootNode = traverseRoot.second;
    if (traverseRoot.first) {
        ASSERT(m_selectors.size() == 1);
        ASSERT(traverseRootNode->isElementNode());
        Element* element = toElement(traverseRootNode);
        if (selectorMatches(m_selectors[0], element, rootNode))
            matchedElements.append(element);
        return;
    }

    unsigned selectorCount = m_selectors.size();
    if (selectorCount == 1) {
        const SelectorData& selector = m_selectors[0];
        for (Element* element = ElementTraversal::firstWithin(rootNode); element; element = ElementTraversal::next(element, rootNode)) {
            if (selectorMatches(selector, element, rootNode)) {
                matchedElements.append(element);
                if (firstMatchOnly)
                    return;
            }
        }
        return;
    }
    for (Element* element = ElementTraversal::firstWithin(rootNode); element; element = ElementTraversal::next(element, rootNode)) {
        for (unsigned i = 0; i < selectorCount; ++i) {
            if (selectorMatches(m_selectors[i], element, rootNode)) {
                matchedElements.append(element);
                if (firstMatchOnly)
                    return;
                break;
            }
        }
    }
}
Пример #24
0
ALWAYS_INLINE void SelectorDataList::executeSingleMultiSelectorData(const Node* rootNode, Vector<RefPtr<Node> >& matchedElements) const
{
    unsigned selectorCount = m_selectors.size();
    for (Element* element = ElementTraversal::firstWithin(rootNode); element; element = ElementTraversal::next(element, rootNode)) {
        for (unsigned i = 0; i < selectorCount; ++i) {
            if (selectorMatches(m_selectors[i], element, rootNode)) {
                matchedElements.append(element);
                if (firstMatchOnly)
                    return;
                break;
            }
        }
    }
}
Пример #25
0
ALWAYS_INLINE void SelectorDataList::executeSingleMultiSelectorData(const Node* rootNode, typename SelectorQueryTrait::OutputType& output) const
{
    unsigned selectorCount = m_selectors.size();
    for (Element* element = ElementTraversal::firstWithin(rootNode); element; element = ElementTraversal::next(element, rootNode)) {
        for (unsigned i = 0; i < selectorCount; ++i) {
            if (selectorMatches(m_selectors[i], element, rootNode)) {
                SelectorQueryTrait::appendOutputForElement(output, element);
                if (SelectorQueryTrait::shouldOnlyMatchFirstElement)
                    return;
                break;
            }
        }
    }
}
Пример #26
0
Element* SelectorDataList::closest(Element& targetElement) const
{
    if (m_needsUpdatedDistribution)
        targetElement.updateDistribution();

    unsigned selectorCount = m_selectors.size();
    for (Element* currentElement = &targetElement; currentElement; currentElement = currentElement->parentElement()) {
        for (unsigned i = 0; i < selectorCount; ++i) {
            if (selectorMatches(*m_selectors[i], *currentElement, targetElement))
                return currentElement;
        }
    }
    return nullptr;
}
Пример #27
0
ALWAYS_INLINE void SelectorDataList::executeSingleMultiSelectorData(const ContainerNode& rootNode, typename SelectorQueryTrait::OutputType& output) const
{
    unsigned selectorCount = m_selectors.size();
    for (auto& element : elementDescendants(const_cast<ContainerNode&>(rootNode))) {
        for (unsigned i = 0; i < selectorCount; ++i) {
            if (selectorMatches(m_selectors[i], element, rootNode)) {
                SelectorQueryTrait::appendOutputForElement(output, &element);
                if (SelectorQueryTrait::shouldOnlyMatchFirstElement)
                    return;
                break;
            }
        }
    }
}