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