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/. */ 6 7 /* 8 * Base class for DOM Core's nsIDOMComment, nsIDOMDocumentType, nsIDOMText, 9 * CDATASection, and nsIDOMProcessingInstruction nodes. 10 */ 11 12 #ifndef nsGenericDOMDataNode_h___ 13 #define nsGenericDOMDataNode_h___ 14 15 #include "mozilla/Attributes.h" 16 #include "nsIContent.h" 17 18 #include "nsTextFragment.h" 19 #include "nsError.h" 20 #include "mozilla/dom/Element.h" 21 #include "nsCycleCollectionParticipant.h" 22 23 #include "nsISMILAttr.h" 24 #include "mozilla/dom/ShadowRoot.h" 25 26 class nsIDocument; 27 class nsIDOMText; 28 29 namespace mozilla { 30 namespace dom { 31 class HTMLSlotElement; 32 } // namespace dom 33 } // namespace mozilla 34 35 #define DATA_NODE_FLAG_BIT(n_) \ 36 NODE_FLAG_BIT(NODE_TYPE_SPECIFIC_BITS_OFFSET + (n_)) 37 38 // Data node specific flags 39 enum { 40 // This bit is set to indicate that if the text node changes to 41 // non-whitespace, we may need to create a frame for it. This bit must 42 // not be set on nodes that already have a frame. 43 NS_CREATE_FRAME_IF_NON_WHITESPACE = DATA_NODE_FLAG_BIT(0), 44 45 // This bit is set to indicate that if the text node changes to 46 // whitespace, we may need to reframe it (or its ancestors). 47 NS_REFRAME_IF_WHITESPACE = DATA_NODE_FLAG_BIT(1), 48 49 // This bit is set to indicate that we have a cached 50 // TextIsOnlyWhitespace value 51 NS_CACHED_TEXT_IS_ONLY_WHITESPACE = DATA_NODE_FLAG_BIT(2), 52 53 // This bit is only meaningful if the NS_CACHED_TEXT_IS_ONLY_WHITESPACE 54 // bit is set, and if so it indicates whether we're only whitespace or 55 // not. 56 NS_TEXT_IS_ONLY_WHITESPACE = DATA_NODE_FLAG_BIT(3), 57 58 // This bit is set if there is a NewlineProperty attached to the node 59 // (used by nsTextFrame). 60 NS_HAS_NEWLINE_PROPERTY = DATA_NODE_FLAG_BIT(4), 61 62 // This bit is set if there is a FlowLengthProperty attached to the node 63 // (used by nsTextFrame). 64 NS_HAS_FLOWLENGTH_PROPERTY = DATA_NODE_FLAG_BIT(5), 65 66 // This bit is set if the node may be modified frequently. This is typically 67 // specified if the instance is in <input> or <textarea>. 68 NS_MAYBE_MODIFIED_FREQUENTLY = DATA_NODE_FLAG_BIT(6), 69 }; 70 71 // Make sure we have enough space for those bits 72 ASSERT_NODE_FLAGS_SPACE(NODE_TYPE_SPECIFIC_BITS_OFFSET + 7); 73 74 #undef DATA_NODE_FLAG_BIT 75 76 class nsGenericDOMDataNode : public nsIContent { 77 public: 78 NS_DECL_CYCLE_COLLECTING_ISUPPORTS 79 80 NS_DECL_ADDSIZEOFEXCLUDINGTHIS 81 82 explicit nsGenericDOMDataNode( 83 already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo); 84 explicit nsGenericDOMDataNode( 85 already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo); 86 MarkAsMaybeModifiedFrequently()87 void MarkAsMaybeModifiedFrequently() { 88 SetFlags(NS_MAYBE_MODIFIED_FREQUENTLY); 89 } 90 91 virtual void GetNodeValueInternal(nsAString& aNodeValue) override; 92 virtual void SetNodeValueInternal(const nsAString& aNodeValue, 93 mozilla::ErrorResult& aError) override; 94 95 // Implementation for nsIDOMCharacterData 96 nsresult GetData(nsAString& aData) const; 97 nsresult SetData(const nsAString& aData); 98 nsresult GetLength(uint32_t* aLength); 99 nsresult SubstringData(uint32_t aOffset, uint32_t aCount, nsAString& aReturn); 100 nsresult AppendData(const nsAString& aArg); 101 nsresult InsertData(uint32_t aOffset, const nsAString& aArg); 102 nsresult DeleteData(uint32_t aOffset, uint32_t aCount); 103 nsresult ReplaceData(uint32_t aOffset, uint32_t aCount, 104 const nsAString& aArg); 105 106 // nsINode methods 107 virtual uint32_t GetChildCount() const override; 108 virtual nsIContent* GetChildAt_Deprecated(uint32_t aIndex) const override; 109 virtual int32_t ComputeIndexOf(const nsINode* aPossibleChild) const override; 110 virtual nsresult InsertChildBefore(nsIContent* aKid, nsIContent* aBeforeThis, 111 bool aNotify) override; 112 virtual nsresult InsertChildAt_Deprecated(nsIContent* aKid, uint32_t aIndex, 113 bool aNotify) override; 114 virtual void RemoveChildAt_Deprecated(uint32_t aIndex, bool aNotify) override; 115 virtual void RemoveChildNode(nsIContent* aKid, bool aNotify) override; GetTextContentInternal(nsAString & aTextContent,mozilla::OOMReporter & aError)116 virtual void GetTextContentInternal(nsAString& aTextContent, 117 mozilla::OOMReporter& aError) override { 118 GetNodeValue(aTextContent); 119 } SetTextContentInternal(const nsAString & aTextContent,nsIPrincipal * aSubjectPrincipal,mozilla::ErrorResult & aError)120 virtual void SetTextContentInternal(const nsAString& aTextContent, 121 nsIPrincipal* aSubjectPrincipal, 122 mozilla::ErrorResult& aError) override { 123 // Batch possible DOMSubtreeModified events. 124 mozAutoSubtreeModified subtree(OwnerDoc(), nullptr); 125 return SetNodeValue(aTextContent, aError); 126 } 127 128 // Implementation for nsIContent 129 virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent, 130 nsIContent* aBindingParent, 131 bool aCompileEventHandlers) override; 132 virtual void UnbindFromTree(bool aDeep = true, 133 bool aNullParent = true) override; 134 135 virtual already_AddRefed<nsINodeList> GetChildren(uint32_t aFilter) override; 136 137 virtual const nsTextFragment* GetText() override; 138 virtual uint32_t TextLength() const override; 139 virtual nsresult SetText(const char16_t* aBuffer, uint32_t aLength, 140 bool aNotify) override; 141 // Need to implement this here too to avoid hiding. SetText(const nsAString & aStr,bool aNotify)142 nsresult SetText(const nsAString& aStr, bool aNotify) { 143 return SetText(aStr.BeginReading(), aStr.Length(), aNotify); 144 } 145 virtual nsresult AppendText(const char16_t* aBuffer, uint32_t aLength, 146 bool aNotify) override; 147 virtual bool TextIsOnlyWhitespace() override; 148 bool ThreadSafeTextIsOnlyWhitespace() const final; 149 virtual bool HasTextForTranslation() override; 150 virtual void AppendTextTo(nsAString& aResult) override; 151 MOZ_MUST_USE 152 virtual bool AppendTextTo(nsAString& aResult, 153 const mozilla::fallible_t&) override; 154 virtual void SaveSubtreeState() override; 155 156 #ifdef DEBUG 157 virtual void List(FILE* out, int32_t aIndent) const override; 158 virtual void DumpContent(FILE* out, int32_t aIndent, 159 bool aDumpAll) const override; 160 #endif 161 162 virtual nsXBLBinding* DoGetXBLBinding() const override; 163 virtual bool IsNodeOfType(uint32_t aFlags) const override; 164 virtual bool IsLink(nsIURI** aURI) const override; 165 Clone(mozilla::dom::NodeInfo * aNodeInfo,nsINode ** aResult,bool aPreallocateChildren)166 virtual nsresult Clone(mozilla::dom::NodeInfo* aNodeInfo, nsINode** aResult, 167 bool aPreallocateChildren) const override { 168 nsCOMPtr<nsINode> result = CloneDataNode(aNodeInfo, true); 169 result.forget(aResult); 170 171 if (!*aResult) { 172 return NS_ERROR_OUT_OF_MEMORY; 173 } 174 175 return NS_OK; 176 } 177 178 nsresult SplitData(uint32_t aOffset, nsIContent** aReturn, 179 bool aCloneAfterOriginal = true); 180 181 // WebIDL API 182 // Our XPCOM GetData is just fine for WebIDL SetData(const nsAString & aData,mozilla::ErrorResult & rv)183 virtual void SetData(const nsAString& aData, mozilla::ErrorResult& rv) { 184 rv = SetData(aData); 185 } 186 // nsINode::Length() returns the right thing for our length attribute 187 void SubstringData(uint32_t aStart, uint32_t aCount, nsAString& aReturn, 188 mozilla::ErrorResult& rv); AppendData(const nsAString & aData,mozilla::ErrorResult & rv)189 void AppendData(const nsAString& aData, mozilla::ErrorResult& rv) { 190 rv = AppendData(aData); 191 } InsertData(uint32_t aOffset,const nsAString & aData,mozilla::ErrorResult & rv)192 void InsertData(uint32_t aOffset, const nsAString& aData, 193 mozilla::ErrorResult& rv) { 194 rv = InsertData(aOffset, aData); 195 } DeleteData(uint32_t aOffset,uint32_t aCount,mozilla::ErrorResult & rv)196 void DeleteData(uint32_t aOffset, uint32_t aCount, mozilla::ErrorResult& rv) { 197 rv = DeleteData(aOffset, aCount); 198 } ReplaceData(uint32_t aOffset,uint32_t aCount,const nsAString & aData,mozilla::ErrorResult & rv)199 void ReplaceData(uint32_t aOffset, uint32_t aCount, const nsAString& aData, 200 mozilla::ErrorResult& rv) { 201 rv = ReplaceData(aOffset, aCount, aData); 202 } 203 TextDataLength()204 uint32_t TextDataLength() const { return mText.GetLength(); } 205 206 //---------------------------------------- 207 208 #ifdef DEBUG 209 void ToCString(nsAString& aBuf, int32_t aOffset, int32_t aLen) const; 210 #endif 211 212 NS_DECL_CYCLE_COLLECTION_SKIPPABLE_SCRIPT_HOLDER_CLASS(nsGenericDOMDataNode) 213 214 protected: 215 virtual ~nsGenericDOMDataNode(); 216 GetNameSpaceElement()217 virtual mozilla::dom::Element* GetNameSpaceElement() override { 218 nsINode* parent = GetParentNode(); 219 220 return parent && parent->IsElement() ? parent->AsElement() : nullptr; 221 } 222 223 nsresult SplitText(uint32_t aOffset, nsIDOMText** aReturn); 224 225 nsresult GetWholeText(nsAString& aWholeText); 226 227 nsresult SetTextInternal( 228 uint32_t aOffset, uint32_t aCount, const char16_t* aBuffer, 229 uint32_t aLength, bool aNotify, 230 CharacterDataChangeInfo::Details* aDetails = nullptr); 231 232 /** 233 * Method to clone this node. This needs to be overriden by all derived 234 * classes. If aCloneText is true the text content will be cloned too. 235 * 236 * @param aOwnerDocument the ownerDocument of the clone 237 * @param aCloneText if true the text content will be cloned too 238 * @return the clone 239 */ 240 virtual nsGenericDOMDataNode* CloneDataNode(mozilla::dom::NodeInfo* aNodeInfo, 241 bool aCloneText) const = 0; 242 243 nsTextFragment mText; 244 245 public: OwnedOnlyByTheDOMTree()246 virtual bool OwnedOnlyByTheDOMTree() override { 247 return GetParent() && mRefCnt.get() == 1; 248 } 249 IsPurple()250 virtual bool IsPurple() override { return mRefCnt.IsPurple(); } RemovePurple()251 virtual void RemovePurple() override { mRefCnt.RemovePurple(); } 252 253 private: 254 already_AddRefed<nsAtom> GetCurrentValueAtom(); 255 }; 256 257 #endif /* nsGenericDOMDataNode_h___ */ 258