Move property cascade out of StyleResolver
https://bugs.webkit.org/show_bug.cgi?id=203361
Reviewed by Zalan Bujtas.
Rename StyleResolver::CascadedProperties -> Style::PropertyCascade and move it into a file of its own.
* Sources.txt:
* WebCore.xcodeproj/project.pbxproj:
* css/StyleResolver.cpp:
(WebCore::StyleResolver::styleForKeyframe):
(WebCore::StyleResolver::styleForPage):
(WebCore::StyleResolver::applyMatchedProperties):
(WebCore::StyleResolver::cascadedPropertiesForRollback):
(WebCore::StyleResolver::applyProperty):
(WebCore::StyleResolver::applyCascadedPropertiesImpl):
(WebCore::shouldApplyPropertyInParseOrder): Deleted.
(WebCore::isValidMarkerStyleProperty): Deleted.
(WebCore::isValidCueStyleProperty): Deleted.
(WebCore::StyleResolver::CascadedProperties::CascadedProperties): Deleted.
(WebCore::StyleResolver::CascadedProperties::hasProperty const): Deleted.
(WebCore::StyleResolver::CascadedProperties::property): Deleted.
(WebCore::StyleResolver::CascadedProperties::hasCustomProperty const): Deleted.
(WebCore::StyleResolver::CascadedProperties::customProperty const): Deleted.
(WebCore::StyleResolver::CascadedProperties::setPropertyInternal): Deleted.
(WebCore::StyleResolver::CascadedProperties::set): Deleted.
(WebCore::StyleResolver::CascadedProperties::setDeferred): Deleted.
(WebCore::StyleResolver::CascadedProperties::addMatch): Deleted.
(WebCore::declarationsForCascadeLevel): Deleted.
(WebCore::StyleResolver::CascadedProperties::addNormalMatches): Deleted.
(WebCore::hasImportantProperties): Deleted.
(WebCore::StyleResolver::CascadedProperties::addImportantMatches): Deleted.
(WebCore::StyleResolver::CascadedProperties::applyDeferredProperties): Deleted.
(WebCore::StyleResolver::CascadedProperties::Property::apply): Deleted.
* css/StyleResolver.h:
(WebCore::StyleResolver::State::authorRollback const):
(WebCore::StyleResolver::State::userRollback const):
(WebCore::StyleResolver::State::setAuthorRollback):
(WebCore::StyleResolver::State::setUserRollback):
(WebCore::StyleResolver::CascadedProperties::customProperties): Deleted.
(WebCore::StyleResolver::cascadeLevel const): Deleted.
(WebCore::StyleResolver::setCascadeLevel): Deleted.
* style/PropertyCascade.cpp: Added.
(WebCore::Style::shouldApplyPropertyInParseOrder):
(WebCore::Style::isValidMarkerStyleProperty):
(WebCore::Style::isValidCueStyleProperty):
(WebCore::Style::PropertyCascade::PropertyCascade):
(WebCore::Style::PropertyCascade::setPropertyInternal):
(WebCore::Style::PropertyCascade::set):
(WebCore::Style::PropertyCascade::setDeferred):
(WebCore::Style::PropertyCascade::addMatch):
(WebCore::Style::declarationsForCascadeLevel):
(WebCore::Style::PropertyCascade::addNormalMatches):
(WebCore::Style::hasImportantProperties):
(WebCore::Style::PropertyCascade::addImportantMatches):
(WebCore::Style::PropertyCascade::applyDeferredProperties):
(WebCore::Style::PropertyCascade::Property::apply):
* style/PropertyCascade.h: Added.
(WebCore::Style::PropertyCascade::customProperties):
(WebCore::Style::PropertyCascade::hasProperty const):
(WebCore::Style::PropertyCascade::property):
(WebCore::Style::PropertyCascade::hasCustomProperty const):
(WebCore::Style::PropertyCascade::customProperty const):
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@251540 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog
index 8f50c46..ab44921 100644
--- a/Source/WebCore/ChangeLog
+++ b/Source/WebCore/ChangeLog
@@ -1,3 +1,69 @@
+2019-10-24 Antti Koivisto <antti@apple.com>
+
+ Move property cascade out of StyleResolver
+ https://bugs.webkit.org/show_bug.cgi?id=203361
+
+ Reviewed by Zalan Bujtas.
+
+ Rename StyleResolver::CascadedProperties -> Style::PropertyCascade and move it into a file of its own.
+
+ * Sources.txt:
+ * WebCore.xcodeproj/project.pbxproj:
+ * css/StyleResolver.cpp:
+ (WebCore::StyleResolver::styleForKeyframe):
+ (WebCore::StyleResolver::styleForPage):
+ (WebCore::StyleResolver::applyMatchedProperties):
+ (WebCore::StyleResolver::cascadedPropertiesForRollback):
+ (WebCore::StyleResolver::applyProperty):
+ (WebCore::StyleResolver::applyCascadedPropertiesImpl):
+ (WebCore::shouldApplyPropertyInParseOrder): Deleted.
+ (WebCore::isValidMarkerStyleProperty): Deleted.
+ (WebCore::isValidCueStyleProperty): Deleted.
+ (WebCore::StyleResolver::CascadedProperties::CascadedProperties): Deleted.
+ (WebCore::StyleResolver::CascadedProperties::hasProperty const): Deleted.
+ (WebCore::StyleResolver::CascadedProperties::property): Deleted.
+ (WebCore::StyleResolver::CascadedProperties::hasCustomProperty const): Deleted.
+ (WebCore::StyleResolver::CascadedProperties::customProperty const): Deleted.
+ (WebCore::StyleResolver::CascadedProperties::setPropertyInternal): Deleted.
+ (WebCore::StyleResolver::CascadedProperties::set): Deleted.
+ (WebCore::StyleResolver::CascadedProperties::setDeferred): Deleted.
+ (WebCore::StyleResolver::CascadedProperties::addMatch): Deleted.
+ (WebCore::declarationsForCascadeLevel): Deleted.
+ (WebCore::StyleResolver::CascadedProperties::addNormalMatches): Deleted.
+ (WebCore::hasImportantProperties): Deleted.
+ (WebCore::StyleResolver::CascadedProperties::addImportantMatches): Deleted.
+ (WebCore::StyleResolver::CascadedProperties::applyDeferredProperties): Deleted.
+ (WebCore::StyleResolver::CascadedProperties::Property::apply): Deleted.
+ * css/StyleResolver.h:
+ (WebCore::StyleResolver::State::authorRollback const):
+ (WebCore::StyleResolver::State::userRollback const):
+ (WebCore::StyleResolver::State::setAuthorRollback):
+ (WebCore::StyleResolver::State::setUserRollback):
+ (WebCore::StyleResolver::CascadedProperties::customProperties): Deleted.
+ (WebCore::StyleResolver::cascadeLevel const): Deleted.
+ (WebCore::StyleResolver::setCascadeLevel): Deleted.
+ * style/PropertyCascade.cpp: Added.
+ (WebCore::Style::shouldApplyPropertyInParseOrder):
+ (WebCore::Style::isValidMarkerStyleProperty):
+ (WebCore::Style::isValidCueStyleProperty):
+ (WebCore::Style::PropertyCascade::PropertyCascade):
+ (WebCore::Style::PropertyCascade::setPropertyInternal):
+ (WebCore::Style::PropertyCascade::set):
+ (WebCore::Style::PropertyCascade::setDeferred):
+ (WebCore::Style::PropertyCascade::addMatch):
+ (WebCore::Style::declarationsForCascadeLevel):
+ (WebCore::Style::PropertyCascade::addNormalMatches):
+ (WebCore::Style::hasImportantProperties):
+ (WebCore::Style::PropertyCascade::addImportantMatches):
+ (WebCore::Style::PropertyCascade::applyDeferredProperties):
+ (WebCore::Style::PropertyCascade::Property::apply):
+ * style/PropertyCascade.h: Added.
+ (WebCore::Style::PropertyCascade::customProperties):
+ (WebCore::Style::PropertyCascade::hasProperty const):
+ (WebCore::Style::PropertyCascade::property):
+ (WebCore::Style::PropertyCascade::hasCustomProperty const):
+ (WebCore::Style::PropertyCascade::customProperty const):
+
2019-10-24 Chris Dumez <cdumez@apple.com>
AudioContext should not prevent entering the back/forward cache
diff --git a/Source/WebCore/Sources.txt b/Source/WebCore/Sources.txt
index 6b62211..edb630d 100644
--- a/Source/WebCore/Sources.txt
+++ b/Source/WebCore/Sources.txt
@@ -2337,6 +2337,7 @@
style/ClassChangeInvalidation.cpp
style/IdChangeInvalidation.cpp
style/InlineTextBoxStyle.cpp
+style/PropertyCascade.cpp
style/StyleChange.cpp
style/StyleFontSizeFunctions.cpp
style/StyleInvalidator.cpp
diff --git a/Source/WebCore/WebCore.xcodeproj/project.pbxproj b/Source/WebCore/WebCore.xcodeproj/project.pbxproj
index 129a20f..39cebec 100644
--- a/Source/WebCore/WebCore.xcodeproj/project.pbxproj
+++ b/Source/WebCore/WebCore.xcodeproj/project.pbxproj
@@ -4832,6 +4832,7 @@
E4A814DA1C70E10D00BF85AC /* AttributeChangeInvalidation.h in Headers */ = {isa = PBXBuildFile; fileRef = E4A814D91C70E10D00BF85AC /* AttributeChangeInvalidation.h */; };
E4A814E01C7338EB00BF85AC /* IdChangeInvalidation.h in Headers */ = {isa = PBXBuildFile; fileRef = E4A814DF1C7338EB00BF85AC /* IdChangeInvalidation.h */; };
E4A8D21622578DB700A8463C /* EventRegion.h in Headers */ = {isa = PBXBuildFile; fileRef = E4A8D21422578DA000A8463C /* EventRegion.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ E4ABABE42361A32900FA4345 /* PropertyCascade.h in Headers */ = {isa = PBXBuildFile; fileRef = E4ABABE22361A32900FA4345 /* PropertyCascade.h */; };
E4AE7C1617D1BB950009FB31 /* ElementIterator.h in Headers */ = {isa = PBXBuildFile; fileRef = E4AE7C1517D1BB950009FB31 /* ElementIterator.h */; settings = {ATTRIBUTES = (Private, ); }; };
E4AE7C1A17D232350009FB31 /* ElementAncestorIterator.h in Headers */ = {isa = PBXBuildFile; fileRef = E4AE7C1917D232350009FB31 /* ElementAncestorIterator.h */; settings = {ATTRIBUTES = (Private, ); }; };
E4AFCFA50DAF29A300F5F55C /* UnitBezier.h in Headers */ = {isa = PBXBuildFile; fileRef = E4AFCFA40DAF29A300F5F55C /* UnitBezier.h */; };
@@ -15141,6 +15142,8 @@
E4A814DF1C7338EB00BF85AC /* IdChangeInvalidation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IdChangeInvalidation.h; sourceTree = "<group>"; };
E4A8D21422578DA000A8463C /* EventRegion.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EventRegion.h; sourceTree = "<group>"; };
E4A8D21522578DA000A8463C /* EventRegion.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = EventRegion.cpp; sourceTree = "<group>"; };
+ E4ABABE22361A32900FA4345 /* PropertyCascade.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PropertyCascade.h; sourceTree = "<group>"; };
+ E4ABABE52361A34200FA4345 /* PropertyCascade.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = PropertyCascade.cpp; sourceTree = "<group>"; };
E4AE7C1517D1BB950009FB31 /* ElementIterator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ElementIterator.h; sourceTree = "<group>"; };
E4AE7C1917D232350009FB31 /* ElementAncestorIterator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ElementAncestorIterator.h; sourceTree = "<group>"; };
E4AFCFA40DAF29A300F5F55C /* UnitBezier.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UnitBezier.h; sourceTree = "<group>"; };
@@ -26872,6 +26875,8 @@
E4A814DF1C7338EB00BF85AC /* IdChangeInvalidation.h */,
1C0106FE192594DF008A4201 /* InlineTextBoxStyle.cpp */,
1C0106FF192594DF008A4201 /* InlineTextBoxStyle.h */,
+ E4ABABE52361A34200FA4345 /* PropertyCascade.cpp */,
+ E4ABABE22361A32900FA4345 /* PropertyCascade.h */,
E401E0A51C3C0CF700F34D10 /* StyleChange.cpp */,
E401E0A31C3C0B8300F34D10 /* StyleChange.h */,
E4D58EB617B4ED8900CBDCA8 /* StyleFontSizeFunctions.cpp */,
@@ -29045,6 +29050,7 @@
759CB837192DA9190012BC64 /* ControlStates.h in Headers */,
FD31602912B0267600C1A359 /* ConvolverNode.h in Headers */,
D8B6152F1032495100C8554A /* Cookie.h in Headers */,
+ E4ABABE42361A32900FA4345 /* PropertyCascade.h in Headers */,
E1424C94164B52C800F32D40 /* CookieJar.h in Headers */,
7A5699702086C619000E0433 /* CookieRequestHeaderFieldProxy.h in Headers */,
33D0212D131DB37B004091A8 /* CookieStorage.h in Headers */,
diff --git a/Source/WebCore/css/StyleResolver.cpp b/Source/WebCore/css/StyleResolver.cpp
index 15434a0..fe6b6d9 100644
--- a/Source/WebCore/css/StyleResolver.cpp
+++ b/Source/WebCore/css/StyleResolver.cpp
@@ -373,8 +373,8 @@
// We don't need to bother with !important. Since there is only ever one
// decl, there's nothing to override. So just add the first properties.
- CascadedProperties cascade(direction, writingMode);
- cascade.addNormalMatches(result, CascadeLevel::AuthorLevel);
+ Style::PropertyCascade cascade(direction, writingMode);
+ cascade.addNormalMatches(result, Style::CascadeLevel::Author);
ApplyCascadedPropertyState applyState { this, &cascade, &result };
applyCascadedProperties(firstCSSProperty, lastHighPriorityProperty, applyState);
@@ -579,8 +579,8 @@
WritingMode writingMode;
extractDirectionAndWritingMode(*m_state.style(), result, direction, writingMode);
- CascadedProperties cascade(direction, writingMode);
- cascade.addNormalMatches(result, CascadeLevel::AuthorLevel);
+ Style::PropertyCascade cascade(direction, writingMode);
+ cascade.addNormalMatches(result, Style::CascadeLevel::Author);
ApplyCascadedPropertyState applyState { this, &cascade, &result };
applyCascadedProperties(firstCSSProperty, lastHighPriorityProperty, applyState);
@@ -1224,39 +1224,6 @@
return collector.matchedRuleList();
}
-static bool shouldApplyPropertyInParseOrder(CSSPropertyID propertyID)
-{
- switch (propertyID) {
- case CSSPropertyWebkitBackgroundClip:
- case CSSPropertyBackgroundClip:
- case CSSPropertyWebkitBackgroundOrigin:
- case CSSPropertyBackgroundOrigin:
- case CSSPropertyWebkitBackgroundSize:
- case CSSPropertyBackgroundSize:
- case CSSPropertyWebkitBorderImage:
- case CSSPropertyBorderImage:
- case CSSPropertyBorderImageSlice:
- case CSSPropertyBorderImageSource:
- case CSSPropertyBorderImageOutset:
- case CSSPropertyBorderImageRepeat:
- case CSSPropertyBorderImageWidth:
- case CSSPropertyWebkitBoxShadow:
- case CSSPropertyBoxShadow:
- case CSSPropertyWebkitTextDecoration:
- case CSSPropertyTextDecorationLine:
- case CSSPropertyTextDecorationStyle:
- case CSSPropertyTextDecorationColor:
- case CSSPropertyTextDecorationSkip:
- case CSSPropertyTextUnderlinePosition:
- case CSSPropertyTextUnderlineOffset:
- case CSSPropertyTextDecorationThickness:
- case CSSPropertyTextDecoration:
- return true;
- default:
- return false;
- }
-}
-
static bool elementTypeHasAppearanceFromUAStyle(const Element& element)
{
// NOTE: This is just a hard-coded list of elements that have some -webkit-appearance value in html.css
@@ -1415,9 +1382,9 @@
// Find out if there's a -webkit-appearance property in effect from the UA sheet.
// If so, we cache the border and background styles so that RenderTheme::adjustStyle()
// can look at them later to figure out if this is a styled form control or not.
- CascadedProperties cascade(direction, writingMode);
- cascade.addNormalMatches(matchResult, CascadeLevel::UserAgentLevel, applyInheritedOnly);
- cascade.addImportantMatches(matchResult, CascadeLevel::UserAgentLevel, applyInheritedOnly);
+ Style::PropertyCascade cascade(direction, writingMode);
+ cascade.addNormalMatches(matchResult, Style::CascadeLevel::UserAgent, applyInheritedOnly);
+ cascade.addImportantMatches(matchResult, Style::CascadeLevel::UserAgent, applyInheritedOnly);
ApplyCascadedPropertyState applyState { this, &cascade, &matchResult };
@@ -1442,13 +1409,13 @@
state.cacheBorderAndBackground();
}
- CascadedProperties cascade(direction, writingMode);
- cascade.addNormalMatches(matchResult, CascadeLevel::UserAgentLevel, applyInheritedOnly);
- cascade.addNormalMatches(matchResult, CascadeLevel::UserLevel, applyInheritedOnly);
- cascade.addNormalMatches(matchResult, CascadeLevel::AuthorLevel, applyInheritedOnly);
- cascade.addImportantMatches(matchResult, CascadeLevel::AuthorLevel, applyInheritedOnly);
- cascade.addImportantMatches(matchResult, CascadeLevel::UserLevel, applyInheritedOnly);
- cascade.addImportantMatches(matchResult, CascadeLevel::UserAgentLevel, applyInheritedOnly);
+ Style::PropertyCascade cascade(direction, writingMode);
+ cascade.addNormalMatches(matchResult, Style::CascadeLevel::UserAgent, applyInheritedOnly);
+ cascade.addNormalMatches(matchResult, Style::CascadeLevel::User, applyInheritedOnly);
+ cascade.addNormalMatches(matchResult, Style::CascadeLevel::Author, applyInheritedOnly);
+ cascade.addImportantMatches(matchResult, Style::CascadeLevel::Author, applyInheritedOnly);
+ cascade.addImportantMatches(matchResult, Style::CascadeLevel::User, applyInheritedOnly);
+ cascade.addImportantMatches(matchResult, Style::CascadeLevel::UserAgent, applyInheritedOnly);
ApplyCascadedPropertyState applyState { this, &cascade, &matchResult };
@@ -1534,81 +1501,6 @@
return false;
}
-// https://www.w3.org/TR/css-pseudo-4/#marker-pseudo (Editor's Draft, 25 July 2017)
-static inline bool isValidMarkerStyleProperty(CSSPropertyID id)
-{
- switch (id) {
- case CSSPropertyColor:
- case CSSPropertyFontFamily:
- case CSSPropertyFontFeatureSettings:
- case CSSPropertyFontSize:
- case CSSPropertyFontStretch:
- case CSSPropertyFontStyle:
- case CSSPropertyFontSynthesis:
- case CSSPropertyFontVariantAlternates:
- case CSSPropertyFontVariantCaps:
- case CSSPropertyFontVariantEastAsian:
- case CSSPropertyFontVariantLigatures:
- case CSSPropertyFontVariantNumeric:
- case CSSPropertyFontVariantPosition:
- case CSSPropertyFontWeight:
-#if ENABLE(VARIATION_FONTS)
- case CSSPropertyFontOpticalSizing:
- case CSSPropertyFontVariationSettings:
-#endif
- return true;
- default:
- break;
- }
- return false;
-}
-
-#if ENABLE(VIDEO_TRACK)
-static inline bool isValidCueStyleProperty(CSSPropertyID id)
-{
- switch (id) {
- case CSSPropertyBackground:
- case CSSPropertyBackgroundAttachment:
- case CSSPropertyBackgroundClip:
- case CSSPropertyBackgroundColor:
- case CSSPropertyBackgroundImage:
- case CSSPropertyBackgroundOrigin:
- case CSSPropertyBackgroundPosition:
- case CSSPropertyBackgroundPositionX:
- case CSSPropertyBackgroundPositionY:
- case CSSPropertyBackgroundRepeat:
- case CSSPropertyBackgroundSize:
- case CSSPropertyColor:
- case CSSPropertyFont:
- case CSSPropertyFontFamily:
- case CSSPropertyFontSize:
- case CSSPropertyFontStyle:
- case CSSPropertyFontVariantCaps:
- case CSSPropertyFontWeight:
- case CSSPropertyLineHeight:
- case CSSPropertyOpacity:
- case CSSPropertyOutline:
- case CSSPropertyOutlineColor:
- case CSSPropertyOutlineOffset:
- case CSSPropertyOutlineStyle:
- case CSSPropertyOutlineWidth:
- case CSSPropertyVisibility:
- case CSSPropertyWhiteSpace:
- case CSSPropertyTextDecoration:
- case CSSPropertyTextShadow:
- case CSSPropertyBorderStyle:
- case CSSPropertyPaintOrder:
- case CSSPropertyStrokeLinejoin:
- case CSSPropertyStrokeLinecap:
- case CSSPropertyStrokeColor:
- case CSSPropertyStrokeWidth:
- return true;
- default:
- break;
- }
- return false;
-}
-#endif
// SVG handles zooming in a different way compared to CSS. The whole document is scaled instead
// of each individual length value in the render style / tree. CSSPrimitiveValue::computeLength*()
// multiplies each resolved length with the zoom multiplier - so for SVG we need to disable that.
@@ -1628,46 +1520,49 @@
return is<SVGElement>(m_state.element()) && !(is<SVGSVGElement>(*m_state.element()) && m_state.element()->parentNode());
}
-StyleResolver::CascadedProperties* StyleResolver::cascadedPropertiesForRollback(const MatchResult& matchResult)
+Style::PropertyCascade* StyleResolver::cascadedPropertiesForRollback(const MatchResult& matchResult)
{
- ASSERT(cascadeLevel() != CascadeLevel::UserAgentLevel);
-
TextDirection direction;
WritingMode writingMode;
extractDirectionAndWritingMode(*state().style(), matchResult, direction, writingMode);
- if (cascadeLevel() == CascadeLevel::AuthorLevel) {
- CascadedProperties* authorRollback = state().authorRollback();
+ switch (state().cascadeLevel()) {
+ case Style::CascadeLevel::Author: {
+ auto* authorRollback = state().authorRollback();
if (authorRollback)
return authorRollback;
- auto newAuthorRollback(makeUnique<CascadedProperties>(direction, writingMode));
+ auto newAuthorRollback = makeUnique<Style::PropertyCascade>(direction, writingMode);
// This special rollback cascade contains UA rules and user rules but no author rules.
- newAuthorRollback->addNormalMatches(matchResult, CascadeLevel::UserAgentLevel, false);
- newAuthorRollback->addNormalMatches(matchResult, CascadeLevel::UserLevel, false);
- newAuthorRollback->addImportantMatches(matchResult, CascadeLevel::UserLevel, false);
- newAuthorRollback->addImportantMatches(matchResult, CascadeLevel::UserAgentLevel, false);
+ newAuthorRollback->addNormalMatches(matchResult, Style::CascadeLevel::UserAgent, false);
+ newAuthorRollback->addNormalMatches(matchResult, Style::CascadeLevel::User, false);
+ newAuthorRollback->addImportantMatches(matchResult, Style::CascadeLevel::User, false);
+ newAuthorRollback->addImportantMatches(matchResult, Style::CascadeLevel::UserAgent, false);
state().setAuthorRollback(newAuthorRollback);
return state().authorRollback();
}
- if (cascadeLevel() == CascadeLevel::UserLevel) {
- CascadedProperties* userRollback = state().userRollback();
+ case Style::CascadeLevel::User: {
+ auto* userRollback = state().userRollback();
if (userRollback)
return userRollback;
- auto newUserRollback(makeUnique<CascadedProperties>(direction, writingMode));
+ auto newUserRollback = makeUnique<Style::PropertyCascade>(direction, writingMode);
// This special rollback cascade contains only UA rules.
- newUserRollback->addNormalMatches(matchResult, CascadeLevel::UserAgentLevel, false);
- newUserRollback->addImportantMatches(matchResult, CascadeLevel::UserAgentLevel, false);
+ newUserRollback->addNormalMatches(matchResult, Style::CascadeLevel::UserAgent, false);
+ newUserRollback->addImportantMatches(matchResult, Style::CascadeLevel::UserAgent, false);
state().setUserRollback(newUserRollback);
return state().userRollback();
}
+ case Style::CascadeLevel::UserAgent:
+ break;
+ }
+ ASSERT_NOT_REACHED();
return nullptr;
}
@@ -1718,7 +1613,7 @@
bool isRevert = valueToCheckForInheritInitial->isRevertValue() || customPropertyValueID == CSSValueRevert;
if (isRevert) {
- if (cascadeLevel() == CascadeLevel::UserAgentLevel || !matchResult)
+ if (state.cascadeLevel() == Style::CascadeLevel::UserAgent || !matchResult)
isUnset = true;
else {
// Fetch the correct rollback object from the state, building it if necessary.
@@ -2135,225 +2030,6 @@
return true;
}
-StyleResolver::CascadedProperties::CascadedProperties(TextDirection direction, WritingMode writingMode)
- : m_direction(direction)
- , m_writingMode(writingMode)
-{
-}
-
-inline bool StyleResolver::CascadedProperties::hasProperty(CSSPropertyID id) const
-{
- ASSERT(id < m_propertyIsPresent.size());
- return m_propertyIsPresent[id];
-}
-
-inline StyleResolver::CascadedProperties::Property& StyleResolver::CascadedProperties::property(CSSPropertyID id)
-{
- return m_properties[id];
-}
-
-inline bool StyleResolver::CascadedProperties::hasCustomProperty(const String& name) const
-{
- return m_customProperties.contains(name);
-}
-
-inline StyleResolver::CascadedProperties::Property StyleResolver::CascadedProperties::customProperty(const String& name) const
-{
- return m_customProperties.get(name);
-}
-
-void StyleResolver::CascadedProperties::setPropertyInternal(Property& property, CSSPropertyID id, CSSValue& cssValue, unsigned linkMatchType, CascadeLevel cascadeLevel, Style::ScopeOrdinal styleScopeOrdinal)
-{
- ASSERT(linkMatchType <= SelectorChecker::MatchAll);
- property.id = id;
- property.level = cascadeLevel;
- property.styleScopeOrdinal = styleScopeOrdinal;
- if (linkMatchType == SelectorChecker::MatchAll) {
- property.cssValue[0] = &cssValue;
- property.cssValue[SelectorChecker::MatchLink] = &cssValue;
- property.cssValue[SelectorChecker::MatchVisited] = &cssValue;
- } else
- property.cssValue[linkMatchType] = &cssValue;
-}
-
-void StyleResolver::CascadedProperties::set(CSSPropertyID id, CSSValue& cssValue, unsigned linkMatchType, CascadeLevel cascadeLevel, Style::ScopeOrdinal styleScopeOrdinal)
-{
- if (CSSProperty::isDirectionAwareProperty(id))
- id = CSSProperty::resolveDirectionAwareProperty(id, m_direction, m_writingMode);
-
- ASSERT(!shouldApplyPropertyInParseOrder(id));
-
- auto& property = m_properties[id];
- ASSERT(id < m_propertyIsPresent.size());
- if (id == CSSPropertyCustom) {
- m_propertyIsPresent.set(id);
- const auto& customValue = downcast<CSSCustomPropertyValue>(cssValue);
- bool hasValue = customProperties().contains(customValue.name());
- if (!hasValue) {
- Property property;
- property.id = id;
- memset(property.cssValue, 0, sizeof(property.cssValue));
- setPropertyInternal(property, id, cssValue, linkMatchType, cascadeLevel, styleScopeOrdinal);
- customProperties().set(customValue.name(), property);
- } else {
- Property property = customProperties().get(customValue.name());
- setPropertyInternal(property, id, cssValue, linkMatchType, cascadeLevel, styleScopeOrdinal);
- customProperties().set(customValue.name(), property);
- }
- return;
- }
-
- if (!m_propertyIsPresent[id])
- memset(property.cssValue, 0, sizeof(property.cssValue));
- m_propertyIsPresent.set(id);
- setPropertyInternal(property, id, cssValue, linkMatchType, cascadeLevel, styleScopeOrdinal);
-}
-
-void StyleResolver::CascadedProperties::setDeferred(CSSPropertyID id, CSSValue& cssValue, unsigned linkMatchType, CascadeLevel cascadeLevel, Style::ScopeOrdinal styleScopeOrdinal)
-{
- ASSERT(!CSSProperty::isDirectionAwareProperty(id));
- ASSERT(shouldApplyPropertyInParseOrder(id));
-
- Property property;
- memset(property.cssValue, 0, sizeof(property.cssValue));
- setPropertyInternal(property, id, cssValue, linkMatchType, cascadeLevel, styleScopeOrdinal);
- m_deferredProperties.append(property);
-}
-
-
-void StyleResolver::CascadedProperties::addMatch(const MatchedProperties& matchedProperties, CascadeLevel cascadeLevel, bool isImportant, bool inheritedOnly)
-{
- auto& styleProperties = *matchedProperties.properties;
- auto propertyWhitelistType = static_cast<PropertyWhitelistType>(matchedProperties.whitelistType);
-
- for (unsigned i = 0, count = styleProperties.propertyCount(); i < count; ++i) {
- auto current = styleProperties.propertyAt(i);
- if (isImportant != current.isImportant())
- continue;
- if (inheritedOnly && !current.isInherited()) {
- // We apply the inherited properties only when using the property cache.
- // A match with a value that is explicitely inherited should never have been cached.
- ASSERT(!current.value()->isInheritedValue());
- continue;
- }
- CSSPropertyID propertyID = current.id();
-
-#if ENABLE(VIDEO_TRACK)
- if (propertyWhitelistType == PropertyWhitelistCue && !isValidCueStyleProperty(propertyID))
- continue;
-#endif
- if (propertyWhitelistType == PropertyWhitelistMarker && !isValidMarkerStyleProperty(propertyID))
- continue;
-
- if (shouldApplyPropertyInParseOrder(propertyID))
- setDeferred(propertyID, *current.value(), matchedProperties.linkMatchType, cascadeLevel, matchedProperties.styleScopeOrdinal);
- else
- set(propertyID, *current.value(), matchedProperties.linkMatchType, cascadeLevel, matchedProperties.styleScopeOrdinal);
- }
-}
-
-
-static auto& declarationsForCascadeLevel(const MatchResult& matchResult, CascadeLevel cascadeLevel)
-{
- switch (cascadeLevel) {
- case CascadeLevel::UserAgentLevel: return matchResult.userAgentDeclarations;
- case CascadeLevel::UserLevel: return matchResult.userDeclarations;
- case CascadeLevel::AuthorLevel: return matchResult.authorDeclarations;
- }
- ASSERT_NOT_REACHED();
- return matchResult.authorDeclarations;
-}
-
-void StyleResolver::CascadedProperties::addNormalMatches(const MatchResult& matchResult, CascadeLevel cascadeLevel, bool inheritedOnly)
-{
- for (auto& matchedDeclarations : declarationsForCascadeLevel(matchResult, cascadeLevel))
- addMatch(matchedDeclarations, cascadeLevel, false, inheritedOnly);
-}
-
-static bool hasImportantProperties(const StyleProperties& properties)
-{
- for (unsigned i = 0, count = properties.propertyCount(); i < count; ++i) {
- if (properties.propertyAt(i).isImportant())
- return true;
- }
- return false;
-}
-
-void StyleResolver::CascadedProperties::addImportantMatches(const MatchResult& matchResult, CascadeLevel cascadeLevel, bool inheritedOnly)
-{
- struct IndexAndOrdinal {
- unsigned index;
- Style::ScopeOrdinal ordinal;
- };
- Vector<IndexAndOrdinal> importantMatches;
- bool hasMatchesFromOtherScopes = false;
-
- auto& matchedDeclarations = declarationsForCascadeLevel(matchResult, cascadeLevel);
-
- for (unsigned i = 0; i < matchedDeclarations.size(); ++i) {
- const MatchedProperties& matchedProperties = matchedDeclarations[i];
-
- if (!hasImportantProperties(*matchedProperties.properties))
- continue;
-
- importantMatches.append({ i, matchedProperties.styleScopeOrdinal });
-
- if (matchedProperties.styleScopeOrdinal != Style::ScopeOrdinal::Element)
- hasMatchesFromOtherScopes = true;
- }
-
- if (importantMatches.isEmpty())
- return;
-
- if (hasMatchesFromOtherScopes) {
- // For !important properties a later shadow tree wins.
- // Match results are sorted in reverse tree context order so this is not needed for normal properties.
- std::stable_sort(importantMatches.begin(), importantMatches.end(), [] (const IndexAndOrdinal& a, const IndexAndOrdinal& b) {
- return a.ordinal < b.ordinal;
- });
- }
-
- for (auto& match : importantMatches)
- addMatch(matchedDeclarations[match.index], cascadeLevel, true, inheritedOnly);
-}
-
-void StyleResolver::CascadedProperties::applyDeferredProperties(StyleResolver& resolver, ApplyCascadedPropertyState& applyState)
-{
- for (auto& property : m_deferredProperties)
- property.apply(resolver, applyState);
-}
-
-void StyleResolver::CascadedProperties::Property::apply(StyleResolver& resolver, ApplyCascadedPropertyState& applyState)
-{
- State& state = resolver.state();
- state.setCascadeLevel(level);
- state.setStyleScopeOrdinal(styleScopeOrdinal);
-
- if (cssValue[SelectorChecker::MatchDefault]) {
- state.setApplyPropertyToRegularStyle(true);
- state.setApplyPropertyToVisitedLinkStyle(false);
- resolver.applyProperty(id, cssValue[SelectorChecker::MatchDefault], applyState, SelectorChecker::MatchDefault);
- }
-
- if (state.style()->insideLink() == InsideLink::NotInside)
- return;
-
- if (cssValue[SelectorChecker::MatchLink]) {
- state.setApplyPropertyToRegularStyle(true);
- state.setApplyPropertyToVisitedLinkStyle(false);
- resolver.applyProperty(id, cssValue[SelectorChecker::MatchLink], applyState, SelectorChecker::MatchLink);
- }
-
- if (cssValue[SelectorChecker::MatchVisited]) {
- state.setApplyPropertyToRegularStyle(false);
- state.setApplyPropertyToVisitedLinkStyle(true);
- resolver.applyProperty(id, cssValue[SelectorChecker::MatchVisited], applyState, SelectorChecker::MatchVisited);
- }
-
- state.setApplyPropertyToRegularStyle(true);
- state.setApplyPropertyToVisitedLinkStyle(false);
-}
-
void StyleResolver::applyCascadedCustomProperty(const String& name, ApplyCascadedPropertyState& state)
{
if (state.appliedCustomProperties.contains(name) || !state.cascade->customProperties().contains(name))
@@ -2442,7 +2118,6 @@
continue;
ASSERT(propertyID != CSSPropertyCustom);
auto& property = state.cascade->property(propertyID);
- ASSERT(!shouldApplyPropertyInParseOrder(propertyID));
if (TrackCycles == CustomPropertyCycleTracking::Disabled) {
// If we don't have any custom properties, then there can't be any cycles.
diff --git a/Source/WebCore/css/StyleResolver.h b/Source/WebCore/css/StyleResolver.h
index 905d2a3..fdc5fb3 100644
--- a/Source/WebCore/css/StyleResolver.h
+++ b/Source/WebCore/css/StyleResolver.h
@@ -28,6 +28,7 @@
#include "ElementRuleCollector.h"
#include "InspectorCSSOMWrappers.h"
#include "MediaQueryEvaluator.h"
+#include "PropertyCascade.h"
#include "RenderStyle.h"
#include "RuleSet.h"
#include "SelectorChecker.h"
@@ -94,12 +95,6 @@
MatchOnlyUserAgentRules,
};
-enum class CascadeLevel: uint8_t {
- UserAgentLevel,
- AuthorLevel,
- UserLevel
-};
-
struct ElementStyle {
ElementStyle(std::unique_ptr<RenderStyle> renderStyle, std::unique_ptr<Style::Relations> relations = { })
: renderStyle(WTFMove(renderStyle))
@@ -151,7 +146,6 @@
std::unique_ptr<RenderStyle> styleForKeyframe(const RenderStyle*, const StyleRuleKeyframe*, KeyframeValue&);
bool isAnimationNameValid(const String&);
-public:
// These methods will give back the set of rules that matched for a given element (or a pseudo-element).
enum CSSRuleFilter {
UAAndUserCSSRules = 1 << 1,
@@ -163,7 +157,6 @@
Vector<RefPtr<StyleRule>> styleRulesForElement(const Element*, unsigned rulesToInclude = AllButEmptyCSSRules);
Vector<RefPtr<StyleRule>> pseudoStyleRulesForElement(const Element*, PseudoId, unsigned rulesToInclude = AllButEmptyCSSRules);
-public:
void applyPropertyToStyle(CSSPropertyID, CSSValue*, std::unique_ptr<RenderStyle>);
void applyPropertyToCurrentStyle(CSSPropertyID, CSSValue*);
@@ -172,7 +165,6 @@
void setFontSize(FontCascadeDescription&, float size);
-public:
bool useSVGZoomRules() const;
bool useSVGZoomRulesForLength() const;
@@ -208,48 +200,6 @@
void clearCachedPropertiesAffectedByViewportUnits();
bool createFilterOperations(const CSSValue& inValue, FilterOperations& outOperations);
-
- class CascadedProperties {
- WTF_MAKE_FAST_ALLOCATED;
- public:
- CascadedProperties(TextDirection, WritingMode);
-
- struct Property {
- void apply(StyleResolver&, ApplyCascadedPropertyState&);
-
- CSSPropertyID id;
- CascadeLevel level;
- Style::ScopeOrdinal styleScopeOrdinal;
- CSSValue* cssValue[3];
- };
-
- bool hasProperty(CSSPropertyID) const;
- Property& property(CSSPropertyID);
-
- void addNormalMatches(const MatchResult&, CascadeLevel, bool inheritedOnly = false);
- void addImportantMatches(const MatchResult&, CascadeLevel, bool inheritedOnly = false);
-
- void applyDeferredProperties(StyleResolver&, ApplyCascadedPropertyState&);
-
- HashMap<AtomString, Property>& customProperties() { return m_customProperties; }
- bool hasCustomProperty(const String&) const;
- Property customProperty(const String&) const;
-
- private:
- void addMatch(const MatchedProperties&, CascadeLevel, bool isImportant, bool inheritedOnly);
- void set(CSSPropertyID, CSSValue&, unsigned linkMatchType, CascadeLevel, Style::ScopeOrdinal);
- void setDeferred(CSSPropertyID, CSSValue&, unsigned linkMatchType, CascadeLevel, Style::ScopeOrdinal);
- static void setPropertyInternal(Property&, CSSPropertyID, CSSValue&, unsigned linkMatchType, CascadeLevel, Style::ScopeOrdinal);
-
- Property m_properties[numCSSProperties + 2];
- std::bitset<numCSSProperties + 2> m_propertyIsPresent;
-
- Vector<Property, 8> m_deferredProperties;
- HashMap<AtomString, Property> m_customProperties;
-
- TextDirection m_direction;
- WritingMode m_writingMode;
- };
void applyCascadedProperties(int firstProperty, int lastProperty, ApplyCascadedPropertyState&);
void applyCascadedCustomProperty(const String& name, ApplyCascadedPropertyState&);
@@ -278,7 +228,7 @@
template<CustomPropertyCycleTracking>
inline void applyCascadedPropertiesImpl(int firstProperty, int lastProperty, ApplyCascadedPropertyState&);
- void cascadeMatches(CascadedProperties&, const MatchResult&, bool important, int startIndex, int endIndex, bool inheritedOnly);
+ void cascadeMatches(Style::PropertyCascade&, const MatchResult&, bool important, int startIndex, int endIndex, bool inheritedOnly);
DocumentRuleSets m_ruleSets;
@@ -336,16 +286,16 @@
const CSSToLengthConversionData& cssToLengthConversionData() const { return m_cssToLengthConversionData; }
- CascadeLevel cascadeLevel() const { return m_cascadeLevel; }
- void setCascadeLevel(CascadeLevel level) { m_cascadeLevel = level; }
+ Style::CascadeLevel cascadeLevel() const { return m_cascadeLevel; }
+ void setCascadeLevel(Style::CascadeLevel level) { m_cascadeLevel = level; }
Style::ScopeOrdinal styleScopeOrdinal() const { return m_styleScopeOrdinal; }
void setStyleScopeOrdinal(Style::ScopeOrdinal styleScopeOrdinal) { m_styleScopeOrdinal = styleScopeOrdinal; }
- CascadedProperties* authorRollback() const { return m_authorRollback.get(); }
- CascadedProperties* userRollback() const { return m_userRollback.get(); }
+ Style::PropertyCascade* authorRollback() const { return m_authorRollback.get(); }
+ Style::PropertyCascade* userRollback() const { return m_userRollback.get(); }
- void setAuthorRollback(std::unique_ptr<CascadedProperties>& rollback) { m_authorRollback = WTFMove(rollback); }
- void setUserRollback(std::unique_ptr<CascadedProperties>& rollback) { m_userRollback = WTFMove(rollback); }
+ void setAuthorRollback(std::unique_ptr<Style::PropertyCascade>& rollback) { m_authorRollback = WTFMove(rollback); }
+ void setUserRollback(std::unique_ptr<Style::PropertyCascade>& rollback) { m_userRollback = WTFMove(rollback); }
const SelectorFilter* selectorFilter() const { return m_selectorFilter; }
@@ -357,8 +307,8 @@
const RenderStyle* m_parentStyle { nullptr };
std::unique_ptr<RenderStyle> m_ownedParentStyle;
const RenderStyle* m_rootElementStyle { nullptr };
- std::unique_ptr<CascadedProperties> m_authorRollback;
- std::unique_ptr<CascadedProperties> m_userRollback;
+ std::unique_ptr<Style::PropertyCascade> m_authorRollback;
+ std::unique_ptr<Style::PropertyCascade> m_userRollback;
const SelectorFilter* m_selectorFilter { nullptr };
@@ -371,7 +321,7 @@
Style::ScopeOrdinal m_styleScopeOrdinal { Style::ScopeOrdinal::Element };
InsideLink m_elementLinkState { InsideLink::NotInside };
- CascadeLevel m_cascadeLevel { CascadeLevel::UserAgentLevel };
+ Style::CascadeLevel m_cascadeLevel { Style::CascadeLevel::UserAgent };
bool m_applyPropertyToRegularStyle { true };
bool m_applyPropertyToVisitedLinkStyle { false };
@@ -388,10 +338,7 @@
bool applyPropertyToRegularStyle() const { return m_state.applyPropertyToRegularStyle(); }
bool applyPropertyToVisitedLinkStyle() const { return m_state.applyPropertyToVisitedLinkStyle(); }
- CascadeLevel cascadeLevel() const { return m_state.cascadeLevel(); }
- void setCascadeLevel(CascadeLevel level) { m_state.setCascadeLevel(level); }
-
- CascadedProperties* cascadedPropertiesForRollback(const MatchResult&);
+ Style::PropertyCascade* cascadedPropertiesForRollback(const MatchResult&);
CSSToStyleMap* styleMap() { return &m_styleMap; }
InspectorCSSOMWrappers& inspectorCSSOMWrappers() { return m_inspectorCSSOMWrappers; }
@@ -407,11 +354,11 @@
bool adjustRenderStyleForTextAutosizing(RenderStyle&, const Element&);
+ void applyProperty(CSSPropertyID, CSSValue*, ApplyCascadedPropertyState&, SelectorChecker::LinkMatchMask = SelectorChecker::MatchDefault);
+
private:
void cacheBorderAndBackground();
- void applyProperty(CSSPropertyID, CSSValue*, ApplyCascadedPropertyState&, SelectorChecker::LinkMatchMask = SelectorChecker::MatchDefault);
-
void applySVGProperty(CSSPropertyID, CSSValue*);
static unsigned computeMatchedPropertiesHash(const MatchResult&);
@@ -476,7 +423,7 @@
// properties have been resolved.
struct ApplyCascadedPropertyState {
StyleResolver* styleResolver;
- StyleResolver::CascadedProperties* cascade;
+ Style::PropertyCascade* cascade;
const MatchResult* matchResult;
Bitmap<numCSSProperties> appliedProperties = { };
HashSet<String> appliedCustomProperties = { };
@@ -484,7 +431,6 @@
HashSet<String> inProgressPropertiesCustom = { };
};
-
inline bool StyleResolver::hasSelectorForAttribute(const Element& element, const AtomString &attributeName) const
{
ASSERT(!attributeName.isEmpty());
diff --git a/Source/WebCore/style/PropertyCascade.cpp b/Source/WebCore/style/PropertyCascade.cpp
new file mode 100644
index 0000000..53cd601
--- /dev/null
+++ b/Source/WebCore/style/PropertyCascade.cpp
@@ -0,0 +1,343 @@
+/*
+ * Copyright (C) 2019 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "PropertyCascade.h"
+
+#include "StyleResolver.h"
+
+namespace WebCore {
+namespace Style {
+
+static inline bool shouldApplyPropertyInParseOrder(CSSPropertyID propertyID)
+{
+ switch (propertyID) {
+ case CSSPropertyWebkitBackgroundClip:
+ case CSSPropertyBackgroundClip:
+ case CSSPropertyWebkitBackgroundOrigin:
+ case CSSPropertyBackgroundOrigin:
+ case CSSPropertyWebkitBackgroundSize:
+ case CSSPropertyBackgroundSize:
+ case CSSPropertyWebkitBorderImage:
+ case CSSPropertyBorderImage:
+ case CSSPropertyBorderImageSlice:
+ case CSSPropertyBorderImageSource:
+ case CSSPropertyBorderImageOutset:
+ case CSSPropertyBorderImageRepeat:
+ case CSSPropertyBorderImageWidth:
+ case CSSPropertyWebkitBoxShadow:
+ case CSSPropertyBoxShadow:
+ case CSSPropertyWebkitTextDecoration:
+ case CSSPropertyTextDecorationLine:
+ case CSSPropertyTextDecorationStyle:
+ case CSSPropertyTextDecorationColor:
+ case CSSPropertyTextDecorationSkip:
+ case CSSPropertyTextUnderlinePosition:
+ case CSSPropertyTextUnderlineOffset:
+ case CSSPropertyTextDecorationThickness:
+ case CSSPropertyTextDecoration:
+ return true;
+ default:
+ return false;
+ }
+}
+
+// https://www.w3.org/TR/css-pseudo-4/#marker-pseudo (Editor's Draft, 25 July 2017)
+static inline bool isValidMarkerStyleProperty(CSSPropertyID id)
+{
+ switch (id) {
+ case CSSPropertyColor:
+ case CSSPropertyFontFamily:
+ case CSSPropertyFontFeatureSettings:
+ case CSSPropertyFontSize:
+ case CSSPropertyFontStretch:
+ case CSSPropertyFontStyle:
+ case CSSPropertyFontSynthesis:
+ case CSSPropertyFontVariantAlternates:
+ case CSSPropertyFontVariantCaps:
+ case CSSPropertyFontVariantEastAsian:
+ case CSSPropertyFontVariantLigatures:
+ case CSSPropertyFontVariantNumeric:
+ case CSSPropertyFontVariantPosition:
+ case CSSPropertyFontWeight:
+#if ENABLE(VARIATION_FONTS)
+ case CSSPropertyFontOpticalSizing:
+ case CSSPropertyFontVariationSettings:
+#endif
+ return true;
+ default:
+ break;
+ }
+ return false;
+}
+
+#if ENABLE(VIDEO_TRACK)
+static inline bool isValidCueStyleProperty(CSSPropertyID id)
+{
+ switch (id) {
+ case CSSPropertyBackground:
+ case CSSPropertyBackgroundAttachment:
+ case CSSPropertyBackgroundClip:
+ case CSSPropertyBackgroundColor:
+ case CSSPropertyBackgroundImage:
+ case CSSPropertyBackgroundOrigin:
+ case CSSPropertyBackgroundPosition:
+ case CSSPropertyBackgroundPositionX:
+ case CSSPropertyBackgroundPositionY:
+ case CSSPropertyBackgroundRepeat:
+ case CSSPropertyBackgroundSize:
+ case CSSPropertyColor:
+ case CSSPropertyFont:
+ case CSSPropertyFontFamily:
+ case CSSPropertyFontSize:
+ case CSSPropertyFontStyle:
+ case CSSPropertyFontVariantCaps:
+ case CSSPropertyFontWeight:
+ case CSSPropertyLineHeight:
+ case CSSPropertyOpacity:
+ case CSSPropertyOutline:
+ case CSSPropertyOutlineColor:
+ case CSSPropertyOutlineOffset:
+ case CSSPropertyOutlineStyle:
+ case CSSPropertyOutlineWidth:
+ case CSSPropertyVisibility:
+ case CSSPropertyWhiteSpace:
+ case CSSPropertyTextDecoration:
+ case CSSPropertyTextShadow:
+ case CSSPropertyBorderStyle:
+ case CSSPropertyPaintOrder:
+ case CSSPropertyStrokeLinejoin:
+ case CSSPropertyStrokeLinecap:
+ case CSSPropertyStrokeColor:
+ case CSSPropertyStrokeWidth:
+ return true;
+ default:
+ break;
+ }
+ return false;
+}
+#endif
+
+PropertyCascade::PropertyCascade(TextDirection direction, WritingMode writingMode)
+ : m_direction(direction)
+ , m_writingMode(writingMode)
+{
+}
+
+PropertyCascade::~PropertyCascade() = default;
+
+void PropertyCascade::setPropertyInternal(Property& property, CSSPropertyID id, CSSValue& cssValue, unsigned linkMatchType, CascadeLevel cascadeLevel, ScopeOrdinal styleScopeOrdinal)
+{
+ ASSERT(linkMatchType <= SelectorChecker::MatchAll);
+ property.id = id;
+ property.level = cascadeLevel;
+ property.styleScopeOrdinal = styleScopeOrdinal;
+ if (linkMatchType == SelectorChecker::MatchAll) {
+ property.cssValue[0] = &cssValue;
+ property.cssValue[SelectorChecker::MatchLink] = &cssValue;
+ property.cssValue[SelectorChecker::MatchVisited] = &cssValue;
+ } else
+ property.cssValue[linkMatchType] = &cssValue;
+}
+
+void PropertyCascade::set(CSSPropertyID id, CSSValue& cssValue, unsigned linkMatchType, CascadeLevel cascadeLevel, ScopeOrdinal styleScopeOrdinal)
+{
+ if (CSSProperty::isDirectionAwareProperty(id))
+ id = CSSProperty::resolveDirectionAwareProperty(id, m_direction, m_writingMode);
+
+ ASSERT(!shouldApplyPropertyInParseOrder(id));
+
+ auto& property = m_properties[id];
+ ASSERT(id < m_propertyIsPresent.size());
+ if (id == CSSPropertyCustom) {
+ m_propertyIsPresent.set(id);
+ const auto& customValue = downcast<CSSCustomPropertyValue>(cssValue);
+ bool hasValue = customProperties().contains(customValue.name());
+ if (!hasValue) {
+ Property property;
+ property.id = id;
+ memset(property.cssValue, 0, sizeof(property.cssValue));
+ setPropertyInternal(property, id, cssValue, linkMatchType, cascadeLevel, styleScopeOrdinal);
+ customProperties().set(customValue.name(), property);
+ } else {
+ Property property = customProperties().get(customValue.name());
+ setPropertyInternal(property, id, cssValue, linkMatchType, cascadeLevel, styleScopeOrdinal);
+ customProperties().set(customValue.name(), property);
+ }
+ return;
+ }
+
+ if (!m_propertyIsPresent[id])
+ memset(property.cssValue, 0, sizeof(property.cssValue));
+ m_propertyIsPresent.set(id);
+ setPropertyInternal(property, id, cssValue, linkMatchType, cascadeLevel, styleScopeOrdinal);
+}
+
+void PropertyCascade::setDeferred(CSSPropertyID id, CSSValue& cssValue, unsigned linkMatchType, CascadeLevel cascadeLevel, ScopeOrdinal styleScopeOrdinal)
+{
+ ASSERT(!CSSProperty::isDirectionAwareProperty(id));
+ ASSERT(shouldApplyPropertyInParseOrder(id));
+
+ Property property;
+ memset(property.cssValue, 0, sizeof(property.cssValue));
+ setPropertyInternal(property, id, cssValue, linkMatchType, cascadeLevel, styleScopeOrdinal);
+ m_deferredProperties.append(property);
+}
+
+
+void PropertyCascade::addMatch(const MatchedProperties& matchedProperties, CascadeLevel cascadeLevel, bool isImportant, bool inheritedOnly)
+{
+ auto& styleProperties = *matchedProperties.properties;
+ auto propertyWhitelistType = static_cast<PropertyWhitelistType>(matchedProperties.whitelistType);
+
+ for (unsigned i = 0, count = styleProperties.propertyCount(); i < count; ++i) {
+ auto current = styleProperties.propertyAt(i);
+ if (isImportant != current.isImportant())
+ continue;
+ if (inheritedOnly && !current.isInherited()) {
+ // Inherited only mode is used after matched properties cache hit.
+ // A match with a value that is explicitly inherited should never have been cached.
+ ASSERT(!current.value()->isInheritedValue());
+ continue;
+ }
+ CSSPropertyID propertyID = current.id();
+
+#if ENABLE(VIDEO_TRACK)
+ if (propertyWhitelistType == PropertyWhitelistCue && !isValidCueStyleProperty(propertyID))
+ continue;
+#endif
+ if (propertyWhitelistType == PropertyWhitelistMarker && !isValidMarkerStyleProperty(propertyID))
+ continue;
+
+ if (shouldApplyPropertyInParseOrder(propertyID))
+ setDeferred(propertyID, *current.value(), matchedProperties.linkMatchType, cascadeLevel, matchedProperties.styleScopeOrdinal);
+ else
+ set(propertyID, *current.value(), matchedProperties.linkMatchType, cascadeLevel, matchedProperties.styleScopeOrdinal);
+ }
+}
+
+static auto& declarationsForCascadeLevel(const MatchResult& matchResult, CascadeLevel cascadeLevel)
+{
+ switch (cascadeLevel) {
+ case CascadeLevel::UserAgent: return matchResult.userAgentDeclarations;
+ case CascadeLevel::User: return matchResult.userDeclarations;
+ case CascadeLevel::Author: return matchResult.authorDeclarations;
+ }
+ ASSERT_NOT_REACHED();
+ return matchResult.authorDeclarations;
+}
+
+void PropertyCascade::addNormalMatches(const MatchResult& matchResult, CascadeLevel cascadeLevel, bool inheritedOnly)
+{
+ for (auto& matchedDeclarations : declarationsForCascadeLevel(matchResult, cascadeLevel))
+ addMatch(matchedDeclarations, cascadeLevel, false, inheritedOnly);
+}
+
+static bool hasImportantProperties(const StyleProperties& properties)
+{
+ for (unsigned i = 0, count = properties.propertyCount(); i < count; ++i) {
+ if (properties.propertyAt(i).isImportant())
+ return true;
+ }
+ return false;
+}
+
+void PropertyCascade::addImportantMatches(const MatchResult& matchResult, CascadeLevel cascadeLevel, bool inheritedOnly)
+{
+ struct IndexAndOrdinal {
+ unsigned index;
+ ScopeOrdinal ordinal;
+ };
+ Vector<IndexAndOrdinal> importantMatches;
+ bool hasMatchesFromOtherScopes = false;
+
+ auto& matchedDeclarations = declarationsForCascadeLevel(matchResult, cascadeLevel);
+
+ for (unsigned i = 0; i < matchedDeclarations.size(); ++i) {
+ const MatchedProperties& matchedProperties = matchedDeclarations[i];
+
+ if (!hasImportantProperties(*matchedProperties.properties))
+ continue;
+
+ importantMatches.append({ i, matchedProperties.styleScopeOrdinal });
+
+ if (matchedProperties.styleScopeOrdinal != ScopeOrdinal::Element)
+ hasMatchesFromOtherScopes = true;
+ }
+
+ if (importantMatches.isEmpty())
+ return;
+
+ if (hasMatchesFromOtherScopes) {
+ // For !important properties a later shadow tree wins.
+ // Match results are sorted in reverse tree context order so this is not needed for normal properties.
+ std::stable_sort(importantMatches.begin(), importantMatches.end(), [] (const IndexAndOrdinal& a, const IndexAndOrdinal& b) {
+ return a.ordinal < b.ordinal;
+ });
+ }
+
+ for (auto& match : importantMatches)
+ addMatch(matchedDeclarations[match.index], cascadeLevel, true, inheritedOnly);
+}
+
+void PropertyCascade::applyDeferredProperties(StyleResolver& resolver, ApplyCascadedPropertyState& applyState)
+{
+ for (auto& property : m_deferredProperties)
+ property.apply(resolver, applyState);
+}
+
+void PropertyCascade::Property::apply(StyleResolver& resolver, ApplyCascadedPropertyState& applyState)
+{
+ StyleResolver::State& state = resolver.state();
+ state.setCascadeLevel(level);
+ state.setStyleScopeOrdinal(styleScopeOrdinal);
+
+ if (cssValue[SelectorChecker::MatchDefault]) {
+ state.setApplyPropertyToRegularStyle(true);
+ state.setApplyPropertyToVisitedLinkStyle(false);
+ resolver.applyProperty(id, cssValue[SelectorChecker::MatchDefault], applyState, SelectorChecker::MatchDefault);
+ }
+
+ if (state.style()->insideLink() == InsideLink::NotInside)
+ return;
+
+ if (cssValue[SelectorChecker::MatchLink]) {
+ state.setApplyPropertyToRegularStyle(true);
+ state.setApplyPropertyToVisitedLinkStyle(false);
+ resolver.applyProperty(id, cssValue[SelectorChecker::MatchLink], applyState, SelectorChecker::MatchLink);
+ }
+
+ if (cssValue[SelectorChecker::MatchVisited]) {
+ state.setApplyPropertyToRegularStyle(false);
+ state.setApplyPropertyToVisitedLinkStyle(true);
+ resolver.applyProperty(id, cssValue[SelectorChecker::MatchVisited], applyState, SelectorChecker::MatchVisited);
+ }
+
+ state.setApplyPropertyToRegularStyle(true);
+ state.setApplyPropertyToVisitedLinkStyle(false);
+}
+
+}
+}
diff --git a/Source/WebCore/style/PropertyCascade.h b/Source/WebCore/style/PropertyCascade.h
new file mode 100644
index 0000000..4e9d62a
--- /dev/null
+++ b/Source/WebCore/style/PropertyCascade.h
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2019 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "ElementRuleCollector.h"
+#include <bitset>
+#include <wtf/Bitmap.h>
+
+namespace WebCore {
+
+class StyleResolver;
+struct ApplyCascadedPropertyState;
+
+namespace Style {
+
+enum class CascadeLevel : uint8_t {
+ UserAgent,
+ User,
+ Author
+};
+
+class PropertyCascade {
+ WTF_MAKE_FAST_ALLOCATED;
+public:
+ PropertyCascade(TextDirection, WritingMode);
+ ~PropertyCascade();
+
+ struct Property {
+ void apply(StyleResolver&, ApplyCascadedPropertyState&);
+
+ CSSPropertyID id;
+ CascadeLevel level;
+ ScopeOrdinal styleScopeOrdinal;
+ CSSValue* cssValue[3];
+ };
+
+ bool hasProperty(CSSPropertyID) const;
+ Property& property(CSSPropertyID);
+
+ void addNormalMatches(const MatchResult&, CascadeLevel, bool inheritedOnly = false);
+ void addImportantMatches(const MatchResult&, CascadeLevel, bool inheritedOnly = false);
+
+ void applyDeferredProperties(StyleResolver&, ApplyCascadedPropertyState&);
+
+ HashMap<AtomString, Property>& customProperties() { return m_customProperties; }
+ bool hasCustomProperty(const String&) const;
+ Property customProperty(const String&) const;
+
+private:
+ void addMatch(const MatchedProperties&, CascadeLevel, bool isImportant, bool inheritedOnly);
+ void set(CSSPropertyID, CSSValue&, unsigned linkMatchType, CascadeLevel, ScopeOrdinal);
+ void setDeferred(CSSPropertyID, CSSValue&, unsigned linkMatchType, CascadeLevel, ScopeOrdinal);
+ static void setPropertyInternal(Property&, CSSPropertyID, CSSValue&, unsigned linkMatchType, CascadeLevel, ScopeOrdinal);
+
+ Property m_properties[numCSSProperties + 2];
+ std::bitset<numCSSProperties + 2> m_propertyIsPresent;
+
+ Vector<Property, 8> m_deferredProperties;
+ HashMap<AtomString, Property> m_customProperties;
+
+ TextDirection m_direction;
+ WritingMode m_writingMode;
+};
+
+inline bool PropertyCascade::hasProperty(CSSPropertyID id) const
+{
+ ASSERT(id < m_propertyIsPresent.size());
+ return m_propertyIsPresent[id];
+}
+
+inline PropertyCascade::Property& PropertyCascade::property(CSSPropertyID id)
+{
+ return m_properties[id];
+}
+
+inline bool PropertyCascade::hasCustomProperty(const String& name) const
+{
+ return m_customProperties.contains(name);
+}
+
+inline PropertyCascade::Property PropertyCascade::customProperty(const String& name) const
+{
+ return m_customProperties.get(name);
+}
+
+}
+}