Bug 1750871 - run mochitest-remote on fission everywhere. r=releng-reviewers,aki
[gecko.git] / dom / base / ShadowRoot.h
blob1fe0576c96a0aef4428e296e047fc620c49d0049
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/. */
7 #ifndef mozilla_dom_shadowroot_h__
8 #define mozilla_dom_shadowroot_h__
10 #include "mozilla/DOMEventTargetHelper.h"
11 #include "mozilla/dom/DocumentBinding.h"
12 #include "mozilla/dom/DocumentFragment.h"
13 #include "mozilla/dom/DocumentOrShadowRoot.h"
14 #include "mozilla/dom/NameSpaceConstants.h"
15 #include "mozilla/dom/ShadowRootBinding.h"
16 #include "mozilla/ServoBindings.h"
17 #include "nsCOMPtr.h"
18 #include "nsCycleCollectionParticipant.h"
19 #include "nsIRadioGroupContainer.h"
20 #include "nsStubMutationObserver.h"
21 #include "nsTHashtable.h"
23 class nsAtom;
24 class nsIContent;
25 class nsXBLPrototypeBinding;
27 namespace mozilla {
29 class EventChainPreVisitor;
30 class ServoStyleRuleMap;
32 enum class StyleRuleChangeKind : uint32_t;
34 namespace css {
35 class Rule;
38 namespace dom {
40 class CSSImportRule;
41 class Element;
42 class HTMLInputElement;
44 class ShadowRoot final : public DocumentFragment,
45 public DocumentOrShadowRoot,
46 public nsIRadioGroupContainer {
47 friend class DocumentOrShadowRoot;
49 public:
50 NS_IMPL_FROMNODE_HELPER(ShadowRoot, IsShadowRoot());
52 NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(ShadowRoot, DocumentFragment)
53 NS_DECL_ISUPPORTS_INHERITED
55 ShadowRoot(Element* aElement, ShadowRootMode aMode,
56 Element::DelegatesFocus aDelegatesFocus,
57 SlotAssignmentMode aSlotAssignment,
58 already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo);
60 void AddSizeOfExcludingThis(nsWindowSizes&, size_t* aNodeSize) const final;
62 // Try to reassign an element or text to a slot.
63 void MaybeReassignContent(nsIContent& aElementOrText);
64 // Called when an element is inserted as a direct child of our host. Tries to
65 // slot the child in one of our slots.
66 void MaybeSlotHostChild(nsIContent&);
67 // Called when a direct child of our host is removed. Tries to un-slot the
68 // child from the currently-assigned slot, if any.
69 void MaybeUnslotHostChild(nsIContent&);
71 // Find the first focusable element in this tree.
72 Element* GetFirstFocusable(bool aWithMouse) const;
74 // Shadow DOM v1
75 Element* Host() const {
76 MOZ_ASSERT(GetHost(),
77 "ShadowRoot always has a host, how did we create "
78 "this ShadowRoot?");
79 return GetHost();
82 ShadowRootMode Mode() const { return mMode; }
83 bool DelegatesFocus() const {
84 return mDelegatesFocus == Element::DelegatesFocus::Yes;
86 SlotAssignmentMode SlotAssignment() const { return mSlotAssignment; }
87 bool IsClosed() const { return mMode == ShadowRootMode::Closed; }
89 void RemoveSheetFromStyles(StyleSheet&);
90 void RuleAdded(StyleSheet&, css::Rule&);
91 void RuleRemoved(StyleSheet&, css::Rule&);
92 void RuleChanged(StyleSheet&, css::Rule*, StyleRuleChangeKind);
93 void ImportRuleLoaded(CSSImportRule&, StyleSheet&);
94 void SheetCloned(StyleSheet&);
95 void StyleSheetApplicableStateChanged(StyleSheet&);
97 /**
98 * Clones internal state, for example stylesheets, of aOther to 'this'.
100 void CloneInternalDataFrom(ShadowRoot* aOther);
101 void InsertSheetAt(size_t aIndex, StyleSheet&);
103 // Calls UnbindFromTree for each of our kids, and also flags us as no longer
104 // being connected.
105 void Unbind();
107 // Only intended for UA widgets / special shadow roots, or for handling
108 // failure cases when adopting (see BlastSubtreeToPieces).
110 // Forgets our shadow host and unbinds all our kids.
111 void Unattach();
113 // Calls BindToTree on each of our kids, and also maybe flags us as being
114 // connected.
115 nsresult Bind();
118 * Explicitly invalidates the style and layout of the flattened-tree subtree
119 * rooted at the element.
121 * You need to use this whenever the flat tree is going to be shuffled in a
122 * way that layout doesn't understand via the usual ContentInserted /
123 * ContentAppended / ContentRemoved notifications. For example, if removing an
124 * element will cause a change in the flat tree such that other element will
125 * start showing up (like fallback content), this method needs to be called on
126 * an ancestor of that element.
128 * It is important that this runs _before_ actually shuffling the flat tree
129 * around, so that layout knows the actual tree that it needs to invalidate.
131 void InvalidateStyleAndLayoutOnSubtree(Element*);
133 private:
134 void InsertSheetIntoAuthorData(size_t aIndex, StyleSheet&,
135 const nsTArray<RefPtr<StyleSheet>>&);
137 void AppendStyleSheet(StyleSheet& aSheet) {
138 InsertSheetAt(SheetCount(), aSheet);
142 * Represents the insertion point in a slot for a given node.
144 struct SlotInsertionPoint {
145 HTMLSlotElement* mSlot = nullptr;
146 Maybe<uint32_t> mIndex;
148 SlotInsertionPoint() = default;
149 SlotInsertionPoint(HTMLSlotElement* aSlot, const Maybe<uint32_t>& aIndex)
150 : mSlot(aSlot), mIndex(aIndex) {}
154 * Return the assignment corresponding to the content node at this particular
155 * point in time.
157 * It's the caller's responsibility to actually call InsertAssignedNode /
158 * AppendAssignedNode in the slot as needed.
160 SlotInsertionPoint SlotInsertionPointFor(nsIContent&);
162 public:
163 void AddSlot(HTMLSlotElement* aSlot);
164 void RemoveSlot(HTMLSlotElement* aSlot);
165 bool HasSlots() const { return !mSlotMap.IsEmpty(); };
166 HTMLSlotElement* GetDefaultSlot() const {
167 SlotArray* list = mSlotMap.Get(u""_ns);
168 return list ? (*list)->ElementAt(0) : nullptr;
171 void PartAdded(const Element&);
172 void PartRemoved(const Element&);
174 IMPL_EVENT_HANDLER(slotchange);
176 const nsTArray<const Element*>& Parts() const { return mParts; }
178 const RawServoAuthorStyles* GetServoStyles() const {
179 return mServoStyles.get();
182 RawServoAuthorStyles* GetServoStyles() { return mServoStyles.get(); }
184 mozilla::ServoStyleRuleMap& ServoStyleRuleMap();
186 JSObject* WrapNode(JSContext*, JS::Handle<JSObject*> aGivenProto) final;
188 void NodeInfoChanged(Document* aOldDoc) override {
189 DocumentFragment::NodeInfoChanged(aOldDoc);
190 ClearAdoptedStyleSheets();
193 void AddToIdTable(Element* aElement, nsAtom* aId);
194 void RemoveFromIdTable(Element* aElement, nsAtom* aId);
196 // WebIDL methods.
197 using mozilla::dom::DocumentOrShadowRoot::GetElementById;
199 Element* GetActiveElement();
202 * These methods allow UA Widget to insert DOM elements into the Shadow ROM
203 * without putting their DOM reflectors to content scope first.
204 * The inserted DOM will have their reflectors in the UA Widget scope.
206 nsINode* ImportNodeAndAppendChildAt(nsINode& aParentNode, nsINode& aNode,
207 bool aDeep, mozilla::ErrorResult& rv);
209 nsINode* CreateElementAndAppendChildAt(nsINode& aParentNode,
210 const nsAString& aTagName,
211 mozilla::ErrorResult& rv);
213 bool IsUAWidget() const { return mIsUAWidget; }
215 void SetIsUAWidget() {
216 MOZ_ASSERT(!HasChildren());
217 SetFlags(NODE_HAS_BEEN_IN_UA_WIDGET);
218 mIsUAWidget = true;
221 bool IsAvailableToElementInternals() const {
222 return mIsAvailableToElementInternals;
225 void SetAvailableToElementInternals() {
226 mIsAvailableToElementInternals = true;
229 void GetEventTargetParent(EventChainPreVisitor& aVisitor) override;
231 // nsIRadioGroupContainer
232 NS_IMETHOD WalkRadioGroup(const nsAString& aName,
233 nsIRadioVisitor* aVisitor) override {
234 return DocumentOrShadowRoot::WalkRadioGroup(aName, aVisitor);
236 virtual void SetCurrentRadioButton(const nsAString& aName,
237 HTMLInputElement* aRadio) override {
238 DocumentOrShadowRoot::SetCurrentRadioButton(aName, aRadio);
240 virtual HTMLInputElement* GetCurrentRadioButton(
241 const nsAString& aName) override {
242 return DocumentOrShadowRoot::GetCurrentRadioButton(aName);
244 NS_IMETHOD
245 GetNextRadioButton(const nsAString& aName, const bool aPrevious,
246 HTMLInputElement* aFocusedRadio,
247 HTMLInputElement** aRadioOut) override {
248 return DocumentOrShadowRoot::GetNextRadioButton(aName, aPrevious,
249 aFocusedRadio, aRadioOut);
251 virtual void AddToRadioGroup(const nsAString& aName,
252 HTMLInputElement* aRadio) override {
253 DocumentOrShadowRoot::AddToRadioGroup(aName, aRadio);
255 virtual void RemoveFromRadioGroup(const nsAString& aName,
256 HTMLInputElement* aRadio) override {
257 DocumentOrShadowRoot::RemoveFromRadioGroup(aName, aRadio);
259 virtual uint32_t GetRequiredRadioCount(
260 const nsAString& aName) const override {
261 return DocumentOrShadowRoot::GetRequiredRadioCount(aName);
263 virtual void RadioRequiredWillChange(const nsAString& aName,
264 bool aRequiredAdded) override {
265 DocumentOrShadowRoot::RadioRequiredWillChange(aName, aRequiredAdded);
267 virtual bool GetValueMissingState(const nsAString& aName) const override {
268 return DocumentOrShadowRoot::GetValueMissingState(aName);
270 virtual void SetValueMissingState(const nsAString& aName,
271 bool aValue) override {
272 return DocumentOrShadowRoot::SetValueMissingState(aName, aValue);
275 protected:
276 // FIXME(emilio): This will need to become more fine-grained.
277 void ApplicableRulesChanged();
279 virtual ~ShadowRoot();
281 const ShadowRootMode mMode;
283 Element::DelegatesFocus mDelegatesFocus;
285 const SlotAssignmentMode mSlotAssignment;
287 // The computed data from the style sheets.
288 UniquePtr<RawServoAuthorStyles> mServoStyles;
289 UniquePtr<mozilla::ServoStyleRuleMap> mStyleRuleMap;
291 using SlotArray = TreeOrderedArray<HTMLSlotElement>;
292 // Map from name of slot to an array of all slots in the shadow DOM with with
293 // the given name. The slots are stored as a weak pointer because the elements
294 // are in the shadow tree and should be kept alive by its parent.
295 nsClassHashtable<nsStringHashKey, SlotArray> mSlotMap;
297 // Unordered array of all elements that have a part attribute in this shadow
298 // tree.
299 nsTArray<const Element*> mParts;
301 bool mIsUAWidget : 1;
303 // https://dom.spec.whatwg.org/#shadowroot-available-to-element-internals
304 bool mIsAvailableToElementInternals : 1;
306 nsresult Clone(dom::NodeInfo*, nsINode** aResult) const override;
309 } // namespace dom
310 } // namespace mozilla
312 #endif // mozilla_dom_shadowroot_h__