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

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

Issue 1645433002: Basic implementation of @apply (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: fix expted.txt for failing test Created 4 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
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/CSSCustomPropertyDeclaration.h" 8 #include "core/css/CSSCustomPropertyDeclaration.h"
8 #include "core/css/CSSKeyframesRule.h" 9 #include "core/css/CSSKeyframesRule.h"
9 #include "core/css/CSSStyleSheet.h" 10 #include "core/css/CSSStyleSheet.h"
10 #include "core/css/StylePropertySet.h" 11 #include "core/css/StylePropertySet.h"
11 #include "core/css/StyleRuleImport.h" 12 #include "core/css/StyleRuleImport.h"
12 #include "core/css/StyleRuleKeyframe.h" 13 #include "core/css/StyleRuleKeyframe.h"
13 #include "core/css/StyleRuleNamespace.h" 14 #include "core/css/StyleRuleNamespace.h"
14 #include "core/css/StyleSheetContents.h" 15 #include "core/css/StyleSheetContents.h"
15 #include "core/css/parser/CSSAtRuleID.h" 16 #include "core/css/parser/CSSAtRuleID.h"
16 #include "core/css/parser/CSSParserObserver.h" 17 #include "core/css/parser/CSSParserObserver.h"
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
68 const CSSProperty& property = input[i]; 69 const CSSProperty& property = input[i];
69 if (property.isImportant() != important) 70 if (property.isImportant() != important)
70 continue; 71 continue;
71 const unsigned propertyIDIndex = property.id() - firstCSSProperty; 72 const unsigned propertyIDIndex = property.id() - firstCSSProperty;
72 73
73 if (property.id() == CSSPropertyVariable) { 74 if (property.id() == CSSPropertyVariable) {
74 const AtomicString& name = toCSSCustomPropertyDeclaration(property.v alue())->name(); 75 const AtomicString& name = toCSSCustomPropertyDeclaration(property.v alue())->name();
75 if (seenCustomProperties.contains(name)) 76 if (seenCustomProperties.contains(name))
76 continue; 77 continue;
77 seenCustomProperties.add(name); 78 seenCustomProperties.add(name);
79 } else if (property.id() == CSSPropertyApplyAtRule) {
80 // TODO(timloh): Do we need to do anything here?
78 } else { 81 } else {
79 if (seenProperties.get(propertyIDIndex)) 82 if (seenProperties.get(propertyIDIndex))
80 continue; 83 continue;
81 seenProperties.set(propertyIDIndex); 84 seenProperties.set(propertyIDIndex);
82 } 85 }
83 output[--unusedEntries] = property; 86 output[--unusedEntries] = property;
84 } 87 }
85 } 88 }
86 89
87 static PassRefPtrWillBeRawPtr<ImmutableStylePropertySet> createStylePropertySet( WillBeHeapVector<CSSProperty, 256>& parsedProperties, CSSParserMode mode) 90 static PassRefPtrWillBeRawPtr<ImmutableStylePropertySet> createStylePropertySet( WillBeHeapVector<CSSProperty, 256>& parsedProperties, CSSParserMode mode)
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after
217 } 220 }
218 } 221 }
219 222
220 selector->setForPage(); 223 selector->setForPage();
221 Vector<OwnPtr<CSSParserSelector>> selectorVector; 224 Vector<OwnPtr<CSSParserSelector>> selectorVector;
222 selectorVector.append(selector.release()); 225 selectorVector.append(selector.release());
223 CSSSelectorList selectorList = CSSSelectorList::adoptSelectorVector(selector Vector); 226 CSSSelectorList selectorList = CSSSelectorList::adoptSelectorVector(selector Vector);
224 return selectorList; 227 return selectorList;
225 } 228 }
226 229
230 PassRefPtrWillBeRawPtr<ImmutableStylePropertySet> CSSParserImpl::parseCustomProp ertySet(CSSParserTokenRange range)
231 {
232 range.consumeWhitespace();
233 if (range.peek().type() != LeftBraceToken)
234 return nullptr;
235 CSSParserTokenRange block = range.consumeBlock();
236 range.consumeWhitespace();
237 if (!range.atEnd())
238 return nullptr;
239 CSSParserImpl parser(strictCSSParserContext());
240 parser.consumeDeclarationList(block, StyleRule::Style);
241
242 // Drop nested @apply rules. Seems nicer to do this here instead of making
243 // a different StyleRule type
244 for (size_t i = parser.m_parsedProperties.size(); i--; ) {
245 if (parser.m_parsedProperties[i].id() == CSSPropertyApplyAtRule)
246 parser.m_parsedProperties.remove(i);
247 }
248
249 return createStylePropertySet(parser.m_parsedProperties, HTMLStandardMode);
250 }
251
227 PassOwnPtr<Vector<double>> CSSParserImpl::parseKeyframeKeyList(const String& key List) 252 PassOwnPtr<Vector<double>> CSSParserImpl::parseKeyframeKeyList(const String& key List)
228 { 253 {
229 return consumeKeyframeKeyList(CSSTokenizer::Scope(keyList).tokenRange()); 254 return consumeKeyframeKeyList(CSSTokenizer::Scope(keyList).tokenRange());
230 } 255 }
231 256
232 bool CSSParserImpl::supportsDeclaration(CSSParserTokenRange& range) 257 bool CSSParserImpl::supportsDeclaration(CSSParserTokenRange& range)
233 { 258 {
234 ASSERT(m_parsedProperties.isEmpty()); 259 ASSERT(m_parsedProperties.isEmpty());
235 consumeDeclaration(range, StyleRule::Style); 260 consumeDeclaration(range, StyleRule::Style);
236 bool result = !m_parsedProperties.isEmpty(); 261 bool result = !m_parsedProperties.isEmpty();
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
342 countAtRule(m_context.useCounter(), id); 367 countAtRule(m_context.useCounter(), id);
343 368
344 if (range.atEnd() || range.peek().type() == SemicolonToken) { 369 if (range.atEnd() || range.peek().type() == SemicolonToken) {
345 range.consume(); 370 range.consume();
346 if (allowedRules == AllowCharsetRules && id == CSSAtRuleCharset) 371 if (allowedRules == AllowCharsetRules && id == CSSAtRuleCharset)
347 return consumeCharsetRule(prelude); 372 return consumeCharsetRule(prelude);
348 if (allowedRules <= AllowImportRules && id == CSSAtRuleImport) 373 if (allowedRules <= AllowImportRules && id == CSSAtRuleImport)
349 return consumeImportRule(prelude); 374 return consumeImportRule(prelude);
350 if (allowedRules <= AllowNamespaceRules && id == CSSAtRuleNamespace) 375 if (allowedRules <= AllowNamespaceRules && id == CSSAtRuleNamespace)
351 return consumeNamespaceRule(prelude); 376 return consumeNamespaceRule(prelude);
377 if (allowedRules == ApplyRules && id == CSSAtRuleApply) {
378 consumeApplyRule(prelude);
379 return nullptr; // consumeApplyRule just updates m_parsedProperties
380 }
352 return nullptr; // Parse error, unrecognised at-rule without block 381 return nullptr; // Parse error, unrecognised at-rule without block
353 } 382 }
354 383
355 CSSParserTokenRange block = range.consumeBlock(); 384 CSSParserTokenRange block = range.consumeBlock();
356 if (allowedRules == KeyframeRules) 385 if (allowedRules == KeyframeRules)
357 return nullptr; // Parse error, no at-rules supported inside @keyframes 386 return nullptr; // Parse error, no at-rules supported inside @keyframes
358 if (allowedRules == NoRules) 387 if (allowedRules == NoRules || allowedRules == ApplyRules)
359 return nullptr; // Parse error, no at-rules supported inside declaration lists 388 return nullptr; // Parse error, no at-rules with blocks supported inside declaration lists
360 389
361 ASSERT(allowedRules <= RegularRules); 390 ASSERT(allowedRules <= RegularRules);
362 391
363 switch (id) { 392 switch (id) {
364 case CSSAtRuleMedia: 393 case CSSAtRuleMedia:
365 return consumeMediaRule(prelude, block); 394 return consumeMediaRule(prelude, block);
366 case CSSAtRuleSupports: 395 case CSSAtRuleSupports:
367 return consumeSupportsRule(prelude, block); 396 return consumeSupportsRule(prelude, block);
368 case CSSAtRuleViewport: 397 case CSSAtRuleViewport:
369 return consumeViewportRule(prelude, block); 398 return consumeViewportRule(prelude, block);
(...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after
595 unsigned endOffset = m_observerWrapper->endOffset(prelude); 624 unsigned endOffset = m_observerWrapper->endOffset(prelude);
596 m_observerWrapper->observer().startRuleHeader(StyleRule::Page, m_observe rWrapper->startOffset(prelude)); 625 m_observerWrapper->observer().startRuleHeader(StyleRule::Page, m_observe rWrapper->startOffset(prelude));
597 m_observerWrapper->observer().endRuleHeader(endOffset); 626 m_observerWrapper->observer().endRuleHeader(endOffset);
598 } 627 }
599 628
600 consumeDeclarationList(block, StyleRule::Style); 629 consumeDeclarationList(block, StyleRule::Style);
601 630
602 return StyleRulePage::create(std::move(selectorList), createStylePropertySet (m_parsedProperties, m_context.mode())); 631 return StyleRulePage::create(std::move(selectorList), createStylePropertySet (m_parsedProperties, m_context.mode()));
603 } 632 }
604 633
634 void CSSParserImpl::consumeApplyRule(CSSParserTokenRange prelude)
635 {
636 ASSERT(RuntimeEnabledFeatures::cssApplyAtRulesEnabled());
637
638 prelude.consumeWhitespace();
639 const CSSParserToken& ident = prelude.consumeIncludingWhitespace();
640 if (!prelude.atEnd() || !CSSVariableParser::isValidVariableName(ident))
641 return; // Parse error, expected a single custom property name
642 m_parsedProperties.append(CSSProperty(
643 CSSPropertyApplyAtRule,
644 CSSCustomIdentValue::create(ident.value())));
645 }
646
605 PassRefPtrWillBeRawPtr<StyleRuleKeyframe> CSSParserImpl::consumeKeyframeStyleRul e(CSSParserTokenRange prelude, CSSParserTokenRange block) 647 PassRefPtrWillBeRawPtr<StyleRuleKeyframe> CSSParserImpl::consumeKeyframeStyleRul e(CSSParserTokenRange prelude, CSSParserTokenRange block)
606 { 648 {
607 OwnPtr<Vector<double>> keyList = consumeKeyframeKeyList(prelude); 649 OwnPtr<Vector<double>> keyList = consumeKeyframeKeyList(prelude);
608 if (!keyList) 650 if (!keyList)
609 return nullptr; 651 return nullptr;
610 652
611 if (m_observerWrapper) { 653 if (m_observerWrapper) {
612 m_observerWrapper->observer().startRuleHeader(StyleRule::Keyframe, m_obs erverWrapper->startOffset(prelude)); 654 m_observerWrapper->observer().startRuleHeader(StyleRule::Keyframe, m_obs erverWrapper->startOffset(prelude));
613 m_observerWrapper->observer().endRuleHeader(m_observerWrapper->endOffset (prelude)); 655 m_observerWrapper->observer().endRuleHeader(m_observerWrapper->endOffset (prelude));
614 } 656 }
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
677 while (!range.atEnd() && range.peek().type() != SemicolonToken) 719 while (!range.atEnd() && range.peek().type() != SemicolonToken)
678 range.consumeComponentValue(); 720 range.consumeComponentValue();
679 721
680 consumeDeclaration(range.makeSubRange(declarationStart, &range.peek( )), ruleType); 722 consumeDeclaration(range.makeSubRange(declarationStart, &range.peek( )), ruleType);
681 723
682 if (useObserver) 724 if (useObserver)
683 m_observerWrapper->skipCommentsBefore(range, false); 725 m_observerWrapper->skipCommentsBefore(range, false);
684 break; 726 break;
685 } 727 }
686 case AtKeywordToken: { 728 case AtKeywordToken: {
687 RefPtrWillBeRawPtr<StyleRuleBase> rule = consumeAtRule(range, NoRule s); 729 AllowedRulesType allowedRules = ruleType == StyleRule::Style && Runt imeEnabledFeatures::cssApplyAtRulesEnabled() ? ApplyRules : NoRules;
730 RefPtrWillBeRawPtr<StyleRuleBase> rule = consumeAtRule(range, allowe dRules);
688 ASSERT_UNUSED(rule, !rule); 731 ASSERT_UNUSED(rule, !rule);
689 break; 732 break;
690 } 733 }
691 default: // Parse error, unexpected token in declaration list 734 default: // Parse error, unexpected token in declaration list
692 while (!range.atEnd() && range.peek().type() != SemicolonToken) 735 while (!range.atEnd() && range.peek().type() != SemicolonToken)
693 range.consumeComponentValue(); 736 range.consumeComponentValue();
694 break; 737 break;
695 } 738 }
696 } 739 }
697 740
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
775 else 818 else
776 return nullptr; // Parser error, invalid value in keyframe selector 819 return nullptr; // Parser error, invalid value in keyframe selector
777 if (range.atEnd()) 820 if (range.atEnd())
778 return result.release(); 821 return result.release();
779 if (range.consume().type() != CommaToken) 822 if (range.consume().type() != CommaToken)
780 return nullptr; // Parser error 823 return nullptr; // Parser error
781 } 824 }
782 } 825 }
783 826
784 } // namespace blink 827 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698