Bug 1850713: remove duplicated setting of early hint preloader id in `ScriptLoader...
[gecko.git] / dom / base / ShadowRoot.h
blobaceb3ab56a73de8be18aa7c31da3cbdeb644998f
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;
26 namespace mozilla {
28 class EventChainPreVisitor;
29 class ServoStyleRuleMap;
31 enum class StyleRuleChangeKind : uint32_t;
33 namespace css {
34 class Rule;
37 namespace dom {
39 class CSSImportRule;
40 class Element;
41 class HTMLInputElement;
43 class ShadowRoot final : public DocumentFragment,
44 public DocumentOrShadowRoot,
45 public nsIRadioGroupContainer {
46 friend class DocumentOrShadowRoot;
48 public:
49 NS_IMPL_FROMNODE_HELPER(ShadowRoot, IsShadowRoot());
51 NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(ShadowRoot, DocumentFragment)
52 NS_DECL_ISUPPORTS_INHERITED
54 ShadowRoot(Element* aElement, ShadowRootMode aMode,
55 Element::DelegatesFocus aDelegatesFocus,
56 SlotAssignmentMode aSlotAssignment,
57 already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo);
59 void AddSizeOfExcludingThis(nsWindowSizes&, size_t* aNodeSize) const final;
61 // Try to reassign an element or text to a slot.
62 void MaybeReassignContent(nsIContent& aElementOrText);
63 // Called when an element is inserted as a direct child of our host. Tries to
64 // slot the child in one of our slots.
65 void MaybeSlotHostChild(nsIContent&);
66 // Called when a direct child of our host is removed. Tries to un-slot the
67 // child from the currently-assigned slot, if any.
68 void MaybeUnslotHostChild(nsIContent&);
70 // Shadow DOM v1
71 Element* Host() const {
72 MOZ_ASSERT(GetHost(),
73 "ShadowRoot always has a host, how did we create "
74 "this ShadowRoot?");
75 return GetHost();
78 ShadowRootMode Mode() const { return mMode; }
79 bool DelegatesFocus() const {
80 return mDelegatesFocus == Element::DelegatesFocus::Yes;
82 SlotAssignmentMode SlotAssignment() const { return mSlotAssignment; }
83 bool IsClosed() const { return mMode == ShadowRootMode::Closed; }
85 void RemoveSheetFromStyles(StyleSheet&);
86 void RuleAdded(StyleSheet&, css::Rule&);
87 void RuleRemoved(StyleSheet&, css::Rule&);
88 void RuleChanged(StyleSheet&, css::Rule*, StyleRuleChangeKind);
89 void ImportRuleLoaded(CSSImportRule&, StyleSheet&);
90 void SheetCloned(StyleSheet&);
91 void StyleSheetApplicableStateChanged(StyleSheet&);
93 /**
94 * Clones internal state, for example stylesheets, of aOther to 'this'.
96 void CloneInternalDataFrom(ShadowRoot* aOther);
97 void InsertSheetAt(size_t aIndex, StyleSheet&);
99 // Calls UnbindFromTree for each of our kids, and also flags us as no longer
100 // being connected.
101 void Unbind();
103 // Only intended for UA widgets / special shadow roots, or for handling
104 // failure cases when adopting (see BlastSubtreeToPieces).
106 // Forgets our shadow host and unbinds all our kids.
107 void Unattach();
109 // Calls BindToTree on each of our kids, and also maybe flags us as being
110 // connected.
111 nsresult Bind();
114 * Explicitly invalidates the style and layout of the flattened-tree subtree
115 * rooted at the element.
117 * You need to use this whenever the flat tree is going to be shuffled in a
118 * way that layout doesn't understand via the usual ContentInserted /
119 * ContentAppended / ContentRemoved notifications. For example, if removing an
120 * element will cause a change in the flat tree such that other element will
121 * start showing up (like fallback content), this method needs to be called on
122 * an ancestor of that element.
124 * It is important that this runs _before_ actually shuffling the flat tree
125 * around, so that layout knows the actual tree that it needs to invalidate.
127 void InvalidateStyleAndLayoutOnSubtree(Element*);
129 private:
130 void InsertSheetIntoAuthorData(size_t aIndex, StyleSheet&,
131 const nsTArray<RefPtr<StyleSheet>>&);
133 void AppendStyleSheet(StyleSheet& aSheet) {
134 InsertSheetAt(SheetCount(), aSheet);
138 * Represents the insertion point in a slot for a given node.
140 struct SlotInsertionPoint {
141 HTMLSlotElement* mSlot = nullptr;
142 Maybe<uint32_t> mIndex;
144 SlotInsertionPoint() = default;
145 SlotInsertionPoint(HTMLSlotElement* aSlot, const Maybe<uint32_t>& aIndex)
146 : mSlot(aSlot), mIndex(aIndex) {}
150 * Return the assignment corresponding to the content node at this particular
151 * point in time.
153 * It's the caller's responsibility to actually call InsertAssignedNode /
154 * AppendAssignedNode in the slot as needed.
156 SlotInsertionPoint SlotInsertionPointFor(nsIContent&);
159 * Returns the effective slot name for a given slottable. In most cases, this
160 * is just the value of the slot attribute, if any, or the empty string, but
161 * this also deals with the <details> shadow tree specially.
163 void GetSlotNameFor(const nsIContent&, nsAString&) const;
166 * Re-assign the current main summary if it has changed.
168 * Must be called only if mIsDetailsShadowTree is true.
170 enum class SummaryChangeReason { Deletion, Insertion };
171 void MaybeReassignMainSummary(SummaryChangeReason);
173 public:
174 void AddSlot(HTMLSlotElement* aSlot);
175 void RemoveSlot(HTMLSlotElement* aSlot);
176 bool HasSlots() const { return !mSlotMap.IsEmpty(); };
177 HTMLSlotElement* GetDefaultSlot() const {
178 SlotArray* list = mSlotMap.Get(u""_ns);
179 return list ? (*list)->ElementAt(0) : nullptr;
182 void PartAdded(const Element&);
183 void PartRemoved(const Element&);
185 IMPL_EVENT_HANDLER(slotchange);
187 const nsTArray<const Element*>& Parts() const { return mParts; }
189 const StyleAuthorStyles* GetServoStyles() const { return mServoStyles.get(); }
191 StyleAuthorStyles* GetServoStyles() { return mServoStyles.get(); }
193 mozilla::ServoStyleRuleMap& ServoStyleRuleMap();
195 JSObject* WrapNode(JSContext*, JS::Handle<JSObject*> aGivenProto) final;
197 void NodeInfoChanged(Document* aOldDoc) override;
199 void AddToIdTable(Element* aElement, nsAtom* aId);
200 void RemoveFromIdTable(Element* aElement, nsAtom* aId);
202 // WebIDL methods.
203 using mozilla::dom::DocumentOrShadowRoot::GetElementById;
205 Element* GetActiveElement();
208 * These methods allow UA Widget to insert DOM elements into the Shadow ROM
209 * without putting their DOM reflectors to content scope first.
210 * The inserted DOM will have their reflectors in the UA Widget scope.
212 nsINode* ImportNodeAndAppendChildAt(nsINode& aParentNode, nsINode& aNode,
213 bool aDeep, mozilla::ErrorResult& rv);
215 nsINode* CreateElementAndAppendChildAt(nsINode& aParentNode,
216 const nsAString& aTagName,
217 mozilla::ErrorResult& rv);
219 bool IsUAWidget() const { return HasBeenInUAWidget(); }
221 void SetIsUAWidget() {
222 MOZ_ASSERT(!HasChildren());
223 SetIsNativeAnonymousRoot();
224 SetFlags(NODE_HAS_BEEN_IN_UA_WIDGET);
227 bool IsAvailableToElementInternals() const {
228 return mIsAvailableToElementInternals;
231 void SetAvailableToElementInternals() {
232 mIsAvailableToElementInternals = true;
235 void GetEventTargetParent(EventChainPreVisitor& aVisitor) override;
237 // nsIRadioGroupContainer
238 NS_IMETHOD WalkRadioGroup(const nsAString& aName,
239 nsIRadioVisitor* aVisitor) override {
240 return DocumentOrShadowRoot::WalkRadioGroup(aName, aVisitor);
242 void SetCurrentRadioButton(const nsAString& aName,
243 HTMLInputElement* aRadio) override {
244 DocumentOrShadowRoot::SetCurrentRadioButton(aName, aRadio);
246 HTMLInputElement* GetCurrentRadioButton(const nsAString& aName) override {
247 return DocumentOrShadowRoot::GetCurrentRadioButton(aName);
249 NS_IMETHOD
250 GetNextRadioButton(const nsAString& aName, const bool aPrevious,
251 HTMLInputElement* aFocusedRadio,
252 HTMLInputElement** aRadioOut) override {
253 return DocumentOrShadowRoot::GetNextRadioButton(aName, aPrevious,
254 aFocusedRadio, aRadioOut);
256 void AddToRadioGroup(const nsAString& aName,
257 HTMLInputElement* aRadio) override {
258 DocumentOrShadowRoot::AddToRadioGroup(aName, aRadio, this);
260 void RemoveFromRadioGroup(const nsAString& aName,
261 HTMLInputElement* aRadio) override {
262 DocumentOrShadowRoot::RemoveFromRadioGroup(aName, aRadio);
264 uint32_t GetRequiredRadioCount(const nsAString& aName) const override {
265 return DocumentOrShadowRoot::GetRequiredRadioCount(aName);
267 void RadioRequiredWillChange(const nsAString& aName,
268 bool aRequiredAdded) override {
269 DocumentOrShadowRoot::RadioRequiredWillChange(aName, aRequiredAdded);
271 bool GetValueMissingState(const nsAString& aName) const override {
272 return DocumentOrShadowRoot::GetValueMissingState(aName);
274 void SetValueMissingState(const nsAString& aName, bool aValue) override {
275 return DocumentOrShadowRoot::SetValueMissingState(aName, aValue);
278 protected:
279 // FIXME(emilio): This will need to become more fine-grained.
280 void ApplicableRulesChanged();
282 virtual ~ShadowRoot();
284 const ShadowRootMode mMode;
286 Element::DelegatesFocus mDelegatesFocus;
288 const SlotAssignmentMode mSlotAssignment;
290 // The computed data from the style sheets.
291 UniquePtr<StyleAuthorStyles> mServoStyles;
292 UniquePtr<mozilla::ServoStyleRuleMap> mStyleRuleMap;
294 using SlotArray = TreeOrderedArray<HTMLSlotElement>;
295 // Map from name of slot to an array of all slots in the shadow DOM with with
296 // the given name. The slots are stored as a weak pointer because the elements
297 // are in the shadow tree and should be kept alive by its parent.
298 nsClassHashtable<nsStringHashKey, SlotArray> mSlotMap;
300 // Unordered array of all elements that have a part attribute in this shadow
301 // tree.
302 nsTArray<const Element*> mParts;
304 // Whether this is the <details> internal shadow tree.
305 bool mIsDetailsShadowTree : 1;
307 // https://dom.spec.whatwg.org/#shadowroot-available-to-element-internals
308 bool mIsAvailableToElementInternals : 1;
310 nsresult Clone(dom::NodeInfo*, nsINode** aResult) const override;
313 } // namespace dom
314 } // namespace mozilla
316 #endif // mozilla_dom_shadowroot_h__