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:
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();
}