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

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

Issue 2315923002: Lazy Parse CSS (Closed)
Patch Set: plug leaks Created 4 years, 3 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"
(...skipping 16 matching lines...) Expand all
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698