From f3f0db7fdaa3b4026001df3a71d94123c84b1283 Mon Sep 17 00:00:00 2001 From: Di Zhang Date: Thu, 23 Jan 2025 16:11:22 -0800 Subject: [PATCH 1/4] Change Selection to be associated with a composed live range --- index.html | 125 +++++++++++++++++++++++++++-------------------------- 1 file changed, 64 insertions(+), 61 deletions(-) diff --git a/index.html b/index.html index 474aca3..093fb25 100644 --- a/index.html +++ b/index.html @@ -112,7 +112,8 @@

[=editing hosts=] in the document.

- Each selection can be associated with a single range. + Each selection can be associated with a single + composed live range range. When there is no range associated with the selection, the selection is empty. The selection must be initially empty. @@ -127,6 +128,20 @@

dev do not. We follow Gecko/WebKit, because it lessens the chance of getRangeAt(0) throwing.

+

To reset the range of [=this=], given the + boundary point start and boundary point + end, run these steps: +

+
    +
  1. Let newCachedRange be a new {{Range}} object.
  2. +
  3. [=Range/Set the start=] of newCachedRange to start. +
  4. +
  5. [=Range/Set the end=] of newCachedRange to end.
  6. +
  7. Let newRange be a new composed live range + whose [=Range/start=] is start, [=Range/end=] is end + and cached live range is newCachedRange.
  8. +
  9. Set [=this=]'s range to be newRange.
  10. +

Once a selection is associated with a given range, it must continue to be associated with that same range until this @@ -167,13 +182,14 @@

selection must be preserved.

- Each selections also have an anchor and a + Each selection also has an anchor and a focus. If the selection's range is null, its anchor and focus are both null. If the selection's range is not null and its direction is forwards, - its anchor is the range's [=range/start=], and its - focus is the [=range/end=]. Otherwise, its focus is the - [=range/start=] and its anchor is the [=range/end=]. + its anchor is the range's cached live range's + [=range/start=], and its focus is the [=range/end=]. Otherwise, + its focus is the [=range/start=] and its anchor is the + [=range/end=].

anchor and focus of selection need not to be in @@ -320,7 +336,7 @@

index is not 0, or if [=this=] is empty or either focus or anchor is not in the [=document tree=]. Otherwise, it must return a reference to (not a - copy of) [=this=]'s range. + copy of) [=this=]'s range's cached live range.

