Closed Bug 1658702 Opened 4 years ago Closed 4 years ago

[Input Events] Set "affected" ranges to the result of `getTargetRanges()` at dispatching `beforeinput` event

Categories

(Core :: DOM: Events, defect, P2)

defect

Tracking

()

RESOLVED FIXED
83 Branch
Tracking Status
firefox83 --- fixed

People

(Reporter: masayuki, Assigned: masayuki)

References

Details

(Keywords: dev-doc-complete)

Attachments

(22 files)

(deleted), text/x-phabricator-request
Details
(deleted), text/x-phabricator-request
Details
(deleted), text/x-phabricator-request
Details
(deleted), text/x-phabricator-request
Details
(deleted), text/x-phabricator-request
Details
(deleted), text/x-phabricator-request
Details
(deleted), text/x-phabricator-request
Details
(deleted), text/x-phabricator-request
Details
(deleted), text/x-phabricator-request
Details
(deleted), text/x-phabricator-request
Details
(deleted), text/x-phabricator-request
Details
(deleted), text/x-phabricator-request
Details
(deleted), text/x-phabricator-request
Details
(deleted), text/x-phabricator-request
Details
(deleted), text/x-phabricator-request
Details
(deleted), text/x-phabricator-request
Details
(deleted), text/x-phabricator-request
Details
(deleted), text/x-phabricator-request
Details
(deleted), text/x-phabricator-request
Details
(deleted), text/x-phabricator-request
Details
(deleted), text/x-phabricator-request
Details
(deleted), text/x-phabricator-request
Details

InputEvent.getTargetRanges() is an important feature of beforeinput event because without this API, web apps cannot know where will be deleted or replaced if they won't cancel the beforeinput event. Currently, we just set selection ranges, but when deleting content, we need to set actual ranges which will be deleted.

I think that we can land the patches separately because the API has not been shipped in any channels and multiple landings make regression window smaller.

Keywords: leave-open

In strictly speaking, we should use same computed target ranges for any edit
actions which causes removing non-collapsed selection. However, for now,
this patch makes only DeleteSelectionAsAction() because it's not so important
differences for shipping beforeinput in Nightly channel.

This patch implements computation of target ranges for this part:
https://searchfox.org/mozilla-central/rev/73a14f1b367948faa571ed2fe5d7eb29460787c1/editor/libeditor/HTMLEditSubActionHandler.cpp#3099-3141

This patch adds some utility methods for computing the ranges. Currently,
it's not yet standardized, but the other browser engines look for leaf content
of another block when blocks are joined (or a block is deleted like this case).
Therefore, we follow the behavior basically, but different from the other
browsers, we should include invisible white-spaces into the range when they
are included. That avoids the invisible white-spaces become visible when
web apps do something instead of us. Note that utility methods have the code,
but this patch does not use it because in this case, we just delete a empty
block ancestor, not join it with previous/next block.

Depends on D88376

This change is corresponding to the part:
https://searchfox.org/mozilla-central/rev/73a14f1b367948faa571ed2fe5d7eb29460787c1/editor/libeditor/HTMLEditSubActionHandler.cpp#3143-3155

When caret is not adjacent the deleting character in bidi text, we may do
nothing except putting caret to the character. So, ComputeRangesToDelete()
shouldn't update the caret position since the caret position will be check
by its Run() later if beforeinput event is not canceled. For avoiding
the code duplication, this patch reimplements
EditorBase::SetCaretBidiLevelForDeletion() as a stack only class and
split the check and updating part from correcting the data.

Note that by the default pref, the new tests failed since it won't be
canceled, and the method still don't compute for deleting a character.

Depends on D88377

This patch adding computation code corresponding to:
https://searchfox.org/mozilla-central/rev/27932d4e6ebd2f4b8519865dad864c72176e4e3b/editor/libeditor/HTMLEditSubActionHandler.cpp#3157-3185

For beforeinput event listeners, AutoSetTemporaryAncestorLimiter is not
enough since when beforeinput event listeners modifies Selection, the
ancestor limit is not set when it has a job. Perhaps, we should make editor
stop using focus/blur event listener and makes nsFocusManager notifies
editor of them synchronously before dispatching the events. But it's not
scope of this bug at least.

Depends on D88378

