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

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

Issue 2503683003: [WIP] Streaming CSS parser (Closed)
Patch Set: rebase Created 3 years, 11 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
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 "core/css/parser/CSSParserImpl.h" 5 #include "core/css/parser/CSSParserImpl.h"
6 6
7 #include "core/css/CSSCustomIdentValue.h" 7 #include "core/css/CSSCustomIdentValue.h"
8 #include "core/css/CSSCustomPropertyDeclaration.h" 8 #include "core/css/CSSCustomPropertyDeclaration.h"
9 #include "core/css/CSSKeyframesRule.h" 9 #include "core/css/CSSKeyframesRule.h"
10 #include "core/css/CSSStyleSheet.h" 10 #include "core/css/CSSStyleSheet.h"
11 #include "core/css/PropertyRegistry.h" 11 #include "core/css/PropertyRegistry.h"
12 #include "core/css/StyleRuleImport.h" 12 #include "core/css/StyleRuleImport.h"
13 #include "core/css/StyleRuleKeyframe.h" 13 #include "core/css/StyleRuleKeyframe.h"
14 #include "core/css/StyleRuleNamespace.h" 14 #include "core/css/StyleRuleNamespace.h"
15 #include "core/css/StyleSheetContents.h" 15 #include "core/css/StyleSheetContents.h"
16 #include "core/css/parser/CSSAtRuleID.h" 16 #include "core/css/parser/CSSAtRuleID.h"
17 #include "core/css/parser/CSSLazyParsingState.h" 17 #include "core/css/parser/CSSLazyParsingState.h"
18 #include "core/css/parser/CSSLazyPropertyParserImpl.h" 18 #include "core/css/parser/CSSLazyPropertyParserImpl.h"
19 #include "core/css/parser/CSSParserObserver.h" 19 #include "core/css/parser/CSSParserObserver.h"
20 #include "core/css/parser/CSSParserObserverWrapper.h"
21 #include "core/css/parser/CSSParserSelector.h" 20 #include "core/css/parser/CSSParserSelector.h"
22 #include "core/css/parser/CSSPropertyParser.h" 21 #include "core/css/parser/CSSPropertyParser.h"
23 #include "core/css/parser/CSSSelectorParser.h" 22 #include "core/css/parser/CSSSelectorParser.h"
24 #include "core/css/parser/CSSSupportsParser.h" 23 #include "core/css/parser/CSSSupportsParser.h"
25 #include "core/css/parser/CSSTokenizer.h" 24 #include "core/css/parser/CSSTokenizer.h"
26 #include "core/css/parser/CSSVariableParser.h" 25 #include "core/css/parser/CSSVariableParser.h"
27 #include "core/css/parser/MediaQueryParser.h" 26 #include "core/css/parser/MediaQueryParser.h"
28 #include "core/dom/Document.h" 27 #include "core/dom/Document.h"
29 #include "core/dom/Element.h" 28 #include "core/dom/Element.h"
30 #include "core/frame/Deprecation.h" 29 #include "core/frame/Deprecation.h"
31 #include "core/frame/UseCounter.h" 30 #include "core/frame/UseCounter.h"
32 #include "platform/instrumentation/tracing/TraceEvent.h" 31 #include "platform/instrumentation/tracing/TraceEvent.h"
33 #include "wtf/PtrUtil.h" 32 #include "wtf/PtrUtil.h"
34 #include <bitset> 33 #include <bitset>
35 #include <memory> 34 #include <memory>
36 35
37 namespace blink { 36 namespace blink {
38 37
39 CSSParserImpl::CSSParserImpl(const CSSParserContext& context, 38 CSSParserImpl::CSSParserImpl(const CSSParserContext& context,
40 StyleSheetContents* styleSheet) 39 StyleSheetContents* styleSheet)
41 : m_context(context), 40 : m_context(context), m_styleSheet(styleSheet) {}
42 m_styleSheet(styleSheet),
43 m_observerWrapper(nullptr) {}
44 41
45 MutableStylePropertySet::SetResult CSSParserImpl::parseValue( 42 MutableStylePropertySet::SetResult CSSParserImpl::parseValue(
46 MutableStylePropertySet* declaration, 43 MutableStylePropertySet* declaration,
47 CSSPropertyID unresolvedProperty, 44 CSSPropertyID unresolvedProperty,
48 const String& string, 45 const String& string,
49 bool important, 46 bool important,
50 const CSSParserContext& context) { 47 const CSSParserContext& context) {
51 CSSParserImpl parser(context); 48 CSSParserImpl parser(context);
52 StyleRule::RuleType ruleType = StyleRule::Style; 49 StyleRule::RuleType ruleType = StyleRule::Style;
53 if (declaration->cssParserMode() == CSSViewportRuleMode) 50 if (declaration->cssParserMode() == CSSViewportRuleMode)
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
153 const String& string, 150 const String& string,
154 Element* element) { 151 Element* element) {
155 Document& document = element->document(); 152 Document& document = element->document();
156 CSSParserContext context = 153 CSSParserContext context =
157 CSSParserContext(document.elementSheet().contents()->parserContext(), 154 CSSParserContext(document.elementSheet().contents()->parserContext(),
158 UseCounter::getFrom(&document)); 155 UseCounter::getFrom(&document));
159 CSSParserMode mode = element->isHTMLElement() && !document.inQuirksMode() 156 CSSParserMode mode = element->isHTMLElement() && !document.inQuirksMode()
160 ? HTMLStandardMode 157 ? HTMLStandardMode
161 : HTMLQuirksMode; 158 : HTMLQuirksMode;
162 context.setMode(mode); 159 context.setMode(mode);
160 CSSTokenizer tokenizer(string);
161 CSSParserTokenStream stream(tokenizer);
163 CSSParserImpl parser(context, document.elementSheet().contents()); 162 CSSParserImpl parser(context, document.elementSheet().contents());
164 CSSTokenizer tokenizer(string); 163 parser.consumeDeclarationList(stream, StyleRule::Style);
165 parser.consumeDeclarationList(tokenizer.tokenRange(), StyleRule::Style);
166 return createStylePropertySet(parser.m_parsedProperties, mode); 164 return createStylePropertySet(parser.m_parsedProperties, mode);
167 } 165 }
168 166
169 bool CSSParserImpl::parseDeclarationList(MutableStylePropertySet* declaration, 167 bool CSSParserImpl::parseDeclarationList(MutableStylePropertySet* declaration,
170 const String& string, 168 const String& string,
171 const CSSParserContext& context) { 169 const CSSParserContext& context) {
172 CSSParserImpl parser(context); 170 CSSParserImpl parser(context);
173 StyleRule::RuleType ruleType = StyleRule::Style; 171 StyleRule::RuleType ruleType = StyleRule::Style;
174 if (declaration->cssParserMode() == CSSViewportRuleMode) 172 if (declaration->cssParserMode() == CSSViewportRuleMode)
175 ruleType = StyleRule::Viewport; 173 ruleType = StyleRule::Viewport;
176 CSSTokenizer tokenizer(string); 174 CSSTokenizer tokenizer(string);
177 parser.consumeDeclarationList(tokenizer.tokenRange(), ruleType); 175 CSSParserTokenStream stream(tokenizer);
176 parser.consumeDeclarationList(stream, ruleType);
178 if (parser.m_parsedProperties.isEmpty()) 177 if (parser.m_parsedProperties.isEmpty())
179 return false; 178 return false;
180 179
181 std::bitset<numCSSProperties> seenProperties; 180 std::bitset<numCSSProperties> seenProperties;
182 size_t unusedEntries = parser.m_parsedProperties.size(); 181 size_t unusedEntries = parser.m_parsedProperties.size();
183 HeapVector<CSSProperty, 256> results(unusedEntries); 182 HeapVector<CSSProperty, 256> results(unusedEntries);
184 HashSet<AtomicString> seenCustomProperties; 183 HashSet<AtomicString> seenCustomProperties;
185 filterProperties(true, parser.m_parsedProperties, results, unusedEntries, 184 filterProperties(true, parser.m_parsedProperties, results, unusedEntries,
186 seenProperties, seenCustomProperties); 185 seenProperties, seenCustomProperties);
187 filterProperties(false, parser.m_parsedProperties, results, unusedEntries, 186 filterProperties(false, parser.m_parsedProperties, results, unusedEntries,
188 seenProperties, seenCustomProperties); 187 seenProperties, seenCustomProperties);
189 if (unusedEntries) 188 if (unusedEntries)
190 results.remove(0, unusedEntries); 189 results.remove(0, unusedEntries);
191 return declaration->addParsedProperties(results); 190 return declaration->addParsedProperties(results);
192 } 191 }
193 192
194 StyleRuleBase* CSSParserImpl::parseRule(const String& string, 193 StyleRuleBase* CSSParserImpl::parseRule(const String& string,
195 const CSSParserContext& context, 194 const CSSParserContext& context,
196 StyleSheetContents* styleSheet, 195 StyleSheetContents* styleSheet,
197 AllowedRulesType allowedRules) { 196 AllowedRulesType allowedRules) {
198 CSSParserImpl parser(context, styleSheet); 197 CSSParserImpl parser(context, styleSheet);
199 CSSTokenizer tokenizer(string); 198 CSSTokenizer tokenizer(string);
200 CSSParserTokenRange range = tokenizer.tokenRange(); 199 CSSParserTokenStream stream(tokenizer);
201 range.consumeWhitespace(); 200 stream.skipWhitespaceAndComments();
202 if (range.atEnd()) 201 if (stream.atEnd())
203 return nullptr; // Parse error, empty rule 202 return nullptr; // Parse error, empty rule
204 StyleRuleBase* rule; 203 StyleRuleBase* rule;
205 if (range.peek().type() == AtKeywordToken) 204 if (stream.peek().type() == AtKeywordToken)
206 rule = parser.consumeAtRule(range, allowedRules); 205 rule = parser.consumeAtRule(stream, allowedRules);
207 else 206 else
208 rule = parser.consumeQualifiedRule(range, allowedRules); 207 rule = parser.consumeQualifiedRule(stream, allowedRules);
209 if (!rule) 208 if (!rule)
210 return nullptr; // Parse error, failed to consume rule 209 return nullptr; // Parse error, failed to consume rule
211 range.consumeWhitespace(); 210 stream.skipWhitespaceAndComments();
212 if (!rule || !range.atEnd()) 211 if (!rule || !stream.atEnd())
213 return nullptr; // Parse error, trailing garbage 212 return nullptr; // Parse error, trailing garbage
214 return rule; 213 return rule;
215 } 214 }
216 215
217 void CSSParserImpl::parseStyleSheet(const String& string, 216 void CSSParserImpl::parseStyleSheet(const String& string,
218 const CSSParserContext& context, 217 const CSSParserContext& context,
219 StyleSheetContents* styleSheet, 218 StyleSheetContents* styleSheet,
220 bool deferPropertyParsing) { 219 bool deferPropertyParsing) {
221 TRACE_EVENT_BEGIN2("blink,blink_style", "CSSParserImpl::parseStyleSheet", 220 TRACE_EVENT_BEGIN2("blink,blink_style", "CSSParserImpl::parseStyleSheet",
222 "baseUrl", context.baseURL().getString().utf8(), "mode", 221 "baseUrl", context.baseURL().getString().utf8(), "mode",
223 context.mode()); 222 context.mode());
224
225 TRACE_EVENT_BEGIN0("blink,blink_style",
226 "CSSParserImpl::parseStyleSheet.tokenize");
227 CSSTokenizer tokenizer(string); 223 CSSTokenizer tokenizer(string);
228 TRACE_EVENT_END0("blink,blink_style", 224 CSSParserTokenStream stream(tokenizer);
229 "CSSParserImpl::parseStyleSheet.tokenize");
230
231 TRACE_EVENT_BEGIN0("blink,blink_style",
232 "CSSParserImpl::parseStyleSheet.parse");
233 CSSParserImpl parser(context, styleSheet); 225 CSSParserImpl parser(context, styleSheet);
234 if (deferPropertyParsing) { 226 if (deferPropertyParsing) {
235 parser.m_lazyState = new CSSLazyParsingState( 227 parser.m_lazyState =
236 context, tokenizer.takeEscapedStrings(), string, parser.m_styleSheet); 228 new CSSLazyParsingState(context, string, parser.m_styleSheet);
237 } 229 }
238 bool firstRuleValid = 230 bool firstRuleValid = parser.consumeRuleList(
239 parser.consumeRuleList(tokenizer.tokenRange(), TopLevelRuleList, 231 stream, TopLevelRuleList, [&styleSheet](StyleRuleBase* rule) {
240 [&styleSheet](StyleRuleBase* rule) { 232 if (rule->isCharsetRule())
241 if (rule->isCharsetRule()) 233 return;
242 return; 234 styleSheet->parserAppendRule(rule);
243 styleSheet->parserAppendRule(rule); 235 });
244 });
245 styleSheet->setHasSyntacticallyValidCSSHeader(firstRuleValid); 236 styleSheet->setHasSyntacticallyValidCSSHeader(firstRuleValid);
246 TRACE_EVENT_END0("blink,blink_style", "CSSParserImpl::parseStyleSheet.parse"); 237 TRACE_EVENT_END1("blink,blink_style", "CSSParserImpl::parseStyleSheet",
247 238 "length", string.length());
248 TRACE_EVENT_END2("blink,blink_style", "CSSParserImpl::parseStyleSheet",
249 "tokenCount", tokenizer.tokenCount(), "length",
250 string.length());
251 } 239 }
252 240
253 CSSSelectorList CSSParserImpl::parsePageSelector( 241 CSSSelectorList CSSParserImpl::parsePageSelector(
254 CSSParserTokenRange range, 242 CSSParserTokenRange range,
255 StyleSheetContents* styleSheet) { 243 StyleSheetContents* styleSheet) {
256 // We only support a small subset of the css-page spec. 244 // We only support a small subset of the css-page spec.
257 range.consumeWhitespace(); 245 range.consumeWhitespace();
258 AtomicString typeSelector; 246 AtomicString typeSelector;
259 if (range.peek().type() == IdentToken) 247 if (range.peek().type() == IdentToken)
260 typeSelector = range.consume().value().toAtomicString(); 248 typeSelector = range.consume().value().toAtomicString();
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
300 ImmutableStylePropertySet* CSSParserImpl::parseCustomPropertySet( 288 ImmutableStylePropertySet* CSSParserImpl::parseCustomPropertySet(
301 CSSParserTokenRange range) { 289 CSSParserTokenRange range) {
302 range.consumeWhitespace(); 290 range.consumeWhitespace();
303 if (range.peek().type() != LeftBraceToken) 291 if (range.peek().type() != LeftBraceToken)
304 return nullptr; 292 return nullptr;
305 CSSParserTokenRange block = range.consumeBlock(); 293 CSSParserTokenRange block = range.consumeBlock();
306 range.consumeWhitespace(); 294 range.consumeWhitespace();
307 if (!range.atEnd()) 295 if (!range.atEnd())
308 return nullptr; 296 return nullptr;
309 CSSParserImpl parser(strictCSSParserContext()); 297 CSSParserImpl parser(strictCSSParserContext());
310 parser.consumeDeclarationList(block, StyleRule::Style); 298 parser.consumeDeclarationListForAtApply(block);
311
312 // Drop nested @apply rules. Seems nicer to do this here instead of making
313 // a different StyleRule type
314 for (size_t i = parser.m_parsedProperties.size(); i--;) {
315 if (parser.m_parsedProperties[i].id() == CSSPropertyApplyAtRule)
316 parser.m_parsedProperties.remove(i);
317 }
318
319 return createStylePropertySet(parser.m_parsedProperties, HTMLStandardMode); 299 return createStylePropertySet(parser.m_parsedProperties, HTMLStandardMode);
320 } 300 }
321 301
322 std::unique_ptr<Vector<double>> CSSParserImpl::parseKeyframeKeyList( 302 std::unique_ptr<Vector<double>> CSSParserImpl::parseKeyframeKeyList(
323 const String& keyList) { 303 const String& keyList) {
324 return consumeKeyframeKeyList(CSSTokenizer(keyList).tokenRange()); 304 return consumeKeyframeKeyList(CSSTokenizer(keyList).tokenRange());
325 } 305 }
326 306
327 bool CSSParserImpl::supportsDeclaration(CSSParserTokenRange& range) { 307 bool CSSParserImpl::supportsDeclaration(CSSParserTokenRange& range) {
328 ASSERT(m_parsedProperties.isEmpty()); 308 ASSERT(m_parsedProperties.isEmpty());
329 consumeDeclaration(range, StyleRule::Style); 309 consumeDeclaration(range, StyleRule::Style, 0, 0);
330 bool result = !m_parsedProperties.isEmpty(); 310 bool result = !m_parsedProperties.isEmpty();
331 m_parsedProperties.clear(); 311 m_parsedProperties.clear();
332 return result; 312 return result;
333 } 313 }
334 314
335 void CSSParserImpl::parseDeclarationListForInspector( 315 void CSSParserImpl::parseDeclarationListForInspector(
336 const String& declaration, 316 const String& declaration,
337 const CSSParserContext& context, 317 const CSSParserContext& context,
338 CSSParserObserver& observer) { 318 CSSParserObserver& observer) {
339 CSSParserImpl parser(context);
340 CSSParserObserverWrapper wrapper(observer);
341 parser.m_observerWrapper = &wrapper;
342 CSSTokenizer tokenizer(declaration, wrapper);
343 observer.startRuleHeader(StyleRule::Style, 0); 319 observer.startRuleHeader(StyleRule::Style, 0);
344 observer.endRuleHeader(1); 320 observer.endRuleHeader(1);
345 parser.consumeDeclarationList(tokenizer.tokenRange(), StyleRule::Style); 321
322 CSSParserImpl parser(context);
323 parser.m_observer = &observer;
324 CSSTokenizer tokenizer(declaration);
325 CSSParserTokenStream stream(tokenizer);
326 parser.consumeDeclarationList(stream, StyleRule::Style);
346 } 327 }
347 328
348 void CSSParserImpl::parseStyleSheetForInspector(const String& string, 329 void CSSParserImpl::parseStyleSheetForInspector(const String& string,
349 const CSSParserContext& context, 330 const CSSParserContext& context,
350 StyleSheetContents* styleSheet, 331 StyleSheetContents* styleSheet,
351 CSSParserObserver& observer) { 332 CSSParserObserver& observer) {
333 CSSTokenizer tokenizer(string);
334 CSSParserTokenStream stream(tokenizer);
352 CSSParserImpl parser(context, styleSheet); 335 CSSParserImpl parser(context, styleSheet);
353 CSSParserObserverWrapper wrapper(observer); 336 parser.m_observer = &observer;
354 parser.m_observerWrapper = &wrapper; 337 bool firstRuleValid = parser.consumeRuleList(
355 CSSTokenizer tokenizer(string, wrapper); 338 stream, TopLevelRuleList, [&styleSheet](StyleRuleBase* rule) {
356 bool firstRuleValid = 339 if (rule->isCharsetRule())
357 parser.consumeRuleList(tokenizer.tokenRange(), TopLevelRuleList, 340 return;
358 [&styleSheet](StyleRuleBase* rule) { 341 styleSheet->parserAppendRule(rule);
359 if (rule->isCharsetRule()) 342 });
360 return;
361 styleSheet->parserAppendRule(rule);
362 });
363 styleSheet->setHasSyntacticallyValidCSSHeader(firstRuleValid); 343 styleSheet->setHasSyntacticallyValidCSSHeader(firstRuleValid);
364 } 344 }
365 345
366 StylePropertySet* CSSParserImpl::parseDeclarationListForLazyStyle( 346 StylePropertySet* CSSParserImpl::parseDeclarationListForLazyStyle(
367 CSSParserTokenRange block, 347 const String& string,
348 size_t startOffset,
368 const CSSParserContext& context) { 349 const CSSParserContext& context) {
350 CSSTokenizer tokenizer(string, startOffset);
351 CSSParserTokenStream stream(tokenizer);
352 stream.peek();
353 // We can't start the stream inside the block as the } wouldn't end the
354 // stream.
355 CSSParserTokenStream block(stream, CSSParserTokenStream::MakeSubStream);
369 CSSParserImpl parser(context); 356 CSSParserImpl parser(context);
370 parser.consumeDeclarationList(std::move(block), StyleRule::Style); 357 parser.consumeDeclarationList(block, StyleRule::Style);
371 return createStylePropertySet(parser.m_parsedProperties, context.mode()); 358 return createStylePropertySet(parser.m_parsedProperties, context.mode());
372 } 359 }
373 360
374 static CSSParserImpl::AllowedRulesType computeNewAllowedRules( 361 static CSSParserImpl::AllowedRulesType computeNewAllowedRules(
375 CSSParserImpl::AllowedRulesType allowedRules, 362 CSSParserImpl::AllowedRulesType allowedRules,
376 StyleRuleBase* rule) { 363 StyleRuleBase* rule) {
377 if (!rule || allowedRules == CSSParserImpl::KeyframeRules || 364 if (!rule || allowedRules == CSSParserImpl::KeyframeRules ||
378 allowedRules == CSSParserImpl::NoRules) 365 allowedRules == CSSParserImpl::NoRules)
379 return allowedRules; 366 return allowedRules;
380 ASSERT(allowedRules <= CSSParserImpl::RegularRules); 367 ASSERT(allowedRules <= CSSParserImpl::RegularRules);
381 if (rule->isCharsetRule() || rule->isImportRule()) 368 if (rule->isCharsetRule() || rule->isImportRule())
382 return CSSParserImpl::AllowImportRules; 369 return CSSParserImpl::AllowImportRules;
383 if (rule->isNamespaceRule()) 370 if (rule->isNamespaceRule())
384 return CSSParserImpl::AllowNamespaceRules; 371 return CSSParserImpl::AllowNamespaceRules;
385 return CSSParserImpl::RegularRules; 372 return CSSParserImpl::RegularRules;
386 } 373 }
387 374
388 template <typename T> 375 template <typename T>
389 bool CSSParserImpl::consumeRuleList(CSSParserTokenRange range, 376 bool CSSParserImpl::consumeRuleList(CSSParserTokenStream& stream,
390 RuleListType ruleListType, 377 RuleListType ruleListType,
391 const T callback) { 378 const T callback) {
392 AllowedRulesType allowedRules = RegularRules; 379 AllowedRulesType allowedRules = RegularRules;
393 switch (ruleListType) { 380 switch (ruleListType) {
394 case TopLevelRuleList: 381 case TopLevelRuleList:
395 allowedRules = AllowCharsetRules; 382 allowedRules = AllowCharsetRules;
396 break; 383 break;
397 case RegularRuleList: 384 case RegularRuleList:
398 allowedRules = RegularRules; 385 allowedRules = RegularRules;
399 break; 386 break;
400 case KeyframesRuleList: 387 case KeyframesRuleList:
401 allowedRules = KeyframeRules; 388 allowedRules = KeyframeRules;
402 break; 389 break;
403 default: 390 default:
404 ASSERT_NOT_REACHED(); 391 ASSERT_NOT_REACHED();
405 } 392 }
406 393
407 bool seenRule = false; 394 bool seenRule = false;
408 bool firstRuleValid = false; 395 bool firstRuleValid = false;
409 while (!range.atEnd()) { 396 while (true) {
410 StyleRuleBase* rule; 397 StyleRuleBase* rule;
411 switch (range.peek().type()) { 398 size_t qualifiedRuleStartOffset = stream.offsetAfterComments();
399 if (stream.atEnd())
400 break;
401 switch (stream.peek().type()) {
412 case WhitespaceToken: 402 case WhitespaceToken:
413 range.consumeWhitespace(); 403 stream.consume();
414 continue; 404 continue;
415 case AtKeywordToken: 405 case AtKeywordToken:
416 rule = consumeAtRule(range, allowedRules); 406 rule = consumeAtRule(stream, allowedRules);
407 stream.clean();
417 break; 408 break;
418 case CDOToken: 409 case CDOToken:
419 case CDCToken: 410 case CDCToken:
420 if (ruleListType == TopLevelRuleList) { 411 if (ruleListType == TopLevelRuleList) {
421 range.consume(); 412 stream.consume();
422 continue; 413 continue;
423 } 414 }
424 // fallthrough 415 // fallthrough
425 default: 416 default:
426 rule = consumeQualifiedRule(range, allowedRules); 417 rule = consumeQualifiedRule(stream, allowedRules,
418 qualifiedRuleStartOffset);
419 stream.clean();
427 break; 420 break;
428 } 421 }
429 if (!seenRule) { 422 if (!seenRule) {
430 seenRule = true; 423 seenRule = true;
431 firstRuleValid = rule; 424 firstRuleValid = rule;
432 } 425 }
433 if (rule) { 426 if (rule) {
434 allowedRules = computeNewAllowedRules(allowedRules, rule); 427 allowedRules = computeNewAllowedRules(allowedRules, rule);
435 callback(rule); 428 callback(rule);
436 } 429 }
437 } 430 }
438 431
439 return firstRuleValid; 432 return firstRuleValid;
440 } 433 }
441 434
442 StyleRuleBase* CSSParserImpl::consumeAtRule(CSSParserTokenRange& range, 435 StyleRuleBase* CSSParserImpl::consumeAtRule(CSSParserTokenStream& stream,
443 AllowedRulesType allowedRules) { 436 AllowedRulesType allowedRules) {
444 ASSERT(range.peek().type() == AtKeywordToken); 437 DCHECK_EQ(stream.peek().type(), AtKeywordToken);
445 const StringView name = range.consumeIncludingWhitespace().value(); 438 const StringView name = stream.peek().value();
446 const CSSParserToken* preludeStart = &range.peek(); 439 stream.consume();
447 while (!range.atEnd() && range.peek().type() != LeftBraceToken && 440 stream.skipWhitespaceAndComments();
448 range.peek().type() != SemicolonToken) 441 size_t preludeStartOffset = stream.offset();
449 range.consumeComponentValue(); 442 size_t preludeStart = stream.index();
443 stream.consumeUntilAtEndOrPeekedTypeIs<LeftBraceToken, SemicolonToken>();
450 444
451 CSSParserTokenRange prelude = range.makeSubRange(preludeStart, &range.peek()); 445 CSSParserTokenRange prelude = stream.makeSubRangeFrom(preludeStart);
452 CSSAtRuleID id = cssAtRuleID(name); 446 CSSAtRuleID id = cssAtRuleID(name);
453 if (id != CSSAtRuleInvalid && m_context.useCounter()) 447 if (id != CSSAtRuleInvalid && m_context.useCounter())
454 countAtRule(m_context.useCounter(), id); 448 countAtRule(m_context.useCounter(), id);
455 449
456 if (range.atEnd() || range.peek().type() == SemicolonToken) { 450 if (stream.atEnd() || stream.peek().type() == SemicolonToken) {
457 range.consume(); 451 size_t preludeEndOffset = stream.previousOffset();
452 if (!stream.atEnd())
453 stream.consume();
458 if (allowedRules == AllowCharsetRules && id == CSSAtRuleCharset) 454 if (allowedRules == AllowCharsetRules && id == CSSAtRuleCharset)
459 return consumeCharsetRule(prelude); 455 return consumeCharsetRule(prelude);
460 if (allowedRules <= AllowImportRules && id == CSSAtRuleImport) 456 if (allowedRules <= AllowImportRules && id == CSSAtRuleImport)
461 return consumeImportRule(prelude); 457 return consumeImportRule(prelude, preludeStartOffset, preludeEndOffset);
462 if (allowedRules <= AllowNamespaceRules && id == CSSAtRuleNamespace) 458 if (allowedRules <= AllowNamespaceRules && id == CSSAtRuleNamespace)
463 return consumeNamespaceRule(prelude); 459 return consumeNamespaceRule(prelude);
464 if (allowedRules == ApplyRules && id == CSSAtRuleApply) { 460 if (allowedRules == ApplyRules && id == CSSAtRuleApply) {
465 consumeApplyRule(prelude); 461 consumeApplyRule(prelude);
466 return nullptr; // consumeApplyRule just updates m_parsedProperties 462 return nullptr; // consumeApplyRule just updates m_parsedProperties
467 } 463 }
468 return nullptr; // Parse error, unrecognised at-rule without block 464 return nullptr; // Parse error, unrecognised at-rule without block
469 } 465 }
470 466
471 CSSParserTokenRange block = range.consumeBlock(); 467 CSSParserTokenStream block(stream, CSSParserTokenStream::MakeSubStream);
472 if (allowedRules == KeyframeRules) 468 if (allowedRules == KeyframeRules)
473 return nullptr; // Parse error, no at-rules supported inside @keyframes 469 return nullptr; // Parse error, no at-rules supported inside @keyframes
474 if (allowedRules == NoRules || allowedRules == ApplyRules) 470 if (allowedRules == NoRules || allowedRules == ApplyRules)
475 return nullptr; // Parse error, no at-rules with blocks supported inside 471 return nullptr; // Parse error, no at-rules with blocks supported inside
476 // declaration lists 472 // declaration lists
477 473
478 ASSERT(allowedRules <= RegularRules); 474 ASSERT(allowedRules <= RegularRules);
479 475
480 switch (id) { 476 switch (id) {
481 case CSSAtRuleMedia: 477 case CSSAtRuleMedia:
482 return consumeMediaRule(prelude, block); 478 return consumeMediaRule(prelude, block, preludeStartOffset);
483 case CSSAtRuleSupports: 479 case CSSAtRuleSupports:
484 return consumeSupportsRule(prelude, block); 480 return consumeSupportsRule(prelude, block, preludeStartOffset);
485 case CSSAtRuleViewport: 481 case CSSAtRuleViewport:
486 return consumeViewportRule(prelude, block); 482 return consumeViewportRule(prelude, block, preludeStartOffset);
487 case CSSAtRuleFontFace: 483 case CSSAtRuleFontFace:
488 return consumeFontFaceRule(prelude, block); 484 return consumeFontFaceRule(prelude, block, preludeStartOffset);
489 case CSSAtRuleWebkitKeyframes: 485 case CSSAtRuleWebkitKeyframes:
490 return consumeKeyframesRule(true, prelude, block); 486 return consumeKeyframesRule(true, prelude, block, preludeStartOffset);
491 case CSSAtRuleKeyframes: 487 case CSSAtRuleKeyframes:
492 return consumeKeyframesRule(false, prelude, block); 488 return consumeKeyframesRule(false, prelude, block, preludeStartOffset);
493 case CSSAtRulePage: 489 case CSSAtRulePage:
494 return consumePageRule(prelude, block); 490 return consumePageRule(prelude, block, preludeStartOffset);
495 default: 491 default:
496 return nullptr; // Parse error, unrecognised at-rule with block 492 return nullptr; // Parse error, unrecognised at-rule with block
497 } 493 }
498 } 494 }
499 495
500 StyleRuleBase* CSSParserImpl::consumeQualifiedRule( 496 StyleRuleBase* CSSParserImpl::consumeQualifiedRule(
501 CSSParserTokenRange& range, 497 CSSParserTokenStream& stream,
502 AllowedRulesType allowedRules) { 498 AllowedRulesType allowedRules,
503 const CSSParserToken* preludeStart = &range.peek(); 499 size_t startOffset) {
504 while (!range.atEnd() && range.peek().type() != LeftBraceToken) 500 if (allowedRules <= RegularRules)
505 range.consumeComponentValue(); 501 return consumeStyleRule(stream, startOffset);
506 502
507 if (range.atEnd()) 503 size_t preludeStart = stream.index();
504 stream.consumeUntilAtEndOrPeekedTypeIs<LeftBraceToken>();
505
506 if (stream.atEnd())
508 return nullptr; // Parse error, EOF instead of qualified rule block 507 return nullptr; // Parse error, EOF instead of qualified rule block
509 508
510 CSSParserTokenRange prelude = range.makeSubRange(preludeStart, &range.peek()); 509 CSSParserTokenRange prelude = stream.makeSubRangeFrom(preludeStart);
511 CSSParserTokenRange block = range.consumeBlock(); 510 CSSParserTokenStream block(stream, CSSParserTokenStream::MakeSubStream);
512 511 DCHECK(allowedRules == KeyframeRules);
513 if (allowedRules <= RegularRules) 512 return consumeKeyframeStyleRule(prelude, block, startOffset);
514 return consumeStyleRule(prelude, block);
515 if (allowedRules == KeyframeRules)
516 return consumeKeyframeStyleRule(prelude, block);
517
518 ASSERT_NOT_REACHED();
519 return nullptr;
520 } 513 }
521 514
522 // This may still consume tokens if it fails 515 // This may still consume tokens if it fails
523 static AtomicString consumeStringOrURI(CSSParserTokenRange& range) { 516 static AtomicString consumeStringOrURI(CSSParserTokenRange& range) {
524 const CSSParserToken& token = range.peek(); 517 const CSSParserToken& token = range.peek();
525 518
526 if (token.type() == StringToken || token.type() == UrlToken) 519 if (token.type() == StringToken || token.type() == UrlToken)
527 return range.consumeIncludingWhitespace().value().toAtomicString(); 520 return range.consumeIncludingWhitespace().value().toAtomicString();
528 521
529 if (token.type() != FunctionToken || 522 if (token.type() != FunctionToken ||
530 !equalIgnoringASCIICase(token.value(), "url")) 523 !equalIgnoringASCIICase(token.value(), "url"))
531 return AtomicString(); 524 return AtomicString();
532 525
533 CSSParserTokenRange contents = range.consumeBlock(); 526 CSSParserTokenRange contents = range.consumeBlock();
534 const CSSParserToken& uri = contents.consumeIncludingWhitespace(); 527 const CSSParserToken& uri = contents.consumeIncludingWhitespace();
535 if (uri.type() == BadStringToken || !contents.atEnd()) 528 if (uri.type() == BadStringToken || !contents.atEnd())
536 return AtomicString(); 529 return AtomicString();
537 DCHECK_EQ(uri.type(), StringToken); 530 DCHECK_EQ(uri.type(), StringToken);
538 return uri.value().toAtomicString(); 531 return uri.value().toAtomicString();
539 } 532 }
540 533
541 StyleRuleCharset* CSSParserImpl::consumeCharsetRule( 534 StyleRuleCharset* CSSParserImpl::consumeCharsetRule(
542 CSSParserTokenRange prelude) { 535 CSSParserTokenRange prelude) {
543 const CSSParserToken& string = prelude.consumeIncludingWhitespace(); 536 const CSSParserToken& string = prelude.consumeIncludingWhitespace();
544 if (string.type() != StringToken || !prelude.atEnd()) 537 if (string.type() != StringToken || !prelude.atEnd())
545 return nullptr; // Parse error, expected a single string 538 return nullptr; // Parse error, expected a single string
546 return StyleRuleCharset::create(); 539 return StyleRuleCharset::create();
547 } 540 }
548 541
549 StyleRuleImport* CSSParserImpl::consumeImportRule(CSSParserTokenRange prelude) { 542 StyleRuleImport* CSSParserImpl::consumeImportRule(CSSParserTokenRange prelude,
543 size_t startOffset,
544 size_t endOffset) {
550 AtomicString uri(consumeStringOrURI(prelude)); 545 AtomicString uri(consumeStringOrURI(prelude));
551 if (uri.isNull()) 546 if (uri.isNull())
552 return nullptr; // Parse error, expected string or URI 547 return nullptr; // Parse error, expected string or URI
553 548
554 if (m_observerWrapper) { 549 if (m_observer) {
555 unsigned endOffset = m_observerWrapper->endOffset(prelude); 550 m_observer->startRuleHeader(StyleRule::Import, startOffset);
556 m_observerWrapper->observer().startRuleHeader( 551 m_observer->endRuleHeader(endOffset);
557 StyleRule::Import, m_observerWrapper->startOffset(prelude)); 552 m_observer->startRuleBody(endOffset);
558 m_observerWrapper->observer().endRuleHeader(endOffset); 553 m_observer->endRuleBody(endOffset);
559 m_observerWrapper->observer().startRuleBody(endOffset);
560 m_observerWrapper->observer().endRuleBody(endOffset);
561 } 554 }
562 555
563 return StyleRuleImport::create(uri, 556 return StyleRuleImport::create(uri,
564 MediaQueryParser::parseMediaQuerySet(prelude)); 557 MediaQueryParser::parseMediaQuerySet(prelude));
565 } 558 }
566 559
567 StyleRuleNamespace* CSSParserImpl::consumeNamespaceRule( 560 StyleRuleNamespace* CSSParserImpl::consumeNamespaceRule(
568 CSSParserTokenRange prelude) { 561 CSSParserTokenRange prelude) {
569 AtomicString namespacePrefix; 562 AtomicString namespacePrefix;
570 if (prelude.peek().type() == IdentToken) 563 if (prelude.peek().type() == IdentToken)
571 namespacePrefix = 564 namespacePrefix =
572 prelude.consumeIncludingWhitespace().value().toAtomicString(); 565 prelude.consumeIncludingWhitespace().value().toAtomicString();
573 566
574 AtomicString uri(consumeStringOrURI(prelude)); 567 AtomicString uri(consumeStringOrURI(prelude));
575 if (uri.isNull() || !prelude.atEnd()) 568 if (uri.isNull() || !prelude.atEnd())
576 return nullptr; // Parse error, expected string or URI 569 return nullptr; // Parse error, expected string or URI
577 570
578 return StyleRuleNamespace::create(namespacePrefix, uri); 571 return StyleRuleNamespace::create(namespacePrefix, uri);
579 } 572 }
580 573
581 StyleRuleMedia* CSSParserImpl::consumeMediaRule(CSSParserTokenRange prelude, 574 StyleRuleMedia* CSSParserImpl::consumeMediaRule(CSSParserTokenRange prelude,
582 CSSParserTokenRange block) { 575 CSSParserTokenStream& block,
576 size_t preludeStartOffset) {
583 HeapVector<Member<StyleRuleBase>> rules; 577 HeapVector<Member<StyleRuleBase>> rules;
584 578
585 if (m_observerWrapper) { 579 if (m_observer) {
586 m_observerWrapper->observer().startRuleHeader( 580 m_observer->startRuleHeader(StyleRule::Media, preludeStartOffset);
587 StyleRule::Media, m_observerWrapper->startOffset(prelude)); 581 m_observer->endRuleHeader(block.offset() - 1);
588 m_observerWrapper->observer().endRuleHeader( 582 m_observer->startRuleBody(block.offset() - 1);
589 m_observerWrapper->endOffset(prelude));
590 m_observerWrapper->observer().startRuleBody(
591 m_observerWrapper->previousTokenStartOffset(block));
592 } 583 }
593 584
594 if (m_styleSheet) 585 if (m_styleSheet)
595 m_styleSheet->setHasMediaQueries(); 586 m_styleSheet->setHasMediaQueries();
596 587
597 consumeRuleList(block, RegularRuleList, 588 consumeRuleList(block, RegularRuleList,
598 [&rules](StyleRuleBase* rule) { rules.push_back(rule); }); 589 [&rules](StyleRuleBase* rule) { rules.push_back(rule); });
599 590
600 if (m_observerWrapper) 591 if (m_observer)
601 m_observerWrapper->observer().endRuleBody( 592 m_observer->endRuleBody(block.offset());
602 m_observerWrapper->endOffset(block));
603 593
604 return StyleRuleMedia::create(MediaQueryParser::parseMediaQuerySet(prelude), 594 return StyleRuleMedia::create(MediaQueryParser::parseMediaQuerySet(prelude),
605 rules); 595 rules);
606 } 596 }
607 597
608 StyleRuleSupports* CSSParserImpl::consumeSupportsRule( 598 StyleRuleSupports* CSSParserImpl::consumeSupportsRule(
609 CSSParserTokenRange prelude, 599 CSSParserTokenRange prelude,
610 CSSParserTokenRange block) { 600 CSSParserTokenStream& block,
601 size_t preludeStartOffset) {
611 CSSSupportsParser::SupportsResult supported = 602 CSSSupportsParser::SupportsResult supported =
612 CSSSupportsParser::supportsCondition(prelude, *this); 603 CSSSupportsParser::supportsCondition(prelude, *this);
613 if (supported == CSSSupportsParser::Invalid) 604 if (supported == CSSSupportsParser::Invalid)
614 return nullptr; // Parse error, invalid @supports condition 605 return nullptr; // Parse error, invalid @supports condition
615 606
616 if (m_observerWrapper) { 607 if (m_observer) {
617 m_observerWrapper->observer().startRuleHeader( 608 m_observer->startRuleHeader(StyleRule::Supports, preludeStartOffset);
618 StyleRule::Supports, m_observerWrapper->startOffset(prelude)); 609 m_observer->endRuleHeader(block.offset() - 1);
619 m_observerWrapper->observer().endRuleHeader( 610 m_observer->startRuleBody(block.offset() - 1);
620 m_observerWrapper->endOffset(prelude));
621 m_observerWrapper->observer().startRuleBody(
622 m_observerWrapper->previousTokenStartOffset(block));
623 } 611 }
624 612
625 HeapVector<Member<StyleRuleBase>> rules; 613 HeapVector<Member<StyleRuleBase>> rules;
626 consumeRuleList(block, RegularRuleList, 614 consumeRuleList(block, RegularRuleList,
627 [&rules](StyleRuleBase* rule) { rules.push_back(rule); }); 615 [&rules](StyleRuleBase* rule) { rules.push_back(rule); });
628 616
629 if (m_observerWrapper) 617 if (m_observer)
630 m_observerWrapper->observer().endRuleBody( 618 m_observer->endRuleBody(block.offset());
631 m_observerWrapper->endOffset(block));
632 619
633 return StyleRuleSupports::create(prelude.serialize().stripWhiteSpace(), 620 return StyleRuleSupports::create(prelude.serialize().stripWhiteSpace(),
634 supported, rules); 621 supported, rules);
635 } 622 }
636 623
637 StyleRuleViewport* CSSParserImpl::consumeViewportRule( 624 StyleRuleViewport* CSSParserImpl::consumeViewportRule(
638 CSSParserTokenRange prelude, 625 CSSParserTokenRange prelude,
639 CSSParserTokenRange block) { 626 CSSParserTokenStream& block,
627 size_t preludeStartOffset) {
640 // Allow @viewport rules from UA stylesheets even if the feature is disabled. 628 // Allow @viewport rules from UA stylesheets even if the feature is disabled.
641 if (!RuntimeEnabledFeatures::cssViewportEnabled() && 629 if (!RuntimeEnabledFeatures::cssViewportEnabled() &&
642 !isUASheetBehavior(m_context.mode())) 630 !isUASheetBehavior(m_context.mode()))
643 return nullptr; 631 return nullptr;
644 632
645 if (!prelude.atEnd()) 633 if (!prelude.atEnd())
646 return nullptr; // Parser error; @viewport prelude should be empty 634 return nullptr; // Parser error; @viewport prelude should be empty
647 635
648 if (m_observerWrapper) { 636 if (m_observer) {
649 unsigned endOffset = m_observerWrapper->endOffset(prelude); 637 m_observer->startRuleHeader(StyleRule::Viewport, preludeStartOffset);
650 m_observerWrapper->observer().startRuleHeader( 638 m_observer->endRuleHeader(block.offset() - 1);
651 StyleRule::Viewport, m_observerWrapper->startOffset(prelude)); 639 m_observer->startRuleBody(block.offset() - 1);
652 m_observerWrapper->observer().endRuleHeader(endOffset); 640 m_observer->endRuleBody(block.offset() - 1);
653 m_observerWrapper->observer().startRuleBody(endOffset);
654 m_observerWrapper->observer().endRuleBody(endOffset);
655 } 641 }
656 642
657 if (m_styleSheet) 643 if (m_styleSheet)
658 m_styleSheet->setHasViewportRule(); 644 m_styleSheet->setHasViewportRule();
659 645
660 consumeDeclarationList(block, StyleRule::Viewport); 646 consumeDeclarationList(block, StyleRule::Viewport);
661 return StyleRuleViewport::create( 647 return StyleRuleViewport::create(
662 createStylePropertySet(m_parsedProperties, CSSViewportRuleMode)); 648 createStylePropertySet(m_parsedProperties, CSSViewportRuleMode));
663 } 649 }
664 650
665 StyleRuleFontFace* CSSParserImpl::consumeFontFaceRule( 651 StyleRuleFontFace* CSSParserImpl::consumeFontFaceRule(
666 CSSParserTokenRange prelude, 652 CSSParserTokenRange prelude,
667 CSSParserTokenRange block) { 653 CSSParserTokenStream& block,
654 size_t preludeStartOffset) {
668 if (!prelude.atEnd()) 655 if (!prelude.atEnd())
669 return nullptr; // Parse error; @font-face prelude should be empty 656 return nullptr; // Parse error; @font-face prelude should be empty
670 657
671 if (m_observerWrapper) { 658 if (m_observer) {
672 unsigned endOffset = m_observerWrapper->endOffset(prelude); 659 m_observer->startRuleHeader(StyleRule::FontFace, preludeStartOffset);
673 m_observerWrapper->observer().startRuleHeader( 660 m_observer->endRuleHeader(block.offset() - 1);
674 StyleRule::FontFace, m_observerWrapper->startOffset(prelude)); 661 m_observer->startRuleBody(block.offset() - 1);
675 m_observerWrapper->observer().endRuleHeader(endOffset); 662 m_observer->endRuleBody(block.offset() - 1);
676 m_observerWrapper->observer().startRuleBody(endOffset);
677 m_observerWrapper->observer().endRuleBody(endOffset);
678 } 663 }
679 664
680 if (m_styleSheet) 665 if (m_styleSheet)
681 m_styleSheet->setHasFontFaceRule(); 666 m_styleSheet->setHasFontFaceRule();
682 667
683 consumeDeclarationList(block, StyleRule::FontFace); 668 consumeDeclarationList(block, StyleRule::FontFace);
684 return StyleRuleFontFace::create( 669 return StyleRuleFontFace::create(
685 createStylePropertySet(m_parsedProperties, CSSFontFaceRuleMode)); 670 createStylePropertySet(m_parsedProperties, CSSFontFaceRuleMode));
686 } 671 }
687 672
688 StyleRuleKeyframes* CSSParserImpl::consumeKeyframesRule( 673 StyleRuleKeyframes* CSSParserImpl::consumeKeyframesRule(
689 bool webkitPrefixed, 674 bool webkitPrefixed,
690 CSSParserTokenRange prelude, 675 CSSParserTokenRange prelude,
691 CSSParserTokenRange block) { 676 CSSParserTokenStream& block,
692 CSSParserTokenRange rangeCopy = prelude; // For inspector callbacks 677 size_t preludeStartOffset) {
693 const CSSParserToken& nameToken = prelude.consumeIncludingWhitespace(); 678 const CSSParserToken& nameToken = prelude.consumeIncludingWhitespace();
694 if (!prelude.atEnd()) 679 if (!prelude.atEnd())
695 return nullptr; // Parse error; expected single non-whitespace token in 680 return nullptr; // Parse error; expected single non-whitespace token in
696 // @keyframes header 681 // @keyframes header
697 682
698 String name; 683 String name;
699 if (nameToken.type() == IdentToken) { 684 if (nameToken.type() == IdentToken) {
700 name = nameToken.value().toString(); 685 name = nameToken.value().toString();
701 } else if (nameToken.type() == StringToken && webkitPrefixed) { 686 } else if (nameToken.type() == StringToken && webkitPrefixed) {
702 if (m_context.useCounter()) 687 if (m_context.useCounter())
703 m_context.useCounter()->count(UseCounter::QuotedKeyframesRule); 688 m_context.useCounter()->count(UseCounter::QuotedKeyframesRule);
704 name = nameToken.value().toString(); 689 name = nameToken.value().toString();
705 } else { 690 } else {
706 return nullptr; // Parse error; expected ident token in @keyframes header 691 return nullptr; // Parse error; expected ident token in @keyframes header
707 } 692 }
708 693
709 if (m_observerWrapper) { 694 if (m_observer) {
710 m_observerWrapper->observer().startRuleHeader( 695 m_observer->startRuleHeader(StyleRule::Keyframes, preludeStartOffset);
711 StyleRule::Keyframes, m_observerWrapper->startOffset(rangeCopy)); 696 m_observer->endRuleHeader(block.offset() - 1);
712 m_observerWrapper->observer().endRuleHeader( 697 m_observer->startRuleBody(block.offset() - 1);
713 m_observerWrapper->endOffset(prelude));
714 m_observerWrapper->observer().startRuleBody(
715 m_observerWrapper->previousTokenStartOffset(block));
716 m_observerWrapper->observer().endRuleBody(
717 m_observerWrapper->endOffset(block));
718 } 698 }
719 699
720 StyleRuleKeyframes* keyframeRule = StyleRuleKeyframes::create(); 700 StyleRuleKeyframes* keyframeRule = StyleRuleKeyframes::create();
721 consumeRuleList( 701 consumeRuleList(
722 block, KeyframesRuleList, [keyframeRule](StyleRuleBase* keyframe) { 702 block, KeyframesRuleList, [keyframeRule](StyleRuleBase* keyframe) {
723 keyframeRule->parserAppendKeyframe(toStyleRuleKeyframe(keyframe)); 703 keyframeRule->parserAppendKeyframe(toStyleRuleKeyframe(keyframe));
724 }); 704 });
725 keyframeRule->setName(name); 705 keyframeRule->setName(name);
726 keyframeRule->setVendorPrefixed(webkitPrefixed); 706 keyframeRule->setVendorPrefixed(webkitPrefixed);
707
708 if (m_observer)
709 m_observer->endRuleBody(block.offset());
710
727 return keyframeRule; 711 return keyframeRule;
728 } 712 }
729 713
730 StyleRulePage* CSSParserImpl::consumePageRule(CSSParserTokenRange prelude, 714 StyleRulePage* CSSParserImpl::consumePageRule(CSSParserTokenRange prelude,
731 CSSParserTokenRange block) { 715 CSSParserTokenStream& block,
716 size_t preludeStartOffset) {
732 CSSSelectorList selectorList = parsePageSelector(prelude, m_styleSheet); 717 CSSSelectorList selectorList = parsePageSelector(prelude, m_styleSheet);
733 if (!selectorList.isValid()) 718 if (!selectorList.isValid())
734 return nullptr; // Parse error, invalid @page selector 719 return nullptr; // Parse error, invalid @page selector
735 720
736 if (m_observerWrapper) { 721 if (m_observer) {
737 unsigned endOffset = m_observerWrapper->endOffset(prelude); 722 m_observer->startRuleHeader(StyleRule::Page, preludeStartOffset);
738 m_observerWrapper->observer().startRuleHeader( 723 m_observer->endRuleHeader(block.offset() - 1);
739 StyleRule::Page, m_observerWrapper->startOffset(prelude));
740 m_observerWrapper->observer().endRuleHeader(endOffset);
741 } 724 }
742 725
743 consumeDeclarationList(block, StyleRule::Style); 726 consumeDeclarationList(block, StyleRule::Style);
744 727
745 return StyleRulePage::create( 728 return StyleRulePage::create(
746 std::move(selectorList), 729 std::move(selectorList),
747 createStylePropertySet(m_parsedProperties, m_context.mode())); 730 createStylePropertySet(m_parsedProperties, m_context.mode()));
748 } 731 }
749 732
750 void CSSParserImpl::consumeApplyRule(CSSParserTokenRange prelude) { 733 void CSSParserImpl::consumeApplyRule(CSSParserTokenRange prelude) {
751 ASSERT(RuntimeEnabledFeatures::cssApplyAtRulesEnabled()); 734 ASSERT(RuntimeEnabledFeatures::cssApplyAtRulesEnabled());
752 735
753 const CSSParserToken& ident = prelude.consumeIncludingWhitespace(); 736 const CSSParserToken& ident = prelude.consumeIncludingWhitespace();
754 if (!prelude.atEnd() || !CSSVariableParser::isValidVariableName(ident)) 737 if (!prelude.atEnd() || !CSSVariableParser::isValidVariableName(ident))
755 return; // Parse error, expected a single custom property name 738 return; // Parse error, expected a single custom property name
756 m_parsedProperties.push_back(CSSProperty( 739 m_parsedProperties.push_back(CSSProperty(
757 CSSPropertyApplyAtRule, 740 CSSPropertyApplyAtRule,
758 *CSSCustomIdentValue::create(ident.value().toAtomicString()))); 741 *CSSCustomIdentValue::create(ident.value().toAtomicString())));
759 } 742 }
760 743
761 StyleRuleKeyframe* CSSParserImpl::consumeKeyframeStyleRule( 744 StyleRuleKeyframe* CSSParserImpl::consumeKeyframeStyleRule(
762 CSSParserTokenRange prelude, 745 CSSParserTokenRange prelude,
763 CSSParserTokenRange block) { 746 CSSParserTokenStream& block,
747 size_t preludeStartOffset) {
764 std::unique_ptr<Vector<double>> keyList = consumeKeyframeKeyList(prelude); 748 std::unique_ptr<Vector<double>> keyList = consumeKeyframeKeyList(prelude);
765 if (!keyList) 749 if (!keyList)
766 return nullptr; 750 return nullptr;
767 751
768 if (m_observerWrapper) { 752 if (m_observer) {
769 m_observerWrapper->observer().startRuleHeader( 753 m_observer->startRuleHeader(StyleRule::Keyframe, preludeStartOffset);
770 StyleRule::Keyframe, m_observerWrapper->startOffset(prelude)); 754 m_observer->endRuleHeader(block.offset() - 1);
771 m_observerWrapper->observer().endRuleHeader(
772 m_observerWrapper->endOffset(prelude));
773 } 755 }
774 756
775 consumeDeclarationList(block, StyleRule::Keyframe); 757 consumeDeclarationList(block, StyleRule::Keyframe);
776 return StyleRuleKeyframe::create( 758 return StyleRuleKeyframe::create(
777 std::move(keyList), 759 std::move(keyList),
778 createStylePropertySet(m_parsedProperties, m_context.mode())); 760 createStylePropertySet(m_parsedProperties, m_context.mode()));
779 } 761 }
780 762
781 static void observeSelectors(CSSParserObserverWrapper& wrapper, 763 StyleRule* CSSParserImpl::consumeStyleRule(CSSParserTokenStream& stream,
782 CSSParserTokenRange selectors) { 764 size_t startOffset) {
783 // This is easier than hooking into the CSSSelectorParser 765 if (m_observer)
784 selectors.consumeWhitespace(); 766 m_observer->startRuleHeader(StyleRule::Style, startOffset);
785 CSSParserTokenRange originalRange = selectors; 767 CSSSelectorList selectorList = CSSSelectorParser::consumeSelector(
786 wrapper.observer().startRuleHeader(StyleRule::Style, 768 stream, m_context, m_styleSheet, startOffset, m_observer);
787 wrapper.startOffset(originalRange));
788 769
789 while (!selectors.atEnd()) { 770 if (!selectorList.isValid())
790 const CSSParserToken* selectorStart = &selectors.peek(); 771 stream.consumeUntilAtEndOrPeekedTypeIs<LeftBraceToken>();
791 while (!selectors.atEnd() && selectors.peek().type() != CommaToken)
792 selectors.consumeComponentValue();
793 CSSParserTokenRange selector =
794 selectors.makeSubRange(selectorStart, &selectors.peek());
795 selectors.consumeIncludingWhitespace();
796 772
797 wrapper.observer().observeSelector(wrapper.startOffset(selector), 773 DCHECK(stream.atEnd() || stream.peek().type() == LeftBraceToken);
798 wrapper.endOffset(selector)); 774
775 if (m_observer)
776 m_observer->endRuleHeader(stream.previousOffset());
777
778 if (!selectorList.isValid()) {
779 if (!stream.atEnd())
780 stream.skipBlock();
781 return nullptr; // Parse error, invalid selector list
799 } 782 }
800 783
801 wrapper.observer().endRuleHeader(wrapper.endOffset(originalRange)); 784 if (m_lazyState && m_lazyState->shouldLazilyParseProperties(selectorList)) {
802 } 785 DCHECK(m_styleSheet);
786 size_t blockOffset = stream.previousOffset();
787 stream.skipBlock();
788 return StyleRule::createLazy(std::move(selectorList),
789 m_lazyState->createLazyParser(blockOffset));
790 }
803 791
804 StyleRule* CSSParserImpl::consumeStyleRule(CSSParserTokenRange prelude, 792 CSSParserTokenStream block(stream, CSSParserTokenStream::MakeSubStream);
805 CSSParserTokenRange block) {
806 CSSSelectorList selectorList =
807 CSSSelectorParser::parseSelector(prelude, m_context, m_styleSheet);
808 if (!selectorList.isValid())
809 return nullptr; // Parse error, invalid selector list
810
811 // TODO(csharrison): How should we lazily parse css that needs the observer?
812 if (m_observerWrapper) {
813 observeSelectors(*m_observerWrapper, prelude);
814 } else if (m_lazyState &&
815 m_lazyState->shouldLazilyParseProperties(selectorList, block)) {
816 DCHECK(m_styleSheet);
817 return StyleRule::createLazy(std::move(selectorList),
818 m_lazyState->createLazyParser(block));
819 }
820 consumeDeclarationList(block, StyleRule::Style); 793 consumeDeclarationList(block, StyleRule::Style);
821 794
822 return StyleRule::create( 795 return StyleRule::create(
823 std::move(selectorList), 796 std::move(selectorList),
824 createStylePropertySet(m_parsedProperties, m_context.mode())); 797 createStylePropertySet(m_parsedProperties, m_context.mode()));
825 } 798 }
826 799
827 void CSSParserImpl::consumeDeclarationList(CSSParserTokenRange range, 800 void CSSParserImpl::consumeDeclarationListForAtApply(
828 StyleRule::RuleType ruleType) { 801 CSSParserTokenRange range) {
829 ASSERT(m_parsedProperties.isEmpty()); 802 DCHECK(m_parsedProperties.isEmpty());
830 803 DCHECK(RuntimeEnabledFeatures::cssApplyAtRulesEnabled());
831 bool useObserver = m_observerWrapper && (ruleType == StyleRule::Style || 804 DCHECK(!m_observer);
832 ruleType == StyleRule::Keyframe);
833 if (useObserver) {
834 m_observerWrapper->observer().startRuleBody(
835 m_observerWrapper->previousTokenStartOffset(range));
836 m_observerWrapper->skipCommentsBefore(range, true);
837 }
838
839 while (!range.atEnd()) { 805 while (!range.atEnd()) {
840 switch (range.peek().type()) { 806 switch (range.peek().type()) {
841 case WhitespaceToken: 807 case WhitespaceToken:
842 case SemicolonToken: 808 case SemicolonToken:
843 range.consume(); 809 range.consume();
844 break; 810 break;
845 case IdentToken: { 811 case IdentToken: {
846 const CSSParserToken* declarationStart = &range.peek(); 812 const CSSParserToken* declarationStart = &range.peek();
847
848 if (useObserver)
849 m_observerWrapper->yieldCommentsBefore(range);
850
851 while (!range.atEnd() && range.peek().type() != SemicolonToken) 813 while (!range.atEnd() && range.peek().type() != SemicolonToken)
852 range.consumeComponentValue(); 814 range.consumeComponentValue();
815 consumeDeclaration(range.makeSubRange(declarationStart, &range.peek()),
816 StyleRule::Style, 0, 0);
817 break;
818 }
819 case AtKeywordToken:
820 range.consume();
821 while (!range.atEnd() && range.peek().type() != LeftBraceToken &&
822 range.peek().type() != SemicolonToken)
823 range.consumeComponentValue();
824 range.consumeComponentValue();
825 break;
826 default: // Parse error, unexpected token in declaration list
827 while (!range.atEnd() && range.peek().type() != SemicolonToken)
828 range.consumeComponentValue();
829 break;
830 }
831 }
832 }
853 833
854 consumeDeclaration(range.makeSubRange(declarationStart, &range.peek()), 834 void CSSParserImpl::consumeDeclarationList(CSSParserTokenStream& stream,
855 ruleType); 835 StyleRule::RuleType ruleType) {
836 DCHECK(m_parsedProperties.isEmpty());
856 837
857 if (useObserver) 838 bool useObserver = m_observer && (ruleType == StyleRule::Style ||
858 m_observerWrapper->skipCommentsBefore(range, false); 839 ruleType == StyleRule::Keyframe);
840 if (useObserver)
841 m_observer->startRuleBody(stream.offset() ? stream.offset() - 1 : 0);
842
843 while (true) {
844 if (useObserver)
845 stream.yieldComments(*m_observer);
846 size_t declarationStartOffset = stream.offset();
847 if (stream.atEnd())
848 break;
849 switch (stream.peek().type()) {
850 case WhitespaceToken:
851 case SemicolonToken:
852 stream.consume();
853 break;
854 case IdentToken: {
855 consumeDeclaration(stream, ruleType, declarationStartOffset);
856 if (!stream.atEnd())
857 stream.consume();
859 break; 858 break;
860 } 859 }
861 case AtKeywordToken: { 860 case AtKeywordToken: {
862 AllowedRulesType allowedRules = 861 AllowedRulesType allowedRules =
863 ruleType == StyleRule::Style && 862 ruleType == StyleRule::Style &&
864 RuntimeEnabledFeatures::cssApplyAtRulesEnabled() 863 RuntimeEnabledFeatures::cssApplyAtRulesEnabled()
865 ? ApplyRules 864 ? ApplyRules
866 : NoRules; 865 : NoRules;
867 StyleRuleBase* rule = consumeAtRule(range, allowedRules); 866 StyleRuleBase* rule = consumeAtRule(stream, allowedRules);
868 DCHECK(!rule); 867 DCHECK(!rule);
869 break; 868 break;
870 } 869 }
871 default: // Parse error, unexpected token in declaration list 870 default: // Parse error, unexpected token in declaration list
872 while (!range.atEnd() && range.peek().type() != SemicolonToken) 871 stream.consumeUntilAtEndOrPeekedTypeIs<SemicolonToken>();
873 range.consumeComponentValue(); 872 if (!stream.atEnd())
873 stream.consume();
874 break; 874 break;
875 } 875 }
876 } 876 }
877 877
878 // Yield remaining comments 878 if (useObserver)
879 if (useObserver) { 879 m_observer->endRuleBody(stream.offset());
880 m_observerWrapper->yieldCommentsBefore(range); 880 }
881 m_observerWrapper->observer().endRuleBody( 881
882 m_observerWrapper->endOffset(range)); 882 void CSSParserImpl::consumeDeclaration(CSSParserTokenStream& stream,
883 } 883 StyleRule::RuleType ruleType,
884 size_t declarationStartOffset) {
885 DCHECK_EQ(stream.peek().type(), IdentToken);
886 size_t startIndex = stream.index();
887 stream.consume();
888 stream.consumeUntilAtEndOrPeekedTypeIs<SemicolonToken>();
889 consumeDeclaration(stream.makeSubRangeFrom(startIndex), ruleType,
890 declarationStartOffset, stream.previousOffset());
891 stream.clean();
884 } 892 }
885 893
886 void CSSParserImpl::consumeDeclaration(CSSParserTokenRange range, 894 void CSSParserImpl::consumeDeclaration(CSSParserTokenRange range,
887 StyleRule::RuleType ruleType) { 895 StyleRule::RuleType ruleType,
888 CSSParserTokenRange rangeCopy = range; // For inspector callbacks 896 size_t declarationStartOffset,
889 897 size_t declarationEndOffset) {
890 ASSERT(range.peek().type() == IdentToken); 898 ASSERT(range.peek().type() == IdentToken);
891 const CSSParserToken& token = range.consumeIncludingWhitespace(); 899 const CSSParserToken& token = range.consumeIncludingWhitespace();
892 CSSPropertyID unresolvedProperty = token.parseAsUnresolvedCSSPropertyID(); 900 CSSPropertyID unresolvedProperty = token.parseAsUnresolvedCSSPropertyID();
893 if (range.consume().type() != ColonToken) 901 if (range.consume().type() != ColonToken)
894 return; // Parse error 902 return; // Parse error
895 903
896 bool important = false; 904 bool important = false;
897 const CSSParserToken* declarationValueEnd = range.end(); 905 const CSSParserToken* declarationValueEnd = range.end();
898 const CSSParserToken* last = range.end() - 1; 906 const CSSParserToken* last = range.end() - 1;
899 while (last->type() == WhitespaceToken) 907 while (last->type() == WhitespaceToken)
(...skipping 24 matching lines...) Expand all
924 variableName, important, isAnimationTainted); 932 variableName, important, isAnimationTainted);
925 } else if (unresolvedProperty != CSSPropertyInvalid) { 933 } else if (unresolvedProperty != CSSPropertyInvalid) {
926 if (m_styleSheet && m_styleSheet->singleOwnerDocument()) 934 if (m_styleSheet && m_styleSheet->singleOwnerDocument())
927 Deprecation::warnOnDeprecatedProperties( 935 Deprecation::warnOnDeprecatedProperties(
928 m_styleSheet->singleOwnerDocument()->frame(), unresolvedProperty); 936 m_styleSheet->singleOwnerDocument()->frame(), unresolvedProperty);
929 consumeDeclarationValue( 937 consumeDeclarationValue(
930 range.makeSubRange(&range.peek(), declarationValueEnd), 938 range.makeSubRange(&range.peek(), declarationValueEnd),
931 unresolvedProperty, important, ruleType); 939 unresolvedProperty, important, ruleType);
932 } 940 }
933 941
934 if (m_observerWrapper && 942 if (m_observer &&
935 (ruleType == StyleRule::Style || ruleType == StyleRule::Keyframe)) { 943 (ruleType == StyleRule::Style || ruleType == StyleRule::Keyframe)) {
936 m_observerWrapper->observer().observeProperty( 944 m_observer->observeProperty(declarationStartOffset, declarationEndOffset,
937 m_observerWrapper->startOffset(rangeCopy), 945 important,
938 m_observerWrapper->endOffset(rangeCopy), important, 946 m_parsedProperties.size() != propertiesCount);
939 m_parsedProperties.size() != propertiesCount);
940 } 947 }
941 } 948 }
942 949
943 void CSSParserImpl::consumeVariableValue(CSSParserTokenRange range, 950 void CSSParserImpl::consumeVariableValue(CSSParserTokenRange range,
944 const AtomicString& variableName, 951 const AtomicString& variableName,
945 bool important, 952 bool important,
946 bool isAnimationTainted) { 953 bool isAnimationTainted) {
947 if (CSSCustomPropertyDeclaration* value = 954 if (CSSCustomPropertyDeclaration* value =
948 CSSVariableParser::parseDeclarationValue(variableName, range, 955 CSSVariableParser::parseDeclarationValue(variableName, range,
949 isAnimationTainted)) 956 isAnimationTainted))
(...skipping 27 matching lines...) Expand all
977 else 984 else
978 return nullptr; // Parser error, invalid value in keyframe selector 985 return nullptr; // Parser error, invalid value in keyframe selector
979 if (range.atEnd()) 986 if (range.atEnd())
980 return result; 987 return result;
981 if (range.consume().type() != CommaToken) 988 if (range.consume().type() != CommaToken)
982 return nullptr; // Parser error 989 return nullptr; // Parser error
983 } 990 }
984 } 991 }
985 992
986 } // namespace blink 993 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698