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 "config.h" | 5 #include "config.h" |
6 #include "core/css/parser/CSSParserImpl.h" | 6 #include "core/css/parser/CSSParserImpl.h" |
7 | 7 |
8 #include "core/css/CSSKeyframesRule.h" | 8 #include "core/css/CSSKeyframesRule.h" |
9 #include "core/css/CSSStyleSheet.h" | 9 #include "core/css/CSSStyleSheet.h" |
10 #include "core/css/StylePropertySet.h" | 10 #include "core/css/StylePropertySet.h" |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
117 range.consumeWhitespace(); | 117 range.consumeWhitespace(); |
118 if (!rule || !range.atEnd()) | 118 if (!rule || !range.atEnd()) |
119 return nullptr; // Parse error, trailing garbage | 119 return nullptr; // Parse error, trailing garbage |
120 return rule; | 120 return rule; |
121 } | 121 } |
122 | 122 |
123 void CSSParserImpl::parseStyleSheet(const String& string, const CSSParserContext
& context, StyleSheetContents* styleSheet) | 123 void CSSParserImpl::parseStyleSheet(const String& string, const CSSParserContext
& context, StyleSheetContents* styleSheet) |
124 { | 124 { |
125 CSSParserImpl parser(context, styleSheet); | 125 CSSParserImpl parser(context, styleSheet); |
126 CSSTokenizer::Scope scope(string); | 126 CSSTokenizer::Scope scope(string); |
127 parser.consumeRuleList(scope.tokenRange(), TopLevelRuleList, [&styleSheet](P
assRefPtrWillBeRawPtr<StyleRuleBase> rule) { | 127 bool firstRuleValid = parser.consumeRuleList(scope.tokenRange(), TopLevelRul
eList, [&styleSheet](PassRefPtrWillBeRawPtr<StyleRuleBase> rule) { |
128 styleSheet->parserAppendRule(rule); | 128 styleSheet->parserAppendRule(rule); |
129 }); | 129 }); |
| 130 styleSheet->setHasSyntacticallyValidCSSHeader(firstRuleValid); |
130 } | 131 } |
131 | 132 |
132 PassOwnPtr<Vector<double>> CSSParserImpl::parseKeyframeKeyList(const String& key
List) | 133 PassOwnPtr<Vector<double>> CSSParserImpl::parseKeyframeKeyList(const String& key
List) |
133 { | 134 { |
134 return consumeKeyframeKeyList(CSSTokenizer::Scope(keyList).tokenRange()); | 135 return consumeKeyframeKeyList(CSSTokenizer::Scope(keyList).tokenRange()); |
135 } | 136 } |
136 | 137 |
137 bool CSSParserImpl::supportsDeclaration(CSSParserTokenRange& range) | 138 bool CSSParserImpl::supportsDeclaration(CSSParserTokenRange& range) |
138 { | 139 { |
139 ASSERT(m_parsedProperties.isEmpty()); | 140 ASSERT(m_parsedProperties.isEmpty()); |
140 consumeDeclaration(range, StyleRule::Style); | 141 consumeDeclaration(range, StyleRule::Style); |
141 bool result = !m_parsedProperties.isEmpty(); | 142 bool result = !m_parsedProperties.isEmpty(); |
142 m_parsedProperties.clear(); | 143 m_parsedProperties.clear(); |
143 return result; | 144 return result; |
144 } | 145 } |
145 | 146 |
146 static CSSParserImpl::AllowedRulesType computeNewAllowedRules(CSSParserImpl::All
owedRulesType allowedRules, StyleRuleBase* rule) | 147 static CSSParserImpl::AllowedRulesType computeNewAllowedRules(CSSParserImpl::All
owedRulesType allowedRules, StyleRuleBase* rule) |
147 { | 148 { |
148 if (!rule || allowedRules == CSSParserImpl::KeyframeRules) | 149 if (!rule || allowedRules == CSSParserImpl::KeyframeRules) |
149 return allowedRules; | 150 return allowedRules; |
150 ASSERT(allowedRules <= CSSParserImpl::RegularRules); | 151 ASSERT(allowedRules <= CSSParserImpl::RegularRules); |
151 if (rule->isImportRule()) | 152 if (rule->isImportRule()) |
152 return CSSParserImpl::AllowImportRules; | 153 return CSSParserImpl::AllowImportRules; |
153 if (rule->isNamespaceRule()) | 154 if (rule->isNamespaceRule()) |
154 return CSSParserImpl::AllowNamespaceRules; | 155 return CSSParserImpl::AllowNamespaceRules; |
155 return CSSParserImpl::RegularRules; | 156 return CSSParserImpl::RegularRules; |
156 } | 157 } |
157 | 158 |
158 template<typename T> | 159 template<typename T> |
159 void CSSParserImpl::consumeRuleList(CSSParserTokenRange range, RuleListType rule
ListType, const T callback) | 160 bool CSSParserImpl::consumeRuleList(CSSParserTokenRange range, RuleListType rule
ListType, const T callback) |
160 { | 161 { |
161 AllowedRulesType allowedRules = RegularRules; | 162 AllowedRulesType allowedRules = RegularRules; |
162 switch (ruleListType) { | 163 switch (ruleListType) { |
163 case TopLevelRuleList: | 164 case TopLevelRuleList: |
164 allowedRules = AllowCharsetRules; | 165 allowedRules = AllowCharsetRules; |
165 break; | 166 break; |
166 case RegularRuleList: | 167 case RegularRuleList: |
167 allowedRules = RegularRules; | 168 allowedRules = RegularRules; |
168 break; | 169 break; |
169 case KeyframesRuleList: | 170 case KeyframesRuleList: |
170 allowedRules = KeyframeRules; | 171 allowedRules = KeyframeRules; |
171 break; | 172 break; |
172 default: | 173 default: |
173 ASSERT_NOT_REACHED(); | 174 ASSERT_NOT_REACHED(); |
174 } | 175 } |
175 | 176 |
| 177 bool seenRule = false; |
| 178 bool firstRuleValid = false; |
176 while (!range.atEnd()) { | 179 while (!range.atEnd()) { |
| 180 RefPtrWillBeRawPtr<StyleRuleBase> rule; |
177 switch (range.peek().type()) { | 181 switch (range.peek().type()) { |
178 case WhitespaceToken: | 182 case WhitespaceToken: |
179 range.consumeWhitespace(); | 183 range.consumeWhitespace(); |
180 break; | 184 continue; |
181 case AtKeywordToken: | 185 case AtKeywordToken: |
182 if (PassRefPtrWillBeRawPtr<StyleRuleBase> rule = consumeAtRule(range
, allowedRules)) { | 186 rule = consumeAtRule(range, allowedRules); |
183 allowedRules = computeNewAllowedRules(allowedRules, rule.get()); | |
184 callback(rule); | |
185 } | |
186 break; | 187 break; |
187 case CDOToken: | 188 case CDOToken: |
188 case CDCToken: | 189 case CDCToken: |
189 if (ruleListType == TopLevelRuleList) { | 190 if (ruleListType == TopLevelRuleList) { |
190 range.consume(); | 191 range.consume(); |
191 break; | 192 continue; |
192 } | 193 } |
193 // fallthrough | 194 // fallthrough |
194 default: | 195 default: |
195 if (PassRefPtrWillBeRawPtr<StyleRuleBase> rule = consumeQualifiedRul
e(range, allowedRules)) { | 196 rule = consumeQualifiedRule(range, allowedRules); |
196 allowedRules = computeNewAllowedRules(allowedRules, rule.get()); | |
197 callback(rule); | |
198 } | |
199 break; | 197 break; |
200 } | 198 } |
| 199 if (!seenRule) { |
| 200 seenRule = true; |
| 201 firstRuleValid = rule; |
| 202 } |
| 203 if (rule) { |
| 204 allowedRules = computeNewAllowedRules(allowedRules, rule.get()); |
| 205 callback(rule.release()); |
| 206 } |
201 } | 207 } |
| 208 |
| 209 return firstRuleValid; |
202 } | 210 } |
203 | 211 |
204 PassRefPtrWillBeRawPtr<StyleRuleBase> CSSParserImpl::consumeAtRule(CSSParserToke
nRange& range, AllowedRulesType allowedRules) | 212 PassRefPtrWillBeRawPtr<StyleRuleBase> CSSParserImpl::consumeAtRule(CSSParserToke
nRange& range, AllowedRulesType allowedRules) |
205 { | 213 { |
206 ASSERT(range.peek().type() == AtKeywordToken); | 214 ASSERT(range.peek().type() == AtKeywordToken); |
207 const CSSParserString& name = range.consume().value(); | 215 const CSSParserString& name = range.consume().value(); |
208 const CSSParserToken* preludeStart = &range.peek(); | 216 const CSSParserToken* preludeStart = &range.peek(); |
209 while (!range.atEnd() && range.peek().type() != LeftBraceToken && range.peek
().type() != SemicolonToken) | 217 while (!range.atEnd() && range.peek().type() != LeftBraceToken && range.peek
().type() != SemicolonToken) |
210 range.consumeComponentValue(); | 218 range.consumeComponentValue(); |
211 | 219 |
212 CSSParserTokenRange prelude = range.makeSubRange(preludeStart, &range.peek()
); | 220 CSSParserTokenRange prelude = range.makeSubRange(preludeStart, &range.peek()
); |
213 | 221 |
214 if (range.atEnd() || range.peek().type() == SemicolonToken) { | 222 if (range.atEnd() || range.peek().type() == SemicolonToken) { |
215 range.consume(); | 223 range.consume(); |
216 if (allowedRules == AllowCharsetRules && name.equalIgnoringCase("charset
")) { | 224 if (allowedRules == AllowCharsetRules && name.equalIgnoringCase("charset
")) |
217 // @charset is actually parsed before we get into the CSS parser. | 225 return consumeCharsetRule(prelude); |
218 // In theory we should validate the prelude is a string, but we don'
t | |
219 // have error logging yet so it doesn't matter. | |
220 return nullptr; | |
221 } | |
222 if (allowedRules <= AllowImportRules && name.equalIgnoringCase("import")
) | 226 if (allowedRules <= AllowImportRules && name.equalIgnoringCase("import")
) |
223 return consumeImportRule(prelude); | 227 return consumeImportRule(prelude); |
224 if (allowedRules <= AllowNamespaceRules && name.equalIgnoringCase("names
pace")) | 228 if (allowedRules <= AllowNamespaceRules && name.equalIgnoringCase("names
pace")) |
225 return consumeNamespaceRule(prelude); | 229 return consumeNamespaceRule(prelude); |
226 return nullptr; // Parse error, unrecognised at-rule without block | 230 return nullptr; // Parse error, unrecognised at-rule without block |
227 } | 231 } |
228 | 232 |
229 CSSParserTokenRange block = range.consumeBlock(); | 233 CSSParserTokenRange block = range.consumeBlock(); |
230 if (allowedRules == KeyframeRules) | 234 if (allowedRules == KeyframeRules) |
231 return nullptr; // Parse error, no at-rules supported inside @keyframes | 235 return nullptr; // Parse error, no at-rules supported inside @keyframes |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
282 return AtomicString(); | 286 return AtomicString(); |
283 | 287 |
284 CSSParserTokenRange contents = range.consumeBlock(); | 288 CSSParserTokenRange contents = range.consumeBlock(); |
285 const CSSParserToken& uri = contents.consumeIncludingWhitespace(); | 289 const CSSParserToken& uri = contents.consumeIncludingWhitespace(); |
286 ASSERT(uri.type() == StringToken); | 290 ASSERT(uri.type() == StringToken); |
287 if (!contents.atEnd()) | 291 if (!contents.atEnd()) |
288 return AtomicString(); | 292 return AtomicString(); |
289 return uri.value(); | 293 return uri.value(); |
290 } | 294 } |
291 | 295 |
| 296 PassRefPtrWillBeRawPtr<StyleRuleCharset> CSSParserImpl::consumeCharsetRule(CSSPa
rserTokenRange prelude) |
| 297 { |
| 298 prelude.consumeWhitespace(); |
| 299 const CSSParserToken& string = prelude.consumeIncludingWhitespace(); |
| 300 if (string.type() != StringToken || !prelude.atEnd()) |
| 301 return nullptr; // Parse error, expected a single string |
| 302 return StyleRuleCharset::create(); |
| 303 } |
| 304 |
292 PassRefPtrWillBeRawPtr<StyleRuleImport> CSSParserImpl::consumeImportRule(CSSPars
erTokenRange prelude) | 305 PassRefPtrWillBeRawPtr<StyleRuleImport> CSSParserImpl::consumeImportRule(CSSPars
erTokenRange prelude) |
293 { | 306 { |
294 prelude.consumeWhitespace(); | 307 prelude.consumeWhitespace(); |
295 AtomicString uri(consumeStringOrURI(prelude)); | 308 AtomicString uri(consumeStringOrURI(prelude)); |
296 if (uri.isNull()) | 309 if (uri.isNull()) |
297 return nullptr; // Parse error, expected string or URI | 310 return nullptr; // Parse error, expected string or URI |
298 return StyleRuleImport::create(uri, MediaQueryParser::parseMediaQuerySet(pre
lude)); | 311 return StyleRuleImport::create(uri, MediaQueryParser::parseMediaQuerySet(pre
lude)); |
299 } | 312 } |
300 | 313 |
301 PassRefPtrWillBeRawPtr<StyleRuleNamespace> CSSParserImpl::consumeNamespaceRule(C
SSParserTokenRange prelude) | 314 PassRefPtrWillBeRawPtr<StyleRuleNamespace> CSSParserImpl::consumeNamespaceRule(C
SSParserTokenRange prelude) |
(...skipping 260 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
562 else | 575 else |
563 return nullptr; // Parser error, invalid value in keyframe selector | 576 return nullptr; // Parser error, invalid value in keyframe selector |
564 if (range.atEnd()) | 577 if (range.atEnd()) |
565 return result.release(); | 578 return result.release(); |
566 if (range.consume().type() != CommaToken) | 579 if (range.consume().type() != CommaToken) |
567 return nullptr; // Parser error | 580 return nullptr; // Parser error |
568 } | 581 } |
569 } | 582 } |
570 | 583 |
571 } // namespace blink | 584 } // namespace blink |
OLD | NEW |