Pushed by masayuki@d-toybox.com: https://hg.mozilla.org/integration/autoland/rev/c1fa84508a52 part 1: Create a path to compute target ranges of deleting edit actions for `beforeinput` events on `HTMLEditor` r=m_kato
Pushed by masayuki@d-toybox.com: https://hg.mozilla.org/integration/autoland/rev/bacd9a2d26c1 part 2: Make `AutoDeleteRangesHandler::ComputeRangesToDelete()` handle the case deleting empty ancestor(s) r=m_kato
Created web-platform-tests PR https://github.com/web-platform-tests/wpt/pull/25288 for changes under testing/web-platform/tests
Upstream PR merged by moz-wptsync-bot
Flags: needinfo?(masayuki)
Pushed by masayuki@d-toybox.com: https://hg.mozilla.org/integration/autoland/rev/0626d2f60030 part 2: Make `AutoDeleteRangesHandler::ComputeRangesToDelete()` handle the case deleting empty ancestor(s) r=m_kato
Pushed by masayuki@d-toybox.com: https://hg.mozilla.org/integration/autoland/rev/1a0b21debe92 part 3: Make `AutoDeleteRangesHandler::ComputeRangesToDelete()` quit without modifying the ranges when it shouldn't delete adjacent character(s) in bidi text r=m_kato
Created web-platform-tests PR https://github.com/web-platform-tests/wpt/pull/25312 for changes under testing/web-platform/tests
Pushed by masayuki@d-toybox.com: https://hg.mozilla.org/integration/autoland/rev/9714d40b233b part 4: Make `AutoDeleteRangesHandler::ComputeRangesToDelete()` extend collapsed ranges for deleting adjacent character or word or the line r=m_kato

This patch corresponds to the following part:

Let's return a range selecting the deleting atomic content (i.e., between
EditorDOMPoint(&content) and EditorDOMPoint::After(content)).

For doing it, we need to shrink the computed range after
AutoRangeArray::ExtendAnchorFocusRangeFor() because layout code puts
range boundaries to start or end of text node in this case.

Then, surprisingly, our deletion code have not used
HandleDeleteCollapsedSelectionAtAtomicContent() in most cases because
AutoRangeArray::ExtendAnchorFocusRangeFor() makes the collapsed range
to non-collapsed. For making the deletion faster and simpler, this patch
shrinks the result of AutoRangeArray::ExtendAnchorFocusRangeFor() if
it has only one range and selects only one atomic content node.

Depends on D88941

Upstream PR merged by moz-wptsync-bot
Pushed by masayuki@d-toybox.com: https://hg.mozilla.org/integration/autoland/rev/404d5145be65 part 5: Add preparation part for deleting collapsed range to `AutoDeleteRangesHandler::ComputeRangesToDelete()` r=m_kato https://hg.mozilla.org/integration/autoland/rev/68b37c99e390 part 6: Make `AutoDeleteRangesHandler::ComputeRangesToDelete()` skip the case deleting an invisible `<br>` element for now r=m_kato

This patch corresponds to:

In WSRunObject.cpp, joining 2 blocks code is split to 3 methods, they are
for:

  1. left block element is an ancestor of right block element
  2. right block element is an ancestor of left block element
  3. left block element and right block element are siblings

The reason why they are split to is, they need to move descendants of child
block element or right block element with different logic. However, this
difference is not a big problem when we compute target ranges because only
the difference is where we need to check whether there are invisible white-
spaces. Therefore, this patch creates only a utility method in WSRunScanner
and makes AutoInclusiveAncestorBlockElementsJoiner::ComputeRangesToDelete()
much simpler than AutoInclusiveAncestorBlockElementsJoiner::Run().

And also this patch fixes a long standing bug that is HTMLEditor tries to
join <body> element and <head> element when you type Backspace at
beginning of the <body> element when <html> element has contenteditable.
Without this fix, the getTargetRange result becomes buggy in this case.

Depends on D88969

