| Index: third_party/WebKit/Source/core/css/parser/CSSParserImpl.cpp
|
| diff --git a/third_party/WebKit/Source/core/css/parser/CSSParserImpl.cpp b/third_party/WebKit/Source/core/css/parser/CSSParserImpl.cpp
|
| index f5bd2e8b8f5f2e1f04e700fea4bbf5833d8ffc5c..a851196dd229bbedb4ea7c2b0e7d5f5dc557b9c6 100644
|
| --- a/third_party/WebKit/Source/core/css/parser/CSSParserImpl.cpp
|
| +++ b/third_party/WebKit/Source/core/css/parser/CSSParserImpl.cpp
|
| @@ -34,10 +34,11 @@
|
|
|
| namespace blink {
|
|
|
| -CSSParserImpl::CSSParserImpl(const CSSParserContext& context, StyleSheetContents* styleSheet)
|
| -: m_context(context)
|
| -, m_styleSheet(styleSheet)
|
| -, m_observerWrapper(nullptr)
|
| +CSSParserImpl::CSSParserImpl(const CSSParserContext& context, StyleSheetContents* styleSheet, bool deferPropertyParsing)
|
| + : m_context(context)
|
| + , m_styleSheet(styleSheet)
|
| + , m_observerWrapper(nullptr)
|
| + , m_deferPropertyParsing(deferPropertyParsing)
|
| {
|
| }
|
|
|
| @@ -159,7 +160,7 @@ StyleRuleBase* CSSParserImpl::parseRule(const String& string, const CSSParserCon
|
| return rule;
|
| }
|
|
|
| -void CSSParserImpl::parseStyleSheet(const String& string, const CSSParserContext& context, StyleSheetContents* styleSheet)
|
| +void CSSParserImpl::parseStyleSheet(const String& string, const CSSParserContext& context, StyleSheetContents* styleSheet, bool deferPropertyParsing)
|
| {
|
| TRACE_EVENT_BEGIN2(
|
| "blink,blink_style", "CSSParserImpl::parseStyleSheet",
|
| @@ -171,13 +172,19 @@ void CSSParserImpl::parseStyleSheet(const String& string, const CSSParserContext
|
| TRACE_EVENT_END0("blink,blink_style", "CSSParserImpl::parseStyleSheet.tokenize");
|
|
|
| TRACE_EVENT_BEGIN0("blink,blink_style", "CSSParserImpl::parseStyleSheet.parse");
|
| - CSSParserImpl parser(context, styleSheet);
|
| + CSSParserImpl parser(context, styleSheet, deferPropertyParsing);
|
| bool firstRuleValid = parser.consumeRuleList(scope.tokenRange(), TopLevelRuleList, [&styleSheet](StyleRuleBase* rule) {
|
| if (rule->isCharsetRule())
|
| return;
|
| styleSheet->parserAppendRule(rule);
|
| });
|
| styleSheet->setHasSyntacticallyValidCSSHeader(firstRuleValid);
|
| +
|
| + // For lazy parsing the owning contents requires ownership of strings the
|
| + // scope allocates.
|
| + if (deferPropertyParsing)
|
| + styleSheet->takeEscapedStrings(scope.releaseEscapedStrings());
|
| +
|
| TRACE_EVENT_END0("blink,blink_style", "CSSParserImpl::parseStyleSheet.parse");
|
|
|
| TRACE_EVENT_END2(
|
| @@ -674,18 +681,20 @@ static void observeSelectors(CSSParserObserverWrapper& wrapper, CSSParserTokenRa
|
| wrapper.observer().endRuleHeader(wrapper.endOffset(originalRange));
|
| }
|
|
|
| -
|
| StyleRule* CSSParserImpl::consumeStyleRule(CSSParserTokenRange prelude, CSSParserTokenRange block)
|
| {
|
| CSSSelectorList selectorList = CSSSelectorParser::parseSelector(prelude, m_context, m_styleSheet);
|
| if (!selectorList.isValid())
|
| return nullptr; // Parse error, invalid selector list
|
|
|
| - if (m_observerWrapper)
|
| + // TODO(csharrison): How should we lazily parse css that needs the observer?
|
| + if (m_observerWrapper) {
|
| observeSelectors(*m_observerWrapper, prelude);
|
| -
|
| + } else if (m_deferPropertyParsing && shouldLazilyParseProperties(selectorList)) {
|
| + DCHECK(m_styleSheet);
|
| + return StyleRule::createLazy(std::move(selectorList), createDeferredPropertiesClosure(block, m_styleSheet->parserContext(), m_context.useCounter()));
|
| + }
|
| consumeDeclarationList(block, StyleRule::Style);
|
| -
|
| return StyleRule::create(std::move(selectorList), createStylePropertySet(m_parsedProperties, m_context.mode()));
|
| }
|
|
|
| @@ -820,4 +829,50 @@ std::unique_ptr<Vector<double>> CSSParserImpl::consumeKeyframeKeyList(CSSParserT
|
| }
|
| }
|
|
|
| +// The closure created here must not outlive the underlying StyleSheetContents,
|
| +// as it has non retaining references to the strings backing the tokens, as
|
| +// well as the parser context.
|
| +std::unique_ptr<DeferredPropertiesClosure> CSSParserImpl::createDeferredPropertiesClosure(CSSParserTokenRange block, const CSSParserContext& sheetContext, UseCounter* counter)
|
| +{
|
| + // Note: there may be optimizations to be had in allocating so many Vectors
|
| + // to store the token copies. One idea is to allocate a large Vector in
|
| + // parseStyleSheet and immediately free it, so we don't go through the slow
|
| + // path in PartitionAlloc.
|
| + Vector<CSSParserToken, 0u> tokens;
|
| +
|
| + // Reserve capacity to minimize heap bloat.
|
| + size_t length = block.end() - block.begin();
|
| + tokens.reserveCapacity(length);
|
| + tokens.append(block.begin(), length);
|
| +
|
| + return WTF::bind(&CSSParserImpl::parseDeclarationListForLazyStyle, WTF::passed(std::move(tokens)), WTF::unretained(&sheetContext), WTF::unretained(counter));
|
| +}
|
| +
|
| +StylePropertySet* CSSParserImpl::parseDeclarationListForLazyStyle(Vector<CSSParserToken> block, const CSSParserContext* sheetContext, UseCounter* counter)
|
| +{
|
| + CSSParserContext context(*sheetContext, counter);
|
| + CSSParserImpl parser(context);
|
| + parser.consumeDeclarationList(block, StyleRule::Style);
|
| + return createStylePropertySet(parser.m_parsedProperties, context.mode());
|
| +}
|
| +
|
| +// Disallow lazy parsing for blocks which have
|
| +// - before/after in their selector list. This ensures we don't cause a
|
| +// collectFeatures() when we trigger parsing for attr() functions which would
|
| +// trigger expensive invalidation propagation.
|
| +//
|
| +// Note: another optimization might be to disallow lazy parsing for rules which
|
| +// will end up being empty. This is hard to know without parsing but we may be
|
| +// able to catch the {}, { } cases. This would be to hit
|
| +// StyleRule::shouldConsiderForMatchingRules more.
|
| +bool CSSParserImpl::shouldLazilyParseProperties(const CSSSelectorList& selectors)
|
| +{
|
| + for (const auto* s = selectors.first(); s; s = CSSSelectorList::next(*s)) {
|
| + const CSSSelector::PseudoType type(s->getPseudoType());
|
| + if (type == CSSSelector::PseudoBefore || type == CSSSelector::PseudoAfter)
|
| + return false;
|
| + }
|
| + return true;
|
| +}
|
| +
|
| } // namespace blink
|
|
|