commit cf35c47f3cb8b832d94b69aee6bce004babb4c73
parent fccd7e8fdfb27a3cebfc12244ea3061a38abca51
Author: Narcis Beleuzu <nbeleuzu@mozilla.com>
Date: Tue, 14 Oct 2025 12:16:02 +0300
Revert "Bug 1992067 - Simplify nsPlainTextSerializer::DoAddText() a bit; r=masayuki" for causing plain Bp-nu bustages
This reverts commit cfacf6f690a59adbd8de17a29e89ad80141f1e85.
This reverts commit 194f39d870caae856234f0a611c05a4a5c9792fc.
This reverts commit 7f8cb6c34c8dcc40672258b59319e80eae916e0a.
This reverts commit e2fbc47166f364668a5bd613e267b50de6081764.
Diffstat:
6 files changed, 103 insertions(+), 249 deletions(-)
diff --git a/dom/serializers/gtest/Common.h b/dom/serializers/gtest/Common.h
@@ -1,21 +0,0 @@
-/* -*- 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/. */
-
-#ifndef dom_serializers_gtest_Common_h
-#define dom_serializers_gtest_Common_h
-
-#include "nsIParserUtils.h"
-#include "nsServiceManagerUtils.h"
-#include "nsString.h"
-
-const uint32_t kDefaultWrapColumn = 72;
-
-void ConvertBufToPlainText(nsString& aConBuf, int aFlag, uint32_t aWrapColumn) {
- nsCOMPtr<nsIParserUtils> utils = do_GetService(NS_PARSERUTILS_CONTRACTID);
- utils->ConvertToPlainText(aConBuf, aFlag, aWrapColumn, aConBuf);
-}
-
-#endif // dom_serializers_gtest_Common_h
diff --git a/dom/serializers/gtest/TestPlainTextSerializer.cpp b/dom/serializers/gtest/TestPlainTextSerializer.cpp
@@ -4,7 +4,6 @@
* 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/. */
-#include "Common.h"
#include "gtest/gtest.h"
#include "nsCRT.h"
#include "nsIDocumentEncoder.h"
@@ -12,6 +11,13 @@
#include "nsServiceManagerUtils.h"
#include "nsString.h"
+const uint32_t kDefaultWrapColumn = 72;
+
+void ConvertBufToPlainText(nsString& aConBuf, int aFlag, uint32_t aWrapColumn) {
+ nsCOMPtr<nsIParserUtils> utils = do_GetService(NS_PARSERUTILS_CONTRACTID);
+ utils->ConvertToPlainText(aConBuf, aFlag, aWrapColumn, aConBuf);
+}
+
// Test for ASCII with format=flowed; delsp=yes
TEST(PlainTextSerializer, ASCIIWithFlowedDelSp)
{
@@ -39,8 +45,8 @@ TEST(PlainTextSerializer, ASCIIWithFlowedDelSp)
"Firefox Firefox Firefox Firefox "
"Firefox \r\nFirefox Firefox Firefox\r\n");
- ASSERT_EQ(test, result)
- << "Wrong HTML to ASCII text serialization with format=flowed; delsp=yes";
+ ASSERT_TRUE(test.Equals(result))
+ << "Wrong HTML to ASCII text serialization with format=flowed; delsp=yes";
}
TEST(PlainTextSerializer, Bug1864820)
@@ -70,7 +76,8 @@ TEST(PlainTextSerializer, Bug1864820)
)#");
result.Trim(" \n");
test.Trim(" \n");
- ASSERT_EQ(test, result) << "Shouldn't hang with format=flowed";
+ ASSERT_TRUE(test.Equals(result))
+ << "Shouldn't hang with format=flowed: " << NS_ConvertUTF16toUTF8(test).get();
}
// Test for CJK with format=flowed; delsp=yes
@@ -104,8 +111,8 @@ TEST(PlainTextSerializer, CJKWithFlowedDelSp)
}
result.AppendLiteral("\r\n");
- ASSERT_EQ(test, result)
- << "Wrong HTML to CJK text serialization with format=flowed; delsp=yes";
+ ASSERT_TRUE(test.Equals(result))
+ << "Wrong HTML to CJK text serialization with format=flowed; delsp=yes";
}
// Test for CJK with DisallowLineBreaking
@@ -135,8 +142,8 @@ TEST(PlainTextSerializer, CJKWithDisallowLineBreaking)
}
result.AppendLiteral("\r\n");
- ASSERT_EQ(test, result)
- << "Wrong HTML to CJK text serialization with OutputDisallowLineBreaking";
+ ASSERT_TRUE(test.Equals(result))
+ << "Wrong HTML to CJK text serialization with OutputDisallowLineBreaking";
}
// Test for Latin with DisallowLineBreaking
@@ -165,8 +172,8 @@ TEST(PlainTextSerializer, LatinWithDisallowLineBreaking)
}
expect.AppendLiteral(" \r\n\r\n");
- ASSERT_EQ(test, expect) << "Wrong HTML to Latin text serialization with "
- "OutputDisallowLineBreaking";
+ ASSERT_TRUE(test.Equals(expect))
+ << "Wrong HTML to Latin text serialization with OutputDisallowLineBreaking";
}
// Test for ASCII with format=flowed; and quoted lines in preformatted span.
@@ -249,11 +256,8 @@ TEST(PlainTextSerializer, PrettyPrintedHtml)
"</body>" NS_LINEBREAK "</html>");
ConvertBufToPlainText(test, 0, kDefaultWrapColumn);
-
- nsAutoString expect;
- expect.AppendLiteral("first" NS_LINEBREAK "second" NS_LINEBREAK);
-
- ASSERT_EQ(test, expect) << "Wrong prettyprinted html to text serialization";
+ ASSERT_TRUE(test.EqualsLiteral("first" NS_LINEBREAK "second" NS_LINEBREAK))
+ << "Wrong prettyprinted html to text serialization";
}
TEST(PlainTextSerializer, PreElement)
@@ -265,12 +269,9 @@ TEST(PlainTextSerializer, PreElement)
"</body>" NS_LINEBREAK "</html>");
ConvertBufToPlainText(test, 0, kDefaultWrapColumn);
-
- nsAutoString expect;
- expect.AppendLiteral(" first" NS_LINEBREAK
- " second" NS_LINEBREAK NS_LINEBREAK);
-
- ASSERT_EQ(test, expect) << "Wrong prettyprinted html to text serialization";
+ ASSERT_TRUE(test.EqualsLiteral(" first" NS_LINEBREAK
+ " second" NS_LINEBREAK NS_LINEBREAK))
+ << "Wrong prettyprinted html to text serialization";
}
TEST(PlainTextSerializer, BlockElement)
@@ -283,11 +284,8 @@ TEST(PlainTextSerializer, BlockElement)
"</body>" NS_LINEBREAK "</html>");
ConvertBufToPlainText(test, 0, kDefaultWrapColumn);
-
- nsAutoString expect;
- expect.AppendLiteral("first" NS_LINEBREAK "second" NS_LINEBREAK);
-
- ASSERT_EQ(test, expect) << "Wrong prettyprinted html to text serialization";
+ ASSERT_TRUE(test.EqualsLiteral("first" NS_LINEBREAK "second" NS_LINEBREAK))
+ << "Wrong prettyprinted html to text serialization";
}
TEST(PlainTextSerializer, PreWrapElementForThunderbird)
@@ -303,16 +301,13 @@ TEST(PlainTextSerializer, PreWrapElementForThunderbird)
const uint32_t wrapColumn = 10;
ConvertBufToPlainText(test, nsIDocumentEncoder::OutputWrap, wrapColumn);
-
// "\n\n first\nline is\ntoo long\n second\nline is\neven\nloooonger\n\n\n"
- nsAutoString expect;
- expect.AppendLiteral(NS_LINEBREAK NS_LINEBREAK
- " first" NS_LINEBREAK "line is" NS_LINEBREAK
- "too long" NS_LINEBREAK " second" NS_LINEBREAK
- "line is" NS_LINEBREAK "even" NS_LINEBREAK
- "loooonger" NS_LINEBREAK NS_LINEBREAK NS_LINEBREAK);
-
- ASSERT_EQ(test, expect) << "Wrong prettyprinted html to text serialization";
+ ASSERT_TRUE(test.EqualsLiteral(
+ NS_LINEBREAK NS_LINEBREAK
+ " first" NS_LINEBREAK "line is" NS_LINEBREAK "too long" NS_LINEBREAK
+ " second" NS_LINEBREAK "line is" NS_LINEBREAK "even" NS_LINEBREAK
+ "loooonger" NS_LINEBREAK NS_LINEBREAK NS_LINEBREAK))
+ << "Wrong prettyprinted html to text serialization";
}
TEST(PlainTextSerializer, Simple)
@@ -322,11 +317,8 @@ TEST(PlainTextSerializer, Simple)
"<html><base>base</base><head><span>span</span></head>"
"<body>body</body></html>");
ConvertBufToPlainText(test, 0, kDefaultWrapColumn);
-
- nsAutoString expect;
- expect.AppendLiteral("basespanbody");
-
- ASSERT_EQ(test, expect) << "Wrong html to text serialization";
+ ASSERT_TRUE(test.EqualsLiteral("basespanbody"))
+ << "Wrong html to text serialization";
}
TEST(PlainTextSerializer, OneHundredAndOneOL)
@@ -359,3 +351,24 @@ TEST(PlainTextSerializer, OneHundredAndOneOL)
expected.AppendLiteral(" 1. X" NS_LINEBREAK);
ASSERT_EQ(test, expected);
}
+
+TEST(PlainTextSerializer, BlockQuoteCite)
+{
+ nsAutoString test;
+ test.AppendLiteral(u"<blockquote type=cite>hello world</blockquote>");
+
+ const uint32_t wrapColumn = 10;
+ ConvertBufToPlainText(test,
+ nsIDocumentEncoder::OutputFormatted |
+ nsIDocumentEncoder::OutputFormatFlowed |
+ nsIDocumentEncoder::OutputCRLineBreak |
+ nsIDocumentEncoder::OutputLFLineBreak,
+ wrapColumn);
+
+ constexpr auto expect = NS_LITERAL_STRING_FROM_CSTRING(
+ "> hello \r\n"
+ "> world\r\n");
+
+ ASSERT_TRUE(test.Equals(expect))
+ << "Wrong blockquote cite to text serialization";
+}
diff --git a/dom/serializers/gtest/TestPlainTextSerializerBlockQuoteCite.cpp b/dom/serializers/gtest/TestPlainTextSerializerBlockQuoteCite.cpp
@@ -1,134 +0,0 @@
-/* -*- 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/. */
-
-#include "Common.h"
-#include "gtest/gtest.h"
-#include "nsCRT.h"
-#include "nsIDocumentEncoder.h"
-#include "nsIParserUtils.h"
-#include "nsServiceManagerUtils.h"
-#include "nsString.h"
-
-TEST(PlainTextSerializerBlockQuoteCite, BlockQuoteCiteWrap)
-{
- nsAutoString test;
- test.AppendLiteral(u"<blockquote type=cite>hello world</blockquote>");
-
- const uint32_t wrapColumn = 10;
- ConvertBufToPlainText(test,
- nsIDocumentEncoder::OutputFormatted |
- nsIDocumentEncoder::OutputFormatFlowed |
- nsIDocumentEncoder::OutputCRLineBreak |
- nsIDocumentEncoder::OutputLFLineBreak,
- wrapColumn);
-
- constexpr auto expect = NS_LITERAL_STRING_FROM_CSTRING(
- "> hello \r\n"
- "> world\r\n");
-
- ASSERT_EQ(test, expect) << "Wrong blockquote cite to text serialization";
-}
-
-TEST(PlainTextSerializerBlockQuoteCite, BlockQuoteCiteNested)
-{
- nsAutoString test;
- test.AppendLiteral(
- u"<blockquote type=cite>aaa"
- u"<blockquote type=cite>bbb"
- u"<blockquote type=cite>ccc"
- u"</blockquote><pre>ddd</pre>"
- u"</blockquote>eee"
- u"</blockquote>");
-
- const uint32_t wrapColumn = 20;
- ConvertBufToPlainText(test,
- nsIDocumentEncoder::OutputFormatted |
- nsIDocumentEncoder::OutputFormatFlowed |
- nsIDocumentEncoder::OutputCRLineBreak |
- nsIDocumentEncoder::OutputLFLineBreak,
- wrapColumn);
-
- constexpr auto expect = NS_LITERAL_STRING_FROM_CSTRING(
- "> aaa\r\n"
- ">> bbb\r\n"
- ">>> ccc\r\n"
- ">> ddd\r\n"
- "> eee\r\n");
-
- ASSERT_EQ(test, expect)
- << "Wrong nested blockquote cite to text serialization";
-}
-
-TEST(PlainTextSerializerBlockQuoteCite, LineBreakAfterBlockQuoteCite)
-{
- nsAutoString test;
- test.AppendLiteral(
- u"<blockquote type=cite>hello world</blockquote>\n<pre>aaa</pre>bbb");
-
- const uint32_t wrapColumn = 20;
- ConvertBufToPlainText(test,
- nsIDocumentEncoder::OutputFormatted |
- nsIDocumentEncoder::OutputFormatFlowed |
- nsIDocumentEncoder::OutputCRLineBreak |
- nsIDocumentEncoder::OutputLFLineBreak,
- wrapColumn);
-
- constexpr auto expect = NS_LITERAL_STRING_FROM_CSTRING(
- "> hello world\r\n"
- "aaa\r\n\r\n"
- "bbb\r\n");
-
- ASSERT_EQ(test, expect) << "Wrong blockquote cite to text serialization";
-}
-
-TEST(PlainTextSerializerBlockQuoteCite, TextAfterBlockQuoteCite)
-{
- nsAutoString test;
- test.AppendLiteral(
- u"<blockquote type=cite>hello world</blockquote>aaa<pre>bbb</pre>ccc");
-
- const uint32_t wrapColumn = 20;
- ConvertBufToPlainText(test,
- nsIDocumentEncoder::OutputFormatted |
- nsIDocumentEncoder::OutputFormatFlowed |
- nsIDocumentEncoder::OutputCRLineBreak |
- nsIDocumentEncoder::OutputLFLineBreak,
- wrapColumn);
-
- constexpr auto expect = NS_LITERAL_STRING_FROM_CSTRING(
- "> hello world\r\n"
- "aaa\r\n\r\n"
- "bbb\r\n\r\n"
- "ccc\r\n");
-
- ASSERT_EQ(test, expect) << "Wrong blockquote cite to text serialization";
-}
-
-TEST(PlainTextSerializerBlockQuoteCite, SelectAfterBlockQuoteCite)
-{
- nsAutoString test;
- test.AppendLiteral(
- u"<blockquote type=cite>first blockquote</blockquote>"
- u"<select><option>aaa</option></select><pre>bbb</pre>"
- u"<blockquote type=cite>second blockquote</blockquote>"
- u"<select><option>\r\n</option></select><pre>ccc</pre>");
-
- const uint32_t wrapColumn = 20;
- ConvertBufToPlainText(test,
- nsIDocumentEncoder::OutputFormatted |
- nsIDocumentEncoder::OutputFormatFlowed |
- nsIDocumentEncoder::OutputCRLineBreak |
- nsIDocumentEncoder::OutputLFLineBreak,
- wrapColumn);
-
- constexpr auto expect = NS_LITERAL_STRING_FROM_CSTRING(
- "> first blockquote\r\n\r\n"
- "bbb\r\n"
- "> second blockquote\r\n\r\n"
- "ccc\r\n");
-
- ASSERT_EQ(test, expect) << "Wrong blockquote cite to text serialization";
-}
diff --git a/dom/serializers/gtest/moz.build b/dom/serializers/gtest/moz.build
@@ -6,7 +6,6 @@
UNIFIED_SOURCES += [
"TestPlainTextSerializer.cpp",
- "TestPlainTextSerializerBlockQuoteCite.cpp",
]
include("/ipc/chromium/chromium-config.mozbuild")
diff --git a/dom/serializers/nsPlainTextSerializer.cpp b/dom/serializers/nsPlainTextSerializer.cpp
@@ -230,8 +230,11 @@ uint32_t nsPlainTextSerializer::OutputManager::GetOutputLength() const {
nsPlainTextSerializer::nsPlainTextSerializer()
: mFloatingLines(-1),
+ mLineBreakDue(false),
kSpace(u" "_ns) // Init of "constant"
{
+ mHeadLevel = 0;
+ mHasWrittenCiteBlockquote = false;
mSpanLevel = 0;
for (int32_t i = 0; i <= 6; i++) {
mHeaderCounter[i] = 0;
@@ -252,6 +255,8 @@ nsPlainTextSerializer::nsPlainTextSerializer()
mIgnoreAboveIndex = (uint32_t)kNotFound;
mULCount = 0;
+
+ mIgnoredChildNodeLevel = 0;
}
nsPlainTextSerializer::~nsPlainTextSerializer() {
@@ -453,21 +458,6 @@ nsPlainTextSerializer::AppendText(Text* aText, int32_t aStartOffset,
return NS_OK;
}
- // If we don't want any output, just return.
- if (!DoOutput()) {
- return NS_OK;
- }
-
- if (mLineBreakDue) {
- EnsureVerticalSpace(mFloatingLines);
- }
-
- // Check whether this text node is under an element that doesn’t need to be
- // serialized. If so, we can return early here.
- if (MustSuppressLeaf()) {
- return NS_OK;
- }
-
nsAutoString textstr;
if (characterDataBuffer->Is2b()) {
textstr.Assign(characterDataBuffer->Get2b() + aStartOffset, length);
@@ -489,11 +479,11 @@ nsPlainTextSerializer::AppendText(Text* aText, int32_t aStartOffset,
while (offset != kNotFound) {
if (offset > start) {
// Pass in the line
- DoAddText(Substring(textstr, start, offset - start));
+ DoAddText(false, Substring(textstr, start, offset - start));
}
// Pass in a newline
- DoAddLineBreak();
+ DoAddText();
start = offset + 1;
offset = textstr.FindCharInSet(u"\n\r", start);
@@ -502,9 +492,9 @@ nsPlainTextSerializer::AppendText(Text* aText, int32_t aStartOffset,
// Consume the last bit of the string if there's any left
if (start < length) {
if (start) {
- DoAddText(Substring(textstr, start, length - start));
+ DoAddText(false, Substring(textstr, start, length - start));
} else {
- DoAddText(textstr);
+ DoAddText(false, textstr);
}
}
@@ -1118,37 +1108,43 @@ bool nsPlainTextSerializer::MustSuppressLeaf() const {
return false;
}
-void nsPlainTextSerializer::DoAddLineBreak() {
- MOZ_ASSERT(DoOutput());
- MOZ_ASSERT(!mLineBreakDue);
- MOZ_ASSERT(mIgnoreAboveIndex == (uint32_t)kNotFound);
- MOZ_ASSERT(!MustSuppressLeaf());
-
- // The only times we want to pass along whitespace from the original
- // html source are if we're forced into preformatted mode via flags,
- // or if we're prettyprinting and we're inside a <pre>.
- // Otherwise, either we're collapsing to minimal text, or we're
- // prettyprinting to mimic the html format, and in neither case
- // does the formatting of the html source help us.
- if (mSettings.HasFlag(nsIDocumentEncoder::OutputPreformatted) ||
- (mPreFormattedMail && !mSettings.GetWrapColumn()) ||
- IsElementPreformatted()) {
- EnsureVerticalSpace(mEmptyLines + 1);
- } else if (!mInWhitespace) {
- Write(kSpace);
- mInWhitespace = true;
+void nsPlainTextSerializer::DoAddText() { DoAddText(true, u""_ns); }
+
+void nsPlainTextSerializer::DoAddText(bool aIsLineBreak,
+ const nsAString& aText) {
+ // If we don't want any output, just return
+ if (!DoOutput()) {
+ return;
}
-}
-void nsPlainTextSerializer::DoAddText(const nsAString& aText) {
- MOZ_ASSERT(DoOutput());
- MOZ_ASSERT(!mLineBreakDue);
- MOZ_ASSERT(mIgnoreAboveIndex == (uint32_t)kNotFound);
- MOZ_ASSERT(!MustSuppressLeaf());
+ if (!aIsLineBreak) {
+ // Make sure to reset this, since it's no longer true.
+ mHasWrittenCiteBlockquote = false;
+ }
- // Reset this, as it’s no longer true after serializing texts, so the next
- // <pre> element will get a leading newline.
- mHasWrittenCiteBlockquote = false;
+ if (mLineBreakDue) EnsureVerticalSpace(mFloatingLines);
+
+ if (MustSuppressLeaf()) {
+ return;
+ }
+
+ if (aIsLineBreak) {
+ // The only times we want to pass along whitespace from the original
+ // html source are if we're forced into preformatted mode via flags,
+ // or if we're prettyprinting and we're inside a <pre>.
+ // Otherwise, either we're collapsing to minimal text, or we're
+ // prettyprinting to mimic the html format, and in neither case
+ // does the formatting of the html source help us.
+ if (mSettings.HasFlag(nsIDocumentEncoder::OutputPreformatted) ||
+ (mPreFormattedMail && !mSettings.GetWrapColumn()) ||
+ IsElementPreformatted()) {
+ EnsureVerticalSpace(mEmptyLines + 1);
+ } else if (!mInWhitespace) {
+ Write(kSpace);
+ mInWhitespace = true;
+ }
+ return;
+ }
Write(aText);
}
diff --git a/dom/serializers/nsPlainTextSerializer.h b/dom/serializers/nsPlainTextSerializer.h
@@ -123,8 +123,9 @@ class nsPlainTextSerializer final : public nsIContentSerializer {
void CloseContainerForOutputFormatted(const nsAtom* aTag);
nsresult DoAddLeaf(const nsAtom* aTag);
- void DoAddText(const nsAString& aText);
- void DoAddLineBreak();
+ void DoAddText();
+ // @param aText Ignored if aIsLineBreak is true.
+ void DoAddText(bool aIsLineBreak, const nsAString& aText);
inline bool DoOutput() const { return mHeadLevel == 0; }
@@ -149,7 +150,7 @@ class nsPlainTextSerializer final : public nsIContentSerializer {
static bool IsCssBlockLevelElement(mozilla::dom::Element* aElement);
private:
- uint32_t mHeadLevel = 0;
+ uint32_t mHeadLevel;
class Settings {
public:
@@ -322,7 +323,7 @@ class nsPlainTextSerializer final : public nsIContentSerializer {
// If we've just written out a cite blockquote, we need to remember it
// so we don't duplicate spaces before a <pre wrap> (which mail uses to quote
// old messages).
- bool mHasWrittenCiteBlockquote = false;
+ bool mHasWrittenCiteBlockquote;
int32_t mFloatingLines; // To store the number of lazy line breaks
@@ -342,7 +343,7 @@ class nsPlainTextSerializer final : public nsIContentSerializer {
// is due because of a closing tag. Setting it to "TRUE" while closing the
// tags. Hence opening tags are guaranteed to start with appropriate line
// breaks.
- bool mLineBreakDue = false;
+ bool mLineBreakDue;
bool mPreformattedBlockBoundary;
@@ -390,7 +391,7 @@ class nsPlainTextSerializer final : public nsIContentSerializer {
// serializer enters those specific nodes, mIgnoredChildNodeLevel increases
// and is greater than 0. Otherwise when serializer leaves those nodes,
// mIgnoredChildNodeLevel decreases.
- uint32_t mIgnoredChildNodeLevel = 0;
+ uint32_t mIgnoredChildNodeLevel;
};
nsresult NS_NewPlainTextSerializer(nsIContentSerializer** aSerializer);