summaryrefslogtreecommitdiffstats
path: root/dom/base/CharacterData.h
diff options
context:
space:
mode:
Diffstat (limited to 'dom/base/CharacterData.h')
-rw-r--r--dom/base/CharacterData.h232
1 files changed, 232 insertions, 0 deletions
diff --git a/dom/base/CharacterData.h b/dom/base/CharacterData.h
new file mode 100644
index 0000000000..4f125953ef
--- /dev/null
+++ b/dom/base/CharacterData.h
@@ -0,0 +1,232 @@
+/* -*- 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/. */
+
+/*
+ * Base class for DOM Core's Comment, DocumentType, Text,
+ * CDATASection, and ProcessingInstruction nodes.
+ */
+
+#ifndef mozilla_dom_CharacterData_h
+#define mozilla_dom_CharacterData_h
+
+#include "mozilla/Attributes.h"
+#include "nsIContent.h"
+#include "nsIMutationObserver.h"
+
+#include "nsTextFragment.h"
+#include "nsError.h"
+#include "nsCycleCollectionParticipant.h"
+
+namespace mozilla::dom {
+class Element;
+class HTMLSlotElement;
+} // namespace mozilla::dom
+
+#define CHARACTER_DATA_FLAG_BIT(n_) \
+ NODE_FLAG_BIT(NODE_TYPE_SPECIFIC_BITS_OFFSET + (n_))
+
+// Data node specific flags
+enum {
+ // This bit is set to indicate that if the text node changes to
+ // non-whitespace, we may need to create a frame for it. This bit must
+ // not be set on nodes that already have a frame.
+ NS_CREATE_FRAME_IF_NON_WHITESPACE = CHARACTER_DATA_FLAG_BIT(0),
+
+ // This bit is set to indicate that if the text node changes to
+ // whitespace, we may need to reframe it (or its ancestors).
+ NS_REFRAME_IF_WHITESPACE = CHARACTER_DATA_FLAG_BIT(1),
+
+ // This bit is set to indicate that we have a cached
+ // TextIsOnlyWhitespace value
+ NS_CACHED_TEXT_IS_ONLY_WHITESPACE = CHARACTER_DATA_FLAG_BIT(2),
+
+ // This bit is only meaningful if the NS_CACHED_TEXT_IS_ONLY_WHITESPACE
+ // bit is set, and if so it indicates whether we're only whitespace or
+ // not.
+ NS_TEXT_IS_ONLY_WHITESPACE = CHARACTER_DATA_FLAG_BIT(3),
+
+ // This bit is set if there is a NewlineProperty attached to the node
+ // (used by nsTextFrame).
+ NS_HAS_NEWLINE_PROPERTY = CHARACTER_DATA_FLAG_BIT(4),
+
+ // This bit is set if there is a FlowLengthProperty attached to the node
+ // (used by nsTextFrame).
+ NS_HAS_FLOWLENGTH_PROPERTY = CHARACTER_DATA_FLAG_BIT(5),
+
+ // This bit is set if the node may be modified frequently. This is typically
+ // specified if the instance is in <input> or <textarea>.
+ NS_MAYBE_MODIFIED_FREQUENTLY = CHARACTER_DATA_FLAG_BIT(6),
+
+ // This bit is set if the node may be masked because of being in a password
+ // field.
+ NS_MAYBE_MASKED = CHARACTER_DATA_FLAG_BIT(7),
+};
+
+// Make sure we have enough space for those bits
+ASSERT_NODE_FLAGS_SPACE(NODE_TYPE_SPECIFIC_BITS_OFFSET + 8);
+
+#undef CHARACTER_DATA_FLAG_BIT
+
+namespace mozilla::dom {
+
+class CharacterData : public nsIContent {
+ public:
+ // We want to avoid the overhead of extra function calls for
+ // refcounting when we're not doing refcount logging, so we can't
+ // NS_DECL_ISUPPORTS_INHERITED.
+ NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr) override;
+ NS_INLINE_DECL_REFCOUNTING_INHERITED(CharacterData, nsIContent);
+
+ NS_DECL_ADDSIZEOFEXCLUDINGTHIS
+
+ explicit CharacterData(already_AddRefed<dom::NodeInfo>&& aNodeInfo);
+
+ void MarkAsMaybeModifiedFrequently() {
+ SetFlags(NS_MAYBE_MODIFIED_FREQUENTLY);
+ }
+ void MarkAsMaybeMasked() { SetFlags(NS_MAYBE_MASKED); }
+
+ NS_IMPL_FROMNODE_HELPER(CharacterData, IsCharacterData())
+
+ virtual void GetNodeValueInternal(nsAString& aNodeValue) override;
+ virtual void SetNodeValueInternal(const nsAString& aNodeValue,
+ ErrorResult& aError) override;
+
+ void GetTextContentInternal(nsAString& aTextContent, OOMReporter&) final {
+ GetNodeValue(aTextContent);
+ }
+
+ void SetTextContentInternal(const nsAString& aTextContent,
+ nsIPrincipal* aSubjectPrincipal,
+ ErrorResult& aError) final;
+
+ // Implementation for nsIContent
+ nsresult BindToTree(BindContext&, nsINode& aParent) override;
+
+ void UnbindFromTree(bool aNullParent = true) override;
+
+ already_AddRefed<nsINodeList> GetChildren(uint32_t aFilter) final {
+ return nullptr;
+ }
+
+ const nsTextFragment* GetText() override { return &mText; }
+ uint32_t TextLength() const final { return TextDataLength(); }
+
+ const nsTextFragment& TextFragment() const { return mText; }
+ uint32_t TextDataLength() const { return mText.GetLength(); }
+
+ /**
+ * Set the text to the given value. If aNotify is true then
+ * the document is notified of the content change.
+ */
+ nsresult SetText(const char16_t* aBuffer, uint32_t aLength, bool aNotify);
+ /**
+ * Append the given value to the current text. If aNotify is true then
+ * the document is notified of the content change.
+ */
+ nsresult SetText(const nsAString& aStr, bool aNotify) {
+ return SetText(aStr.BeginReading(), aStr.Length(), aNotify);
+ }
+
+ /**
+ * Append the given value to the current text. If aNotify is true then
+ * the document is notified of the content change.
+ */
+ nsresult AppendText(const char16_t* aBuffer, uint32_t aLength, bool aNotify);
+
+ bool TextIsOnlyWhitespace() final;
+ bool ThreadSafeTextIsOnlyWhitespace() const final;
+
+ /**
+ * Append the text content to aResult.
+ */
+ void AppendTextTo(nsAString& aResult) const { mText.AppendTo(aResult); }
+
+ /**
+ * Append the text content to aResult.
+ */
+ [[nodiscard]] bool AppendTextTo(nsAString& aResult,
+ const fallible_t& aFallible) const {
+ return mText.AppendTo(aResult, aFallible);
+ }
+
+ void SaveSubtreeState() final {}
+
+#ifdef MOZ_DOM_LIST
+ void ToCString(nsAString& aBuf, int32_t aOffset, int32_t aLen) const;
+
+ void List(FILE* out, int32_t aIndent) const override {}
+
+ void DumpContent(FILE* out, int32_t aIndent, bool aDumpAll) const override {}
+#endif
+
+ bool IsNodeOfType(uint32_t aFlags) const override { return false; }
+
+ nsresult Clone(dom::NodeInfo* aNodeInfo, nsINode** aResult) const override {
+ RefPtr<CharacterData> result = CloneDataNode(aNodeInfo, true);
+ result.forget(aResult);
+
+ if (!*aResult) {
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+
+ return NS_OK;
+ }
+
+ // WebIDL API
+ void GetData(nsAString& aData) const;
+ virtual void SetData(const nsAString& aData, ErrorResult& rv);
+ // nsINode::Length() returns the right thing for our length attribute
+ void SubstringData(uint32_t aStart, uint32_t aCount, nsAString& aReturn,
+ ErrorResult& rv);
+ void AppendData(const nsAString& aData, ErrorResult& rv);
+ void InsertData(uint32_t aOffset, const nsAString& aData, ErrorResult& rv);
+ void DeleteData(uint32_t aOffset, uint32_t aCount, ErrorResult& rv);
+ void ReplaceData(uint32_t aOffset, uint32_t aCount, const nsAString& aData,
+ ErrorResult& rv);
+
+ //----------------------------------------
+
+ NS_DECL_CYCLE_COLLECTION_SKIPPABLE_WRAPPERCACHE_CLASS_INHERITED(CharacterData,
+ nsIContent)
+
+ /**
+ * Compare two CharacterData nodes for text equality.
+ */
+ [[nodiscard]] bool TextEquals(const CharacterData* aOther) const {
+ return mText.TextEquals(aOther->mText);
+ }
+
+ protected:
+ virtual ~CharacterData();
+
+ Element* GetNameSpaceElement() final;
+
+ nsresult SetTextInternal(
+ uint32_t aOffset, uint32_t aCount, const char16_t* aBuffer,
+ uint32_t aLength, bool aNotify,
+ CharacterDataChangeInfo::Details* aDetails = nullptr);
+
+ /**
+ * Method to clone this node. This needs to be overriden by all derived
+ * classes. If aCloneText is true the text content will be cloned too.
+ *
+ * @param aOwnerDocument the ownerDocument of the clone
+ * @param aCloneText if true the text content will be cloned too
+ * @return the clone
+ */
+ virtual already_AddRefed<CharacterData> CloneDataNode(
+ dom::NodeInfo* aNodeInfo, bool aCloneText) const = 0;
+
+ nsTextFragment mText;
+
+ private:
+ already_AddRefed<nsAtom> GetCurrentValueAtom();
+};
+
+} // namespace mozilla::dom
+
+#endif /* mozilla_dom_CharacterData_h */