Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(119)

Side by Side Diff: Source/core/css/parser/CSSParserImpl.cpp

Issue 1018213004: CSS Parser: Mark on stylesheets whether the first rule was valid (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Created 5 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « Source/core/css/parser/CSSParserImpl.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
OLDNEW
« no previous file with comments | « Source/core/css/parser/CSSParserImpl.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698