/* -*- 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 DOM_SVG_SVGELEMENT_H_ #define DOM_SVG_SVGELEMENT_H_ /* SVGElement is the base class for all SVG content elements. It implements all the common DOM interfaces and handles attributes. */ #include "mozilla/Attributes.h" #include "mozilla/RefPtr.h" #include "mozilla/SVGAnimatedClass.h" #include "mozilla/SVGContentUtils.h" #include "mozilla/dom/DOMRect.h" #include "mozilla/dom/Element.h" #include "mozilla/gfx/MatrixFwd.h" #include "mozilla/UniquePtr.h" #include "nsChangeHint.h" #include "nsCycleCollectionParticipant.h" #include "nsError.h" #include "nsISupportsImpl.h" #include "nsStyledElement.h" #include "gfxMatrix.h" // {70db954d-e452-4be3-83aa-f54a51cf7890} #define MOZILLA_SVGELEMENT_IID \ { \ 0x70db954d, 0xe452, 0x4be3, { \ 0x82, 0xaa, 0xf5, 0x4a, 0x51, 0xcf, 0x78, 0x90 \ } \ } nsresult NS_NewSVGElement(mozilla::dom::Element** aResult, already_AddRefed&& aNodeInfo); class mozAutoDocUpdate; namespace mozilla { class DeclarationBlock; class SVGAnimatedBoolean; class SVGAnimatedEnumeration; class SVGAnimatedInteger; class SVGAnimatedIntegerPair; class SVGAnimatedLength; class SVGAnimatedLengthList; class SVGAnimatedNumber; class SVGAnimatedNumberList; class SVGAnimatedNumberPair; class SVGAnimatedOrient; class SVGAnimatedPathSegList; class SVGAnimatedPointList; class SVGAnimatedString; class SVGAnimatedPreserveAspectRatio; class SVGAnimatedTransformList; class SVGAnimatedViewBox; class SVGNumberList; class SVGStringList; class SVGUserUnitList; struct SVGEnumMapping; namespace dom { class DOMSVGStringList; class SVGSVGElement; class SVGViewportElement; using SVGElementBase = nsStyledElement; class SVGElement : public SVGElementBase // nsIContent { protected: explicit SVGElement(already_AddRefed&& aNodeInfo); friend nsresult( ::NS_NewSVGElement(mozilla::dom::Element** aResult, already_AddRefed&& aNodeInfo)); nsresult Init(); virtual ~SVGElement(); public: virtual nsresult Clone(mozilla::dom::NodeInfo*, nsINode** aResult) const MOZ_MUST_OVERRIDE override; // From Element nsresult CopyInnerTo(mozilla::dom::Element* aDest); NS_DECLARE_STATIC_IID_ACCESSOR(MOZILLA_SVGELEMENT_IID) // nsISupports NS_INLINE_DECL_REFCOUNTING_INHERITED(SVGElement, SVGElementBase) NS_DECL_ADDSIZEOFEXCLUDINGTHIS NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr) override; void DidAnimateClass(); void SetNonce(const nsAString& aNonce) { SetProperty(nsGkAtoms::nonce, new nsString(aNonce), nsINode::DeleteProperty); } void RemoveNonce() { RemoveProperty(nsGkAtoms::nonce); } void GetNonce(nsAString& aNonce) const { nsString* cspNonce = static_cast(GetProperty(nsGkAtoms::nonce)); if (cspNonce) { aNonce = *cspNonce; } } // nsIContent interface methods virtual nsresult BindToTree(BindContext&, nsINode& aParent) override; virtual nsChangeHint GetAttributeChangeHint(const nsAtom* aAttribute, int32_t aModType) const override; virtual bool IsNodeOfType(uint32_t aFlags) const override; /** * We override the default to unschedule computation of Servo declaration * blocks when adopted across documents. */ virtual void NodeInfoChanged(Document* aOldDoc) override; NS_IMETHOD_(bool) IsAttributeMapped(const nsAtom* aAttribute) const override; static const MappedAttributeEntry sFillStrokeMap[]; static const MappedAttributeEntry sGraphicsMap[]; static const MappedAttributeEntry sTextContentElementsMap[]; static const MappedAttributeEntry sFontSpecificationMap[]; static const MappedAttributeEntry sGradientStopMap[]; static const MappedAttributeEntry sViewportsMap[]; static const MappedAttributeEntry sMarkersMap[]; static const MappedAttributeEntry sColorMap[]; static const MappedAttributeEntry sFiltersMap[]; static const MappedAttributeEntry sFEFloodMap[]; static const MappedAttributeEntry sLightingEffectsMap[]; static const MappedAttributeEntry sMaskMap[]; NS_IMPL_FROMNODE(SVGElement, kNameSpaceID_SVG) // Gets the element that establishes the rectangular viewport against which // we should resolve percentage lengths (our "coordinate context"). Returns // nullptr for outer or SVG without an parent (invalid SVG). mozilla::dom::SVGViewportElement* GetCtx() const; /** * Returns aMatrix pre-multiplied by (explicit or implicit) transforms that * are introduced by attributes on this element. * * If aWhich is eAllTransforms, then all the transforms from the coordinate * space established by this element for its children to the coordinate * space established by this element's parent element for this element, are * included. * * If aWhich is eUserSpaceToParent, then only the transforms from this * element's userspace to the coordinate space established by its parent is * included. This includes any transforms introduced by the 'transform' * attribute, transform animations and animateMotion, but not any offsets * due to e.g. 'x'/'y' attributes, or any transform due to a 'viewBox' * attribute. (SVG userspace is defined to be the coordinate space in which * coordinates on an element apply.) * * If aWhich is eChildToUserSpace, then only the transforms from the * coordinate space established by this element for its childre to this * elements userspace are included. This includes any offsets due to e.g. * 'x'/'y' attributes, and any transform due to a 'viewBox' attribute, but * does not include any transforms due to the 'transform' attribute. */ virtual gfxMatrix PrependLocalTransformsTo( const gfxMatrix& aMatrix, SVGTransformTypes aWhich = eAllTransforms) const; // Setter for to set the current transformation // Only visible for SVGGraphicElement, so it's a no-op here, and that // subclass has the useful implementation. virtual void SetAnimateMotionTransform( const mozilla::gfx::Matrix* aMatrix) { /*no-op*/ } virtual const mozilla::gfx::Matrix* GetAnimateMotionTransform() const { return nullptr; } bool IsStringAnimatable(uint8_t aAttrEnum) { return GetStringInfo().mStringInfo[aAttrEnum].mIsAnimatable; } bool NumberAttrAllowsPercentage(uint8_t aAttrEnum) { return GetNumberInfo().mNumberInfo[aAttrEnum].mPercentagesAllowed; } virtual bool HasValidDimensions() const { return true; } void SetLength(nsAtom* aName, const SVGAnimatedLength& aLength); enum class ValToUse { Base, Anim }; static bool UpdateDeclarationBlockFromLength(DeclarationBlock& aBlock, nsCSSPropertyID aPropId, const SVGAnimatedLength& aLength, ValToUse aValToUse); nsAttrValue WillChangeLength(uint8_t aAttrEnum, const mozAutoDocUpdate& aProofOfUpdate); nsAttrValue WillChangeNumberPair(uint8_t aAttrEnum); nsAttrValue WillChangeIntegerPair(uint8_t aAttrEnum, const mozAutoDocUpdate& aProofOfUpdate); nsAttrValue WillChangeOrient(const mozAutoDocUpdate& aProofOfUpdate); nsAttrValue WillChangeViewBox(const mozAutoDocUpdate& aProofOfUpdate); nsAttrValue WillChangePreserveAspectRatio( const mozAutoDocUpdate& aProofOfUpdate); nsAttrValue WillChangeNumberList(uint8_t aAttrEnum, const mozAutoDocUpdate& aProofOfUpdate); nsAttrValue WillChangeLengthList(uint8_t aAttrEnum, const mozAutoDocUpdate& aProofOfUpdate); nsAttrValue WillChangePointList(const mozAutoDocUpdate& aProofOfUpdate); nsAttrValue WillChangePathSegList(const mozAutoDocUpdate& aProofOfUpdate); nsAttrValue WillChangeTransformList(const mozAutoDocUpdate& aProofOfUpdate); nsAttrValue WillChangeStringList(bool aIsConditionalProcessingAttribute, uint8_t aAttrEnum, const mozAutoDocUpdate& aProofOfUpdate); void DidChangeLength(uint8_t aAttrEnum, const nsAttrValue& aEmptyOrOldValue, const mozAutoDocUpdate& aProofOfUpdate); void DidChangeNumber(uint8_t aAttrEnum); void DidChangeNumberPair(uint8_t aAttrEnum, const nsAttrValue& aEmptyOrOldValue); void DidChangeInteger(uint8_t aAttrEnum); void DidChangeIntegerPair(uint8_t aAttrEnum, const nsAttrValue& aEmptyOrOldValue, const mozAutoDocUpdate& aProofOfUpdate); void DidChangeBoolean(uint8_t aAttrEnum); void DidChangeEnum(uint8_t aAttrEnum); void DidChangeOrient(const nsAttrValue& aEmptyOrOldValue, const mozAutoDocUpdate& aProofOfUpdate); void DidChangeViewBox(const nsAttrValue& aEmptyOrOldValue, const mozAutoDocUpdate& aProofOfUpdate); void DidChangePreserveAspectRatio(const nsAttrValue& aEmptyOrOldValue, const mozAutoDocUpdate& aProofOfUpdate); void DidChangeNumberList(uint8_t aAttrEnum, const nsAttrValue& aEmptyOrOldValue, const mozAutoDocUpdate& aProofOfUpdate); void DidChangeLengthList(uint8_t aAttrEnum, const nsAttrValue& aEmptyOrOldValue, const mozAutoDocUpdate& aProofOfUpdate); void DidChangePointList(const nsAttrValue& aEmptyOrOldValue, const mozAutoDocUpdate& aProofOfUpdate); void DidChangePathSegList(const nsAttrValue& aEmptyOrOldValue, const mozAutoDocUpdate& aProofOfUpdate); void DidChangeTransformList(const nsAttrValue& aEmptyOrOldValue, const mozAutoDocUpdate& aProofOfUpdate); void DidChangeString(uint8_t aAttrEnum) {} void DidChangeStringList(bool aIsConditionalProcessingAttribute, uint8_t aAttrEnum, const nsAttrValue& aEmptyOrOldValue, const mozAutoDocUpdate& aProofOfUpdate); void DidAnimateLength(uint8_t aAttrEnum); void DidAnimateNumber(uint8_t aAttrEnum); void DidAnimateNumberPair(uint8_t aAttrEnum); void DidAnimateInteger(uint8_t aAttrEnum); void DidAnimateIntegerPair(uint8_t aAttrEnum); void DidAnimateBoolean(uint8_t aAttrEnum); void DidAnimateEnum(uint8_t aAttrEnum); void DidAnimateOrient(); void DidAnimateViewBox(); void DidAnimatePreserveAspectRatio(); void DidAnimateNumberList(uint8_t aAttrEnum); void DidAnimateLengthList(uint8_t aAttrEnum); void DidAnimatePointList(); void DidAnimatePathSegList(); void DidAnimateTransformList(int32_t aModType); void DidAnimateString(uint8_t aAttrEnum); enum { /** * Flag to indicate to GetAnimatedXxx() methods that the object being * requested should be allocated if it hasn't already been allocated, and * that the method should not return null. Only applicable to methods that * need to allocate the object that they return. */ DO_ALLOCATE = 0x1 }; SVGAnimatedLength* GetAnimatedLength(uint8_t aAttrEnum); SVGAnimatedLength* GetAnimatedLength(const nsAtom* aAttrName); void GetAnimatedLengthValues(float* aFirst, ...); void GetAnimatedNumberValues(float* aFirst, ...); void GetAnimatedIntegerValues(int32_t* aFirst, ...); SVGAnimatedNumberList* GetAnimatedNumberList(uint8_t aAttrEnum); SVGAnimatedNumberList* GetAnimatedNumberList(nsAtom* aAttrName); void GetAnimatedLengthListValues(SVGUserUnitList* aFirst, ...); SVGAnimatedLengthList* GetAnimatedLengthList(uint8_t aAttrEnum); virtual SVGAnimatedPointList* GetAnimatedPointList() { return nullptr; } virtual SVGAnimatedPathSegList* GetAnimPathSegList() { // DOM interface 'SVGAnimatedPathData' (*inherited* by SVGPathElement) // has a member called 'animatedPathSegList' member, so we have a shorter // name so we don't get hidden by the GetAnimatedPathSegList declared by // NS_DECL_NSIDOMSVGANIMATEDPATHDATA. return nullptr; } /** * Get the SVGAnimatedTransformList for this element. * * Despite the fact that animated transform lists are used for a variety of * attributes, no SVG element uses more than one. * * It's relatively uncommon for elements to have their transform attribute * set, so to save memory the SVGAnimatedTransformList is not allocated * until the attribute is set/animated or its DOM wrapper is created. Callers * that require the SVGAnimatedTransformList to be allocated and for this * method to return non-null must pass the DO_ALLOCATE flag. */ virtual SVGAnimatedTransformList* GetAnimatedTransformList( uint32_t aFlags = 0) { return nullptr; } mozilla::UniquePtr GetAnimatedAttr(int32_t aNamespaceID, nsAtom* aName) override; void AnimationNeedsResample(); void FlushAnimations(); virtual void RecompileScriptEventListeners() override; void GetStringBaseValue(uint8_t aAttrEnum, nsAString& aResult) const; void SetStringBaseValue(uint8_t aAttrEnum, const nsAString& aValue); virtual nsStaticAtom* GetPointListAttrName() const { return nullptr; } virtual nsStaticAtom* GetPathDataAttrName() const { return nullptr; } virtual nsStaticAtom* GetTransformListAttrName() const { return nullptr; } const nsAttrValue* GetAnimatedClassName() const { if (!mClassAttribute.IsAnimated()) { return nullptr; } return mClassAnimAttr.get(); } virtual void ClearAnyCachedPath() {} virtual bool IsTransformable() { return false; } // WebIDL mozilla::dom::SVGSVGElement* GetOwnerSVGElement(); SVGElement* GetViewportElement(); already_AddRefed ClassName(); void UpdateContentDeclarationBlock(); const mozilla::DeclarationBlock* GetContentDeclarationBlock() const; protected: virtual JSObject* WrapNode(JSContext* cx, JS::Handle aGivenProto) override; // We define BeforeSetAttr here and mark it final to ensure it is NOT used // by SVG elements. // This is because we're not currently passing the correct value for aValue to // BeforeSetAttr since it would involve allocating extra SVG value types. // See the comment in SVGElement::WillChangeValue. nsresult BeforeSetAttr(int32_t aNamespaceID, nsAtom* aName, const nsAttrValueOrString* aValue, bool aNotify) final; virtual nsresult AfterSetAttr(int32_t aNamespaceID, nsAtom* aName, const nsAttrValue* aValue, const nsAttrValue* aOldValue, nsIPrincipal* aSubjectPrincipal, bool aNotify) override; virtual bool ParseAttribute(int32_t aNamespaceID, nsAtom* aAttribute, const nsAString& aValue, nsIPrincipal* aMaybeScriptedPrincipal, nsAttrValue& aResult) override; static nsresult ReportAttributeParseFailure(Document* aDocument, nsAtom* aAttribute, const nsAString& aValue); nsAttrValue WillChangeValue(nsAtom* aName, const mozAutoDocUpdate& aProofOfUpdate); // aNewValue is set to the old value. This value may be invalid if // !StoresOwnData. void DidChangeValue(nsAtom* aName, const nsAttrValue& aEmptyOrOldValue, nsAttrValue& aNewValue, const mozAutoDocUpdate& aProofOfUpdate); void MaybeSerializeAttrBeforeRemoval(nsAtom* aName, bool aNotify); nsAtom* GetEventNameForAttr(nsAtom* aAttr); struct LengthInfo { nsStaticAtom* const mName; const float mDefaultValue; const uint8_t mDefaultUnitType; const uint8_t mCtxType; }; struct LengthAttributesInfo { SVGAnimatedLength* const mLengths; const LengthInfo* const mLengthInfo; const uint32_t mLengthCount; LengthAttributesInfo(SVGAnimatedLength* aLengths, LengthInfo* aLengthInfo, uint32_t aLengthCount) : mLengths(aLengths), mLengthInfo(aLengthInfo), mLengthCount(aLengthCount) {} void Reset(uint8_t aAttrEnum); }; struct NumberInfo { nsStaticAtom* const mName; const float mDefaultValue; const bool mPercentagesAllowed; }; struct NumberAttributesInfo { SVGAnimatedNumber* const mNumbers; const NumberInfo* const mNumberInfo; const uint32_t mNumberCount; NumberAttributesInfo(SVGAnimatedNumber* aNumbers, NumberInfo* aNumberInfo, uint32_t aNumberCount) : mNumbers(aNumbers), mNumberInfo(aNumberInfo), mNumberCount(aNumberCount) {} void Reset(uint8_t aAttrEnum); }; struct NumberPairInfo { nsStaticAtom* const mName; const float mDefaultValue1; const float mDefaultValue2; }; struct NumberPairAttributesInfo { SVGAnimatedNumberPair* const mNumberPairs; const NumberPairInfo* const mNumberPairInfo; const uint32_t mNumberPairCount; NumberPairAttributesInfo(SVGAnimatedNumberPair* aNumberPairs, NumberPairInfo* aNumberPairInfo, uint32_t aNumberPairCount) : mNumberPairs(aNumberPairs), mNumberPairInfo(aNumberPairInfo), mNumberPairCount(aNumberPairCount) {} void Reset(uint8_t aAttrEnum); }; struct IntegerInfo { nsStaticAtom* const mName; const int32_t mDefaultValue; }; struct IntegerAttributesInfo { SVGAnimatedInteger* const mIntegers; const IntegerInfo* const mIntegerInfo; const uint32_t mIntegerCount; IntegerAttributesInfo(SVGAnimatedInteger* aIntegers, IntegerInfo* aIntegerInfo, uint32_t aIntegerCount) : mIntegers(aIntegers), mIntegerInfo(aIntegerInfo), mIntegerCount(aIntegerCount) {} void Reset(uint8_t aAttrEnum); }; struct IntegerPairInfo { nsStaticAtom* const mName; const int32_t mDefaultValue1; const int32_t mDefaultValue2; }; struct IntegerPairAttributesInfo { SVGAnimatedIntegerPair* const mIntegerPairs; const IntegerPairInfo* const mIntegerPairInfo; const uint32_t mIntegerPairCount; IntegerPairAttributesInfo(SVGAnimatedIntegerPair* aIntegerPairs, IntegerPairInfo* aIntegerPairInfo, uint32_t aIntegerPairCount) : mIntegerPairs(aIntegerPairs), mIntegerPairInfo(aIntegerPairInfo), mIntegerPairCount(aIntegerPairCount) {} void Reset(uint8_t aAttrEnum); }; struct BooleanInfo { nsStaticAtom* const mName; const bool mDefaultValue; }; struct BooleanAttributesInfo { SVGAnimatedBoolean* const mBooleans; const BooleanInfo* const mBooleanInfo; const uint32_t mBooleanCount; BooleanAttributesInfo(SVGAnimatedBoolean* aBooleans, BooleanInfo* aBooleanInfo, uint32_t aBooleanCount) : mBooleans(aBooleans), mBooleanInfo(aBooleanInfo), mBooleanCount(aBooleanCount) {} void Reset(uint8_t aAttrEnum); }; friend class mozilla::SVGAnimatedEnumeration; struct EnumInfo { nsStaticAtom* const mName; const SVGEnumMapping* const mMapping; const uint16_t mDefaultValue; }; struct EnumAttributesInfo { SVGAnimatedEnumeration* const mEnums; const EnumInfo* const mEnumInfo; const uint32_t mEnumCount; EnumAttributesInfo(SVGAnimatedEnumeration* aEnums, EnumInfo* aEnumInfo, uint32_t aEnumCount) : mEnums(aEnums), mEnumInfo(aEnumInfo), mEnumCount(aEnumCount) {} void Reset(uint8_t aAttrEnum); void SetUnknownValue(uint8_t aAttrEnum); }; struct NumberListInfo { nsStaticAtom* const mName; }; struct NumberListAttributesInfo { SVGAnimatedNumberList* const mNumberLists; const NumberListInfo* const mNumberListInfo; const uint32_t mNumberListCount; NumberListAttributesInfo(SVGAnimatedNumberList* aNumberLists, NumberListInfo* aNumberListInfo, uint32_t aNumberListCount) : mNumberLists(aNumberLists), mNumberListInfo(aNumberListInfo), mNumberListCount(aNumberListCount) {} void Reset(uint8_t aAttrEnum); }; struct LengthListInfo { nsStaticAtom* const mName; const uint8_t mAxis; /** * Flag to indicate whether appending zeros to the end of the list would * change the rendering of the SVG for the attribute in question. For x and * y on the element this is true, but for dx and dy on this * is false. This flag is fed down to SVGLengthListSMILType so it can * determine if it can sensibly animate from-to lists of different lengths, * which is desirable in the case of dx and dy. */ const bool mCouldZeroPadList; }; struct LengthListAttributesInfo { SVGAnimatedLengthList* const mLengthLists; const LengthListInfo* const mLengthListInfo; const uint32_t mLengthListCount; LengthListAttributesInfo(SVGAnimatedLengthList* aLengthLists, LengthListInfo* aLengthListInfo, uint32_t aLengthListCount) : mLengthLists(aLengthLists), mLengthListInfo(aLengthListInfo), mLengthListCount(aLengthListCount) {} void Reset(uint8_t aAttrEnum); }; struct StringInfo { nsStaticAtom* const mName; const int32_t mNamespaceID; const bool mIsAnimatable; }; struct StringAttributesInfo { SVGAnimatedString* const mStrings; const StringInfo* const mStringInfo; const uint32_t mStringCount; StringAttributesInfo(SVGAnimatedString* aStrings, StringInfo* aStringInfo, uint32_t aStringCount) : mStrings(aStrings), mStringInfo(aStringInfo), mStringCount(aStringCount) {} void Reset(uint8_t aAttrEnum); }; friend class DOMSVGStringList; struct StringListInfo { nsStaticAtom* const mName; }; struct StringListAttributesInfo { SVGStringList* const mStringLists; const StringListInfo* const mStringListInfo; const uint32_t mStringListCount; StringListAttributesInfo(SVGStringList* aStringLists, StringListInfo* aStringListInfo, uint32_t aStringListCount) : mStringLists(aStringLists), mStringListInfo(aStringListInfo), mStringListCount(aStringListCount) {} void Reset(uint8_t aAttrEnum); }; virtual LengthAttributesInfo GetLengthInfo(); virtual NumberAttributesInfo GetNumberInfo(); virtual NumberPairAttributesInfo GetNumberPairInfo(); virtual IntegerAttributesInfo GetIntegerInfo(); virtual IntegerPairAttributesInfo GetIntegerPairInfo(); virtual BooleanAttributesInfo GetBooleanInfo(); virtual EnumAttributesInfo GetEnumInfo(); // We assume all orients, viewboxes and preserveAspectRatios are alike // so we don't need to wrap the class virtual SVGAnimatedOrient* GetAnimatedOrient(); virtual SVGAnimatedPreserveAspectRatio* GetAnimatedPreserveAspectRatio(); virtual SVGAnimatedViewBox* GetAnimatedViewBox(); virtual NumberListAttributesInfo GetNumberListInfo(); virtual LengthListAttributesInfo GetLengthListInfo(); virtual StringAttributesInfo GetStringInfo(); virtual StringListAttributesInfo GetStringListInfo(); static SVGEnumMapping sSVGUnitTypesMap[]; private: void UnsetAttrInternal(int32_t aNameSpaceID, nsAtom* aName, bool aNotify); SVGAnimatedClass mClassAttribute; UniquePtr mClassAnimAttr; RefPtr mContentDeclarationBlock; }; NS_DEFINE_STATIC_IID_ACCESSOR(SVGElement, MOZILLA_SVGELEMENT_IID) /** * A macro to implement the NS_NewSVGXXXElement() functions. */ #define NS_IMPL_NS_NEW_SVG_ELEMENT(_elementName) \ nsresult NS_NewSVG##_elementName##Element( \ nsIContent** aResult, \ already_AddRefed&& aNodeInfo) { \ RefPtr nodeInfo(aNodeInfo); \ auto* nim = nodeInfo->NodeInfoManager(); \ RefPtr it = \ new (nim) mozilla::dom::SVG##_elementName##Element(nodeInfo.forget()); \ \ nsresult rv = it->Init(); \ \ if (NS_FAILED(rv)) { \ return rv; \ } \ \ it.forget(aResult); \ \ return rv; \ } #define NS_IMPL_NS_NEW_SVG_ELEMENT_CHECK_PARSER(_elementName) \ nsresult NS_NewSVG##_elementName##Element( \ nsIContent** aResult, \ already_AddRefed&& aNodeInfo, \ mozilla::dom::FromParser aFromParser) { \ RefPtr nodeInfo(aNodeInfo); \ auto* nim = nodeInfo->NodeInfoManager(); \ RefPtr it = \ new (nim) mozilla::dom::SVG##_elementName##Element(nodeInfo.forget(), \ aFromParser); \ \ nsresult rv = it->Init(); \ \ if (NS_FAILED(rv)) { \ return rv; \ } \ \ it.forget(aResult); \ \ return rv; \ } // No unlinking, we'd need to null out the value pointer (the object it // points to is held by the element) and null-check it everywhere. #define NS_SVG_VAL_IMPL_CYCLE_COLLECTION(_val, _element) \ NS_IMPL_CYCLE_COLLECTION_CLASS(_val) \ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(_val) \ NS_IMPL_CYCLE_COLLECTION_TRAVERSE(_element) \ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END \ NS_IMPL_CYCLE_COLLECTION_UNLINK_0(_val) #define NS_SVG_VAL_IMPL_CYCLE_COLLECTION_WRAPPERCACHED(_val, _element) \ NS_IMPL_CYCLE_COLLECTION_CLASS(_val) \ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(_val) \ NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER \ NS_IMPL_CYCLE_COLLECTION_UNLINK_END \ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(_val) \ NS_IMPL_CYCLE_COLLECTION_TRAVERSE(_element) \ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END \ NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(_val) \ NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER \ NS_IMPL_CYCLE_COLLECTION_TRACE_END } // namespace dom } // namespace mozilla #endif // DOM_SVG_SVGELEMENT_H_