Commit Graph

942 Commits

Author SHA1 Message Date
Masayuki Nakano
3d600c8b5d Bug 1989861 - Make HTMLEditor::EnsureNoFollowingUnnecessaryLineBreak consider a preceding <br> of a mailcite is necessary a=dmeehan
The serializer needs to make each mailcite starts from head of a line.
However, mailcite may be a blocked `<span>`.  So, its preceding `<br>`
is not required from the HTML point of view, but we need to preserve
it for the serializer.

If we need this hack in some other places, we should make
`HTMLEditUtils::GetFollowingUnnecessaryLineBreak()` aware of this
special handling in a follow up bug.

Differential Revision: https://phabricator.services.mozilla.com/D270784
2025-10-31 12:52:00 +00:00
Masayuki Nakano
8e23c15e1b Bug 1951518 - Make HTMLEditor::DeleteRangesWithTransaction stop deleting Text which has only a collapsible white-space r=m_kato
In bug 1925635, I moved the post processing after deleting ranges in
`EditorBase::DeleteRangesWithTransaction` into the `HTMLEditor`'s override.
At this time, I makes it uses `HTMLEditUtils::IsEmptyNode` to check whether
the `Text` and its containers become empty. Therefore, if `Ctrl`+`Backspace`
deletes the only word in the `Text` which starts with a collapsible white-space
causes deleting the `Text` after deleting all visible characters in the `Text`.

Therefore, this makes check it with `Text::TextDataLength` too before searching
the most distant ancestor inline element which becomes empty.

However, it may cause leading invisible white-spaces of the only word visible
because `nsFrameSelection` computes the word range strictly in the `Text`.
Therefore, this patch also makes `HTMLEditor::DeleteRangesWithTransaction` and
`AutoDeleteRangesHandler::ComputeRangesToDeleteRangesWithTransaction` extend
each range to delete to include surrounding invisible white-spaces too.

Therefore, this patch adds the new method to `AutoClonedRangeArray`.

Then, I hit 4 existing bugs with new test failures.

One is `HTMLEditUtils::LineRequiresPaddingLineBreakToBeVisible`.  It checks
whether the candidate point to insert a `<br>` is followed by a block boundary
first.  Then, it checks whether the candidate point follows a collapsible
white-space or a block boundary.  However, it uses
`WSRunScanner::ScanPreviousVisibleNodeOrBlockBoundary()` which ignores invisible
white-spaces.  Therefore, it will ignore the new invisible white-space and
reaches preceding `Text`.  Thus, it fails to put a `<br>` and makes the new
invisible white-space "fixed" as invisible.

Therefore, this patch rewrites the check with using
`HTMLEditUtils::GetPreviousLeafContentOrPreviousBlockElement()`.

Next one is, `HTMLEditor::DeleteEmptyInclusiveAncestorInlineElements()`
returns end of deleted node if it's followed by a non-editable node, i.e.,
an element has `contenteditable="false"`.  Therefore, its caller inserts a
`<br>` to the end of the container when deleting preceding editable node of a
non-editable node.

Therefore, this patch removes the editable state check.