Pushed by masayuki@d-toybox.com: https://hg.mozilla.org/integration/autoland/rev/a8bd1c21c95c part 7: Make `AutoDeleteRangesHandler::ComputeRangesToDelete()` compute text deletion range from a collapsed range r=m_kato
Pushed by masayuki@d-toybox.com: https://hg.mozilla.org/integration/autoland/rev/ad9e11f73c27 part 8: Add `AutoDeleteRangesHandler::ComputeRangesToDeleteAtomicContent()` to compute atomic content deleting target range r=m_kato
Created web-platform-tests PR https://github.com/web-platform-tests/wpt/pull/25419 for changes under testing/web-platform/tests
Upstream PR merged by moz-wptsync-bot
Pushed by masayuki@d-toybox.com: https://hg.mozilla.org/integration/autoland/rev/409bdd70e2f2 part 9: Add `AutoDeleteRangesHandler::ComputeRangesToDeleteHRElement()` to compute the target range for deleting `<hr>` element r=m_kato
Regressions: 1663460
Regressions: 1663725
Attachment #9173924 - Attachment description: Bug 1658702 - part 10: Implement a path to compute joining 2 blocks from current block boundary r=m_kato! → Bug 1658702 - part 10: Implement a path to compute target ranges when joining 2 blocks from current block boundary r=m_kato!

This patch corresponds to:

HandleDeleteCollapsedSelectionAtCurrentBlockBoundary() delete leaf content
of the child block when the block is not joined with current block. For
doing it, it creates another AutoDeleteRangesHandler with collapsing selection
in the child block. Then, it may refer selection for handling bidi text.
Therefore, the computation code which is added by this patch may modify
selection temporarily for the child AutoDeleteRangeHandler. However, the
selection change shouldn't cause running any scrip (even if chrome script)
because it's required only for this hack. Therefore, this patch blocks all
notifications and selection change events with AutoHideSelectionChanges.
Therefore, this patch marks
AutoBlockElementsJoiner::ComputeRangesToDeleteAtOtherBlockBoundary() as
MOZ_CAN_RUN_SCRIPT_BOUNDARY for using HTMLEditor::CollapseSelectionTo().

Depends on D89278

This patch corresponds to:

Note that the new failure of input-events-get-target-ranges-forwarddelete.html
is mismatch between target range (including the trailing white-space) and
actually deleted range (not including the trailing white-space). Let's
accept this new failure for now since not so important problem and same test
with backspace has same bug.

Depends on D89869

Pushed by masayuki@d-toybox.com: https://hg.mozilla.org/integration/autoland/rev/a75148ad144d part 10: Implement a path to compute target ranges when joining 2 blocks from current block boundary r=m_kato
Created web-platform-tests PR https://github.com/web-platform-tests/wpt/pull/25533 for changes under testing/web-platform/tests

HTMLEditor falls back to EditorBase::DeleteRangesWithTransaction() in
some cases, especially when handling non-collapsed ranges. Therefore, we
need to implement it for the following patches.

The code corresponds to:

Basically, we don't need to touch the ranges, but if aDirectionAndAmount is
nsIEditor::eNext or nsIEditor::ePrevious, each collapsed range is extened
for:

  • previous character (treating only surrogate pair)
  • next character (treating only surrogate pair)
  • selecting another content node

This logic is much rougher than what AutoDeleteRangesHandler and its nested
classes do. So, HTMLEditor should stop using it in the future, but we need
to keep using it for now.

Depends on D90210

Upstream PR merged by moz-wptsync-bot
Pushed by masayuki@d-toybox.com: https://hg.mozilla.org/integration/autoland/rev/9befc4883a41 part 11: Implement a path to compute target ranges when joining 2 blocks from outer block boundary r=m_kato
Pushed by masayuki@d-toybox.com: https://hg.mozilla.org/integration/autoland/rev/101769e6e04b part 12: Implement paths to compute ranges to delete non-collapsed ranges r=m_kato
Pushed by masayuki@d-toybox.com: https://hg.mozilla.org/integration/autoland/rev/059d4faee987 part 13: Add WPT for `getTargetRanges()` for non-collapsed selection r=m_kato https://hg.mozilla.org/integration/autoland/rev/345abec5b219 part 14: Implement a path to compute target ranges of `EditorBase::DeleteRangesWithTransaction()` r=m_kato
Created web-platform-tests PR https://github.com/web-platform-tests/wpt/pull/25591 for changes under testing/web-platform/tests

This patch corresponds to:

However, it seems that this is a dead path in most cases because most tests
added by this patch are handled as non-collapsed range deletion. The
collapsed range is extended by AutoRangeArray::ExtendAnchorFocusRangeFor().

Depends on D90214

