1 | /* |
2 | * Copyright (C) 1999 Lars Knoll (knoll@kde.org) |
3 | * Copyright (C) 2003-2014 Apple Inc. All rights reserved. |
4 | * |
5 | * This library is free software; you can redistribute it and/or |
6 | * modify it under the terms of the GNU Library General Public |
7 | * License as published by the Free Software Foundation; either |
8 | * version 2 of the License, or (at your option) any later version. |
9 | * |
10 | * This library is distributed in the hope that it will be useful, |
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
13 | * Library General Public License for more details. |
14 | * |
15 | * You should have received a copy of the GNU Library General Public License |
16 | * along with this library; see the file COPYING.LIB. If not, write to |
17 | * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
18 | * Boston, MA 02110-1301, USA. |
19 | * |
20 | */ |
21 | |
22 | #pragma once |
23 | |
24 | #include "RuleFeature.h" |
25 | #include "SelectorCompiler.h" |
26 | #include "SelectorFilter.h" |
27 | #include "StyleRule.h" |
28 | #include <wtf/Forward.h> |
29 | #include <wtf/HashMap.h> |
30 | #include <wtf/text/AtomicString.h> |
31 | #include <wtf/text/AtomicStringHash.h> |
32 | |
33 | namespace WebCore { |
34 | |
35 | enum PropertyWhitelistType { |
36 | PropertyWhitelistNone = 0, |
37 | PropertyWhitelistMarker, |
38 | #if ENABLE(VIDEO_TRACK) |
39 | PropertyWhitelistCue |
40 | #endif |
41 | }; |
42 | |
43 | class CSSSelector; |
44 | class ContainerNode; |
45 | class MediaQueryEvaluator; |
46 | class Node; |
47 | class StyleResolver; |
48 | class StyleSheetContents; |
49 | |
50 | enum class MatchBasedOnRuleHash : unsigned { |
51 | None, |
52 | Universal, |
53 | ClassA, |
54 | ClassB, |
55 | ClassC |
56 | }; |
57 | |
58 | class RuleData { |
59 | public: |
60 | static const unsigned maximumSelectorComponentCount = 8192; |
61 | |
62 | RuleData(StyleRule*, unsigned selectorIndex, unsigned selectorListIndex, unsigned position); |
63 | |
64 | unsigned position() const { return m_position; } |
65 | StyleRule* rule() const { return m_rule.get(); } |
66 | const CSSSelector* selector() const { return m_rule->selectorList().selectorAt(m_selectorIndex); } |
67 | unsigned selectorIndex() const { return m_selectorIndex; } |
68 | unsigned selectorListIndex() const { return m_selectorListIndex; } |
69 | |
70 | bool canMatchPseudoElement() const { return m_canMatchPseudoElement; } |
71 | MatchBasedOnRuleHash matchBasedOnRuleHash() const { return static_cast<MatchBasedOnRuleHash>(m_matchBasedOnRuleHash); } |
72 | bool containsUncommonAttributeSelector() const { return m_containsUncommonAttributeSelector; } |
73 | unsigned linkMatchType() const { return m_linkMatchType; } |
74 | PropertyWhitelistType propertyWhitelistType() const { return static_cast<PropertyWhitelistType>(m_propertyWhitelistType); } |
75 | const SelectorFilter::Hashes& descendantSelectorIdentifierHashes() const { return m_descendantSelectorIdentifierHashes; } |
76 | |
77 | void disableSelectorFiltering() { m_descendantSelectorIdentifierHashes[0] = 0; } |
78 | |
79 | private: |
80 | RefPtr<StyleRule> m_rule; |
81 | unsigned m_selectorIndex : 16; |
82 | unsigned m_selectorListIndex : 16; |
83 | // This number was picked fairly arbitrarily. We can probably lower it if we need to. |
84 | // Some simple testing showed <100,000 RuleData's on large sites. |
85 | unsigned m_position : 18; |
86 | unsigned m_matchBasedOnRuleHash : 3; |
87 | unsigned m_canMatchPseudoElement : 1; |
88 | unsigned m_containsUncommonAttributeSelector : 1; |
89 | unsigned m_linkMatchType : 2; // SelectorChecker::LinkMatchMask |
90 | unsigned m_propertyWhitelistType : 2; |
91 | SelectorFilter::Hashes m_descendantSelectorIdentifierHashes; |
92 | }; |
93 | |
94 | struct SameSizeAsRuleData { |
95 | void* a; |
96 | unsigned b; |
97 | unsigned c; |
98 | unsigned d[4]; |
99 | }; |
100 | |
101 | COMPILE_ASSERT(sizeof(RuleData) == sizeof(SameSizeAsRuleData), RuleData_should_stay_small); |
102 | |
103 | class RuleSet { |
104 | WTF_MAKE_NONCOPYABLE(RuleSet); WTF_MAKE_FAST_ALLOCATED; |
105 | public: |
106 | struct RuleSetSelectorPair { |
107 | RuleSetSelectorPair(const CSSSelector* selector, std::unique_ptr<RuleSet> ruleSet) : selector(selector), ruleSet(WTFMove(ruleSet)) { } |
108 | RuleSetSelectorPair(const RuleSetSelectorPair& pair) : selector(pair.selector), ruleSet(const_cast<RuleSetSelectorPair*>(&pair)->ruleSet.release()) { } |
109 | |
110 | const CSSSelector* selector; |
111 | std::unique_ptr<RuleSet> ruleSet; |
112 | }; |
113 | |
114 | RuleSet(); |
115 | ~RuleSet(); |
116 | |
117 | typedef Vector<RuleData, 1> RuleDataVector; |
118 | typedef HashMap<AtomicString, std::unique_ptr<RuleDataVector>> AtomRuleMap; |
119 | |
120 | void addRulesFromSheet(StyleSheetContents&, const MediaQueryEvaluator&, StyleResolver* = 0); |
121 | |
122 | void addStyleRule(StyleRule*); |
123 | void addRule(StyleRule*, unsigned selectorIndex, unsigned selectorListIndex); |
124 | void (StyleRulePage*); |
125 | void addToRuleSet(const AtomicString& key, AtomRuleMap&, const RuleData&); |
126 | void shrinkToFit(); |
127 | void disableAutoShrinkToFit() { m_autoShrinkToFitEnabled = false; } |
128 | |
129 | const RuleFeatureSet& features() const { return m_features; } |
130 | |
131 | const RuleDataVector* idRules(const AtomicString& key) const { return m_idRules.get(key); } |
132 | const RuleDataVector* classRules(const AtomicString& key) const { return m_classRules.get(key); } |
133 | const RuleDataVector* tagRules(const AtomicString& key, bool isHTMLName) const; |
134 | const RuleDataVector* shadowPseudoElementRules(const AtomicString& key) const { return m_shadowPseudoElementRules.get(key); } |
135 | const RuleDataVector* linkPseudoClassRules() const { return &m_linkPseudoClassRules; } |
136 | #if ENABLE(VIDEO_TRACK) |
137 | const RuleDataVector* cuePseudoRules() const { return &m_cuePseudoRules; } |
138 | #endif |
139 | const RuleDataVector& hostPseudoClassRules() const { return m_hostPseudoClassRules; } |
140 | const RuleDataVector& slottedPseudoElementRules() const { return m_slottedPseudoElementRules; } |
141 | const RuleDataVector* focusPseudoClassRules() const { return &m_focusPseudoClassRules; } |
142 | const RuleDataVector* universalRules() const { return &m_universalRules; } |
143 | |
144 | const Vector<StyleRulePage*>& () const { return m_pageRules; } |
145 | |
146 | unsigned ruleCount() const { return m_ruleCount; } |
147 | |
148 | bool hasShadowPseudoElementRules() const; |
149 | bool hasHostPseudoClassRulesMatchingInShadowTree() const { return m_hasHostPseudoClassRulesMatchingInShadowTree; } |
150 | |
151 | private: |
152 | void addChildRules(const Vector<RefPtr<StyleRuleBase>>&, const MediaQueryEvaluator& medium, StyleResolver*, bool isInitiatingElementInUserAgentShadowTree); |
153 | |
154 | AtomRuleMap m_idRules; |
155 | AtomRuleMap m_classRules; |
156 | AtomRuleMap m_tagLocalNameRules; |
157 | AtomRuleMap m_tagLowercaseLocalNameRules; |
158 | AtomRuleMap m_shadowPseudoElementRules; |
159 | RuleDataVector m_linkPseudoClassRules; |
160 | #if ENABLE(VIDEO_TRACK) |
161 | RuleDataVector m_cuePseudoRules; |
162 | #endif |
163 | RuleDataVector m_hostPseudoClassRules; |
164 | RuleDataVector m_slottedPseudoElementRules; |
165 | RuleDataVector m_focusPseudoClassRules; |
166 | RuleDataVector m_universalRules; |
167 | Vector<StyleRulePage*> ; |
168 | unsigned m_ruleCount { 0 }; |
169 | bool m_hasHostPseudoClassRulesMatchingInShadowTree { false }; |
170 | bool m_autoShrinkToFitEnabled { true }; |
171 | RuleFeatureSet m_features; |
172 | }; |
173 | |
174 | inline const RuleSet::RuleDataVector* RuleSet::tagRules(const AtomicString& key, bool isHTMLName) const |
175 | { |
176 | const AtomRuleMap* tagRules; |
177 | if (isHTMLName) |
178 | tagRules = &m_tagLowercaseLocalNameRules; |
179 | else |
180 | tagRules = &m_tagLocalNameRules; |
181 | return tagRules->get(key); |
182 | } |
183 | |
184 | } // namespace WebCore |
185 | |
186 | namespace WTF { |
187 | |
188 | // RuleData is simple enough that initializing to 0 and moving with memcpy will totally work. |
189 | template<> struct VectorTraits<WebCore::RuleData> : SimpleClassVectorTraits { }; |
190 | |
191 | } // namespace WTF |
192 | |