tor-browser

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

commit 59ba1365602235fbbbdd0fa3512e4c7d88aa40b2
parent b1895729f74be92a1ea60fbae0f63df0a433f326
Author: Jonathan Mendez <jmendez@mozilla.com>
Date:   Fri,  7 Nov 2025 23:27:37 +0000

Bug 1953524 - Create helpers for leading/trailing whitespace to remove duplicated code. r=emilio,layout-reviewers

Differential Revision: https://phabricator.services.mozilla.com/D271665

Diffstat:
Mdom/base/CharacterData.cpp | 63+++++++++++++++++++++++++++++++++++++++++++++++++++++----------
Mdom/base/CharacterData.h | 13+++++++++++++
Mdom/serializers/nsDocumentEncoder.cpp | 14++++++--------
Mlayout/printing/nsPrintJob.cpp | 11++---------
4 files changed, 74 insertions(+), 27 deletions(-)

diff --git a/dom/base/CharacterData.cpp b/dom/base/CharacterData.cpp @@ -533,21 +533,64 @@ bool CharacterData::ThreadSafeTextIsOnlyWhitespace() const { return HasFlag(NS_TEXT_IS_ONLY_WHITESPACE); } - const char* cp = mBuffer.Get1b(); - const char* end = cp + mBuffer.GetLength(); + return CheckTextIsOnlyWhitespace(0, mBuffer.GetLength()); +} - while (cp < end) { - char ch = *cp; +bool CharacterData::TextStartsWithOnlyWhitespace(uint32_t aOffset) const { + MOZ_ASSERT(aOffset <= mBuffer.GetLength()); - // NOTE(emilio): If you ever change the definition of "whitespace" here, you - // need to change it too in RestyleManager::CharacterDataChanged. - if (!dom::IsSpaceCharacter(ch)) { - return false; - } + if (HasFlag(NS_CACHED_TEXT_IS_ONLY_WHITESPACE) && + HasFlag(NS_TEXT_IS_ONLY_WHITESPACE)) { + return true; + } + + return CheckTextIsOnlyWhitespace(0, aOffset); +} + +bool CharacterData::TextEndsWithOnlyWhitespace(uint32_t aOffset) const { + MOZ_ASSERT(aOffset <= mBuffer.GetLength()); - ++cp; + if (HasFlag(NS_CACHED_TEXT_IS_ONLY_WHITESPACE) && + HasFlag(NS_TEXT_IS_ONLY_WHITESPACE)) { + return true; } + return CheckTextIsOnlyWhitespace(aOffset, mBuffer.GetLength()); +} + +bool CharacterData::CheckTextIsOnlyWhitespace(uint32_t aStartOffset, + uint32_t aEndOffset) const { + if (mBuffer.Is2b()) { + const char16_t* cp = mBuffer.Get2b() + aStartOffset; + const char16_t* end = mBuffer.Get2b() + aEndOffset; + + while (cp < end) { + char16_t ch = *cp; + + // NOTE(emilio): If you ever change the definition of "whitespace" here, + // you need to change it too in RestyleManager::CharacterDataChanged. + if (!dom::IsSpaceCharacter(ch)) { + return false; + } + + ++cp; + } + } else { + const char* cp = mBuffer.Get1b() + aStartOffset; + const char* end = mBuffer.Get1b() + aEndOffset; + + while (cp < end) { + char ch = *cp; + + // NOTE(emilio): If you ever change the definition of "whitespace" here, + // you need to change it too in RestyleManager::CharacterDataChanged. + if (!dom::IsSpaceCharacter(ch)) { + return false; + } + + ++cp; + } + } return true; } diff --git a/dom/base/CharacterData.h b/dom/base/CharacterData.h @@ -147,6 +147,16 @@ class CharacterData : public nsIContent { bool ThreadSafeTextIsOnlyWhitespace() const final; /** + * Check if all text before the given offset is whitespace. + */ + bool TextStartsWithOnlyWhitespace(uint32_t aOffset) const; + + /** + * Check if all text at or after the given offset is whitespace. + */ + bool TextEndsWithOnlyWhitespace(uint32_t aOffset) const; + + /** * Append the text content to aResult. */ void AppendTextTo(nsAString& aResult) const { mBuffer.AppendTo(aResult); } @@ -260,6 +270,9 @@ class CharacterData : public nsIContent { private: already_AddRefed<nsAtom> GetCurrentValueAtom(); + + bool CheckTextIsOnlyWhitespace(uint32_t aStartOffset, + uint32_t aEndOffset) const; }; } // namespace mozilla::dom diff --git a/dom/serializers/nsDocumentEncoder.cpp b/dom/serializers/nsDocumentEncoder.cpp @@ -1994,10 +1994,9 @@ nsresult nsHTMLCopyEncoder::GetPromotedPoint(Endpoint aWhere, nsINode* aNode, // unless everything before us in just whitespace. NOTE: we need a more // general solution that truly detects all cases of non-significant // whitesace with no false alarms. - nsAutoString text; - nodeAsText->SubstringData(0, offset, text, IgnoreErrors()); - text.CompressWhitespace(); - if (!text.IsEmpty()) return NS_OK; + if (!nodeAsText->TextStartsWithOnlyWhitespace(offset)) { + return NS_OK; + } bResetPromotion = true; } // else @@ -2057,10 +2056,9 @@ nsresult nsHTMLCopyEncoder::GetPromotedPoint(Endpoint aWhere, nsINode* aNode, // unless everything after us in just whitespace. NOTE: we need a more // general solution that truly detects all cases of non-significant // whitespace with no false alarms. - nsAutoString text; - nodeAsText->SubstringData(offset, len - offset, text, IgnoreErrors()); - text.CompressWhitespace(); - if (!text.IsEmpty()) return NS_OK; + if (!nodeAsText->TextEndsWithOnlyWhitespace(offset)) { + return NS_OK; + } bResetPromotion = true; } rv = GetNodeLocation(aNode, address_of(parent), &offset); diff --git a/layout/printing/nsPrintJob.cpp b/layout/printing/nsPrintJob.cpp @@ -1599,10 +1599,7 @@ void SelectionRangeState::SelectNodesExceptInSubtree(const Position& aStart, if (start.mNode != text && aStart.mOffset && aStart.mOffset < text->Length()) { // Only insert ellipsis if there is any non-whitespace prior to selection. - nsAutoString leadingText; - text->SubstringData(0, aStart.mOffset, leadingText, IgnoreErrors()); - leadingText.CompressWhitespace(); - if (!leadingText.IsEmpty()) { + if (!text->TextStartsWithOnlyWhitespace(aStart.mOffset)) { text->InsertData(aStart.mOffset, kEllipsis, IgnoreErrors()); ellipsizedStart = true; } @@ -1628,11 +1625,7 @@ void SelectionRangeState::SelectNodesExceptInSubtree(const Position& aStart, if (auto* text = Text::FromNode(start.mNode)) { if (start.mOffset && start.mOffset < text->Length()) { // Only insert ellipsis if there is any non-whitespace after selection. - nsAutoString trailingText; - text->SubstringData(start.mOffset, text->Length() - start.mOffset, - trailingText, IgnoreErrors()); - trailingText.CompressWhitespace(); - if (!trailingText.IsEmpty()) { + if (!text->TextEndsWithOnlyWhitespace(start.mOffset)) { text->InsertData(start.mOffset, kEllipsis, IgnoreErrors()); start.mOffset += kEllipsis.Length(); }