1/* 2 * Copyright (C) 2003 Lars Knoll (knoll@kde.org) 3 * Copyright (C) 2004, 2005, 2006, 2008 Apple Inc. All rights reserved. 4 * 5 * This library is free software; you can redistribute it and/or 6 * modify it under the terms of the GNU Library General Public 7 * License as published by the Free Software Foundation; either 8 * version 2 of the License, or (at your option) any later version. 9 * 10 * This library is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 * Library General Public License for more details. 14 * 15 * You should have received a copy of the GNU Library General Public License 16 * along with this library; see the file COPYING.LIB. If not, write to 17 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 18 * Boston, MA 02110-1301, USA. 19 */ 20 21#include "config.h" 22#include "CSSParserValues.h" 23 24#include "CSSPrimitiveValue.h" 25#include "CSSFunctionValue.h" 26#include "CSSSelector.h" 27#include "CSSSelectorList.h" 28#include "SelectorPseudoTypeMap.h" 29 30namespace WebCore { 31 32using namespace WTF; 33 34void destroy(const CSSParserValue& value) 35{ 36 if (value.unit == CSSParserValue::Function) 37 delete value.function; 38 else if (value.unit == CSSParserValue::ValueList) 39 delete value.valueList; 40} 41 42CSSParserValueList::~CSSParserValueList() 43{ 44 for (size_t i = 0, size = m_values.size(); i < size; i++) 45 destroy(m_values[i]); 46} 47 48void CSSParserValueList::addValue(const CSSParserValue& v) 49{ 50 m_values.append(v); 51} 52 53void CSSParserValueList::insertValueAt(unsigned i, const CSSParserValue& v) 54{ 55 m_values.insert(i, v); 56} 57 58void CSSParserValueList::deleteValueAt(unsigned i) 59{ 60 m_values.remove(i); 61} 62 63void CSSParserValueList::extend(CSSParserValueList& valueList) 64{ 65 for (unsigned int i = 0; i < valueList.size(); ++i) 66 m_values.append(*(valueList.valueAt(i))); 67} 68 69PassRefPtr<CSSValue> CSSParserValue::createCSSValue() 70{ 71 RefPtr<CSSValue> parsedValue; 72 if (id) 73 return CSSPrimitiveValue::createIdentifier(id); 74 75 if (unit == CSSParserValue::Operator) { 76 RefPtr<CSSPrimitiveValue> primitiveValue = CSSPrimitiveValue::createParserOperator(iValue); 77 primitiveValue->setPrimitiveType(CSSPrimitiveValue::CSS_PARSER_OPERATOR); 78 return primitiveValue.release(); 79 } 80 if (unit == CSSParserValue::Function) 81 return CSSFunctionValue::create(function); 82 if (unit == CSSParserValue::ValueList) 83 return CSSValueList::createFromParserValueList(*valueList); 84 if (unit >= CSSParserValue::Q_EMS) 85 return CSSPrimitiveValue::createAllowingMarginQuirk(fValue, CSSPrimitiveValue::CSS_EMS); 86 87 CSSPrimitiveValue::UnitTypes primitiveUnit = static_cast<CSSPrimitiveValue::UnitTypes>(unit); 88 switch (primitiveUnit) { 89 case CSSPrimitiveValue::CSS_IDENT: 90 case CSSPrimitiveValue::CSS_PROPERTY_ID: 91 case CSSPrimitiveValue::CSS_VALUE_ID: 92 return CSSPrimitiveValue::create(string, CSSPrimitiveValue::CSS_PARSER_IDENTIFIER); 93 case CSSPrimitiveValue::CSS_NUMBER: 94 return CSSPrimitiveValue::create(fValue, isInt ? CSSPrimitiveValue::CSS_PARSER_INTEGER : CSSPrimitiveValue::CSS_NUMBER); 95 case CSSPrimitiveValue::CSS_STRING: 96 case CSSPrimitiveValue::CSS_URI: 97 case CSSPrimitiveValue::CSS_PARSER_HEXCOLOR: 98 return CSSPrimitiveValue::create(string, primitiveUnit); 99 case CSSPrimitiveValue::CSS_PERCENTAGE: 100 case CSSPrimitiveValue::CSS_EMS: 101 case CSSPrimitiveValue::CSS_EXS: 102 case CSSPrimitiveValue::CSS_PX: 103 case CSSPrimitiveValue::CSS_CM: 104 case CSSPrimitiveValue::CSS_MM: 105 case CSSPrimitiveValue::CSS_IN: 106 case CSSPrimitiveValue::CSS_PT: 107 case CSSPrimitiveValue::CSS_PC: 108 case CSSPrimitiveValue::CSS_DEG: 109 case CSSPrimitiveValue::CSS_RAD: 110 case CSSPrimitiveValue::CSS_GRAD: 111 case CSSPrimitiveValue::CSS_MS: 112 case CSSPrimitiveValue::CSS_S: 113 case CSSPrimitiveValue::CSS_HZ: 114 case CSSPrimitiveValue::CSS_KHZ: 115 case CSSPrimitiveValue::CSS_VW: 116 case CSSPrimitiveValue::CSS_VH: 117 case CSSPrimitiveValue::CSS_VMIN: 118 case CSSPrimitiveValue::CSS_VMAX: 119 case CSSPrimitiveValue::CSS_TURN: 120 case CSSPrimitiveValue::CSS_REMS: 121 case CSSPrimitiveValue::CSS_CHS: 122 case CSSPrimitiveValue::CSS_FR: 123 return CSSPrimitiveValue::create(fValue, primitiveUnit); 124 case CSSPrimitiveValue::CSS_UNKNOWN: 125 case CSSPrimitiveValue::CSS_DIMENSION: 126 case CSSPrimitiveValue::CSS_ATTR: 127 case CSSPrimitiveValue::CSS_COUNTER: 128 case CSSPrimitiveValue::CSS_RECT: 129 case CSSPrimitiveValue::CSS_RGBCOLOR: 130 case CSSPrimitiveValue::CSS_DPPX: 131 case CSSPrimitiveValue::CSS_DPI: 132 case CSSPrimitiveValue::CSS_DPCM: 133 case CSSPrimitiveValue::CSS_PAIR: 134#if ENABLE(DASHBOARD_SUPPORT) 135 case CSSPrimitiveValue::CSS_DASHBOARD_REGION: 136#endif 137 case CSSPrimitiveValue::CSS_UNICODE_RANGE: 138 case CSSPrimitiveValue::CSS_PARSER_OPERATOR: 139 case CSSPrimitiveValue::CSS_PARSER_INTEGER: 140 case CSSPrimitiveValue::CSS_PARSER_IDENTIFIER: 141 case CSSPrimitiveValue::CSS_COUNTER_NAME: 142 case CSSPrimitiveValue::CSS_SHAPE: 143 case CSSPrimitiveValue::CSS_QUAD: 144 case CSSPrimitiveValue::CSS_CALC: 145 case CSSPrimitiveValue::CSS_CALC_PERCENTAGE_WITH_NUMBER: 146 case CSSPrimitiveValue::CSS_CALC_PERCENTAGE_WITH_LENGTH: 147 return 0; 148 } 149 150 ASSERT_NOT_REACHED(); 151 return 0; 152} 153 154CSSParserSelector* CSSParserSelector::parsePagePseudoSelector(const CSSParserString& pseudoTypeString) 155{ 156 CSSSelector::PagePseudoClassType pseudoType; 157 if (pseudoTypeString.equalIgnoringCase("first")) 158 pseudoType = CSSSelector::PagePseudoClassFirst; 159 else if (pseudoTypeString.equalIgnoringCase("left")) 160 pseudoType = CSSSelector::PagePseudoClassLeft; 161 else if (pseudoTypeString.equalIgnoringCase("right")) 162 pseudoType = CSSSelector::PagePseudoClassRight; 163 else 164 return nullptr; 165 166 auto selector = std::make_unique<CSSParserSelector>(); 167 selector->m_selector->m_match = CSSSelector::PagePseudoClass; 168 selector->m_selector->setPagePseudoType(pseudoType); 169 return selector.release(); 170} 171 172CSSParserSelector* CSSParserSelector::parsePseudoElementSelector(CSSParserString& pseudoTypeString) 173{ 174 pseudoTypeString.lower(); 175 AtomicString name = pseudoTypeString; 176 177 CSSSelector::PseudoElementType pseudoType = CSSSelector::parsePseudoElementType(name); 178 if (pseudoType == CSSSelector::PseudoElementUnknown) 179 return nullptr; 180 181 auto selector = std::make_unique<CSSParserSelector>(); 182 selector->m_selector->m_match = CSSSelector::PseudoElement; 183 selector->m_selector->setPseudoElementType(pseudoType); 184 selector->m_selector->setValue(name); 185 return selector.release(); 186} 187 188#if ENABLE(VIDEO_TRACK) 189CSSParserSelector* CSSParserSelector::parsePseudoElementCueFunctionSelector(const CSSParserString& functionIdentifier, Vector<std::unique_ptr<CSSParserSelector>>* parsedSelectorVector) 190{ 191 ASSERT_UNUSED(functionIdentifier, String(functionIdentifier) == "cue("); 192 193 std::unique_ptr<Vector<std::unique_ptr<CSSParserSelector>>> selectorVector(parsedSelectorVector); 194 195 if (!selectorVector) 196 return nullptr; 197 198 auto selector = std::make_unique<CSSParserSelector>(); 199 selector->m_selector->m_match = CSSSelector::PseudoElement; 200 selector->m_selector->setPseudoElementType(CSSSelector::PseudoElementCue); 201 selector->adoptSelectorVector(*selectorVector); 202 return selector.release(); 203} 204#endif 205 206CSSParserSelector* CSSParserSelector::parsePseudoClassAndCompatibilityElementSelector(CSSParserString& pseudoTypeString) 207{ 208 PseudoClassOrCompatibilityPseudoElement pseudoType = parsePseudoClassAndCompatibilityElementString(pseudoTypeString); 209 if (pseudoType.pseudoClass != CSSSelector::PseudoClassUnknown) { 210 auto selector = std::make_unique<CSSParserSelector>(); 211 selector->m_selector->m_match = CSSSelector::PseudoClass; 212 selector->m_selector->m_pseudoType = pseudoType.pseudoClass; 213 return selector.release(); 214 } 215 if (pseudoType.compatibilityPseudoElement != CSSSelector::PseudoElementUnknown) { 216 auto selector = std::make_unique<CSSParserSelector>(); 217 selector->m_selector->m_match = CSSSelector::PseudoElement; 218 selector->m_selector->setPseudoElementType(pseudoType.compatibilityPseudoElement); 219 AtomicString name = pseudoTypeString; 220 selector->m_selector->setValue(name); 221 return selector.release(); 222 } 223 return nullptr; 224} 225 226CSSParserSelector::CSSParserSelector() 227 : m_selector(std::make_unique<CSSSelector>()) 228{ 229} 230 231CSSParserSelector::CSSParserSelector(const QualifiedName& tagQName) 232 : m_selector(std::make_unique<CSSSelector>(tagQName)) 233{ 234} 235 236CSSParserSelector::~CSSParserSelector() 237{ 238 if (!m_tagHistory) 239 return; 240 Vector<std::unique_ptr<CSSParserSelector>, 16> toDelete; 241 std::unique_ptr<CSSParserSelector> selector = WTF::move(m_tagHistory); 242 while (true) { 243 std::unique_ptr<CSSParserSelector> next = WTF::move(selector->m_tagHistory); 244 toDelete.append(WTF::move(selector)); 245 if (!next) 246 break; 247 selector = WTF::move(next); 248 } 249} 250 251void CSSParserSelector::adoptSelectorVector(Vector<std::unique_ptr<CSSParserSelector>>& selectorVector) 252{ 253 auto selectorList = std::make_unique<CSSSelectorList>(); 254 selectorList->adoptSelectorVector(selectorVector); 255 m_selector->setSelectorList(WTF::move(selectorList)); 256} 257 258void CSSParserSelector::setPseudoClassValue(const CSSParserString& pseudoClassString) 259{ 260 ASSERT(m_selector->m_match == CSSSelector::PseudoClass); 261 262 PseudoClassOrCompatibilityPseudoElement pseudoType = parsePseudoClassAndCompatibilityElementString(pseudoClassString); 263 m_selector->m_pseudoType = pseudoType.pseudoClass; 264} 265 266bool CSSParserSelector::isSimple() const 267{ 268 if (m_selector->selectorList() || m_selector->matchesPseudoElement()) 269 return false; 270 271 if (!m_tagHistory) 272 return true; 273 274 if (m_selector->m_match == CSSSelector::Tag) { 275 // We can't check against anyQName() here because namespace may not be nullAtom. 276 // Example: 277 // @namespace "http://www.w3.org/2000/svg"; 278 // svg:not(:root) { ... 279 if (m_selector->tagQName().localName() == starAtom) 280 return m_tagHistory->isSimple(); 281 } 282 283 return false; 284} 285 286void CSSParserSelector::insertTagHistory(CSSSelector::Relation before, std::unique_ptr<CSSParserSelector> selector, CSSSelector::Relation after) 287{ 288 if (m_tagHistory) 289 selector->setTagHistory(WTF::move(m_tagHistory)); 290 setRelation(before); 291 selector->setRelation(after); 292 m_tagHistory = WTF::move(selector); 293} 294 295void CSSParserSelector::appendTagHistory(CSSSelector::Relation relation, std::unique_ptr<CSSParserSelector> selector) 296{ 297 CSSParserSelector* end = this; 298 while (end->tagHistory()) 299 end = end->tagHistory(); 300 end->setRelation(relation); 301 end->setTagHistory(WTF::move(selector)); 302} 303 304void CSSParserSelector::prependTagSelector(const QualifiedName& tagQName, bool tagIsForNamespaceRule) 305{ 306 auto second = std::make_unique<CSSParserSelector>(); 307 second->m_selector = WTF::move(m_selector); 308 second->m_tagHistory = WTF::move(m_tagHistory); 309 m_tagHistory = WTF::move(second); 310 311 m_selector = std::make_unique<CSSSelector>(tagQName, tagIsForNamespaceRule); 312 m_selector->m_relation = CSSSelector::SubSelector; 313} 314 315} 316 317