The root cause of this bug is, we tried to compute new offset with offset at
the new node. However, as explained in the inline comments, it should compute
the offset with the right node offset in the new mode. Therefore, it needs
to handle it by itself instead of just calling `SelAdjInsertNode`.
Differential Revision: https://phabricator.services.mozilla.com/D171965
As of the prior patch, these are no longer needed. I removed
these with a script, then ran clang-format on the files, then
manually reverted a few unrelated changed from the formatter.
Differential Revision: https://phabricator.services.mozilla.com/D164829
Between splitting a node and undoing it, web apps can move split nodes anywhere.
Therefore, it shouldn't assume they are always in same parent node, and
`RangeUpdater::SelAdjJoinNodes` needs to handle it correctly.
Unfortunately, `RangeUpdater::SelAdjJoinNodes` cannot handle nested cases
correctly, e.g., right node was in `aRemovedContent` or right node was in
the container of `aStartOfRightContent.GetContainer()`. However, it's not
a new regression, and such complicated situation breaks undoing anyway.
Therefore, I think that we don't need to care about it for now.
Differential Revision: https://phabricator.services.mozilla.com/D159230
They are used in public inline methods of `HTMLEditor`. Therefore, they should
be defined in an exposed header file without other internal use things for the
editor module. Then, we can stop exposing `HTMLEditHelpers.h`.
Depends on D158632
Differential Revision: https://phabricator.services.mozilla.com/D158633
This patch adds new path to adjust selection for the new split node direction.
So this does not change any behavior of the existing path.
Differential Revision: https://phabricator.services.mozilla.com/D158100
This changes the existing path's behavior a bit. However, it should not affect
to web apps in the wild because it must be really rare case that web apps
inserting new nodes into the removing node while moving its children.
Differential Revision: https://phabricator.services.mozilla.com/D158099
When selection is `abc<b>[def</b>]ghi`, `insertParagraph` command will delete
the `<b>` element first, then, `Selection` becomes `abc{}ghi`. Then,
`HTMLEditor::InsertParagraphSeparatorAsSubAction` wraps all of the line in
the default paragraph, `<div>`, with
`HTMLEditor::FormatBlockContainerWithTransaction` (although this is incompatible
behavior with the other browsers). At this time, new `<div>` is inserted before
the first text node and then, move the text nodes into the new `<div>`.
However, `RangeUpdater::DidMoveNode` just slides the offsets if containers of
registered DOM points are the ex-parent of the moving nodes. Therefore, the
tracked selection range in `HTMLEditor::FormatBlockContainerWithTransaction`
become `<div></div>abc{}def`, then, `<div>abcdef</div>{}`, but the expected
behavior is of course, `<div>abc{}def</div>`, then, split the new `<div>`.
So the problem is, `DidMoveNode` assumes that DOM points won't point the moving
content node. If the node is pointed, it should keep pointing in the new
parent.
Note that the expectations of new tests are based on Chrome, therefore, the
new known failures are incompatible with Chrome.
Differential Revision: https://phabricator.services.mozilla.com/D156798
In bug 1739524, I misunderstood the meaning of `aOffset` of `SelAdjJoinNodes`.
After joining 2 nodes, and a point points right node which will have ex-left
node content, the point needs to point ex-start of the right node to keep
next insertion point as-is. Therefore, it's not useful with new join nodes
direction, it needs to know the ex-offset of the right node.
Differential Revision: https://phabricator.services.mozilla.com/D155438
This patch makes it take `AutoRangeArray` and it can save a snapshot of the
ranges and restore it like `AutoSelectionRestorer`.
For accessing `HTMLEditor::RangeUpdaterRef` for clearing the saved ranges,
`AutoRangeArray` needs to store `HTMLEditor`. Therefore, its constructors
and the destructor cannot be inlined in the header due to the include-hell.
Differential Revision: https://phabricator.services.mozilla.com/D149089
Creating both `DeleteNodeTransaction` and `InsertNodeTransaction` wastes
memory. They should be done in an instance instead.
Fortunately, no edit action listener checks whether the deleted node is still
in the composed document or not, etc. Therefore, we can simply notify them of
both deletion and insertion which were done in
`EditorBase::InsertNodeWithTransaction` and
`EditorBase::DeleteNodeWithTransaction`. Note that previously, the range
updater needs to ignore the notifications from them while the node is being
moved. However, it does not require anymore. Therefore, this patch makes it
stop locking, and that would fix minor problem in the case of legacy mutation
event listeners run another edit action.
On the other hand, this changes some edge cases handling of
`MoveNodeWithTransaction` which are detected by the WPT. According to the
previous result of applying this patch, `nsINode::InsertBefore` fails and that
leads some errors at updating the changed range. I guess that the cause is
that there is some bugs at updating insertion point after deleting the node from
the DOM tree around here:
https://searchfox.org/mozilla-central/rev/0ffae75b690219858e5a45a39f8759a8aee7b9a2/editor/libeditor/HTMLEditor.cpp#5058-5071
However, it's safely fixed by the new code which does not remove the node from
the DOM tree explicitly. So, I think that it's safe to accept this behavior
change for web apps in the wild.
Differential Revision: https://phabricator.services.mozilla.com/D146397
The creation and initialization cost of `nsRange` is expensive. And just
comparing DOM points does not require the checks of ancestors which are
required by `nsRange` to observe DOM mutations. Therefore, although the
logic is not exactly same, we can skip the additional unnecessary cost.
Note that the Editor module checks without `nsRange`'s strict initialization
in most places so that it must not be required to do the strict check only in
`SelectionState`.
Additionally, this moves some definitions of `SelectionState` methods to
its header for making them inlined since the dependency is now reduced.
Finally, some methods are renamed to align to `Selection` API.
Depends on D145226
Differential Revision: https://phabricator.services.mozilla.com/D145227
This is the most cases of the warnings. If previous transactions occurred in
now disconnected subtree, e.g., they are replaced by setting `innerHTML` to
check different scenarios, `nsRange::CompareBoundaryPoints` return error.
Therefore, this case should be handled before comparing the range boundaries
and logged for making easier to debug.
Depends on D145225
Differential Revision: https://phabricator.services.mozilla.com/D145226
The warnings are caused by comparing a range with non-positioned range, or
comparing non-positioned ranges. And `SelectionState::IsCollapsed()` may
return `true` when it has and only has a non-positioned range.
Therefore, this patch adds new method which checks whether the selection cache
points a caret position or not instead of the "collapsed" state, and make
`PlaceholderTransaction::StartSelectionEquals` check is result before calling
`SelectionState::Equals`.
Differential Revision: https://phabricator.services.mozilla.com/D145225
It's an internal API corresponding to `Selection.getRangeAt` DOM API.
I think that it should use `uint32_t` rather than `size_t` because of the
consistency with the DOM API and `Selection::RangeCount()`.
This patch fixes all callers of `GetRangeAt()`, and rewrites it with ranged-
loops unless original ones do not refer `RangeCount()` every time and may run
script in the loop.
Differential Revision: https://phabricator.services.mozilla.com/D128848
Currently, it assumes that `aLeftNode` is new node and the other is the original
one. However, we need the opposite case when we fix bug 1735608.
Unfortunately, we cannot test the new path until we fix bug 1735608. Therefore,
the new path may contain some bugs.
Differential Revision: https://phabricator.services.mozilla.com/D130427
Currently, it assumes that all children or text data of `aRightContent` is
moved into `aLeftContent`. However, we need the opposite case when we fix
bug 1735608.
Unfortunately, we cannot test the new path until we fix bug 1735608. Therefore,
the new path may contain some bugs.
Differential Revision: https://phabricator.services.mozilla.com/D130426
The crash is caused by the infinite loop to delete unnecessary ranges.
The `i` is always equals or larger than `0` due to unsigned. So, if
`Selection::RangeCount()` is `0`, `i` can be `UINT32_MAX`.
Instead, we can use `nsTArray<RefPtr<RangeItem>>::TruncateLength()`.
Differential Revision: https://phabricator.services.mozilla.com/D119564
It should be treated as `uint32_t` since DOM API does so. However, there are
some exceptions:
* Result of `nsINode::ComputeIndexOf()`
* Result of `nsAString` methods
They return `-1` as not found, and anyway, they cannot treat large integer
than `INT32_MAX`. Therefore, this patch does not touch around them.
Differential Revision: https://phabricator.services.mozilla.com/D118933
Currently, when `HTMLEditor` replaces text in a text node, `HTMLEditor`
creates a set of `DeleteTextTransaction` and `InsertTextTransaction`.
However, this has bad impact for footprint and causes the callers messy.
This patch creates `ReplaceTextTransaction` instead and
`HTMLEditor::ReplaceTextWithTransaction()` as its wrapper. Unfortunately,
this becomes not calling `nsIEditActionListener::DidDeleteText()`, however,
this is not used by mozilla-central, comm-central nor BlueGriffon. IIRC,
it was not removed for some legacy addons of Thunderbird. Therefore, it
must be okay to remove it.
Differential Revision: https://phabricator.services.mozilla.com/D76078
`nsRange` instances are allocated a lot in the heap especially by editor and
spellchecker. The allocation cost is too bad for benchmarks. Therefore,
we should reuse released instances as far as possible. For managing it in
static factory methods of `nsRange`, we need to hide `nsRange` constructor.
Differential Revision: https://phabricator.services.mozilla.com/D61237
SelectionState doesn't save and restore current selection's direction. So the
direction of selection is always default after undoing.
So we should restore direction of selection.
Differential Revision: https://phabricator.services.mozilla.com/D2259
To reduce QI, I would like to replace nsIDOMNode with nsINode. And some
parameters in *DataTransder.cpp's methods is unused (it uses as nullptr),
so we should remove these parameters.
Also nsIDOMNodeList is unused now, so we should remove this including.
MozReview-Commit-ID: 1QTIkxDazjJ
A lot of methods take |const EditorRawDOMPoint&| as their argument. However,
some of them are called with EditorDOMPoint::AsRaw(). This is not good for
performance because:
1. Needs to create temporary instance of EditorRawDOMPoint.
2. EditorRawDOMPoint::AsRaw() may be used by simple mistake.
3. Such methods may call EditorRawDOMPoint::Offset(), however, it's not copied
to the original EditorDOMPoint instance. So, callers may need to compute
offset again.
So, such methods should be changed to template methods if they are not virtual
method and AsRaw() should be gotten rid of for prevent it looking not expensive.
MozReview-Commit-ID: DAqqW4a2EMS
This crashtest case hits assertion in SelAdjInsertNode due to invalid offset
point. So we check whether this is valid.
Also, SelAdjCreateNode and SelAdjInsertNode should use EditorRawDOMPoint to avoid offset calculation and check valid offset.
MozReview-Commit-ID: A1kaKEzc36e
EditorDOMPointBase::Container() may return nullptr. So, it should be renamed
to GetContainer().
Then, the method name becomes longer and a lot of callers access the result
directly. So, there should be following methods to make the callers shorter:
- GetContainerAsContent() to return the container as nsIContent*.
- GetContainerAsElement() to return the container as dom::Element*.
- GetContainerAsText() to return the container as dom::Text.
- GetContainerAsDOMNode() to return the container as nsIDOMNode*.
- CanContainerHaveChildren() to check if the container can have child nodes.
- IsInDataNode() to check if the point is in a data node including text node.
- IsInTextNode() to check if the point is in a text node.
- IsContainerHTMLElement() to check if the container is specific HTML element.
- IsContainerAnyOfHTMLElements() to check if the container is one of the
specified HTML elements.
MozReview-Commit-ID: LkN2WBbCPj0
EditorBase::CreateTxnForSplitNode() and EditorBase::SplitNode() takes a set of
container and offset in it for specifying a point to split.
Instead, they should take EditorRawDOMPoint for specifying start of right node.
MozReview-Commit-ID: 5VwS8oudzIT
EditorUtils::IsDescendantOf() current takes a pointer to offset or a pointer to
child content if the caller needs to know the child of the most ancestor node.
However, some callers should get a child as EditorDOMPoint or EditorRawDOMPoint.
Then, they can be used for some editor methods which need to take child node
for performance optimization.
This patch makes EditorUtils::IsDescendantOf() as only two overloads. One takes
pointer to EditorRawDOMPoint as optional out argument. The other takes pointer
to EditorDOMPoint as an out param.
Additionally, this creates new constructor of AutoTrackDOMPoint for making it
can treat EditorDOMPoint directly.
MozReview-Commit-ID: IsAGTUvKI19