ALWAYS_INLINE void SelectorDataList::executeCompiledSingleMultiSelectorData(const ContainerNode& rootNode, typename SelectorQueryTrait::OutputType& output) const { SelectorChecker::CheckingContext checkingContext(SelectorChecker::Mode::QueryingRules); checkingContext.scope = rootNode.isDocumentNode() ? nullptr : &rootNode; for (auto& element : elementDescendants(const_cast<ContainerNode&>(rootNode))) { for (auto& selector : m_selectors) { #if CSS_SELECTOR_JIT_PROFILING selector.compiledSelectorUsed(); #endif bool matched = false; void* compiledSelectorChecker = selector.compiledSelectorCodeRef.code().executableAddress(); if (selector.compilationStatus == SelectorCompilationStatus::SimpleSelectorChecker) { auto selectorChecker = SelectorCompiler::querySelectorSimpleSelectorCheckerFunction(compiledSelectorChecker, selector.compilationStatus); matched = selectorChecker(&element); } else { ASSERT(selector.compilationStatus == SelectorCompilationStatus::SelectorCheckerWithCheckingContext); auto selectorChecker = SelectorCompiler::querySelectorSelectorCheckerFunctionWithCheckingContext(compiledSelectorChecker, selector.compilationStatus); matched = selectorChecker(&element, &checkingContext); } if (matched) { SelectorQueryTrait::appendOutputForElement(output, &element); if (SelectorQueryTrait::shouldOnlyMatchFirstElement) return; break; } } } }
ALWAYS_INLINE void SelectorDataList::executeSingleTagNameSelectorData(const ContainerNode& rootNode, const SelectorData& selectorData, typename SelectorQueryTrait::OutputType& output) const { ASSERT(m_selectors.size() == 1); ASSERT(isSingleTagNameSelector(*selectorData.selector)); const QualifiedName& tagQualifiedName = selectorData.selector->tagQName(); const AtomicString& selectorLocalName = tagQualifiedName.localName(); const AtomicString& selectorNamespaceURI = tagQualifiedName.namespaceURI(); if (selectorNamespaceURI == starAtom) { if (selectorLocalName != starAtom) { // Common case: name defined, selectorNamespaceURI is a wildcard. elementsForLocalName<SelectorQueryTrait>(rootNode, selectorLocalName, output); } else { // Other fairly common case: both are wildcards. anyElement<SelectorQueryTrait>(rootNode, output); } } else { // Fallback: NamespaceURI is set, selectorLocalName may be starAtom. for (auto& element : elementDescendants(const_cast<ContainerNode&>(rootNode))) { if (element.namespaceURI() == selectorNamespaceURI && (selectorLocalName == starAtom || element.tagQName().localName() == selectorLocalName)) { SelectorQueryTrait::appendOutputForElement(output, &element); if (SelectorQueryTrait::shouldOnlyMatchFirstElement) return; } } } }
static inline void anyElement(const ContainerNode& rootNode, typename SelectorQueryTrait::OutputType& output) { for (auto& element : elementDescendants(const_cast<ContainerNode&>(rootNode))) { SelectorQueryTrait::appendOutputForElement(output, &element); if (SelectorQueryTrait::shouldOnlyMatchFirstElement) return; } }
ALWAYS_INLINE void SelectorDataList::executeCompiledSimpleSelectorChecker(const ContainerNode& rootNode, SelectorCompiler::SimpleSelectorChecker selectorChecker, typename SelectorQueryTrait::OutputType& output) const { for (auto& element : elementDescendants(const_cast<ContainerNode&>(rootNode))) { if (selectorChecker(&element)) { SelectorQueryTrait::appendOutputForElement(output, &element); if (SelectorQueryTrait::shouldOnlyMatchFirstElement) return; } } }
static inline void elementsForLocalName(const ContainerNode& rootNode, const AtomicString& localName, typename SelectorQueryTrait::OutputType& output) { for (auto& element : elementDescendants(const_cast<ContainerNode&>(rootNode))) { if (element.tagQName().localName() == localName) { SelectorQueryTrait::appendOutputForElement(output, &element); if (SelectorQueryTrait::shouldOnlyMatchFirstElement) return; } } }
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; } } }
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; } } } }
Element* DocumentFragment::getElementById(const AtomicString& id) const { // Fast path for ShadowRoot, where we are both a DocumentFragment and a TreeScope. if (isTreeScope()) return treeScope().getElementById(id); // Otherwise, fall back to iterating all of the element descendants. for (auto& element : elementDescendants(*this)) { if (element.getIdAttribute() == id) return const_cast<Element*>(&element); } return nullptr; }
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; } } } }
ALWAYS_INLINE void SelectorDataList::executeSingleClassNameSelectorData(const ContainerNode& rootNode, const SelectorData& selectorData, typename SelectorQueryTrait::OutputType& output) const { ASSERT(m_selectors.size() == 1); ASSERT(isSingleClassNameSelector(*selectorData.selector)); const AtomicString& className = selectorData.selector->value(); for (auto& element : elementDescendants(const_cast<ContainerNode&>(rootNode))) { if (element.hasClass() && element.classNames().contains(className)) { SelectorQueryTrait::appendOutputForElement(output, &element); if (SelectorQueryTrait::shouldOnlyMatchFirstElement) return; } } }
ALWAYS_INLINE void SelectorDataList::executeCompiledSimpleSelectorChecker(const ContainerNode& searchRootNode, SelectorCompiler::QuerySelectorSimpleSelectorChecker selectorChecker, typename SelectorQueryTrait::OutputType& output, const SelectorData& selectorData) const { for (auto& element : elementDescendants(const_cast<ContainerNode&>(searchRootNode))) { #if CSS_SELECTOR_JIT_PROFILING selectorData.compiledSelectorUsed(); #else UNUSED_PARAM(selectorData); #endif if (selectorChecker(&element)) { SelectorQueryTrait::appendOutputForElement(output, &element); if (SelectorQueryTrait::shouldOnlyMatchFirstElement) return; } } }
ALWAYS_INLINE void SelectorDataList::executeCompiledSelectorCheckerWithCheckingContext(const ContainerNode& rootNode, const ContainerNode& searchRootNode, SelectorCompiler::QuerySelectorSelectorCheckerWithCheckingContext selectorChecker, typename SelectorQueryTrait::OutputType& output, const SelectorData& selectorData) const { SelectorChecker::CheckingContext checkingContext(SelectorChecker::Mode::QueryingRules); checkingContext.scope = rootNode.isDocumentNode() ? nullptr : &rootNode; for (auto& element : elementDescendants(const_cast<ContainerNode&>(searchRootNode))) { #if CSS_SELECTOR_JIT_PROFILING selectorData.compiledSelectorUsed(); #else UNUSED_PARAM(selectorData); #endif if (selectorChecker(&element, &checkingContext)) { SelectorQueryTrait::appendOutputForElement(output, &element); if (SelectorQueryTrait::shouldOnlyMatchFirstElement) return; } } }