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