Next, `AutoBlockElementsJoiner::HandleDeleteNonCollapsedRange` may put a padding
`<br>` after the moved line, but it does not assume that the moved line does not
ends with a block boundary.  This causes failing #46 and #48 tests in
`text_bug772796.html`.  E.g., when pressing `Delete` in
`<div>foo[]<div><span style="white-space:pre"><div>bar</div>baz</span>`, we move
the second `<div>` as a child of the parent `<span>` to end of the first `<div>`
like `<div>foo<span style="white-space:pre"><div>bar</div></span></div>...`.
Without the change, it starts to put unnecessary `<br>` after ` the `<span>`
because of the bug fix in `HTMLEditUtils::LineRequiresPaddingLineBreakToBeVisible`
above.  This result is completely odd from the users point of view (looks like
just move caret), but we should avoid to put the unnecessary `<br>`.

Finally, we'll fail an assertion when putting caret at the last of
`AutoBlockElementsJoiner::DeleteContentInRange` because it forgets to flush
the tracking range before using it. This appeared by the changes above.

Therefore, this patch fixes this bug too.

Differential Revision: https://phabricator.services.mozilla.com/D240703
2025-03-17 23:02:10 +00:00
Masayuki Nakano
9add283d50 Bug 1954413 - Get rid of nsINode::GetChromeOnlyAccessSubtreeRootParent() r=smaug
It's an alias of `nsINode::GetClosestNativeAnonymousSubtreeRootParentOrHost()`
and oddly it returns `const nsIContent*` rather than `nsIContent*`.  Therefore,
some callers need to use `const_cast`.

Differential Revision: https://phabricator.services.mozilla.com/D241776
2025-03-17 12:49:58 +00:00
Masayuki Nakano
a5637890c7 Bug 1946001 - Fix some points which may cross independent selection boundary r=emilio,jjaschke
This patch fixes multiple points which may cross independent selection
boundaries which is element boundary of the native anonymous `<div>` for
editable content in text controls.  The reason why I don't split this patch is,
fixing one of them leads another assertion failure.  So, I couldn't pass all
tests with separated patches.

1. `nsFrameTraversal` should take `Element` instead of `nsIFrame` for the
limiter because e.g., inline editing host like `<span contenteditable>` may
have multiple frames if it's wrapped.  Therefore, we should make it take
an element as the ancestor limiter, and check it when getting parent frame
or after getting previous or next frame.
2. `nsIFrame::PeekBackwardAndForward` may cross the boundary because it does not
take the anonymous `<div>` element as ancestor limiter of the selection.  It's
currently used only for extending selection.  Therefore, I rename it to make
it clearer.
3. `SelectionMovementUtils::GetPrevNextBidiLevel` to take the ancestor limiter
for calling `nsIFrame::GetFrameFromDirection()`.
4. `nsINode` should have a method to return the `nsFrameSelection` instance
which manages the selection in the node.  This makes the check simpler, and
this is not expensive.  Then, for making it clearer, I rename
`TextControlElement::GetConstFrameSelection()` to
`GetIndependentFrameSelection()`.
5. `nsINode::GetSelectionRootContent()` should have an option to return
independent selection root when the node is its host for
`nsFrameSelection::ConstrainFrameAndPointToAnchorSubtree()`
6. `nsFrameSelection::ConstrainFrameAndPointToAnchorSubtree()` should not
retrieve independent selection root when the given frame is a text control
frame.
7. `RangeUtils` should get parent with checking the independent selection
boundaries.
8. `Selection::Extend` should assert if the destination is managed by its
frame selection to detect a bug.

Differential Revision: https://phabricator.services.mozilla.com/D241587
2025-03-17 12:49:57 +00:00
Tom Schuster
b8d11d463f Bug 1951893 - Remove unneeded StaticAtom suffixes. r=emilio
Differential Revision: https://phabricator.services.mozilla.com/D240598
2025-03-11 11:36:09 +00:00
Masayuki Nakano
de3eb719c4 Bug 1951007 - Make style editing commands check whether the editing host is contenteditable="plaintext-only" to consider whether it's enabled r=m_kato
The style editing commands should be disabled in
`contenteditable="plaintext-only"`.  Currently, we return `false` from
`execCommand`, but we still claim that the commands are enabled for
`queryCommandEnabled`.

Differential Revision: https://phabricator.services.mozilla.com/D239985
2025-03-10 06:06:16 +00:00
Masayuki Nakano
b2e66c86f6 Bug 1940377 - part 8: Make HTMLEditor stop normalizing white-spaces during initialization r=m_kato
Enabling the new normalizer causes this assertion failure:
```
###!!! ASSERTION: Want to fire DOMNodeRemoved event, but it's not safe: 'Error', file /builds/worker/checkouts/gecko/dom/base/nsContentUtils.cpp:5586
#01: NS_DebugBreak [xpcom/base/nsDebugImpl.cpp:508]
#02: nsContentUtils::MaybeFireNodeRemoved(nsINode*, nsINode*) [dom/base/nsContentUtils.cpp:5587]
#03: nsINode::RemoveChild(nsINode&, mozilla::ErrorResult&) [dom/base/nsINode.cpp:0]
#04: mozilla::DeleteNodeTransaction::DoTransaction() [editor/libeditor/DeleteNodeTransaction.cpp:112]
#05: mozilla::EditorBase::DoTransactionInternal(nsITransaction*) [editor/libeditor/EditorBase.cpp:929]
#06: mozilla::EditorBase::DeleteNodeWithTransaction(nsIContent&) [editor/libeditor/EditorBase.cpp:2685]
#07: mozilla::WhiteSpaceVisibilityKeeper::NormalizeWhiteSpacesToSplitTextNodeAt(mozilla::HTMLEditor&, mozilla::EditorDOMPointBase<RefPtr<mozilla::dom::Text>, nsIContent*> const&, mozilla::EnumSet<mozilla::WhiteSpaceVisibilityKeeper::NormalizeOption, unsigned int>) [editor/libeditor/WhiteSpaceVisibilityKeeper.cpp:1384]
#08: mozilla::WhiteSpaceVisibilityKeeper::NormalizeWhiteSpacesToSplitAt(mozilla::HTMLEditor&, mozilla::EditorDOMPointBase<nsCOMPtr<nsINode>, nsCOMPtr<nsIContent> > const&, mozilla::EnumSet<mozilla::WhiteSpaceVisibilityKeeper::NormalizeOption, unsigned int>) [editor/libeditor/WhiteSpaceVisibilityKeeper.cpp:1599]
#09: mozilla::HTMLEditor::PrepareToInsertLineBreak(mozilla::HTMLEditor::LineBreakType, mozilla::EditorDOMPointBase<nsCOMPtr<nsINode>, nsCOMPtr<nsIContent> > const&) [editor/libeditor/HTMLEditor.cpp:4418]
#10: mozilla::EditorBase::InsertPaddingBRElementForEmptyLastLineWithTransaction(mozilla::EditorDOMPointBase<nsCOMPtr<nsINode>, nsCOMPtr<nsIContent> > const&) [editor/libeditor/EditorBase.cpp:2511]
#11: mozilla::HTMLEditor::InsertBRElementToEmptyListItemsAndTableCellsInRange(mozilla::RangeBoundaryBase<nsINode*, nsIContent*> const&, mozilla::RangeBoundaryBase<nsINode*, nsIContent*> const&) [editor/libeditor/HTMLEditSubActionHandler.cpp:0]
#12: mozilla::HTMLEditor::InitEditorContentAndSelection() [editor/libeditor/HTMLEditSubActionHandler.cpp:187]
#13: mozilla::HTMLEditor::Init(mozilla::dom::Document&, mozilla::ComposerCommandsUpdater&, unsigned int) [editor/libeditor/HTMLEditor.cpp:412]
#14: nsEditingSession::SetupEditorOnWindow(nsPIDOMWindowOuter&) [editor/composer/nsEditingSession.cpp:405]
```

The initialization is required only for empty table cells and empty list items
and they are typically not used at initial document.  So, I think that it's fine
to stop normalizing white-spaces before succeeded to initialize `HTMLEditor`.

If this change causes a web-compat issue in the wild, let's make it run
asynchronously.

Differential Revision: https://phabricator.services.mozilla.com/D239473
2025-03-08 22:31:57 +00:00
Masayuki Nakano
2e3d9fe6d5 Bug 1940377 - part 6: Make delete handlers use the new white-space normalizer r=m_kato
Unfortunately, this patch becomes big because this includes multiple utility
methods to normalize white-spaces and touching a lot of places.

In some edge cases, this starts failing when the new white-space normalizer is
enabled.

```
FAIL execCommand("forwarddelete", false, ""): "a &nbsp;[] |&nbsp; &nbsp;b" - assert_equals: Modified text is wrong expected "a &nbsp;" but got "a&nbsp;&nbsp;"
FAIL execCommand("forwarddelete", false, ""): "a&nbsp;&nbsp;&nbsp;[]&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;b" - assert_equals: Modified text is wrong expected "a&nbsp;&nbsp;&nbsp;" but got "a&nbsp; &nbsp;"
FAIL execCommand("forwarddelete", false, ""): "a&nbsp;&nbsp;&nbsp;[]b|&nbsp;&nbsp;&nbsp;&nbsp;c" - assert_equals: Modified text is wrong expected "a&nbsp;&nbsp;&nbsp;" but got "a&nbsp; &nbsp;"
FAIL execCommand("forwarddelete", false, ""): "a&nbsp;&nbsp;&nbsp;[]&nbsp;<span style=white-space:pre;>   </span>" - assert_equals: expected "a&nbsp;&nbsp;&nbsp;<span style=\"white-space:pre;\">   </span>" but got "a&nbsp; &nbsp;<span style=\"white-space:pre;\">   </span>"
```
In these failures, we normalize the trailing white-spaces of the preceding
`Text` too, but Chrome does not do that.  However, in some cases, they do
in similar cases.  Therefore, it's hard to align all cases due to the handling
order difference.  Additionally, these failure results are not odd.  So, these
new failures are acceptable.

```
FAIL execCommand("forwarddelete", false, ""): "<span>abc[]&nbsp;<span> &nbsp;def</span></span>" - assert_equals: expected "<span>abc<span>&nbsp; def</span></span>" but got "<span>abc<span> &nbsp;def</span></span>"
FAIL execCommand("forwarddelete", false, ""): "<span><span>abc[]&nbsp;</span> &nbsp;def</span>" - assert_equals: expected "<span><span>abc</span>&nbsp; def</span>" but got "<span><span>abc</span> &nbsp;def</span>"
FAIL execCommand("forwarddelete", false, ""): "<span>abc[]&nbsp;</span><span> &nbsp;def</span>" - assert_equals: expected "<span>abc</span><span>&nbsp; def</span>" but got "<span>abc</span><span> &nbsp;def</span>"
FAIL execCommand("forwarddelete", false, ""): "<span>abc[]&nbsp; </span><span>&nbsp;&nbsp;def</span>" - assert_equals: expected "<span>abc&nbsp;</span><span>&nbsp;&nbsp;def</span>" but got "<span>abc </span><span>&nbsp;&nbsp;def</span>"

