Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "core/css/parser/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" |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 27 #include "core/dom/Element.h" | 27 #include "core/dom/Element.h" |
| 28 #include "core/frame/Deprecation.h" | 28 #include "core/frame/Deprecation.h" |
| 29 #include "core/frame/UseCounter.h" | 29 #include "core/frame/UseCounter.h" |
| 30 #include "platform/TraceEvent.h" | 30 #include "platform/TraceEvent.h" |
| 31 #include "wtf/PtrUtil.h" | 31 #include "wtf/PtrUtil.h" |
| 32 #include <bitset> | 32 #include <bitset> |
| 33 #include <memory> | 33 #include <memory> |
| 34 | 34 |
| 35 namespace blink { | 35 namespace blink { |
| 36 | 36 |
| 37 CSSParserImpl::CSSParserImpl(const CSSParserContext& context, StyleSheetContents * styleSheet) | 37 CSSParserImpl::CSSParserImpl(const CSSParserContext& context, StyleSheetContents * styleSheet, bool deferPropertyParsing) |
| 38 : m_context(context) | 38 : m_context(context) |
| 39 , m_styleSheet(styleSheet) | 39 , m_styleSheet(styleSheet) |
| 40 , m_observerWrapper(nullptr) | 40 , m_observerWrapper(nullptr) |
| 41 , m_deferPropertyParsing(deferPropertyParsing) | |
| 41 { | 42 { |
| 42 } | 43 } |
| 43 | 44 |
| 44 bool CSSParserImpl::parseValue(MutableStylePropertySet* declaration, CSSProperty ID unresolvedProperty, const String& string, bool important, const CSSParserCont ext& context) | 45 bool CSSParserImpl::parseValue(MutableStylePropertySet* declaration, CSSProperty ID unresolvedProperty, const String& string, bool important, const CSSParserCont ext& context) |
| 45 { | 46 { |
| 46 CSSParserImpl parser(context); | 47 CSSParserImpl parser(context); |
| 47 StyleRule::RuleType ruleType = StyleRule::Style; | 48 StyleRule::RuleType ruleType = StyleRule::Style; |
| 48 if (declaration->cssParserMode() == CSSViewportRuleMode) | 49 if (declaration->cssParserMode() == CSSViewportRuleMode) |
| 49 ruleType = StyleRule::Viewport; | 50 ruleType = StyleRule::Viewport; |
| 50 CSSTokenizer::Scope scope(string); | 51 CSSTokenizer::Scope scope(string); |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 152 else | 153 else |
| 153 rule = parser.consumeQualifiedRule(range, allowedRules); | 154 rule = parser.consumeQualifiedRule(range, allowedRules); |
| 154 if (!rule) | 155 if (!rule) |
| 155 return nullptr; // Parse error, failed to consume rule | 156 return nullptr; // Parse error, failed to consume rule |
| 156 range.consumeWhitespace(); | 157 range.consumeWhitespace(); |
| 157 if (!rule || !range.atEnd()) | 158 if (!rule || !range.atEnd()) |
| 158 return nullptr; // Parse error, trailing garbage | 159 return nullptr; // Parse error, trailing garbage |
| 159 return rule; | 160 return rule; |
| 160 } | 161 } |
| 161 | 162 |
| 162 void CSSParserImpl::parseStyleSheet(const String& string, const CSSParserContext & context, StyleSheetContents* styleSheet) | 163 void CSSParserImpl::parseStyleSheet(const String& string, const CSSParserContext & context, StyleSheetContents* styleSheet, bool deferPropertyParsing) |
| 163 { | 164 { |
| 164 TRACE_EVENT_BEGIN2( | 165 TRACE_EVENT_BEGIN2( |
| 165 "blink,blink_style", "CSSParserImpl::parseStyleSheet", | 166 "blink,blink_style", "CSSParserImpl::parseStyleSheet", |
| 166 "baseUrl", context.baseURL().getString().utf8(), | 167 "baseUrl", context.baseURL().getString().utf8(), |
| 167 "mode", context.mode()); | 168 "mode", context.mode()); |
| 168 | 169 |
| 169 TRACE_EVENT_BEGIN0("blink,blink_style", "CSSParserImpl::parseStyleSheet.toke nize"); | 170 TRACE_EVENT_BEGIN0("blink,blink_style", "CSSParserImpl::parseStyleSheet.toke nize"); |
| 170 CSSTokenizer::Scope scope(string); | 171 CSSTokenizer::Scope scope(string); |
| 171 TRACE_EVENT_END0("blink,blink_style", "CSSParserImpl::parseStyleSheet.tokeni ze"); | 172 TRACE_EVENT_END0("blink,blink_style", "CSSParserImpl::parseStyleSheet.tokeni ze"); |
| 172 | 173 |
| 173 TRACE_EVENT_BEGIN0("blink,blink_style", "CSSParserImpl::parseStyleSheet.pars e"); | 174 TRACE_EVENT_BEGIN0("blink,blink_style", "CSSParserImpl::parseStyleSheet.pars e"); |
| 174 CSSParserImpl parser(context, styleSheet); | 175 CSSParserImpl parser(context, styleSheet, deferPropertyParsing); |
| 175 bool firstRuleValid = parser.consumeRuleList(scope.tokenRange(), TopLevelRul eList, [&styleSheet](StyleRuleBase* rule) { | 176 bool firstRuleValid = parser.consumeRuleList(scope.tokenRange(), TopLevelRul eList, [&styleSheet](StyleRuleBase* rule) { |
| 176 if (rule->isCharsetRule()) | 177 if (rule->isCharsetRule()) |
| 177 return; | 178 return; |
| 178 styleSheet->parserAppendRule(rule); | 179 styleSheet->parserAppendRule(rule); |
| 179 }); | 180 }); |
| 180 styleSheet->setHasSyntacticallyValidCSSHeader(firstRuleValid); | 181 styleSheet->setHasSyntacticallyValidCSSHeader(firstRuleValid); |
| 182 | |
| 183 // For lazy parsing the owning contents requires ownership of strings the | |
| 184 // scope allocates. | |
| 185 if (deferPropertyParsing) | |
| 186 styleSheet->takeEscapedStrings(scope.releaseEscapedStrings()); | |
| 187 | |
| 181 TRACE_EVENT_END0("blink,blink_style", "CSSParserImpl::parseStyleSheet.parse" ); | 188 TRACE_EVENT_END0("blink,blink_style", "CSSParserImpl::parseStyleSheet.parse" ); |
| 182 | 189 |
| 183 TRACE_EVENT_END2( | 190 TRACE_EVENT_END2( |
| 184 "blink,blink_style", "CSSParserImpl::parseStyleSheet", | 191 "blink,blink_style", "CSSParserImpl::parseStyleSheet", |
| 185 "tokenCount", scope.tokenCount(), | 192 "tokenCount", scope.tokenCount(), |
| 186 "length", string.length()); | 193 "length", string.length()); |
| 187 } | 194 } |
| 188 | 195 |
| 189 CSSSelectorList CSSParserImpl::parsePageSelector(CSSParserTokenRange range, Styl eSheetContents* styleSheet) | 196 CSSSelectorList CSSParserImpl::parsePageSelector(CSSParserTokenRange range, Styl eSheetContents* styleSheet) |
| 190 { | 197 { |
| (...skipping 483 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 674 wrapper.observer().endRuleHeader(wrapper.endOffset(originalRange)); | 681 wrapper.observer().endRuleHeader(wrapper.endOffset(originalRange)); |
| 675 } | 682 } |
| 676 | 683 |
| 677 | 684 |
| 678 StyleRule* CSSParserImpl::consumeStyleRule(CSSParserTokenRange prelude, CSSParse rTokenRange block) | 685 StyleRule* CSSParserImpl::consumeStyleRule(CSSParserTokenRange prelude, CSSParse rTokenRange block) |
| 679 { | 686 { |
| 680 CSSSelectorList selectorList = CSSSelectorParser::parseSelector(prelude, m_c ontext, m_styleSheet); | 687 CSSSelectorList selectorList = CSSSelectorParser::parseSelector(prelude, m_c ontext, m_styleSheet); |
| 681 if (!selectorList.isValid()) | 688 if (!selectorList.isValid()) |
| 682 return nullptr; // Parse error, invalid selector list | 689 return nullptr; // Parse error, invalid selector list |
| 683 | 690 |
| 684 if (m_observerWrapper) | 691 // TODO(csharrison): How should we lazily parse css that needs the observer? |
| 692 if (m_observerWrapper) { | |
| 685 observeSelectors(*m_observerWrapper, prelude); | 693 observeSelectors(*m_observerWrapper, prelude); |
| 694 } else if (m_deferPropertyParsing) { | |
| 695 DCHECK(m_styleSheet); | |
| 696 bool forceStrict = false; | |
| 697 StyleRule* rule = StyleRule::createLazy(std::move(selectorList), createD eferredPropertiesClosure(block, m_context, &forceStrict)); | |
| 698 if (forceStrict) | |
| 699 rule->properties(); | |
| 700 return rule; | |
| 701 } | |
| 686 | 702 |
| 687 consumeDeclarationList(block, StyleRule::Style); | 703 consumeDeclarationList(block, StyleRule::Style); |
| 688 | |
| 689 return StyleRule::create(std::move(selectorList), createStylePropertySet(m_p arsedProperties, m_context.mode())); | 704 return StyleRule::create(std::move(selectorList), createStylePropertySet(m_p arsedProperties, m_context.mode())); |
| 690 } | 705 } |
| 691 | 706 |
| 692 void CSSParserImpl::consumeDeclarationList(CSSParserTokenRange range, StyleRule: :RuleType ruleType) | 707 void CSSParserImpl::consumeDeclarationList(CSSParserTokenRange range, StyleRule: :RuleType ruleType) |
| 693 { | 708 { |
| 694 ASSERT(m_parsedProperties.isEmpty()); | 709 ASSERT(m_parsedProperties.isEmpty()); |
| 695 | 710 |
| 696 bool useObserver = m_observerWrapper && (ruleType == StyleRule::Style || rul eType == StyleRule::Keyframe); | 711 bool useObserver = m_observerWrapper && (ruleType == StyleRule::Style || rul eType == StyleRule::Keyframe); |
| 697 if (useObserver) { | 712 if (useObserver) { |
| 698 m_observerWrapper->observer().startRuleBody(m_observerWrapper->previousT okenStartOffset(range)); | 713 m_observerWrapper->observer().startRuleBody(m_observerWrapper->previousT okenStartOffset(range)); |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 813 result->append(1); | 828 result->append(1); |
| 814 else | 829 else |
| 815 return nullptr; // Parser error, invalid value in keyframe selector | 830 return nullptr; // Parser error, invalid value in keyframe selector |
| 816 if (range.atEnd()) | 831 if (range.atEnd()) |
| 817 return result; | 832 return result; |
| 818 if (range.consume().type() != CommaToken) | 833 if (range.consume().type() != CommaToken) |
| 819 return nullptr; // Parser error | 834 return nullptr; // Parser error |
| 820 } | 835 } |
| 821 } | 836 } |
| 822 | 837 |
| 838 // The closure created here must not outlive the underlying StyleSheetContents, | |
| 839 // as it has non retaining references to the strings backing the tokens, as | |
| 840 // well as the parser context. | |
| 841 // Sets forceStrict to true if we should bail out on lazy parsing. This occurs | |
| 842 // for: | |
| 843 // - attr() functions (which require invalidation set propogation) | |
| 844 // - Empty property sets (so that emptiness can be established without forcing | |
| 845 // a strict point in general. | |
| 846 std::unique_ptr<CSSParser::DeferredPropertiesClosure> CSSParserImpl::createDefer redPropertiesClosure(CSSParserTokenRange block, const CSSParserContext& context, bool* forceStrict) | |
| 847 { | |
| 848 // TODO(csharrison): A slightly more complex design could have the | |
| 849 // StyleSheetContents own the tokens. This would mean we don't have to copy | |
| 850 // them to a local vector here. | |
| 851 size_t length = block.end() - block.begin(); | |
| 852 std::unique_ptr<Vector<CSSParserToken>> tokens = WTF::wrapUnique(new Vector< CSSParserToken>); | |
| 853 tokens->reserveInitialCapacity(length); | |
| 854 while (!block.atEnd()) { | |
| 855 const CSSParserToken& token = block.consume(); | |
| 856 if (token.type() == CSSParserTokenType::FunctionToken && token.value() = = "attr") { | |
|
Timothy Loh
2016/09/26 05:18:00
I think attr is case insensitive.
Charlie Harrison
2016/09/26 22:14:45
I've moved the check to checking "before/after" in
| |
| 857 *forceStrict = true; | |
| 858 } | |
| 859 tokens->append(token); | |
|
Timothy Loh
2016/09/26 05:18:01
Probably nicer to use Vector::append(const U*, siz
Charlie Harrison
2016/09/26 22:14:45
Cool :) Done.
| |
| 860 } | |
| 861 if (tokens->isEmpty()) | |
| 862 *forceStrict = true; | |
| 863 | |
| 864 return WTF::bind(&CSSParserImpl::parseDeclarationListForLazyStyle, WTF::pass ed(std::move(tokens)), WTF::unretained(&context)); | |
| 865 } | |
| 866 | |
| 867 StylePropertySet* CSSParserImpl::parseDeclarationListForLazyStyle(std::unique_pt r<Vector<CSSParserToken>> block, const CSSParserContext* context) | |
| 868 { | |
| 869 CSSParserImpl parser(*context); | |
| 870 parser.consumeDeclarationList(*block, StyleRule::Style); | |
| 871 return createStylePropertySet(parser.m_parsedProperties, context->mode()); | |
| 872 } | |
| 873 | |
| 874 | |
| 823 } // namespace blink | 875 } // namespace blink |
| OLD | NEW |