ServoElementSnapshot.h (4998B)
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 #ifndef mozilla_ServoElementSnapshot_h 8 #define mozilla_ServoElementSnapshot_h 9 10 #include "AttrArray.h" 11 #include "MainThreadUtils.h" 12 #include "mozilla/TypedEnumBits.h" 13 #include "mozilla/dom/BorrowedAttrInfo.h" 14 #include "mozilla/dom/RustTypes.h" 15 #include "nsAtom.h" 16 #include "nsAttrName.h" 17 #include "nsAttrValue.h" 18 #include "nsChangeHint.h" 19 #include "nsGkAtoms.h" 20 21 namespace mozilla { 22 namespace dom { 23 class Element; 24 } 25 26 /** 27 * A bitflags enum class used to determine what data does a ServoElementSnapshot 28 * contains. 29 */ 30 enum class ServoElementSnapshotFlags : uint8_t { 31 State = 1 << 0, 32 Attributes = 1 << 1, 33 Id = 1 << 2, 34 MaybeClass = 1 << 3, 35 OtherPseudoClassState = 1 << 4, 36 CustomState = 1 << 5, 37 }; 38 39 MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(ServoElementSnapshotFlags) 40 41 /** 42 * This class holds all non-tree-structural state of an element that might be 43 * used for selector matching eventually. 44 * 45 * This means the attributes, and the element state, such as :hover, :active, 46 * etc... 47 */ 48 class ServoElementSnapshot { 49 typedef dom::BorrowedAttrInfo BorrowedAttrInfo; 50 typedef dom::Element Element; 51 52 // TODO: Now that the element state shares a representation with rust we 53 // should be able to do better and not use the internal type. 54 typedef dom::ElementState::InternalType ServoStateType; 55 56 public: 57 typedef ServoElementSnapshotFlags Flags; 58 59 explicit ServoElementSnapshot(const Element&); 60 61 ~ServoElementSnapshot() { 62 MOZ_ASSERT(NS_IsMainThread()); 63 MOZ_COUNT_DTOR(ServoElementSnapshot); 64 } 65 66 bool HasAttrs() const { return HasAny(Flags::Attributes); } 67 68 bool HasState() const { return HasAny(Flags::State); } 69 70 bool HasOtherPseudoClassState() const { 71 return HasAny(Flags::OtherPseudoClassState); 72 } 73 74 /** 75 * Captures the given state (if not previously captured). 76 */ 77 void AddState(dom::ElementState aState) { 78 if (!HasAny(Flags::State)) { 79 mState = aState.GetInternalValue(); 80 mContains |= Flags::State; 81 } 82 } 83 84 /** 85 * Captures the given element attributes (if not previously captured). 86 * 87 * The attribute name and namespace are used to note which kind of attribute 88 * has changed. 89 */ 90 void AddAttrs(const Element&, int32_t aNameSpaceID, nsAtom* aAttribute); 91 92 /** 93 * Captures the given element custom states. 94 */ 95 void AddCustomStates(Element&); 96 97 /** 98 * Captures some other pseudo-class matching state not included in 99 * ElementState. 100 */ 101 void AddOtherPseudoClassState(const Element&); 102 103 /** 104 * Needed methods for attribute matching. 105 */ 106 BorrowedAttrInfo GetAttrInfoAt(uint32_t aIndex) const { 107 MOZ_ASSERT(HasAttrs()); 108 if (aIndex >= mAttrs.Length()) { 109 return BorrowedAttrInfo(nullptr, nullptr); 110 } 111 return BorrowedAttrInfo(&mAttrs[aIndex].mName, &mAttrs[aIndex].mValue); 112 } 113 114 const nsAttrValue* GetParsedAttr(nsAtom* aLocalName) const { 115 return GetParsedAttr(aLocalName, kNameSpaceID_None); 116 } 117 118 const nsAttrValue* GetParsedAttr(nsAtom* aLocalName, 119 int32_t aNamespaceID) const { 120 MOZ_ASSERT(HasAttrs()); 121 uint32_t i, len = mAttrs.Length(); 122 if (aNamespaceID == kNameSpaceID_None) { 123 // This should be the common case so lets make an optimized loop 124 for (i = 0; i < len; ++i) { 125 if (mAttrs[i].mName.Equals(aLocalName)) { 126 return &mAttrs[i].mValue; 127 } 128 } 129 130 return nullptr; 131 } 132 133 for (i = 0; i < len; ++i) { 134 if (mAttrs[i].mName.Equals(aLocalName, aNamespaceID)) { 135 return &mAttrs[i].mValue; 136 } 137 } 138 139 return nullptr; 140 } 141 142 bool IsInChromeDocument() const { return mIsInChromeDocument; } 143 bool SupportsLangAttr() const { return mSupportsLangAttr; } 144 145 bool HasAny(Flags aFlags) const { return bool(mContains & aFlags); } 146 147 bool IsTableBorderNonzero() const { 148 MOZ_ASSERT(HasOtherPseudoClassState()); 149 return mIsTableBorderNonzero; 150 } 151 152 bool IsSelectListBox() const { 153 MOZ_ASSERT(HasOtherPseudoClassState()); 154 return mIsSelectListBox; 155 } 156 157 private: 158 // TODO: Profile, a 1 or 2 element AutoTArray could be worth it, given we know 159 // we're dealing with attribute changes when we take snapshots of attributes, 160 // though it can be wasted space if we deal with a lot of state-only 161 // snapshots. 162 nsTArray<AttrArray::InternalAttr> mAttrs; 163 nsTArray<RefPtr<nsAtom>> mChangedAttrNames; 164 nsTArray<RefPtr<nsAtom>> mCustomStates; 165 nsAttrValue mClass; 166 ServoStateType mState; 167 Flags mContains; 168 bool mIsInChromeDocument : 1; 169 bool mSupportsLangAttr : 1; 170 bool mIsTableBorderNonzero : 1; 171 bool mIsSelectListBox : 1; 172 bool mClassAttributeChanged : 1; 173 bool mIdAttributeChanged : 1; 174 }; 175 176 } // namespace mozilla 177 178 #endif