```
In these failures, we don't normalize the leading white-spaces of the following
`Text`.  However, Chrome does so in some other cases.  So, it's hard to align
the behavior in these cases too.  The new normalizer ensures that the preceding
`Text` ends with a visible char.  Therefore, the following `Text` won't starts
with new invisible white-spaces.  Therefore, these failures are also acceptable.

```
FAIL execCommand("forwarddelete", false, ""): "<span style=white-space:pre;>  [] </span>&nbsp;&nbsp;&nbsp;a" - assert_equals: expected "<span style=\"white-space:pre;\">  </span>&nbsp; &nbsp;a" but got "<span style=\"white-space:pre;\">  </span>&nbsp;&nbsp;&nbsp;a"
```
In this failure, we don't normalize the following `Text` but Chrome does it.
However, I don't think we should do it because this updates the `Text` which
is preformatted.  Therefore, this is also acceptable.

So, I think that we can accept all new failures.

Differential Revision: https://phabricator.services.mozilla.com/D239468
2025-03-08 22:31:56 +00:00
Masayuki Nakano
1dc6c56a97 Bug 1940377 - part 5: Make HTMLEditor::InsertElementAtSelectionAsAction normalize white-spaces around the insertion point if the new normalizer is enabled r=m_kato
Surprisingly, it has not normalize white-spaces around it. So, in some edge
cases, it might cause changing visibility of surrounding white-spaces.

Differential Revision: https://phabricator.services.mozilla.com/D239467
2025-03-08 22:31:56 +00:00
Masayuki Nakano
e8e8d245bc Bug 1940377 - part 3: Make "insert paragraph" handlers use the new normalizer if it's enabled r=m_kato
Unfortunately, this change does not make
`white-spaces-after-execCommand-insertparagraph.tentative.html` pass because
the insert paragraph handler inserts a temporary `<br>` element and that causes
normalizing the following white-spaces at the split point.  However, Chrome
does not normalize the following white-spaces if it begins with an NBSP.

Differential Revision: https://phabricator.services.mozilla.com/D239465
2025-03-08 22:31:55 +00:00
Masayuki Nakano
5d714df94f Bug 1940377 - part 2: Make HandleInsertLineBreak use the new normalizer if it's available r=m_kato
When inserting a `<br>` element or a preformatted line break at middle of a
`Text`, we need to split it first.  At this time, we should normalize the
surrounding white-spaces before split.  Then, we can use only one
`ReplaceTextTransaction` instance for the normalization in the most cases.

Differential Revision: https://phabricator.services.mozilla.com/D239464
2025-03-08 22:31:54 +00:00
Masayuki Nakano
c0723c81ee Bug 1940377 - part 1: Make WhiteSpaceVisibilityKeeper::InsertTextOrInsertOrUpdateCompositionString support blink compatible white-space sequence r=m_kato
First, it makes it deletes invisible white-spaces at the insertion point.
This makes the further processing simpler.

Second, it extends the range to update in `Text` which will contain the
insertion string when it's not used for inserting nor updating composition
string, as containing all surrounding white-spaces at the insertion point.

Next, it normalizes the inserting string with the surrounding white-spaces with
the same rules as the other browsers especially as Chrome.
1. a collapsible white-space at start or end of a `Text` is always an NBSP.
2. a collapsible white-space immediately before or after a preformatted line
break is always an NBSP.
3. a collapsible white-space surrounded by non-collapsible chars is always an
ASCII white-space.
4. collapsible white-spaces are pairs of an NBSP and an ASCII white-space.

Then, we can make `HTMLEditor::OnEndHandlingTopLevelEditSubActionInternal()`
stop normalizing white-spaces when inserting text.

Differential Revision: https://phabricator.services.mozilla.com/D239463
2025-03-08 22:31:54 +00:00
Goloman Adrian
2973813822 Backed out 9 changesets (bug 1940377) for causing wpt failures @elete-to-join-blocks.tentative.html.
Backed out changeset c08fbe668983 (bug 1940377)
Backed out changeset afe170b7d586 (bug 1940377)
Backed out changeset fbd25039fe81 (bug 1940377)
Backed out changeset 9cec5876c849 (bug 1940377)
Backed out changeset d4eabf000418 (bug 1940377)
Backed out changeset d6b44f519481 (bug 1940377)
Backed out changeset a3fd780478a3 (bug 1940377)
Backed out changeset 80dba0103823 (bug 1940377)
Backed out changeset d06e8bb673e8 (bug 1940377)
2025-03-08 08:25:13 +02:00
Masayuki Nakano
e1671a4314 Bug 1183844 - Make backColor getter method never stop scanning ancestors of the closest ancestor block r=m_kato
Chrome returns `background-color` value either inline and block even in the
HTML styling mode and even if the ancestor is outside of the editing host.
However, our handler stops at the closest inclusive ancestor block to scan
the `background-color` [1] and we don't scan background color if it's in the
HTML styling mode [2].

The latter could be expected by Thunderbird.  Therefore, this patch does not
change the behavior if it's a mail editor.

1. https://searchfox.org/mozilla-central/rev/405d0b26a98dec92d8009b38a8ad1c1609475f1e/editor/libeditor/HTMLEditor.cpp#2810-2816
2. https://searchfox.org/mozilla-central/rev/405d0b26a98dec92d8009b38a8ad1c1609475f1e/editor/libeditor/HTMLEditor.cpp#2688-2689

Differential Revision: https://phabricator.services.mozilla.com/D239867
2025-03-08 04:13:24 +00:00
Masayuki Nakano
521972f410 Bug 1940377 - part 8: Make HTMLEditor stop normalizing white-spaces during initialization r=m_kato
Enabling the new normalizer causes this assertion failure:
```
###!!! ASSERTION: Want to fire DOMNodeRemoved event, but it's not safe: 'Error', file /builds/worker/checkouts/gecko/dom/base/nsContentUtils.cpp:5586
#01: NS_DebugBreak [xpcom/base/nsDebugImpl.cpp:508]
#02: nsContentUtils::MaybeFireNodeRemoved(nsINode*, nsINode*) [dom/base/nsContentUtils.cpp:5587]
#03: nsINode::RemoveChild(nsINode&, mozilla::ErrorResult&) [dom/base/nsINode.cpp:0]
#04: mozilla::DeleteNodeTransaction::DoTransaction() [editor/libeditor/DeleteNodeTransaction.cpp:112]
#05: mozilla::EditorBase::DoTransactionInternal(nsITransaction*) [editor/libeditor/EditorBase.cpp:929]
#06: mozilla::EditorBase::DeleteNodeWithTransaction(nsIContent&) [editor/libeditor/EditorBase.cpp:2685]
#07: mozilla::WhiteSpaceVisibilityKeeper::NormalizeWhiteSpacesToSplitTextNodeAt(mozilla::HTMLEditor&, mozilla::EditorDOMPointBase<RefPtr<mozilla::dom::Text>, nsIContent*> const&, mozilla::EnumSet<mozilla::WhiteSpaceVisibilityKeeper::NormalizeOption, unsigned int>) [editor/libeditor/WhiteSpaceVisibilityKeeper.cpp:1384]
#08: mozilla::WhiteSpaceVisibilityKeeper::NormalizeWhiteSpacesToSplitAt(mozilla::HTMLEditor&, mozilla::EditorDOMPointBase<nsCOMPtr<nsINode>, nsCOMPtr<nsIContent> > const&, mozilla::EnumSet<mozilla::WhiteSpaceVisibilityKeeper::NormalizeOption, unsigned int>) [editor/libeditor/WhiteSpaceVisibilityKeeper.cpp:1599]
#09: mozilla::HTMLEditor::PrepareToInsertLineBreak(mozilla::HTMLEditor::LineBreakType, mozilla::EditorDOMPointBase<nsCOMPtr<nsINode>, nsCOMPtr<nsIContent> > const&) [editor/libeditor/HTMLEditor.cpp:4418]
#10: mozilla::EditorBase::InsertPaddingBRElementForEmptyLastLineWithTransaction(mozilla::EditorDOMPointBase<nsCOMPtr<nsINode>, nsCOMPtr<nsIContent> > const&) [editor/libeditor/EditorBase.cpp:2511]
#11: mozilla::HTMLEditor::InsertBRElementToEmptyListItemsAndTableCellsInRange(mozilla::RangeBoundaryBase<nsINode*, nsIContent*> const&, mozilla::RangeBoundaryBase<nsINode*, nsIContent*> const&) [editor/libeditor/HTMLEditSubActionHandler.cpp:0]
#12: mozilla::HTMLEditor::InitEditorContentAndSelection() [editor/libeditor/HTMLEditSubActionHandler.cpp:187]
#13: mozilla::HTMLEditor::Init(mozilla::dom::Document&, mozilla::ComposerCommandsUpdater&, unsigned int) [editor/libeditor/HTMLEditor.cpp:412]
#14: nsEditingSession::SetupEditorOnWindow(nsPIDOMWindowOuter&) [editor/composer/nsEditingSession.cpp:405]
```

The initialization is required only for empty table cells and empty list items
and they are typically not used at initial document.  So, I think that it's fine
to stop normalizing white-spaces before succeeded to initialize `HTMLEditor`.

If this change causes a web-compat issue in the wild, let's make it run
asynchronously.

Differential Revision: https://phabricator.services.mozilla.com/D239473
2025-03-08 00:23:17 +00:00
Masayuki Nakano
f8da424b74 Bug 1940377 - part 6: Make delete handlers use the new white-space normalizer r=m_kato
Unfortunately, this patch becomes big because this includes multiple utility
methods to normalize white-spaces and touching a lot of places.

In some edge cases, this starts failing when the new white-space normalizer is
enabled.

```
FAIL execCommand("forwarddelete", false, ""): "a &nbsp;[] |&nbsp; &nbsp;b" - assert_equals: Modified text is wrong expected "a &nbsp;" but got "a&nbsp;&nbsp;"
FAIL execCommand("forwarddelete", false, ""): "a&nbsp;&nbsp;&nbsp;[]&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;b" - assert_equals: Modified text is wrong expected "a&nbsp;&nbsp;&nbsp;" but got "a&nbsp; &nbsp;"
FAIL execCommand("forwarddelete", false, ""): "a&nbsp;&nbsp;&nbsp;[]b|&nbsp;&nbsp;&nbsp;&nbsp;c" - assert_equals: Modified text is wrong expected "a&nbsp;&nbsp;&nbsp;" but got "a&nbsp; &nbsp;"
FAIL execCommand("forwarddelete", false, ""): "a&nbsp;&nbsp;&nbsp;[]&nbsp;<span style=white-space:pre;>   </span>" - assert_equals: expected "a&nbsp;&nbsp;&nbsp;<span style=\"white-space:pre;\">   </span>" but got "a&nbsp; &nbsp;<span style=\"white-space:pre;\">   </span>"
```
In these failures, we normalize the trailing white-spaces of the preceding
`Text` too, but Chrome does not do that.  However, in some cases, they do
in similar cases.  Therefore, it's hard to align all cases due to the handling
order difference.  Additionally, these failure results are not odd.  So, these
new failures are acceptable.

```
FAIL execCommand("forwarddelete", false, ""): "<span>abc[]&nbsp;<span> &nbsp;def</span></span>" - assert_equals: expected "<span>abc<span>&nbsp; def</span></span>" but got "<span>abc<span> &nbsp;def</span></span>"
FAIL execCommand("forwarddelete", false, ""): "<span><span>abc[]&nbsp;</span> &nbsp;def</span>" - assert_equals: expected "<span><span>abc</span>&nbsp; def</span>" but got "<span><span>abc</span> &nbsp;def</span>"
FAIL execCommand("forwarddelete", false, ""): "<span>abc[]&nbsp;</span><span> &nbsp;def</span>" - assert_equals: expected "<span>abc</span><span>&nbsp; def</span>" but got "<span>abc</span><span> &nbsp;def</span>"
FAIL execCommand("forwarddelete", false, ""): "<span>abc[]&nbsp; </span><span>&nbsp;&nbsp;def</span>" - assert_equals: expected "<span>abc&nbsp;</span><span>&nbsp;&nbsp;def</span>" but got "<span>abc </span><span>&nbsp;&nbsp;def</span>"

