Diff
Modified: trunk/Source/WebCore/ChangeLog (283487 => 283488)
--- trunk/Source/WebCore/ChangeLog 2021-10-04 05:37:08 UTC (rev 283487)
+++ trunk/Source/WebCore/ChangeLog 2021-10-04 06:37:45 UTC (rev 283488)
@@ -1,3 +1,52 @@
+2021-10-03 Antti Koivisto <[email protected]>
+
+ Move RuleSet builder to a file of its own
+ https://bugs.webkit.org/show_bug.cgi?id=231137
+
+ Reviewed by Alan Bujtas.
+
+ There is quite a bit of code for it.
+
+ There is lots of room for refactoring and cleanups here. This patch does none of it.
+
+ * Sources.txt:
+ * WebCore.xcodeproj/project.pbxproj:
+ * style/RuleSet.cpp:
+ (WebCore::Style::RuleSet::addRule):
+ (WebCore::Style::RuleSet::addRulesFromSheet):
+ (WebCore::Style::RuleSet::Builder::addChildRules): Deleted.
+ (WebCore::Style::RuleSet::Builder::addRulesFromSheet): Deleted.
+ (WebCore::Style::RuleSet::Builder::~Builder): Deleted.
+ (WebCore::Style::RuleSet::Builder::addStyleRule): Deleted.
+ (WebCore::Style::RuleSet::Builder::registerLayers): Deleted.
+ (WebCore::Style::RuleSet::Builder::pushCascadeLayer): Deleted.
+ (WebCore::Style::RuleSet::Builder::popCascadeLayer): Deleted.
+ (WebCore::Style::RuleSet::Builder::updateCascadeLayerOrder): Deleted.
+ (WebCore::Style::RuleSet::Builder::addMutatingRulesToResolver): Deleted.
+ (WebCore::Style::RuleSet::MediaQueryCollector::pushAndEvaluate): Deleted.
+ (WebCore::Style::RuleSet::MediaQueryCollector::pop): Deleted.
+ (WebCore::Style::RuleSet::MediaQueryCollector::didMutateResolver): Deleted.
+ (WebCore::Style::RuleSet::MediaQueryCollector::addRuleIfNeeded): Deleted.
+
+ MediaQueryCollector (an implementation detail of the Builder) moves too.
+
+ * style/RuleSet.h:
+ * style/RuleSetBuilder.cpp: Added.
+ (WebCore::Style::RuleSetBuilder::~RuleSetBuilder):
+ (WebCore::Style::RuleSetBuilder::addChildRules):
+ (WebCore::Style::RuleSetBuilder::addRulesFromSheet):
+ (WebCore::Style::RuleSetBuilder::addStyleRule):
+ (WebCore::Style::RuleSetBuilder::registerLayers):
+ (WebCore::Style::RuleSetBuilder::pushCascadeLayer):
+ (WebCore::Style::RuleSetBuilder::popCascadeLayer):
+ (WebCore::Style::RuleSetBuilder::updateCascadeLayerOrder):
+ (WebCore::Style::RuleSetBuilder::addMutatingRulesToResolver):
+ (WebCore::Style::RuleSetMediaQueryCollector::pushAndEvaluate):
+ (WebCore::Style::RuleSetMediaQueryCollector::pop):
+ (WebCore::Style::RuleSetMediaQueryCollector::didMutateResolver):
+ (WebCore::Style::RuleSetMediaQueryCollector::addRuleIfNeeded):
+ * style/RuleSetBuilder.h: Added.
+
2021-10-03 Alan Bujtas <[email protected]>
[LFC][IFC] Do not take hanging whitespace sequence into account while finding expansion opportunities
Modified: trunk/Source/WebCore/Sources.txt (283487 => 283488)
--- trunk/Source/WebCore/Sources.txt 2021-10-04 05:37:08 UTC (rev 283487)
+++ trunk/Source/WebCore/Sources.txt 2021-10-04 06:37:45 UTC (rev 283488)
@@ -2480,6 +2480,7 @@
style/RuleData.cpp
style/RuleFeature.cpp
style/RuleSet.cpp
+style/RuleSetBuilder.cpp
style/StyleAdjuster.cpp
style/StyleBuilder.cpp
style/StyleBuilderState.cpp
Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (283487 => 283488)
--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj 2021-10-04 05:37:08 UTC (rev 283487)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj 2021-10-04 06:37:45 UTC (rev 283488)
@@ -5271,6 +5271,7 @@
E47C39321FE6E10500BBBC6B /* RenderTreeBuilderList.h in Headers */ = {isa = PBXBuildFile; fileRef = E47C39281FE6E0DD00BBBC6B /* RenderTreeBuilderList.h */; };
E47C39331FE6E10800BBBC6B /* RenderTreeBuilderMultiColumn.h in Headers */ = {isa = PBXBuildFile; fileRef = E47C39271FE6E0DC00BBBC6B /* RenderTreeBuilderMultiColumn.h */; };
E47CEBC92706EF5200B8D8F5 /* InlineWalker.h in Headers */ = {isa = PBXBuildFile; fileRef = E47CEBC72706EF5100B8D8F5 /* InlineWalker.h */; };
+ E47CEBEA2709DFD100B8D8F5 /* RuleSetBuilder.h in Headers */ = {isa = PBXBuildFile; fileRef = E47CEBE82709DFD000B8D8F5 /* RuleSetBuilder.h */; };
E47CEBE12709916D00B8D8F5 /* InlineIteratorTextBox.h in Headers */ = {isa = PBXBuildFile; fileRef = E47CEBE02709916D00B8D8F5 /* InlineIteratorTextBox.h */; settings = {ATTRIBUTES = (Private, ); }; };
E47E276516036ED200EE2AFB /* ExtensionStyleSheets.h in Headers */ = {isa = PBXBuildFile; fileRef = E47E276416036ED200EE2AFB /* ExtensionStyleSheets.h */; settings = {ATTRIBUTES = (Private, ); }; };
E47FC8A325B84D72005495FC /* LoadSchedulingMode.h in Headers */ = {isa = PBXBuildFile; fileRef = E47FC8A125B84D71005495FC /* LoadSchedulingMode.h */; settings = {ATTRIBUTES = (Private, ); }; };
@@ -16531,6 +16532,8 @@
E47C392B1FE6E0DF00BBBC6B /* RenderTreeBuilderList.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RenderTreeBuilderList.cpp; sourceTree = "<group>"; };
E47C392C1FE6E0DF00BBBC6B /* RenderTreeUpdater.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RenderTreeUpdater.h; sourceTree = "<group>"; };
E47CEBC72706EF5100B8D8F5 /* InlineWalker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InlineWalker.h; sourceTree = "<group>"; };
+ E47CEBE82709DFD000B8D8F5 /* RuleSetBuilder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RuleSetBuilder.h; sourceTree = "<group>"; };
+ E47CEBEB2709DFDC00B8D8F5 /* RuleSetBuilder.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = RuleSetBuilder.cpp; sourceTree = "<group>"; };
E47CEBDE2709916400B8D8F5 /* InlineIteratorTextBox.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = InlineIteratorTextBox.cpp; sourceTree = "<group>"; };
E47CEBE02709916D00B8D8F5 /* InlineIteratorTextBox.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InlineIteratorTextBox.h; sourceTree = "<group>"; };
E47E276416036ED200EE2AFB /* ExtensionStyleSheets.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ExtensionStyleSheets.h; sourceTree = "<group>"; };
@@ -29403,6 +29406,8 @@
A79BAD9E161E7F3F00C2E652 /* RuleFeature.h */,
A79BAD9F161E7F3F00C2E652 /* RuleSet.cpp */,
A79BADA0161E7F3F00C2E652 /* RuleSet.h */,
+ E47CEBEB2709DFDC00B8D8F5 /* RuleSetBuilder.cpp */,
+ E47CEBE82709DFD000B8D8F5 /* RuleSetBuilder.h */,
7173DEBD2614DF040097DF32 /* Styleable.cpp */,
713922BC2518AB70005DB3C2 /* Styleable.h */,
E45BA6B22376227E004DFC07 /* StyleAdjuster.cpp */,
@@ -35001,6 +35006,7 @@
E4863CFE23842E9E00972158 /* RuleData.h in Headers */,
A79BADA2161E7F3F00C2E652 /* RuleFeature.h in Headers */,
A79BADA4161E7F3F00C2E652 /* RuleSet.h in Headers */,
+ E47CEBEA2709DFD100B8D8F5 /* RuleSetBuilder.h in Headers */,
51BA947123AC305300444846 /* RunJavaScriptParameters.h in Headers */,
2D76BB821945632400CFD29A /* RunLoopObserver.h in Headers */,
1A569D1F0D7E2B82007C3983 /* runtime_array.h in Headers */,
Modified: trunk/Source/WebCore/style/RuleSet.cpp (283487 => 283488)
--- trunk/Source/WebCore/style/RuleSet.cpp 2021-10-04 05:37:08 UTC (rev 283487)
+++ trunk/Source/WebCore/style/RuleSet.cpp 2021-10-04 06:37:45 UTC (rev 283488)
@@ -35,6 +35,7 @@
#include "CSSSelectorList.h"
#include "HTMLNames.h"
#include "MediaQueryEvaluator.h"
+#include "RuleSetBuilder.h"
#include "SecurityOrigin.h"
#include "SelectorChecker.h"
#include "SelectorFilter.h"
@@ -83,7 +84,7 @@
return leftmostSelector->match() == CSSSelector::PseudoClass && leftmostSelector->pseudoClassType() == CSSSelector::PseudoClassHost;
}
-void RuleSet::addRule(const StyleRule& rule, unsigned selectorIndex, unsigned selectorListIndex, unsigned cascadeLayerIdentifier, MediaQueryCollector* mediaQueryCollector)
+void RuleSet::addRule(const StyleRule& rule, unsigned selectorIndex, unsigned selectorListIndex, unsigned cascadeLayerIdentifier, RuleSetMediaQueryCollector* mediaQueryCollector)
{
RuleData ruleData(rule, selectorIndex, selectorListIndex, m_ruleCount++);
@@ -273,7 +274,7 @@
void RuleSet::addRulesFromSheet(const StyleSheetContents& sheet, const MediaQueryEvaluator& evaluator)
{
- Builder builder { *this, MediaQueryCollector { evaluator } };
+ RuleSetBuilder builder { *this, RuleSetMediaQueryCollector { evaluator } };
builder.addRulesFromSheet(sheet);
if (m_autoShrinkToFitEnabled)
@@ -283,7 +284,7 @@
void RuleSet::addRulesFromSheet(const StyleSheetContents& sheet, const MediaQuerySet* sheetQuery, const MediaQueryEvaluator& evaluator, Style::Resolver& resolver)
{
auto canUseDynamicMediaQueryResolution = [&] {
- Builder builder { *this, MediaQueryCollector { evaluator, true }, nullptr, Builder::Mode::ResolverMutationScan };
+ RuleSetBuilder builder { *this, RuleSetMediaQueryCollector { evaluator, true }, nullptr, RuleSetBuilder::Mode::ResolverMutationScan };
if (builder.mediaQueryCollector.pushAndEvaluate(sheetQuery))
builder.addRulesFromSheet(sheet);
builder.mediaQueryCollector.pop(sheetQuery);
@@ -290,7 +291,7 @@
return !builder.mediaQueryCollector.didMutateResolverWithinDynamicMediaQuery;
}();
- Builder builder { *this, MediaQueryCollector { evaluator, canUseDynamicMediaQueryResolution }, &resolver };
+ RuleSetBuilder builder { *this, RuleSetMediaQueryCollector { evaluator, canUseDynamicMediaQueryResolution }, &resolver };
if (builder.mediaQueryCollector.pushAndEvaluate(sheetQuery))
builder.addRulesFromSheet(sheet);
@@ -310,227 +311,6 @@
shrinkToFit();
}
-void RuleSet::Builder::addChildRules(const Vector<RefPtr<StyleRuleBase>>& rules)
-{
- for (auto& rule : rules) {
- if (mode == Mode::ResolverMutationScan && mediaQueryCollector.didMutateResolverWithinDynamicMediaQuery)
- break;
-
- if (is<StyleRule>(*rule)) {
- if (mode == Mode::Normal)
- addStyleRule(downcast<StyleRule>(*rule));
- continue;
- }
- if (is<StyleRulePage>(*rule)) {
- if (mode == Mode::Normal)
- ruleSet->addPageRule(downcast<StyleRulePage>(*rule));
- continue;
- }
- if (is<StyleRuleMedia>(*rule)) {
- auto& mediaRule = downcast<StyleRuleMedia>(*rule);
- if (mediaQueryCollector.pushAndEvaluate(&mediaRule.mediaQueries()))
- addChildRules(mediaRule.childRules());
- mediaQueryCollector.pop(&mediaRule.mediaQueries());
- continue;
- }
- if (is<StyleRuleLayer>(*rule)) {
- auto& layerRule = downcast<StyleRuleLayer>(*rule);
- if (layerRule.isStatement()) {
- // Statement syntax just registers the layers.
- registerLayers(layerRule.nameList());
- continue;
- }
- // Block syntax.
- pushCascadeLayer(layerRule.name());
- addChildRules(layerRule.childRules());
- popCascadeLayer(layerRule.name());
- continue;
- }
- if (is<StyleRuleFontFace>(*rule) || is<StyleRuleFontPaletteValues>(*rule) || is<StyleRuleKeyframes>(*rule)) {
- if (mode == Mode::ResolverMutationScan) {
- mediaQueryCollector.didMutateResolver();
- continue;
- }
- if (resolver)
- collectedResolverMutatingRules.append({ *rule, currentCascadeLayerIdentifier });
- continue;
- }
- if (is<StyleRuleSupports>(*rule) && downcast<StyleRuleSupports>(*rule).conditionIsSupported()) {
- addChildRules(downcast<StyleRuleSupports>(*rule).childRules());
- continue;
- }
- }
-}
-
-void RuleSet::Builder::addRulesFromSheet(const StyleSheetContents& sheet)
-{
- for (auto& rule : sheet.layerRulesBeforeImportRules())
- registerLayers(rule->nameList());
-
- for (auto& rule : sheet.importRules()) {
- if (!rule->styleSheet())
- continue;
-
- if (mediaQueryCollector.pushAndEvaluate(rule->mediaQueries())) {
- auto& cascadeLayerName = rule->cascadeLayerName();
- if (cascadeLayerName)
- pushCascadeLayer(*cascadeLayerName);
-
- addRulesFromSheet(*rule->styleSheet());
-
- if (cascadeLayerName)
- popCascadeLayer(*cascadeLayerName);
- }
- mediaQueryCollector.pop(rule->mediaQueries());
- }
-
- addChildRules(sheet.childRules());
-}
-
-RuleSet::Builder::~Builder()
-{
- if (mode == Mode::ResolverMutationScan)
- return;
-
- updateCascadeLayerOrder();
- addMutatingRulesToResolver();
-}
-
-void RuleSet::Builder::addStyleRule(const StyleRule& rule)
-{
- auto& selectorList = rule.selectorList();
- if (selectorList.isEmpty())
- return;
- unsigned selectorListIndex = 0;
- for (size_t selectorIndex = 0; selectorIndex != notFound; selectorIndex = selectorList.indexOfNextSelectorAfter(selectorIndex))
- ruleSet->addRule(rule, selectorIndex, selectorListIndex++, currentCascadeLayerIdentifier, &mediaQueryCollector);
-}
-
-void RuleSet::Builder::registerLayers(const Vector<CascadeLayerName>& names)
-{
- for (auto& name : names) {
- pushCascadeLayer(name);
- popCascadeLayer(name);
- }
-}
-
-void RuleSet::Builder::pushCascadeLayer(const CascadeLayerName& name)
-{
- if (mode != Mode::Normal)
- return;
-
- if (cascadeLayerIdentifierMap.isEmpty() && !ruleSet->m_cascadeLayers.isEmpty()) {
- // For incremental build, reconstruct the name->identifier map.
- CascadeLayerIdentifier identifier = 0;
- for (auto& layer : ruleSet->m_cascadeLayers)
- cascadeLayerIdentifierMap.add(layer.resolvedName, ++identifier);
- }
-
- auto nameResolvingAnonymous = [&] {
- if (name.isEmpty()) {
- // Make unique name for an anonymous layer.
- unsigned long long random = randomNumber() * std::numeric_limits<unsigned long long>::max();
- return CascadeLayerName { "anon_"_s + String::number(random) };
- }
- return name;
- };
-
- // For hierarchical names we register the containing layers individually first.
- for (auto& nameSegment : nameResolvingAnonymous()) {
- resolvedCascadeLayerName.append(nameSegment);
- currentCascadeLayerIdentifier = cascadeLayerIdentifierMap.ensure(resolvedCascadeLayerName, [&] {
- // Previously unseen layer.
- ruleSet->m_cascadeLayers.append({ resolvedCascadeLayerName, currentCascadeLayerIdentifier });
- return ruleSet->m_cascadeLayers.size();
- }).iterator->value;
- }
-}
-
-void RuleSet::Builder::popCascadeLayer(const CascadeLayerName& name)
-{
- if (mode != Mode::Normal)
- return;
-
- for (auto size = name.isEmpty() ? 1 : name.size(); size--;) {
- resolvedCascadeLayerName.removeLast();
- currentCascadeLayerIdentifier = ruleSet->cascadeLayerForIdentifier(currentCascadeLayerIdentifier).parentIdentifier;
- }
-}
-
-void RuleSet::Builder::updateCascadeLayerOrder()
-{
- if (cascadeLayerIdentifierMap.isEmpty())
- return;
-
- auto compare = [&](CascadeLayerIdentifier a, CascadeLayerIdentifier b) {
- while (a && b) {
- // Identifiers are in parse order which almost corresponds to the layer priority order.
- // The only exception is when a sublayer gets added to a layer after adding other non-sublayers.
- // To resolve this we need look for a shared ancestor layer.
- auto aParent = ruleSet->cascadeLayerForIdentifier(a).parentIdentifier;
- auto bParent = ruleSet->cascadeLayerForIdentifier(b).parentIdentifier;
- if (aParent == bParent || aParent == b || bParent == a)
- break;
- if (aParent > bParent)
- a = aParent;
- else
- b = bParent;
- }
- return a < b;
- };
-
- Vector<CascadeLayerIdentifier> orderVector;
- auto layerCount = ruleSet->m_cascadeLayers.size();
- orderVector.reserveInitialCapacity(layerCount);
- for (CascadeLayerIdentifier identifier = 1; identifier <= layerCount; ++identifier)
- orderVector.uncheckedAppend(identifier);
-
- std::sort(orderVector.begin(), orderVector.end(), compare);
-
- for (unsigned i = 0; i < orderVector.size(); ++i)
- ruleSet->cascadeLayerForIdentifier(orderVector[i]).order = i + 1;
-}
-
-void RuleSet::Builder::addMutatingRulesToResolver()
-{
- if (!resolver)
- return;
-
- auto compareLayers = [&](const ResolverMutatingRule& a, const ResolverMutatingRule& b) {
- auto aOrder = ruleSet->cascadeLayerOrderForIdentifier(a.layerIdentifier);
- auto bOrder = ruleSet->cascadeLayerOrderForIdentifier(b.layerIdentifier);
- return aOrder < bOrder;
- };
-
- // The order may change so we need to reprocess resolver mutating rules from earlier stylesheets.
- auto rulesToAdd = std::exchange(ruleSet->m_resolverMutatingRulesInLayers, { });
- rulesToAdd.appendVector(WTFMove(collectedResolverMutatingRules));
-
- if (!cascadeLayerIdentifierMap.isEmpty())
- std::stable_sort(rulesToAdd.begin(), rulesToAdd.end(), compareLayers);
-
- for (auto& collectedRule : rulesToAdd) {
- if (collectedRule.layerIdentifier)
- ruleSet->m_resolverMutatingRulesInLayers.append(collectedRule);
-
- auto& rule = collectedRule.rule;
- if (is<StyleRuleFontFace>(rule)) {
- resolver->document().fontSelector().addFontFaceRule(downcast<StyleRuleFontFace>(rule.get()), false);
- resolver->invalidateMatchedDeclarationsCache();
- continue;
- }
- if (is<StyleRuleFontPaletteValues>(rule)) {
- resolver->document().fontSelector().addFontPaletteValuesRule(downcast<StyleRuleFontPaletteValues>(rule.get()));
- resolver->invalidateMatchedDeclarationsCache();
- continue;
- }
- if (is<StyleRuleKeyframes>(rule)) {
- resolver->addKeyframeStyle(downcast<StyleRuleKeyframes>(rule.get()));
- continue;
- }
- }
-}
-
template<typename Function>
void RuleSet::traverseRuleDatas(Function&& function)
{
@@ -670,67 +450,5 @@
m_resolverMutatingRulesInLayers.shrinkToFit();
}
-RuleSet::MediaQueryCollector::~MediaQueryCollector() = default;
-
-bool RuleSet::MediaQueryCollector::pushAndEvaluate(const MediaQuerySet* set)
-{
- if (!set)
- return true;
-
- // Only evaluate static expressions that require style rebuild.
- MediaQueryDynamicResults dynamicResults;
- auto mode = collectDynamic ? MediaQueryEvaluator::Mode::AlwaysMatchDynamic : MediaQueryEvaluator::Mode::Normal;
-
- bool result = evaluator.evaluate(*set, &dynamicResults, mode);
-
- if (!dynamicResults.viewport.isEmpty())
- hasViewportDependentMediaQueries = true;
-
- if (!dynamicResults.isEmpty())
- dynamicContextStack.append({ *set });
-
- return result;
-}
-
-void RuleSet::MediaQueryCollector::pop(const MediaQuerySet* set)
-{
- if (!set || dynamicContextStack.isEmpty() || set != &dynamicContextStack.last().set.get())
- return;
-
- if (!dynamicContextStack.last().affectedRulePositions.isEmpty() || !collectDynamic) {
- DynamicMediaQueryRules rules;
- for (auto& context : dynamicContextStack)
- rules.mediaQuerySets.append(context.set.get());
-
- if (collectDynamic) {
- rules.affectedRulePositions.appendVector(dynamicContextStack.last().affectedRulePositions);
- rules.ruleFeatures = WTFMove(dynamicContextStack.last().ruleFeatures);
- rules.ruleFeatures.shrinkToFit();
- } else
- rules.requiresFullReset = true;
-
- dynamicMediaQueryRules.append(WTFMove(rules));
- }
-
- dynamicContextStack.removeLast();
-}
-
-void RuleSet::MediaQueryCollector::didMutateResolver()
-{
- if (dynamicContextStack.isEmpty())
- return;
- didMutateResolverWithinDynamicMediaQuery = true;
-}
-
-void RuleSet::MediaQueryCollector::addRuleIfNeeded(const RuleData& ruleData)
-{
- if (dynamicContextStack.isEmpty())
- return;
-
- auto& context = dynamicContextStack.last();
- context.affectedRulePositions.append(ruleData.position());
- context.ruleFeatures.append({ ruleData });
-}
-
} // namespace Style
} // namespace WebCore
Modified: trunk/Source/WebCore/style/RuleSet.h (283487 => 283488)
--- trunk/Source/WebCore/style/RuleSet.h 2021-10-04 05:37:08 UTC (rev 283487)
+++ trunk/Source/WebCore/style/RuleSet.h 2021-10-04 06:37:45 UTC (rev 283488)
@@ -1,6 +1,6 @@
/*
* Copyright (C) 1999 Lars Knoll ([email protected])
- * Copyright (C) 2003-2019 Apple Inc. All rights reserved.
+ * Copyright (C) 2003-2021 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
@@ -42,6 +42,7 @@
class Resolver;
class RuleSet;
+struct RuleSetMediaQueryCollector;
using InvalidationRuleSetVector = Vector<RefPtr<const RuleSet>, 1>;
@@ -85,33 +86,10 @@
}
};
- struct MediaQueryCollector {
- ~MediaQueryCollector();
-
- const MediaQueryEvaluator& evaluator;
- const bool collectDynamic { false };
-
- struct DynamicContext {
- Ref<const MediaQuerySet> set;
- Vector<size_t> affectedRulePositions { };
- RuleFeatureVector ruleFeatures { };
- };
- Vector<DynamicContext> dynamicContextStack { };
-
- Vector<DynamicMediaQueryRules> dynamicMediaQueryRules { };
- bool didMutateResolverWithinDynamicMediaQuery { false };
- bool hasViewportDependentMediaQueries { false };
-
- bool pushAndEvaluate(const MediaQuerySet*);
- void pop(const MediaQuerySet*);
- void didMutateResolver();
- void addRuleIfNeeded(const RuleData&);
- };
-
void addRulesFromSheet(const StyleSheetContents&, const MediaQueryEvaluator&);
void addRulesFromSheet(const StyleSheetContents&, const MediaQuerySet* sheetQuery, const MediaQueryEvaluator&, Style::Resolver&);
- void addRule(const StyleRule&, unsigned selectorIndex, unsigned selectorListIndex, unsigned cascadeLayerOrder = 0, MediaQueryCollector* = nullptr);
+ void addRule(const StyleRule&, unsigned selectorIndex, unsigned selectorListIndex, unsigned cascadeLayerOrder = 0, RuleSetMediaQueryCollector* = nullptr);
void addPageRule(StyleRulePage&);
void addToRuleSet(const AtomString& key, AtomRuleMap&, const RuleData&);
@@ -148,6 +126,8 @@
unsigned cascadeLayerOrderFor(const RuleData&) const;
private:
+ friend struct RuleSetBuilder;
+
RuleSet();
using CascadeLayerIdentifier = unsigned;
@@ -157,33 +137,6 @@
CascadeLayerIdentifier layerIdentifier;
};
- struct Builder {
- enum class Mode { Normal, ResolverMutationScan };
-
- Ref<RuleSet> ruleSet;
- MediaQueryCollector mediaQueryCollector;
- Style::Resolver* resolver { nullptr };
- Mode mode { Mode::Normal };
- CascadeLayerName resolvedCascadeLayerName { };
- HashMap<CascadeLayerName, CascadeLayerIdentifier> cascadeLayerIdentifierMap { };
- CascadeLayerIdentifier currentCascadeLayerIdentifier { 0 };
- Vector<ResolverMutatingRule> collectedResolverMutatingRules { };
-
- void addRulesFromSheet(const StyleSheetContents&);
-
- ~Builder();
-
- private:
- void addChildRules(const Vector<RefPtr<StyleRuleBase>>&);
- void addStyleRule(const StyleRule&);
-
- void registerLayers(const Vector<CascadeLayerName>&);
- void pushCascadeLayer(const CascadeLayerName&);
- void popCascadeLayer(const CascadeLayerName&);
- void updateCascadeLayerOrder();
- void addMutatingRulesToResolver();
- };
-
struct CollectedMediaQueryChanges {
bool requiredFullReset { false };
Vector<size_t> changedQueryIndexes { };
Added: trunk/Source/WebCore/style/RuleSetBuilder.cpp (0 => 283488)
--- trunk/Source/WebCore/style/RuleSetBuilder.cpp (rev 0)
+++ trunk/Source/WebCore/style/RuleSetBuilder.cpp 2021-10-04 06:37:45 UTC (rev 283488)
@@ -0,0 +1,319 @@
+/*
+ * 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-2021 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 "RuleSetBuilder.h"
+
+namespace WebCore {
+namespace Style {
+
+RuleSetBuilder::~RuleSetBuilder()
+{
+ if (mode == Mode::ResolverMutationScan)
+ return;
+
+ updateCascadeLayerOrder();
+ addMutatingRulesToResolver();
+}
+
+void RuleSetBuilder::addChildRules(const Vector<RefPtr<StyleRuleBase>>& rules)
+{
+ for (auto& rule : rules) {
+ if (mode == Mode::ResolverMutationScan && mediaQueryCollector.didMutateResolverWithinDynamicMediaQuery)
+ break;
+
+ if (is<StyleRule>(*rule)) {
+ if (mode == Mode::Normal)
+ addStyleRule(downcast<StyleRule>(*rule));
+ continue;
+ }
+ if (is<StyleRulePage>(*rule)) {
+ if (mode == Mode::Normal)
+ ruleSet->addPageRule(downcast<StyleRulePage>(*rule));
+ continue;
+ }
+ if (is<StyleRuleMedia>(*rule)) {
+ auto& mediaRule = downcast<StyleRuleMedia>(*rule);
+ if (mediaQueryCollector.pushAndEvaluate(&mediaRule.mediaQueries()))
+ addChildRules(mediaRule.childRules());
+ mediaQueryCollector.pop(&mediaRule.mediaQueries());
+ continue;
+ }
+ if (is<StyleRuleLayer>(*rule)) {
+ auto& layerRule = downcast<StyleRuleLayer>(*rule);
+ if (layerRule.isStatement()) {
+ // Statement syntax just registers the layers.
+ registerLayers(layerRule.nameList());
+ continue;
+ }
+ // Block syntax.
+ pushCascadeLayer(layerRule.name());
+ addChildRules(layerRule.childRules());
+ popCascadeLayer(layerRule.name());
+ continue;
+ }
+ if (is<StyleRuleFontFace>(*rule) || is<StyleRuleFontPaletteValues>(*rule) || is<StyleRuleKeyframes>(*rule)) {
+ if (mode == Mode::ResolverMutationScan) {
+ mediaQueryCollector.didMutateResolver();
+ continue;
+ }
+ if (resolver)
+ collectedResolverMutatingRules.append({ *rule, currentCascadeLayerIdentifier });
+ continue;
+ }
+ if (is<StyleRuleSupports>(*rule) && downcast<StyleRuleSupports>(*rule).conditionIsSupported()) {
+ addChildRules(downcast<StyleRuleSupports>(*rule).childRules());
+ continue;
+ }
+ }
+}
+
+void RuleSetBuilder::addRulesFromSheet(const StyleSheetContents& sheet)
+{
+ for (auto& rule : sheet.layerRulesBeforeImportRules())
+ registerLayers(rule->nameList());
+
+ for (auto& rule : sheet.importRules()) {
+ if (!rule->styleSheet())
+ continue;
+
+ if (mediaQueryCollector.pushAndEvaluate(rule->mediaQueries())) {
+ auto& cascadeLayerName = rule->cascadeLayerName();
+ if (cascadeLayerName)
+ pushCascadeLayer(*cascadeLayerName);
+
+ addRulesFromSheet(*rule->styleSheet());
+
+ if (cascadeLayerName)
+ popCascadeLayer(*cascadeLayerName);
+ }
+ mediaQueryCollector.pop(rule->mediaQueries());
+ }
+
+ addChildRules(sheet.childRules());
+}
+
+void RuleSetBuilder::addStyleRule(const StyleRule& rule)
+{
+ auto& selectorList = rule.selectorList();
+ if (selectorList.isEmpty())
+ return;
+ unsigned selectorListIndex = 0;
+ for (size_t selectorIndex = 0; selectorIndex != notFound; selectorIndex = selectorList.indexOfNextSelectorAfter(selectorIndex))
+ ruleSet->addRule(rule, selectorIndex, selectorListIndex++, currentCascadeLayerIdentifier, &mediaQueryCollector);
+}
+
+void RuleSetBuilder::registerLayers(const Vector<CascadeLayerName>& names)
+{
+ for (auto& name : names) {
+ pushCascadeLayer(name);
+ popCascadeLayer(name);
+ }
+}
+
+void RuleSetBuilder::pushCascadeLayer(const CascadeLayerName& name)
+{
+ if (mode != Mode::Normal)
+ return;
+
+ if (cascadeLayerIdentifierMap.isEmpty() && !ruleSet->m_cascadeLayers.isEmpty()) {
+ // For incremental build, reconstruct the name->identifier map.
+ RuleSet::CascadeLayerIdentifier identifier = 0;
+ for (auto& layer : ruleSet->m_cascadeLayers)
+ cascadeLayerIdentifierMap.add(layer.resolvedName, ++identifier);
+ }
+
+ auto nameResolvingAnonymous = [&] {
+ if (name.isEmpty()) {
+ // Make unique name for an anonymous layer.
+ unsigned long long random = randomNumber() * std::numeric_limits<unsigned long long>::max();
+ return CascadeLayerName { "anon_"_s + String::number(random) };
+ }
+ return name;
+ };
+
+ // For hierarchical names we register the containing layers individually first.
+ for (auto& nameSegment : nameResolvingAnonymous()) {
+ resolvedCascadeLayerName.append(nameSegment);
+ currentCascadeLayerIdentifier = cascadeLayerIdentifierMap.ensure(resolvedCascadeLayerName, [&] {
+ // Previously unseen layer.
+ ruleSet->m_cascadeLayers.append({ resolvedCascadeLayerName, currentCascadeLayerIdentifier });
+ return ruleSet->m_cascadeLayers.size();
+ }).iterator->value;
+ }
+}
+
+void RuleSetBuilder::popCascadeLayer(const CascadeLayerName& name)
+{
+ if (mode != Mode::Normal)
+ return;
+
+ for (auto size = name.isEmpty() ? 1 : name.size(); size--;) {
+ resolvedCascadeLayerName.removeLast();
+ currentCascadeLayerIdentifier = ruleSet->cascadeLayerForIdentifier(currentCascadeLayerIdentifier).parentIdentifier;
+ }
+}
+
+void RuleSetBuilder::updateCascadeLayerOrder()
+{
+ if (cascadeLayerIdentifierMap.isEmpty())
+ return;
+
+ auto compare = [&](auto a, auto b) {
+ while (a && b) {
+ // Identifiers are in parse order which almost corresponds to the layer priority order.
+ // The only exception is when a sublayer gets added to a layer after adding other non-sublayers.
+ // To resolve this we need look for a shared ancestor layer.
+ auto aParent = ruleSet->cascadeLayerForIdentifier(a).parentIdentifier;
+ auto bParent = ruleSet->cascadeLayerForIdentifier(b).parentIdentifier;
+ if (aParent == bParent || aParent == b || bParent == a)
+ break;
+ if (aParent > bParent)
+ a = aParent;
+ else
+ b = bParent;
+ }
+ return a < b;
+ };
+
+ Vector<RuleSet::CascadeLayerIdentifier> orderVector;
+ auto layerCount = ruleSet->m_cascadeLayers.size();
+ orderVector.reserveInitialCapacity(layerCount);
+ for (RuleSet::CascadeLayerIdentifier identifier = 1; identifier <= layerCount; ++identifier)
+ orderVector.uncheckedAppend(identifier);
+
+ std::sort(orderVector.begin(), orderVector.end(), compare);
+
+ for (unsigned i = 0; i < orderVector.size(); ++i)
+ ruleSet->cascadeLayerForIdentifier(orderVector[i]).order = i + 1;
+}
+
+void RuleSetBuilder::addMutatingRulesToResolver()
+{
+ if (!resolver)
+ return;
+
+ auto compareLayers = [&](const auto& a, const auto& b) {
+ auto aOrder = ruleSet->cascadeLayerOrderForIdentifier(a.layerIdentifier);
+ auto bOrder = ruleSet->cascadeLayerOrderForIdentifier(b.layerIdentifier);
+ return aOrder < bOrder;
+ };
+
+ // The order may change so we need to reprocess resolver mutating rules from earlier stylesheets.
+ auto rulesToAdd = std::exchange(ruleSet->m_resolverMutatingRulesInLayers, { });
+ rulesToAdd.appendVector(WTFMove(collectedResolverMutatingRules));
+
+ if (!cascadeLayerIdentifierMap.isEmpty())
+ std::stable_sort(rulesToAdd.begin(), rulesToAdd.end(), compareLayers);
+
+ for (auto& collectedRule : rulesToAdd) {
+ if (collectedRule.layerIdentifier)
+ ruleSet->m_resolverMutatingRulesInLayers.append(collectedRule);
+
+ auto& rule = collectedRule.rule;
+ if (is<StyleRuleFontFace>(rule)) {
+ resolver->document().fontSelector().addFontFaceRule(downcast<StyleRuleFontFace>(rule.get()), false);
+ resolver->invalidateMatchedDeclarationsCache();
+ continue;
+ }
+ if (is<StyleRuleFontPaletteValues>(rule)) {
+ resolver->document().fontSelector().addFontPaletteValuesRule(downcast<StyleRuleFontPaletteValues>(rule.get()));
+ resolver->invalidateMatchedDeclarationsCache();
+ continue;
+ }
+ if (is<StyleRuleKeyframes>(rule)) {
+ resolver->addKeyframeStyle(downcast<StyleRuleKeyframes>(rule.get()));
+ continue;
+ }
+ }
+}
+
+RuleSetMediaQueryCollector::~RuleSetMediaQueryCollector() = default;
+
+bool RuleSetMediaQueryCollector::pushAndEvaluate(const MediaQuerySet* set)
+{
+ if (!set)
+ return true;
+
+ // Only evaluate static expressions that require style rebuild.
+ MediaQueryDynamicResults dynamicResults;
+ auto mode = collectDynamic ? MediaQueryEvaluator::Mode::AlwaysMatchDynamic : MediaQueryEvaluator::Mode::Normal;
+
+ bool result = evaluator.evaluate(*set, &dynamicResults, mode);
+
+ if (!dynamicResults.viewport.isEmpty())
+ hasViewportDependentMediaQueries = true;
+
+ if (!dynamicResults.isEmpty())
+ dynamicContextStack.append({ *set });
+
+ return result;
+}
+
+void RuleSetMediaQueryCollector::pop(const MediaQuerySet* set)
+{
+ if (!set || dynamicContextStack.isEmpty() || set != &dynamicContextStack.last().set.get())
+ return;
+
+ if (!dynamicContextStack.last().affectedRulePositions.isEmpty() || !collectDynamic) {
+ RuleSet::DynamicMediaQueryRules rules;
+ for (auto& context : dynamicContextStack)
+ rules.mediaQuerySets.append(context.set.get());
+
+ if (collectDynamic) {
+ rules.affectedRulePositions.appendVector(dynamicContextStack.last().affectedRulePositions);
+ rules.ruleFeatures = WTFMove(dynamicContextStack.last().ruleFeatures);
+ rules.ruleFeatures.shrinkToFit();
+ } else
+ rules.requiresFullReset = true;
+
+ dynamicMediaQueryRules.append(WTFMove(rules));
+ }
+
+ dynamicContextStack.removeLast();
+}
+
+void RuleSetMediaQueryCollector::didMutateResolver()
+{
+ if (dynamicContextStack.isEmpty())
+ return;
+ didMutateResolverWithinDynamicMediaQuery = true;
+}
+
+void RuleSetMediaQueryCollector::addRuleIfNeeded(const RuleData& ruleData)
+{
+ if (dynamicContextStack.isEmpty())
+ return;
+
+ auto& context = dynamicContextStack.last();
+ context.affectedRulePositions.append(ruleData.position());
+ context.ruleFeatures.append({ ruleData });
+}
+
+}
+}
Added: trunk/Source/WebCore/style/RuleSetBuilder.h (0 => 283488)
--- trunk/Source/WebCore/style/RuleSetBuilder.h (rev 0)
+++ trunk/Source/WebCore/style/RuleSetBuilder.h 2021-10-04 06:37:45 UTC (rev 283488)
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 1999 Lars Knoll ([email protected])
+ * Copyright (C) 2003-2021 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 "RuleSet.h"
+
+namespace WebCore {
+namespace Style {
+
+struct RuleSetMediaQueryCollector {
+ ~RuleSetMediaQueryCollector();
+
+ const MediaQueryEvaluator& evaluator;
+ const bool collectDynamic { false };
+
+ struct DynamicContext {
+ Ref<const MediaQuerySet> set;
+ Vector<size_t> affectedRulePositions { };
+ RuleFeatureVector ruleFeatures { };
+ };
+ Vector<DynamicContext> dynamicContextStack { };
+
+ Vector<RuleSet::DynamicMediaQueryRules> dynamicMediaQueryRules { };
+ bool didMutateResolverWithinDynamicMediaQuery { false };
+ bool hasViewportDependentMediaQueries { false };
+
+ bool pushAndEvaluate(const MediaQuerySet*);
+ void pop(const MediaQuerySet*);
+ void didMutateResolver();
+ void addRuleIfNeeded(const RuleData&);
+};
+
+struct RuleSetBuilder {
+ enum class Mode { Normal, ResolverMutationScan };
+
+ Ref<RuleSet> ruleSet;
+ RuleSetMediaQueryCollector mediaQueryCollector;
+ Resolver* resolver { nullptr };
+ Mode mode { Mode::Normal };
+ CascadeLayerName resolvedCascadeLayerName { };
+ HashMap<CascadeLayerName, RuleSet::CascadeLayerIdentifier> cascadeLayerIdentifierMap { };
+ RuleSet::CascadeLayerIdentifier currentCascadeLayerIdentifier { 0 };
+ Vector<RuleSet::ResolverMutatingRule> collectedResolverMutatingRules { };
+
+ void addRulesFromSheet(const StyleSheetContents&);
+
+ ~RuleSetBuilder();
+
+private:
+ void addChildRules(const Vector<RefPtr<StyleRuleBase>>&);
+ void addStyleRule(const StyleRule&);
+
+ void registerLayers(const Vector<CascadeLayerName>&);
+ void pushCascadeLayer(const CascadeLayerName&);
+ void popCascadeLayer(const CascadeLayerName&);
+ void updateCascadeLayerOrder();
+ void addMutatingRulesToResolver();
+};
+
+}
+}