Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "core/css/parser/CSSSelectorParser.h" | 5 #include "core/css/parser/CSSSelectorParser.h" |
| 6 | 6 |
| 7 #include "core/css/CSSSelectorList.h" | 7 #include "core/css/CSSSelectorList.h" |
| 8 #include "core/css/StyleSheetContents.h" | 8 #include "core/css/StyleSheetContents.h" |
| 9 #include "core/frame/UseCounter.h" | 9 #include "core/frame/UseCounter.h" |
| 10 #include "platform/RuntimeEnabledFeatures.h" | 10 #include "platform/RuntimeEnabledFeatures.h" |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 123 return CSSSelectorList(); | 123 return CSSSelectorList(); |
| 124 selectorList.append(selector.release()); | 124 selectorList.append(selector.release()); |
| 125 } | 125 } |
| 126 | 126 |
| 127 if (m_failedParsing) | 127 if (m_failedParsing) |
| 128 return CSSSelectorList(); | 128 return CSSSelectorList(); |
| 129 | 129 |
| 130 return CSSSelectorList::adoptSelectorVector(selectorList); | 130 return CSSSelectorList::adoptSelectorVector(selectorList); |
| 131 } | 131 } |
| 132 | 132 |
| 133 namespace { | |
| 134 | |
| 135 enum CompoundSelectorFlags { | |
| 136 HasPseudoElementForRightmostCompound = 1 << 1, | |
|
Timothy Loh
2016/01/19 04:59:27
Shouldn't we start counting from 1 << 0?
rune
2016/01/19 08:41:51
Done.
| |
| 137 HasContentPseudoElement = 1 << 2 | |
| 138 }; | |
| 139 | |
| 140 unsigned extractCompoundFlags(const CSSParserSelector& simpleSelector, CSSParser Mode parserMode) | |
| 141 { | |
| 142 if (simpleSelector.match() != CSSSelector::PseudoElement) | |
| 143 return 0; | |
| 144 if (simpleSelector.pseudoType() == CSSSelector::PseudoContent) | |
| 145 return HasContentPseudoElement; | |
| 146 if (simpleSelector.pseudoType() == CSSSelector::PseudoShadow) | |
| 147 return 0; | |
| 148 // TODO(rune@opera.com): crbug.com/578131 | |
| 149 // The UASheetMode check is a work-around to allow this selector in mediaCon trols(New).css: | |
| 150 // input[type="range" i]::-webkit-media-slider-container > div { | |
| 151 if (parserMode == UASheetMode && simpleSelector.pseudoType() == CSSSelector: :PseudoWebKitCustomElement) | |
| 152 return 0; | |
| 153 return HasPseudoElementForRightmostCompound; | |
| 154 } | |
| 155 | |
| 156 } // namespace | |
| 157 | |
| 133 PassOwnPtr<CSSParserSelector> CSSSelectorParser::consumeComplexSelector(CSSParse rTokenRange& range) | 158 PassOwnPtr<CSSParserSelector> CSSSelectorParser::consumeComplexSelector(CSSParse rTokenRange& range) |
| 134 { | 159 { |
| 135 OwnPtr<CSSParserSelector> selector = consumeCompoundSelector(range); | 160 OwnPtr<CSSParserSelector> selector = consumeCompoundSelector(range); |
| 136 if (!selector) | 161 if (!selector) |
| 137 return nullptr; | 162 return nullptr; |
| 138 | 163 |
| 139 bool previousCompoundHasContentPseudo = false; | |
| 140 | 164 |
| 141 for (CSSParserSelector* simple = selector.get(); simple && !previousCompound HasContentPseudo; simple = simple->tagHistory()) | 165 unsigned previousCompoundFlags = 0; |
| 142 previousCompoundHasContentPseudo = simple->pseudoType() == CSSSelector:: PseudoContent; | 166 |
| 167 for (CSSParserSelector* simple = selector.get(); simple && !previousCompound Flags; simple = simple->tagHistory()) | |
| 168 previousCompoundFlags |= extractCompoundFlags(*simple, m_context.mode()) ; | |
| 143 | 169 |
| 144 while (CSSSelector::Relation combinator = consumeCombinator(range)) { | 170 while (CSSSelector::Relation combinator = consumeCombinator(range)) { |
| 145 OwnPtr<CSSParserSelector> nextSelector = consumeCompoundSelector(range); | 171 OwnPtr<CSSParserSelector> nextSelector = consumeCompoundSelector(range); |
| 146 if (!nextSelector) | 172 if (!nextSelector) |
| 147 return combinator == CSSSelector::Descendant ? selector.release() : nullptr; | 173 return combinator == CSSSelector::Descendant ? selector.release() : nullptr; |
| 174 if (previousCompoundFlags & HasPseudoElementForRightmostCompound) | |
| 175 return nullptr; | |
| 148 CSSParserSelector* end = nextSelector.get(); | 176 CSSParserSelector* end = nextSelector.get(); |
| 149 bool compoundHasContentPseudo = end->pseudoType() == CSSSelector::Pseudo Content; | 177 unsigned compoundFlags = extractCompoundFlags(*end, m_context.mode()); |
| 150 while (end->tagHistory()) { | 178 while (end->tagHistory()) { |
| 151 end = end->tagHistory(); | 179 end = end->tagHistory(); |
| 152 compoundHasContentPseudo |= end->pseudoType() == CSSSelector::Pseudo Content; | 180 compoundFlags |= extractCompoundFlags(*end, m_context.mode()); |
| 153 } | 181 } |
| 154 end->setRelation(combinator); | 182 end->setRelation(combinator); |
| 155 if (previousCompoundHasContentPseudo) | 183 if (previousCompoundFlags & HasContentPseudoElement) |
| 156 end->setRelationIsAffectedByPseudoContent(); | 184 end->setRelationIsAffectedByPseudoContent(); |
| 157 previousCompoundHasContentPseudo = compoundHasContentPseudo; | 185 previousCompoundFlags = compoundFlags; |
| 158 end->setTagHistory(selector.release()); | 186 end->setTagHistory(selector.release()); |
| 159 | 187 |
| 160 selector = nextSelector.release(); | 188 selector = nextSelector.release(); |
| 161 } | 189 } |
| 162 | 190 |
| 163 return selector.release(); | 191 return selector.release(); |
| 164 } | 192 } |
| 165 | 193 |
| 166 namespace { | 194 namespace { |
| 167 | 195 |
| (...skipping 547 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 715 | 743 |
| 716 if (!splitAfter || !splitAfter->tagHistory()) | 744 if (!splitAfter || !splitAfter->tagHistory()) |
| 717 return compoundSelector; | 745 return compoundSelector; |
| 718 | 746 |
| 719 OwnPtr<CSSParserSelector> secondCompound = splitAfter->releaseTagHistory(); | 747 OwnPtr<CSSParserSelector> secondCompound = splitAfter->releaseTagHistory(); |
| 720 secondCompound->appendTagHistory(CSSSelector::ShadowPseudo, compoundSelector ); | 748 secondCompound->appendTagHistory(CSSSelector::ShadowPseudo, compoundSelector ); |
| 721 return secondCompound.release(); | 749 return secondCompound.release(); |
| 722 } | 750 } |
| 723 | 751 |
| 724 } // namespace blink | 752 } // namespace blink |
| OLD | NEW |