diff options
Diffstat (limited to 'dom/html/nsGenericHTMLElement.h')
-rw-r--r-- | dom/html/nsGenericHTMLElement.h | 1461 |
1 files changed, 1461 insertions, 0 deletions
diff --git a/dom/html/nsGenericHTMLElement.h b/dom/html/nsGenericHTMLElement.h new file mode 100644 index 0000000000..f6e7d2415d --- /dev/null +++ b/dom/html/nsGenericHTMLElement.h @@ -0,0 +1,1461 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#ifndef nsGenericHTMLElement_h___ +#define nsGenericHTMLElement_h___ + +#include "mozilla/Attributes.h" +#include "mozilla/EventForwards.h" +#include "nsNameSpaceManager.h" // for kNameSpaceID_None +#include "nsIFormControl.h" +#include "nsGkAtoms.h" +#include "nsContentCreatorFunctions.h" +#include "nsStyledElement.h" +#include "mozilla/dom/BindingDeclarations.h" +#include "mozilla/dom/Element.h" +#include "mozilla/dom/DOMRect.h" +#include "mozilla/dom/ValidityState.h" +#include "mozilla/dom/PopoverData.h" +#include "mozilla/dom/ToggleEvent.h" + +#include <cstdint> + +class nsDOMTokenList; +class nsIFormControlFrame; +class nsIFrame; +class nsILayoutHistoryState; +class nsIURI; +struct nsSize; + +enum nsCSSPropertyID : int32_t; + +namespace mozilla { +class EditorBase; +class ErrorResult; +class EventChainPostVisitor; +class EventChainPreVisitor; +class EventChainVisitor; +class EventListenerManager; +class PresState; +namespace dom { +class ElementInternals; +class HTMLFormElement; +enum class FetchPriority : uint8_t; +} // namespace dom +} // namespace mozilla + +using nsGenericHTMLElementBase = nsStyledElement; + +/** + * A common superclass for HTML elements + */ +class nsGenericHTMLElement : public nsGenericHTMLElementBase { + public: + using Element::Focus; + using Element::SetTabIndex; + explicit nsGenericHTMLElement( + already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo) + : nsGenericHTMLElementBase(std::move(aNodeInfo)) { + NS_ASSERTION(mNodeInfo->NamespaceID() == kNameSpaceID_XHTML, + "Unexpected namespace"); + AddStatesSilently(mozilla::dom::ElementState::LTR); + } + + NS_INLINE_DECL_REFCOUNTING_INHERITED(nsGenericHTMLElement, + nsGenericHTMLElementBase) + + NS_IMPL_FROMNODE(nsGenericHTMLElement, kNameSpaceID_XHTML) + + // From Element + nsresult CopyInnerTo(mozilla::dom::Element* aDest); + + void GetTitle(mozilla::dom::DOMString& aTitle) { + GetHTMLAttr(nsGkAtoms::title, aTitle); + } + void SetTitle(const nsAString& aTitle) { + SetHTMLAttr(nsGkAtoms::title, aTitle); + } + void GetLang(mozilla::dom::DOMString& aLang) { + GetHTMLAttr(nsGkAtoms::lang, aLang); + } + void SetLang(const nsAString& aLang) { SetHTMLAttr(nsGkAtoms::lang, aLang); } + bool Translate() const override; + void SetTranslate(bool aTranslate, mozilla::ErrorResult& aError) { + SetHTMLAttr(nsGkAtoms::translate, aTranslate ? u"yes"_ns : u"no"_ns, + aError); + } + void GetDir(nsAString& aDir) { GetHTMLEnumAttr(nsGkAtoms::dir, aDir); } + void SetDir(const nsAString& aDir, mozilla::ErrorResult& aError) { + SetHTMLAttr(nsGkAtoms::dir, aDir, aError); + } + void GetPopover(nsString& aPopover) const; + void SetPopover(const nsAString& aPopover, mozilla::ErrorResult& aError) { + SetOrRemoveNullableStringAttr(nsGkAtoms::popover, aPopover, aError); + } + bool Hidden() const { return GetBoolAttr(nsGkAtoms::hidden); } + void SetHidden(bool aHidden, mozilla::ErrorResult& aError) { + SetHTMLBoolAttr(nsGkAtoms::hidden, aHidden, aError); + } + bool Inert() const { return GetBoolAttr(nsGkAtoms::inert); } + void SetInert(bool aInert, mozilla::ErrorResult& aError) { + SetHTMLBoolAttr(nsGkAtoms::inert, aInert, aError); + } + MOZ_CAN_RUN_SCRIPT void Click(mozilla::dom::CallerType aCallerType); + void GetAccessKey(nsString& aAccessKey) { + GetHTMLAttr(nsGkAtoms::accesskey, aAccessKey); + } + void SetAccessKey(const nsAString& aAccessKey, mozilla::ErrorResult& aError) { + SetHTMLAttr(nsGkAtoms::accesskey, aAccessKey, aError); + } + void GetAccessKeyLabel(nsString& aAccessKeyLabel); + virtual bool Draggable() const { + return AttrValueIs(kNameSpaceID_None, nsGkAtoms::draggable, + nsGkAtoms::_true, eIgnoreCase); + } + void SetDraggable(bool aDraggable, mozilla::ErrorResult& aError) { + SetHTMLAttr(nsGkAtoms::draggable, aDraggable ? u"true"_ns : u"false"_ns, + aError); + } + void GetContentEditable(nsString& aContentEditable) { + ContentEditableTristate value = GetContentEditableValue(); + if (value == eTrue) { + aContentEditable.AssignLiteral("true"); + } else if (value == eFalse) { + aContentEditable.AssignLiteral("false"); + } else { + aContentEditable.AssignLiteral("inherit"); + } + } + void SetContentEditable(const nsAString& aContentEditable, + mozilla::ErrorResult& aError) { + if (aContentEditable.LowerCaseEqualsLiteral("inherit")) { + UnsetHTMLAttr(nsGkAtoms::contenteditable, aError); + } else if (aContentEditable.LowerCaseEqualsLiteral("true")) { + SetHTMLAttr(nsGkAtoms::contenteditable, u"true"_ns, aError); + } else if (aContentEditable.LowerCaseEqualsLiteral("false")) { + SetHTMLAttr(nsGkAtoms::contenteditable, u"false"_ns, aError); + } else { + aError.Throw(NS_ERROR_DOM_SYNTAX_ERR); + } + } + bool IsContentEditable() { + for (nsIContent* node = this; node; node = node->GetParent()) { + nsGenericHTMLElement* element = FromNode(node); + if (element) { + ContentEditableTristate value = element->GetContentEditableValue(); + if (value != eInherit) { + return value == eTrue; + } + } + } + return false; + } + + mozilla::dom::PopoverAttributeState GetPopoverAttributeState() const; + void PopoverPseudoStateUpdate(bool aOpen, bool aNotify); + bool PopoverOpen() const; + bool CheckPopoverValidity(mozilla::dom::PopoverVisibilityState aExpectedState, + Document* aExpectedDocument, ErrorResult& aRv); + already_AddRefed<mozilla::dom::ToggleEvent> CreateToggleEvent( + const nsAString& aEventType, const nsAString& aOldState, + const nsAString& aNewState, mozilla::Cancelable); + /** Returns true if the event has been cancelled. */ + MOZ_CAN_RUN_SCRIPT bool FireToggleEvent( + mozilla::dom::PopoverVisibilityState aOldState, + mozilla::dom::PopoverVisibilityState aNewState, const nsAString& aType); + MOZ_CAN_RUN_SCRIPT void QueuePopoverEventTask( + mozilla::dom::PopoverVisibilityState aOldState); + MOZ_CAN_RUN_SCRIPT void RunPopoverToggleEventTask( + mozilla::dom::PopoverToggleEventTask* aTask, + mozilla::dom::PopoverVisibilityState aOldState); + MOZ_CAN_RUN_SCRIPT void ShowPopover(ErrorResult& aRv); + MOZ_CAN_RUN_SCRIPT void ShowPopoverInternal(Element* aInvoker, + ErrorResult& aRv); + MOZ_CAN_RUN_SCRIPT_BOUNDARY void HidePopoverWithoutRunningScript(); + MOZ_CAN_RUN_SCRIPT void HidePopoverInternal(bool aFocusPreviousElement, + bool aFireEvents, + ErrorResult& aRv); + MOZ_CAN_RUN_SCRIPT void HidePopover(ErrorResult& aRv); + MOZ_CAN_RUN_SCRIPT bool TogglePopover( + const mozilla::dom::Optional<bool>& aForce, ErrorResult& aRv); + MOZ_CAN_RUN_SCRIPT void FocusPopover(); + void ForgetPreviouslyFocusedElementAfterHidingPopover(); + MOZ_CAN_RUN_SCRIPT void FocusPreviousElementAfterHidingPopover(); + + MOZ_CAN_RUN_SCRIPT void FocusCandidate(Element*, bool aClearUpFocus); + + void SetNonce(const nsAString& aNonce) { + SetProperty(nsGkAtoms::nonce, new nsString(aNonce), + nsINode::DeleteProperty<nsString>, /* aTransfer = */ true); + } + void RemoveNonce() { RemoveProperty(nsGkAtoms::nonce); } + void GetNonce(nsAString& aNonce) const { + nsString* cspNonce = static_cast<nsString*>(GetProperty(nsGkAtoms::nonce)); + if (cspNonce) { + aNonce = *cspNonce; + } + } + + /** Returns whether a form control should be default-focusable. */ + bool IsFormControlDefaultFocusable(bool aWithMouse) const; + + /** + * Returns the count of descendants (inclusive of this node) in + * the uncomposed document that are explicitly set as editable. + */ + uint32_t EditableInclusiveDescendantCount(); + + bool Spellcheck(); + void SetSpellcheck(bool aSpellcheck, mozilla::ErrorResult& aError) { + SetHTMLAttr(nsGkAtoms::spellcheck, aSpellcheck ? u"true"_ns : u"false"_ns, + aError); + } + + MOZ_CAN_RUN_SCRIPT + void GetInnerText(mozilla::dom::DOMString& aValue, ErrorResult& aError); + MOZ_CAN_RUN_SCRIPT + void GetOuterText(mozilla::dom::DOMString& aValue, ErrorResult& aError) { + return GetInnerText(aValue, aError); + } + MOZ_CAN_RUN_SCRIPT void SetInnerText(const nsAString& aValue); + MOZ_CAN_RUN_SCRIPT void SetOuterText(const nsAString& aValue, + ErrorResult& aRv); + + void GetInputMode(nsAString& aValue) { + GetEnumAttr(nsGkAtoms::inputmode, nullptr, aValue); + } + void SetInputMode(const nsAString& aValue, ErrorResult& aRv) { + SetHTMLAttr(nsGkAtoms::inputmode, aValue, aRv); + } + virtual void GetAutocapitalize(nsAString& aValue) const; + void SetAutocapitalize(const nsAString& aValue, ErrorResult& aRv) { + SetHTMLAttr(nsGkAtoms::autocapitalize, aValue, aRv); + } + + void GetEnterKeyHint(nsAString& aValue) const { + GetEnumAttr(nsGkAtoms::enterkeyhint, nullptr, aValue); + } + void SetEnterKeyHint(const nsAString& aValue, ErrorResult& aRv) { + SetHTMLAttr(nsGkAtoms::enterkeyhint, aValue, aRv); + } + + /** + * Determine whether an attribute is an event (onclick, etc.) + * @param aName the attribute + * @return whether the name is an event handler name + */ + bool IsEventAttributeNameInternal(nsAtom* aName) override; + +#define EVENT(name_, id_, type_, struct_) /* nothing; handled by nsINode */ +// The using nsINode::Get/SetOn* are to avoid warnings about shadowing the XPCOM +// getter and setter on nsINode. +#define FORWARDED_EVENT(name_, id_, type_, struct_) \ + using nsINode::GetOn##name_; \ + using nsINode::SetOn##name_; \ + mozilla::dom::EventHandlerNonNull* GetOn##name_(); \ + void SetOn##name_(mozilla::dom::EventHandlerNonNull* handler); +#define ERROR_EVENT(name_, id_, type_, struct_) \ + using nsINode::GetOn##name_; \ + using nsINode::SetOn##name_; \ + already_AddRefed<mozilla::dom::EventHandlerNonNull> GetOn##name_(); \ + void SetOn##name_(mozilla::dom::EventHandlerNonNull* handler); +#include "mozilla/EventNameList.h" // IWYU pragma: keep +#undef ERROR_EVENT +#undef FORWARDED_EVENT +#undef EVENT + mozilla::dom::Element* GetOffsetParent() { + mozilla::CSSIntRect rcFrame; + return GetOffsetRect(rcFrame); + } + int32_t OffsetTop() { + mozilla::CSSIntRect rcFrame; + GetOffsetRect(rcFrame); + + return rcFrame.y; + } + int32_t OffsetLeft() { + mozilla::CSSIntRect rcFrame; + GetOffsetRect(rcFrame); + + return rcFrame.x; + } + int32_t OffsetWidth() { + mozilla::CSSIntRect rcFrame; + GetOffsetRect(rcFrame); + + return rcFrame.Width(); + } + int32_t OffsetHeight() { + mozilla::CSSIntRect rcFrame; + GetOffsetRect(rcFrame); + + return rcFrame.Height(); + } + + // These methods are already implemented in nsIContent but we want something + // faster for HTMLElements ignoring the namespace checking. + // This is safe because we already know that we are in the HTML namespace. + inline bool IsHTMLElement() const { return true; } + + inline bool IsHTMLElement(nsAtom* aTag) const { + return mNodeInfo->Equals(aTag); + } + + template <typename First, typename... Args> + inline bool IsAnyOfHTMLElements(First aFirst, Args... aArgs) const { + return IsNodeInternal(aFirst, aArgs...); + } + + // https://html.spec.whatwg.org/multipage/custom-elements.html#dom-attachinternals + virtual already_AddRefed<mozilla::dom::ElementInternals> AttachInternals( + ErrorResult& aRv); + + mozilla::dom::ElementInternals* GetInternals() const; + + bool IsFormAssociatedCustomElements() const; + + // Returns true if the event should not be handled from GetEventTargetParent. + virtual bool IsDisabledForEvents(mozilla::WidgetEvent* aEvent) { + return false; + } + + bool Autofocus() const { return GetBoolAttr(nsGkAtoms::autofocus); } + void SetAutofocus(bool aVal, ErrorResult& aRv) { + SetHTMLBoolAttr(nsGkAtoms::autofocus, aVal, aRv); + } + + protected: + virtual ~nsGenericHTMLElement() = default; + + public: + // Implementation for nsIContent + nsresult BindToTree(BindContext&, nsINode& aParent) override; + void UnbindFromTree(bool aNullParent = true) override; + + Focusable IsFocusableWithoutStyle(bool aWithMouse) override { + Focusable result; + IsHTMLFocusable(aWithMouse, &result.mFocusable, &result.mTabIndex); + return result; + } + /** + * Returns true if a subclass is not allowed to override the value returned + * in aIsFocusable. + */ + virtual bool IsHTMLFocusable(bool aWithMouse, bool* aIsFocusable, + int32_t* aTabIndex); + MOZ_CAN_RUN_SCRIPT + mozilla::Result<bool, nsresult> PerformAccesskey( + bool aKeyCausesActivation, bool aIsTrustedEvent) override; + + /** + * Check if an event for an anchor can be handled + * @return true if the event can be handled, false otherwise + */ + bool CheckHandleEventForAnchorsPreconditions( + mozilla::EventChainVisitor& aVisitor); + void GetEventTargetParentForAnchors(mozilla::EventChainPreVisitor& aVisitor); + MOZ_CAN_RUN_SCRIPT + nsresult PostHandleEventForAnchors(mozilla::EventChainPostVisitor& aVisitor); + bool IsHTMLLink(nsIURI** aURI) const; + + // HTML element methods + void Compact() { mAttrs.Compact(); } + + void UpdateEditableState(bool aNotify) override; + + bool ParseAttribute(int32_t aNamespaceID, nsAtom* aAttribute, + const nsAString& aValue, + nsIPrincipal* aMaybeScriptedPrincipal, + nsAttrValue& aResult) override; + + bool ParseBackgroundAttribute(int32_t aNamespaceID, nsAtom* aAttribute, + const nsAString& aValue, nsAttrValue& aResult); + + NS_IMETHOD_(bool) IsAttributeMapped(const nsAtom* aAttribute) const override; + nsMapRuleToAttributesFunc GetAttributeMappingFunction() const override; + + /** + * Get the base target for any links within this piece + * of content. Generally, this is the document's base target, + * but certain content carries a local base for backward + * compatibility. + * + * @param aBaseTarget the base target [OUT] + */ + void GetBaseTarget(nsAString& aBaseTarget) const; + + /** + * Get the primary form control frame for this element. Same as + * GetPrimaryFrame(), except it QI's to nsIFormControlFrame. + * + * @param aFlush whether to flush out frames so that they're up to date. + * @return the primary frame as nsIFormControlFrame + */ + nsIFormControlFrame* GetFormControlFrame(bool aFlushFrames); + + //---------------------------------------- + + /** + * Parse an alignment attribute (top/middle/bottom/baseline) + * + * @param aString the string to parse + * @param aResult the resulting HTMLValue + * @return whether the value was parsed + */ + static bool ParseAlignValue(const nsAString& aString, nsAttrValue& aResult); + + /** + * Parse a div align string to value (left/right/center/middle/justify) + * + * @param aString the string to parse + * @param aResult the resulting HTMLValue + * @return whether the value was parsed + */ + static bool ParseDivAlignValue(const nsAString& aString, + nsAttrValue& aResult); + + /** + * Convert a table halign string to value (left/right/center/char/justify) + * + * @param aString the string to parse + * @param aResult the resulting HTMLValue + * @return whether the value was parsed + */ + static bool ParseTableHAlignValue(const nsAString& aString, + nsAttrValue& aResult); + + /** + * Convert a table cell halign string to value + * + * @param aString the string to parse + * @param aResult the resulting HTMLValue + * @return whether the value was parsed + */ + static bool ParseTableCellHAlignValue(const nsAString& aString, + nsAttrValue& aResult); + + /** + * Convert a table valign string to value (left/right/center/char/justify/ + * abscenter/absmiddle/middle) + * + * @param aString the string to parse + * @param aResult the resulting HTMLValue + * @return whether the value was parsed + */ + static bool ParseTableVAlignValue(const nsAString& aString, + nsAttrValue& aResult); + + /** + * Convert an image attribute to value (width, height, hspace, vspace, border) + * + * @param aAttribute the attribute to parse + * @param aString the string to parse + * @param aResult the resulting HTMLValue + * @return whether the value was parsed + */ + static bool ParseImageAttribute(nsAtom* aAttribute, const nsAString& aString, + nsAttrValue& aResult); + + static bool ParseReferrerAttribute(const nsAString& aString, + nsAttrValue& aResult); + + /** + * Convert a frameborder string to value (yes/no/1/0) + * + * @param aString the string to parse + * @param aResult the resulting HTMLValue + * @return whether the value was parsed + */ + static bool ParseFrameborderValue(const nsAString& aString, + nsAttrValue& aResult); + + /** + * Convert a scrolling string to value (yes/no/on/off/scroll/noscroll/auto) + * + * @param aString the string to parse + * @param aResult the resulting HTMLValue + * @return whether the value was parsed + */ + static bool ParseScrollingValue(const nsAString& aString, + nsAttrValue& aResult); + + /* + * Attribute Mapping Helpers + */ + + /** + * A style attribute mapping function for the most common attributes, to be + * called by subclasses' attribute mapping functions. Currently handles + * dir, lang and hidden, could handle others. + * + * @param aAttributes the list of attributes to map + * @param aData the returned rule data [INOUT] + * @see GetAttributeMappingFunction + */ + static void MapCommonAttributesInto(mozilla::MappedDeclarationsBuilder&); + /** + * Same as MapCommonAttributesInto except that it does not handle hidden. + * @see GetAttributeMappingFunction + */ + static void MapCommonAttributesIntoExceptHidden( + mozilla::MappedDeclarationsBuilder&); + + static const MappedAttributeEntry sCommonAttributeMap[]; + static const MappedAttributeEntry sImageMarginSizeAttributeMap[]; + static const MappedAttributeEntry sImageBorderAttributeMap[]; + static const MappedAttributeEntry sImageAlignAttributeMap[]; + static const MappedAttributeEntry sDivAlignAttributeMap[]; + static const MappedAttributeEntry sBackgroundAttributeMap[]; + static const MappedAttributeEntry sBackgroundColorAttributeMap[]; + + /** + * Helper to map the align attribute. + * @see GetAttributeMappingFunction + */ + static void MapImageAlignAttributeInto(mozilla::MappedDeclarationsBuilder&); + + /** + * Helper to map the align attribute for things like <div>, <h1>, etc. + * @see GetAttributeMappingFunction + */ + static void MapDivAlignAttributeInto(mozilla::MappedDeclarationsBuilder&); + + /** + * Helper to map the valign attribute for things like <col>, <tr>, <section>. + * @see GetAttributeMappingFunction + */ + static void MapVAlignAttributeInto(mozilla::MappedDeclarationsBuilder&); + + /** + * Helper to map the image border attribute. + * @see GetAttributeMappingFunction + */ + static void MapImageBorderAttributeInto(mozilla::MappedDeclarationsBuilder&); + /** + * Helper to map the image margin attribute into a style struct. + * + * @param aAttributes the list of attributes to map + * @param aData the returned rule data [INOUT] + * @see GetAttributeMappingFunction + */ + static void MapImageMarginAttributeInto(mozilla::MappedDeclarationsBuilder&); + + /** + * Helper to map a given dimension (width/height) into the declaration + * block, handling percentages and numbers. + */ + static void MapDimensionAttributeInto(mozilla::MappedDeclarationsBuilder&, + nsCSSPropertyID, const nsAttrValue&); + + /** + * Maps the aspect ratio given width and height attributes. + */ + static void DoMapAspectRatio(const nsAttrValue& aWidth, + const nsAttrValue& aHeight, + mozilla::MappedDeclarationsBuilder&); + + // Whether to map the width and height attributes to aspect-ratio. + enum class MapAspectRatio { No, Yes }; + + /** + * Helper to map the image position attribute into a style struct. + */ + static void MapImageSizeAttributesInto(mozilla::MappedDeclarationsBuilder&, + MapAspectRatio = MapAspectRatio::No); + + /** + * Helper to map the width and height attributes into the aspect-ratio + * property. + * + * If you also map the width/height attributes to width/height (as you should + * for any HTML element that isn't <canvas>) then you should use + * MapImageSizeAttributesInto instead, passing MapAspectRatio::Yes instead, as + * that'd be faster. + */ + static void MapAspectRatioInto(mozilla::MappedDeclarationsBuilder&); + + /** + * Helper to map `width` attribute into a style struct. + * + * @param aAttributes the list of attributes to map + * @param aData the returned rule data [INOUT] + * @see GetAttributeMappingFunction + */ + static void MapWidthAttributeInto(mozilla::MappedDeclarationsBuilder&); + + /** + * Helper to map `height` attribute. + * @see GetAttributeMappingFunction + */ + static void MapHeightAttributeInto(mozilla::MappedDeclarationsBuilder&); + /** + * Helper to map the background attribute + * @see GetAttributeMappingFunction + */ + static void MapBackgroundInto(mozilla::MappedDeclarationsBuilder&); + /** + * Helper to map the bgcolor attribute + * @see GetAttributeMappingFunction + */ + static void MapBGColorInto(mozilla::MappedDeclarationsBuilder&); + /** + * Helper to map the background attributes (currently background and bgcolor) + * @see GetAttributeMappingFunction + */ + static void MapBackgroundAttributesInto(mozilla::MappedDeclarationsBuilder&); + /** + * Helper to map the scrolling attribute on FRAME and IFRAME. + * @see GetAttributeMappingFunction + */ + static void MapScrollingAttributeInto(mozilla::MappedDeclarationsBuilder&); + + // Form Helper Routines + /** + * Find an ancestor of this content node which is a form (could be null) + * @param aCurrentForm the current form for this node. If this is + * non-null, and no ancestor form is found, and the current form is in + * a connected subtree with the node, the current form will be + * returned. This is needed to handle cases when HTML elements have a + * current form that they're not descendants of. + * @note This method should not be called if the element has a form attribute. + */ + mozilla::dom::HTMLFormElement* FindAncestorForm( + mozilla::dom::HTMLFormElement* aCurrentForm = nullptr); + + /** + * See if the document being tested has nav-quirks mode enabled. + * @param doc the document + */ + static bool InNavQuirksMode(Document*); + + /** + * Gets the absolute URI value of an attribute, by resolving any relative + * URIs in the attribute against the baseuri of the element. If the attribute + * isn't a relative URI the value of the attribute is returned as is. Only + * works for attributes in null namespace. + * + * @param aAttr name of attribute. + * @param aBaseAttr name of base attribute. + * @param aResult result value [out] + */ + void GetURIAttr(nsAtom* aAttr, nsAtom* aBaseAttr, nsAString& aResult) const; + + /** + * Gets the absolute URI values of an attribute, by resolving any relative + * URIs in the attribute against the baseuri of the element. If a substring + * isn't a relative URI, the substring is returned as is. Only works for + * attributes in null namespace. + */ + bool GetURIAttr(nsAtom* aAttr, nsAtom* aBaseAttr, nsIURI** aURI) const; + + bool IsHidden() const { return HasAttr(nsGkAtoms::hidden); } + + bool IsLabelable() const override; + + static bool MatchLabelsElement(Element* aElement, int32_t aNamespaceID, + nsAtom* aAtom, void* aData); + + already_AddRefed<nsINodeList> Labels(); + + static bool LegacyTouchAPIEnabled(JSContext* aCx, JSObject* aObj); + + static inline bool CanHaveName(nsAtom* aTag) { + return aTag == nsGkAtoms::img || aTag == nsGkAtoms::form || + aTag == nsGkAtoms::embed || aTag == nsGkAtoms::object; + } + static inline bool ShouldExposeNameAsHTMLDocumentProperty(Element* aElement) { + return aElement->IsHTMLElement() && + CanHaveName(aElement->NodeInfo()->NameAtom()); + } + static inline bool ShouldExposeIdAsHTMLDocumentProperty(Element* aElement) { + if (aElement->IsHTMLElement(nsGkAtoms::object)) { + return true; + } + + // Per spec, <img> is exposed by id only if it also has a nonempty + // name (which doesn't have to match the id or anything). + // HasName() is true precisely when name is nonempty. + return aElement->IsHTMLElement(nsGkAtoms::img) && aElement->HasName(); + } + + virtual inline void ResultForDialogSubmit(nsAString& aResult) { + GetAttr(nsGkAtoms::value, aResult); + } + + // <https://html.spec.whatwg.org/#fetch-priority-attribute>. + static mozilla::dom::FetchPriority ToFetchPriority(const nsAString& aValue); + + void GetFetchPriority(nsAString& aFetchPriority) const; + + void SetFetchPriority(const nsAString& aFetchPriority) { + SetHTMLAttr(nsGkAtoms::fetchpriority, aFetchPriority); + } + + protected: + mozilla::dom::FetchPriority GetFetchPriority() const; + + static void ParseFetchPriority(const nsAString& aValue, nsAttrValue& aResult); + + private: + /** + * Add/remove this element to the documents name cache + */ + void AddToNameTable(nsAtom* aName); + void RemoveFromNameTable(); + + /** + * Register or unregister an access key to this element based on the + * accesskey attribute. + */ + void RegUnRegAccessKey(bool aDoReg) override { + if (!HasFlag(NODE_HAS_ACCESSKEY)) { + return; + } + + nsStyledElement::RegUnRegAccessKey(aDoReg); + } + + protected: + void BeforeSetAttr(int32_t aNamespaceID, nsAtom* aName, + const nsAttrValue* aValue, bool aNotify) override; + // TODO: Convert AfterSetAttr to MOZ_CAN_RUN_SCRIPT and get rid of + // kungFuDeathGrip in it. + MOZ_CAN_RUN_SCRIPT_BOUNDARY void AfterSetAttr( + int32_t aNamespaceID, nsAtom* aName, const nsAttrValue* aValue, + const nsAttrValue* aOldValue, nsIPrincipal* aMaybeScriptedPrincipal, + bool aNotify) override; + + MOZ_CAN_RUN_SCRIPT void AfterSetPopoverAttr(); + + mozilla::EventListenerManager* GetEventListenerManagerForAttr( + nsAtom* aAttrName, bool* aDefer) override; + + /** + * Handles dispatching a simulated click on `this` on space or enter. + * TODO: Convert this to MOZ_CAN_RUN_SCRIPT (bug 1415230) + */ + MOZ_CAN_RUN_SCRIPT_BOUNDARY void HandleKeyboardActivation( + mozilla::EventChainPostVisitor&); + + /** Dispatch a simulated mouse click by keyboard to the given element. */ + MOZ_CAN_RUN_SCRIPT static nsresult DispatchSimulatedClick( + nsGenericHTMLElement* aElement, bool aIsTrusted, + nsPresContext* aPresContext); + + /** + * Create a URI for the given aURISpec string. + * Returns INVALID_STATE_ERR and nulls *aURI if aURISpec is empty + * and the document's URI matches the element's base URI. + */ + nsresult NewURIFromString(const nsAString& aURISpec, nsIURI** aURI); + + void GetHTMLAttr(nsAtom* aName, nsAString& aResult) const { + GetAttr(aName, aResult); + } + void GetHTMLAttr(nsAtom* aName, mozilla::dom::DOMString& aResult) const { + GetAttr(aName, aResult); + } + void GetHTMLEnumAttr(nsAtom* aName, nsAString& aResult) const { + GetEnumAttr(aName, nullptr, aResult); + } + void GetHTMLURIAttr(nsAtom* aName, nsAString& aResult) const { + GetURIAttr(aName, nullptr, aResult); + } + + void SetHTMLAttr(nsAtom* aName, const nsAString& aValue) { + SetAttr(kNameSpaceID_None, aName, aValue, true); + } + void SetHTMLAttr(nsAtom* aName, const nsAString& aValue, + mozilla::ErrorResult& aError) { + SetAttr(aName, aValue, aError); + } + void SetHTMLAttr(nsAtom* aName, const nsAString& aValue, + nsIPrincipal* aTriggeringPrincipal, + mozilla::ErrorResult& aError) { + SetAttr(aName, aValue, aTriggeringPrincipal, aError); + } + void UnsetHTMLAttr(nsAtom* aName, mozilla::ErrorResult& aError) { + UnsetAttr(aName, aError); + } + void SetHTMLBoolAttr(nsAtom* aName, bool aValue, + mozilla::ErrorResult& aError) { + if (aValue) { + SetHTMLAttr(aName, u""_ns, aError); + } else { + UnsetHTMLAttr(aName, aError); + } + } + template <typename T> + void SetHTMLIntAttr(nsAtom* aName, T aValue, mozilla::ErrorResult& aError) { + nsAutoString value; + value.AppendInt(aValue); + + SetHTMLAttr(aName, value, aError); + } + + /** + * Gets the integer-value of an attribute, returns specified default value + * if the attribute isn't set or isn't set to an integer. Only works for + * attributes in null namespace. + * + * @param aAttr name of attribute. + * @param aDefault default-value to return if attribute isn't set. + */ + int32_t GetIntAttr(nsAtom* aAttr, int32_t aDefault) const; + + /** + * Sets value of attribute to specified integer. Only works for attributes + * in null namespace. + * + * @param aAttr name of attribute. + * @param aValue Integer value of attribute. + */ + nsresult SetIntAttr(nsAtom* aAttr, int32_t aValue); + + /** + * Gets the unsigned integer-value of an attribute, returns specified default + * value if the attribute isn't set or isn't set to an integer. Only works for + * attributes in null namespace. + * + * @param aAttr name of attribute. + * @param aDefault default-value to return if attribute isn't set. + */ + uint32_t GetUnsignedIntAttr(nsAtom* aAttr, uint32_t aDefault) const; + + /** + * Sets value of attribute to specified unsigned integer. Only works for + * attributes in null namespace. + * + * @param aAttr name of attribute. + * @param aValue Integer value of attribute. + * @param aDefault Default value (in case value is out of range). If the spec + * doesn't provide one, should be 1 if the value is limited to + * nonzero values, and 0 otherwise. + */ + void SetUnsignedIntAttr(nsAtom* aName, uint32_t aValue, uint32_t aDefault, + mozilla::ErrorResult& aError) { + nsAutoString value; + if (aValue > INT32_MAX) { + value.AppendInt(aDefault); + } else { + value.AppendInt(aValue); + } + + SetHTMLAttr(aName, value, aError); + } + + /** + * Gets the unsigned integer-value of an attribute that is stored as a + * dimension (i.e. could be an integer or a percentage), returns specified + * default value if the attribute isn't set or isn't set to a dimension. Only + * works for attributes in null namespace. + * + * @param aAttr name of attribute. + * @param aDefault default-value to return if attribute isn't set. + */ + uint32_t GetDimensionAttrAsUnsignedInt(nsAtom* aAttr, + uint32_t aDefault) const; + + enum class Reflection { + Unlimited, + OnlyPositive, + }; + + /** + * Sets value of attribute to specified double. Only works for attributes + * in null namespace. + * + * Implements + * https://html.spec.whatwg.org/multipage/common-dom-interfaces.html#reflecting-content-attributes-in-idl-attributes:idl-double + * + * @param aAttr name of attribute. + * @param aValue Double value of attribute. + */ + template <Reflection Limited = Reflection::Unlimited> + void SetDoubleAttr(nsAtom* aAttr, double aValue, mozilla::ErrorResult& aRv) { + // 1. If the reflected IDL attribute is limited to only positive numbers and + // the given value is not greater than 0, then return. + if (Limited == Reflection::OnlyPositive && aValue <= 0) { + return; + } + + // 2. Run this's set the content attribute with the given value, converted + // to the best representation of the number as a floating-point number. + nsAutoString value; + value.AppendFloat(aValue); + + SetHTMLAttr(aAttr, value, aRv); + } + + /** + * Locates the EditorBase associated with this node. In general this is + * equivalent to GetEditorInternal(), but for designmode or contenteditable, + * this may need to get an editor that's not actually on this element's + * associated TextControlFrame. This is used by the spellchecking routines + * to get the editor affected by changing the spellcheck attribute on this + * node. + */ + virtual already_AddRefed<mozilla::EditorBase> GetAssociatedEditor(); + + /** + * Get the frame's offset information for offsetTop/Left/Width/Height. + * Returns the parent the offset is relative to. + * @note This method flushes pending notifications (FlushType::Layout). + * @param aRect the offset information [OUT] + */ + mozilla::dom::Element* GetOffsetRect(mozilla::CSSIntRect& aRect); + + /** + * Ensures all editors associated with a subtree are synced, for purposes of + * spellchecking. + */ + static void SyncEditorsOnSubtree(nsIContent* content); + + enum ContentEditableTristate { eInherit = -1, eFalse = 0, eTrue = 1 }; + + /** + * Returns eTrue if the element has a contentEditable attribute and its value + * is "true" or an empty string. Returns eFalse if the element has a + * contentEditable attribute and its value is "false". Otherwise returns + * eInherit. + */ + ContentEditableTristate GetContentEditableValue() const { + static const Element::AttrValuesArray values[] = { + nsGkAtoms::_false, nsGkAtoms::_true, nsGkAtoms::_empty, nullptr}; + + if (!MayHaveContentEditableAttr()) return eInherit; + + int32_t value = FindAttrValueIn( + kNameSpaceID_None, nsGkAtoms::contenteditable, values, eIgnoreCase); + + return value > 0 ? eTrue : (value == 0 ? eFalse : eInherit); + } + + // Used by A, AREA, LINK, and STYLE. + already_AddRefed<nsIURI> GetHrefURIForAnchors() const; + + private: + void ChangeEditableState(int32_t aChange); +}; + +namespace mozilla::dom { +class HTMLFieldSetElement; +} // namespace mozilla::dom + +#define HTML_ELEMENT_FLAG_BIT(n_) \ + NODE_FLAG_BIT(ELEMENT_TYPE_SPECIFIC_BITS_OFFSET + (n_)) + +// HTMLElement specific bits +enum { + // Used to handle keyboard activation. + HTML_ELEMENT_ACTIVE_FOR_KEYBOARD = HTML_ELEMENT_FLAG_BIT(0), + // Similar to HTMLInputElement's mInhibitRestoration, used to prevent + // form-associated custom elements not created by a network parser from + // being restored. + HTML_ELEMENT_INHIBIT_RESTORATION = HTML_ELEMENT_FLAG_BIT(1), + + // Remaining bits are type specific. + HTML_ELEMENT_TYPE_SPECIFIC_BITS_OFFSET = + ELEMENT_TYPE_SPECIFIC_BITS_OFFSET + 2, +}; + +ASSERT_NODE_FLAGS_SPACE(HTML_ELEMENT_TYPE_SPECIFIC_BITS_OFFSET); + +#define FORM_ELEMENT_FLAG_BIT(n_) \ + NODE_FLAG_BIT(HTML_ELEMENT_TYPE_SPECIFIC_BITS_OFFSET + (n_)) + +// Form element specific bits +enum { + // If this flag is set on an nsGenericHTMLFormElement or an HTMLImageElement, + // that means that we have added ourselves to our mForm. It's possible to + // have a non-null mForm, but not have this flag set. That happens when the + // form is set via the content sink. + ADDED_TO_FORM = FORM_ELEMENT_FLAG_BIT(0), + + // If this flag is set on an nsGenericHTMLFormElement or an HTMLImageElement, + // that means that its form is in the process of being unbound from the tree, + // and this form element hasn't re-found its form in + // nsGenericHTMLFormElement::UnbindFromTree yet. + MAYBE_ORPHAN_FORM_ELEMENT = FORM_ELEMENT_FLAG_BIT(1), + + // If this flag is set on an nsGenericHTMLElement or an HTMLImageElement, then + // the element might be in the past names map of its form. + MAY_BE_IN_PAST_NAMES_MAP = FORM_ELEMENT_FLAG_BIT(2) +}; + +// NOTE: I don't think it's possible to have both ADDED_TO_FORM and +// MAYBE_ORPHAN_FORM_ELEMENT set at the same time, so if it becomes an issue we +// can probably merge them into the same bit. --bz + +ASSERT_NODE_FLAGS_SPACE(HTML_ELEMENT_TYPE_SPECIFIC_BITS_OFFSET + 3); + +#undef FORM_ELEMENT_FLAG_BIT + +/** + * A helper class for form elements that can contain children + */ +class nsGenericHTMLFormElement : public nsGenericHTMLElement { + public: + nsGenericHTMLFormElement( + already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo); + + // nsIContent + void SaveSubtreeState() override; + nsresult BindToTree(BindContext&, nsINode& aParent) override; + void UnbindFromTree(bool aNullParent = true) override; + + /** + * This callback is called by a fieldest on all its elements whenever its + * disabled attribute is changed so the element knows its disabled state + * might have changed. + * + * @note Classes redefining this method should not do any content + * state updates themselves but should just make sure to call into + * nsGenericHTMLFormElement::FieldSetDisabledChanged. + */ + virtual void FieldSetDisabledChanged(bool aNotify); + + void FieldSetFirstLegendChanged(bool aNotify) { UpdateFieldSet(aNotify); } + + /** + * This callback is called by a fieldset on all it's elements when it's being + * destroyed. When called, the elements should check that aFieldset is there + * first parent fieldset and null mFieldset in that case only. + * + * @param aFieldSet The fieldset being removed. + */ + void ForgetFieldSet(nsIContent* aFieldset); + + void ClearForm(bool aRemoveFromForm, bool aUnbindOrDelete); + + /** + * Get the layout history object for a particular piece of content. + * + * @param aRead if true, won't return a layout history state if the + * layout history state is empty. + * @return the history state object + */ + already_AddRefed<nsILayoutHistoryState> GetLayoutHistory(bool aRead); + + // Sets the user-interacted flag in + // https://html.spec.whatwg.org/#user-interacted, if it applies. + virtual void SetUserInteracted(bool aNotify) {} + + protected: + virtual ~nsGenericHTMLFormElement() = default; + + void BeforeSetAttr(int32_t aNamespaceID, nsAtom* aName, + const nsAttrValue* aValue, bool aNotify) override; + + void AfterSetAttr(int32_t aNameSpaceID, nsAtom* aName, + const nsAttrValue* aValue, const nsAttrValue* aOldValue, + nsIPrincipal* aMaybeScriptedPrincipal, + bool aNotify) override; + + virtual void BeforeSetForm(mozilla::dom::HTMLFormElement* aForm, + bool aBindToTree) {} + + virtual void AfterClearForm(bool aUnbindOrDelete) {} + + /** + * Check our disabled content attribute and fieldset's (if it exists) disabled + * state to decide whether our disabled flag should be toggled. + */ + virtual void UpdateDisabledState(bool aNotify); + bool IsReadOnlyInternal() const final; + + virtual void SetFormInternal(mozilla::dom::HTMLFormElement* aForm, + bool aBindToTree) {} + + virtual mozilla::dom::HTMLFormElement* GetFormInternal() const { + return nullptr; + } + + virtual mozilla::dom::HTMLFieldSetElement* GetFieldSetInternal() const { + return nullptr; + } + + virtual void SetFieldSetInternal( + mozilla::dom::HTMLFieldSetElement* aFieldset) {} + + /** + * This method will update the form owner, using @form or looking to a parent. + * + * @param aBindToTree Whether the element is being attached to the tree. + * @param aFormIdElement The element associated with the id in @form. If + * aBindToTree is false, aFormIdElement *must* contain the element associated + * with the id in @form. Otherwise, it *must* be null. + * + * @note Callers of UpdateFormOwner have to be sure the element is in a + * document (GetUncomposedDoc() != nullptr). + */ + virtual void UpdateFormOwner(bool aBindToTree, Element* aFormIdElement); + + /** + * This method will update mFieldset and set it to the first fieldset parent. + */ + void UpdateFieldSet(bool aNotify); + + /** + * Add a form id observer which will observe when the element with the id in + * @form will change. + * + * @return The element associated with the current id in @form (may be null). + */ + Element* AddFormIdObserver(); + + /** + * Remove the form id observer. + */ + void RemoveFormIdObserver(); + + /** + * This method is a a callback for IDTargetObserver (from Document). + * It will be called each time the element associated with the id in @form + * changes. + */ + static bool FormIdUpdated(Element* aOldElement, Element* aNewElement, + void* aData); + + // Returns true if the event should not be handled from GetEventTargetParent + bool IsElementDisabledForEvents(mozilla::WidgetEvent* aEvent, + nsIFrame* aFrame); + + /** + * Returns if the control can be disabled. + */ + virtual bool CanBeDisabled() const { return false; } + + /** + * Returns if the readonly attribute applies. + */ + virtual bool DoesReadOnlyApply() const { return false; } + + /** + * Returns true if the element is a form associated element. + * See https://html.spec.whatwg.org/#form-associated-element. + */ + virtual bool IsFormAssociatedElement() const { return false; } + + /** + * Save to presentation state. The form element will determine whether it + * has anything to save and if so, create an entry in the layout history for + * its pres context. + */ + virtual void SaveState() {} +}; + +class nsGenericHTMLFormControlElement : public nsGenericHTMLFormElement, + public nsIFormControl { + public: + nsGenericHTMLFormControlElement( + already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo, FormControlType); + + NS_DECL_ISUPPORTS_INHERITED + + NS_IMPL_FROMNODE_HELPER(nsGenericHTMLFormControlElement, + IsHTMLFormControlElement()) + + // nsINode + nsINode* GetScopeChainParent() const override; + bool IsHTMLFormControlElement() const final { return true; } + + // nsIContent + IMEState GetDesiredIMEState() override; + + // nsGenericHTMLElement + // autocapitalize attribute support + void GetAutocapitalize(nsAString& aValue) const override; + bool IsHTMLFocusable(bool aWithMouse, bool* aIsFocusable, + int32_t* aTabIndex) override; + + // EventTarget + void GetEventTargetParent(mozilla::EventChainPreVisitor& aVisitor) override; + nsresult PreHandleEvent(mozilla::EventChainVisitor& aVisitor) override; + + // nsIFormControl + mozilla::dom::HTMLFieldSetElement* GetFieldSet() override; + mozilla::dom::HTMLFormElement* GetForm() const override { return mForm; } + void SetForm(mozilla::dom::HTMLFormElement* aForm) override; + void ClearForm(bool aRemoveFromForm, bool aUnbindOrDelete) override; + + protected: + virtual ~nsGenericHTMLFormControlElement(); + + // Element + bool IsLabelable() const override; + + // nsGenericHTMLFormElement + bool CanBeDisabled() const override; + bool DoesReadOnlyApply() const override; + void SetFormInternal(mozilla::dom::HTMLFormElement* aForm, + bool aBindToTree) override; + mozilla::dom::HTMLFormElement* GetFormInternal() const override; + mozilla::dom::HTMLFieldSetElement* GetFieldSetInternal() const override; + void SetFieldSetInternal( + mozilla::dom::HTMLFieldSetElement* aFieldset) override; + bool IsFormAssociatedElement() const override { return true; } + + /** + * Update our required/optional flags to match the given aIsRequired boolean. + */ + void UpdateRequiredState(bool aIsRequired, bool aNotify); + + bool IsAutocapitalizeInheriting() const; + + nsresult SubmitDirnameDir(mozilla::dom::FormData* aFormData); + + /** The form that contains this control */ + mozilla::dom::HTMLFormElement* mForm; + + /* This is a pointer to our closest fieldset parent if any */ + mozilla::dom::HTMLFieldSetElement* mFieldSet; +}; + +enum class PopoverTargetAction : uint8_t { + Toggle, + Show, + Hide, +}; + +class nsGenericHTMLFormControlElementWithState + : public nsGenericHTMLFormControlElement { + public: + nsGenericHTMLFormControlElementWithState( + already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo, + mozilla::dom::FromParser aFromParser, FormControlType); + + bool IsGenericHTMLFormControlElementWithState() const final { return true; } + NS_IMPL_FROMNODE_HELPER(nsGenericHTMLFormControlElementWithState, + IsGenericHTMLFormControlElementWithState()) + + // Element + bool ParseAttribute(int32_t aNamespaceID, nsAtom* aAttribute, + const nsAString& aValue, + nsIPrincipal* aMaybeScriptedPrincipal, + nsAttrValue& aResult) override; + + // PopoverInvokerElement + mozilla::dom::Element* GetPopoverTargetElement() const; + void SetPopoverTargetElement(mozilla::dom::Element*); + void GetPopoverTargetAction(nsAString& aValue) const { + GetHTMLEnumAttr(nsGkAtoms::popovertargetaction, aValue); + } + void SetPopoverTargetAction(const nsAString& aValue) { + SetHTMLAttr(nsGkAtoms::popovertargetaction, aValue); + } + + // InvokerElement + mozilla::dom::Element* GetInvokeTargetElement() const; + void SetInvokeTargetElement(mozilla::dom::Element*); + void GetInvokeAction(nsAString& aValue) const; + nsAtom* GetInvokeAction() const; + void SetInvokeAction(const nsAString& aValue) { + SetHTMLAttr(nsGkAtoms::invokeaction, aValue); + } + + /** + * https://html.spec.whatwg.org/#popover-target-attribute-activation-behavior + */ + MOZ_CAN_RUN_SCRIPT void HandlePopoverTargetAction(); + + MOZ_CAN_RUN_SCRIPT void HandleInvokeTargetAction(); + + /** + * Get the presentation state for a piece of content, or create it if it does + * not exist. Generally used by SaveState(). + */ + mozilla::PresState* GetPrimaryPresState(); + + /** + * Called when we have been cloned and adopted, and the information of the + * node has been changed. + */ + void NodeInfoChanged(Document* aOldDoc) override; + + void GetFormAction(nsString& aValue); + + protected: + /** + * Restore from presentation state. You pass in the presentation state for + * this form control (generated with GenerateStateKey() + "-C") and the form + * control will grab its state from there. + * + * @param aState the pres state to use to restore the control + * @return true if the form control was a checkbox and its + * checked state was restored, false otherwise. + */ + virtual bool RestoreState(mozilla::PresState* aState) { return false; } + + /** + * Restore the state for a form control in response to the element being + * inserted into the document by the parser. Ends up calling RestoreState(). + * + * GenerateStateKey() must already have been called. + * + * @return false if RestoreState() was not called, the return + * value of RestoreState() otherwise. + */ + bool RestoreFormControlState(); + + /* Generates the state key for saving the form state in the session if not + computed already. The result is stored in mStateKey. */ + void GenerateStateKey(); + + int32_t GetParserInsertedControlNumberForStateKey() const override { + return mControlNumber; + } + + /* Used to store the key to that element in the session. Is void until + GenerateStateKey has been used */ + nsCString mStateKey; + + // A number for this form control that is unique within its owner document. + // This is only set to a number for elements inserted into the document by + // the parser from the network. Otherwise, it is -1. + int32_t mControlNumber; +}; + +#define NS_INTERFACE_MAP_ENTRY_IF_TAG(_interface, _tag) \ + NS_INTERFACE_MAP_ENTRY_CONDITIONAL(_interface, \ + mNodeInfo->Equals(nsGkAtoms::_tag)) + +namespace mozilla::dom { + +using HTMLContentCreatorFunction = + nsGenericHTMLElement* (*)(already_AddRefed<mozilla::dom::NodeInfo>&&, + mozilla::dom::FromParser); + +} // namespace mozilla::dom + +/** + * A macro to declare the NS_NewHTMLXXXElement() functions. + */ +#define NS_DECLARE_NS_NEW_HTML_ELEMENT(_elementName) \ + namespace mozilla { \ + namespace dom { \ + class HTML##_elementName##Element; \ + } \ + } \ + nsGenericHTMLElement* NS_NewHTML##_elementName##Element( \ + already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo, \ + mozilla::dom::FromParser aFromParser = mozilla::dom::NOT_FROM_PARSER); + +#define NS_DECLARE_NS_NEW_HTML_ELEMENT_AS_SHARED(_elementName) \ + inline nsGenericHTMLElement* NS_NewHTML##_elementName##Element( \ + already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo, \ + mozilla::dom::FromParser aFromParser = mozilla::dom::NOT_FROM_PARSER) { \ + return NS_NewHTMLSharedElement(std::move(aNodeInfo), aFromParser); \ + } + +/** + * A macro to implement the NS_NewHTMLXXXElement() functions. + */ +#define NS_IMPL_NS_NEW_HTML_ELEMENT(_elementName) \ + nsGenericHTMLElement* NS_NewHTML##_elementName##Element( \ + already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo, \ + mozilla::dom::FromParser aFromParser) { \ + RefPtr<mozilla::dom::NodeInfo> nodeInfo(aNodeInfo); \ + auto* nim = nodeInfo->NodeInfoManager(); \ + MOZ_ASSERT(nim); \ + return new (nim) \ + mozilla::dom::HTML##_elementName##Element(nodeInfo.forget()); \ + } + +#define NS_IMPL_NS_NEW_HTML_ELEMENT_CHECK_PARSER(_elementName) \ + nsGenericHTMLElement* NS_NewHTML##_elementName##Element( \ + already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo, \ + mozilla::dom::FromParser aFromParser) { \ + RefPtr<mozilla::dom::NodeInfo> nodeInfo(aNodeInfo); \ + auto* nim = nodeInfo->NodeInfoManager(); \ + MOZ_ASSERT(nim); \ + return new (nim) mozilla::dom::HTML##_elementName##Element( \ + nodeInfo.forget(), aFromParser); \ + } + +// Here, we expand 'NS_DECLARE_NS_NEW_HTML_ELEMENT()' by hand. +// (Calling the macro directly (with no args) produces compiler warnings.) +nsGenericHTMLElement* NS_NewHTMLElement( + already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo, + mozilla::dom::FromParser aFromParser = mozilla::dom::NOT_FROM_PARSER); + +// Distinct from the above in order to have function pointer that compared +// unequal to a function pointer to the above. +nsGenericHTMLElement* NS_NewCustomElement( + already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo, + mozilla::dom::FromParser aFromParser = mozilla::dom::NOT_FROM_PARSER); + +NS_DECLARE_NS_NEW_HTML_ELEMENT(Shared) +NS_DECLARE_NS_NEW_HTML_ELEMENT(SharedList) + +NS_DECLARE_NS_NEW_HTML_ELEMENT(Anchor) +NS_DECLARE_NS_NEW_HTML_ELEMENT(Area) +NS_DECLARE_NS_NEW_HTML_ELEMENT(Audio) +NS_DECLARE_NS_NEW_HTML_ELEMENT(BR) +NS_DECLARE_NS_NEW_HTML_ELEMENT(Body) +NS_DECLARE_NS_NEW_HTML_ELEMENT(Button) +NS_DECLARE_NS_NEW_HTML_ELEMENT(Canvas) +NS_DECLARE_NS_NEW_HTML_ELEMENT(Content) +NS_DECLARE_NS_NEW_HTML_ELEMENT(Mod) +NS_DECLARE_NS_NEW_HTML_ELEMENT(Data) +NS_DECLARE_NS_NEW_HTML_ELEMENT(DataList) +NS_DECLARE_NS_NEW_HTML_ELEMENT(Details) +NS_DECLARE_NS_NEW_HTML_ELEMENT(Dialog) +NS_DECLARE_NS_NEW_HTML_ELEMENT(Div) +NS_DECLARE_NS_NEW_HTML_ELEMENT(Embed) +NS_DECLARE_NS_NEW_HTML_ELEMENT(FieldSet) +NS_DECLARE_NS_NEW_HTML_ELEMENT(Font) +NS_DECLARE_NS_NEW_HTML_ELEMENT(Form) +NS_DECLARE_NS_NEW_HTML_ELEMENT(Frame) +NS_DECLARE_NS_NEW_HTML_ELEMENT(FrameSet) +NS_DECLARE_NS_NEW_HTML_ELEMENT(HR) +NS_DECLARE_NS_NEW_HTML_ELEMENT_AS_SHARED(Head) +NS_DECLARE_NS_NEW_HTML_ELEMENT(Heading) +NS_DECLARE_NS_NEW_HTML_ELEMENT_AS_SHARED(Html) +NS_DECLARE_NS_NEW_HTML_ELEMENT(IFrame) +NS_DECLARE_NS_NEW_HTML_ELEMENT(Image) +NS_DECLARE_NS_NEW_HTML_ELEMENT(Input) +NS_DECLARE_NS_NEW_HTML_ELEMENT(LI) +NS_DECLARE_NS_NEW_HTML_ELEMENT(Label) +NS_DECLARE_NS_NEW_HTML_ELEMENT(Legend) +NS_DECLARE_NS_NEW_HTML_ELEMENT(Link) +NS_DECLARE_NS_NEW_HTML_ELEMENT(Marquee) +NS_DECLARE_NS_NEW_HTML_ELEMENT(Map) +NS_DECLARE_NS_NEW_HTML_ELEMENT(Menu) +NS_DECLARE_NS_NEW_HTML_ELEMENT(Meta) +NS_DECLARE_NS_NEW_HTML_ELEMENT(Meter) +NS_DECLARE_NS_NEW_HTML_ELEMENT(Object) +NS_DECLARE_NS_NEW_HTML_ELEMENT(OptGroup) +NS_DECLARE_NS_NEW_HTML_ELEMENT(Option) +NS_DECLARE_NS_NEW_HTML_ELEMENT(Output) +NS_DECLARE_NS_NEW_HTML_ELEMENT(Paragraph) +NS_DECLARE_NS_NEW_HTML_ELEMENT(Picture) +NS_DECLARE_NS_NEW_HTML_ELEMENT(Pre) +NS_DECLARE_NS_NEW_HTML_ELEMENT(Progress) +NS_DECLARE_NS_NEW_HTML_ELEMENT(Script) +NS_DECLARE_NS_NEW_HTML_ELEMENT(Select) +NS_DECLARE_NS_NEW_HTML_ELEMENT(Slot) +NS_DECLARE_NS_NEW_HTML_ELEMENT(Source) +NS_DECLARE_NS_NEW_HTML_ELEMENT(Span) +NS_DECLARE_NS_NEW_HTML_ELEMENT(Style) +NS_DECLARE_NS_NEW_HTML_ELEMENT(Summary) +NS_DECLARE_NS_NEW_HTML_ELEMENT(TableCaption) +NS_DECLARE_NS_NEW_HTML_ELEMENT(TableCell) +NS_DECLARE_NS_NEW_HTML_ELEMENT(TableCol) +NS_DECLARE_NS_NEW_HTML_ELEMENT(Table) +NS_DECLARE_NS_NEW_HTML_ELEMENT(TableRow) +NS_DECLARE_NS_NEW_HTML_ELEMENT(TableSection) +NS_DECLARE_NS_NEW_HTML_ELEMENT(Tbody) +NS_DECLARE_NS_NEW_HTML_ELEMENT(Template) +NS_DECLARE_NS_NEW_HTML_ELEMENT(TextArea) +NS_DECLARE_NS_NEW_HTML_ELEMENT(Tfoot) +NS_DECLARE_NS_NEW_HTML_ELEMENT(Thead) +NS_DECLARE_NS_NEW_HTML_ELEMENT(Time) +NS_DECLARE_NS_NEW_HTML_ELEMENT(Title) +NS_DECLARE_NS_NEW_HTML_ELEMENT(Track) +NS_DECLARE_NS_NEW_HTML_ELEMENT(Unknown) +NS_DECLARE_NS_NEW_HTML_ELEMENT(Video) + +#endif /* nsGenericHTMLElement_h___ */ |