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/css/GroupRule.h" 10 #include "mozilla/dom/CSSImportRule.h" 11 #include "mozilla/dom/CSSRuleBinding.h" 12 #include "mozilla/dom/CSSStyleRule.h" 13 #include "mozilla/dom/Document.h" 14 #include "mozilla/dom/Element.h" 15 #include "mozilla/dom/ShadowRoot.h" 16 #include "mozilla/IntegerRange.h" 17 #include "mozilla/ServoStyleSet.h" 18 #include "mozilla/StyleSheetInlines.h" 19 #include "nsStyleSheetService.h" 20 21 using namespace mozilla::dom; 22 23 namespace mozilla { 24 EnsureTable(ServoStyleSet & aStyleSet)25void ServoStyleRuleMap::EnsureTable(ServoStyleSet& aStyleSet) { 26 if (!IsEmpty()) { 27 return; 28 } 29 aStyleSet.EnumerateStyleSheets( 30 [&](StyleSheet& aSheet) { FillTableFromStyleSheet(aSheet); }); 31 } 32 EnsureTable(ShadowRoot & aShadowRoot)33void ServoStyleRuleMap::EnsureTable(ShadowRoot& aShadowRoot) { 34 if (!IsEmpty()) { 35 return; 36 } 37 for (auto index : IntegerRange(aShadowRoot.SheetCount())) { 38 FillTableFromStyleSheet(*aShadowRoot.SheetAt(index)); 39 } 40 } 41 SheetAdded(StyleSheet & aStyleSheet)42void ServoStyleRuleMap::SheetAdded(StyleSheet& aStyleSheet) { 43 if (!IsEmpty()) { 44 FillTableFromStyleSheet(aStyleSheet); 45 } 46 } 47 SheetRemoved(StyleSheet & aStyleSheet)48void ServoStyleRuleMap::SheetRemoved(StyleSheet& aStyleSheet) { 49 // Invalidate all data inside. This isn't strictly necessary since 50 // we should always get update from document before new queries come. 51 // But it is probably still safer if we try to avoid having invalid 52 // pointers inside. Also if the document keep adding and removing 53 // stylesheets, this would also prevent us from infinitely growing 54 // memory usage. 55 mTable.Clear(); 56 } 57 RuleAdded(StyleSheet & aStyleSheet,css::Rule & aStyleRule)58void ServoStyleRuleMap::RuleAdded(StyleSheet& aStyleSheet, 59 css::Rule& aStyleRule) { 60 if (!IsEmpty()) { 61 FillTableFromRule(aStyleRule); 62 } 63 } 64 RuleRemoved(StyleSheet & aStyleSheet,css::Rule & aStyleRule)65void ServoStyleRuleMap::RuleRemoved(StyleSheet& aStyleSheet, 66 css::Rule& aStyleRule) { 67 if (IsEmpty()) { 68 return; 69 } 70 71 switch (aStyleRule.Type()) { 72 case CSSRule_Binding::STYLE_RULE: { 73 auto& rule = static_cast<CSSStyleRule&>(aStyleRule); 74 mTable.Remove(rule.Raw()); 75 break; 76 } 77 case CSSRule_Binding::IMPORT_RULE: 78 case CSSRule_Binding::MEDIA_RULE: 79 case CSSRule_Binding::SUPPORTS_RULE: 80 case CSSRule_Binding::DOCUMENT_RULE: { 81 // See the comment in StyleSheetRemoved. 82 mTable.Clear(); 83 break; 84 } 85 case CSSRule_Binding::FONT_FACE_RULE: 86 case CSSRule_Binding::PAGE_RULE: 87 case CSSRule_Binding::KEYFRAMES_RULE: 88 case CSSRule_Binding::KEYFRAME_RULE: 89 case CSSRule_Binding::NAMESPACE_RULE: 90 case CSSRule_Binding::COUNTER_STYLE_RULE: 91 case CSSRule_Binding::FONT_FEATURE_VALUES_RULE: 92 break; 93 default: 94 MOZ_ASSERT_UNREACHABLE("Unhandled rule"); 95 } 96 } 97 SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const98size_t ServoStyleRuleMap::SizeOfIncludingThis( 99 MallocSizeOf aMallocSizeOf) const { 100 size_t n = aMallocSizeOf(this); 101 n += mTable.ShallowSizeOfExcludingThis(aMallocSizeOf); 102 return n; 103 } 104 FillTableFromRule(css::Rule & aRule)105void ServoStyleRuleMap::FillTableFromRule(css::Rule& aRule) { 106 switch (aRule.Type()) { 107 case CSSRule_Binding::STYLE_RULE: { 108 auto& rule = static_cast<CSSStyleRule&>(aRule); 109 mTable.InsertOrUpdate(rule.Raw(), &rule); 110 break; 111 } 112 case CSSRule_Binding::MEDIA_RULE: 113 case CSSRule_Binding::SUPPORTS_RULE: 114 case CSSRule_Binding::DOCUMENT_RULE: { 115 auto& rule = static_cast<css::GroupRule&>(aRule); 116 auto ruleList = static_cast<ServoCSSRuleList*>(rule.CssRules()); 117 FillTableFromRuleList(*ruleList); 118 break; 119 } 120 case CSSRule_Binding::IMPORT_RULE: { 121 auto& rule = static_cast<CSSImportRule&>(aRule); 122 MOZ_ASSERT(aRule.GetStyleSheet()); 123 FillTableFromStyleSheet(*rule.GetStyleSheet()); 124 break; 125 } 126 } 127 } 128 FillTableFromRuleList(ServoCSSRuleList & aRuleList)129void ServoStyleRuleMap::FillTableFromRuleList(ServoCSSRuleList& aRuleList) { 130 for (uint32_t i : IntegerRange(aRuleList.Length())) { 131 FillTableFromRule(*aRuleList.GetRule(i)); 132 } 133 } 134 FillTableFromStyleSheet(StyleSheet & aSheet)135void ServoStyleRuleMap::FillTableFromStyleSheet(StyleSheet& aSheet) { 136 if (aSheet.IsComplete()) { 137 FillTableFromRuleList(*aSheet.GetCssRulesInternal()); 138 } 139 } 140 141 } // namespace mozilla 142