tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

CharacterData.h (10088B)


      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 Comment, DocumentType, Text,
      9 * CDATASection, and ProcessingInstruction nodes.
     10 */
     11 
     12 #ifndef mozilla_dom_CharacterData_h
     13 #define mozilla_dom_CharacterData_h
     14 
     15 #include "CharacterDataBuffer.h"
     16 #include "nsCycleCollectionParticipant.h"
     17 #include "nsError.h"
     18 #include "nsIContent.h"
     19 #include "nsIMutationObserver.h"
     20 
     21 namespace mozilla::dom {
     22 class Element;
     23 class HTMLSlotElement;
     24 }  // namespace mozilla::dom
     25 
     26 #define CHARACTER_DATA_FLAG_BIT(n_) \
     27  NODE_FLAG_BIT(NODE_TYPE_SPECIFIC_BITS_OFFSET + (n_))
     28 
     29 // Data node specific flags
     30 enum {
     31  // This bit is set to indicate that if the text node changes to
     32  // non-whitespace, we may need to create a frame for it. This bit must
     33  // not be set on nodes that already have a frame.
     34  NS_CREATE_FRAME_IF_NON_WHITESPACE = CHARACTER_DATA_FLAG_BIT(0),
     35 
     36  // This bit is set to indicate that if the text node changes to
     37  // whitespace, we may need to reframe it (or its ancestors).
     38  NS_REFRAME_IF_WHITESPACE = CHARACTER_DATA_FLAG_BIT(1),
     39 
     40  // This bit is set to indicate that we have a cached
     41  // TextIsOnlyWhitespace value
     42  NS_CACHED_TEXT_IS_ONLY_WHITESPACE = CHARACTER_DATA_FLAG_BIT(2),
     43 
     44  // This bit is only meaningful if the NS_CACHED_TEXT_IS_ONLY_WHITESPACE
     45  // bit is set, and if so it indicates whether we're only whitespace or
     46  // not.
     47  NS_TEXT_IS_ONLY_WHITESPACE = CHARACTER_DATA_FLAG_BIT(3),
     48 
     49  // This bit is set if there is a NewlineProperty attached to the node
     50  // (used by nsTextFrame).
     51  NS_HAS_NEWLINE_PROPERTY = CHARACTER_DATA_FLAG_BIT(4),
     52 
     53  // This bit is set if there is a FlowLengthProperty attached to the node
     54  // (used by nsTextFrame).
     55  NS_HAS_FLOWLENGTH_PROPERTY = CHARACTER_DATA_FLAG_BIT(5),
     56 
     57  // This bit is set if the node may be modified frequently.  This is typically
     58  // specified if the instance is in <input> or <textarea>.
     59  NS_MAYBE_MODIFIED_FREQUENTLY = CHARACTER_DATA_FLAG_BIT(6),
     60 
     61  // This bit is set if the node may be masked because of being in a password
     62  // field.
     63  NS_MAYBE_MASKED = CHARACTER_DATA_FLAG_BIT(7),
     64 
     65  // Set if this text might be responsible for setting the directionality
     66  // of a dir="auto" ancestor.
     67  NS_MAY_SET_DIR_AUTO = CHARACTER_DATA_FLAG_BIT(8),
     68 };
     69 
     70 // Make sure we have enough space for those bits
     71 ASSERT_NODE_FLAGS_SPACE(NODE_TYPE_SPECIFIC_BITS_OFFSET + 8);
     72 
     73 #undef CHARACTER_DATA_FLAG_BIT
     74 
     75 namespace mozilla::dom {
     76 
     77 class CharacterData : public nsIContent {
     78 public:
     79  // We want to avoid the overhead of extra function calls for
     80  // refcounting when we're not doing refcount logging, so we can't
     81  // NS_DECL_ISUPPORTS_INHERITED.
     82  NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr) override;
     83  NS_INLINE_DECL_REFCOUNTING_INHERITED(CharacterData, nsIContent);
     84 
     85  NS_DECL_ADDSIZEOFEXCLUDINGTHIS
     86 
     87  explicit CharacterData(already_AddRefed<dom::NodeInfo>&& aNodeInfo);
     88 
     89  void MarkAsMaybeModifiedFrequently() {
     90    SetFlags(NS_MAYBE_MODIFIED_FREQUENTLY);
     91  }
     92  void MarkAsMaybeMasked() { SetFlags(NS_MAYBE_MASKED); }
     93 
     94  void SetMaySetDirAuto() { SetFlags(NS_MAY_SET_DIR_AUTO); }
     95  bool MaySetDirAuto() const { return HasFlag(NS_MAY_SET_DIR_AUTO); }
     96  void ClearMaySetDirAuto() { UnsetFlags(NS_MAY_SET_DIR_AUTO); }
     97 
     98  NS_IMPL_FROMNODE_HELPER(CharacterData, IsCharacterData())
     99 
    100  void GetNodeValueInternal(nsAString& aNodeValue) override;
    101  void SetNodeValueInternal(
    102      const nsAString& aNodeValue, ErrorResult& aError,
    103      MutationEffectOnScript aMutationEffectOnScript) override;
    104 
    105  void GetTextContentInternal(nsAString& aTextContent, OOMReporter&) final {
    106    GetNodeValue(aTextContent);
    107  }
    108 
    109  void SetTextContentInternal(
    110      const nsAString& aTextContent, nsIPrincipal* aSubjectPrincipal,
    111      ErrorResult& aError,
    112      MutationEffectOnScript aMutationEffectOnScript) final;
    113 
    114  // Implementation for nsIContent
    115  nsresult BindToTree(BindContext&, nsINode& aParent) override;
    116 
    117  void UnbindFromTree(UnbindContext&) override;
    118 
    119  const CharacterDataBuffer* GetCharacterDataBuffer() const override {
    120    return &mBuffer;
    121  }
    122  uint32_t TextLength() const final { return TextDataLength(); }
    123 
    124  const CharacterDataBuffer& DataBuffer() const { return mBuffer; }
    125  uint32_t TextDataLength() const { return mBuffer.GetLength(); }
    126 
    127  /**
    128   * Set the text to the given value. If aNotify is true then
    129   * the document is notified of the content change.
    130   */
    131  nsresult SetText(const char16_t* aBuffer, uint32_t aLength, bool aNotify);
    132  /**
    133   * Append the given value to the current text. If aNotify is true then
    134   * the document is notified of the content change.
    135   */
    136  nsresult SetText(const nsAString& aStr, bool aNotify) {
    137    return SetText(aStr.BeginReading(), aStr.Length(), aNotify);
    138  }
    139 
    140  /**
    141   * Append the given value to the current text. If aNotify is true then
    142   * the document is notified of the content change.
    143   */
    144  nsresult AppendText(const char16_t* aBuffer, uint32_t aLength, bool aNotify);
    145 
    146  bool TextIsOnlyWhitespace() final;
    147  bool ThreadSafeTextIsOnlyWhitespace() const final;
    148 
    149  /**
    150   * Check if all text before the given offset is whitespace.
    151   */
    152  bool TextStartsWithOnlyWhitespace(uint32_t aOffset) const;
    153 
    154  /**
    155   * Check if all text at or after the given offset is whitespace.
    156   */
    157  bool TextEndsWithOnlyWhitespace(uint32_t aOffset) const;
    158 
    159  /**
    160   * Append the text content to aResult.
    161   */
    162  void AppendTextTo(nsAString& aResult) const { mBuffer.AppendTo(aResult); }
    163 
    164  /**
    165   * Append the text content to aResult.
    166   */
    167  [[nodiscard]] bool AppendTextTo(nsAString& aResult,
    168                                  const fallible_t& aFallible) const {
    169    return mBuffer.AppendTo(aResult, aFallible);
    170  }
    171 
    172  void SaveSubtreeState() final {}
    173 
    174 #ifdef MOZ_DOM_LIST
    175  void ToCString(nsAString& aBuf, int32_t aOffset, int32_t aLen) const;
    176 
    177  void List(FILE* out, int32_t aIndent) const override {}
    178 
    179  void DumpContent(FILE* out, int32_t aIndent, bool aDumpAll) const override {}
    180 #endif
    181 
    182  nsresult Clone(dom::NodeInfo* aNodeInfo, nsINode** aResult) const override {
    183    RefPtr<CharacterData> result = CloneDataNode(aNodeInfo, true);
    184    result.forget(aResult);
    185 
    186    if (!*aResult) {
    187      return NS_ERROR_OUT_OF_MEMORY;
    188    }
    189 
    190    return NS_OK;
    191  }
    192 
    193  // WebIDL API
    194  void GetData(nsAString& aData) const;
    195  void SetData(const nsAString& aData, ErrorResult& rv) {
    196    SetDataInternal(aData, MutationEffectOnScript::DropTrustWorthiness, rv);
    197  }
    198  virtual void SetDataInternal(const nsAString& aData,
    199                               MutationEffectOnScript aMutationEffectOnScript,
    200                               ErrorResult& rv);
    201  // nsINode::Length() returns the right thing for our length attribute
    202  void SubstringData(uint32_t aStart, uint32_t aCount, nsAString& aReturn,
    203                     ErrorResult& rv);
    204  void AppendData(const nsAString& aData, ErrorResult& rv) {
    205    AppendDataInternal(aData, MutationEffectOnScript::DropTrustWorthiness, rv);
    206  }
    207  void AppendDataInternal(const nsAString& aData,
    208                          MutationEffectOnScript aMutationEffectOnScript,
    209                          ErrorResult& rv);
    210  void InsertData(uint32_t aOffset, const nsAString& aData, ErrorResult& rv) {
    211    InsertDataInternal(aOffset, aData,
    212                       MutationEffectOnScript::DropTrustWorthiness, rv);
    213  }
    214  void InsertDataInternal(uint32_t aOffset, const nsAString& aData,
    215                          MutationEffectOnScript aMutationEffectOnScript,
    216                          ErrorResult& rv);
    217  void DeleteData(uint32_t aOffset, uint32_t aCount, ErrorResult& rv) {
    218    DeleteDataInternal(aOffset, aCount,
    219                       MutationEffectOnScript::DropTrustWorthiness, rv);
    220  }
    221  void DeleteDataInternal(uint32_t aOffset, uint32_t aCount,
    222                          MutationEffectOnScript aMutationEffectOnScript,
    223                          ErrorResult& rv);
    224  void ReplaceData(uint32_t aOffset, uint32_t aCount, const nsAString& aData,
    225                   ErrorResult& rv) {
    226    ReplaceDataInternal(aOffset, aCount, aData,
    227                        MutationEffectOnScript::DropTrustWorthiness, rv);
    228  }
    229  void ReplaceDataInternal(uint32_t aOffset, uint32_t aCount,
    230                           const nsAString& aData,
    231                           MutationEffectOnScript aMutationEffectOnScript,
    232                           ErrorResult& rv);
    233 
    234  //----------------------------------------
    235 
    236  NS_DECL_CYCLE_COLLECTION_SKIPPABLE_WRAPPERCACHE_CLASS_INHERITED(CharacterData,
    237                                                                  nsIContent)
    238 
    239  /**
    240   * Compare two CharacterData nodes for text equality.
    241   */
    242  [[nodiscard]] bool TextEquals(const CharacterData* aOther) const {
    243    return mBuffer.BufferEquals(aOther->mBuffer);
    244  }
    245 
    246 protected:
    247  virtual ~CharacterData();
    248 
    249  Element* GetNameSpaceElement() final;
    250 
    251  nsresult SetTextInternal(
    252      uint32_t aOffset, uint32_t aCount, const char16_t* aBuffer,
    253      uint32_t aLength, bool aNotify,
    254      MutationEffectOnScript aMutationEffectOnScript =
    255          MutationEffectOnScript::DropTrustWorthiness,
    256      CharacterDataChangeInfo::Details* aDetails = nullptr);
    257 
    258  /**
    259   * Method to clone this node. This needs to be overriden by all derived
    260   * classes. If aCloneText is true the text content will be cloned too.
    261   *
    262   * @param aOwnerDocument the ownerDocument of the clone
    263   * @param aCloneText if true the text content will be cloned too
    264   * @return the clone
    265   */
    266  virtual already_AddRefed<CharacterData> CloneDataNode(
    267      dom::NodeInfo* aNodeInfo, bool aCloneText) const = 0;
    268 
    269  CharacterDataBuffer mBuffer;
    270 
    271 private:
    272  already_AddRefed<nsAtom> GetCurrentValueAtom();
    273 
    274  bool CheckTextIsOnlyWhitespace(uint32_t aStartOffset,
    275                                 uint32_t aEndOffset) const;
    276 };
    277 
    278 }  // namespace mozilla::dom
    279 
    280 #endif /* mozilla_dom_CharacterData_h */