Backed out changeset 9d8b4c0b99ed (bug 1945683) for causing btime failures. CLOSED...
[gecko.git] / dom / base / ShadowRoot.h
blob0f0f1510da491076be46e672cf60459e59a3ba96
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 "nsStubMutationObserver.h"
20 #include "nsTHashtable.h"
22 class nsAtom;
23 class nsIContent;
25 namespace mozilla {
27 class EventChainPreVisitor;
28 class ServoStyleRuleMap;
30 enum class StyleRuleChangeKind : uint32_t;
32 namespace css {
33 class Rule;
36 namespace dom {
38 class CSSImportRule;
39 class Element;
40 class HTMLInputElement;
41 class OwningTrustedHTMLOrNullIsEmptyString;
42 class TrustedHTMLOrString;
43 class TrustedHTMLOrNullIsEmptyString;
45 class ShadowRoot final : public DocumentFragment, public DocumentOrShadowRoot {
46 friend class DocumentOrShadowRoot;
48 using Declarative = Element::ShadowRootDeclarative;
49 using IsClonable = Element::ShadowRootClonable;
50 using IsSerializable = Element::ShadowRootSerializable;
52 public:
53 NS_IMPL_FROMNODE_HELPER(ShadowRoot, IsShadowRoot());
55 NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(ShadowRoot, DocumentFragment)
56 NS_DECL_ISUPPORTS_INHERITED
58 ShadowRoot(Element* aElement, ShadowRootMode aMode,
59 Element::DelegatesFocus aDelegatesFocus,
60 SlotAssignmentMode aSlotAssignment, IsClonable aClonable,
61 IsSerializable aIsSerializable, Declarative aDeclarative,
62 already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo);
64 void AddSizeOfExcludingThis(nsWindowSizes&, size_t* aNodeSize) const final;
66 // Try to reassign an element or text to a slot.
67 void MaybeReassignContent(nsIContent& aElementOrText);
68 // Called when an element is inserted as a direct child of our host. Tries to
69 // slot the child in one of our slots.
70 void MaybeSlotHostChild(nsIContent&);
71 // Called when a direct child of our host is removed. Tries to un-slot the
72 // child from the currently-assigned slot, if any.
73 void MaybeUnslotHostChild(nsIContent&);
75 // Shadow DOM v1
76 Element* Host() const {
77 MOZ_ASSERT(GetHost(),
78 "ShadowRoot always has a host, how did we create "
79 "this ShadowRoot?");
80 return GetHost();
83 ShadowRootMode Mode() const { return mMode; }
84 bool DelegatesFocus() const {
85 return mDelegatesFocus == Element::DelegatesFocus::Yes;
87 SlotAssignmentMode SlotAssignment() const { return mSlotAssignment; }
88 bool Clonable() const { return mIsClonable == IsClonable::Yes; }
89 bool IsClosed() const { return mMode == ShadowRootMode::Closed; }
90 bool Serializable() const { return mIsSerializable == IsSerializable::Yes; }
92 void RemoveSheetFromStyles(StyleSheet&);
93 void RuleAdded(StyleSheet&, css::Rule&);
94 void RuleRemoved(StyleSheet&, css::Rule&);
95 void RuleChanged(StyleSheet&, css::Rule*, const StyleRuleChange&);
96 void ImportRuleLoaded(StyleSheet&);
97 void SheetCloned(StyleSheet&);
98 void StyleSheetApplicableStateChanged(StyleSheet&);
101 * Clones internal state, for example stylesheets, of aOther to 'this'.
103 void CloneInternalDataFrom(ShadowRoot* aOther);
104 void InsertSheetAt(size_t aIndex, StyleSheet&);
106 // Calls UnbindFromTree for each of our kids, and also flags us as no longer
107 // being connected.
108 void Unbind();
110 // Only intended for UA widgets / special shadow roots, or for handling
111 // failure cases when adopting (see BlastSubtreeToPieces).
113 // Forgets our shadow host and unbinds all our kids.
114 void Unattach();
116 // Calls BindToTree on each of our kids, and also maybe flags us as being
117 // connected.
118 nsresult Bind();
121 * Explicitly invalidates the style and layout of the flattened-tree subtree
122 * rooted at the element.
124 * You need to use this whenever the flat tree is going to be shuffled in a
125 * way that layout doesn't understand via the usual ContentInserted /
126 * ContentAppended / ContentRemoved notifications. For example, if removing an
127 * element will cause a change in the flat tree such that other element will
128 * start showing up (like fallback content), this method needs to be called on
129 * an ancestor of that element.
131 * It is important that this runs _before_ actually shuffling the flat tree
132 * around, so that layout knows the actual tree that it needs to invalidate.
134 void InvalidateStyleAndLayoutOnSubtree(Element*);
136 private:
137 void InsertSheetIntoAuthorData(size_t aIndex, StyleSheet&,
138 const nsTArray<RefPtr<StyleSheet>>&);
140 void AppendStyleSheet(StyleSheet& aSheet) {
141 InsertSheetAt(SheetCount(), aSheet);
145 * Represents the insertion point in a slot for a given node.
147 struct SlotInsertionPoint {
148 HTMLSlotElement* mSlot = nullptr;
149 Maybe<uint32_t> mIndex;
151 SlotInsertionPoint() = default;
152 SlotInsertionPoint(HTMLSlotElement* aSlot, const Maybe<uint32_t>& aIndex)
153 : mSlot(aSlot), mIndex(aIndex) {}
157 * Return the assignment corresponding to the content node at this particular
158 * point in time.
160 * It's the caller's responsibility to actually call InsertAssignedNode /
161 * AppendAssignedNode in the slot as needed.
163 SlotInsertionPoint SlotInsertionPointFor(nsIContent&);
166 * Returns the effective slot name for a given slottable. In most cases, this
167 * is just the value of the slot attribute, if any, or the empty string, but
168 * this also deals with the <details> shadow tree specially.
170 void GetSlotNameFor(const nsIContent&, nsAString&) const;
173 * Re-assign the current main summary if it has changed.
175 * Must be called only if mIsDetailsShadowTree is true.
177 enum class SummaryChangeReason { Deletion, Insertion };
178 void MaybeReassignMainSummary(SummaryChangeReason);
180 public:
181 void AddSlot(HTMLSlotElement* aSlot);
182 void RemoveSlot(HTMLSlotElement* aSlot);
183 bool HasSlots() const { return !mSlotMap.IsEmpty(); };
184 HTMLSlotElement* GetDefaultSlot() const {
185 SlotArray* list = mSlotMap.Get(u""_ns);
186 return list ? (*list)->ElementAt(0) : nullptr;
189 void PartAdded(const Element&);
190 void PartRemoved(const Element&);
192 IMPL_EVENT_HANDLER(slotchange);
194 const nsTArray<const Element*>& Parts() const { return mParts; }
196 const StyleAuthorStyles* GetServoStyles() const { return mServoStyles.get(); }
198 StyleAuthorStyles* GetServoStyles() { return mServoStyles.get(); }
200 mozilla::ServoStyleRuleMap& ServoStyleRuleMap();
202 JSObject* WrapNode(JSContext*, JS::Handle<JSObject*> aGivenProto) final;
204 void NodeInfoChanged(Document* aOldDoc) override;
206 void AddToIdTable(Element* aElement, nsAtom* aId);
207 void RemoveFromIdTable(Element* aElement, nsAtom* aId);
209 // WebIDL methods.
210 using mozilla::dom::DocumentOrShadowRoot::GetElementById;
212 Element* GetActiveElement();
215 * These methods allow UA Widget to insert DOM elements into the Shadow ROM
216 * without putting their DOM reflectors to content scope first.
217 * The inserted DOM will have their reflectors in the UA Widget scope.
219 nsINode* ImportNodeAndAppendChildAt(nsINode& aParentNode, nsINode& aNode,
220 bool aDeep, mozilla::ErrorResult& rv);
222 nsINode* CreateElementAndAppendChildAt(nsINode& aParentNode,
223 const nsAString& aTagName,
224 mozilla::ErrorResult& rv);
226 bool IsUAWidget() const { return HasBeenInUAWidget(); }
228 void SetIsUAWidget() {
229 MOZ_ASSERT(!HasChildren());
230 SetIsNativeAnonymousRoot();
231 SetFlags(NODE_HAS_BEEN_IN_UA_WIDGET);
234 bool IsAvailableToElementInternals() const {
235 return mIsAvailableToElementInternals;
238 void SetAvailableToElementInternals() {
239 mIsAvailableToElementInternals = true;
242 void GetEventTargetParent(EventChainPreVisitor& aVisitor) override;
244 bool IsDeclarative() const { return mIsDeclarative == Declarative::Yes; }
245 void SetIsDeclarative(Declarative aIsDeclarative) {
246 mIsDeclarative = aIsDeclarative;
248 void SetIsDeclarative(bool aIsDeclarative) {
249 mIsDeclarative = aIsDeclarative ? Declarative::Yes : Declarative::No;
252 MOZ_CAN_RUN_SCRIPT
253 void SetHTMLUnsafe(const TrustedHTMLOrString& aHTML, ErrorResult& aError);
255 // @param aInnerHTML will always be of type `NullIsEmptyString`.
256 void GetInnerHTML(OwningTrustedHTMLOrNullIsEmptyString& aInnerHTML);
258 MOZ_CAN_RUN_SCRIPT void SetInnerHTML(
259 const TrustedHTMLOrNullIsEmptyString& aInnerHTML, ErrorResult& aError);
261 void GetHTML(const GetHTMLOptions& aOptions, nsAString& aResult);
263 protected:
264 // FIXME(emilio): This will need to become more fine-grained.
265 void ApplicableRulesChanged();
267 virtual ~ShadowRoot();
269 // Make sure that the first field is pointer-aligned so it doesn't get packed
270 // in the base class' padding, since otherwise rust-bindgen can't generate
271 // correct bindings for it, see
272 // https://github.com/rust-lang/rust-bindgen/issues/380
274 // The computed data from the style sheets.
275 UniquePtr<StyleAuthorStyles> mServoStyles;
276 UniquePtr<mozilla::ServoStyleRuleMap> mStyleRuleMap;
278 using SlotArray = TreeOrderedArray<HTMLSlotElement*>;
279 // Map from name of slot to an array of all slots in the shadow DOM with with
280 // the given name. The slots are stored as a weak pointer because the elements
281 // are in the shadow tree and should be kept alive by its parent.
282 nsClassHashtable<nsStringHashKey, SlotArray> mSlotMap;
284 // Unordered array of all elements that have a part attribute in this shadow
285 // tree.
286 nsTArray<const Element*> mParts;
288 const ShadowRootMode mMode;
290 Element::DelegatesFocus mDelegatesFocus;
292 const SlotAssignmentMode mSlotAssignment;
294 // Whether this is the <details> internal shadow tree.
295 bool mIsDetailsShadowTree : 1;
297 // https://dom.spec.whatwg.org/#shadowroot-available-to-element-internals
298 bool mIsAvailableToElementInternals : 1;
300 // https://dom.spec.whatwg.org/#shadowroot-declarative
301 Declarative mIsDeclarative;
303 // https://dom.spec.whatwg.org/#shadowroot-clonable
304 const IsClonable mIsClonable;
306 // https://dom.spec.whatwg.org/#shadowroot-serializable
307 const IsSerializable mIsSerializable;
309 nsresult Clone(dom::NodeInfo*, nsINode** aResult) const override;
312 } // namespace dom
313 } // namespace mozilla
315 #endif // mozilla_dom_shadowroot_h__