Thus subsequent calls of this method returns the same range @@ -345,8 +361,8 @@

  • If rangeCount is not 0, abort these steps.
  • -
  • Set [=this=]'s range to range by a strong reference - (not by making a copy). +
  • Set [=this=]'s range's cached live range to range by + a strong reference (not by making a copy).
  • @@ -379,8 +395,8 @@

    The method must make [=this=] empty by disassociating its - range if [=this=]'s range is range. - Otherwise, it must throw a {{NotFoundError}}. + range if [=this=]'s range's cached live range is + range. Otherwise, it must throw a {{NotFoundError}}.

    @@ -476,13 +492,8 @@

    [=shadow-including inclusive ancestor=] of node, abort these steps. -
  • Otherwise, let newRange be a new range. -
  • -
  • [=Range/Set the start=] the [=range/start=] and the - [=range/end=] of newRange to (node, - offset). -
  • -
  • Set [=this=]'s range to newRange. +
  • Otherwise, reset the range with (node, + offset) and (node, offset).
  • @@ -500,13 +511,17 @@

    - The method must throw {{InvalidStateError}} exception if the - [=this=] is empty. Otherwise, it must create a new - range, [=Range/set the start=] both its [=range/start=] and - [=range/end=] to the [=range/start=] of [=this=]'s range, - and then set [=this=]'s range to the newly-created - range. + The method must follow these steps:

    +
      +
    1. If [=this=] is empty, throw an {{InvalidStateError}} + exception and abort these steps. +
    2. +
    3. Let bp be the [=Range/start=] of [=this=]'s range. +
    4. +
    5. Reset the range with bp and bp. +
    6. +

    For collapseToStart/End, IE9 mutates the existing range, while Firefox 9.0a2 and Chrome 15 dev replace it with a new one. The spec @@ -518,13 +533,18 @@

    collapseToEnd() method
    -

    - The method must throw {{InvalidStateError}} exception if the - [=this=] is empty. Otherwise, it must create a new - range, [=Range/set the start=] both its [=range/start=] and - [=range/end=] to the [=range/end=] of [=this=]'s range, and - then set [=this=]'s range to the newly-created range. -

    +

    + The method must follow these steps: +

    +
      +
    1. If [=this=] is empty, throw an {{InvalidStateError}} + exception and abort these steps. +
    2. +
    3. Let bp be the [=Range/end=] of [=this=]'s range. +
    4. +
    5. Reset the range with bp and bp. +
    6. +
    extend() method @@ -546,24 +566,18 @@

    newFocus be the boundary point (node, offset). -
  • Let newRange be a new range. -
  • -
  • If node's [=tree/root=] is not the same as the - [=this=]'s range's [=tree/root=], [=Range/set the start=] - newRange's [=range/start=] and [=range/end=] to - newFocus. +
  • If node's [=tree/root=] is not the same as + [=this=]'s range's [=tree/root=], reset the range with + newFocus and newFocus.
  • Otherwise, if oldAnchor is [=boundary point/before=] - or equal to newFocus, [=Range/set the start=] - newRange's [=range/start=] to oldAnchor, then - set its [=range/end=] to newFocus. -
  • -
  • Otherwise, [=Range/set the start=] newRange's - [=range/start=] to newFocus, then set its [=range/end=] - to oldAnchor. + or equal to newFocus, reset the range + with oldAnchor and newFocus.
  • -
  • Set [=this=]'s range to newRange. +
  • Otherwise, reset the range with newFocus + and oldAnchor.
  • +
  • If newFocus is [=boundary point/before=] oldAnchor, set [=this=]'s direction to backwards. Otherwise, set it to forwards. @@ -604,15 +618,10 @@

    focus be the boundary point (focusNode, focusOffset).

  • -
  • Let newRange be a new range. -
  • If anchor is [=boundary point/before=] - focus, [=Range/set the start=] the newRange's - [=range/start=] to anchor and its [=range/end=] to - focus. Otherwise, [=Range/set the start=] them to - focus and anchor respectively. -
  • -
  • Set [=this=]'s range to newRange. + focus, reset the range with anchor and + focus. Otherwise, reset the range with + focus and anchor.
  • If focus is [=boundary point/before=] anchor, set [=this=]'s direction to @@ -634,17 +643,11 @@

  • If node's [=tree/root=] is not the document associated with [=this=], abort these steps.
  • -
  • Let newRange be a new range and - childCount be the number of [=tree/children=] of +
  • Let childCount be the number of [=tree/children=] of node.
  • -
  • Set newRange's [=range/start=] to (node, - 0). -
  • -
  • Set newRange's [=range/end=] to (node, - childCount). -
  • -
  • Set [=this=]'s range to newRange. +
  • Reset the range with (node, 0) + and (node, childCount).
  • Set [=this=]'s direction to forwards.
  • From 23db74f82a4e43d9eb19b66fd854abc7c336d839 Mon Sep 17 00:00:00 2001 From: Di Zhang Date: Wed, 5 Mar 2025 14:44:12 -0800 Subject: [PATCH 2/4] Rename and address review comments --- index.html | 75 ++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 48 insertions(+), 27 deletions(-) diff --git a/index.html b/index.html index 093fb25..aa2f3b7 100644 --- a/index.html +++ b/index.html @@ -113,7 +113,7 @@

    Each selection can be associated with a single - composed live range range. + composed selection range range. When there is no range associated with the selection, the selection is empty. The selection must be initially empty. @@ -128,19 +128,30 @@

    dev do not. We follow Gecko/WebKit, because it lessens the chance of getRangeAt(0) throwing.

    -

    To reset the range of [=this=], given the +

    To set the composed selection range of [=this=], given the boundary point start and boundary point end, run these steps:

      -
    1. Let newCachedRange be a new {{Range}} object.
    2. -
    3. [=Range/Set the start=] of newCachedRange to start. +
    4. Let liveRange be a new {{Range/}} object.
    5. +
    6. [=Range/Set the start=] of liveRange to start.
    7. -
    8. [=Range/Set the end=] of newCachedRange to end.
    9. -
    10. Let newRange be a new composed live range - whose [=Range/start=] is start, [=Range/end=] is end - and cached live range is newCachedRange.
    11. -
    12. Set [=this=]'s range to be newRange.
    13. +
    14. [=Range/Set the end=] of liveRange to end.
    15. +
    16. Let composedRange be a new + composed selection range + whose [=Range/start=] is start, [=Range/end=] is + end and legacy selection range is + liveRange.
    17. +

      + While the above steps might look identical, liveRange and + composedRange could end up in very different states. The + liveRange follows [=Range/set the start=] and + [=Range/set the end=] algorithms, which will collapse in cross-root + cases. On the other hand, composedRange is set directly + without any collapsing logic. +

      +
    18. Set [=this=]'s composed selection range to + composedRange.

    Once a selection is associated with a given range, it @@ -186,7 +197,7 @@

    focus. If the selection's range is null, its anchor and focus are both null. If the selection's range is not null and its direction is forwards, - its anchor is the range's cached live range's + its anchor is the range's legacy selection range's [=range/start=], and its focus is the [=range/end=]. Otherwise, its focus is the [=range/start=] and its anchor is the [=range/end=]. @@ -336,7 +347,7 @@

    index is not 0, or if [=this=] is empty or either focus or anchor is not in the [=document tree=]. Otherwise, it must return a reference to (not a - copy of) [=this=]'s range's cached live range. + copy of) [=this=]'s range's legacy selection range.

    Thus subsequent calls of this method returns the same range @@ -361,8 +372,8 @@

  • If rangeCount is not 0, abort these steps.
  • -
  • Set [=this=]'s range's cached live range to range by - a strong reference (not by making a copy). +
  • Set [=this=]'s range's legacy selection range to + range by a strong reference (not by making a copy).
  • @@ -395,7 +406,7 @@

    The method must make [=this=] empty by disassociating its - range if [=this=]'s range's cached live range is + range if [=this=]'s range's legacy selection range is range. Otherwise, it must throw a {{NotFoundError}}.

    @@ -492,8 +503,9 @@

    [=shadow-including inclusive ancestor=] of node, abort these steps.

  • -
  • Otherwise, reset the range with (node, - offset) and (node, offset). +
  • Otherwise, set the composed selection range with + (node, offset) and + (node, offset).
  • @@ -517,9 +529,11 @@

  • If [=this=] is empty, throw an {{InvalidStateError}} exception and abort these steps.
  • -
  • Let bp be the [=Range/start=] of [=this=]'s range. +
  • Let bp be the [=Range/start=] of [=this=]'s + range.
  • -
  • Reset the range with bp and bp. +
  • Set the composed selection range with bp and + bp.
  • @@ -542,7 +556,8 @@

  • Let bp be the [=Range/end=] of [=this=]'s range.
  • -
  • Reset the range with bp and bp. +
  • Set the composed selection range with bp and + bp.
  • @@ -567,15 +582,17 @@

    offset).
  • If node's [=tree/root=] is not the same as - [=this=]'s range's [=tree/root=], reset the range with + [=this=]'s range's [=tree/root=], + set the composed selection range with newFocus and newFocus.
  • Otherwise, if oldAnchor is [=boundary point/before=] - or equal to newFocus, reset the range + or equal to newFocus, + set the composed selection range with oldAnchor and newFocus.
  • -
  • Otherwise, reset the range with newFocus - and oldAnchor. +
  • Otherwise, set the composed selection range with + newFocus and oldAnchor.
  • If newFocus is [=boundary point/before=] @@ -618,9 +635,12 @@

    focus be the boundary point (focusNode, focusOffset).

  • -
  • If anchor is [=boundary point/before=] - focus, reset the range with anchor and - focus. Otherwise, reset the range with +
  • If anchorNode's [=tree/root=] is the same as + focusNode's [=tree/root=] and anchor is + [=boundary point/before=] focus, + set the composed selection range with + anchor and focus. Otherwise, + set the composed selection range with focus and anchor.
  • If focus is [=boundary point/before=] @@ -646,7 +666,8 @@

  • Let childCount be the number of [=tree/children=] of node.
  • -
  • Reset the range with (node, 0) +
  • Set the composed selection range with + (node, 0) and (node, childCount).
  • Set [=this=]'s direction to forwards. From d0111340ba7c547971b67ca796e51f2287578b48 Mon Sep 17 00:00:00 2001 From: Di Zhang Date: Wed, 5 Mar 2025 15:04:38 -0800 Subject: [PATCH 3/4] Fix format --- index.html | 33 ++++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/index.html b/index.html index aa2f3b7..cc4a402 100644 --- a/index.html +++ b/index.html @@ -133,26 +133,29 @@

    end, run these steps:

      -
    1. Let liveRange be a new {{Range/}} object.
    2. -
    3. [=Range/Set the start=] of liveRange to start. -
    4. -
    5. [=Range/Set the end=] of liveRange to end.
    6. -
    7. Let composedRange be a new - composed selection range - whose [=Range/start=] is start, [=Range/end=] is - end and legacy selection range is - liveRange.
    8. -

      - While the above steps might look identical, liveRange and +

    9. Let liveRange be a new {{Range/}} object.
    10. +
    11. [=Range/Set the start=] of liveRange to start. +
    12. +
    13. [=Range/Set the end=] of liveRange to end. +
    14. +
    15. Let composedRange be a new + composed selection range + whose [=Range/start=] is start, [=Range/end=] is + end and legacy selection range is + liveRange. +
    16. +
    17. Set [=this=]'s composed selection range to + composedRange. +
    18. +
    +

    + While the steps 2-3 and 4 might look identical, liveRange and composedRange could end up in very different states. The liveRange follows [=Range/set the start=] and [=Range/set the end=] algorithms, which will collapse in cross-root cases. On the other hand, composedRange is set directly without any collapsing logic. -

    -
  • Set [=this=]'s composed selection range to - composedRange.
  • - +

    Once a selection is associated with a given range, it must continue to be associated with that same range until this From c58cfb16a63f13b4f9916dc7ed5801e7e9636bc9 Mon Sep 17 00:00:00 2001 From: Di Zhang Date: Fri, 28 Mar 2025 16:46:56 -0700 Subject: [PATCH 4/4] Use new naming: composed/uncomposed range --- index.html | 236 ++++++++++++++++++++++++++++------------------------- 1 file changed, 124 insertions(+), 112 deletions(-) diff --git a/index.html b/index.html index cc4a402..6e14f2e 100644 --- a/index.html +++ b/index.html @@ -113,10 +113,11 @@

    Each selection can be associated with a single - composed selection range range. - When there is no range associated with the selection, the - selection is empty. The selection must be initially - empty. + composed range composed range, + which will have an associated legacy uncomposed range + uncomposed range. When there is no composed range + associated with the selection, the selection is empty. + The selection must be initially empty.

    A document's selection is a singleton object associated @@ -128,23 +129,22 @@

    dev do not. We follow Gecko/WebKit, because it lessens the chance of getRangeAt(0) throwing.

    -

    To set the composed selection range of [=this=], given the +

    To set the composed range of [=this=], given the boundary point start and boundary point end, run these steps:

      -
    1. Let liveRange be a new {{Range/}} object.
    2. +
    3. Let liveRange be a new {{Range}} object.
    4. [=Range/Set the start=] of liveRange to start.
    5. [=Range/Set the end=] of liveRange to end.
    6. Let composedRange be a new - composed selection range - whose [=Range/start=] is start, [=Range/end=] is - end and legacy selection range is - liveRange. + composed range whose [=Range/start=] is + start, [=Range/end=] is end and + legacy uncomposed range is liveRange.
    7. -
    8. Set [=this=]'s composed selection range to +
    9. Set [=this=]'s composed range to composedRange.
    @@ -157,9 +157,9 @@

    without any collapsing logic.

    - Once a selection is associated with a given range, it - must continue to be associated with that same range until this - specification requires otherwise. + Once a selection is associated with a given + composed range, it must continue to be associated with that same + composed range until this specification requires otherwise.

    For instance, if the DOM changes in a way that changes the range's @@ -170,40 +170,41 @@

    object, as required elsewhere in this specification.

    - If the selection's range is not null and is + If the selection's uncomposed range is not null and is [=range/collapsed=], then the caret position must be at that - range's boundary point. When the selection is not - [=range/collapsed=], this specification does not define the caret - position; user agents should follow platform conventions in deciding - whether the caret is at the start of the selection, the end of - the selection, or somewhere else. + uncomposed range's boundary point. When the + selection is not [=range/collapsed=], this specification does not + define the caret position; user agents should follow platform + conventions in deciding whether the caret is at the start of the + selection, the end of the selection, or somewhere else.

    Each selection has a direction: forwards, backwards, or directionless. If the user creates a selection by indicating first one boundary point of the - range and then the other (such as by clicking on one point and - dragging to another), and the first indicated boundary point is - [=boundary point/after=] the second, then the corresponding - selection must initially be backwards. If the first - indicated boundary point is [=boundary point/before=] the - second, then the corresponding selection must initially be - forwards. Otherwise, it must be directionless. + composed range and then the other (such as by clicking on one + point and dragging to another), and the first indicated + boundary point is [=boundary point/after=] the second, then the + corresponding selection must initially be backwards. + If the first indicated boundary point is + [=boundary point/before=] the second, then the corresponding + selection must initially be forwards. + Otherwise, it must be directionless.

    - When the selection's range is mutated by scripts, e.g. - via {{Range/selectNode(node)}}, direction of the + When the selection's composed range is mutated by scripts, + e.g. via {{Range/selectNode(node)}}, direction of the selection must be preserved.

    Each selection also has an anchor and a - focus. If the selection's range is null, its - anchor and focus are both null. If the selection's - range is not null and its direction is forwards, - its anchor is the range's legacy selection range's - [=range/start=], and its focus is the [=range/end=]. Otherwise, - its focus is the [=range/start=] and its anchor is the - [=range/end=]. + focus. If the selection's uncomposed range is + null, its anchor and focus are both null. If the + selection's uncomposed range is not null and its + direction is forwards, its anchor is the + uncomposed range's [=range/start=], and its focus is the + [=range/end=]. Otherwise, its focus is the [=range/start=] and + its anchor is the [=range/end=].

    anchor and focus of selection need not to be in @@ -326,7 +327,7 @@

    The attribute must return `"None"` if [=this=] is empty or either focus or anchor is not in the [=document - tree=], `"Caret"` if [=this=]'s range is + tree=], `"Caret"` if [=this=]'s uncomposed range is [=range/collapsed=], and `"Range"` otherwise.

    @@ -350,12 +351,13 @@

    index is not 0, or if [=this=] is empty or either focus or anchor is not in the [=document tree=]. Otherwise, it must return a reference to (not a - copy of) [=this=]'s range's legacy selection range. + copy of) [=this=]'s uncomposed range.

    - Thus subsequent calls of this method returns the same range - object if nothing has removed [=this=]'s range in the meantime. In - particular, getSelection().getRangeAt(0) === + Thus subsequent calls of this method returns the same + uncomposed range object if nothing has removed [=this=]'s + range in the meantime. In particular, + getSelection().getRangeAt(0) === getSelection().getRangeAt(0) evaluates to true if the selection is not empty.

    @@ -375,31 +377,37 @@

  • If rangeCount is not 0, abort these steps.
  • -
  • Set [=this=]'s range's legacy selection range to - range by a strong reference (not by making a copy). +
  • Set [=this=]'s uncomposed range to range + by a strong reference (not by making a copy). +
  • +
  • Set [=this=]'s composed range's [=Range/start=] to + range's start. +
  • +
  • Set [=this=]'s composed range's [=Range/end=] to + range's end.
  • - Since range is added by reference, subsequent calls to - getRangeAt(0) returns the same object, and any changes - that a script makes to range after it is added must be - reflected in the selection, until something else removes or - replaces [=this=]'s range. In particular, the - selection will contain b as opposed to - a after running the following code: var r = - document.createRange(); r.selectNode(a); + Since uncomposed range is added by reference, subsequent + calls to getRangeAt(0) returns the same object, and any + changes that a script makes to uncomposed range after it is + added must be reflected in the selection, until something + else removes or replaces [=this=]'s uncomposed range. + In particular, the selection will contain b as + opposed to a after running the following code: + var r = document.createRange(); r.selectNode(a); getSelection().addRange(r); r.selectNode(b);

    At Step 2, Chrome 58 and Edge 25 do nothing. Firefox 51 gives you a multi-range selection. At least they keep the exisiting - range. + uncomposed range.

    At Step 3, Chrome 58 and Firefox 51 store a reference, as described here. Edge 25 stores a copy. Firefox 51 changes its - selection if the range is modified. + selection if the uncomposed range is modified.

    @@ -409,7 +417,7 @@

    The method must make [=this=] empty by disassociating its - range if [=this=]'s range's legacy selection range is + composed range if [=this=]'s uncomposed range is range. Otherwise, it must throw a {{NotFoundError}}.

    @@ -419,7 +427,8 @@

    The method must make [=this=] empty by disassociating its - range if [=this=] has an associated range. + composed range if [=this=] has an associated + composed range.

    @@ -439,8 +448,9 @@

  • If [=this=] is empty, return an empty array.
  • Otherwise, let startNode be [=range/start node=] of - the [=range=] associated with [=this=], and let - startOffset be [=range/start offset=] of the [=range=]. + the composed range associated with [=this=], and let + startOffset be [=range/start offset=] of the + composed range.
  • While startNode is a [=node=], startNode's [=tree/root=] is a [=shadow root=], and @@ -457,9 +467,10 @@

  • -
  • Let endNode be [=range/end node=] of the [=range=] - associated with [=this=], and let endOffset be - [=range/end offset=] of the [=range=]. +
  • Let endNode be [=range/end node=] of the + composed range associated with [=this=], and let + endOffset be [=range/end offset=] of the + composed range.
  • While endNode is a [=node=], endNode's [=tree/root=] is a [=shadow root=], and endNode's @@ -506,7 +517,7 @@

    [=shadow-including inclusive ancestor=] of node, abort these steps.

  • -
  • Otherwise, set the composed selection range with +
  • Otherwise, set the composed range with (node, offset) and (node, offset).
  • @@ -533,9 +544,9 @@

    exception and abort these steps.

  • Let bp be the [=Range/start=] of [=this=]'s - range. + uncomposed range.
  • -
  • Set the composed selection range with bp and +
  • Set the composed range with bp and bp.
  • @@ -557,9 +568,10 @@

  • If [=this=] is empty, throw an {{InvalidStateError}} exception and abort these steps.
  • -
  • Let bp be the [=Range/end=] of [=this=]'s range. +
  • Let bp be the [=Range/end=] of [=this=]'s + uncomposed range.
  • -
  • Set the composed selection range with bp and +
  • Set the composed range with bp and bp.
  • @@ -585,19 +597,17 @@

    offset).
  • If node's [=tree/root=] is not the same as - [=this=]'s range's [=tree/root=], - set the composed selection range with + [=this=]'s uncomposed range's [=tree/root=], + set the composed range with newFocus and newFocus.
  • Otherwise, if oldAnchor is [=boundary point/before=] - or equal to newFocus, - set the composed selection range + or equal to newFocus, set the composed range with oldAnchor and newFocus.
  • -
  • Otherwise, set the composed selection range with +
  • Otherwise, set the composed range with newFocus and oldAnchor.
  • -
  • If newFocus is [=boundary point/before=] oldAnchor, set [=this=]'s direction to backwards. Otherwise, set it to forwards. @@ -638,12 +648,11 @@

    focus be the boundary point (focusNode, focusOffset).

  • -
  • If anchorNode's [=tree/root=] is the same as - focusNode's [=tree/root=] and anchor is - [=boundary point/before=] focus, - set the composed selection range with + +
  • If anchor is [=boundary point/before=] + focus, set the composed range with anchor and focus. Otherwise, - set the composed selection range with + set the composed range with focus and anchor.
  • If focus is [=boundary point/before=] @@ -669,7 +678,7 @@

  • Let childCount be the number of [=tree/children=] of node.
  • -
  • Set the composed selection range with +
  • Set the composed range with (node, 0) and (node, childCount).
  • @@ -769,9 +778,9 @@

    The method must invoke {{Range/deleteContents()}} on [=this=]'s - range if [=this=] is not empty and both focus - and anchor are in the [=document tree=]. Otherwise the - method must do nothing. + uncomposed range if [=this=] is not empty and + both focus and anchor are in the [=document tree=]. + Otherwise the method must do nothing.

    This is the one method that actually mutates the range instead of @@ -792,21 +801,22 @@

    Otherwise, if allowPartialContainment is false, the method must return true if and - only if [=range/start=] of its range is [=boundary + only if [=range/start=] of its uncomposed range is [=boundary point/before=] or visually equivalent to the first boundary point in the node and [=range/end=] - of its range is [=boundary point/after=] or visually - equivalent to the last boundary point in the + of its uncomposed range is [=boundary point/after=] or + visually equivalent to the last boundary point in the node.

    If allowPartialContainment is true, the method must return true if and only if [=range/start=] - of its range is [=boundary point/before=] or visually - equivalent to the last boundary point in the node - and [=range/end=] of its range is - [=boundary point/after=] or visually equivalent to the first - boundary point in the node. + of its uncomposed range is [=boundary point/before=] or + visually equivalent to the last boundary point in the + node and [=range/end=] of its + uncomposed range is [=boundary point/after=] or visually + equivalent to the first boundary point in the + node.

    @@ -815,8 +825,8 @@

    The stringification must return the string, which is the - concatenation of the rendered text if there is a [=range=] - associated with [=this=]. + concatenation of the rendered text if there is a + uncomposed range associated with [=this=].

    If the selection is within a textarea or input @@ -856,7 +866,7 @@

    All of the members of the {{Selection}} interface are defined in terms - of operations on the range object (if any) + of operations on the composed range object (if any) represented by the object. These operations can raise exceptions, as defined for the {{Range}} interface; this can therefore result in the members of the Selection interface raising exceptions as well, @@ -970,25 +980,26 @@

    When the user agent is to [=replace data=] or [=CharacterData/substring data=] on {{CharacterData}}, the user agent must update the - range associated with selection of the [=Node/node - document=] of the {{CharacterData}} as if it's a live range. + composed range and uncomposed range associated with + selection of the [=Node/node document=] of the {{CharacterData}}.

    When the user agent is to split a {{Text}} [=node=], the user agent - must update the range associated with selection of the - [=Node/node document=] of the {{Text}} as if it's a live range. + must update the composed range and uncomposed range + associated with selection of the [=Node/node document=] of the + {{Text}}.

    When the user agent is to run steps for normalize() - method, the user agent must update the range associated with - selection of the [=Node/node document=] of [=this=] as if it's a - live range. + method, the user agent must update the composed range and + uncomposed range associated with selection of the + [=Node/node document=] of [=this=].

    When the user agent is to [=remove=] or [=insert=] a [=node=], the user - agent must update the range associated with selection of - the [=Node/node document=] of the [=node=] as if it's a live - range. + agent must update the composed range and uncomposed range + associated with selection of the [=Node/node document=] of the + [=node=].

    @@ -999,15 +1010,15 @@

    The user agent should allow the user to change the selection associated with the [=navigable/active document=]. If the user makes any modification to a selection, the user agent must create a - new range with suitable [=range/start=] and [=range/end=] of the - range and associate the selection with this new - range (not modify the existing range), and set update - selection's direction to forwards if the - [=range/start=] is [=boundary point/before=] or equal to the - [=range/end=], backwards if if the [=range/end=] is [=boundary - point/before=] the [=range/start=], or directionless if the - [=range/start=] and the [=range/end=] cannot be ordered due to the - platform convention. + new composed range with suitable [=range/start=] and + [=range/end=] of the composed range and associate the + selection with this new composed range (not modify the + existing composed range), and set update selection's + direction to forwards if the [=range/start=] is + [=boundary point/before=] or equal to the [=range/end=], + backwards if if the [=range/end=] is [=boundary point/before=] + the [=range/start=], or directionless if the [=range/start=] and + the [=range/end=] cannot be ordered due to the platform convention.

    The user agent must not make a selection empty if it was @@ -1049,8 +1060,9 @@

    selectionchange event

    - When the selection is dissociated with its range, - associated with a new range, or the associated range's + When the selection is dissociated with its composed range, + associated with a new composed range, or the associated + composed range or uncomposed range's boundary point is mutated either by the user or the content script, the user agent must schedule a selectionchange event on document.