```
In these failures, we don't normalize the leading white-spaces of the following
`Text`.  However, Chrome does so in some other cases.  So, it's hard to align
the behavior in these cases too.  The new normalizer ensures that the preceding
`Text` ends with a visible char.  Therefore, the following `Text` won't starts
with new invisible white-spaces.  Therefore, these failures are also acceptable.

```
FAIL execCommand("forwarddelete", false, ""): "<span style=white-space:pre;>  [] </span>&nbsp;&nbsp;&nbsp;a" - assert_equals: expected "<span style=\"white-space:pre;\">  </span>&nbsp; &nbsp;a" but got "<span style=\"white-space:pre;\">  </span>&nbsp;&nbsp;&nbsp;a"
```
In this failure, we don't normalize the following `Text` but Chrome does it.
However, I don't think we should do it because this updates the `Text` which
is preformatted.  Therefore, this is also acceptable.

So, I think that we can accept all new failures.

Differential Revision: https://phabricator.services.mozilla.com/D239468
2025-03-08 00:23:16 +00:00
Masayuki Nakano
3ad48f7385 Bug 1940377 - part 5: Make HTMLEditor::InsertElementAtSelectionAsAction normalize white-spaces around the insertion point if the new normalizer is enabled r=m_kato
Surprisingly, it has not normalize white-spaces around it. So, in some edge
cases, it might cause changing visibility of surrounding white-spaces.

Differential Revision: https://phabricator.services.mozilla.com/D239467
2025-03-08 00:23:16 +00:00
Masayuki Nakano
e14afee1c1 Bug 1940377 - part 3: Make "insert paragraph" handlers use the new normalizer if it's enabled r=m_kato
Unfortunately, this change does not make
`white-spaces-after-execCommand-insertparagraph.tentative.html` pass because
the insert paragraph handler inserts a temporary `<br>` element and that causes
normalizing the following white-spaces at the split point.  However, Chrome
does not normalize the following white-spaces if it begins with an NBSP.

Differential Revision: https://phabricator.services.mozilla.com/D239465
2025-03-08 00:23:15 +00:00
Masayuki Nakano
cb5f775b5c Bug 1940377 - part 2: Make HandleInsertLineBreak use the new normalizer if it's available r=m_kato
When inserting a `<br>` element or a preformatted line break at middle of a
`Text`, we need to split it first.  At this time, we should normalize the
surrounding white-spaces before split.  Then, we can use only one
`ReplaceTextTransaction` instance for the normalization in the most cases.

Differential Revision: https://phabricator.services.mozilla.com/D239464
2025-03-08 00:23:15 +00:00
Masayuki Nakano
f7f5dd6a64 Bug 1940377 - part 1: Make WhiteSpaceVisibilityKeeper::InsertTextOrInsertOrUpdateCompositionString support blink compatible white-space sequence r=m_kato
First, it makes it deletes invisible white-spaces at the insertion point.
This makes the further processing simpler.

Second, it extends the range to update in `Text` which will contain the
insertion string when it's not used for inserting nor updating composition
string, as containing all surrounding white-spaces at the insertion point.

Next, it normalizes the inserting string with the surrounding white-spaces with
the same rules as the other browsers especially as Chrome.
1. a collapsible white-space at start or end of a `Text` is always an NBSP.
2. a collapsible white-space immediately before or after a preformatted line
break is always an NBSP.
3. a collapsible white-space surrounded by non-collapsible chars is always an
ASCII white-space.
4. collapsible white-spaces are pairs of an NBSP and an ASCII white-space.

Then, we can make `HTMLEditor::OnEndHandlingTopLevelEditSubActionInternal()`
stop normalizing white-spaces when inserting text.

Differential Revision: https://phabricator.services.mozilla.com/D239463
2025-03-08 00:23:14 +00:00
Masayuki Nakano
b1c038ee42 Bug 1949901 - Hide selection changes from web apps which are caused by the hacks of HTMLEditor r=m_kato
The hacks are only for specific web apps.  Therefore, unless they require to
know the selection changes, we don't need to expose that.

Differential Revision: https://phabricator.services.mozilla.com/D239835
2025-02-27 08:07:10 +00:00
Florian Quèze
84cb1ba88b Bug 1944631 - Migrate histograms to use Glean APIs for HTMLEDITORS_*, r=chutten.
Differential Revision: https://phabricator.services.mozilla.com/D238654
2025-02-25 15:27:52 +00:00
Masayuki Nakano
de4057edf4 Bug 1948172 - Use editable point when suggesting caret point r=m_kato
If I run `./mach wpt testing/web-platform/tests/editing` with just enabling the
new normalizer, I see some assertion failures which are caused by scanning or
updating non-editable regions.

According to the debug result, it's caused by sometimes caret point is suggested
in non-editable node and further handling will use various utilities which
asserts whether the target is editable.

Ideally, we should add assertion into `CaretPoint`, but it's hard and I don't
have enough time to fix every regression which will be found by fuzzing tests
even though most of them are not so important in the real web apps.  Therefore,
this fixes only the causes which I found in the WPTs.

Differential Revision: https://phabricator.services.mozilla.com/D238408
2025-02-20 02:08:33 +00:00
Masayuki Nakano
f7daa6d35b Bug 1947106 - Make the hack for bug 1938110 and bug 1940278 run only when we use the legacy white-space normalizer r=m_kato
The hacks are required only for the other legacy behavior which uses ASCII
white-space even before a block boundary but with a padding `<br>` element.
Therefore, once we use the Blink compare behavior, it'll put an NBSP without
a padding `<br>`, we don't need them anymore.

Differential Revision: https://phabricator.services.mozilla.com/D237523
2025-02-12 06:47:32 +00:00
Masayuki Nakano
ad9fbd6b1a Bug 1947099 - Get rid of unused aDocument parameter of EditorBase::InsertTextWithTransaction r=m_kato
Differential Revision: https://phabricator.services.mozilla.com/D237518
2025-02-11 23:42:53 +00:00
Masayuki Nakano
da4abce2d9 Bug 1945714 - Rename RangeBoundaryBase::Container() to GetContainer() r=jjaschke,dom-core
Usually, we name methods as `GetFoo()` if they may return `nullptr`, on the
other hand, we name methods as `Foo()` if they won't return `nullptr`.

`RangeBoundaryBase::Container()` may return `nullptr`.  So, this name may cause
misleading of some developers.  Let's rename it as `GetContainer()`.

This does not change anything for avoiding merge conflict with the other
landings.

Differential Revision: https://phabricator.services.mozilla.com/D236796
2025-02-10 01:29:40 +00:00
Masayuki Nakano
af8a5eb1a9 Bug 1944737 - Make the mutation observers of HTMLEditor stop creating AutoEditActionDataSetter r=m_kato
They grabs `Selection`, but that appears in the profile.  Fortunately, we
don't require the instance in the methods including the callees.  Therefore,
we don't need to create it at every mutation.

Differential Revision: https://phabricator.services.mozilla.com/D236095
2025-02-04 01:02:05 +00:00
Jan-Niklas Jaeschke
6624852dc9 Bug 1943179 - Add [[nodiscard]] to ContentIterator methods that return nsresult. r=masayuki
Differential Revision: https://phabricator.services.mozilla.com/D235361
2025-01-28 18:26:31 +00:00
Sandor Molnar
829c6cdf91 Backed out changeset afeecd52c4a7 (bug 1943179) for causing build bustages @ FilteredContentIterator.cpp CLOSED TREE 2025-01-28 18:24:33 +02:00
Jan-Niklas Jaeschke
d85b643e72 Bug 1943179 - Add [[nodiscard]] to ContentIterator methods that return nsresult. r=masayuki
Differential Revision: https://phabricator.services.mozilla.com/D235361
2025-01-28 15:54:36 +00:00
Emilio Cobos Álvarez
d5d33843fb Bug 1943542 - Remove contenteditable / EditorOverride sheet. r=masayuki
Move the relevant bits to html.css or other UA sheets, and use faster
things than attribute selectors (read: classes) for resizers and such
things.

The hidden class can just be a hidden attribute since we don't otherwise
style these.

The cursor can just be set at the resizer / grabber creation time.

One known behavior change other than this is not styling using the
_moz_abspos attribute. The reasoning for this is that these are content
nodes, and in general having these kinds of rules for content nodes
isn't great. E.g. these two pages behave differently:

 * data:text/html,<div _moz_abspos=black>boo</div>
 * data:text/html,<div _moz_abspos=black>boo</div><div contenteditable></div>

We could use the style attribute for this, I suppose, just like we set
the position or what not, but then we need to save / restore as needed
or something. I'd rather not change the stacking order or backgrounds or
what not, too.

If you feel very strongly about that piece of functionality of the
abspos editor I could try to restore it somehow. But I honestly rather
not.

The rest of the stuff should just work.

Differential Revision: https://phabricator.services.mozilla.com/D235319
2025-01-26 12:31:18 +00:00
Masayuki Nakano
b67e405f29 Bug 1926483 - part 4: Make WSRunScanner::Scan(InclusiveNext|Previous)VisibleNodeOrBlockBoundary take WSRunScanner::Scan and ancestor limiter r=m_kato
Note that this removes a lot of `aEditingHost` params.  This may cause odd
behavior if editing host is changed by a legacy mutation event listener.
However, it'll be completely deleted soon and even if we meet some regressions,
we can just restore the param to set `aAncestorLimiter`.

Differential Revision: https://phabricator.services.mozilla.com/D233794
2025-01-24 05:00:48 +00:00
Masayuki Nakano
395226db0c Bug 1926483 - part 1: Make WSRunScanner instance free from editing host r=m_kato
If it scans starting from a editable point, it does not require the editing
host as an ancestor limiter.  Therefore, some users can be free from editing
host.

Differential Revision: https://phabricator.services.mozilla.com/D233791
2025-01-24 05:00:47 +00:00
Masayuki Nakano
2b503ca56d Bug 1943226 - Make nsFrameSelection treat limiters are elements r=jjaschke,dom-core
`nsFrameSelection::GetLimiter()` is not `nullptr` only when it's an instance for
an independent selection of a text control.  In the case, it's set to the editor
root anonymous `<div>` of the text control.  Despite the name, this is already
optimized only for this purpose in `nsFrameSelection::NodeIsInLimiters()`.
Thus, we don't have any problems to make this clearer for the other developers
with renaming some parameter names.

`nsFrameSelection::GetAncestorLimiter()` is also always an `Element`.  So,
we can change this to `Element` too.

Differential Revision: https://phabricator.services.mozilla.com/D235254
2025-01-24 02:53:07 +00:00
Masayuki Nakano
4e6fcb1183 Bug 1943228 - Rename methods GetSomethingWithoutCreation() to GetExtantSomething() r=edgar,dom-core
Differential Revision: https://phabricator.services.mozilla.com/D235256
2025-01-23 23:47:28 +00:00
Butkovits Atila
173aee505b Backed out 5 changesets (bug 1926483) for causing failures at WSRunScanner.h. CLOSED TREE
Backed out changeset fa4c36cef1c5 (bug 1926483)
Backed out changeset 24bdcd7af3e0 (bug 1926483)
Backed out changeset 1df51ca968f8 (bug 1926483)
Backed out changeset 7aceecb585e4 (bug 1926483)
Backed out changeset 41b040b374a2 (bug 1926483)
2025-01-23 07:35:22 +02:00
Masayuki Nakano
8e2501c776 Bug 1926483 - part 4: Make WSRunScanner::Scan(InclusiveNext|Previous)VisibleNodeOrBlockBoundary take WSRunScanner::Scan and ancestor limiter r=m_kato
Note that this removes a lot of `aEditingHost` params.  This may cause odd
behavior if editing host is changed by a legacy mutation event listener.
However, it'll be completely deleted soon and even if we meet some regressions,
we can just restore the param to set `aAncestorLimiter`.

Differential Revision: https://phabricator.services.mozilla.com/D233794
2025-01-23 05:01:57 +00:00
Masayuki Nakano
d36ef81488 Bug 1926483 - part 1: Make WSRunScanner instance free from editing host r=m_kato
If it scans starting from a editable point, it does not require the editing
host as an ancestor limiter.  Therefore, some users can be free from editing
host.

Differential Revision: https://phabricator.services.mozilla.com/D233791
2025-01-23 05:01:56 +00:00
Masayuki Nakano
bd4fdbf30a Bug 1939220 - part 3: Make TextFragmentData::BoundaryData not depend on the editing host r=m_kato
Its role is scanning the DOM.  Therefore, it can know which node is an editing
host during a scan.  Therefore, it does not require the editing host parameter.
To fix that, some utility methods of `HTMLEditUtils` needs to work with
non-editable nodes.  Therefore, this patch also updates `HTMLEditUtils`.

Finally, this gets rid of the `NS_ASSERTION`s in the constructor of
`TextFragmentData` because it'll be available with non-editable nodes too.
Although current all callers assume that it works as in an editing host.

Differential Revision: https://phabricator.services.mozilla.com/D232934
2025-01-20 08:03:58 +00:00
Masayuki Nakano
771489d350 Bug 1939220 - part 1: Split WSRunObject files for WSRunScanner and WhiteSpaceVisibilityKeeper r=m_kato
Differential Revision: https://phabricator.services.mozilla.com/D232932
2025-01-20 08:03:57 +00:00
Sandor Molnar
11ae540bbc Backed out 6 changesets (bug 1939220) for causing build bustages CLOSED TREE
Backed out changeset b15602e6fbf5 (bug 1939220)
Backed out changeset 129d2cd2e11e (bug 1939220)
Backed out changeset b663c3b349f0 (bug 1939220)
Backed out changeset cbd9e4f12bd2 (bug 1939220)
Backed out changeset 81260f9e6677 (bug 1939220)
Backed out changeset f33e7201796d (bug 1939220)
2025-01-20 05:02:53 +02:00
Masayuki Nakano
5a37bc8a95 Bug 1939220 - part 3: Make TextFragmentData::BoundaryData not depend on the editing host r=m_kato
Its role is scanning the DOM.  Therefore, it can know which node is an editing
host during a scan.  Therefore, it does not require the editing host parameter.
To fix that, some utility methods of `HTMLEditUtils` needs to work with
non-editable nodes.  Therefore, this patch also updates `HTMLEditUtils`.

Finally, this gets rid of the `NS_ASSERTION`s in the constructor of
`TextFragmentData` because it'll be available with non-editable nodes too.
Although current all callers assume that it works as in an editing host.

Differential Revision: https://phabricator.services.mozilla.com/D232934
2025-01-19 23:35:35 +00:00
Masayuki Nakano
0537c53049 Bug 1939220 - part 1: Split WSRunObject files for WSRunScanner and WhiteSpaceVisibilityKeeper r=m_kato
Differential Revision: https://phabricator.services.mozilla.com/D232932
2025-01-19 23:35:34 +00:00
Masayuki Nakano
6719c8c037 Bug 1941827 - Make DocumentModifiedEvent and HTMLEditor::OnModifyDocument assume there is no editing host r=m_kato
The logic before getting editing host in them are correct, but both
`nsIContent::GetEditingHost()` and `HTMLEditor::ComputeEditingHostInternal()`
return `Document::GetBody()` result if it's in the design mode.

For now, we should just add nullptr checks into the methods since they are
required only for some specific web apps.

Differential Revision: https://phabricator.services.mozilla.com/D234442
2025-01-16 06:33:26 +00:00
Masayuki Nakano
b3e620e413 Bug 1939065 - Optimize HTMLEditor::DoSplitNode and HTMLEditor::DoJoinNodes for IMEContentObserver r=m_kato
`HTMLEditor::DoSplitNode` does:
1. Insert a new right node
2. Move content in left node into the right node

`HTMLEditor::DoJoinNodes` does:
1. Move content of the right node to the left node
2. Delete the left node

So, all things are done when connected. Therefore `IMEContentObserver` uses its
cache and it's harder to debug. Additionally, temporarily the touching range
becomes wider then the result at joining nodes. That could cause IME gets
received longer text change range. Therefore, they should do:

`HTMLEditor::DoSplitNode`:
1. Move content in left node to the orphan new right node (then, only removing
content is handled by `IMEContentObserver`)
2. Insert the right node (then, `IMEContentObserver` can compute the offset and
length only once)

`HTMLEditor::DoJoinNodes`:
1. Delete the right node (then, all moving content is treated as removed by
`IMEContentObserver`, i.e., it needs to compute offset/length once)
2. Move the non-connected right node children into the left node (then,
`IMEContentObserver` can cache all moving nodes and compute offset/length once)

Differential Revision: https://phabricator.services.mozilla.com/D232882
2025-01-16 02:13:32 +00:00
Emilio Cobos Álvarez
3c1b64acfe Bug 1940412 - Add batch removal information to nsIMutationObserver::ContentWillBeRemoved, and use it in some trivial-ish places. r=dom-core,credential-management-reviewers,sefeng
The idea is to use it on the style (via PresShell->RestyleManager) to do
invalidation faster in cases like bug 1940405.

Differential Revision: https://phabricator.services.mozilla.com/D233547
2025-01-15 20:39:40 +00:00
Masayuki Nakano
6f4cdf57e0 Bug 1941520 - Make HTMLEditor::OnModifyDocument set top level edit sub-action before maintaining the white-space visibility r=m_kato
When pasting text, a `paste` event is fired before a `beforeinput` event.
Therefore, the editor still does not have top level edit sub-action.  Therefore,
the DOM mutation caused by the web app will be handled by
`HTMLEditor::OnModifyDocument` immediately after removing the script blocker.
At this time, we may do:
* insert a padding `<br>` if something immediately after last input is removed
* replace a collapsible white-space if padding `<br>` is removed

Then, each handler sets the top level edit sub-action and the post-processor
will run immediately.  Then, especially in the latter case,
`WhiteSpaceVisibilityKeeper::NormalizeVisibleWhiteSpacesAt` will insert a
padding `<br>` again and restores the replaced NBSP to a collapsible
white-space unexpectedly.

Therefore, if web apps trying to normalize the pasted content with removing
the pasted nodes temporarily, it may cause entering an infinite loop.

This patch makes `HTMLEditor::OnModifyDocument` set edit sub-action for the
hacks to avoid running the post-processor.

Additionally, this touches `EditorBase::DoTransactionInternal` to avoid the
assertion failure of the new test.  The assertion failure indicates a logical
bug of our basic strategy.  However, we should not touch the big design change
for now.  (Anyway, the hack should be removed as soon as possible.)

Differential Revision: https://phabricator.services.mozilla.com/D234278
2025-01-15 08:24:34 +00:00
Masayuki Nakano
12b6be8aa3 Bug 1938862 - Create EditorBase::InsertBRElement r=m_kato
Differential Revision: https://phabricator.services.mozilla.com/D232891
2025-01-14 08:03:51 +00:00
Masayuki Nakano
148cf5936e Bug 1940278 - Make HTMLEditor replace collapsible ASCII white-space with an NBSP if it's visible by a following <br> but it's removed r=m_kato
This is a hack until bug 503838 is fixed.

The other browsers puts an NBSP for the last ASCII white-space immediately
before a block boundary to make it visible.  However, we currently need to
keep using an ASCII white-space as-is with putting a padding `<br>` element.

However, web apps may delete the `<br>` for some reasons without maintaining
the preceding collapsible white-space visibility since it's not required in
the other browsers.

Therefore, this patch replaces the white-spaces only when we meet such
situation.  Of course, this breaks the undo stack, but touching the DOM anyway
causes breaking the undo stack.  Thus, we can trust the web app as that it
manages their on undo stack.

Differential Revision: https://phabricator.services.mozilla.com/D233472
2025-01-09 06:48:27 +00:00
Stanca Serban
7f9c520449 Backed out changeset ef3aed257e91 (bug 1939065) for causing mochitests failures in test_composition_text_querycontent.xhtml. CLOSED TREE 2025-01-09 04:21:29 +02:00