~mmach/netext73/webkit2gtk

« back to all changes in this revision

Viewing changes to Source/WebCore/style/StyleScopeRuleSets.cpp

  • Committer: mmach
  • Date: 2023-06-16 17:21:37 UTC
  • Revision ID: netbit73@gmail.com-20230616172137-2rqx6yr96ga9g3kp
1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
 
3
 *           (C) 2004-2005 Allan Sandfeld Jensen (kde@carewolf.com)
 
4
 * Copyright (C) 2006, 2007 Nicholas Shanks (webkit@nickshanks.com)
 
5
 * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Apple Inc. All rights reserved.
 
6
 * Copyright (C) 2007 Alexey Proskuryakov <ap@webkit.org>
 
7
 * Copyright (C) 2007, 2008 Eric Seidel <eric@webkit.org>
 
8
 * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
 
9
 * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
 
10
 * Copyright (C) Research In Motion Limited 2011. All rights reserved.
 
11
 * Copyright (C) 2013 Google Inc. All rights reserved.
 
12
 *
 
13
 * This library is free software; you can redistribute it and/or
 
14
 * modify it under the terms of the GNU Library General Public
 
15
 * License as published by the Free Software Foundation; either
 
16
 * version 2 of the License, or (at your option) any later version.
 
17
 *
 
18
 * This library is distributed in the hope that it will be useful,
 
19
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
20
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
21
 * Library General Public License for more details.
 
22
 *
 
23
 * You should have received a copy of the GNU Library General Public License
 
24
 * along with this library; see the file COPYING.LIB.  If not, write to
 
25
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 
26
 * Boston, MA 02110-1301, USA.
 
27
 */
 
28
 
 
29
#include "config.h"
 
30
#include "StyleScopeRuleSets.h"
 
31
 
 
32
#include "CSSStyleSheet.h"
 
33
#include "ExtensionStyleSheets.h"
 
34
#include "MediaQueryEvaluator.h"
 
35
#include "StyleResolver.h"
 
36
#include "StyleSheetContents.h"
 
