void CSSSelectorList::adoptSelectorVector(Vector<OwnPtr<CSSParserSelector>>& selectorVector)
{
    deleteSelectors();
    size_t flattenedSize = 0;
    for (size_t i = 0; i < selectorVector.size(); ++i) {
        for (CSSParserSelector* selector = selectorVector[i].get(); selector; selector = selector->tagHistory())
            ++flattenedSize;
    }
    ASSERT(flattenedSize);
    m_selectorArray = reinterpret_cast<CSSSelector*>(fastMalloc(sizeof(CSSSelector) * flattenedSize));
    size_t arrayIndex = 0;
    for (size_t i = 0; i < selectorVector.size(); ++i) {
        CSSParserSelector* current = selectorVector[i].get();
        while (current) {
            // Move item from the parser selector vector into m_selectorArray without invoking destructor (Ugh.)
            CSSSelector* currentSelector = current->releaseSelector().leakPtr();
            memcpy(&m_selectorArray[arrayIndex], currentSelector, sizeof(CSSSelector));
            fastFree(currentSelector);

            current = current->tagHistory();
            ASSERT(!m_selectorArray[arrayIndex].isLastInSelectorList());
            if (current)
                m_selectorArray[arrayIndex].setNotLastInTagHistory();
            ++arrayIndex;
        }
        ASSERT(m_selectorArray[arrayIndex - 1].isLastInTagHistory());
    }
    ASSERT(flattenedSize == arrayIndex);
    m_selectorArray[arrayIndex - 1].setLastInSelectorList();
    selectorVector.clear();
}
Exemple #2
0
void CSSParserSelector::appendTagHistory(CSSSelector::Relation relation, PassOwnPtr<CSSParserSelector> selector)
{
    CSSParserSelector* end = this;
    while (end->tagHistory())
        end = end->tagHistory();
    end->setRelation(relation);
    end->setTagHistory(selector);
}
Exemple #3
0
void CSSParserSelector::appendTagHistory(CSSSelector::Relation relation, std::unique_ptr<CSSParserSelector> selector)
{
    CSSParserSelector* end = this;
    while (end->tagHistory())
        end = end->tagHistory();
    end->setRelation(relation);
    end->setTagHistory(std::move(selector));
}
Exemple #4
0
CSSParserSelector* CSSParserSelector::findDistributedPseudoElementSelector() const
{
    CSSParserSelector* selector = const_cast<CSSParserSelector*>(this);
    do {
        if (selector->isDistributedPseudoElement())
            return selector;
    } while ((selector = selector->tagHistory()));
    return 0;
}
Exemple #5
0
bool CSSParserSelector::hasHostPseudoSelector() const
{
    CSSParserSelector* selector = const_cast<CSSParserSelector*>(this);
    do {
        if (selector->pseudoType() == CSSSelector::PseudoHost || selector->pseudoType() == CSSSelector::PseudoHostContext)
            return true;
    } while ((selector = selector->tagHistory()));
    return false;
}
void CSSParserSelector::appendTagHistory(CSSParserSelectorCombinator relation, std::unique_ptr<CSSParserSelector> selector)
{
    CSSParserSelector* end = this;
    while (end->tagHistory())
        end = end->tagHistory();

    CSSSelector::Relation selectorRelation;
    switch (relation) {
    case CSSParserSelectorCombinator::Child:
        selectorRelation = CSSSelector::Child;
        break;
    case CSSParserSelectorCombinator::DescendantSpace:
        selectorRelation = CSSSelector::Descendant;
        break;
#if ENABLE(CSS_SELECTORS_LEVEL4)
    case CSSParserSelectorCombinator::DescendantDoubleChild:
        selectorRelation = CSSSelector::Descendant;
        break;
#endif
    case CSSParserSelectorCombinator::DirectAdjacent:
        selectorRelation = CSSSelector::DirectAdjacent;
        break;
    case CSSParserSelectorCombinator::IndirectAdjacent:
        selectorRelation = CSSSelector::IndirectAdjacent;
        break;
    }
    end->setRelation(selectorRelation);

#if ENABLE(CSS_SELECTORS_LEVEL4)
    if (relation == CSSParserSelectorCombinator::DescendantDoubleChild)
        end->setDescendantUseDoubleChildSyntax();
#endif

    end->setTagHistory(WTFMove(selector));
}
Exemple #7
0
CSSSelectorList CSSSelectorList::adoptSelectorVector(
    Vector<std::unique_ptr<CSSParserSelector>>& selectorVector) {
  size_t flattenedSize = 0;
  for (size_t i = 0; i < selectorVector.size(); ++i) {
    for (CSSParserSelector* selector = selectorVector[i].get(); selector;
         selector = selector->tagHistory())
      ++flattenedSize;
  }
  ASSERT(flattenedSize);

  CSSSelectorList list;
  list.m_selectorArray =
      reinterpret_cast<CSSSelector*>(WTF::Partitions::fastMalloc(
          sizeof(CSSSelector) * flattenedSize, kCSSSelectorTypeName));
  size_t arrayIndex = 0;
  for (size_t i = 0; i < selectorVector.size(); ++i) {
    CSSParserSelector* current = selectorVector[i].get();
    while (current) {
      // Move item from the parser selector vector into m_selectorArray without
      // invoking destructor (Ugh.)
      CSSSelector* currentSelector = current->releaseSelector().release();
      memcpy(&list.m_selectorArray[arrayIndex], currentSelector,
             sizeof(CSSSelector));
      WTF::Partitions::fastFree(currentSelector);

      current = current->tagHistory();
      ASSERT(!list.m_selectorArray[arrayIndex].isLastInSelectorList());
      if (current)
        list.m_selectorArray[arrayIndex].setNotLastInTagHistory();
      ++arrayIndex;
    }
    ASSERT(list.m_selectorArray[arrayIndex - 1].isLastInTagHistory());
  }
  ASSERT(flattenedSize == arrayIndex);
  list.m_selectorArray[arrayIndex - 1].setLastInSelectorList();
  selectorVector.clear();

  return list;
}
Exemple #8
0
void CSSSelectorParser::rewriteSpecifiersWithElementNameForCustomPseudoElement(const QualifiedName& tag, const AtomicString& elementName, CSSParserSelector* specifiers, bool tagIsForNamespaceRule)
{
    CSSParserSelector* lastShadowPseudo = specifiers;
    CSSParserSelector* history = specifiers;
    while (history->tagHistory()) {
        history = history->tagHistory();
        if (history->crossesTreeScopes() || history->hasShadowPseudo())
            lastShadowPseudo = history;
    }

    if (lastShadowPseudo->tagHistory()) {
        if (tag != anyQName())
            lastShadowPseudo->tagHistory()->prependTagSelector(tag, tagIsForNamespaceRule);
        return;
    }

    // For shadow-ID pseudo-elements to be correctly matched, the ShadowPseudo combinator has to be used.
    // We therefore create a new Selector with that combinator here in any case, even if matching any (host) element in any namespace (i.e. '*').
    OwnPtr<CSSParserSelector> elementNameSelector = adoptPtr(new CSSParserSelector(tag));
    lastShadowPseudo->setTagHistory(elementNameSelector.release());
    lastShadowPseudo->setRelation(CSSSelector::ShadowPseudo);
}
Exemple #9
0
void CSSSelectorList::adoptSelectorVector(Vector<OwnPtr<CSSParserSelector> >& selectorVector)
{
    deleteSelectors();
    const size_t vectorSize = selectorVector.size();
    size_t flattenedSize = 0;
    for (size_t i = 0; i < vectorSize; ++i) {        
        for (CSSParserSelector* selector = selectorVector[i].get(); selector; selector = selector->tagHistory())
            ++flattenedSize;
    }
    ASSERT(flattenedSize);
    if (flattenedSize == 1) {
        m_selectorArray = selectorVector[0]->releaseSelector().leakPtr();
        m_selectorArray->setLastInSelectorList();
        ASSERT(m_selectorArray->isLastInTagHistory());
        selectorVector.shrink(0);
        return;
    }
    m_selectorArray = reinterpret_cast<CSSSelector*>(fastMalloc(sizeof(CSSSelector) * flattenedSize));
    size_t arrayIndex = 0;
    for (size_t i = 0; i < vectorSize; ++i) {
        CSSParserSelector* current = selectorVector[i].get();
        while (current) {
            OwnPtr<CSSSelector> selector = current->releaseSelector();
            current = current->tagHistory();
            move(selector.release(), &m_selectorArray[arrayIndex]);
            ASSERT(!m_selectorArray[arrayIndex].isLastInSelectorList());
            if (current)
                m_selectorArray[arrayIndex].setNotLastInTagHistory();
            ++arrayIndex;
        }
        ASSERT(m_selectorArray[arrayIndex - 1].isLastInTagHistory());
    }
    ASSERT(flattenedSize == arrayIndex);
    m_selectorArray[arrayIndex - 1].setLastInSelectorList();
    selectorVector.shrink(0);
}
Exemple #10
0
std::unique_ptr<CSSParserSelector> CSSSelectorParser::consumeComplexSelector(
    CSSParserTokenRange& range) {
  std::unique_ptr<CSSParserSelector> selector = consumeCompoundSelector(range);
  if (!selector)
    return nullptr;

  unsigned previousCompoundFlags = 0;

  for (CSSParserSelector* simple = selector.get();
       simple && !previousCompoundFlags; simple = simple->tagHistory())
    previousCompoundFlags |= extractCompoundFlags(*simple, m_context.mode());

  while (CSSSelector::RelationType combinator = consumeCombinator(range)) {
    std::unique_ptr<CSSParserSelector> nextSelector =
        consumeCompoundSelector(range);
    if (!nextSelector)
      return combinator == CSSSelector::Descendant ? std::move(selector)
                                                   : nullptr;
    if (previousCompoundFlags & HasPseudoElementForRightmostCompound)
      return nullptr;
    CSSParserSelector* end = nextSelector.get();
    unsigned compoundFlags = extractCompoundFlags(*end, m_context.mode());
    while (end->tagHistory()) {
      end = end->tagHistory();
      compoundFlags |= extractCompoundFlags(*end, m_context.mode());
    }
    end->setRelation(combinator);
    if (previousCompoundFlags & HasContentPseudoElement)
      end->setRelationIsAffectedByPseudoContent();
    previousCompoundFlags = compoundFlags;
    end->setTagHistory(std::move(selector));

    selector = std::move(nextSelector);
  }

  return selector;
}
Exemple #11
0
std::unique_ptr<CSSParserSelector>
CSSSelectorParser::splitCompoundAtImplicitShadowCrossingCombinator(
    std::unique_ptr<CSSParserSelector> compoundSelector) {
  // The tagHistory is a linked list that stores combinator separated compound
  // selectors from right-to-left. Yet, within a single compound selector,
  // stores the simple selectors from left-to-right.
  //
  // ".a.b > div#id" is stored in a tagHistory as [div, #id, .a, .b], each
  // element in the list stored with an associated relation (combinator or
  // SubSelector).
  //
  // ::cue, ::shadow, and custom pseudo elements have an implicit ShadowPseudo
  // combinator to their left, which really makes for a new compound selector,
  // yet it's consumed by the selector parser as a single compound selector.
  //
  // Example:
  //
  // input#x::-webkit-clear-button -> [ ::-webkit-clear-button, input, #x ]
  //
  // Likewise, ::slotted() pseudo element has an implicit ShadowSlot combinator
  // to its left for finding matching slot element in other TreeScope.
  //
  // Example:
  //
  // slot[name=foo]::slotted(div) -> [ ::slotted(div), slot, [name=foo] ]
  CSSParserSelector* splitAfter = compoundSelector.get();

  while (splitAfter->tagHistory() &&
         !splitAfter->tagHistory()->needsImplicitShadowCombinatorForMatching())
    splitAfter = splitAfter->tagHistory();

  if (!splitAfter || !splitAfter->tagHistory())
    return compoundSelector;

  std::unique_ptr<CSSParserSelector> secondCompound =
      splitAfter->releaseTagHistory();
  secondCompound->appendTagHistory(
      secondCompound->pseudoType() == CSSSelector::PseudoSlotted
          ? CSSSelector::ShadowSlot
          : CSSSelector::ShadowPseudo,
      std::move(compoundSelector));
  return secondCompound;
}
Exemple #12
0
PassOwnPtr<CSSParserSelector> CSSSelectorParser::consumeComplexSelector(CSSParserTokenRange& range)
{
    OwnPtr<CSSParserSelector> selector = consumeCompoundSelector(range);
    if (!selector)
        return nullptr;
    while (CSSSelector::Relation combinator = consumeCombinator(range)) {
        OwnPtr<CSSParserSelector> nextSelector = consumeCompoundSelector(range);
        if (!nextSelector)
            return combinator == CSSSelector::Descendant ? selector.release() : nullptr;
        CSSParserSelector* end = nextSelector.get();
        while (end->tagHistory())
            end = end->tagHistory();
        end->setRelation(combinator);
        if (selector->isContentPseudoElement())
            end->setRelationIsAffectedByPseudoContent();
        end->setTagHistory(selector.release());

        selector = nextSelector.release();
    }

    return selector.release();
}