ServoStyleRuleMap.cpp (6366B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #include "mozilla/ServoStyleRuleMap.h" 8 9 #include "mozilla/IntegerRange.h" 10 #include "mozilla/ServoBindings.h" 11 #include "mozilla/ServoStyleSet.h" 12 #include "mozilla/StyleSheetInlines.h" 13 #include "mozilla/css/GroupRule.h" 14 #include "mozilla/dom/CSSImportRule.h" 15 #include "mozilla/dom/CSSNestedDeclarations.h" 16 #include "mozilla/dom/CSSPositionTryRule.h" 17 #include "mozilla/dom/CSSRuleBinding.h" 18 #include "mozilla/dom/CSSStyleRule.h" 19 #include "mozilla/dom/Document.h" 20 #include "mozilla/dom/Element.h" 21 #include "mozilla/dom/ShadowRoot.h" 22 23 using namespace mozilla::dom; 24 25 namespace mozilla { 26 27 void ServoStyleRuleMap::EnsureTable(ServoStyleSet& aStyleSet) { 28 if (!IsEmpty()) { 29 return; 30 } 31 aStyleSet.EnumerateStyleSheets( 32 [&](StyleSheet& aSheet) { FillTableFromStyleSheet(aSheet); }); 33 } 34 35 void ServoStyleRuleMap::EnsureTable(ShadowRoot& aShadowRoot) { 36 if (!IsEmpty()) { 37 return; 38 } 39 for (auto index : IntegerRange(aShadowRoot.SheetCount())) { 40 FillTableFromStyleSheet(*aShadowRoot.SheetAt(index)); 41 } 42 for (const auto& sheet : aShadowRoot.AdoptedStyleSheets()) { 43 FillTableFromStyleSheet(*sheet); 44 } 45 } 46 47 void ServoStyleRuleMap::SheetAdded(StyleSheet& aStyleSheet) { 48 if (!IsEmpty()) { 49 FillTableFromStyleSheet(aStyleSheet); 50 } 51 } 52 53 void ServoStyleRuleMap::SheetCloned(StyleSheet& aStyleSheet) { 54 // Invalidate all data inside. We could probably track down all the individual 55 // rules that changed etc, but it doesn't seem worth it. 56 // 57 // TODO: We can't do this until GetCssRulesInternal stops cloning. 58 // mTable.Clear(); 59 } 60 61 void ServoStyleRuleMap::SheetRemoved(StyleSheet& aStyleSheet) { 62 // Invalidate all data inside. This isn't strictly necessary since 63 // we should always get update from document before new queries come. 64 // But it is probably still safer if we try to avoid having invalid 65 // pointers inside. Also if the document keep adding and removing 66 // stylesheets, this would also prevent us from infinitely growing 67 // memory usage. 68 mTable.Clear(); 69 } 70 71 void ServoStyleRuleMap::RuleAdded(StyleSheet& aStyleSheet, 72 css::Rule& aStyleRule) { 73 if (!IsEmpty()) { 74 FillTableFromRule(aStyleRule); 75 } 76 } 77 78 void ServoStyleRuleMap::RuleRemoved(StyleSheet& aStyleSheet, 79 css::Rule& aStyleRule) { 80 if (IsEmpty()) { 81 return; 82 } 83 84 switch (aStyleRule.Type()) { 85 case StyleCssRuleType::Style: 86 case StyleCssRuleType::NestedDeclarations: 87 case StyleCssRuleType::Import: 88 case StyleCssRuleType::Media: 89 case StyleCssRuleType::Supports: 90 case StyleCssRuleType::LayerBlock: 91 case StyleCssRuleType::Container: 92 case StyleCssRuleType::Document: 93 case StyleCssRuleType::Scope: 94 case StyleCssRuleType::StartingStyle: 95 case StyleCssRuleType::PositionTry: { 96 // See the comment in SheetRemoved. 97 mTable.Clear(); 98 break; 99 } 100 case StyleCssRuleType::CustomMedia: 101 case StyleCssRuleType::LayerStatement: 102 case StyleCssRuleType::FontFace: 103 case StyleCssRuleType::Page: 104 case StyleCssRuleType::Property: 105 case StyleCssRuleType::Keyframes: 106 case StyleCssRuleType::Keyframe: 107 case StyleCssRuleType::Margin: 108 case StyleCssRuleType::Namespace: 109 case StyleCssRuleType::CounterStyle: 110 case StyleCssRuleType::FontFeatureValues: 111 case StyleCssRuleType::FontPaletteValues: 112 break; 113 } 114 } 115 116 size_t ServoStyleRuleMap::SizeOfIncludingThis( 117 MallocSizeOf aMallocSizeOf) const { 118 size_t n = aMallocSizeOf(this); 119 n += mTable.ShallowSizeOfExcludingThis(aMallocSizeOf); 120 return n; 121 } 122 123 void ServoStyleRuleMap::RuleDeclarationsChanged( 124 css::Rule& aRule, const StyleLockedDeclarationBlock* aOld, 125 const StyleLockedDeclarationBlock* aNew) { 126 MOZ_ASSERT(aOld); 127 MOZ_ASSERT(aNew); 128 if (IsEmpty()) { 129 return; 130 } 131 auto old = mTable.Extract(aOld); 132 MOZ_ASSERT(old.valueOr(nullptr) == &aRule, 133 "We were tracking the wrong rule?"); 134 mTable.InsertOrUpdate(aNew, &aRule); 135 } 136 137 void ServoStyleRuleMap::FillTableFromRule(css::Rule& aRule) { 138 switch (aRule.Type()) { 139 case StyleCssRuleType::NestedDeclarations: { 140 auto& rule = static_cast<CSSNestedDeclarations&>(aRule); 141 mTable.InsertOrUpdate(rule.RawStyle(), &rule); 142 break; 143 } 144 case StyleCssRuleType::PositionTry: { 145 auto& rule = static_cast<CSSPositionTryRule&>(aRule); 146 mTable.InsertOrUpdate(rule.RawStyle(), &rule); 147 break; 148 } 149 case StyleCssRuleType::Style: { 150 auto& rule = static_cast<CSSStyleRule&>(aRule); 151 mTable.InsertOrUpdate(rule.RawStyle(), &rule); 152 [[fallthrough]]; 153 } 154 case StyleCssRuleType::LayerBlock: 155 case StyleCssRuleType::Media: 156 case StyleCssRuleType::Supports: 157 case StyleCssRuleType::Container: 158 case StyleCssRuleType::Document: 159 case StyleCssRuleType::Scope: 160 case StyleCssRuleType::StartingStyle: { 161 auto& rule = static_cast<css::GroupRule&>(aRule); 162 FillTableFromRuleList(*rule.CssRules()); 163 break; 164 } 165 case StyleCssRuleType::Import: { 166 auto& rule = static_cast<CSSImportRule&>(aRule); 167 if (auto* sheet = rule.GetStyleSheet()) { 168 FillTableFromStyleSheet(*sheet); 169 } 170 break; 171 } 172 case StyleCssRuleType::CustomMedia: 173 case StyleCssRuleType::LayerStatement: 174 case StyleCssRuleType::FontFace: 175 case StyleCssRuleType::Page: 176 case StyleCssRuleType::Property: 177 case StyleCssRuleType::Keyframes: 178 case StyleCssRuleType::Keyframe: 179 case StyleCssRuleType::Margin: 180 case StyleCssRuleType::Namespace: 181 case StyleCssRuleType::CounterStyle: 182 case StyleCssRuleType::FontFeatureValues: 183 case StyleCssRuleType::FontPaletteValues: 184 break; 185 } 186 } 187 188 void ServoStyleRuleMap::FillTableFromRuleList(ServoCSSRuleList& aRuleList) { 189 for (uint32_t i : IntegerRange(aRuleList.Length())) { 190 FillTableFromRule(*aRuleList.GetRule(i)); 191 } 192 } 193 194 void ServoStyleRuleMap::FillTableFromStyleSheet(StyleSheet& aSheet) { 195 if (aSheet.IsComplete()) { 196 FillTableFromRuleList(*aSheet.GetCssRulesInternal()); 197 } 198 } 199 200 } // namespace mozilla