Diff
Modified: trunk/Source/WebCore/ChangeLog (252627 => 252628)
--- trunk/Source/WebCore/ChangeLog 2019-11-19 15:26:13 UTC (rev 252627)
+++ trunk/Source/WebCore/ChangeLog 2019-11-19 15:34:28 UTC (rev 252628)
@@ -1,3 +1,80 @@
+2019-11-19 Antti Koivisto <[email protected]>
+
+ Move ElementRuleCollector to Style namespace
+ https://bugs.webkit.org/show_bug.cgi?id=204329
+
+ Reviewed by Sam Weinig.
+
+ Also move PageRuleCollector.
+
+ * Sources.txt:
+ * WebCore.xcodeproj/project.pbxproj:
+ * bindings/js/CallTracerTypes.h:
+ * css/DOMCSSRegisterCustomProperty.cpp:
+ (WebCore::DOMCSSRegisterCustomProperty::registerProperty):
+ * dom/Document.cpp:
+ (WebCore::Document::styleForElementIgnoringPendingStylesheets):
+ * html/canvas/CanvasRenderingContext2D.cpp:
+ (WebCore::CanvasRenderingContext2D::setFont):
+ * html/canvas/CanvasRenderingContext2DBase.cpp:
+ (WebCore::toStyleVariant):
+ (WebCore::CanvasRenderingContext2DBase::strokeStyle const):
+ (WebCore::CanvasRenderingContext2DBase::setStrokeStyle):
+ (WebCore::CanvasRenderingContext2DBase::fillStyle const):
+ (WebCore::CanvasRenderingContext2DBase::setFillStyle):
+
+ Rename CanvasRenderingContext2DBase::Style to StyleVariant to avoid name conflicts.
+
+ (WebCore::toStyle): Deleted.
+ * html/canvas/CanvasRenderingContext2DBase.h:
+ * inspector/InspectorCanvas.cpp:
+ (WebCore::InspectorCanvas::buildAction):
+ * page/FrameView.cpp:
+ (WebCore::FrameView::styleHidesScrollbarWithOrientation const):
+ (WebCore::FrameView::updateScrollCorner):
+ * rendering/RenderElement.cpp:
+ (WebCore::RenderElement::getCachedPseudoStyle const):
+ (WebCore::RenderElement::getUncachedPseudoStyle const):
+ (WebCore::RenderElement::selectionPseudoStyle const):
+ * rendering/RenderElement.h:
+ * rendering/RenderLayer.cpp:
+ (WebCore::RenderLayer::calculateClipRects const):
+ * rendering/RenderObject.h:
+ * rendering/RenderScrollbar.cpp:
+ (WebCore::RenderScrollbar::getScrollbarPseudoStyle const):
+ * rendering/updating/RenderTreeUpdater.cpp:
+ (WebCore::pseudoStyleCacheIsInvalid):
+ * style/ElementRuleCollector.cpp: Renamed from Source/WebCore/css/ElementRuleCollector.cpp.
+ (WebCore::Style::MatchRequest::MatchRequest):
+ (WebCore::Style::ElementRuleCollector::ElementRuleCollector):
+ (WebCore::Style::ElementRuleCollector::addMatchedRule):
+ (WebCore::Style::ElementRuleCollector::collectMatchingRules):
+ (WebCore::Style::ElementRuleCollector::transferMatchedRules):
+ (WebCore::Style::ElementRuleCollector::matchAuthorShadowPseudoElementRules):
+ (WebCore::Style::ElementRuleCollector::matchHostPseudoClassRules):
+ (WebCore::Style::ElementRuleCollector::matchSlottedPseudoElementRules):
+ (WebCore::Style::ElementRuleCollector::matchPartPseudoElementRulesForScope):
+ (WebCore::Style::ElementRuleCollector::collectSlottedPseudoElementRulesForSlot):
+ (WebCore::Style::ElementRuleCollector::matchUARules):
+ (WebCore::Style::ElementRuleCollector::ruleMatches):
+ (WebCore::Style::ElementRuleCollector::collectMatchingRulesForList):
+ (WebCore::Style::ElementRuleCollector::matchAllRules):
+ (WebCore::Style::ElementRuleCollector::hasAnyMatchingRules):
+ (WebCore::Style::ElementRuleCollector::addMatchedProperties):
+ * style/ElementRuleCollector.h: Renamed from Source/WebCore/css/ElementRuleCollector.h.
+ (WebCore::Style::PseudoElementRequest::PseudoElementRequest):
+ (WebCore::Style::ElementRuleCollector::setPseudoElementRequest):
+ (WebCore::Style::ElementRuleCollector::styleRelations const):
+ (WebCore::Style::ElementRuleCollector::transferMatchedRules):
+ * style/PageRuleCollector.cpp: Renamed from Source/WebCore/css/PageRuleCollector.cpp.
+ (WebCore::Style::PageRuleCollector::matchPageRules):
+ * style/PageRuleCollector.h: Renamed from Source/WebCore/css/PageRuleCollector.h.
+ (WebCore::Style::PageRuleCollector::PageRuleCollector):
+ * style/StyleResolver.cpp:
+ (WebCore::Style::Resolver::pseudoStyleForElement):
+ (WebCore::Style::Resolver::pseudoStyleRulesForElement):
+ * style/StyleResolver.h:
+
2019-11-19 Wenson Hsieh <[email protected]>
[Clipboard API] Add support for Clipboard.readText()
Modified: trunk/Source/WebCore/Sources.txt (252627 => 252628)
--- trunk/Source/WebCore/Sources.txt 2019-11-19 15:26:13 UTC (rev 252627)
+++ trunk/Source/WebCore/Sources.txt 2019-11-19 15:34:28 UTC (rev 252628)
@@ -755,7 +755,6 @@
css/DeprecatedCSSOMPrimitiveValue.cpp
css/DeprecatedCSSOMValue.cpp
css/DeprecatedCSSOMValueList.cpp
-css/ElementRuleCollector.cpp
css/FontVariantBuilder.cpp
css/InspectorCSSOMWrappers.cpp
css/LengthFunctions.cpp
@@ -767,7 +766,6 @@
css/MediaQueryList.cpp
css/MediaQueryMatcher.cpp
css/MediaQueryParserContext.cpp
-css/PageRuleCollector.cpp
css/PropertySetCSSStyleDeclaration.cpp
css/RGBColor.cpp
css/SVGCSSComputedStyleDeclaration.cpp
@@ -2340,9 +2338,11 @@
style/AttributeChangeInvalidation.cpp
style/ClassChangeInvalidation.cpp
+style/ElementRuleCollector.cpp
style/IdChangeInvalidation.cpp
style/InlineTextBoxStyle.cpp
style/MatchedDeclarationsCache.cpp
+style/PageRuleCollector.cpp
style/PropertyCascade.cpp
style/RuleFeature.cpp
style/RuleSet.cpp
Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (252627 => 252628)
--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj 2019-11-19 15:26:13 UTC (rev 252627)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj 2019-11-19 15:34:28 UTC (rev 252628)
@@ -27019,6 +27019,8 @@
E4ABABF42368C6EF00FA4345 /* CascadeLevel.h */,
E4A814D51C6DEE8D00BF85AC /* ClassChangeInvalidation.cpp */,
E4A814D31C6DEC4000BF85AC /* ClassChangeInvalidation.h */,
+ FBDB619A16D6032A00BB3394 /* ElementRuleCollector.cpp */,
+ FBDB619E16D6036500BB3394 /* ElementRuleCollector.h */,
E4A814DD1C7338D100BF85AC /* IdChangeInvalidation.cpp */,
E4A814DF1C7338EB00BF85AC /* IdChangeInvalidation.h */,
1C0106FE192594DF008A4201 /* InlineTextBoxStyle.cpp */,
@@ -27025,6 +27027,8 @@
1C0106FF192594DF008A4201 /* InlineTextBoxStyle.h */,
E45BA6AB2374927B004DFC07 /* MatchedDeclarationsCache.cpp */,
E45BA6A82374926B004DFC07 /* MatchedDeclarationsCache.h */,
+ FBDB619C16D6034600BB3394 /* PageRuleCollector.cpp */,
+ FBDB61A016D6037E00BB3394 /* PageRuleCollector.h */,
E4ABABE52361A34200FA4345 /* PropertyCascade.cpp */,
E4ABABE22361A32900FA4345 /* PropertyCascade.h */,
A79BAD9D161E7F3F00C2E652 /* RuleFeature.cpp */,
@@ -27388,8 +27392,6 @@
836ACEC01ECA62B0004BD012 /* DOMMatrixReadOnly.h */,
836ACEC11ECA62B0004BD012 /* DOMMatrixReadOnly.idl */,
837DFB341EBFEA7000601385 /* ElementCSSInlineStyle.idl */,
- FBDB619A16D6032A00BB3394 /* ElementRuleCollector.cpp */,
- FBDB619E16D6036500BB3394 /* ElementRuleCollector.h */,
1C66260E1C6E7CA600AB527C /* FontFace.cpp */,
1C66260F1C6E7CA600AB527C /* FontFace.h */,
C280833C1C6DB194001451B6 /* FontFace.idl */,
@@ -27432,8 +27434,6 @@
D3AA10F2123A98AA0092152B /* MediaQueryMatcher.h */,
4471710B205AF945000A116E /* MediaQueryParserContext.cpp */,
4471710C205AF945000A116E /* MediaQueryParserContext.h */,
- FBDB619C16D6034600BB3394 /* PageRuleCollector.cpp */,
- FBDB61A016D6037E00BB3394 /* PageRuleCollector.h */,
A80E6CD10A1989CA007FB8C5 /* Pair.h */,
3189E6DB16B2103500386EA3 /* plugIns.css */,
E4BBED0C14F4025D003F0B98 /* PropertySetCSSStyleDeclaration.cpp */,
Modified: trunk/Source/WebCore/bindings/js/CallTracerTypes.h (252627 => 252628)
--- trunk/Source/WebCore/bindings/js/CallTracerTypes.h 2019-11-19 15:26:13 UTC (rev 252627)
+++ trunk/Source/WebCore/bindings/js/CallTracerTypes.h 2019-11-19 15:34:28 UTC (rev 252628)
@@ -122,7 +122,7 @@
// variant
CanvasImageSource,
- CanvasRenderingContext2DBase::Style,
+ CanvasRenderingContext2DBase::StyleVariant,
#if ENABLE(WEBGL)
WebGLRenderingContextBase::BufferDataSource,
Optional<WebGLRenderingContextBase::BufferDataSource>,
Modified: trunk/Source/WebCore/css/DOMCSSRegisterCustomProperty.cpp (252627 => 252628)
--- trunk/Source/WebCore/css/DOMCSSRegisterCustomProperty.cpp 2019-11-19 15:26:13 UTC (rev 252627)
+++ trunk/Source/WebCore/css/DOMCSSRegisterCustomProperty.cpp 2019-11-19 15:34:28 UTC (rev 252628)
@@ -61,7 +61,7 @@
return Exception { SyntaxError, "The given initial value must be computationally independent." };
- MatchResult matchResult;
+ Style::MatchResult matchResult;
auto parentStyle = RenderStyle::clone(*style);
Style::Builder dummyBuilder(*style, { document, parentStyle }, matchResult, { });
Deleted: trunk/Source/WebCore/css/ElementRuleCollector.cpp (252627 => 252628)
--- trunk/Source/WebCore/css/ElementRuleCollector.cpp 2019-11-19 15:26:13 UTC (rev 252627)
+++ trunk/Source/WebCore/css/ElementRuleCollector.cpp 2019-11-19 15:34:28 UTC (rev 252628)
@@ -1,676 +0,0 @@
-/*
- * Copyright (C) 1999 Lars Knoll ([email protected])
- * (C) 2004-2005 Allan Sandfeld Jensen ([email protected])
- * Copyright (C) 2006, 2007 Nicholas Shanks ([email protected])
- * Copyright (C) 2005-2018 Apple Inc. All rights reserved.
- * Copyright (C) 2007 Alexey Proskuryakov <[email protected]>
- * Copyright (C) 2007, 2008 Eric Seidel <[email protected]>
- * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
- * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
- * Copyright (C) Research In Motion Limited 2011. All rights reserved.
- * Copyright (C) 2012 Google Inc. All rights reserved.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#include "config.h"
-#include "ElementRuleCollector.h"
-
-#include "CSSDefaultStyleSheets.h"
-#include "CSSRuleList.h"
-#include "CSSSelector.h"
-#include "CSSValueKeywords.h"
-#include "HTMLElement.h"
-#include "HTMLSlotElement.h"
-#include "SVGElement.h"
-#include "SelectorCompiler.h"
-#include "SelectorFilter.h"
-#include "ShadowRoot.h"
-#include "StyleProperties.h"
-#include "StyleResolver.h"
-#include "StyleScope.h"
-#include "StyleScopeRuleSets.h"
-#include "StyledElement.h"
-#include <wtf/SetForScope.h>
-
-namespace WebCore {
-
-static const StyleProperties& leftToRightDeclaration()
-{
- static auto& declaration = [] () -> const StyleProperties& {
- auto properties = MutableStyleProperties::create();
- properties->setProperty(CSSPropertyDirection, CSSValueLtr);
- return properties.leakRef();
- }();
- return declaration;
-}
-
-static const StyleProperties& rightToLeftDeclaration()
-{
- static auto& declaration = [] () -> const StyleProperties& {
- auto properties = MutableStyleProperties::create();
- properties->setProperty(CSSPropertyDirection, CSSValueRtl);
- return properties.leakRef();
- }();
- return declaration;
-}
-
-class MatchRequest {
-public:
- MatchRequest(const Style::RuleSet* ruleSet, Style::ScopeOrdinal styleScopeOrdinal = Style::ScopeOrdinal::Element)
- : ruleSet(ruleSet)
- , styleScopeOrdinal(styleScopeOrdinal)
- {
- }
- const Style::RuleSet* ruleSet;
- Style::ScopeOrdinal styleScopeOrdinal;
-};
-
-ElementRuleCollector::ElementRuleCollector(const Element& element, const Style::ScopeRuleSets& ruleSets, const SelectorFilter* selectorFilter)
- : m_element(element)
- , m_authorStyle(ruleSets.authorStyle())
- , m_userStyle(ruleSets.userStyle())
- , m_userAgentMediaQueryStyle(ruleSets.userAgentMediaQueryStyle())
- , m_selectorFilter(selectorFilter)
-{
- ASSERT(!m_selectorFilter || m_selectorFilter->parentStackIsConsistent(element.parentNode()));
-}
-
-ElementRuleCollector::ElementRuleCollector(const Element& element, const Style::RuleSet& authorStyle, const SelectorFilter* selectorFilter)
- : m_element(element)
- , m_authorStyle(authorStyle)
- , m_selectorFilter(selectorFilter)
-{
- ASSERT(!m_selectorFilter || m_selectorFilter->parentStackIsConsistent(element.parentNode()));
-}
-
-const MatchResult& ElementRuleCollector::matchResult() const
-{
- ASSERT(m_mode == SelectorChecker::Mode::ResolvingStyle);
- return m_result;
-}
-
-const Vector<RefPtr<StyleRule>>& ElementRuleCollector::matchedRuleList() const
-{
- ASSERT(m_mode == SelectorChecker::Mode::CollectingRules);
- return m_matchedRuleList;
-}
-
-inline void ElementRuleCollector::addMatchedRule(const Style::RuleData& ruleData, unsigned specificity, Style::ScopeOrdinal styleScopeOrdinal)
-{
- m_matchedRules.append({ &ruleData, specificity, styleScopeOrdinal });
-}
-
-void ElementRuleCollector::clearMatchedRules()
-{
- m_matchedRules.clear();
- m_keepAliveSlottedPseudoElementRules.clear();
- m_matchedRuleTransferIndex = 0;
-}
-
-inline void ElementRuleCollector::addElementStyleProperties(const StyleProperties* propertySet, bool isCacheable)
-{
- if (!propertySet || propertySet->isEmpty())
- return;
-
- if (!isCacheable)
- m_result.isCacheable = false;
-
- addMatchedProperties({ propertySet }, DeclarationOrigin::Author);
-}
-
-void ElementRuleCollector::collectMatchingRules(const MatchRequest& matchRequest)
-{
- ASSERT(matchRequest.ruleSet);
- ASSERT_WITH_MESSAGE(!(m_mode == SelectorChecker::Mode::CollectingRulesIgnoringVirtualPseudoElements && m_pseudoStyleRequest.pseudoId != PseudoId::None), "When in StyleInvalidation or SharingRules, SelectorChecker does not try to match the pseudo ID. While ElementRuleCollector supports matching a particular pseudoId in this case, this would indicate a error at the call site since matching a particular element should be unnecessary.");
-
- auto* shadowRoot = element().containingShadowRoot();
- if (shadowRoot && shadowRoot->mode() == ShadowRootMode::UserAgent)
- collectMatchingShadowPseudoElementRules(matchRequest);
-
- // We need to collect the rules for id, class, tag, and everything else into a buffer and
- // then sort the buffer.
- auto& id = element().idForStyleResolution();
- if (!id.isNull())
- collectMatchingRulesForList(matchRequest.ruleSet->idRules(id), matchRequest);
- if (element().hasClass()) {
- for (size_t i = 0; i < element().classNames().size(); ++i)
- collectMatchingRulesForList(matchRequest.ruleSet->classRules(element().classNames()[i]), matchRequest);
- }
-
- if (element().isLink())
- collectMatchingRulesForList(matchRequest.ruleSet->linkPseudoClassRules(), matchRequest);
- if (SelectorChecker::matchesFocusPseudoClass(element()))
- collectMatchingRulesForList(matchRequest.ruleSet->focusPseudoClassRules(), matchRequest);
- collectMatchingRulesForList(matchRequest.ruleSet->tagRules(element().localName(), element().isHTMLElement() && element().document().isHTMLDocument()), matchRequest);
- collectMatchingRulesForList(matchRequest.ruleSet->universalRules(), matchRequest);
-}
-
-
-Vector<MatchedProperties>& ElementRuleCollector::declarationsForOrigin(MatchResult& matchResult, DeclarationOrigin declarationOrigin)
-{
- switch (declarationOrigin) {
- case DeclarationOrigin::UserAgent: return matchResult.userAgentDeclarations;
- case DeclarationOrigin::User: return matchResult.userDeclarations;
- case DeclarationOrigin::Author: return matchResult.authorDeclarations;
- }
- ASSERT_NOT_REACHED();
- return matchResult.authorDeclarations;
-}
-
-void ElementRuleCollector::sortAndTransferMatchedRules(DeclarationOrigin declarationOrigin)
-{
- if (m_matchedRules.isEmpty())
- return;
-
- sortMatchedRules();
-
- transferMatchedRules(declarationOrigin);
-}
-
-void ElementRuleCollector::transferMatchedRules(DeclarationOrigin declarationOrigin, Optional<Style::ScopeOrdinal> fromScope)
-{
- if (m_mode != SelectorChecker::Mode::CollectingRules)
- declarationsForOrigin(m_result, declarationOrigin).reserveCapacity(m_matchedRules.size());
-
- for (; m_matchedRuleTransferIndex < m_matchedRules.size(); ++m_matchedRuleTransferIndex) {
- auto& matchedRule = m_matchedRules[m_matchedRuleTransferIndex];
- if (fromScope && matchedRule.styleScopeOrdinal < *fromScope)
- break;
-
- if (m_mode == SelectorChecker::Mode::CollectingRules) {
- m_matchedRuleList.append(matchedRule.ruleData->rule());
- continue;
- }
-
- addMatchedProperties({
- &matchedRule.ruleData->rule()->properties(),
- static_cast<uint16_t>(matchedRule.ruleData->linkMatchType()),
- static_cast<uint16_t>(matchedRule.ruleData->propertyWhitelistType()),
- matchedRule.styleScopeOrdinal
- }, declarationOrigin);
- }
-}
-
-void ElementRuleCollector::matchAuthorRules()
-{
- clearMatchedRules();
-
- collectMatchingAuthorRules();
-
- sortAndTransferMatchedRules(DeclarationOrigin::Author);
-}
-
-bool ElementRuleCollector::matchesAnyAuthorRules()
-{
- clearMatchedRules();
-
- // FIXME: This should bail out on first match.
- collectMatchingAuthorRules();
-
- return !m_matchedRules.isEmpty();
-}
-
-void ElementRuleCollector::collectMatchingAuthorRules()
-{
- {
- MatchRequest matchRequest(&m_authorStyle);
- collectMatchingRules(matchRequest);
- }
-
- auto* parent = element().parentElement();
- if (parent && parent->shadowRoot())
- matchSlottedPseudoElementRules();
-
- if (element().shadowRoot())
- matchHostPseudoClassRules();
-
- if (element().isInShadowTree()) {
- matchAuthorShadowPseudoElementRules();
- matchPartPseudoElementRules();
- }
-}
-
-void ElementRuleCollector::matchAuthorShadowPseudoElementRules()
-{
- ASSERT(element().isInShadowTree());
- auto& shadowRoot = *element().containingShadowRoot();
- if (shadowRoot.mode() != ShadowRootMode::UserAgent)
- return;
- // Look up shadow pseudo elements also from the host scope author style as they are web-exposed.
- auto& hostAuthorRules = Style::Scope::forNode(*shadowRoot.host()).resolver().ruleSets().authorStyle();
- MatchRequest hostAuthorRequest { &hostAuthorRules, Style::ScopeOrdinal::ContainingHost };
- collectMatchingShadowPseudoElementRules(hostAuthorRequest);
-}
-
-void ElementRuleCollector::matchHostPseudoClassRules()
-{
- ASSERT(element().shadowRoot());
-
- auto& shadowAuthorStyle = element().shadowRoot()->styleScope().resolver().ruleSets().authorStyle();
- auto& shadowHostRules = shadowAuthorStyle.hostPseudoClassRules();
- if (shadowHostRules.isEmpty())
- return;
-
- SetForScope<bool> change(m_isMatchingHostPseudoClass, true);
-
- MatchRequest hostMatchRequest { nullptr, Style::ScopeOrdinal::Shadow };
- collectMatchingRulesForList(&shadowHostRules, hostMatchRequest);
-}
-
-void ElementRuleCollector::matchSlottedPseudoElementRules()
-{
- auto* slot = element().assignedSlot();
- auto styleScopeOrdinal = Style::ScopeOrdinal::FirstSlot;
-
- for (; slot; slot = slot->assignedSlot(), ++styleScopeOrdinal) {
- auto& styleScope = Style::Scope::forNode(*slot);
- if (!styleScope.resolver().ruleSets().isAuthorStyleDefined())
- continue;
- // Find out if there are any ::slotted rules in the shadow tree matching the current slot.
- // FIXME: This is really part of the slot style and could be cached when resolving it.
- ElementRuleCollector collector(*slot, styleScope.resolver().ruleSets().authorStyle(), nullptr);
- auto slottedPseudoElementRules = collector.collectSlottedPseudoElementRulesForSlot();
- if (!slottedPseudoElementRules)
- continue;
- // Match in the current scope.
- SetForScope<bool> change(m_isMatchingSlottedPseudoElements, true);
-
- MatchRequest scopeMatchRequest(nullptr, styleScopeOrdinal);
- collectMatchingRulesForList(slottedPseudoElementRules.get(), scopeMatchRequest);
-
- m_keepAliveSlottedPseudoElementRules.append(WTFMove(slottedPseudoElementRules));
- }
-}
-
-void ElementRuleCollector::matchPartPseudoElementRules()
-{
- ASSERT(element().isInShadowTree());
-
- bool isUAShadowPseudoElement = element().containingShadowRoot()->mode() == ShadowRootMode::UserAgent && !element().shadowPseudoId().isNull();
-
- auto& partMatchingElement = isUAShadowPseudoElement ? *element().shadowHost() : element();
- if (partMatchingElement.partNames().isEmpty() || !partMatchingElement.isInShadowTree())
- return;
-
- matchPartPseudoElementRulesForScope(*partMatchingElement.containingShadowRoot());
-}
-
-void ElementRuleCollector::matchPartPseudoElementRulesForScope(const ShadowRoot& scopeShadowRoot)
-{
- auto& shadowHost = *scopeShadowRoot.host();
- {
- SetForScope<RefPtr<const Element>> partMatchingScope(m_shadowHostInPartRuleScope, &shadowHost);
-
- auto& hostAuthorRules = Style::Scope::forNode(shadowHost).resolver().ruleSets().authorStyle();
- MatchRequest hostAuthorRequest { &hostAuthorRules, Style::ScopeOrdinal::ContainingHost };
- collectMatchingRulesForList(&hostAuthorRules.partPseudoElementRules(), hostAuthorRequest);
- }
-
- // Element may be exposed to styling from enclosing scopes via exportparts attributes.
- if (scopeShadowRoot.partMappings().isEmpty())
- return;
-
- if (auto* parentScopeShadowRoot = shadowHost.containingShadowRoot())
- matchPartPseudoElementRulesForScope(*parentScopeShadowRoot);
-}
-
-void ElementRuleCollector::collectMatchingShadowPseudoElementRules(const MatchRequest& matchRequest)
-{
- ASSERT(matchRequest.ruleSet);
- ASSERT(element().containingShadowRoot()->mode() == ShadowRootMode::UserAgent);
-
- auto& rules = *matchRequest.ruleSet;
-#if ENABLE(VIDEO_TRACK)
- // FXIME: WebVTT should not be done by styling UA shadow trees like this.
- if (element().isWebVTTElement())
- collectMatchingRulesForList(rules.cuePseudoRules(), matchRequest);
-#endif
- auto& pseudoId = element().shadowPseudoId();
- if (!pseudoId.isEmpty())
- collectMatchingRulesForList(rules.shadowPseudoElementRules(pseudoId), matchRequest);
-}
-
-std::unique_ptr<Style::RuleSet::RuleDataVector> ElementRuleCollector::collectSlottedPseudoElementRulesForSlot()
-{
- ASSERT(is<HTMLSlotElement>(element()));
-
- clearMatchedRules();
-
- m_mode = SelectorChecker::Mode::CollectingRules;
-
- // Match global author rules.
- MatchRequest matchRequest(&m_authorStyle);
- collectMatchingRulesForList(&m_authorStyle.slottedPseudoElementRules(), matchRequest);
-
- if (m_matchedRules.isEmpty())
- return { };
-
- auto ruleDataVector = makeUnique<Style::RuleSet::RuleDataVector>();
- ruleDataVector->reserveInitialCapacity(m_matchedRules.size());
- for (auto& matchedRule : m_matchedRules)
- ruleDataVector->uncheckedAppend(*matchedRule.ruleData);
-
- return ruleDataVector;
-}
-
-void ElementRuleCollector::matchUserRules()
-{
- if (!m_userStyle)
- return;
-
- clearMatchedRules();
-
- MatchRequest matchRequest(m_userStyle);
- collectMatchingRules(matchRequest);
-
- sortAndTransferMatchedRules(DeclarationOrigin::User);
-}
-
-void ElementRuleCollector::matchUARules()
-{
- // First we match rules from the user agent sheet.
- if (CSSDefaultStyleSheets::simpleDefaultStyleSheet)
- m_result.isCacheable = false;
- auto* userAgentStyleSheet = m_isPrintStyle
- ? CSSDefaultStyleSheets::defaultPrintStyle : CSSDefaultStyleSheets::defaultStyle;
- matchUARules(*userAgentStyleSheet);
-
- // In quirks mode, we match rules from the quirks user agent sheet.
- if (element().document().inQuirksMode())
- matchUARules(*CSSDefaultStyleSheets::defaultQuirksStyle);
-
- if (m_userAgentMediaQueryStyle)
- matchUARules(*m_userAgentMediaQueryStyle);
-}
-
-void ElementRuleCollector::matchUARules(const Style::RuleSet& rules)
-{
- clearMatchedRules();
-
- collectMatchingRules(MatchRequest(&rules));
-
- sortAndTransferMatchedRules(DeclarationOrigin::UserAgent);
-}
-
-static const CSSSelector* findSlottedPseudoElementSelector(const CSSSelector* selector)
-{
- for (; selector; selector = selector->tagHistory()) {
- if (selector->match() == CSSSelector::PseudoElement && selector->pseudoElementType() == CSSSelector::PseudoElementSlotted) {
- if (auto* list = selector->selectorList())
- return list->first();
- break;
- }
- };
- return nullptr;
-}
-
-inline bool ElementRuleCollector::ruleMatches(const Style::RuleData& ruleData, unsigned& specificity)
-{
- // We know a sufficiently simple single part selector matches simply because we found it from the rule hash when filtering the RuleSet.
- // This is limited to HTML only so we don't need to check the namespace (because of tag name match).
- auto matchBasedOnRuleHash = ruleData.matchBasedOnRuleHash();
- if (matchBasedOnRuleHash != Style::MatchBasedOnRuleHash::None && element().isHTMLElement()) {
- ASSERT_WITH_MESSAGE(m_pseudoStyleRequest.pseudoId == PseudoId::None, "If we match based on the rule hash while collecting for a particular pseudo element ID, we would add incorrect rules for that pseudo element ID. We should never end in ruleMatches() with a pseudo element if the ruleData cannot match any pseudo element.");
-
- switch (matchBasedOnRuleHash) {
- case Style::MatchBasedOnRuleHash::None:
- ASSERT_NOT_REACHED();
- break;
- case Style::MatchBasedOnRuleHash::Universal:
- specificity = 0;
- break;
- case Style::MatchBasedOnRuleHash::ClassA:
- specificity = static_cast<unsigned>(SelectorSpecificityIncrement::ClassA);
- break;
- case Style::MatchBasedOnRuleHash::ClassB:
- specificity = static_cast<unsigned>(SelectorSpecificityIncrement::ClassB);
- break;
- case Style::MatchBasedOnRuleHash::ClassC:
- specificity = static_cast<unsigned>(SelectorSpecificityIncrement::ClassC);
- break;
- }
- return true;
- }
-
-#if ENABLE(CSS_SELECTOR_JIT)
- auto& compiledSelector = ruleData.rule()->compiledSelectorForListIndex(ruleData.selectorListIndex());
- void* compiledSelectorChecker = compiledSelector.codeRef.code().executableAddress();
- if (!compiledSelectorChecker && compiledSelector.status == SelectorCompilationStatus::NotCompiled) {
- compiledSelector.status = SelectorCompiler::compileSelector(ruleData.selector(), SelectorCompiler::SelectorContext::RuleCollector, compiledSelector.codeRef);
-
- compiledSelectorChecker = compiledSelector.codeRef.code().executableAddress();
- }
-
- if (compiledSelectorChecker && compiledSelector.status == SelectorCompilationStatus::SimpleSelectorChecker) {
- auto selectorChecker = SelectorCompiler::ruleCollectorSimpleSelectorCheckerFunction(compiledSelectorChecker, compiledSelector.status);
-#if !ASSERT_MSG_DISABLED
- unsigned ignoreSpecificity;
- ASSERT_WITH_MESSAGE(!selectorChecker(&element(), &ignoreSpecificity) || m_pseudoStyleRequest.pseudoId == PseudoId::None, "When matching pseudo elements, we should never compile a selector checker without context unless it cannot match anything.");
-#endif
-#if CSS_SELECTOR_JIT_PROFILING
- ruleData.compiledSelectorUsed();
-#endif
- bool selectorMatches = selectorChecker(&element(), &specificity);
-
- if (selectorMatches && ruleData.containsUncommonAttributeSelector())
- m_didMatchUncommonAttributeSelector = true;
-
- return selectorMatches;
- }
-#endif // ENABLE(CSS_SELECTOR_JIT)
-
- SelectorChecker::CheckingContext context(m_mode);
- context.pseudoId = m_pseudoStyleRequest.pseudoId;
- context.scrollbarState = m_pseudoStyleRequest.scrollbarState;
- context.isMatchingHostPseudoClass = m_isMatchingHostPseudoClass;
- context.shadowHostInPartRuleScope = m_shadowHostInPartRuleScope.get();
-
- bool selectorMatches;
-#if ENABLE(CSS_SELECTOR_JIT)
- if (compiledSelectorChecker) {
- ASSERT(compiledSelector.status == SelectorCompilationStatus::SelectorCheckerWithCheckingContext);
-
- auto selectorChecker = SelectorCompiler::ruleCollectorSelectorCheckerFunctionWithCheckingContext(compiledSelectorChecker, compiledSelector.status);
-
-#if CSS_SELECTOR_JIT_PROFILING
- compiledSelector.useCount++;
-#endif
- selectorMatches = selectorChecker(&element(), &context, &specificity);
- } else
-#endif // ENABLE(CSS_SELECTOR_JIT)
- {
- auto* selector = ruleData.selector();
- if (m_isMatchingSlottedPseudoElements) {
- selector = findSlottedPseudoElementSelector(ruleData.selector());
- if (!selector)
- return false;
- }
- // Slow path.
- SelectorChecker selectorChecker(element().document());
- selectorMatches = selectorChecker.match(*selector, element(), context, specificity);
- }
-
- if (ruleData.containsUncommonAttributeSelector()) {
- if (selectorMatches || context.pseudoIDSet)
- m_didMatchUncommonAttributeSelector = true;
- }
- m_matchedPseudoElementIds.merge(context.pseudoIDSet);
- m_styleRelations.appendVector(context.styleRelations);
-
- return selectorMatches;
-}
-
-void ElementRuleCollector::collectMatchingRulesForList(const Style::RuleSet::RuleDataVector* rules, const MatchRequest& matchRequest)
-{
- if (!rules)
- return;
-
- for (unsigned i = 0, size = rules->size(); i < size; ++i) {
- const auto& ruleData = rules->data()[i];
-
- if (!ruleData.canMatchPseudoElement() && m_pseudoStyleRequest.pseudoId != PseudoId::None)
- continue;
-
- if (m_selectorFilter && m_selectorFilter->fastRejectSelector(ruleData.descendantSelectorIdentifierHashes()))
- continue;
-
- StyleRule* rule = ruleData.rule();
-
- // If the rule has no properties to apply, then ignore it in the non-debug mode.
- // Note that if we get null back here, it means we have a rule with deferred properties,
- // and that means we always have to consider it.
- const StyleProperties* properties = rule->propertiesWithoutDeferredParsing();
- if (properties && properties->isEmpty() && !m_shouldIncludeEmptyRules)
- continue;
-
- unsigned specificity;
- if (ruleMatches(ruleData, specificity))
- addMatchedRule(ruleData, specificity, matchRequest.styleScopeOrdinal);
- }
-}
-
-static inline bool compareRules(MatchedRule r1, MatchedRule r2)
-{
- // For normal properties the earlier scope wins. This may be reversed by !important which is handled when resolving cascade.
- if (r1.styleScopeOrdinal != r2.styleScopeOrdinal)
- return r1.styleScopeOrdinal > r2.styleScopeOrdinal;
-
- if (r1.specificity != r2.specificity)
- return r1.specificity < r2.specificity;
-
- return r1.ruleData->position() < r2.ruleData->position();
-}
-
-void ElementRuleCollector::sortMatchedRules()
-{
- std::sort(m_matchedRules.begin(), m_matchedRules.end(), compareRules);
-}
-
-void ElementRuleCollector::matchAllRules(bool matchAuthorAndUserStyles, bool includeSMILProperties)
-{
- matchUARules();
-
- // Now we check user sheet rules.
- if (matchAuthorAndUserStyles)
- matchUserRules();
-
- // Now check author rules, beginning first with presentational attributes mapped from HTML.
- if (is<StyledElement>(element())) {
- auto& styledElement = downcast<StyledElement>(element());
- addElementStyleProperties(styledElement.presentationAttributeStyle());
-
- // Now we check additional mapped declarations.
- // Tables and table cells share an additional mapped rule that must be applied
- // after all attributes, since their mapped style depends on the values of multiple attributes.
- addElementStyleProperties(styledElement.additionalPresentationAttributeStyle());
-
- if (is<HTMLElement>(styledElement)) {
- bool isAuto;
- auto textDirection = downcast<HTMLElement>(styledElement).directionalityIfhasDirAutoAttribute(isAuto);
- auto& properties = textDirection == TextDirection::LTR ? leftToRightDeclaration() : rightToLeftDeclaration();
- if (isAuto)
- addMatchedProperties({ &properties }, DeclarationOrigin::Author);
- }
- }
-
- if (matchAuthorAndUserStyles) {
- clearMatchedRules();
-
- collectMatchingAuthorRules();
- sortMatchedRules();
-
- transferMatchedRules(DeclarationOrigin::Author, Style::ScopeOrdinal::Element);
-
- // Inline style behaves as if it has higher specificity than any rule.
- addElementInlineStyleProperties(includeSMILProperties);
-
- // Rules from the host scope override inline style.
- transferMatchedRules(DeclarationOrigin::Author, Style::ScopeOrdinal::ContainingHost);
- }
-}
-
-void ElementRuleCollector::addElementInlineStyleProperties(bool includeSMILProperties)
-{
- if (!is<StyledElement>(element()))
- return;
-
- if (auto* inlineStyle = downcast<StyledElement>(element()).inlineStyle()) {
- // FIXME: Media control shadow trees seem to have problems with caching.
- bool isInlineStyleCacheable = !inlineStyle->isMutable() && !element().isInShadowTree();
- addElementStyleProperties(inlineStyle, isInlineStyleCacheable);
- }
-
- if (includeSMILProperties && is<SVGElement>(element()))
- addElementStyleProperties(downcast<SVGElement>(element()).animatedSMILStyleProperties(), false /* isCacheable */);
-}
-
-bool ElementRuleCollector::hasAnyMatchingRules(const Style::RuleSet* ruleSet)
-{
- clearMatchedRules();
-
- m_mode = SelectorChecker::Mode::CollectingRulesIgnoringVirtualPseudoElements;
- collectMatchingRules(MatchRequest(ruleSet));
-
- return !m_matchedRules.isEmpty();
-}
-
-void ElementRuleCollector::addMatchedProperties(MatchedProperties&& matchedProperties, DeclarationOrigin declarationOrigin)
-{
- // FIXME: This should be moved to the matched properties cache code.
- auto computeIsCacheable = [&] {
- if (!m_result.isCacheable)
- return false;
-
- if (matchedProperties.styleScopeOrdinal != Style::ScopeOrdinal::Element)
- return false;
-
- auto& properties = *matchedProperties.properties;
- for (unsigned i = 0, count = properties.propertyCount(); i < count; ++i) {
- // Currently the property cache only copy the non-inherited values and resolve
- // the inherited ones.
- // Here we define some exception were we have to resolve some properties that are not inherited
- // by default. If those exceptions become too common on the web, it should be possible
- // to build a list of exception to resolve instead of completely disabling the cache.
- StyleProperties::PropertyReference current = properties.propertyAt(i);
- if (current.isInherited())
- continue;
-
- // If the property value is explicitly inherited, we need to apply further non-inherited properties
- // as they might override the value inherited here. For this reason we don't allow declarations with
- // explicitly inherited properties to be cached.
- const CSSValue& value = *current.value();
- if (value.isInheritedValue())
- return false;
-
- // The value currentColor has implicitely the same side effect. It depends on the value of color,
- // which is an inherited value, making the non-inherited property implicitly inherited.
- if (is<CSSPrimitiveValue>(value) && downcast<CSSPrimitiveValue>(value).valueID() == CSSValueCurrentcolor)
- return false;
-
- if (value.hasVariableReferences())
- return false;
- }
-
- return true;
- };
-
- m_result.isCacheable = computeIsCacheable();
-
- declarationsForOrigin(m_result, declarationOrigin).append(WTFMove(matchedProperties));
-}
-
-} // namespace WebCore
Deleted: trunk/Source/WebCore/css/ElementRuleCollector.h (252627 => 252628)
--- trunk/Source/WebCore/css/ElementRuleCollector.h 2019-11-19 15:26:13 UTC (rev 252627)
+++ trunk/Source/WebCore/css/ElementRuleCollector.h 2019-11-19 15:34:28 UTC (rev 252628)
@@ -1,182 +0,0 @@
-/*
- * Copyright (C) 1999 Lars Knoll ([email protected])
- * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2013, 2014 Apple Inc. All rights reserved.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#pragma once
-
-#include "MediaQueryEvaluator.h"
-#include "RuleSet.h"
-#include "SelectorChecker.h"
-#include "StyleScope.h"
-#include <memory>
-#include <wtf/RefPtr.h>
-#include <wtf/Vector.h>
-
-namespace WebCore {
-
-class MatchRequest;
-class SelectorFilter;
-
-namespace Style {
-class ScopeRuleSets;
-}
-
-class PseudoStyleRequest {
-public:
- PseudoStyleRequest(PseudoId pseudoId, Optional<StyleScrollbarState> scrollbarState = WTF::nullopt)
- : pseudoId(pseudoId)
- , scrollbarState(scrollbarState)
- {
- }
-
- PseudoId pseudoId;
- Optional<StyleScrollbarState> scrollbarState;
-};
-
-struct MatchedRule {
- const Style::RuleData* ruleData;
- unsigned specificity;
- Style::ScopeOrdinal styleScopeOrdinal;
-};
-
-struct MatchedProperties {
- RefPtr<const StyleProperties> properties;
- uint16_t linkMatchType { SelectorChecker::MatchAll };
- uint16_t whitelistType { Style::PropertyWhitelistNone };
- Style::ScopeOrdinal styleScopeOrdinal { Style::ScopeOrdinal::Element };
-};
-
-struct MatchResult {
- bool isCacheable { true };
- Vector<MatchedProperties> userAgentDeclarations;
- Vector<MatchedProperties> userDeclarations;
- Vector<MatchedProperties> authorDeclarations;
-
- bool operator==(const MatchResult& other) const
- {
- return isCacheable == other.isCacheable
- && userAgentDeclarations == other.userAgentDeclarations
- && userDeclarations == other.userDeclarations
- && authorDeclarations == other.authorDeclarations;
- }
- bool operator!=(const MatchResult& other) const { return !(*this == other); }
-
- bool isEmpty() const { return userAgentDeclarations.isEmpty() && userDeclarations.isEmpty() && authorDeclarations.isEmpty(); }
-};
-
-class ElementRuleCollector {
-public:
- ElementRuleCollector(const Element&, const Style::ScopeRuleSets&, const SelectorFilter*);
- ElementRuleCollector(const Element&, const Style::RuleSet& authorStyle, const SelectorFilter*);
-
- void setIncludeEmptyRules(bool value) { m_shouldIncludeEmptyRules = value; }
-
- void matchAllRules(bool matchAuthorAndUserStyles, bool includeSMILProperties);
- void matchUARules();
- void matchAuthorRules();
- void matchUserRules();
-
- bool matchesAnyAuthorRules();
-
- void setMode(SelectorChecker::Mode mode) { m_mode = mode; }
- void setPseudoStyleRequest(const PseudoStyleRequest& request) { m_pseudoStyleRequest = request; }
- void setMedium(const MediaQueryEvaluator* medium) { m_isPrintStyle = medium->mediaTypeMatchSpecific("print"); }
-
- bool hasAnyMatchingRules(const Style::RuleSet*);
-
- const MatchResult& matchResult() const;
- const Vector<RefPtr<StyleRule>>& matchedRuleList() const;
-
- void clearMatchedRules();
-
- const PseudoIdSet& matchedPseudoElementIds() const { return m_matchedPseudoElementIds; }
- const Style::Relations& styleRelations() const { return m_styleRelations; }
- bool didMatchUncommonAttributeSelector() const { return m_didMatchUncommonAttributeSelector; }
-
-private:
- void addElementStyleProperties(const StyleProperties*, bool isCacheable = true);
-
- void matchUARules(const Style::RuleSet&);
-
- void collectMatchingAuthorRules();
- void addElementInlineStyleProperties(bool includeSMILProperties);
-
- void matchAuthorShadowPseudoElementRules();
- void matchHostPseudoClassRules();
- void matchSlottedPseudoElementRules();
- void matchPartPseudoElementRules();
- void matchPartPseudoElementRulesForScope(const ShadowRoot& scopeShadowRoot);
-
- void collectMatchingShadowPseudoElementRules(const MatchRequest&);
- std::unique_ptr<Style::RuleSet::RuleDataVector> collectSlottedPseudoElementRulesForSlot();
-
- void collectMatchingRules(const MatchRequest&);
- void collectMatchingRulesForList(const Style::RuleSet::RuleDataVector*, const MatchRequest&);
- bool ruleMatches(const Style::RuleData&, unsigned &specificity);
-
- void sortMatchedRules();
-
- enum class DeclarationOrigin { UserAgent, User, Author };
- static Vector<MatchedProperties>& declarationsForOrigin(MatchResult&, DeclarationOrigin);
- void sortAndTransferMatchedRules(DeclarationOrigin);
- void transferMatchedRules(DeclarationOrigin, Optional<Style::ScopeOrdinal> forScope = { });
-
- void addMatchedRule(const Style::RuleData&, unsigned specificity, Style::ScopeOrdinal);
- void addMatchedProperties(MatchedProperties&&, DeclarationOrigin);
-
- const Element& element() const { return m_element.get(); }
-
- const Ref<const Element> m_element;
- const Style::RuleSet& m_authorStyle;
- const Style::RuleSet* m_userStyle { nullptr };
- const Style::RuleSet* m_userAgentMediaQueryStyle { nullptr };
- const SelectorFilter* m_selectorFilter { nullptr };
-
- bool m_shouldIncludeEmptyRules { false };
- bool m_isPrintStyle { false };
- PseudoStyleRequest m_pseudoStyleRequest { PseudoId::None };
- SelectorChecker::Mode m_mode { SelectorChecker::Mode::ResolvingStyle };
- bool m_isMatchingSlottedPseudoElements { false };
- bool m_isMatchingHostPseudoClass { false };
- RefPtr<const Element> m_shadowHostInPartRuleScope;
- Vector<std::unique_ptr<Style::RuleSet::RuleDataVector>> m_keepAliveSlottedPseudoElementRules;
-
- Vector<MatchedRule, 64> m_matchedRules;
- size_t m_matchedRuleTransferIndex { 0 };
-
- // Output.
- Vector<RefPtr<StyleRule>> m_matchedRuleList;
- bool m_didMatchUncommonAttributeSelector { false };
- MatchResult m_result;
- Style::Relations m_styleRelations;
- PseudoIdSet m_matchedPseudoElementIds;
-};
-
-inline bool operator==(const MatchedProperties& a, const MatchedProperties& b)
-{
- return a.properties == b.properties && a.linkMatchType == b.linkMatchType;
-}
-
-inline bool operator!=(const MatchedProperties& a, const MatchedProperties& b)
-{
- return !(a == b);
-}
-
-} // namespace WebCore
Deleted: trunk/Source/WebCore/css/PageRuleCollector.cpp (252627 => 252628)
--- trunk/Source/WebCore/css/PageRuleCollector.cpp 2019-11-19 15:26:13 UTC (rev 252627)
+++ trunk/Source/WebCore/css/PageRuleCollector.cpp 2019-11-19 15:34:28 UTC (rev 252628)
@@ -1,131 +0,0 @@
-/*
- * Copyright (C) 1999 Lars Knoll ([email protected])
- * (C) 2004-2005 Allan Sandfeld Jensen ([email protected])
- * Copyright (C) 2006, 2007 Nicholas Shanks ([email protected])
- * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 Apple Inc. All rights reserved.
- * Copyright (C) 2007 Alexey Proskuryakov <[email protected]>
- * Copyright (C) 2007, 2008 Eric Seidel <[email protected]>
- * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
- * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
- * Copyright (C) Research In Motion Limited 2011. All rights reserved.
- * Copyright (C) 2012 Google Inc. All rights reserved.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#include "config.h"
-#include "PageRuleCollector.h"
-
-#include "CSSDefaultStyleSheets.h"
-#include "StyleProperties.h"
-#include "StyleRule.h"
-
-namespace WebCore {
-
-static inline bool comparePageRules(const StyleRulePage* r1, const StyleRulePage* r2)
-{
- return r1->selector()->specificityForPage() < r2->selector()->specificityForPage();
-}
-
-bool PageRuleCollector::isLeftPage(int pageIndex) const
-{
- bool isFirstPageLeft = false;
- if (!m_state.rootElementStyle()->isLeftToRightDirection())
- isFirstPageLeft = true;
-
- return (pageIndex + (isFirstPageLeft ? 1 : 0)) % 2;
-}
-
-bool PageRuleCollector::isFirstPage(int pageIndex) const
-{
- // FIXME: In case of forced left/right page, page at index 1 (not 0) can be the first page.
- return (!pageIndex);
-}
-
-String PageRuleCollector::pageName(int /* pageIndex */) const
-{
- // FIXME: Implement page index to page name mapping.
- return emptyString();
-}
-
-void PageRuleCollector::matchAllPageRules(int pageIndex)
-{
- const bool isLeft = isLeftPage(pageIndex);
- const bool isFirst = isFirstPage(pageIndex);
- const String page = pageName(pageIndex);
-
- matchPageRules(CSSDefaultStyleSheets::defaultPrintStyle, isLeft, isFirst, page);
- matchPageRules(m_ruleSets.userStyle(), isLeft, isFirst, page);
- // Only consider the global author RuleSet for @page rules, as per the HTML5 spec.
- if (m_ruleSets.isAuthorStyleDefined())
- matchPageRules(&m_ruleSets.authorStyle(), isLeft, isFirst, page);
-}
-
-void PageRuleCollector::matchPageRules(Style::RuleSet* rules, bool isLeftPage, bool isFirstPage, const String& pageName)
-{
- if (!rules)
- return;
-
- Vector<StyleRulePage*> matchedPageRules;
- matchPageRulesForList(matchedPageRules, rules->pageRules(), isLeftPage, isFirstPage, pageName);
- if (matchedPageRules.isEmpty())
- return;
-
- std::stable_sort(matchedPageRules.begin(), matchedPageRules.end(), comparePageRules);
-
- for (unsigned i = 0; i < matchedPageRules.size(); i++)
- m_result.authorDeclarations.append({ &matchedPageRules[i]->properties() });
-}
-
-static bool checkPageSelectorComponents(const CSSSelector* selector, bool isLeftPage, bool isFirstPage, const String& pageName)
-{
- for (const CSSSelector* component = selector; component; component = component->tagHistory()) {
- if (component->match() == CSSSelector::Tag) {
- const AtomString& localName = component->tagQName().localName();
- if (localName != starAtom() && localName != pageName)
- return false;
- } else if (component->match() == CSSSelector::PagePseudoClass) {
- CSSSelector::PagePseudoClassType pseudoType = component->pagePseudoClassType();
- if ((pseudoType == CSSSelector::PagePseudoClassLeft && !isLeftPage)
- || (pseudoType == CSSSelector::PagePseudoClassRight && isLeftPage)
- || (pseudoType == CSSSelector::PagePseudoClassFirst && !isFirstPage))
- {
- return false;
- }
- }
- }
- return true;
-}
-
-void PageRuleCollector::matchPageRulesForList(Vector<StyleRulePage*>& matchedRules, const Vector<StyleRulePage*>& rules, bool isLeftPage, bool isFirstPage, const String& pageName)
-{
- for (unsigned i = 0; i < rules.size(); ++i) {
- StyleRulePage* rule = rules[i];
-
- if (!checkPageSelectorComponents(rule->selector(), isLeftPage, isFirstPage, pageName))
- continue;
-
- // If the rule has no properties to apply, then ignore it.
- const StyleProperties& properties = rule->properties();
- if (properties.isEmpty())
- continue;
-
- // Add this rule to our list of matched rules.
- matchedRules.append(rule);
- }
-}
-
-} // namespace WebCore
Deleted: trunk/Source/WebCore/css/PageRuleCollector.h (252627 => 252628)
--- trunk/Source/WebCore/css/PageRuleCollector.h 2019-11-19 15:26:13 UTC (rev 252627)
+++ trunk/Source/WebCore/css/PageRuleCollector.h 2019-11-19 15:34:28 UTC (rev 252628)
@@ -1,56 +0,0 @@
-/*
- * Copyright (C) 1999 Lars Knoll ([email protected])
- * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserved.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#pragma once
-
-#include "StyleResolver.h"
-#include "StyleScopeRuleSets.h"
-#include <wtf/Forward.h>
-
-namespace WebCore {
-
-class StyleRulePage;
-
-class PageRuleCollector {
-public:
- PageRuleCollector(Style::Resolver::State& state, Style::ScopeRuleSets& ruleSets)
- : m_state(state)
- , m_ruleSets(ruleSets) { }
-
- void matchAllPageRules(int pageIndex);
- const MatchResult& matchResult() const { return m_result; }
-
-private:
- bool isLeftPage(int pageIndex) const;
- bool isRightPage(int pageIndex) const { return !isLeftPage(pageIndex); }
- bool isFirstPage(int pageIndex) const;
- String pageName(int pageIndex) const;
-
- void matchPageRules(Style::RuleSet* rules, bool isLeftPage, bool isFirstPage, const String& pageName);
- void matchPageRulesForList(Vector<StyleRulePage*>& matchedRules, const Vector<StyleRulePage*>& rules, bool isLeftPage, bool isFirstPage, const String& pageName);
-
- const Style::Resolver::State& m_state;
- Style::ScopeRuleSets& m_ruleSets;
-
- MatchResult m_result;
-};
-
-} // namespace WebCore
Modified: trunk/Source/WebCore/dom/Document.cpp (252627 => 252628)
--- trunk/Source/WebCore/dom/Document.cpp 2019-11-19 15:26:13 UTC (rev 252627)
+++ trunk/Source/WebCore/dom/Document.cpp 2019-11-19 15:34:28 UTC (rev 252628)
@@ -2127,7 +2127,7 @@
auto& resolver = element.styleResolver();
if (pseudoElementSpecifier != PseudoId::None)
- return resolver.pseudoStyleForElement(element, PseudoStyleRequest(pseudoElementSpecifier), *parentStyle);
+ return resolver.pseudoStyleForElement(element, { pseudoElementSpecifier }, *parentStyle);
auto elementStyle = resolver.styleForElement(element, parentStyle);
if (elementStyle.relations) {
Modified: trunk/Source/WebCore/html/canvas/CanvasRenderingContext2D.cpp (252627 => 252628)
--- trunk/Source/WebCore/html/canvas/CanvasRenderingContext2D.cpp 2019-11-19 15:26:13 UTC (rev 252627)
+++ trunk/Source/WebCore/html/canvas/CanvasRenderingContext2D.cpp 2019-11-19 15:34:28 UTC (rev 252628)
@@ -172,9 +172,9 @@
// Now map the font property longhands into the style.
- MatchResult matchResult;
+ Style::MatchResult matchResult;
auto parentStyle = RenderStyle::clone(*newStyle);
- WebCore::Style::Builder styleBuilder(*newStyle, { document, parentStyle }, matchResult, { });
+ Style::Builder styleBuilder(*newStyle, { document, parentStyle }, matchResult, { });
styleBuilder.applyPropertyValue(CSSPropertyFontFamily, parsedStyle->getPropertyCSSValue(CSSPropertyFontFamily).get());
styleBuilder.applyPropertyValue(CSSPropertyFontStyle, parsedStyle->getPropertyCSSValue(CSSPropertyFontStyle).get());
Modified: trunk/Source/WebCore/html/canvas/CanvasRenderingContext2DBase.cpp (252627 => 252628)
--- trunk/Source/WebCore/html/canvas/CanvasRenderingContext2DBase.cpp 2019-11-19 15:26:13 UTC (rev 252627)
+++ trunk/Source/WebCore/html/canvas/CanvasRenderingContext2DBase.cpp 2019-11-19 15:34:28 UTC (rev 252628)
@@ -1871,7 +1871,7 @@
compositeBuffer(*buffer, bufferRect, op);
}
-static CanvasRenderingContext2DBase::Style toStyle(const CanvasStyle& style)
+static CanvasRenderingContext2DBase::StyleVariant toStyleVariant(const CanvasStyle& style)
{
if (auto gradient = style.canvasGradient())
return gradient;
@@ -1880,12 +1880,12 @@
return style.color();
}
-CanvasRenderingContext2DBase::Style CanvasRenderingContext2DBase::strokeStyle() const
+CanvasRenderingContext2DBase::StyleVariant CanvasRenderingContext2DBase::strokeStyle() const
{
- return toStyle(state().strokeStyle);
+ return toStyleVariant(state().strokeStyle);
}
-void CanvasRenderingContext2DBase::setStrokeStyle(CanvasRenderingContext2DBase::Style&& style)
+void CanvasRenderingContext2DBase::setStrokeStyle(CanvasRenderingContext2DBase::StyleVariant&& style)
{
WTF::switchOn(style,
[this] (const String& string) { this->setStrokeColor(string); },
@@ -1894,12 +1894,12 @@
);
}
-CanvasRenderingContext2DBase::Style CanvasRenderingContext2DBase::fillStyle() const
+CanvasRenderingContext2DBase::StyleVariant CanvasRenderingContext2DBase::fillStyle() const
{
- return toStyle(state().fillStyle);
+ return toStyleVariant(state().fillStyle);
}
-void CanvasRenderingContext2DBase::setFillStyle(CanvasRenderingContext2DBase::Style&& style)
+void CanvasRenderingContext2DBase::setFillStyle(CanvasRenderingContext2DBase::StyleVariant&& style)
{
WTF::switchOn(style,
[this] (const String& string) { this->setFillColor(string); },
Modified: trunk/Source/WebCore/html/canvas/CanvasRenderingContext2DBase.h (252627 => 252628)
--- trunk/Source/WebCore/html/canvas/CanvasRenderingContext2DBase.h 2019-11-19 15:26:13 UTC (rev 252627)
+++ trunk/Source/WebCore/html/canvas/CanvasRenderingContext2DBase.h 2019-11-19 15:34:28 UTC (rev 252628)
@@ -179,11 +179,11 @@
void drawImageFromRect(HTMLImageElement&, float sx = 0, float sy = 0, float sw = 0, float sh = 0, float dx = 0, float dy = 0, float dw = 0, float dh = 0, const String& compositeOperation = emptyString());
- using Style = Variant<String, RefPtr<CanvasGradient>, RefPtr<CanvasPattern>>;
- Style strokeStyle() const;
- void setStrokeStyle(Style&&);
- Style fillStyle() const;
- void setFillStyle(Style&&);
+ using StyleVariant = Variant<String, RefPtr<CanvasGradient>, RefPtr<CanvasPattern>>;
+ StyleVariant strokeStyle() const;
+ void setStrokeStyle(StyleVariant&&);
+ StyleVariant fillStyle() const;
+ void setFillStyle(StyleVariant&&);
ExceptionOr<Ref<CanvasGradient>> createLinearGradient(float x0, float y0, float x1, float y1);
ExceptionOr<Ref<CanvasGradient>> createRadialGradient(float x0, float y0, float r0, float x1, float y1, float r1);
Modified: trunk/Source/WebCore/inspector/InspectorCanvas.cpp (252627 => 252628)
--- trunk/Source/WebCore/inspector/InspectorCanvas.cpp 2019-11-19 15:26:13 UTC (rev 252627)
+++ trunk/Source/WebCore/inspector/InspectorCanvas.cpp 2019-11-19 15:34:28 UTC (rev 252628)
@@ -1064,7 +1064,7 @@
[&] (const CanvasImageSource& value) {
WTF::visit(parseParameter, value);
},
- [&] (const CanvasRenderingContext2DBase::Style& value) {
+ [&] (const CanvasRenderingContext2DBase::StyleVariant& value) {
WTF::visit(parseParameter, value);
},
#if ENABLE(WEBGL)
Modified: trunk/Source/WebCore/page/FrameView.cpp (252627 => 252628)
--- trunk/Source/WebCore/page/FrameView.cpp 2019-11-19 15:26:13 UTC (rev 252627)
+++ trunk/Source/WebCore/page/FrameView.cpp 2019-11-19 15:34:28 UTC (rev 252628)
@@ -1431,7 +1431,7 @@
StyleScrollbarState scrollbarState;
scrollbarState.scrollbarPart = ScrollbarBGPart;
scrollbarState.orientation = orientation;
- auto scrollbarStyle = renderer->getUncachedPseudoStyle(PseudoStyleRequest(PseudoId::Scrollbar, scrollbarState), &renderer->style());
+ auto scrollbarStyle = renderer->getUncachedPseudoStyle({ PseudoId::Scrollbar, scrollbarState }, &renderer->style());
return scrollbarStyle && scrollbarStyle->display() == DisplayType::None;
}
@@ -3862,7 +3862,7 @@
Element* body = doc ? doc->bodyOrFrameset() : nullptr;
if (body && body->renderer()) {
renderer = body->renderer();
- cornerStyle = renderer->getUncachedPseudoStyle(PseudoStyleRequest(PseudoId::ScrollbarCorner), &renderer->style());
+ cornerStyle = renderer->getUncachedPseudoStyle({ PseudoId::ScrollbarCorner }, &renderer->style());
}
if (!cornerStyle) {
@@ -3870,7 +3870,7 @@
Element* docElement = doc ? doc->documentElement() : nullptr;
if (docElement && docElement->renderer()) {
renderer = docElement->renderer();
- cornerStyle = renderer->getUncachedPseudoStyle(PseudoStyleRequest(PseudoId::ScrollbarCorner), &renderer->style());
+ cornerStyle = renderer->getUncachedPseudoStyle({ PseudoId::ScrollbarCorner }, &renderer->style());
}
}
@@ -3878,7 +3878,7 @@
// If we have an owning iframe/frame element, then it can set the custom scrollbar also.
// FIXME: Seems wrong to do this for cross-origin frames.
if (RenderWidget* renderer = frame().ownerRenderer())
- cornerStyle = renderer->getUncachedPseudoStyle(PseudoStyleRequest(PseudoId::ScrollbarCorner), &renderer->style());
+ cornerStyle = renderer->getUncachedPseudoStyle({ PseudoId::ScrollbarCorner }, &renderer->style());
}
}
Modified: trunk/Source/WebCore/rendering/RenderElement.cpp (252627 => 252628)
--- trunk/Source/WebCore/rendering/RenderElement.cpp 2019-11-19 15:26:13 UTC (rev 252627)
+++ trunk/Source/WebCore/rendering/RenderElement.cpp 2019-11-19 15:34:28 UTC (rev 252628)
@@ -1358,15 +1358,15 @@
if (cachedStyle)
return cachedStyle;
- std::unique_ptr<RenderStyle> result = getUncachedPseudoStyle(PseudoStyleRequest(pseudo), parentStyle);
+ std::unique_ptr<RenderStyle> result = getUncachedPseudoStyle({ pseudo }, parentStyle);
if (result)
return const_cast<RenderStyle&>(m_style).addCachedPseudoStyle(WTFMove(result));
return nullptr;
}
-std::unique_ptr<RenderStyle> RenderElement::getUncachedPseudoStyle(const PseudoStyleRequest& pseudoStyleRequest, const RenderStyle* parentStyle, const RenderStyle* ownStyle) const
+std::unique_ptr<RenderStyle> RenderElement::getUncachedPseudoStyle(const Style::PseudoElementRequest& pseudoElementRequest, const RenderStyle* parentStyle, const RenderStyle* ownStyle) const
{
- if (pseudoStyleRequest.pseudoId < PseudoId::FirstInternalPseudoId && !ownStyle && !style().hasPseudoStyle(pseudoStyleRequest.pseudoId))
+ if (pseudoElementRequest.pseudoId < PseudoId::FirstInternalPseudoId && !ownStyle && !style().hasPseudoStyle(pseudoElementRequest.pseudoId))
return nullptr;
if (!parentStyle) {
@@ -1379,7 +1379,7 @@
auto& styleResolver = element()->styleResolver();
- std::unique_ptr<RenderStyle> style = styleResolver.pseudoStyleForElement(*element(), pseudoStyleRequest, *parentStyle);
+ std::unique_ptr<RenderStyle> style = styleResolver.pseudoStyleForElement(*element(), pseudoElementRequest, *parentStyle);
if (style)
Style::loadPendingResources(*style, document(), element());
@@ -1415,11 +1415,11 @@
if (ShadowRoot* root = element()->containingShadowRoot()) {
if (root->mode() == ShadowRootMode::UserAgent) {
if (Element* shadowHost = element()->shadowHost())
- return shadowHost->renderer()->getUncachedPseudoStyle(PseudoStyleRequest(PseudoId::Selection));
+ return shadowHost->renderer()->getUncachedPseudoStyle({ PseudoId::Selection });
}
}
- return getUncachedPseudoStyle(PseudoStyleRequest(PseudoId::Selection));
+ return getUncachedPseudoStyle({ PseudoId::Selection });
}
Color RenderElement::selectionForegroundColor() const
Modified: trunk/Source/WebCore/rendering/RenderElement.h (252627 => 252628)
--- trunk/Source/WebCore/rendering/RenderElement.h 2019-11-19 15:26:13 UTC (rev 252627)
+++ trunk/Source/WebCore/rendering/RenderElement.h 2019-11-19 15:34:28 UTC (rev 252628)
@@ -58,7 +58,7 @@
// The pseudo element style can be cached or uncached. Use the cached method if the pseudo element doesn't respect
// any pseudo classes (and therefore has no concept of changing state).
const RenderStyle* getCachedPseudoStyle(PseudoId, const RenderStyle* parentStyle = nullptr) const;
- std::unique_ptr<RenderStyle> getUncachedPseudoStyle(const PseudoStyleRequest&, const RenderStyle* parentStyle = nullptr, const RenderStyle* ownStyle = nullptr) const;
+ std::unique_ptr<RenderStyle> getUncachedPseudoStyle(const Style::PseudoElementRequest&, const RenderStyle* parentStyle = nullptr, const RenderStyle* ownStyle = nullptr) const;
// This is null for anonymous renderers.
Element* element() const { return downcast<Element>(RenderObject::node()); }
Modified: trunk/Source/WebCore/rendering/RenderLayer.cpp (252627 => 252628)
--- trunk/Source/WebCore/rendering/RenderLayer.cpp 2019-11-19 15:26:13 UTC (rev 252627)
+++ trunk/Source/WebCore/rendering/RenderLayer.cpp 2019-11-19 15:34:28 UTC (rev 252628)
@@ -6698,7 +6698,7 @@
void RenderLayer::updateScrollCornerStyle()
{
RenderElement* actualRenderer = rendererForScrollbar(renderer());
- auto corner = renderer().hasOverflowClip() ? actualRenderer->getUncachedPseudoStyle(PseudoStyleRequest(PseudoId::ScrollbarCorner), &actualRenderer->style()) : nullptr;
+ auto corner = renderer().hasOverflowClip() ? actualRenderer->getUncachedPseudoStyle({ PseudoId::ScrollbarCorner }, &actualRenderer->style()) : nullptr;
if (!corner) {
clearScrollCorner();
@@ -6725,7 +6725,7 @@
void RenderLayer::updateResizerStyle()
{
RenderElement* actualRenderer = rendererForScrollbar(renderer());
- auto resizer = renderer().hasOverflowClip() ? actualRenderer->getUncachedPseudoStyle(PseudoStyleRequest(PseudoId::Resizer), &actualRenderer->style()) : nullptr;
+ auto resizer = renderer().hasOverflowClip() ? actualRenderer->getUncachedPseudoStyle({ PseudoId::Resizer }, &actualRenderer->style()) : nullptr;
if (!resizer) {
clearResizer();
Modified: trunk/Source/WebCore/rendering/RenderObject.h (252627 => 252628)
--- trunk/Source/WebCore/rendering/RenderObject.h 2019-11-19 15:26:13 UTC (rev 252627)
+++ trunk/Source/WebCore/rendering/RenderObject.h 2019-11-19 15:34:28 UTC (rev 252628)
@@ -53,7 +53,6 @@
class InlineBox;
class Path;
class Position;
-class PseudoStyleRequest;
class RenderBoxModelObject;
class RenderInline;
class RenderBlock;
@@ -85,6 +84,10 @@
struct ScrollRectToVisibleOptions;
+namespace Style {
+class PseudoElementRequest;
+}
+
// Base class for all rendering tree objects.
class RenderObject : public CachedImageClient, public CanMakeWeakPtr<RenderObject> {
WTF_MAKE_ISO_ALLOCATED(RenderObject);
Modified: trunk/Source/WebCore/rendering/RenderScrollbar.cpp (252627 => 252628)
--- trunk/Source/WebCore/rendering/RenderScrollbar.cpp 2019-11-19 15:26:13 UTC (rev 252627)
+++ trunk/Source/WebCore/rendering/RenderScrollbar.cpp 2019-11-19 15:34:28 UTC (rev 252628)
@@ -150,7 +150,7 @@
scrollbarState.enabled = enabled();
scrollbarState.scrollCornerIsVisible = scrollableArea().isScrollCornerVisible();
- std::unique_ptr<RenderStyle> result = owningRenderer()->getUncachedPseudoStyle(PseudoStyleRequest(pseudoId, scrollbarState), &owningRenderer()->style());
+ std::unique_ptr<RenderStyle> result = owningRenderer()->getUncachedPseudoStyle({ pseudoId, scrollbarState }, &owningRenderer()->style());
// Scrollbars for root frames should always have background color
// unless explicitly specified as transparent. So we force it.
// This is because WebKit assumes scrollbar to be always painted and missing background
Modified: trunk/Source/WebCore/rendering/updating/RenderTreeUpdater.cpp (252627 => 252628)
--- trunk/Source/WebCore/rendering/updating/RenderTreeUpdater.cpp 2019-11-19 15:26:13 UTC (rev 252627)
+++ trunk/Source/WebCore/rendering/updating/RenderTreeUpdater.cpp 2019-11-19 15:34:28 UTC (rev 252628)
@@ -279,7 +279,7 @@
for (auto& cache : *pseudoStyleCache) {
PseudoId pseudoId = cache->styleType();
- std::unique_ptr<RenderStyle> newPseudoStyle = renderer->getUncachedPseudoStyle(PseudoStyleRequest(pseudoId), newStyle, newStyle);
+ std::unique_ptr<RenderStyle> newPseudoStyle = renderer->getUncachedPseudoStyle({ pseudoId }, newStyle, newStyle);
if (!newPseudoStyle)
return true;
if (*newPseudoStyle != *cache) {
Copied: trunk/Source/WebCore/style/ElementRuleCollector.cpp (from rev 252627, trunk/Source/WebCore/css/ElementRuleCollector.cpp) (0 => 252628)
--- trunk/Source/WebCore/style/ElementRuleCollector.cpp (rev 0)
+++ trunk/Source/WebCore/style/ElementRuleCollector.cpp 2019-11-19 15:34:28 UTC (rev 252628)
@@ -0,0 +1,678 @@
+/*
+ * Copyright (C) 1999 Lars Knoll ([email protected])
+ * (C) 2004-2005 Allan Sandfeld Jensen ([email protected])
+ * Copyright (C) 2006, 2007 Nicholas Shanks ([email protected])
+ * Copyright (C) 2005-2018 Apple Inc. All rights reserved.
+ * Copyright (C) 2007 Alexey Proskuryakov <[email protected]>
+ * Copyright (C) 2007, 2008 Eric Seidel <[email protected]>
+ * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
+ * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ * Copyright (C) Research In Motion Limited 2011. All rights reserved.
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+#include "ElementRuleCollector.h"
+
+#include "CSSDefaultStyleSheets.h"
+#include "CSSRuleList.h"
+#include "CSSSelector.h"
+#include "CSSValueKeywords.h"
+#include "HTMLElement.h"
+#include "HTMLSlotElement.h"
+#include "SVGElement.h"
+#include "SelectorCompiler.h"
+#include "SelectorFilter.h"
+#include "ShadowRoot.h"
+#include "StyleProperties.h"
+#include "StyleResolver.h"
+#include "StyleScope.h"
+#include "StyleScopeRuleSets.h"
+#include "StyledElement.h"
+#include <wtf/SetForScope.h>
+
+namespace WebCore {
+namespace Style {
+
+static const StyleProperties& leftToRightDeclaration()
+{
+ static auto& declaration = [] () -> const StyleProperties& {
+ auto properties = MutableStyleProperties::create();
+ properties->setProperty(CSSPropertyDirection, CSSValueLtr);
+ return properties.leakRef();
+ }();
+ return declaration;
+}
+
+static const StyleProperties& rightToLeftDeclaration()
+{
+ static auto& declaration = [] () -> const StyleProperties& {
+ auto properties = MutableStyleProperties::create();
+ properties->setProperty(CSSPropertyDirection, CSSValueRtl);
+ return properties.leakRef();
+ }();
+ return declaration;
+}
+
+class MatchRequest {
+public:
+ MatchRequest(const RuleSet* ruleSet, ScopeOrdinal styleScopeOrdinal = ScopeOrdinal::Element)
+ : ruleSet(ruleSet)
+ , styleScopeOrdinal(styleScopeOrdinal)
+ {
+ }
+ const RuleSet* ruleSet;
+ ScopeOrdinal styleScopeOrdinal;
+};
+
+ElementRuleCollector::ElementRuleCollector(const Element& element, const ScopeRuleSets& ruleSets, const SelectorFilter* selectorFilter)
+ : m_element(element)
+ , m_authorStyle(ruleSets.authorStyle())
+ , m_userStyle(ruleSets.userStyle())
+ , m_userAgentMediaQueryStyle(ruleSets.userAgentMediaQueryStyle())
+ , m_selectorFilter(selectorFilter)
+{
+ ASSERT(!m_selectorFilter || m_selectorFilter->parentStackIsConsistent(element.parentNode()));
+}
+
+ElementRuleCollector::ElementRuleCollector(const Element& element, const RuleSet& authorStyle, const SelectorFilter* selectorFilter)
+ : m_element(element)
+ , m_authorStyle(authorStyle)
+ , m_selectorFilter(selectorFilter)
+{
+ ASSERT(!m_selectorFilter || m_selectorFilter->parentStackIsConsistent(element.parentNode()));
+}
+
+const MatchResult& ElementRuleCollector::matchResult() const
+{
+ ASSERT(m_mode == SelectorChecker::Mode::ResolvingStyle);
+ return m_result;
+}
+
+const Vector<RefPtr<StyleRule>>& ElementRuleCollector::matchedRuleList() const
+{
+ ASSERT(m_mode == SelectorChecker::Mode::CollectingRules);
+ return m_matchedRuleList;
+}
+
+inline void ElementRuleCollector::addMatchedRule(const RuleData& ruleData, unsigned specificity, ScopeOrdinal styleScopeOrdinal)
+{
+ m_matchedRules.append({ &ruleData, specificity, styleScopeOrdinal });
+}
+
+void ElementRuleCollector::clearMatchedRules()
+{
+ m_matchedRules.clear();
+ m_keepAliveSlottedPseudoElementRules.clear();
+ m_matchedRuleTransferIndex = 0;
+}
+
+inline void ElementRuleCollector::addElementStyleProperties(const StyleProperties* propertySet, bool isCacheable)
+{
+ if (!propertySet || propertySet->isEmpty())
+ return;
+
+ if (!isCacheable)
+ m_result.isCacheable = false;
+
+ addMatchedProperties({ propertySet }, DeclarationOrigin::Author);
+}
+
+void ElementRuleCollector::collectMatchingRules(const MatchRequest& matchRequest)
+{
+ ASSERT(matchRequest.ruleSet);
+ ASSERT_WITH_MESSAGE(!(m_mode == SelectorChecker::Mode::CollectingRulesIgnoringVirtualPseudoElements && m_pseudoElementRequest.pseudoId != PseudoId::None), "When in StyleInvalidation or SharingRules, SelectorChecker does not try to match the pseudo ID. While ElementRuleCollector supports matching a particular pseudoId in this case, this would indicate a error at the call site since matching a particular element should be unnecessary.");
+
+ auto* shadowRoot = element().containingShadowRoot();
+ if (shadowRoot && shadowRoot->mode() == ShadowRootMode::UserAgent)
+ collectMatchingShadowPseudoElementRules(matchRequest);
+
+ // We need to collect the rules for id, class, tag, and everything else into a buffer and
+ // then sort the buffer.
+ auto& id = element().idForStyleResolution();
+ if (!id.isNull())
+ collectMatchingRulesForList(matchRequest.ruleSet->idRules(id), matchRequest);
+ if (element().hasClass()) {
+ for (size_t i = 0; i < element().classNames().size(); ++i)
+ collectMatchingRulesForList(matchRequest.ruleSet->classRules(element().classNames()[i]), matchRequest);
+ }
+
+ if (element().isLink())
+ collectMatchingRulesForList(matchRequest.ruleSet->linkPseudoClassRules(), matchRequest);
+ if (SelectorChecker::matchesFocusPseudoClass(element()))
+ collectMatchingRulesForList(matchRequest.ruleSet->focusPseudoClassRules(), matchRequest);
+ collectMatchingRulesForList(matchRequest.ruleSet->tagRules(element().localName(), element().isHTMLElement() && element().document().isHTMLDocument()), matchRequest);
+ collectMatchingRulesForList(matchRequest.ruleSet->universalRules(), matchRequest);
+}
+
+
+Vector<MatchedProperties>& ElementRuleCollector::declarationsForOrigin(MatchResult& matchResult, DeclarationOrigin declarationOrigin)
+{
+ switch (declarationOrigin) {
+ case DeclarationOrigin::UserAgent: return matchResult.userAgentDeclarations;
+ case DeclarationOrigin::User: return matchResult.userDeclarations;
+ case DeclarationOrigin::Author: return matchResult.authorDeclarations;
+ }
+ ASSERT_NOT_REACHED();
+ return matchResult.authorDeclarations;
+}
+
+void ElementRuleCollector::sortAndTransferMatchedRules(DeclarationOrigin declarationOrigin)
+{
+ if (m_matchedRules.isEmpty())
+ return;
+
+ sortMatchedRules();
+
+ transferMatchedRules(declarationOrigin);
+}
+
+void ElementRuleCollector::transferMatchedRules(DeclarationOrigin declarationOrigin, Optional<ScopeOrdinal> fromScope)
+{
+ if (m_mode != SelectorChecker::Mode::CollectingRules)
+ declarationsForOrigin(m_result, declarationOrigin).reserveCapacity(m_matchedRules.size());
+
+ for (; m_matchedRuleTransferIndex < m_matchedRules.size(); ++m_matchedRuleTransferIndex) {
+ auto& matchedRule = m_matchedRules[m_matchedRuleTransferIndex];
+ if (fromScope && matchedRule.styleScopeOrdinal < *fromScope)
+ break;
+
+ if (m_mode == SelectorChecker::Mode::CollectingRules) {
+ m_matchedRuleList.append(matchedRule.ruleData->rule());
+ continue;
+ }
+
+ addMatchedProperties({
+ &matchedRule.ruleData->rule()->properties(),
+ static_cast<uint16_t>(matchedRule.ruleData->linkMatchType()),
+ static_cast<uint16_t>(matchedRule.ruleData->propertyWhitelistType()),
+ matchedRule.styleScopeOrdinal
+ }, declarationOrigin);
+ }
+}
+
+void ElementRuleCollector::matchAuthorRules()
+{
+ clearMatchedRules();
+
+ collectMatchingAuthorRules();
+
+ sortAndTransferMatchedRules(DeclarationOrigin::Author);
+}
+
+bool ElementRuleCollector::matchesAnyAuthorRules()
+{
+ clearMatchedRules();
+
+ // FIXME: This should bail out on first match.
+ collectMatchingAuthorRules();
+
+ return !m_matchedRules.isEmpty();
+}
+
+void ElementRuleCollector::collectMatchingAuthorRules()
+{
+ {
+ MatchRequest matchRequest(&m_authorStyle);
+ collectMatchingRules(matchRequest);
+ }
+
+ auto* parent = element().parentElement();
+ if (parent && parent->shadowRoot())
+ matchSlottedPseudoElementRules();
+
+ if (element().shadowRoot())
+ matchHostPseudoClassRules();
+
+ if (element().isInShadowTree()) {
+ matchAuthorShadowPseudoElementRules();
+ matchPartPseudoElementRules();
+ }
+}
+
+void ElementRuleCollector::matchAuthorShadowPseudoElementRules()
+{
+ ASSERT(element().isInShadowTree());
+ auto& shadowRoot = *element().containingShadowRoot();
+ if (shadowRoot.mode() != ShadowRootMode::UserAgent)
+ return;
+ // Look up shadow pseudo elements also from the host scope author style as they are web-exposed.
+ auto& hostAuthorRules = Scope::forNode(*shadowRoot.host()).resolver().ruleSets().authorStyle();
+ MatchRequest hostAuthorRequest { &hostAuthorRules, ScopeOrdinal::ContainingHost };
+ collectMatchingShadowPseudoElementRules(hostAuthorRequest);
+}
+
+void ElementRuleCollector::matchHostPseudoClassRules()
+{
+ ASSERT(element().shadowRoot());
+
+ auto& shadowAuthorStyle = element().shadowRoot()->styleScope().resolver().ruleSets().authorStyle();
+ auto& shadowHostRules = shadowAuthorStyle.hostPseudoClassRules();
+ if (shadowHostRules.isEmpty())
+ return;
+
+ SetForScope<bool> change(m_isMatchingHostPseudoClass, true);
+
+ MatchRequest hostMatchRequest { nullptr, ScopeOrdinal::Shadow };
+ collectMatchingRulesForList(&shadowHostRules, hostMatchRequest);
+}
+
+void ElementRuleCollector::matchSlottedPseudoElementRules()
+{
+ auto* slot = element().assignedSlot();
+ auto styleScopeOrdinal = ScopeOrdinal::FirstSlot;
+
+ for (; slot; slot = slot->assignedSlot(), ++styleScopeOrdinal) {
+ auto& styleScope = Scope::forNode(*slot);
+ if (!styleScope.resolver().ruleSets().isAuthorStyleDefined())
+ continue;
+ // Find out if there are any ::slotted rules in the shadow tree matching the current slot.
+ // FIXME: This is really part of the slot style and could be cached when resolving it.
+ ElementRuleCollector collector(*slot, styleScope.resolver().ruleSets().authorStyle(), nullptr);
+ auto slottedPseudoElementRules = collector.collectSlottedPseudoElementRulesForSlot();
+ if (!slottedPseudoElementRules)
+ continue;
+ // Match in the current scope.
+ SetForScope<bool> change(m_isMatchingSlottedPseudoElements, true);
+
+ MatchRequest scopeMatchRequest(nullptr, styleScopeOrdinal);
+ collectMatchingRulesForList(slottedPseudoElementRules.get(), scopeMatchRequest);
+
+ m_keepAliveSlottedPseudoElementRules.append(WTFMove(slottedPseudoElementRules));
+ }
+}
+
+void ElementRuleCollector::matchPartPseudoElementRules()
+{
+ ASSERT(element().isInShadowTree());
+
+ bool isUAShadowPseudoElement = element().containingShadowRoot()->mode() == ShadowRootMode::UserAgent && !element().shadowPseudoId().isNull();
+
+ auto& partMatchingElement = isUAShadowPseudoElement ? *element().shadowHost() : element();
+ if (partMatchingElement.partNames().isEmpty() || !partMatchingElement.isInShadowTree())
+ return;
+
+ matchPartPseudoElementRulesForScope(*partMatchingElement.containingShadowRoot());
+}
+
+void ElementRuleCollector::matchPartPseudoElementRulesForScope(const ShadowRoot& scopeShadowRoot)
+{
+ auto& shadowHost = *scopeShadowRoot.host();
+ {
+ SetForScope<RefPtr<const Element>> partMatchingScope(m_shadowHostInPartRuleScope, &shadowHost);
+
+ auto& hostAuthorRules = Scope::forNode(shadowHost).resolver().ruleSets().authorStyle();
+ MatchRequest hostAuthorRequest { &hostAuthorRules, ScopeOrdinal::ContainingHost };
+ collectMatchingRulesForList(&hostAuthorRules.partPseudoElementRules(), hostAuthorRequest);
+ }
+
+ // Element may be exposed to styling from enclosing scopes via exportparts attributes.
+ if (scopeShadowRoot.partMappings().isEmpty())
+ return;
+
+ if (auto* parentScopeShadowRoot = shadowHost.containingShadowRoot())
+ matchPartPseudoElementRulesForScope(*parentScopeShadowRoot);
+}
+
+void ElementRuleCollector::collectMatchingShadowPseudoElementRules(const MatchRequest& matchRequest)
+{
+ ASSERT(matchRequest.ruleSet);
+ ASSERT(element().containingShadowRoot()->mode() == ShadowRootMode::UserAgent);
+
+ auto& rules = *matchRequest.ruleSet;
+#if ENABLE(VIDEO_TRACK)
+ // FXIME: WebVTT should not be done by styling UA shadow trees like this.
+ if (element().isWebVTTElement())
+ collectMatchingRulesForList(rules.cuePseudoRules(), matchRequest);
+#endif
+ auto& pseudoId = element().shadowPseudoId();
+ if (!pseudoId.isEmpty())
+ collectMatchingRulesForList(rules.shadowPseudoElementRules(pseudoId), matchRequest);
+}
+
+std::unique_ptr<RuleSet::RuleDataVector> ElementRuleCollector::collectSlottedPseudoElementRulesForSlot()
+{
+ ASSERT(is<HTMLSlotElement>(element()));
+
+ clearMatchedRules();
+
+ m_mode = SelectorChecker::Mode::CollectingRules;
+
+ // Match global author rules.
+ MatchRequest matchRequest(&m_authorStyle);
+ collectMatchingRulesForList(&m_authorStyle.slottedPseudoElementRules(), matchRequest);
+
+ if (m_matchedRules.isEmpty())
+ return { };
+
+ auto ruleDataVector = makeUnique<RuleSet::RuleDataVector>();
+ ruleDataVector->reserveInitialCapacity(m_matchedRules.size());
+ for (auto& matchedRule : m_matchedRules)
+ ruleDataVector->uncheckedAppend(*matchedRule.ruleData);
+
+ return ruleDataVector;
+}
+
+void ElementRuleCollector::matchUserRules()
+{
+ if (!m_userStyle)
+ return;
+
+ clearMatchedRules();
+
+ MatchRequest matchRequest(m_userStyle);
+ collectMatchingRules(matchRequest);
+
+ sortAndTransferMatchedRules(DeclarationOrigin::User);
+}
+
+void ElementRuleCollector::matchUARules()
+{
+ // First we match rules from the user agent sheet.
+ if (CSSDefaultStyleSheets::simpleDefaultStyleSheet)
+ m_result.isCacheable = false;
+ auto* userAgentStyleSheet = m_isPrintStyle
+ ? CSSDefaultStyleSheets::defaultPrintStyle : CSSDefaultStyleSheets::defaultStyle;
+ matchUARules(*userAgentStyleSheet);
+
+ // In quirks mode, we match rules from the quirks user agent sheet.
+ if (element().document().inQuirksMode())
+ matchUARules(*CSSDefaultStyleSheets::defaultQuirksStyle);
+
+ if (m_userAgentMediaQueryStyle)
+ matchUARules(*m_userAgentMediaQueryStyle);
+}
+
+void ElementRuleCollector::matchUARules(const RuleSet& rules)
+{
+ clearMatchedRules();
+
+ collectMatchingRules(MatchRequest(&rules));
+
+ sortAndTransferMatchedRules(DeclarationOrigin::UserAgent);
+}
+
+static const CSSSelector* findSlottedPseudoElementSelector(const CSSSelector* selector)
+{
+ for (; selector; selector = selector->tagHistory()) {
+ if (selector->match() == CSSSelector::PseudoElement && selector->pseudoElementType() == CSSSelector::PseudoElementSlotted) {
+ if (auto* list = selector->selectorList())
+ return list->first();
+ break;
+ }
+ };
+ return nullptr;
+}
+
+inline bool ElementRuleCollector::ruleMatches(const RuleData& ruleData, unsigned& specificity)
+{
+ // We know a sufficiently simple single part selector matches simply because we found it from the rule hash when filtering the RuleSet.
+ // This is limited to HTML only so we don't need to check the namespace (because of tag name match).
+ auto matchBasedOnRuleHash = ruleData.matchBasedOnRuleHash();
+ if (matchBasedOnRuleHash != MatchBasedOnRuleHash::None && element().isHTMLElement()) {
+ ASSERT_WITH_MESSAGE(m_pseudoElementRequest.pseudoId == PseudoId::None, "If we match based on the rule hash while collecting for a particular pseudo element ID, we would add incorrect rules for that pseudo element ID. We should never end in ruleMatches() with a pseudo element if the ruleData cannot match any pseudo element.");
+
+ switch (matchBasedOnRuleHash) {
+ case MatchBasedOnRuleHash::None:
+ ASSERT_NOT_REACHED();
+ break;
+ case MatchBasedOnRuleHash::Universal:
+ specificity = 0;
+ break;
+ case MatchBasedOnRuleHash::ClassA:
+ specificity = static_cast<unsigned>(SelectorSpecificityIncrement::ClassA);
+ break;
+ case MatchBasedOnRuleHash::ClassB:
+ specificity = static_cast<unsigned>(SelectorSpecificityIncrement::ClassB);
+ break;
+ case MatchBasedOnRuleHash::ClassC:
+ specificity = static_cast<unsigned>(SelectorSpecificityIncrement::ClassC);
+ break;
+ }
+ return true;
+ }
+
+#if ENABLE(CSS_SELECTOR_JIT)
+ auto& compiledSelector = ruleData.rule()->compiledSelectorForListIndex(ruleData.selectorListIndex());
+ void* compiledSelectorChecker = compiledSelector.codeRef.code().executableAddress();
+ if (!compiledSelectorChecker && compiledSelector.status == SelectorCompilationStatus::NotCompiled) {
+ compiledSelector.status = SelectorCompiler::compileSelector(ruleData.selector(), SelectorCompiler::SelectorContext::RuleCollector, compiledSelector.codeRef);
+
+ compiledSelectorChecker = compiledSelector.codeRef.code().executableAddress();
+ }
+
+ if (compiledSelectorChecker && compiledSelector.status == SelectorCompilationStatus::SimpleSelectorChecker) {
+ auto selectorChecker = SelectorCompiler::ruleCollectorSimpleSelectorCheckerFunction(compiledSelectorChecker, compiledSelector.status);
+#if !ASSERT_MSG_DISABLED
+ unsigned ignoreSpecificity;
+ ASSERT_WITH_MESSAGE(!selectorChecker(&element(), &ignoreSpecificity) || m_pseudoElementRequest.pseudoId == PseudoId::None, "When matching pseudo elements, we should never compile a selector checker without context unless it cannot match anything.");
+#endif
+#if CSS_SELECTOR_JIT_PROFILING
+ ruleData.compiledSelectorUsed();
+#endif
+ bool selectorMatches = selectorChecker(&element(), &specificity);
+
+ if (selectorMatches && ruleData.containsUncommonAttributeSelector())
+ m_didMatchUncommonAttributeSelector = true;
+
+ return selectorMatches;
+ }
+#endif // ENABLE(CSS_SELECTOR_JIT)
+
+ SelectorChecker::CheckingContext context(m_mode);
+ context.pseudoId = m_pseudoElementRequest.pseudoId;
+ context.scrollbarState = m_pseudoElementRequest.scrollbarState;
+ context.isMatchingHostPseudoClass = m_isMatchingHostPseudoClass;
+ context.shadowHostInPartRuleScope = m_shadowHostInPartRuleScope.get();
+
+ bool selectorMatches;
+#if ENABLE(CSS_SELECTOR_JIT)
+ if (compiledSelectorChecker) {
+ ASSERT(compiledSelector.status == SelectorCompilationStatus::SelectorCheckerWithCheckingContext);
+
+ auto selectorChecker = SelectorCompiler::ruleCollectorSelectorCheckerFunctionWithCheckingContext(compiledSelectorChecker, compiledSelector.status);
+
+#if CSS_SELECTOR_JIT_PROFILING
+ compiledSelector.useCount++;
+#endif
+ selectorMatches = selectorChecker(&element(), &context, &specificity);
+ } else
+#endif // ENABLE(CSS_SELECTOR_JIT)
+ {
+ auto* selector = ruleData.selector();
+ if (m_isMatchingSlottedPseudoElements) {
+ selector = findSlottedPseudoElementSelector(ruleData.selector());
+ if (!selector)
+ return false;
+ }
+ // Slow path.
+ SelectorChecker selectorChecker(element().document());
+ selectorMatches = selectorChecker.match(*selector, element(), context, specificity);
+ }
+
+ if (ruleData.containsUncommonAttributeSelector()) {
+ if (selectorMatches || context.pseudoIDSet)
+ m_didMatchUncommonAttributeSelector = true;
+ }
+ m_matchedPseudoElementIds.merge(context.pseudoIDSet);
+ m_styleRelations.appendVector(context.styleRelations);
+
+ return selectorMatches;
+}
+
+void ElementRuleCollector::collectMatchingRulesForList(const RuleSet::RuleDataVector* rules, const MatchRequest& matchRequest)
+{
+ if (!rules)
+ return;
+
+ for (unsigned i = 0, size = rules->size(); i < size; ++i) {
+ const auto& ruleData = rules->data()[i];
+
+ if (!ruleData.canMatchPseudoElement() && m_pseudoElementRequest.pseudoId != PseudoId::None)
+ continue;
+
+ if (m_selectorFilter && m_selectorFilter->fastRejectSelector(ruleData.descendantSelectorIdentifierHashes()))
+ continue;
+
+ StyleRule* rule = ruleData.rule();
+
+ // If the rule has no properties to apply, then ignore it in the non-debug mode.
+ // Note that if we get null back here, it means we have a rule with deferred properties,
+ // and that means we always have to consider it.
+ const StyleProperties* properties = rule->propertiesWithoutDeferredParsing();
+ if (properties && properties->isEmpty() && !m_shouldIncludeEmptyRules)
+ continue;
+
+ unsigned specificity;
+ if (ruleMatches(ruleData, specificity))
+ addMatchedRule(ruleData, specificity, matchRequest.styleScopeOrdinal);
+ }
+}
+
+static inline bool compareRules(MatchedRule r1, MatchedRule r2)
+{
+ // For normal properties the earlier scope wins. This may be reversed by !important which is handled when resolving cascade.
+ if (r1.styleScopeOrdinal != r2.styleScopeOrdinal)
+ return r1.styleScopeOrdinal > r2.styleScopeOrdinal;
+
+ if (r1.specificity != r2.specificity)
+ return r1.specificity < r2.specificity;
+
+ return r1.ruleData->position() < r2.ruleData->position();
+}
+
+void ElementRuleCollector::sortMatchedRules()
+{
+ std::sort(m_matchedRules.begin(), m_matchedRules.end(), compareRules);
+}
+
+void ElementRuleCollector::matchAllRules(bool matchAuthorAndUserStyles, bool includeSMILProperties)
+{
+ matchUARules();
+
+ // Now we check user sheet rules.
+ if (matchAuthorAndUserStyles)
+ matchUserRules();
+
+ // Now check author rules, beginning first with presentational attributes mapped from HTML.
+ if (is<StyledElement>(element())) {
+ auto& styledElement = downcast<StyledElement>(element());
+ addElementStyleProperties(styledElement.presentationAttributeStyle());
+
+ // Now we check additional mapped declarations.
+ // Tables and table cells share an additional mapped rule that must be applied
+ // after all attributes, since their mapped style depends on the values of multiple attributes.
+ addElementStyleProperties(styledElement.additionalPresentationAttributeStyle());
+
+ if (is<HTMLElement>(styledElement)) {
+ bool isAuto;
+ auto textDirection = downcast<HTMLElement>(styledElement).directionalityIfhasDirAutoAttribute(isAuto);
+ auto& properties = textDirection == TextDirection::LTR ? leftToRightDeclaration() : rightToLeftDeclaration();
+ if (isAuto)
+ addMatchedProperties({ &properties }, DeclarationOrigin::Author);
+ }
+ }
+
+ if (matchAuthorAndUserStyles) {
+ clearMatchedRules();
+
+ collectMatchingAuthorRules();
+ sortMatchedRules();
+
+ transferMatchedRules(DeclarationOrigin::Author, ScopeOrdinal::Element);
+
+ // Inline style behaves as if it has higher specificity than any rule.
+ addElementInlineStyleProperties(includeSMILProperties);
+
+ // Rules from the host scope override inline style.
+ transferMatchedRules(DeclarationOrigin::Author, ScopeOrdinal::ContainingHost);
+ }
+}
+
+void ElementRuleCollector::addElementInlineStyleProperties(bool includeSMILProperties)
+{
+ if (!is<StyledElement>(element()))
+ return;
+
+ if (auto* inlineStyle = downcast<StyledElement>(element()).inlineStyle()) {
+ // FIXME: Media control shadow trees seem to have problems with caching.
+ bool isInlineStyleCacheable = !inlineStyle->isMutable() && !element().isInShadowTree();
+ addElementStyleProperties(inlineStyle, isInlineStyleCacheable);
+ }
+
+ if (includeSMILProperties && is<SVGElement>(element()))
+ addElementStyleProperties(downcast<SVGElement>(element()).animatedSMILStyleProperties(), false /* isCacheable */);
+}
+
+bool ElementRuleCollector::hasAnyMatchingRules(const RuleSet* ruleSet)
+{
+ clearMatchedRules();
+
+ m_mode = SelectorChecker::Mode::CollectingRulesIgnoringVirtualPseudoElements;
+ collectMatchingRules(MatchRequest(ruleSet));
+
+ return !m_matchedRules.isEmpty();
+}
+
+void ElementRuleCollector::addMatchedProperties(MatchedProperties&& matchedProperties, DeclarationOrigin declarationOrigin)
+{
+ // FIXME: This should be moved to the matched properties cache code.
+ auto computeIsCacheable = [&] {
+ if (!m_result.isCacheable)
+ return false;
+
+ if (matchedProperties.styleScopeOrdinal != ScopeOrdinal::Element)
+ return false;
+
+ auto& properties = *matchedProperties.properties;
+ for (unsigned i = 0, count = properties.propertyCount(); i < count; ++i) {
+ // Currently the property cache only copy the non-inherited values and resolve
+ // the inherited ones.
+ // Here we define some exception were we have to resolve some properties that are not inherited
+ // by default. If those exceptions become too common on the web, it should be possible
+ // to build a list of exception to resolve instead of completely disabling the cache.
+ StyleProperties::PropertyReference current = properties.propertyAt(i);
+ if (current.isInherited())
+ continue;
+
+ // If the property value is explicitly inherited, we need to apply further non-inherited properties
+ // as they might override the value inherited here. For this reason we don't allow declarations with
+ // explicitly inherited properties to be cached.
+ const CSSValue& value = *current.value();
+ if (value.isInheritedValue())
+ return false;
+
+ // The value currentColor has implicitely the same side effect. It depends on the value of color,
+ // which is an inherited value, making the non-inherited property implicitly inherited.
+ if (is<CSSPrimitiveValue>(value) && downcast<CSSPrimitiveValue>(value).valueID() == CSSValueCurrentcolor)
+ return false;
+
+ if (value.hasVariableReferences())
+ return false;
+ }
+
+ return true;
+ };
+
+ m_result.isCacheable = computeIsCacheable();
+
+ declarationsForOrigin(m_result, declarationOrigin).append(WTFMove(matchedProperties));
+}
+
+}
+} // namespace WebCore
Copied: trunk/Source/WebCore/style/ElementRuleCollector.h (from rev 252627, trunk/Source/WebCore/css/ElementRuleCollector.h) (0 => 252628)
--- trunk/Source/WebCore/style/ElementRuleCollector.h (rev 0)
+++ trunk/Source/WebCore/style/ElementRuleCollector.h 2019-11-19 15:34:28 UTC (rev 252628)
@@ -0,0 +1,183 @@
+/*
+ * Copyright (C) 1999 Lars Knoll ([email protected])
+ * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2013, 2014 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#pragma once
+
+#include "MediaQueryEvaluator.h"
+#include "RuleSet.h"
+#include "SelectorChecker.h"
+#include "StyleScope.h"
+#include <memory>
+#include <wtf/RefPtr.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+class SelectorFilter;
+
+namespace Style {
+
+class MatchRequest;
+class ScopeRuleSets;
+
+class PseudoElementRequest {
+public:
+ PseudoElementRequest(PseudoId pseudoId, Optional<StyleScrollbarState> scrollbarState = WTF::nullopt)
+ : pseudoId(pseudoId)
+ , scrollbarState(scrollbarState)
+ {
+ }
+
+ PseudoId pseudoId;
+ Optional<StyleScrollbarState> scrollbarState;
+};
+
+struct MatchedRule {
+ const RuleData* ruleData;
+ unsigned specificity;
+ ScopeOrdinal styleScopeOrdinal;
+};
+
+struct MatchedProperties {
+ RefPtr<const StyleProperties> properties;
+ uint16_t linkMatchType { SelectorChecker::MatchAll };
+ uint16_t whitelistType { PropertyWhitelistNone };
+ ScopeOrdinal styleScopeOrdinal { ScopeOrdinal::Element };
+};
+
+struct MatchResult {
+ bool isCacheable { true };
+ Vector<MatchedProperties> userAgentDeclarations;
+ Vector<MatchedProperties> userDeclarations;
+ Vector<MatchedProperties> authorDeclarations;
+
+ bool operator==(const MatchResult& other) const
+ {
+ return isCacheable == other.isCacheable
+ && userAgentDeclarations == other.userAgentDeclarations
+ && userDeclarations == other.userDeclarations
+ && authorDeclarations == other.authorDeclarations;
+ }
+ bool operator!=(const MatchResult& other) const { return !(*this == other); }
+
+ bool isEmpty() const { return userAgentDeclarations.isEmpty() && userDeclarations.isEmpty() && authorDeclarations.isEmpty(); }
+};
+
+class ElementRuleCollector {
+public:
+ ElementRuleCollector(const Element&, const ScopeRuleSets&, const SelectorFilter*);
+ ElementRuleCollector(const Element&, const RuleSet& authorStyle, const SelectorFilter*);
+
+ void setIncludeEmptyRules(bool value) { m_shouldIncludeEmptyRules = value; }
+
+ void matchAllRules(bool matchAuthorAndUserStyles, bool includeSMILProperties);
+ void matchUARules();
+ void matchAuthorRules();
+ void matchUserRules();
+
+ bool matchesAnyAuthorRules();
+
+ void setMode(SelectorChecker::Mode mode) { m_mode = mode; }
+ void setPseudoElementRequest(const PseudoElementRequest& request) { m_pseudoElementRequest = request; }
+ void setMedium(const MediaQueryEvaluator* medium) { m_isPrintStyle = medium->mediaTypeMatchSpecific("print"); }
+
+ bool hasAnyMatchingRules(const RuleSet*);
+
+ const MatchResult& matchResult() const;
+ const Vector<RefPtr<StyleRule>>& matchedRuleList() const;
+
+ void clearMatchedRules();
+
+ const PseudoIdSet& matchedPseudoElementIds() const { return m_matchedPseudoElementIds; }
+ const Relations& styleRelations() const { return m_styleRelations; }
+ bool didMatchUncommonAttributeSelector() const { return m_didMatchUncommonAttributeSelector; }
+
+private:
+ void addElementStyleProperties(const StyleProperties*, bool isCacheable = true);
+
+ void matchUARules(const RuleSet&);
+
+ void collectMatchingAuthorRules();
+ void addElementInlineStyleProperties(bool includeSMILProperties);
+
+ void matchAuthorShadowPseudoElementRules();
+ void matchHostPseudoClassRules();
+ void matchSlottedPseudoElementRules();
+ void matchPartPseudoElementRules();
+ void matchPartPseudoElementRulesForScope(const ShadowRoot& scopeShadowRoot);
+
+ void collectMatchingShadowPseudoElementRules(const MatchRequest&);
+ std::unique_ptr<RuleSet::RuleDataVector> collectSlottedPseudoElementRulesForSlot();
+
+ void collectMatchingRules(const MatchRequest&);
+ void collectMatchingRulesForList(const RuleSet::RuleDataVector*, const MatchRequest&);
+ bool ruleMatches(const RuleData&, unsigned &specificity);
+
+ void sortMatchedRules();
+
+ enum class DeclarationOrigin { UserAgent, User, Author };
+ static Vector<MatchedProperties>& declarationsForOrigin(MatchResult&, DeclarationOrigin);
+ void sortAndTransferMatchedRules(DeclarationOrigin);
+ void transferMatchedRules(DeclarationOrigin, Optional<ScopeOrdinal> forScope = { });
+
+ void addMatchedRule(const RuleData&, unsigned specificity, ScopeOrdinal);
+ void addMatchedProperties(MatchedProperties&&, DeclarationOrigin);
+
+ const Element& element() const { return m_element.get(); }
+
+ const Ref<const Element> m_element;
+ const RuleSet& m_authorStyle;
+ const RuleSet* m_userStyle { nullptr };
+ const RuleSet* m_userAgentMediaQueryStyle { nullptr };
+ const SelectorFilter* m_selectorFilter { nullptr };
+
+ bool m_shouldIncludeEmptyRules { false };
+ bool m_isPrintStyle { false };
+ PseudoElementRequest m_pseudoElementRequest { PseudoId::None };
+ SelectorChecker::Mode m_mode { SelectorChecker::Mode::ResolvingStyle };
+ bool m_isMatchingSlottedPseudoElements { false };
+ bool m_isMatchingHostPseudoClass { false };
+ RefPtr<const Element> m_shadowHostInPartRuleScope;
+ Vector<std::unique_ptr<RuleSet::RuleDataVector>> m_keepAliveSlottedPseudoElementRules;
+
+ Vector<MatchedRule, 64> m_matchedRules;
+ size_t m_matchedRuleTransferIndex { 0 };
+
+ // Output.
+ Vector<RefPtr<StyleRule>> m_matchedRuleList;
+ bool m_didMatchUncommonAttributeSelector { false };
+ MatchResult m_result;
+ Relations m_styleRelations;
+ PseudoIdSet m_matchedPseudoElementIds;
+};
+
+inline bool operator==(const MatchedProperties& a, const MatchedProperties& b)
+{
+ return a.properties == b.properties && a.linkMatchType == b.linkMatchType;
+}
+
+inline bool operator!=(const MatchedProperties& a, const MatchedProperties& b)
+{
+ return !(a == b);
+}
+
+} // namespace Style
+} // namespace WebCore
Copied: trunk/Source/WebCore/style/PageRuleCollector.cpp (from rev 252627, trunk/Source/WebCore/css/PageRuleCollector.cpp) (0 => 252628)
--- trunk/Source/WebCore/style/PageRuleCollector.cpp (rev 0)
+++ trunk/Source/WebCore/style/PageRuleCollector.cpp 2019-11-19 15:34:28 UTC (rev 252628)
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 1999 Lars Knoll ([email protected])
+ * (C) 2004-2005 Allan Sandfeld Jensen ([email protected])
+ * Copyright (C) 2006, 2007 Nicholas Shanks ([email protected])
+ * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 Apple Inc. All rights reserved.
+ * Copyright (C) 2007 Alexey Proskuryakov <[email protected]>
+ * Copyright (C) 2007, 2008 Eric Seidel <[email protected]>
+ * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
+ * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ * Copyright (C) Research In Motion Limited 2011. All rights reserved.
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+#include "PageRuleCollector.h"
+
+#include "CSSDefaultStyleSheets.h"
+#include "StyleProperties.h"
+#include "StyleRule.h"
+
+namespace WebCore {
+namespace Style {
+
+static inline bool comparePageRules(const StyleRulePage* r1, const StyleRulePage* r2)
+{
+ return r1->selector()->specificityForPage() < r2->selector()->specificityForPage();
+}
+
+bool PageRuleCollector::isLeftPage(int pageIndex) const
+{
+ bool isFirstPageLeft = false;
+ if (!m_state.rootElementStyle()->isLeftToRightDirection())
+ isFirstPageLeft = true;
+
+ return (pageIndex + (isFirstPageLeft ? 1 : 0)) % 2;
+}
+
+bool PageRuleCollector::isFirstPage(int pageIndex) const
+{
+ // FIXME: In case of forced left/right page, page at index 1 (not 0) can be the first page.
+ return (!pageIndex);
+}
+
+String PageRuleCollector::pageName(int /* pageIndex */) const
+{
+ // FIXME: Implement page index to page name mapping.
+ return emptyString();
+}
+
+void PageRuleCollector::matchAllPageRules(int pageIndex)
+{
+ const bool isLeft = isLeftPage(pageIndex);
+ const bool isFirst = isFirstPage(pageIndex);
+ const String page = pageName(pageIndex);
+
+ matchPageRules(CSSDefaultStyleSheets::defaultPrintStyle, isLeft, isFirst, page);
+ matchPageRules(m_ruleSets.userStyle(), isLeft, isFirst, page);
+ // Only consider the global author RuleSet for @page rules, as per the HTML5 spec.
+ if (m_ruleSets.isAuthorStyleDefined())
+ matchPageRules(&m_ruleSets.authorStyle(), isLeft, isFirst, page);
+}
+
+void PageRuleCollector::matchPageRules(RuleSet* rules, bool isLeftPage, bool isFirstPage, const String& pageName)
+{
+ if (!rules)
+ return;
+
+ Vector<StyleRulePage*> matchedPageRules;
+ matchPageRulesForList(matchedPageRules, rules->pageRules(), isLeftPage, isFirstPage, pageName);
+ if (matchedPageRules.isEmpty())
+ return;
+
+ std::stable_sort(matchedPageRules.begin(), matchedPageRules.end(), comparePageRules);
+
+ for (unsigned i = 0; i < matchedPageRules.size(); i++)
+ m_result.authorDeclarations.append({ &matchedPageRules[i]->properties() });
+}
+
+static bool checkPageSelectorComponents(const CSSSelector* selector, bool isLeftPage, bool isFirstPage, const String& pageName)
+{
+ for (const CSSSelector* component = selector; component; component = component->tagHistory()) {
+ if (component->match() == CSSSelector::Tag) {
+ const AtomString& localName = component->tagQName().localName();
+ if (localName != starAtom() && localName != pageName)
+ return false;
+ } else if (component->match() == CSSSelector::PagePseudoClass) {
+ CSSSelector::PagePseudoClassType pseudoType = component->pagePseudoClassType();
+ if ((pseudoType == CSSSelector::PagePseudoClassLeft && !isLeftPage)
+ || (pseudoType == CSSSelector::PagePseudoClassRight && isLeftPage)
+ || (pseudoType == CSSSelector::PagePseudoClassFirst && !isFirstPage))
+ {
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
+void PageRuleCollector::matchPageRulesForList(Vector<StyleRulePage*>& matchedRules, const Vector<StyleRulePage*>& rules, bool isLeftPage, bool isFirstPage, const String& pageName)
+{
+ for (unsigned i = 0; i < rules.size(); ++i) {
+ StyleRulePage* rule = rules[i];
+
+ if (!checkPageSelectorComponents(rule->selector(), isLeftPage, isFirstPage, pageName))
+ continue;
+
+ // If the rule has no properties to apply, then ignore it.
+ const StyleProperties& properties = rule->properties();
+ if (properties.isEmpty())
+ continue;
+
+ // Add this rule to our list of matched rules.
+ matchedRules.append(rule);
+ }
+}
+
+} // namespace Style
+} // namespace WebCore
Copied: trunk/Source/WebCore/style/PageRuleCollector.h (from rev 252627, trunk/Source/WebCore/css/PageRuleCollector.h) (0 => 252628)
--- trunk/Source/WebCore/style/PageRuleCollector.h (rev 0)
+++ trunk/Source/WebCore/style/PageRuleCollector.h 2019-11-19 15:34:28 UTC (rev 252628)
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 1999 Lars Knoll ([email protected])
+ * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#pragma once
+
+#include "StyleResolver.h"
+#include "StyleScopeRuleSets.h"
+#include <wtf/Forward.h>
+
+namespace WebCore {
+
+class StyleRulePage;
+
+namespace Style {
+
+class PageRuleCollector {
+public:
+ PageRuleCollector(Resolver::State& state, ScopeRuleSets& ruleSets)
+ : m_state(state)
+ , m_ruleSets(ruleSets) { }
+
+ void matchAllPageRules(int pageIndex);
+ const MatchResult& matchResult() const { return m_result; }
+
+private:
+ bool isLeftPage(int pageIndex) const;
+ bool isRightPage(int pageIndex) const { return !isLeftPage(pageIndex); }
+ bool isFirstPage(int pageIndex) const;
+ String pageName(int pageIndex) const;
+
+ void matchPageRules(RuleSet* rules, bool isLeftPage, bool isFirstPage, const String& pageName);
+ void matchPageRulesForList(Vector<StyleRulePage*>& matchedRules, const Vector<StyleRulePage*>& rules, bool isLeftPage, bool isFirstPage, const String& pageName);
+
+ const Resolver::State& m_state;
+ ScopeRuleSets& m_ruleSets;
+
+ MatchResult m_result;
+};
+
+} // namespace Style
+} // namespace WebCore
Modified: trunk/Source/WebCore/style/StyleResolver.cpp (252627 => 252628)
--- trunk/Source/WebCore/style/StyleResolver.cpp 2019-11-19 15:26:13 UTC (rev 252627)
+++ trunk/Source/WebCore/style/StyleResolver.cpp 2019-11-19 15:34:28 UTC (rev 252628)
@@ -398,7 +398,7 @@
}
}
-std::unique_ptr<RenderStyle> Resolver::pseudoStyleForElement(const Element& element, const PseudoStyleRequest& pseudoStyleRequest, const RenderStyle& parentStyle, const RenderStyle* parentBoxStyle, const SelectorFilter* selectorFilter)
+std::unique_ptr<RenderStyle> Resolver::pseudoStyleForElement(const Element& element, const PseudoElementRequest& pseudoElementRequest, const RenderStyle& parentStyle, const RenderStyle* parentBoxStyle, const SelectorFilter* selectorFilter)
{
auto state = State(element, &parentStyle, m_overrideDocumentElementStyle);
@@ -411,7 +411,7 @@
}
ElementRuleCollector collector(element, m_ruleSets, selectorFilter);
- collector.setPseudoStyleRequest(pseudoStyleRequest);
+ collector.setPseudoElementRequest(pseudoElementRequest);
collector.setMedium(&m_mediaQueryEvaluator);
collector.matchUARules();
@@ -425,7 +425,7 @@
if (collector.matchResult().isEmpty())
return nullptr;
- state.style()->setStyleType(pseudoStyleRequest.pseudoId);
+ state.style()->setStyleType(pseudoElementRequest.pseudoId);
applyMatchedProperties(state, collector.matchResult());
@@ -498,7 +498,7 @@
ElementRuleCollector collector(*element, m_ruleSets, nullptr);
collector.setMode(SelectorChecker::Mode::CollectingRules);
- collector.setPseudoStyleRequest(PseudoStyleRequest(pseudoId));
+ collector.setPseudoElementRequest({ pseudoId });
collector.setMedium(&m_mediaQueryEvaluator);
collector.setIncludeEmptyRules(rulesToInclude & EmptyCSSRules);
Modified: trunk/Source/WebCore/style/StyleResolver.h (252627 => 252628)
--- trunk/Source/WebCore/style/StyleResolver.h 2019-11-19 15:26:13 UTC (rev 252627)
+++ trunk/Source/WebCore/style/StyleResolver.h 2019-11-19 15:34:28 UTC (rev 252628)
@@ -44,7 +44,6 @@
class Element;
class KeyframeList;
class KeyframeValue;
-class PageRuleCollector;
class RuleData;
class RuleSet;
class SelectorFilter;
@@ -90,7 +89,7 @@
void keyframeStylesForAnimation(const Element&, const RenderStyle*, KeyframeList&);
- std::unique_ptr<RenderStyle> pseudoStyleForElement(const Element&, const PseudoStyleRequest&, const RenderStyle& parentStyle, const RenderStyle* parentBoxStyle = nullptr, const SelectorFilter* = nullptr);
+ std::unique_ptr<RenderStyle> pseudoStyleForElement(const Element&, const PseudoElementRequest&, const RenderStyle& parentStyle, const RenderStyle* parentBoxStyle = nullptr, const SelectorFilter* = nullptr);
std::unique_ptr<RenderStyle> styleForPage(int pageIndex);
std::unique_ptr<RenderStyle> defaultStyleForElement(const Element*);
@@ -155,7 +154,7 @@
InspectorCSSOMWrappers& inspectorCSSOMWrappers() { return m_inspectorCSSOMWrappers; }
private:
- friend class WebCore::PageRuleCollector;
+ friend class PageRuleCollector;
class State {
public: