diff options
Diffstat (limited to 'Source/WebCore/css/CSSParserValues.cpp')
-rw-r--r-- | Source/WebCore/css/CSSParserValues.cpp | 258 |
1 files changed, 211 insertions, 47 deletions
diff --git a/Source/WebCore/css/CSSParserValues.cpp b/Source/WebCore/css/CSSParserValues.cpp index 7d5fc853d..db7540e8a 100644 --- a/Source/WebCore/css/CSSParserValues.cpp +++ b/Source/WebCore/css/CSSParserValues.cpp @@ -1,6 +1,6 @@ /* * Copyright (C) 2003 Lars Knoll (knoll@kde.org) - * Copyright (C) 2004, 2005, 2006, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2004, 2005, 2006, 2008, 2014 Apple Inc. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -21,25 +21,33 @@ #include "config.h" #include "CSSParserValues.h" +#include "CSSCustomPropertyValue.h" #include "CSSPrimitiveValue.h" #include "CSSFunctionValue.h" #include "CSSSelector.h" #include "CSSSelectorList.h" -#if ENABLE(CSS_VARIABLES) #include "CSSVariableValue.h" -#endif +#include "SelectorPseudoTypeMap.h" +#include <wtf/text/StringBuilder.h> namespace WebCore { using namespace WTF; +void destroy(const CSSParserValue& value) +{ + if (value.unit == CSSParserValue::Function) + delete value.function; + else if (value.unit == CSSParserValue::ValueList) + delete value.valueList; + else if (value.unit == CSSParserValue::Variable) + delete value.variable; +} + CSSParserValueList::~CSSParserValueList() { - size_t numValues = m_values.size(); - for (size_t i = 0; i < numValues; i++) { - if (m_values[i].unit == CSSParserValue::Function) - delete m_values[i].function; - } + for (size_t i = 0, size = m_values.size(); i < size; i++) + destroy(m_values[i]); } void CSSParserValueList::addValue(const CSSParserValue& v) @@ -63,6 +71,21 @@ void CSSParserValueList::extend(CSSParserValueList& valueList) m_values.append(*(valueList.valueAt(i))); } +bool CSSParserValueList::containsVariables() const +{ + for (unsigned i = 0; i < size(); i++) { + auto* parserValue = &m_values[i]; + if (parserValue->unit == CSSParserValue::Variable) + return true; + if (parserValue->unit == CSSParserValue::Function && parserValue->function->args + && parserValue->function->args->containsVariables()) + return true; + if (parserValue->unit == CSSParserValue::ValueList && parserValue->valueList->containsVariables()) + return true; + } + return false; +} + PassRefPtr<CSSValue> CSSParserValue::createCSSValue() { RefPtr<CSSValue> parsedValue; @@ -76,6 +99,11 @@ PassRefPtr<CSSValue> CSSParserValue::createCSSValue() } if (unit == CSSParserValue::Function) return CSSFunctionValue::create(function); + if (unit == CSSParserValue::Variable) + return CSSVariableValue::create(variable); + if (unit == CSSParserValue::ValueList) + return CSSValueList::createFromParserValueList(*valueList); + if (unit >= CSSParserValue::Q_EMS) return CSSPrimitiveValue::createAllowingMarginQuirk(fValue, CSSPrimitiveValue::CSS_EMS); @@ -89,10 +117,10 @@ PassRefPtr<CSSValue> CSSParserValue::createCSSValue() return CSSPrimitiveValue::create(fValue, isInt ? CSSPrimitiveValue::CSS_PARSER_INTEGER : CSSPrimitiveValue::CSS_NUMBER); case CSSPrimitiveValue::CSS_STRING: case CSSPrimitiveValue::CSS_URI: -#if ENABLE(CSS_VARIABLES) - case CSSPrimitiveValue::CSS_VARIABLE_NAME: -#endif case CSSPrimitiveValue::CSS_PARSER_HEXCOLOR: + case CSSPrimitiveValue::CSS_DIMENSION: + case CSSPrimitiveValue::CSS_UNICODE_RANGE: + case CSSPrimitiveValue::CSS_PARSER_WHITESPACE: return CSSPrimitiveValue::create(string, primitiveUnit); case CSSPrimitiveValue::CSS_PERCENTAGE: case CSSPrimitiveValue::CSS_EMS: @@ -117,9 +145,9 @@ PassRefPtr<CSSValue> CSSParserValue::createCSSValue() case CSSPrimitiveValue::CSS_TURN: case CSSPrimitiveValue::CSS_REMS: case CSSPrimitiveValue::CSS_CHS: + case CSSPrimitiveValue::CSS_FR: return CSSPrimitiveValue::create(fValue, primitiveUnit); case CSSPrimitiveValue::CSS_UNKNOWN: - case CSSPrimitiveValue::CSS_DIMENSION: case CSSPrimitiveValue::CSS_ATTR: case CSSPrimitiveValue::CSS_COUNTER: case CSSPrimitiveValue::CSS_RECT: @@ -131,13 +159,16 @@ PassRefPtr<CSSValue> CSSParserValue::createCSSValue() #if ENABLE(DASHBOARD_SUPPORT) case CSSPrimitiveValue::CSS_DASHBOARD_REGION: #endif - case CSSPrimitiveValue::CSS_UNICODE_RANGE: case CSSPrimitiveValue::CSS_PARSER_OPERATOR: case CSSPrimitiveValue::CSS_PARSER_INTEGER: case CSSPrimitiveValue::CSS_PARSER_IDENTIFIER: case CSSPrimitiveValue::CSS_COUNTER_NAME: case CSSPrimitiveValue::CSS_SHAPE: + case CSSPrimitiveValue::CSS_FONT_FAMILY: case CSSPrimitiveValue::CSS_QUAD: +#if ENABLE(CSS_SCROLL_SNAP) + case CSSPrimitiveValue::CSS_LENGTH_REPEAT: +#endif case CSSPrimitiveValue::CSS_CALC: case CSSPrimitiveValue::CSS_CALC_PERCENTAGE_WITH_NUMBER: case CSSPrimitiveValue::CSS_CALC_PERCENTAGE_WITH_LENGTH: @@ -148,13 +179,88 @@ PassRefPtr<CSSValue> CSSParserValue::createCSSValue() return 0; } +CSSParserSelector* CSSParserSelector::parsePagePseudoSelector(const CSSParserString& pseudoTypeString) +{ + CSSSelector::PagePseudoClassType pseudoType; + if (equalLettersIgnoringASCIICase(pseudoTypeString, "first")) + pseudoType = CSSSelector::PagePseudoClassFirst; + else if (equalLettersIgnoringASCIICase(pseudoTypeString, "left")) + pseudoType = CSSSelector::PagePseudoClassLeft; + else if (equalLettersIgnoringASCIICase(pseudoTypeString, "right")) + pseudoType = CSSSelector::PagePseudoClassRight; + else + return nullptr; + + auto selector = std::make_unique<CSSParserSelector>(); + selector->m_selector->setMatch(CSSSelector::PagePseudoClass); + selector->m_selector->setPagePseudoType(pseudoType); + return selector.release(); +} + +CSSParserSelector* CSSParserSelector::parsePseudoElementSelector(CSSParserString& pseudoTypeString) +{ + pseudoTypeString.convertToASCIILowercaseInPlace(); + AtomicString name = pseudoTypeString; + + CSSSelector::PseudoElementType pseudoType = CSSSelector::parsePseudoElementType(name); + if (pseudoType == CSSSelector::PseudoElementUnknown) + return nullptr; + + auto selector = std::make_unique<CSSParserSelector>(); + selector->m_selector->setMatch(CSSSelector::PseudoElement); + selector->m_selector->setPseudoElementType(pseudoType); + selector->m_selector->setValue(name); + return selector.release(); +} + +#if ENABLE(VIDEO_TRACK) +CSSParserSelector* CSSParserSelector::parsePseudoElementCueFunctionSelector(const CSSParserString& functionIdentifier, Vector<std::unique_ptr<CSSParserSelector>>* parsedSelectorVector) +{ + ASSERT_UNUSED(functionIdentifier, String(functionIdentifier) == "cue("); + + std::unique_ptr<Vector<std::unique_ptr<CSSParserSelector>>> selectorVector(parsedSelectorVector); + + if (!selectorVector) + return nullptr; + + auto selector = std::make_unique<CSSParserSelector>(); + selector->m_selector->setMatch(CSSSelector::PseudoElement); + selector->m_selector->setPseudoElementType(CSSSelector::PseudoElementCue); + selector->adoptSelectorVector(*selectorVector); + return selector.release(); +} +#endif + +CSSParserSelector* CSSParserSelector::parsePseudoClassAndCompatibilityElementSelector(CSSParserString& pseudoTypeString) +{ + if (pseudoTypeString.length() && pseudoTypeString[pseudoTypeString.length() - 1] == '(') + return nullptr; + + PseudoClassOrCompatibilityPseudoElement pseudoType = parsePseudoClassAndCompatibilityElementString(pseudoTypeString); + if (pseudoType.pseudoClass != CSSSelector::PseudoClassUnknown) { + auto selector = std::make_unique<CSSParserSelector>(); + selector->m_selector->setMatch(CSSSelector::PseudoClass); + selector->m_selector->setPseudoClassType(pseudoType.pseudoClass); + return selector.release(); + } + if (pseudoType.compatibilityPseudoElement != CSSSelector::PseudoElementUnknown) { + auto selector = std::make_unique<CSSParserSelector>(); + selector->m_selector->setMatch(CSSSelector::PseudoElement); + selector->m_selector->setPseudoElementType(pseudoType.compatibilityPseudoElement); + AtomicString name = pseudoTypeString; + selector->m_selector->setValue(name); + return selector.release(); + } + return nullptr; +} + CSSParserSelector::CSSParserSelector() - : m_selector(adoptPtr(fastNew<CSSSelector>())) + : m_selector(std::make_unique<CSSSelector>()) { } CSSParserSelector::CSSParserSelector(const QualifiedName& tagQName) - : m_selector(adoptPtr(new CSSSelector(tagQName))) + : m_selector(std::make_unique<CSSSelector>(tagQName)) { } @@ -162,71 +268,129 @@ CSSParserSelector::~CSSParserSelector() { if (!m_tagHistory) return; - Vector<OwnPtr<CSSParserSelector>, 16> toDelete; - OwnPtr<CSSParserSelector> selector = m_tagHistory.release(); + Vector<std::unique_ptr<CSSParserSelector>, 16> toDelete; + std::unique_ptr<CSSParserSelector> selector = WTFMove(m_tagHistory); while (true) { - OwnPtr<CSSParserSelector> next = selector->m_tagHistory.release(); - toDelete.append(selector.release()); + std::unique_ptr<CSSParserSelector> next = WTFMove(selector->m_tagHistory); + toDelete.append(WTFMove(selector)); if (!next) break; - selector = next.release(); + selector = WTFMove(next); } } -void CSSParserSelector::adoptSelectorVector(Vector<OwnPtr<CSSParserSelector> >& selectorVector) +void CSSParserSelector::adoptSelectorVector(Vector<std::unique_ptr<CSSParserSelector>>& selectorVector) { - CSSSelectorList* selectorList = fastNew<CSSSelectorList>(); + auto selectorList = std::make_unique<CSSSelectorList>(); selectorList->adoptSelectorVector(selectorVector); - m_selector->setSelectorList(adoptPtr(selectorList)); + m_selector->setSelectorList(WTFMove(selectorList)); +} + +void CSSParserSelector::setLangArgumentList(const Vector<CSSParserString>& stringVector) +{ + ASSERT_WITH_MESSAGE(!stringVector.isEmpty(), "No CSS Selector takes an empty argument list."); + auto argumentList = std::make_unique<Vector<AtomicString>>(); + argumentList->reserveInitialCapacity(stringVector.size()); + for (const AtomicString& languageArgument : stringVector) + argumentList->append(languageArgument); + m_selector->setLangArgumentList(WTFMove(argumentList)); +} + +void CSSParserSelector::setPseudoClassValue(const CSSParserString& pseudoClassString) +{ + ASSERT(m_selector->match() == CSSSelector::PseudoClass); + + PseudoClassOrCompatibilityPseudoElement pseudoType = parsePseudoClassAndCompatibilityElementString(pseudoClassString); + m_selector->setPseudoClassType(pseudoType.pseudoClass); } -bool CSSParserSelector::isSimple() const +static bool selectorListMatchesPseudoElement(const CSSSelectorList* selectorList) { - if (m_selector->selectorList() || m_selector->matchesPseudoElement()) + if (!selectorList) return false; - if (!m_tagHistory) - return true; - - if (m_selector->m_match == CSSSelector::Tag) { - // We can't check against anyQName() here because namespace may not be nullAtom. - // Example: - // @namespace "http://www.w3.org/2000/svg"; - // svg:not(:root) { ... - if (m_selector->tagQName().localName() == starAtom) - return m_tagHistory->isSimple(); + for (const CSSSelector* subSelector = selectorList->first(); subSelector; subSelector = CSSSelectorList::next(subSelector)) { + for (const CSSSelector* selector = subSelector; selector; selector = selector->tagHistory()) { + if (selector->matchesPseudoElement()) + return true; + if (const CSSSelectorList* subselectorList = selector->selectorList()) { + if (selectorListMatchesPseudoElement(subselectorList)) + return true; + } + } } - return false; } -void CSSParserSelector::insertTagHistory(CSSSelector::Relation before, PassOwnPtr<CSSParserSelector> selector, CSSSelector::Relation after) +bool CSSParserSelector::matchesPseudoElement() const +{ + return m_selector->matchesPseudoElement() || selectorListMatchesPseudoElement(m_selector->selectorList()); +} + +void CSSParserSelector::insertTagHistory(CSSSelector::Relation before, std::unique_ptr<CSSParserSelector> selector, CSSSelector::Relation after) { if (m_tagHistory) - selector->setTagHistory(m_tagHistory.release()); + selector->setTagHistory(WTFMove(m_tagHistory)); setRelation(before); selector->setRelation(after); - m_tagHistory = selector; + m_tagHistory = WTFMove(selector); } -void CSSParserSelector::appendTagHistory(CSSSelector::Relation relation, PassOwnPtr<CSSParserSelector> selector) +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(selector); + end->setTagHistory(WTFMove(selector)); +} + +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)); } void CSSParserSelector::prependTagSelector(const QualifiedName& tagQName, bool tagIsForNamespaceRule) { - OwnPtr<CSSParserSelector> second = adoptPtr(new CSSParserSelector); - second->m_selector = m_selector.release(); - second->m_tagHistory = m_tagHistory.release(); - m_tagHistory = second.release(); + auto second = std::make_unique<CSSParserSelector>(); + second->m_selector = WTFMove(m_selector); + second->m_tagHistory = WTFMove(m_tagHistory); + m_tagHistory = WTFMove(second); - m_selector = adoptPtr(new CSSSelector(tagQName, tagIsForNamespaceRule)); - m_selector->m_relation = CSSSelector::SubSelector; + m_selector = std::make_unique<CSSSelector>(tagQName, tagIsForNamespaceRule); + m_selector->setRelation(CSSSelector::SubSelector); } } |