37
 
 
38
namespace WebCore {
 
39
namespace Style {
 
40
 
 
41
ScopeRuleSets::ScopeRuleSets(Resolver& styleResolver)
 
42
    : m_styleResolver(styleResolver)
 
43
{
 
44
    m_authorStyle = RuleSet::create();
 
45
    m_authorStyle->disableAutoShrinkToFit();
 
46
}
 
47
 
 
48
ScopeRuleSets::~ScopeRuleSets()
 
49
{
 
50
    RELEASE_ASSERT(!m_isInvalidatingStyleWithRuleSets);
 
51
}
 
52
 
 
53
RuleSet* ScopeRuleSets::userAgentMediaQueryStyle() const
 
54
{
 
55
    updateUserAgentMediaQueryStyleIfNeeded();
 
56
    return m_userAgentMediaQueryStyle.get();
 
57
}
 
58
 
 
59
void ScopeRuleSets::updateUserAgentMediaQueryStyleIfNeeded() const
 
60
{
 
61
    if (!UserAgentStyle::mediaQueryStyleSheet)
 
62
        return;
 
63
 
 
64
    auto ruleCount = UserAgentStyle::mediaQueryStyleSheet->ruleCount();
 
65
    if (m_userAgentMediaQueryStyle && ruleCount == m_userAgentMediaQueryRuleCountOnUpdate)
 
66
        return;
 
67
    m_userAgentMediaQueryRuleCountOnUpdate = ruleCount;
 
68
 
 
69
    // Media queries on user agent sheet need to evaluated in document context. They behave like author sheets in this respect.
 
70
    auto& mediaQueryEvaluator = m_styleResolver.mediaQueryEvaluator();
 
71
    m_userAgentMediaQueryStyle = RuleSet::create();
 
72
    
 
73
    m_userAgentMediaQueryStyle->addRulesFromSheet(*UserAgentStyle::mediaQueryStyleSheet, nullptr, mediaQueryEvaluator, m_styleResolver);
 
74
}
 
75
 
 
76
RuleSet* ScopeRuleSets::userStyle() const
 
77
{
 
78
    if (m_usesSharedUserStyle)
 
79
        return m_styleResolver.document().styleScope().resolver().ruleSets().userStyle();
 
80
    return m_userStyle.get();
 
81
}
 
82
 
 
83
void ScopeRuleSets::initializeUserStyle()
 
84
{
 
85
    auto& extensionStyleSheets = m_styleResolver.document().extensionStyleSheets();
 
86
    auto& mediaQueryEvaluator = m_styleResolver.mediaQueryEvaluator();
 
87
    auto tempUserStyle = RuleSet::create();
 
88
    if (CSSStyleSheet* pageUserSheet = extensionStyleSheets.pageUserSheet())
 
89
        tempUserStyle->addRulesFromSheet(pageUserSheet->contents(), nullptr, mediaQueryEvaluator, m_styleResolver);
 
90
    collectRulesFromUserStyleSheets(extensionStyleSheets.injectedUserStyleSheets(), tempUserStyle.get(), mediaQueryEvaluator);
 
91
    collectRulesFromUserStyleSheets(extensionStyleSheets.documentUserStyleSheets(), tempUserStyle.get(), mediaQueryEvaluator);
 
92
    if (tempUserStyle->ruleCount() > 0 || tempUserStyle->pageRules().size() > 0)
 
93
        m_userStyle = WTFMove(tempUserStyle);
 
94
}
 
95
 
 
96
void ScopeRuleSets::collectRulesFromUserStyleSheets(const Vector<RefPtr<CSSStyleSheet>>& userSheets, RuleSet& userStyle, const MediaQueryEvaluator& medium)
 
97
{
 
98
    for (unsigned i = 0; i < userSheets.size(); ++i) {
 
99
        ASSERT(userSheets[i]->contents().isUserStyleSheet());
 
100
        userStyle.addRulesFromSheet(userSheets[i]->contents(), nullptr, medium, m_styleResolver);
 
101
    }
 
102
}
 
103
 
 
104
static RefPtr<RuleSet> makeRuleSet(const Vector<RuleFeature>& rules)
 
105
{
 
106
    size_t size = rules.size();
 
107
    if (!size)
 
108
        return nullptr;
 
109
    auto ruleSet = RuleSet::create();
 
110
    for (size_t i = 0; i < size; ++i)
 
111
        ruleSet->addRule(*rules[i].styleRule, rules[i].selectorIndex, rules[i].selectorListIndex);
 
112
    ruleSet->shrinkToFit();
 
113
    return ruleSet;
 
114
}
 
115
 
 
116
void ScopeRuleSets::resetAuthorStyle()
 
117
{
 
118
    m_isAuthorStyleDefined = true;
 
119
    m_authorStyle = RuleSet::create();
 
120
    m_authorStyle->disableAutoShrinkToFit();
 
121
}
 
122
 
 
123
void ScopeRuleSets::resetUserAgentMediaQueryStyle()
 
124
{
 
125
    m_userAgentMediaQueryStyle = nullptr;
 
126
}
 
127
 
 
128
bool ScopeRuleSets::hasViewportDependentMediaQueries() const
 
129
{
 
130
    if (m_authorStyle->hasViewportDependentMediaQueries())
 
131
        return true;
 
132
    if (m_userStyle && m_userStyle->hasViewportDependentMediaQueries())
 
133
        return true;
 
134
    if (m_userAgentMediaQueryStyle && m_userAgentMediaQueryStyle->hasViewportDependentMediaQueries())
 
135
        return true;
 
136
 
 
137
    return false;
 
138
}
 
139
 
 
140
Optional<DynamicMediaQueryEvaluationChanges> ScopeRuleSets::evaluteDynamicMediaQueryRules(const MediaQueryEvaluator& evaluator)
 
141
{
 
142
    Optional<DynamicMediaQueryEvaluationChanges> evaluationChanges;
 
143
 
 
144
    auto evaluate = [&](auto* ruleSet) {
 
145
        if (!ruleSet)
 
146
            return;
 
147
        if (auto changes = ruleSet->evaluteDynamicMediaQueryRules(evaluator)) {
 
148
            if (evaluationChanges)
 
149
                evaluationChanges->append(WTFMove(*changes));
 
150
            else
 
151
                evaluationChanges = changes;
 
152
        }
 
153
    };
 
154
 
 
155
    evaluate(&authorStyle());
 
156
    evaluate(userStyle());
 
157
    evaluate(userAgentMediaQueryStyle());
 
158
 
 
159
    return evaluationChanges;
 
160
}
 
161
 
 
162
void ScopeRuleSets::appendAuthorStyleSheets(const Vector<RefPtr<CSSStyleSheet>>& styleSheets, MediaQueryEvaluator* medium, InspectorCSSOMWrappers& inspectorCSSOMWrappers)
 
163
{
 
164
    for (auto& cssSheet : styleSheets) {
 
165
        ASSERT(!cssSheet->disabled());
 
166
        m_authorStyle->addRulesFromSheet(cssSheet->contents(), cssSheet->mediaQueries(), *medium, m_styleResolver);
 
167
        inspectorCSSOMWrappers.collectFromStyleSheetIfNeeded(cssSheet.get());
 
168
    }
 
169
 
 
170
    m_authorStyle->shrinkToFit();
 
171
    collectFeatures();
 
172
}
 
173
 
 
174
void ScopeRuleSets::collectFeatures() const
 
175
{
 
176
    RELEASE_ASSERT(!m_isInvalidatingStyleWithRuleSets);
 
177
 
 
178
    m_features.clear();
 
179
    // Collect all ids and rules using sibling selectors (:first-child and similar)
 
180
    // in the current set of stylesheets. Style sharing code uses this information to reject
 
181
    // sharing candidates.
 
182
    if (UserAgentStyle::defaultStyle)
 
183
        m_features.add(UserAgentStyle::defaultStyle->features());
 
184
    m_defaultStyleVersionOnFeatureCollection = UserAgentStyle::defaultStyleVersion;
 
185
 
 
186
    if (auto* userAgentMediaQueryStyle = this->userAgentMediaQueryStyle())
 
187
        m_features.add(userAgentMediaQueryStyle->features());
 
188
 
 
189
    if (m_authorStyle)
 
190
        m_features.add(m_authorStyle->features());
 
191
    if (auto* userStyle = this->userStyle())
 
192
        m_features.add(userStyle->features());
 
193
 
 
194
    m_siblingRuleSet = makeRuleSet(m_features.siblingRules);
 
195
    m_uncommonAttributeRuleSet = makeRuleSet(m_features.uncommonAttributeRules);
 
196
 
 
197
    m_classInvalidationRuleSets.clear();
 
198
    m_attributeInvalidationRuleSets.clear();
 
199
    m_cachedHasComplexSelectorsForStyleAttribute = WTF::nullopt;
 
200
 
 
201
    m_features.shrinkToFit();
 
202
}
 
203
 
 
204
template<typename RuleFeatureType>
 
205
static Vector<InvalidationRuleSet>* ensureInvalidationRuleSets(const AtomString& key, HashMap<AtomString, std::unique_ptr<Vector<InvalidationRuleSet>>>& ruleSetMap, const HashMap<AtomString, std::unique_ptr<Vector<RuleFeatureType>>>& ruleFeatures)
 
206
{
 
207
    return ruleSetMap.ensure(key, [&] () -> std::unique_ptr<Vector<InvalidationRuleSet>> {
 
208
        auto* features = ruleFeatures.get(key);
 
209
        if (!features)
 
210
            return nullptr;
 
211
 
 
212
        std::array<RefPtr<RuleSet>, matchElementCount> matchElementArray;
 
213
        std::array<Vector<const CSSSelector*>, matchElementCount> invalidationSelectorArray;
 
214
        for (auto& feature : *features) {
 
215
            auto arrayIndex = static_cast<unsigned>(*feature.matchElement);
 
216
            auto& ruleSet = matchElementArray[arrayIndex];
 
217
            if (!ruleSet)
 
218
                ruleSet = RuleSet::create();
 
219
            ruleSet->addRule(*feature.styleRule, feature.selectorIndex, feature.selectorListIndex);
 
220
            if constexpr (std::is_same<RuleFeatureType, RuleFeatureWithInvalidationSelector>::value) {
 
221
                if (feature.invalidationSelector)
 
222
                    invalidationSelectorArray[arrayIndex].append(feature.invalidationSelector);
 
223
            }
 
224
        }
 
225
        auto invalidationRuleSets = makeUnique<Vector<InvalidationRuleSet>>();
 
226
        for (unsigned i = 0; i < matchElementArray.size(); ++i) {
 
227
            if (matchElementArray[i])
 
228
                invalidationRuleSets->append({ static_cast<MatchElement>(i), *matchElementArray[i], WTFMove(invalidationSelectorArray[i]) });
 
229
        }
 
230
        return invalidationRuleSets;
 
231
    }).iterator->value.get();
 
232
}
 
233
 
 
234
const Vector<InvalidationRuleSet>* ScopeRuleSets::classInvalidationRuleSets(const AtomString& className) const
 
235
{
 
236
    return ensureInvalidationRuleSets(className, m_classInvalidationRuleSets, m_features.classRules);
 
237
}
 
238
 
 
239
const Vector<InvalidationRuleSet>* ScopeRuleSets::attributeInvalidationRuleSets(const AtomString& attributeName) const
 
240
{
 
241
    return ensureInvalidationRuleSets(attributeName, m_attributeInvalidationRuleSets, m_features.attributeRules);
 
242
}
 
243
 
 
244
bool ScopeRuleSets::hasComplexSelectorsForStyleAttribute() const
 
245
{
 
246
    auto compute = [&] {
 
247
        auto* ruleSets = attributeInvalidationRuleSets(HTMLNames::styleAttr->localName());
 
248
        if (!ruleSets)
 
249
            return false;
 
250
        for (auto& ruleSet : *ruleSets) {
 
251
            if (ruleSet.matchElement != MatchElement::Subject)
 
252
                return true;
 
253
        }
 
254
        return false;
 
255
    };
 
256
 
 
257
    if (!m_cachedHasComplexSelectorsForStyleAttribute)
 
258
        m_cachedHasComplexSelectorsForStyleAttribute = compute();
 
259
 
 
260
    return *m_cachedHasComplexSelectorsForStyleAttribute;
 
261
}
 
262
 
 
263
} // namespace Style
 
264
} // namespace WebCore