When joining 2 block elements, the left block element may ends with invisible
<br> element or the right block element may follows an invisible <br>
element if it's a descendant of the left block element. In those cases, the
invisible <br> element must be start of the target range of the joining
block elements since it'll be deleted.

Depends on D90540

Currently, target ranges do not extend the ranges even when deleting empty
parent elements of the range. Therefore, the frag indicating whether empty
parents removed or not is not necessary for the methods.

Depends on D90541

Pushed by masayuki@d-toybox.com: https://hg.mozilla.org/integration/autoland/rev/5581f76448f6 part 15: Implement shortcut case of `AutoDeleteRangesHandler::HandleDeleteNonCollapsedRanges()` r=m_kato
Pushed by masayuki@d-toybox.com: https://hg.mozilla.org/integration/autoland/rev/29aa922055a1 part 16: Implement `AutoBlockElementsJoiner::ComputeRangesToDeleteContentInRanges()` and `AutoBlockElementsJoiner::ComputeRangesToJoinBlockElementsInSameParent()` r=m_kato

A lot of edit actions calls DeleteSelectionAsSubAction() if selection is
not collapsed. In such case, getTargetRanges() should return same result
as when the selection range is simply deleted.

This patch creates 2 methods to consider whether EditAction causes
running DeleteSelectionAsSubAction() with collapsed selection or
non-collapsed selection.

And makes DeleteSelectionAsAction() stop initializing the target ranges
itself. Instead, makes AutoEditActionDataSetter do it immediately before
dispatching beforeinput event unless it's been already initialized manually.

The correctness of the new utility methods are tested with new MOZ_ASSERT
in DeleteSelectionAsSubAction().

Additionally, this reorganizes input-events-get-target-ranges-*.html.

  • Moving common code into input-events-get-target-ranges.js
  • Moving non-collapsed selection cases into input-events-get-target-ranges-non-collapsed-selection.html
  • Adding "typing a" case into the new test for testing this patch's behavior

Depends on D90542

If deleting/replacing range selects a text node, it may shrink the range
to start and end of the text node. So, the result may not be wider than
the original range.

This behavior is compatible with Blink.

Depends on D90639

Upstream PR merged by moz-wptsync-bot
Pushed by masayuki@d-toybox.com: https://hg.mozilla.org/integration/autoland/rev/47cdef9c2e5c part 17: Implement the last path to handle non-collapsed ranges deletion r=m_kato
Pushed by masayuki@d-toybox.com: https://hg.mozilla.org/integration/autoland/rev/787fd92f95f6 part 18: Implement the path to compute target ranges when deleting around an invisible `<br>` element r=m_kato
Created web-platform-tests PR https://github.com/web-platform-tests/wpt/pull/25781 for changes under testing/web-platform/tests
Pushed by masayuki@d-toybox.com: https://hg.mozilla.org/integration/autoland/rev/d786eaafa4d1 part 19: Make `WSRunScanner::GetRangeForDeletingBlockElementBoundaries()` contain preceding invisible `<br>` element at start of joining blocks range r=m_kato https://hg.mozilla.org/integration/autoland/rev/a7161d6d6941 part 20: Get rid of all `nsIEditor::EStripWrappers` argument from all methods computing target ranges r=m_kato
Upstream PR merged by moz-wptsync-bot
Pushed by masayuki@d-toybox.com: https://hg.mozilla.org/integration/autoland/rev/77da8a3e42c0 part 21 Initialize target ranges for all edit actions which runs `DeleteSelectionAsSubAction()` r=m_kato https://hg.mozilla.org/integration/autoland/rev/384654269ee3 part 22: Get rid of wrong `MOZ_ASSERT`s in `WSRunScanner::GetRangeExtendToContainInvisibleWhiteSpacesAtRangeBoundaries()` r=m_kato
Created web-platform-tests PR https://github.com/web-platform-tests/wpt/pull/25809 for changes under testing/web-platform/tests
Status: ASSIGNED → RESOLVED
Closed: 4 years ago
Resolution: --- → FIXED
Target Milestone: --- → 83 Branch
Upstream PR merged by moz-wptsync-bot

These changes have been documented; see https://github.com/mdn/sprints/issues/3799#issuecomment-717309934 for the full details.

Let us know if you need anything else. Thanks!

You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: