Fix some delete-related bugs
authorAryeh Gregor <AryehGregor+gitcommit@gmail.com>
Tue, 30 Aug 2011 13:52:24 -0600
changeset 553 5d11411c4a35
parent 552 bfb0c735c728
child 554 1e2008504cf6
Fix some delete-related bugs

Now the selection is in the right place for backspacing on something
like <ol><li>foo</li></ol>{}<br>. This was a horrifyingly complicated
commit given how simple the changes I wanted were! I've filed a new bug
to refactor delete stuff:

http://www.w3.org/Bugs/Public/show_bug.cgi?id=13973

Fixes: http://www.w3.org/Bugs/Public/show_bug.cgi?id=13830
editing.html
implementation.js
preprocess
source.html
--- a/editing.html	Mon Aug 29 14:42:53 2011 -0600
+++ b/editing.html	Tue Aug 30 13:52:24 2011 -0600
@@ -65,7 +65,7 @@
 <body class=draft>
 <div class=head id=head>
 <h1>HTML Editing APIs</h1>
-<h2 class="no-num no-toc" id=work-in-progress-&mdash;-last-update-29-august-2011>Work in Progress &mdash; Last Update 29 August 2011</h2>
+<h2 class="no-num no-toc" id=work-in-progress-&mdash;-last-update-30-august-2011>Work in Progress &mdash; Last Update 30 August 2011</h2>
 <dl>
  <dt>Editor
  <dd>Aryeh Gregor &lt;<a href=mailto:[email protected]>[email protected]</a>&gt;
@@ -154,7 +154,7 @@
    <li><a href=#assorted-block-formatting-command-algorithms>Assorted block formatting command algorithms</a></li>
    <li><a href=#block-extending-a-range>Block-extending a range</a></li>
    <li><a href=#recording-and-restoring-overrides>Recording and restoring overrides</a></li>
-   <li><a href=#deleting-the-contents-of-a-range>Deleting the contents of a range</a></li>
+   <li><a href=#deleting-the-selection>Deleting the selection</a></li>
    <li><a href="#splitting-a-node-list's-parent">Splitting a node list's parent</a></li>
    <li><a href=#canonical-space-sequences>Canonical space sequences</a></li>
    <li><a href=#indenting-and-outdenting>Indenting and outdenting</a></li>
@@ -1306,7 +1306,18 @@
   <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#tree-order>tree order</a>.
 
   <li>If <var title="">ref</var> is an <a href=#editable>editable</a> <a href=#extraneous-line-break>extraneous line
-  break</a>, remove it from its <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-parent title=concept-tree-parent>parent</a>.
+  break</a>:
+
+  <ol>
+    <li>
+    <p class=comments>If the block ends with <code title="">&lt;span&gt;&lt;br&gt;&lt;/span&gt;</code>, for
+    instance, we want to remove the span too.
+
+    <p>While <var title="">ref</var>'s <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-parent title=concept-tree-parent>parent</a> is <a href=#editable>editable</a> and
+    <a href=#invisible>invisible</a>, set <var title="">ref</var> to its <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-parent title=concept-tree-parent>parent</a>.
+
+    <li>Remove <var title="">ref</var> from its <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-parent title=concept-tree-parent>parent</a>.
+  </ol>
 </ol>
 
 <p>To <dfn id=remove-extraneous-line-breaks-from>remove extraneous line breaks from</dfn> a <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-node title=concept-node>node</a>, first
@@ -4410,31 +4421,33 @@
 </ol>
 
 <[email protected]}-->
-<h3 id=deleting-the-contents-of-a-range>Deleting the contents of a range</h3>
+<h3 id=deleting-the-selection>Deleting the selection</h3>
 
 <p class=comments>TODO: Consider what should happen for block merging in corner
 cases like display: inline-table.
 
-<p>To <dfn id=delete-the-contents>delete the contents</dfn> of a <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range title=concept-range>range</a> <var title="">range</var>, given a
-<var title="">block merging</var> flag that defaults to true and a <var title="">strip
-wrappers</var> flag that defaults to true:
+<p>To <dfn id=delete-the-selection>delete the selection</dfn>, given a <var title="">block merging</var> flag
+that defaults to true, a <var title="">strip wrappers</var> flag that defaults to
+true, and a string <var title="">direction</var> that defaults to "forward":
 
 <div class=note>
 <p>The idea behind this algorithm is self-explanatory, but the details wind up
 being remarkably complicated.
 
-<p>First, any editable nodes inside the range will be deleted, and the range
-will be collapsed.  By way of contrast, <a href=#effectively-contained>effectively contained</a>
-tries to expand the range to include as much as possible, so <code title="">&lt;p&gt;[foo]&lt;/p&gt;</code> contains the <code title="">&lt;p&gt;</code>.  What
-we do here is contract the range to include as little as possible, so <code title="">{&lt;p&gt;foo&lt;/p&gt;}</code> contains only <code title="">foo</code> and
-doesn't delete the paragraph.
-
-<p>After that, if the range originally started and ended in different blocks,
-and the <var title="">block merging</var> flag is true, the end block will get merged
-into the start block.  This is needed so if the user selects text on several
-lines and deletes it, the text immediately that was before the selection winds
-up on the same line as the text immediately after it.  For example, <code title="">&lt;p&gt;fo[o&lt;/p&gt;&lt;div&gt;b]ar&lt;/div&gt;</code> becomes <code title="">&lt;p&gt;fo[]ar&lt;/p&gt;</code>.  This procedure winds up being tricky, and
-takes up a large chunk of the logic.
+<p>First, any editable nodes inside the selection will be deleted, and the
+selection will be collapsed.  By way of contrast, <a href=#effectively-contained>effectively
+contained</a> tries to expand the range to include as much as possible, so
+<code title="">&lt;p&gt;[foo]&lt;/p&gt;</code> contains the <code title="">&lt;p&gt;</code>.  What we do here is contract
+the range to include as little as possible, so <code title="">{&lt;p&gt;foo&lt;/p&gt;} </code> contains
+only <code title="">foo</code> and doesn't delete the paragraph.
+
+<p>After that, if the selection originally started and ended in different
+blocks, and the <var title="">block merging</var> flag is true, the end block will get
+merged into the start block.  This is needed so if the user selects text on
+several lines and deletes it, the text immediately that was before the
+selection winds up on the same line as the text immediately after it.  For
+example, <code title="">&lt;p&gt;fo[o&lt;/p&gt;&lt;div&gt;b]ar&lt;/div&gt;</code> becomes <code title="">&lt;p&gt;fo[]ar&lt;/p&gt;</code>.
+This procedure winds up being tricky, and takes up a large chunk of the logic.
 
 <p>Tables are a notable special case.  If an entire table is contained in the
 range, it will be deleted.  If it's anything less, only the contents of the
@@ -4456,11 +4469,12 @@
 </div>
 
 <ol>
-  <li>If <var title="">range</var> is null, abort these steps and do nothing.
+  <li>If the <a href=#active-range>active range</a> is null, abort these steps and do
+  nothing.
 
   <li>Let <var title="">start node</var>, <var title="">start offset</var>, <var title="">end node</var>,
-  and <var title="">end offset</var> be <var title="">range</var>'s <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</a> and
-  <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-end title=concept-range-end>end</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-node title=concept-boundary-point-node>nodes</a> and <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-offset title=concept-boundary-point-offset>offsets</a>.
+  and <var title="">end offset</var> be the <a href=#active-range>active range</a>'s <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</a>
+  and <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-end title=concept-range-end>end</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-node title=concept-boundary-point-node>nodes</a> and <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-offset title=concept-boundary-point-offset>offsets</a>.
 
   <li>
   <div class=comments>
@@ -4475,7 +4489,7 @@
 -&gt; foo&lt;br /&gt;{bar]
 -&gt; foo&lt;br /&gt;[bar]</pre>
 
-  <p>and we deselected the &lt;br&gt;.
+  <p>and we deselected the <code title="">&lt;br&gt;</code>.
   </div>
 
   <p>While <var title="">start node</var> has at least one <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-child title=concept-tree-child>child</a>:
@@ -4489,7 +4503,7 @@
 -&gt; &lt;b&gt;foo{&lt;/b&gt;&lt;i&gt;bar]&lt;/i&gt;
 -&gt; &lt;b&gt;foo&lt;/b&gt;{&lt;i&gt;bar]&lt;/i&gt;</pre>
 
-    <p>Then the next step will make it &lt;b&gt;foo&lt;/b&gt;&lt;i&gt;[bar]&lt;/i&gt;.
+    <p>Then the next step will make it <code title="">&lt;b&gt;foo&lt;/b&gt;&lt;i&gt;[bar]&lt;/i&gt;</code>.
 
     <p>We don't want to do this for block nodes, because that would lead to
     something like
@@ -4497,7 +4511,7 @@
       <pre>&lt;p&gt;foo[&lt;/p&gt;&lt;p&gt;]bar&lt;p&gt;</pre>
 
     <p>ultimately collapsing, which is wrong.  Once we do the deletion, it
-    needs to wind up &lt;p&gt;foo[]bar&lt;/p&gt;, whereas an actually collapsed
+    needs to wind up <code title="">&lt;p&gt;foo[]bar&lt;/p&gt;</code>, whereas an actually collapsed
     selection should do nothing.
     </div>
 
@@ -4562,8 +4576,17 @@
   </ol>
 
   <li>If (<var title="">end node</var>, <var title="">end offset</var>) is not <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-bp-after title=concept-bp-after>after</a>
-  (<var title="">start node</var>, <var title="">start offset</var>), set <var title="">range</var>'s
-  <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-end title=concept-range-end>end</a> to its <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</a> and abort these steps.
+  (<var title="">start node</var>, <var title="">start offset</var>):
+
+  <ol>
+    <li>If <var title="">direction</var> is "forward", call <code class=external data-anolis-spec=domrange title=dom-Selection-collapseToStart><a href=http://html5.org/specs/dom-range.html#dom-selection-collapsetostart>collapseToStart()</a></code> on the
+    <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#context-object>context object</a>'s <code class=external data-anolis-spec=domrange><a href=http://html5.org/specs/dom-range.html#selection>Selection</a></code>.
+
+    <li>Otherwise, call <code class=external data-anolis-spec=domrange title=dom-Selection-collapseToEnd><a href=http://html5.org/specs/dom-range.html#dom-selection-collapsetoend>collapseToEnd()</a></code> on the <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#context-object>context object</a>'s
+    <code class=external data-anolis-spec=domrange><a href=http://html5.org/specs/dom-range.html#selection>Selection</a></code>.
+
+    <li>Abort these steps.
+  </ol>
 
   <li>If <var title="">start node</var> is a <code class=external data-anolis-spec=domcore><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#text>Text</a></code> node and <var title="">start offset</var>
   is 0, set <var title="">start offset</var> to the <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-indexof title=concept-indexof>index</a> of <var title="">start node</var>,
@@ -4573,9 +4596,11 @@
   its <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-node-length title=concept-node-length>length</a>, set <var title="">end offset</var> to one plus the <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-indexof title=concept-indexof>index</a> of
   <var title="">end node</var>, then set <var title="">end node</var> to its <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-parent title=concept-tree-parent>parent</a>.
 
-  <li>Set <var title="">range</var>'s <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</a> to (<var title="">start node</var>,
-  <var title="">start offset</var>) and its <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-end title=concept-range-end>end</a> to (<var title="">end node</var>,
-  <var title="">end offset</var>).
+  <li>Call <code class=external data-anolis-spec=domrange title=dom-Selection-collapse><a href=http://html5.org/specs/dom-range.html#dom-selection-collapse>collapse(<var title="">start node</var>, <var title="">start offset</var>)</a></code> on
+  the <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#context-object>context object</a>'s <code class=external data-anolis-spec=domrange><a href=http://html5.org/specs/dom-range.html#selection>Selection</a></code>.
+
+  <li>Call <code class=external data-anolis-spec=domrange title=dom-Selection-extend><a href=http://html5.org/specs/dom-range.html#dom-selection-extend>extend(<var title="">end node</var>, <var title="">end offset</var>)</a></code> on the
+  <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#context-object>context object</a>'s <code class=external data-anolis-spec=domrange><a href=http://html5.org/specs/dom-range.html#selection>Selection</a></code>.
 
   <li>
   <div class=comments>
@@ -4589,8 +4614,8 @@
   anything.
   </div>
 
-  <p>Let <var title="">start block</var> be the <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-node title=concept-boundary-point-node>node</a> of
-  <var title="">range</var>.
+  <p>Let <var title="">start block</var> be the <a href=#active-range>active range</a>'s
+  <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-node title=concept-boundary-point-node>node</a>.
 
   <li>While <var title="">start block</var>'s <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-parent title=concept-tree-parent>parent</a> is <a href=#in-the-same-editing-host>in the same editing
   host</a> and <var title="">start block</var> is an <a href=#inline-node>inline node</a>, set
@@ -4626,8 +4651,7 @@
   <var title="">start block</var>, or <var title="">start block</var> is a <code class=external data-anolis-spec=html title="the td element"><a href=http://www.whatwg.org/html/#the-td-element>td</a></code> or <code class=external data-anolis-spec=html title="the th element"><a href=http://www.whatwg.org/html/#the-th-element>th</a></code>, set
   <var title="">start block</var> to null.
 
-  <li>Let <var title="">end block</var> be the <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-end title=concept-range-end>end</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-node title=concept-boundary-point-node>node</a> of
-  <var title="">range</var>.
+  <li>Let <var title="">end block</var> be the <a href=#active-range>active range</a>'s <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-end title=concept-range-end>end</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-node title=concept-boundary-point-node>node</a>.
 
   <li>While <var title="">end block</var>'s <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-parent title=concept-tree-parent>parent</a> is <a href=#in-the-same-editing-host>in the same editing
   host</a> and <var title="">end block</var> is an <a href=#inline-node>inline node</a>, set
@@ -4669,7 +4693,11 @@
     <li><a href=#canonicalize-whitespace>Canonicalize whitespace</a> at (<var title="">start node</var>,
     <var title="">start offset</var>).
 
-    <li>Set <var title="">range</var>'s <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-end title=concept-range-end>end</a> to its <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</a>.
+    <li>If <var title="">direction</var> is "forward", call <code class=external data-anolis-spec=domrange title=dom-Selection-collapseToStart><a href=http://html5.org/specs/dom-range.html#dom-selection-collapsetostart>collapseToStart()</a></code> on the
+    <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#context-object>context object</a>'s <code class=external data-anolis-spec=domrange><a href=http://html5.org/specs/dom-range.html#selection>Selection</a></code>.
+
+    <li>Otherwise, call <code class=external data-anolis-spec=domrange title=dom-Selection-collapseToEnd><a href=http://html5.org/specs/dom-range.html#dom-selection-collapsetoend>collapseToEnd()</a></code> on the <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#context-object>context object</a>'s
+    <code class=external data-anolis-spec=domrange><a href=http://html5.org/specs/dom-range.html#selection>Selection</a></code>.
 
     <li>
     <p class=comments>This is needed to restore any overrides that would
@@ -4697,9 +4725,9 @@
   cell-selection mode when you try to select between cells, at least in some
   cases, instead of selecting letter-by-letter.
 
-  <p>For each <var title="">node</var> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#contained>contained</a> in <var title="">range</var>, append
-  <var title="">node</var> to <var title="">node list</var> if the last member of <var title="">node
-  list</var> (if any) is not an <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-ancestor title=concept-tree-ancestor>ancestor</a> of <var title="">node</var>;
+  <p>For each <var title="">node</var> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#contained>contained</a> in the <a href=#active-range>active range</a>,
+  append <var title="">node</var> to <var title="">node list</var> if the last member of
+  <var title="">node list</var> (if any) is not an <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-ancestor title=concept-tree-ancestor>ancestor</a> of <var title="">node</var>;
   <var title="">node</var> is <a href=#editable>editable</a>; and <var title="">node</var> is not a
   <code class=external data-anolis-spec=html title="the thead element"><a href=http://www.whatwg.org/html/#the-thead-element>thead</a></code>, <code class=external data-anolis-spec=html title="the tbody element"><a href=http://www.whatwg.org/html/#the-tbody-element>tbody</a></code>, <code class=external data-anolis-spec=html title="the tfoot element"><a href=http://www.whatwg.org/html/#the-tfoot-element>tfoot</a></code>, <code class=external data-anolis-spec=html title="the tr element"><a href=http://www.whatwg.org/html/#the-tr-element>tr</a></code>, <code class=external data-anolis-spec=html title="the th element"><a href=http://www.whatwg.org/html/#the-th-element>th</a></code>, or <code class=external data-anolis-spec=html title="the td element"><a href=http://www.whatwg.org/html/#the-td-element>td</a></code>.
 
@@ -4738,10 +4766,11 @@
   <li>If <var title="">end node</var> is an <a href=#editable>editable</a> <code class=external data-anolis-spec=domcore><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#text>Text</a></code> node, call
   <code class=external data-anolis-spec=domcore title=dom-CharacterData-deleteData><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-characterdata-deletedata>deleteData(0, <var title="">end offset</var>)</a></code> on it.
 
-  <li><a href=#canonicalize-whitespace>Canonicalize whitespace</a> at <var title="">range</var>'s
+  <li><a href=#canonicalize-whitespace>Canonicalize whitespace</a> at the <a href=#active-range>active range</a>'s
   <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</a>.
 
-  <li><a href=#canonicalize-whitespace>Canonicalize whitespace</a> at <var title="">range</var>'s <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-end title=concept-range-end>end</a>.
+  <li><a href=#canonicalize-whitespace>Canonicalize whitespace</a> at the <a href=#active-range>active range</a>'s
+  <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-end title=concept-range-end>end</a>.
 
   <li>
   <div class=comments>
@@ -4771,7 +4800,11 @@
   and <var title="">end block</var> are the same:
 
   <ol>
-    <li>Set <var title="">range</var>'s <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-end title=concept-range-end>end</a> to its <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</a>.
+    <li>If <var title="">direction</var> is "forward", call <code class=external data-anolis-spec=domrange title=dom-Selection-collapseToStart><a href=http://html5.org/specs/dom-range.html#dom-selection-collapsetostart>collapseToStart()</a></code> on the
+    <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#context-object>context object</a>'s <code class=external data-anolis-spec=domrange><a href=http://html5.org/specs/dom-range.html#selection>Selection</a></code>.
+
+    <li>Otherwise, call <code class=external data-anolis-spec=domrange title=dom-Selection-collapseToEnd><a href=http://html5.org/specs/dom-range.html#dom-selection-collapsetoend>collapseToEnd()</a></code> on the <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#context-object>context object</a>'s
+    <code class=external data-anolis-spec=domrange><a href=http://html5.org/specs/dom-range.html#selection>Selection</a></code>.
 
     <li><a href=#restore-states-and-values>Restore states and values</a> from <var title="">overrides</var>.
 
@@ -4788,9 +4821,6 @@
   <p>If <var title="">start block</var> has one <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-child title=concept-tree-child>child</a>, which is a <a href=#collapsed-block-prop>collapsed
   block prop</a>, remove its <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-child title=concept-tree-child>child</a> from it.
 
-  <li>If <var title="">end block</var> has one <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-child title=concept-tree-child>child</a>, which is a <a href=#collapsed-block-prop>collapsed
-  block prop</a>, remove its <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-child title=concept-tree-child>child</a> from it.
-
   <li>
   <p class=comments>Just repeatedly blow up the end block in this case.
 
@@ -4802,8 +4832,9 @@
     <li>While <var title="">reference node</var> is not a <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-child title=concept-tree-child>child</a> of <var title="">start
     block</var>, set <var title="">reference node</var> to its <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-parent title=concept-tree-parent>parent</a>.
 
-    <li>Set the <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</a> and <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-end title=concept-range-end>end</a> of <var title="">range</var> to
-    (<var title="">start block</var>, <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-indexof title=concept-indexof>index</a> of <var title="">reference node</var>).
+    <li>Call <code class=external data-anolis-spec=domrange title=dom-Selection-collapse><a href=http://html5.org/specs/dom-range.html#dom-selection-collapse>collapse()</a></code> on the <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#context-object>context object</a>'s <code class=external data-anolis-spec=domrange><a href=http://html5.org/specs/dom-range.html#selection>Selection</a></code>, with
+    first argument <var title="">start block</var> and second argument the <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-indexof title=concept-indexof>index</a> of
+    <var title="">reference node</var>.
 
     <li>If <var title="">end block</var> has no <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-child title=concept-tree-child>children</a>:
 
@@ -4860,8 +4891,9 @@
   block</var>:
 
   <ol>
-    <li>Set the <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</a> and <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-end title=concept-range-end>end</a> of <var title="">range</var> to
-    (<var title="">start block</var>, <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-node-length title=concept-node-length>length</a> of <var title="">start block</var>).
+    <li>Call <code class=external data-anolis-spec=domrange title=dom-Selection-collapse><a href=http://html5.org/specs/dom-range.html#dom-selection-collapse>collapse()</a></code> on the <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#context-object>context object</a>'s <code class=external data-anolis-spec=domrange><a href=http://html5.org/specs/dom-range.html#selection>Selection</a></code>, with
+    first argument <var title="">start block</var> and second argument <var title="">start
+    block</var>'s <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-node-length title=concept-node-length>length</a>.
 
     <li>Let <var title="">reference node</var> be <var title="">start block</var>.
 
@@ -4875,12 +4907,12 @@
     <li>Let <var title="">nodes to move</var> be a list of <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-node title=concept-node>nodes</a>, initially empty.
 
     <li>If <var title="">reference node</var>'s <code class=external data-anolis-spec=domcore title=dom-Node-nextSibling><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-node-nextsibling>nextSibling</a></code> is neither null nor a
-    <code class=external data-anolis-spec=html title="the br element"><a href=http://www.whatwg.org/html/#the-br-element>br</a></code> nor a <a href=#block-node>block node</a>, append it to <var title="">nodes to
-    move</var>.
-
-    <li>While <var title="">nodes to move</var> is nonempty and its last member's
-    <code class=external data-anolis-spec=domcore title=dom-Node-nextSibling><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-node-nextsibling>nextSibling</a></code> is neither null nor a <code class=external data-anolis-spec=html title="the br element"><a href=http://www.whatwg.org/html/#the-br-element>br</a></code> nor a <a href=#block-node>block node</a>,
-    append it to <var title="">nodes to move</var>.
+    <a href=#block-node>block node</a>, append it to <var title="">nodes to move</var>.
+
+    <li>While <var title="">nodes to move</var> is nonempty and its last member isn't a
+    <code class=external data-anolis-spec=html title="the br element"><a href=http://www.whatwg.org/html/#the-br-element>br</a></code> and its last member's <code class=external data-anolis-spec=domcore title=dom-Node-nextSibling><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-node-nextsibling>nextSibling</a></code> is neither null nor a
+    <a href=#block-node>block node</a>, append its last member's <code class=external data-anolis-spec=domcore title=dom-Node-nextSibling><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-node-nextsibling>nextSibling</a></code> to
+    <var title="">nodes to move</var>.
 
     <li><a href=#record-the-values>Record the values</a> of <var title="">nodes to move</var>, and let
     <var title="">values</var> be the result.
@@ -4888,9 +4920,6 @@
     <li>For each <var title="">node</var> in <var title="">nodes to move</var>, append
     <var title="">node</var> as the last <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-child title=concept-tree-child>child</a> of <var title="">start block</var>,
     <a href=#preserving-ranges>preserving ranges</a>.
-
-    <li>If the <code class=external data-anolis-spec=domcore title=dom-Node-nextSibling><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-node-nextsibling>nextSibling</a></code> of <var title="">reference node</var> is a <code class=external data-anolis-spec=html title="the br element"><a href=http://www.whatwg.org/html/#the-br-element>br</a></code>, remove
-    it from its <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-parent title=concept-tree-parent>parent</a>.
   </ol>
 
   <li>
@@ -4901,8 +4930,9 @@
   <p>Otherwise:
 
   <ol>
-    <li>Set the <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</a> and <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-end title=concept-range-end>end</a> of <var title="">range</var> to
-    (<var title="">start block</var>, <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-node-length title=concept-node-length>length</a> of <var title="">start block</var>).
+    <li>Call <code class=external data-anolis-spec=domrange title=dom-Selection-collapse><a href=http://html5.org/specs/dom-range.html#dom-selection-collapse>collapse()</a></code> on the <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#context-object>context object</a>'s <code class=external data-anolis-spec=domrange><a href=http://html5.org/specs/dom-range.html#selection>Selection</a></code>, with
+    first argument <var title="">start block</var> and second argument <var title="">start
+    block</var>'s <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-node-length title=concept-node-length>length</a>.
 
     <li>If <var title="">end block</var>'s <code class=external data-anolis-spec=domcore title=dom-Node-firstChild><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-node-firstchild>firstChild</a></code> is an <a href=#inline-node>inline node</a>
     and <var title="">start block</var>'s <code class=external data-anolis-spec=domcore title=dom-Node-lastChild><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-node-lastchild>lastChild</a></code> is a <code class=external data-anolis-spec=html title="the br element"><a href=http://www.whatwg.org/html/#the-br-element>br</a></code>, remove <var title="">start
@@ -4926,6 +4956,9 @@
   <code class=external data-anolis-spec=domcore title=dom-Document-createElement><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-document-createelement>createElement("br")</a></code> on the <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#context-object>context object</a> and append the result as the
   last <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-child title=concept-tree-child>child</a> of <var title="">start block</var>.
 
+  <li><a href=#remove-extraneous-line-breaks-at-the-end-of>Remove extraneous line breaks at the end of</a> <var title="">start
+  block</var>.
+
   <li><a href=#restore-states-and-values>Restore states and values</a> from <var title="">overrides</var>.
 </ol>
 
@@ -6557,7 +6590,7 @@
 
 <div class=note>
 <p>This is the same as hitting backspace (see <a href=#additional-requirements>Additional requirements</a>).  The easy part is
-if the selection isn't collapsed: just <a href=#delete-the-contents>delete the contents</a>.  But
+if the selection isn't collapsed: just <a href=#delete-the-selection>delete the selection</a>.  But
 it turns out rich-text editors have a lot of special behaviors for hitting
 backspace with a collapsed selection.  Most obviously, if there's a text node
 right before the cursor (maybe wrapped in some inline elements), we delete its
@@ -6600,8 +6633,8 @@
 <p><a href=#action>Action</a>:
 
 <ol>
-  <li>If the <a href=#active-range>active range</a> is not <code class=external data-anolis-spec=domrange title=dom-Range-collapsed><a href=http://html5.org/specs/dom-range.html#dom-range-collapsed>collapsed</a></code>, <a href=#delete-the-contents>delete the contents</a>
-  of the <a href=#active-range>active range</a> and abort these steps.
+  <li>If the <a href=#active-range>active range</a> is not <code class=external data-anolis-spec=domrange title=dom-Range-collapsed><a href=http://html5.org/specs/dom-range.html#dom-range-collapsed>collapsed</a></code>, <a href=#delete-the-selection>delete the selection</a>
+  and abort these steps.
 
   <li>
   <p class=comments>Needed so that if there are multiple consecutive spaces we
@@ -6691,10 +6724,21 @@
   </div>
 
   <p>If <var title="">node</var> is a <code class=external data-anolis-spec=domcore><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#text>Text</a></code> node and <var title="">offset</var> is not zero,
-  call <code class=external data-anolis-spec=domrange title=dom-Selection-collapse><a href=http://html5.org/specs/dom-range.html#dom-selection-collapse>collapse(<var title="">node</var>, <var title="">offset</var>)</a></code> on the <code class=external data-anolis-spec=domrange><a href=http://html5.org/specs/dom-range.html#selection>Selection</a></code>.
-  Then <a href=#delete-the-contents>delete the contents</a> of the <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range title=concept-range>range</a> with <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</a>
-  (<var title="">node</var>, <var title="">offset</var> &minus; 1) and <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-end title=concept-range-end>end</a>
-  (<var title="">node</var>, <var title="">offset</var>) and abort these steps.
+  or if <var title="">node</var> is a <a href=#block-node>block node</a> that has a <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-child title=concept-tree-child>child</a> with
+  <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-indexof title=concept-indexof>index</a> <var title="">offset</var> &minus; 1 and that <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-child title=concept-tree-child>child</a> is a <code class=external data-anolis-spec=html title="the br element"><a href=http://www.whatwg.org/html/#the-br-element>br</a></code> or
+  <code class=external data-anolis-spec=html title="the hr element"><a href=http://www.whatwg.org/html/#the-hr-element>hr</a></code> or <code class=external data-anolis-spec=html title="the img element"><a href=http://www.whatwg.org/html/#the-img-element>img</a></code>:
+
+  <ol>
+    <li>Call <code class=external data-anolis-spec=domrange title=dom-Selection-collapse><a href=http://html5.org/specs/dom-range.html#dom-selection-collapse>collapse(<var title="">node</var>, <var title="">offset</var>)</a></code> on the
+    <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#context-object>context object</a>'s <code class=external data-anolis-spec=domrange><a href=http://html5.org/specs/dom-range.html#selection>Selection</a></code>.
+
+    <li>Call <code class=external data-anolis-spec=domrange title=dom-Selection-extend><a href=http://html5.org/specs/dom-range.html#dom-selection-extend>extend(<var title="">node</var>, <var title="">offset</var> &minus; 1)</a></code> on the
+    <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#context-object>context object</a>'s <code class=external data-anolis-spec=domrange><a href=http://html5.org/specs/dom-range.html#selection>Selection</a></code>.
+
+    <li><a href=#delete-the-selection>Delete the selection</a>.
+
+    <li>Abort these steps.
+  </ol>
 
   <li>
   <p class=comments>At the time of this writing, this should be impossible.
@@ -6702,13 +6746,6 @@
 
   <p>If <var title="">node</var> is an <a href=#inline-node>inline node</a>, abort these steps.
 
-  <li>If <var title="">node</var> has a <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-child title=concept-tree-child>child</a> with <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-indexof title=concept-indexof>index</a> <var title="">offset</var>
-  &minus; 1 and that <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-child title=concept-tree-child>child</a> is a <code class=external data-anolis-spec=html title="the br element"><a href=http://www.whatwg.org/html/#the-br-element>br</a></code> or <code class=external data-anolis-spec=html title="the hr element"><a href=http://www.whatwg.org/html/#the-hr-element>hr</a></code> or <code class=external data-anolis-spec=html title="the img element"><a href=http://www.whatwg.org/html/#the-img-element>img</a></code>, call
-  <code class=external data-anolis-spec=domrange title=dom-Selection-collapse><a href=http://html5.org/specs/dom-range.html#dom-selection-collapse>collapse(<var title="">node</var>, <var title="">offset</var>)</a></code> on the <code class=external data-anolis-spec=domrange><a href=http://html5.org/specs/dom-range.html#selection>Selection</a></code>.
-  Then <a href=#delete-the-contents>delete the contents</a> of the <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range title=concept-range>range</a> with <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</a>
-  (<var title="">node</var>, <var title="">offset</var> &minus; 1) and <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-end title=concept-range-end>end</a>
-  (<var title="">node</var>, <var title="">offset</var>) and abort these steps.
-
   <li>
   <p class=comments> If we're at the beginning of a list, we want to outdent
   the first list item.  This doesn't actually match anyone or anything.  Word
@@ -6853,13 +6890,17 @@
   an <a href=#inline-node>inline node</a>:
 
   <ol>
+    <li>Call <code class=external data-anolis-spec=domrange title=dom-Selection-collapse><a href=http://html5.org/specs/dom-range.html#dom-selection-collapse>collapse(<var title="">start node</var>, <var title="">start offset</var>
+    &minus; 1)</a></code> on the <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#context-object>context object</a>'s <code class=external data-anolis-spec=domrange><a href=http://html5.org/specs/dom-range.html#selection>Selection</a></code>.
+
+    <li>Call <code class=external data-anolis-spec=domrange title=dom-Selection-extend><a href=http://html5.org/specs/dom-range.html#dom-selection-extend>extend(<var title="">start node</var>, <var title="">start offset</var>)</a></code> on the
+    <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#context-object>context object</a>'s <code class=external data-anolis-spec=domrange><a href=http://html5.org/specs/dom-range.html#selection>Selection</a></code>.
+
+    <li><a href=#delete-the-selection>Delete the selection</a>.
+
     <li>Call <code class=external data-anolis-spec=domrange title=dom-Selection-collapse><a href=http://html5.org/specs/dom-range.html#dom-selection-collapse>collapse(<var title="">node</var>, <var title="">offset</var>)</a></code> on the
     <code class=external data-anolis-spec=domrange><a href=http://html5.org/specs/dom-range.html#selection>Selection</a></code>.
 
-    <li><a href=#delete-the-contents>Delete the contents</a> of the <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range title=concept-range>range</a> with <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</a>
-    (<var title="">start node</var>, <var title="">start offset</var> &minus; 1) and <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-end title=concept-range-end>end</a>
-    (<var title="">start node</var>, <var title="">start offset</var>).
-
     <li>Abort these steps.
   </ol>
 
@@ -6908,22 +6949,49 @@
   <li>
   <p class=comments>When merging adjacent list items, make sure we only merge
   the items themselves, not any block children.  We want
-  &lt;li&gt;&lt;p&gt;foo&lt;li&gt;&lt;p&gt;bar to become &lt;li&gt;&lt;p&gt;foo&lt;p&gt;bar, not
-  &lt;li&gt;&lt;p&gt;foo&lt;br&gt;bar or &lt;li&gt;&lt;p&gt;foobar.
-
-  <p>If the <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-child title=concept-tree-child>child</a> of <var title="">start node</var> with <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-indexof title=concept-indexof>index</a> <var title="">start
-  offset</var> is an <code class=external data-anolis-spec=html title="the li element"><a href=http://www.whatwg.org/html/#the-li-element>li</a></code> or <code class=external data-anolis-spec=html title="the dt element"><a href=http://www.whatwg.org/html/#the-dt-element>dt</a></code> or <code class=external data-anolis-spec=html title="the dd element"><a href=http://www.whatwg.org/html/#the-dd-element>dd</a></code>, and its <code class=external data-anolis-spec=domcore title=dom-Node-previousSibling><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-node-previoussibling>previousSibling</a></code> is
-  also an <code class=external data-anolis-spec=html title="the li element"><a href=http://www.whatwg.org/html/#the-li-element>li</a></code> or <code class=external data-anolis-spec=html title="the dt element"><a href=http://www.whatwg.org/html/#the-dt-element>dt</a></code> or <code class=external data-anolis-spec=html title="the dd element"><a href=http://www.whatwg.org/html/#the-dd-element>dd</a></code>, set <var title="">start node</var> to its
-  <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-child title=concept-tree-child>child</a> with <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-indexof title=concept-indexof>index</a> <var title="">start offset</var> &minus; 1, then set
-  <var title="">start offset</var> to <var title="">start node</var>'s <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-node-length title=concept-node-length>length</a>, then set
-  <var title="">node</var> to <var title="">start node</var>'s <code class=external data-anolis-spec=domcore title=dom-Node-nextSibling><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-node-nextsibling>nextSibling</a></code>, then set
-  <var title="">offset</var> to 0.
+  <code title="">&lt;li&gt;&lt;p&gt;foo&lt;li&gt;&lt;p&gt;[]bar</code> to become <code title="">&lt;li&gt;&lt;p&gt;foo&lt;p&gt;[]bar</code>, not
+  <code title="">&lt;li&gt;&lt;p&gt;foo&lt;br&gt;[]bar</code> or <code title="">&lt;li&gt;&lt;p&gt;foo[]bar</code>.  To do the
+  deletion, we need to wipe out the current selection, so we save it as a
+  range.  Saving it as a node/offset pair isn't enough, because it might be
+  invalid after we do the deletion.  A range will update according to the range
+  mutation rules.
+
+  <p>If <var title="">start node</var>'s <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-child title=concept-tree-child>child</a> with <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-indexof title=concept-indexof>index</a> <var title="">start
+  offset</var> is an <code class=external data-anolis-spec=html title="the li element"><a href=http://www.whatwg.org/html/#the-li-element>li</a></code> or <code class=external data-anolis-spec=html title="the dt element"><a href=http://www.whatwg.org/html/#the-dt-element>dt</a></code> or <code class=external data-anolis-spec=html title="the dd element"><a href=http://www.whatwg.org/html/#the-dd-element>dd</a></code>, and that <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-child title=concept-tree-child>child</a>'s
+  <code class=external data-anolis-spec=domcore title=dom-Node-previousSibling><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-node-previoussibling>previousSibling</a></code> is also an <code class=external data-anolis-spec=html title="the li element"><a href=http://www.whatwg.org/html/#the-li-element>li</a></code> or <code class=external data-anolis-spec=html title="the dt element"><a href=http://www.whatwg.org/html/#the-dt-element>dt</a></code> or <code class=external data-anolis-spec=html title="the dd element"><a href=http://www.whatwg.org/html/#the-dd-element>dd</a></code>:
+
+  <ol>
+    <li>Call <code class=external data-anolis-spec=domrange title=dom-Range-cloneRange><a href=http://html5.org/specs/dom-range.html#dom-range-clonerange>cloneRange()</a></code> on the <a href=#active-range>active range</a>, and let
+    <var title="">original range</var> be the result.
+
+    <li>Set <var title="">start node</var> to its <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-child title=concept-tree-child>child</a> with <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-indexof title=concept-indexof>index</a> <var title="">start
+    offset</var> &minus; 1.
+
+    <li>Set <var title="">start offset</var> to <var title="">start node</var>'s <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-node-length title=concept-node-length>length</a>.
+
+    <li>Set <var title="">node</var> to <var title="">start node</var>'s <code class=external data-anolis-spec=domcore title=dom-Node-nextSibling><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-node-nextsibling>nextSibling</a></code>.
+
+    <li>Call <code class=external data-anolis-spec=domrange title=dom-Selection-collapse><a href=http://html5.org/specs/dom-range.html#dom-selection-collapse>collapse(<var title="">start node</var>, <var title="">start offset</var>)</a></code> on
+    the <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#context-object>context object</a>'s <code class=external data-anolis-spec=domrange><a href=http://html5.org/specs/dom-range.html#selection>Selection</a></code>.
+
+    <li>Call <code class=external data-anolis-spec=domrange title=dom-Selection-extend><a href=http://html5.org/specs/dom-range.html#dom-selection-extend>extend(<var title="">node</var>, 0)</a></code> on the <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#context-object>context object</a>'s
+    <code class=external data-anolis-spec=domrange><a href=http://html5.org/specs/dom-range.html#selection>Selection</a></code>.
+
+    <li><a href=#delete-the-selection>Delete the selection</a>.
+
+    <li>Call <code class=external data-anolis-spec=domrange title=dom-Selection-removeAllRanges><a href=http://html5.org/specs/dom-range.html#dom-selection-removeallranges>removeAllRanges()</a></code> on the <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#context-object>context object</a>'s <code class=external data-anolis-spec=domrange><a href=http://html5.org/specs/dom-range.html#selection>Selection</a></code>.
+
+    <li>Call <code class=external data-anolis-spec=domrange title=dom-Selection-addRange><a href=http://html5.org/specs/dom-range.html#dom-selection-addrange>addRange(<var title="">original range</var>)</a></code> on the <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#context-object>context object</a>'s
+    <code class=external data-anolis-spec=domrange><a href=http://html5.org/specs/dom-range.html#selection>Selection</a></code>.
+
+    <li>Abort these steps.
+  </ol>
 
   <li>
   <p class=comments>General block-merging case.
 
-  <p>Otherwise, while <var title="">start node</var> has a <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-child title=concept-tree-child>child</a> with <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-indexof title=concept-indexof>index</a>
-  <var title="">start offset</var> minus one:
+  <p>While <var title="">start node</var> has a <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-child title=concept-tree-child>child</a> with <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-indexof title=concept-indexof>index</a> <var title="">start
+  offset</var> minus one:
 
   <ol>
     <li>If <var title="">start node</var>'s <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-child title=concept-tree-child>child</a> with <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-indexof title=concept-indexof>index</a> <var title="">start
@@ -6936,9 +7004,13 @@
     <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-node-length title=concept-node-length>length</a> of <var title="">start node</var>.
   </ol>
 
-  <li><a href=#delete-the-contents>Delete the contents</a> of the <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range title=concept-range>range</a> with <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</a>
-  (<var title="">start node</var>, <var title="">start offset</var>) and <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-end title=concept-range-end>end</a>
-  (<var title="">node</var>, <var title="">offset</var>).
+  <li>Call <code class=external data-anolis-spec=domrange title=dom-Selection-collapse><a href=http://html5.org/specs/dom-range.html#dom-selection-collapse>collapse(<var title="">start node</var>, <var title="">start offset</var>)</a></code> on
+  the <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#context-object>context object</a>'s <code class=external data-anolis-spec=domrange><a href=http://html5.org/specs/dom-range.html#selection>Selection</a></code>.
+
+  <li>Call <code class=external data-anolis-spec=domrange title=dom-Selection-extend><a href=http://html5.org/specs/dom-range.html#dom-selection-extend>extend(<var title="">node</var>, <var title="">offset</var>)</a></code> on the
+  <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#context-object>context object</a>'s <code class=external data-anolis-spec=domrange><a href=http://html5.org/specs/dom-range.html#selection>Selection</a></code>.
+
+  <li><a href=#delete-the-selection>Delete the selection</a>, with <var title="">direction</var> "backward".
 </ol>
 
 
@@ -7290,8 +7362,8 @@
 <p><a href=#action>Action</a>:
 
 <ol>
-  <li>If the <a href=#active-range>active range</a> is not <code class=external data-anolis-spec=domrange title=dom-Range-collapsed><a href=http://html5.org/specs/dom-range.html#dom-range-collapsed>collapsed</a></code>, <a href=#delete-the-contents>delete the contents</a>
-  of the <a href=#active-range>active range</a> and abort these steps.
+  <li>If the <a href=#active-range>active range</a> is not <code class=external data-anolis-spec=domrange title=dom-Range-collapsed><a href=http://html5.org/specs/dom-range.html#dom-range-collapsed>collapsed</a></code>, <a href=#delete-the-selection>delete the selection</a>
+  and abort these steps.
 
   <li><a href=#canonicalize-whitespace>Canonicalize whitespace</a> at (<a href=#active-range>active range</a>'s
   <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-node title=concept-boundary-point-node>node</a>, <a href=#active-range>active range</a>'s <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-offset title=concept-boundary-point-offset>offset</a>).
@@ -7312,10 +7384,6 @@
     <a href=#invisible>invisible</a> <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-node title=concept-node>node</a>, remove that <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-child title=concept-tree-child>child</a> from
     <var title="">node</var>.
 
-    <li>Otherwise, if <var title="">node</var> has a <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-child title=concept-tree-child>child</a> with <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-indexof title=concept-indexof>index</a>
-    <var title="">offset</var> and that <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-child title=concept-tree-child>child</a> is a <a href=#collapsed-block-prop>collapsed block
-    prop</a>, add one to <var title="">offset</var>.
-
     <li>Otherwise, if <var title="">offset</var> is the <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-node-length title=concept-node-length>length</a> of
     <var title="">node</var> and <var title="">node</var> is an <a href=#inline-node>inline node</a>, or if
     <var title="">node</var> is <a href=#invisible>invisible</a>, set <var title="">offset</var> to one
@@ -7327,9 +7395,9 @@
     delete.
 
     <p>Otherwise, if <var title="">node</var> has a <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-child title=concept-tree-child>child</a> with <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-indexof title=concept-indexof>index</a>
-    <var title="">offset</var> and that <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-child title=concept-tree-child>child</a> is not a <a href=#block-node>block node</a> or a
-    <code class=external data-anolis-spec=html title="the br element"><a href=http://www.whatwg.org/html/#the-br-element>br</a></code> or an <code class=external data-anolis-spec=html title="the img element"><a href=http://www.whatwg.org/html/#the-img-element>img</a></code>, set <var title="">node</var> to that <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-child title=concept-tree-child>child</a>, then set
-    <var title="">offset</var> to zero.
+    <var title="">offset</var> and that <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-child title=concept-tree-child>child</a> is neither a <a href=#block-node>block node</a>
+    nor a <code class=external data-anolis-spec=html title="the br element"><a href=http://www.whatwg.org/html/#the-br-element>br</a></code> nor an <code class=external data-anolis-spec=html title="the img element"><a href=http://www.whatwg.org/html/#the-img-element>img</a></code> nor a <a href=#collapsed-block-prop>collapsed block prop</a>, set
+    <var title="">node</var> to that <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-child title=concept-tree-child>child</a>, then set <var title="">offset</var> to zero.
 
     <li>Otherwise, break from this loop.
   </ol>
@@ -7338,9 +7406,6 @@
   <var title="">node</var>'s <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-node-length title=concept-node-length>length</a>:
 
   <ol>
-    <li>Call <code class=external data-anolis-spec=domrange title=dom-Selection-collapse><a href=http://html5.org/specs/dom-range.html#dom-selection-collapse>collapse(<var title="">node</var>, <var title="">offset</var>)</a></code> on the
-    <code class=external data-anolis-spec=domrange><a href=http://html5.org/specs/dom-range.html#selection>Selection</a></code>.
-
     <li>Let <var title="">end offset</var> be <var title="">offset</var> plus one.
 
     <li>
@@ -7371,9 +7436,13 @@
     general category M when interpreted as a Unicode code point, add one to
     <var title="">end offset</var>.
 
-    <li><a href=#delete-the-contents>Delete the contents</a> of the <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range title=concept-range>range</a> with <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</a>
-    (<var title="">node</var>, <var title="">offset</var>) and <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-end title=concept-range-end>end</a> (<var title="">node</var>,
-    <var title="">end offset</var>).
+    <li>Call <code class=external data-anolis-spec=domrange title=dom-Selection-collapse><a href=http://html5.org/specs/dom-range.html#dom-selection-collapse>collapse(<var title="">node</var>, <var title="">offset</var>)</a></code> on the
+    <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#context-object>context object</a>'s <code class=external data-anolis-spec=domrange><a href=http://html5.org/specs/dom-range.html#selection>Selection</a></code>.
+
+    <li>Call <code class=external data-anolis-spec=domrange title=dom-Selection-extend><a href=http://html5.org/specs/dom-range.html#dom-selection-extend>extend(<var title="">node</var>, <var title="">end offset</var>)</a></code> on the
+    <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#context-object>context object</a>'s <code class=external data-anolis-spec=domrange><a href=http://html5.org/specs/dom-range.html#selection>Selection</a></code>.
+
+    <li><a href=#delete-the-selection>Delete the selection</a>.
 
     <li>Abort these steps.
   </ol>
@@ -7381,11 +7450,20 @@
   <li>If <var title="">node</var> is an <a href=#inline-node>inline node</a>, abort these steps.
 
   <li>If <var title="">node</var> has a <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-child title=concept-tree-child>child</a> with <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-indexof title=concept-indexof>index</a> <var title="">offset</var> and
-  that <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-child title=concept-tree-child>child</a> is a <code class=external data-anolis-spec=html title="the br element"><a href=http://www.whatwg.org/html/#the-br-element>br</a></code> or <code class=external data-anolis-spec=html title="the hr element"><a href=http://www.whatwg.org/html/#the-hr-element>hr</a></code> or <code class=external data-anolis-spec=html title="the img element"><a href=http://www.whatwg.org/html/#the-img-element>img</a></code>, call
-  <code class=external data-anolis-spec=domrange title=dom-Selection-collapse><a href=http://html5.org/specs/dom-range.html#dom-selection-collapse>collapse(<var title="">node</var>, <var title="">offset</var>)</a></code> on the <code class=external data-anolis-spec=domrange><a href=http://html5.org/specs/dom-range.html#selection>Selection</a></code>.
-  Then <a href=#delete-the-contents>delete the contents</a> of the <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range title=concept-range>range</a> with <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</a>
-  (<var title="">node</var>, <var title="">offset</var>) and <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-end title=concept-range-end>end</a> (<var title="">node</var>,
-  <var title="">offset</var> + 1) and abort these steps.
+  that <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-child title=concept-tree-child>child</a> is a <code class=external data-anolis-spec=html title="the br element"><a href=http://www.whatwg.org/html/#the-br-element>br</a></code> or <code class=external data-anolis-spec=html title="the hr element"><a href=http://www.whatwg.org/html/#the-hr-element>hr</a></code> or <code class=external data-anolis-spec=html title="the img element"><a href=http://www.whatwg.org/html/#the-img-element>img</a></code>, but is not a
+  <a href=#collapsed-block-prop>collapsed block prop</a>:
+
+  <ol>
+    <li>Call <code class=external data-anolis-spec=domrange title=dom-Selection-collapse><a href=http://html5.org/specs/dom-range.html#dom-selection-collapse>collapse(<var title="">node</var>, <var title="">offset</var>)</a></code> on the
+    <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#context-object>context object</a>'s <code class=external data-anolis-spec=domrange><a href=http://html5.org/specs/dom-range.html#selection>Selection</a></code>.
+
+    <li>Call <code class=external data-anolis-spec=domrange title=dom-Selection-extend><a href=http://html5.org/specs/dom-range.html#dom-selection-extend>extend(<var title="">node</var>, <var title="">offset</var> + 1)</a></code> on the
+    <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#context-object>context object</a>'s <code class=external data-anolis-spec=domrange><a href=http://html5.org/specs/dom-range.html#selection>Selection</a></code>.
+
+    <li><a href=#delete-the-selection>Delete the selection</a>.
+
+    <li>Abort these steps.
+  </ol>
 
   <li>
   <p class=comments>No special list-item behavior for forwardDelete here,
@@ -7394,6 +7472,10 @@
   <p>Let <var title="">end node</var> equal <var title="">node</var> and let <var title="">end
   offset</var> equal <var title="">offset</var>.
 
+  <li>If <var title="">end node</var> has a <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-child title=concept-tree-child>child</a> with <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-indexof title=concept-indexof>index</a> <var title="">end
+  offset</var>, and that <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-child title=concept-tree-child>child</a> is a <a href=#collapsed-block-prop>collapsed block prop</a>, add
+  one to <var title="">end offset</var>.
+
   <li>Repeat the following steps:
 
   <ol>
@@ -7401,7 +7483,7 @@
     <var title="">end offset</var> to one plus the <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-indexof title=concept-indexof>index</a> of <var title="">end node</var> and
     then set <var title="">end node</var> to its <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-parent title=concept-tree-parent>parent</a>.
 
-    <li>Otherwise, if <var title="">end node</var> has a an <a href=#editable>editable</a>
+    <li>Otherwise, if <var title="">end node</var> has an <a href=#editable>editable</a>
     <a href=#invisible>invisible</a> <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-child title=concept-tree-child>child</a> with <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-indexof title=concept-indexof>index</a> <var title="">end offset</var>,
     remove it from <var title="">end node</var>.
 
@@ -7437,13 +7519,17 @@
   <code class=external data-anolis-spec=html title="the hr element"><a href=http://www.whatwg.org/html/#the-hr-element>hr</a></code> or <code class=external data-anolis-spec=html title="the br element"><a href=http://www.whatwg.org/html/#the-br-element>br</a></code>:
 
   <ol>
+    <li>Call <code class=external data-anolis-spec=domrange title=dom-Selection-collapse><a href=http://html5.org/specs/dom-range.html#dom-selection-collapse>collapse(<var title="">end node</var>, <var title="">end offset</var>)</a></code> on the
+    <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#context-object>context object</a>'s <code class=external data-anolis-spec=domrange><a href=http://html5.org/specs/dom-range.html#selection>Selection</a></code>.
+
+    <li>Call <code class=external data-anolis-spec=domrange title=dom-Selection-extend><a href=http://html5.org/specs/dom-range.html#dom-selection-extend>extend(<var title="">end node</var>, <var title="">end offset</var> + 1)</a></code> on the
+    <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#context-object>context object</a>'s <code class=external data-anolis-spec=domrange><a href=http://html5.org/specs/dom-range.html#selection>Selection</a></code>.
+
+    <li><a href=#delete-the-selection>Delete the selection</a>.
+
     <li>Call <code class=external data-anolis-spec=domrange title=dom-Selection-collapse><a href=http://html5.org/specs/dom-range.html#dom-selection-collapse>collapse(<var title="">node</var>, <var title="">offset</var>)</a></code> on the
     <code class=external data-anolis-spec=domrange><a href=http://html5.org/specs/dom-range.html#selection>Selection</a></code>.
 
-    <li><a href=#delete-the-contents>Delete the contents</a> of the <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range title=concept-range>range</a> with <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-end title=concept-range-end>end</a>
-    (<var title="">end node</var>, <var title="">end offset</var>) and <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-end title=concept-range-end>end</a> (<var title="">end
-    node</var>, <var title="">end offset</var> + 1).
-
     <li>Abort these steps.
   </ol>
 
@@ -7463,9 +7549,13 @@
     <var title="">end offset</var> and set <var title="">end offset</var> to zero.
   </ol>
 
-  <li><a href=#delete-the-contents>Delete the contents</a> of the <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range title=concept-range>range</a> with <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</a>
-  (<var title="">node</var>, <var title="">offset</var>) and <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-end title=concept-range-end>end</a> (<var title="">end node</var>,
-  <var title="">end offset</var>).
+  <li>Call <code class=external data-anolis-spec=domrange title=dom-Selection-collapse><a href=http://html5.org/specs/dom-range.html#dom-selection-collapse>collapse(<var title="">node</var>, <var title="">offset</var>)</a></code> on the
+  <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#context-object>context object</a>'s <code class=external data-anolis-spec=domrange><a href=http://html5.org/specs/dom-range.html#selection>Selection</a></code>.
+
+  <li>Call <code class=external data-anolis-spec=domrange title=dom-Selection-extend><a href=http://html5.org/specs/dom-range.html#dom-selection-extend>extend(<var title="">end node</var>, <var title="">end offset</var>)</a></code> on the
+  <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#context-object>context object</a>'s <code class=external data-anolis-spec=domrange><a href=http://html5.org/specs/dom-range.html#selection>Selection</a></code>.
+
+  <li><a href=#delete-the-selection>Delete the selection</a>.
 </ol>
 
 
@@ -7590,19 +7680,26 @@
 <p><a href=#action>Action</a>:
 
 <ol>
-  <li>Let <var title="">range</var> be the <a href=#active-range>active range</a>.
-
-  <li>While <var title="">range</var>'s <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-offset title=concept-boundary-point-offset>offset</a> is 0 and its <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-node title=concept-boundary-point-node>node</a>'s
-  <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-parent title=concept-tree-parent>parent</a> is not null, set <var title="">range</var>'s <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</a> to (<a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-parent title=concept-tree-parent>parent</a>
-  of <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-node title=concept-boundary-point-node>node</a>, <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-indexof title=concept-indexof>index</a> of <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-node title=concept-boundary-point-node>node</a>).
-
-  <li>While <var title="">range</var>'s <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-end title=concept-range-end>end</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-offset title=concept-boundary-point-offset>offset</a> is the <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-node-length title=concept-node-length>length</a> of its
-  <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-end title=concept-range-end>end</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-node title=concept-boundary-point-node>node</a>, and its <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-end title=concept-range-end>end</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-node title=concept-boundary-point-node>node</a>'s <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-parent title=concept-tree-parent>parent</a> is not null, set
-  <var title="">range</var>'s <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-end title=concept-range-end>end</a> to (<a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-parent title=concept-tree-parent>parent</a> of <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-end title=concept-range-end>end</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-node title=concept-boundary-point-node>node</a>, 1 + <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-indexof title=concept-indexof>index</a>
-  of <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-node title=concept-boundary-point-node>node</a>).
-
-  <li><a href=#delete-the-contents>Delete the contents</a> of <var title="">range</var>, with <var title="">block
-  merging</var> false.
+  <li>Let <var title="">start node</var>, <var title="">start offset</var>, <var title="">end node</var>,
+  and <var title="">end offset</var> be the <a href=#active-range>active range</a>'s <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</a>
+  and <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-end title=concept-range-end>end</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-node title=concept-boundary-point-node>nodes</a> and <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-offset title=concept-boundary-point-offset>offsets</a>.
+
+  <li>While <var title="">start offset</var> is 0 and <var title="">start node</var>'s
+  <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-parent title=concept-tree-parent>parent</a> is not null, set <var title="">start offset</var> to <var title="">start
+  node</var>'s <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-indexof title=concept-indexof>index</a>, then set <var title="">start node</var> to its <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-parent title=concept-tree-parent>parent</a>.
+
+  <li>While <var title="">end offset</var> is <var title="">end node</var>'s <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-node-length title=concept-node-length>length</a>, and
+  <var title="">end node</var>'s <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-parent title=concept-tree-parent>parent</a> is not null, set <var title="">end offset</var> to
+  one plus <var title="">end node</var>'s <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-indexof title=concept-indexof>index</a>, then set <var title="">end node</var> to its
+  <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-parent title=concept-tree-parent>parent</a>.
+
+  <li>Call <code class=external data-anolis-spec=domrange title=dom-Selection-collapse><a href=http://html5.org/specs/dom-range.html#dom-selection-collapse>collapse(<var title="">start node</var>, <var title="">start offset</var>)</a></code> on
+  the <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#context-object>context object</a>'s <code class=external data-anolis-spec=domrange><a href=http://html5.org/specs/dom-range.html#selection>Selection</a></code>.
+
+  <li>Call <code class=external data-anolis-spec=domrange title=dom-Selection-extend><a href=http://html5.org/specs/dom-range.html#dom-selection-extend>extend(<var title="">end node</var>, <var title="">end offset</var>)</a></code> on the
+  <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#context-object>context object</a>'s <code class=external data-anolis-spec=domrange><a href=http://html5.org/specs/dom-range.html#selection>Selection</a></code>.
+
+  <li><a href=#delete-the-selection>Delete the selection</a>, with <var title="">block merging</var> false.
 
   <li>If the <a href=#active-range>active range</a>'s <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-node title=concept-boundary-point-node>node</a> is neither
   <a href=#editable>editable</a> nor an <a href=#editing-host>editing host</a>, abort these steps.
@@ -7612,19 +7709,22 @@
   text node, because that will leave an empty text node.
 
   <p>If the <a href=#active-range>active range</a>'s <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-node title=concept-boundary-point-node>node</a> is a <code class=external data-anolis-spec=domcore><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#text>Text</a></code> node and
-  its <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-offset title=concept-boundary-point-offset>offset</a> is zero, set the <a href=#active-range>active range</a>'s
-  <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</a> and <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-end title=concept-range-end>end</a> to (<a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-parent title=concept-tree-parent>parent</a> of <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-node title=concept-boundary-point-node>node</a>, <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-indexof title=concept-indexof>index</a> of
-  <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-node title=concept-boundary-point-node>node</a>).
+  its <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-offset title=concept-boundary-point-offset>offset</a> is zero, call <code class=external data-anolis-spec=domrange title=dom-Selection-collapse><a href=http://html5.org/specs/dom-range.html#dom-selection-collapse>collapse()</a></code> on the <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#context-object>context object</a>'s
+  <code class=external data-anolis-spec=domrange><a href=http://html5.org/specs/dom-range.html#selection>Selection</a></code>, with first argument the <a href=#active-range>active range</a>'s
+  <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-node title=concept-boundary-point-node>node</a>'s <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-parent title=concept-tree-parent>parent</a> and second argument the <a href=#active-range>active
+  range</a>'s <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-node title=concept-boundary-point-node>node</a>'s <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-indexof title=concept-indexof>index</a>.
 
   <li>If the <a href=#active-range>active range</a>'s <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-node title=concept-boundary-point-node>node</a> is a <code class=external data-anolis-spec=domcore><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#text>Text</a></code> node and
-  its <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-offset title=concept-boundary-point-offset>offset</a> is the <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-node-length title=concept-node-length>length</a> of its <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-node title=concept-boundary-point-node>node</a>, set the
-  <a href=#active-range>active range</a>'s <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</a> and <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-end title=concept-range-end>end</a> to (<a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-parent title=concept-tree-parent>parent</a> of
-  <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-node title=concept-boundary-point-node>node</a>, 1 + <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-indexof title=concept-indexof>index</a> of <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-node title=concept-boundary-point-node>node</a>).
+  its <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-offset title=concept-boundary-point-offset>offset</a> is the <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-node-length title=concept-node-length>length</a> of its <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-node title=concept-boundary-point-node>node</a>, call
+  <code class=external data-anolis-spec=domrange title=dom-Selection-collapse><a href=http://html5.org/specs/dom-range.html#dom-selection-collapse>collapse()</a></code> on the <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#context-object>context object</a>'s <code class=external data-anolis-spec=domrange><a href=http://html5.org/specs/dom-range.html#selection>Selection</a></code>, with first
+  argument the <a href=#active-range>active range</a>'s <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-node title=concept-boundary-point-node>node</a>'s <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-parent title=concept-tree-parent>parent</a>, and the
+  second argument one plus the <a href=#active-range>active range</a>'s <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-node title=concept-boundary-point-node>node</a>'s
+  <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-indexof title=concept-indexof>index</a>.
 
   <li>Let <var title="">hr</var> be the result of calling <code class=external data-anolis-spec=domcore title=dom-Document-createElement><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-document-createelement>createElement("hr")</a></code> on the
   <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#context-object>context object</a>.
 
-  <li>Run <code class=external data-anolis-spec=domrange title=dom-Range-insertNode><a href=http://html5.org/specs/dom-range.html#dom-range-insertnode>insertNode(<var title="">hr</var>)</a></code> on <var title="">range</var>.
+  <li>Run <code class=external data-anolis-spec=domrange title=dom-Range-insertNode><a href=http://html5.org/specs/dom-range.html#dom-range-insertnode>insertNode(<var title="">hr</var>)</a></code> on the <a href=#active-range>active range</a>.
 
   <li>
   <p class=comments>IE9 and Chrome 13 dev seem to never break up any ancestors,
@@ -7637,12 +7737,9 @@
 
   <p><a href=#fix-disallowed-ancestors>Fix disallowed ancestors</a> of <var title="">hr</var>.
 
-  <li>Let <var title="">selection</var> be the result of running <code class=external data-anolis-spec=domrange title=dom-Document-getSelection><a href=http://html5.org/specs/dom-range.html#dom-document-getselection>getSelection()</a></code> on the
-  <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#context-object>context object</a>.
-
-  <li>Run <code class=external data-anolis-spec=domrange title=dom-Selection-collapse><a href=http://html5.org/specs/dom-range.html#dom-selection-collapse>collapse()</a></code> on <var title="">selection</var>, with first argument equal
-  to the <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-parent title=concept-tree-parent>parent</a> of <var title="">hr</var> and the second argument equal to one plus
-  the <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-indexof title=concept-indexof>index</a> of <var title="">hr</var>.
+  <li>Run <code class=external data-anolis-spec=domrange title=dom-Selection-collapse><a href=http://html5.org/specs/dom-range.html#dom-selection-collapse>collapse()</a></code> on the <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#context-object>context object</a>'s <code class=external data-anolis-spec=domrange><a href=http://html5.org/specs/dom-range.html#selection>Selection</a></code>, with first
+  argument <var title="">hr</var>'s <a class=external data-anolis-spec=domcore href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-tree-parent title=concept-tree-parent>parent</a> and the second argument equal to one plus
+  <var title="">hr</var>'s <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-indexof title=concept-indexof>index</a>.
 </ol>
 
 
@@ -7697,7 +7794,7 @@
   true.
   </div>
 
-  <p><a href=#delete-the-contents>Delete the contents</a> of the <a href=#active-range>active range</a>.
+  <p><a href=#delete-the-selection>Delete the selection</a>.
 
   <li>If the <a href=#active-range>active range</a>'s <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-node title=concept-boundary-point-node>node</a> is neither
   <a href=#editable>editable</a> nor an <a href=#editing-host>editing host</a>, abort these steps.
@@ -7800,8 +7897,6 @@
   <p>If <var title="">value</var> is the empty string, abort these steps and do
   nothing.
 
-  <li>Let <var title="">range</var> be the <a href=#active-range>active range</a>.
-
   <li>
   <p class=comments>Firefox 7.0a2 seems to strip the wrapper or not depending
   on the exact positioning of the selection: &lt;b&gt;{foo}&lt;/b&gt; yes,
@@ -7811,8 +7906,9 @@
   the board because they might be meaningful: e.g., a background-color when the
   image is small or not fully opaque.
 
-  <p><a href=#delete-the-contents>Delete the contents</a> of <var title="">range</var>, with <var title="">strip
-  wrappers</var> false.
+  <p><a href=#delete-the-selection>Delete the selection</a>, with <var title="">strip wrappers</var> false.
+
+  <li>Let <var title="">range</var> be the <a href=#active-range>active range</a>.
 
   <li>If the <a href=#active-range>active range</a>'s <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-node title=concept-boundary-point-node>node</a> is neither
   <a href=#editable>editable</a> nor an <a href=#editing-host>editing host</a>, abort these steps.
@@ -7882,8 +7978,7 @@
   endpoints.  Chrome 14 dev strips wrappers but recreates any styles using new
   wrappers.  Opera 11.50 strips all wrappers.
 
-  <p><a href=#delete-the-contents>Delete the contents</a> of the <a href=#active-range>active range</a>, with
-  <var title="">strip wrappers</var> false.
+  <p><a href=#delete-the-selection>Delete the selection</a>, with <var title="">strip wrappers</var> false.
 
   <li>If the <a href=#active-range>active range</a>'s <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-node title=concept-boundary-point-node>node</a> is neither
   <a href=#editable>editable</a> nor an <a href=#editing-host>editing host</a>, abort these steps.
@@ -8011,7 +8106,7 @@
 <p><a href=#action>Action</a>:
 
 <ol>
-  <li><a href=#delete-the-contents>Delete the contents</a> of the <a href=#active-range>active range</a>.
+  <li><a href=#delete-the-selection>Delete the selection</a>.
 
   <li>If the <a href=#active-range>active range</a>'s <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-node title=concept-boundary-point-node>node</a> is neither
   <a href=#editable>editable</a> nor an <a href=#editing-host>editing host</a>, abort these steps.
@@ -8416,8 +8511,7 @@
   deletion at all).  This behavior seems to closely match IE9.
   </div>
 
-  <p><a href=#delete-the-contents>Delete the contents</a> of the <a href=#active-range>active range</a>, with
-  <var title="">strip wrappers</var> false.
+  <p><a href=#delete-the-selection>Delete the selection</a>, with <var title="">strip wrappers</var> false.
 
   <li>If the <a href=#active-range>active range</a>'s <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-range-start title=concept-range-start>start</a> <a class=external data-anolis-spec=domrange href=http://html5.org/specs/dom-range.html#concept-boundary-point-node title=concept-boundary-point-node>node</a> is neither
   <a href=#editable>editable</a> nor an <a href=#editing-host>editing host</a>, abort these steps.
@@ -8815,11 +8909,11 @@
 
 <p class=comments>See comment for <a href=#the-copy-command>copy</a>.
 
-<p><a href=#action>Action</a>: The user agent must either <a href=#delete-the-contents>delete the
-contents</a> of the <a href=#active-range>active range</a> and then paste the clipboard's
-contents to the current cursor position, as though the user had requested it,
-or raise a <code class=external data-anolis-spec=domcore title=dom-DOMException-SECURITY_ERR><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-domexception-security_err>SECURITY_ERR</a></code> exception.  This specification does not define
-exactly how the clipboard is to be converted to HTML for pasting, but the <a href=http://dev.w3.org/2006/webapi/clipops/clipops.html>Clipboard API and
+<p><a href=#action>Action</a>: The user agent must either <a href=#delete-the-selection>delete the
+selection</a> and then paste the clipboard's contents to the current cursor
+position, as though the user had requested it, or raise a <code class=external data-anolis-spec=domcore title=dom-DOMException-SECURITY_ERR><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-domexception-security_err>SECURITY_ERR</a></code>
+exception.  This specification does not define exactly how the clipboard is to
+be converted to HTML for pasting, but the <a href=http://dev.w3.org/2006/webapi/clipops/clipops.html>Clipboard API and
 events</a> specification might be useful.
 
 <p>User agents should exercise caution in respecting this command,
--- a/implementation.js	Mon Aug 29 14:42:53 2011 -0600
+++ b/implementation.js	Tue Aug 30 13:52:24 2011 -0600
@@ -1185,6 +1185,9 @@
 ///// Assorted common algorithms /////
 //@{
 
+// Magic array of extra ranges whose endpoints we want to preserve.
+var extraRanges = [];
+
 function movePreservingRanges(node, newParent, newIndex) {
 	// For convenience, I allow newIndex to be -1 to mean "insert at the end".
 	if (newIndex == -1) {
@@ -1202,10 +1205,10 @@
 	var oldParent = node.parentNode;
 	var oldIndex = getNodeIndex(node);
 
-	// We only even attempt to preserve the global range object and the ranges
-	// in the selection, not every range out there (the latter is probably
-	// impossible).
-	var ranges = [globalRange];
+	// We preserve the global range object, the ranges in the selection, and
+	// any range that's in the extraRanges array.  Any other ranges won't get
+	// updated, because we have no references to them.
+	var ranges = [globalRange].concat(extraRanges);
 	for (var i = 0; i < getSelection().rangeCount; i++) {
 		ranges.push(getSelection().getRangeAt(i));
 	}
@@ -1256,8 +1259,13 @@
 	globalRange.setStart(boundaryPoints[0][0], boundaryPoints[0][1]);
 	globalRange.setEnd(boundaryPoints[1][0], boundaryPoints[1][1]);
 
+	for (var i = 0; i < extraRanges.length; i++) {
+		extraRanges[i].setStart(boundaryPoints[2*i + 2][0], boundaryPoints[2*i + 2][1]);
+		extraRanges[i].setEnd(boundaryPoints[2*i + 3][0], boundaryPoints[2*i + 3][1]);
+	}
+
 	getSelection().removeAllRanges();
-	for (var i = 1; i < ranges.length; i++) {
+	for (var i = 1 + extraRanges.length; i < ranges.length; i++) {
 		var newRange = document.createRange();
 		newRange.setStart(boundaryPoints[2*i][0], boundaryPoints[2*i][1]);
 		newRange.setEnd(boundaryPoints[2*i + 1][0], boundaryPoints[2*i + 1][1]);
@@ -1350,10 +1358,17 @@
 		ref = previousNode(ref);
 	}
 
-	// "If ref is an editable extraneous line break, remove it from its
-	// parent."
+	// "If ref is an editable extraneous line break:"
 	if (isEditable(ref)
 	&& isExtraneousLineBreak(ref)) {
+		// "While ref's parent is editable and invisible, set ref to its
+		// parent."
+		while (isEditable(ref.parentNode)
+		&& isInvisible(ref.parentNode)) {
+			ref = ref.parentNode;
+		}
+
+		// "Remove ref from its parent."
 		ref.parentNode.removeChild(ref);
 	}
 }
@@ -4341,54 +4356,31 @@
 }
 
 //@}
-///// Deleting the contents of a range /////
+///// Deleting the selection /////
 //@{
 
-function deleteContents() {
-	// We accept several different calling conventions:
-	//
-	// 1) A single argument, which is a range.
-	//
-	// 2) Two arguments, the first being a range and the second flags.
-	//
-	// 3) Four arguments, the start and end of a range.
-	//
-	// 4) Five arguments, the start and end of a range plus flags.
-	//
-	// The flags argument is a dictionary that can have up to two keys,
-	// blockMerging and stripWrappers, whose corresponding values are
-	// interpreted as boolean.  E.g., {stripWrappers: false}.
-	var range;
-	var flags = {};
-
-	if (arguments.length < 3) {
-		range = arguments[0];
-	} else {
-		range = document.createRange();
-		range.setStart(arguments[0], arguments[1]);
-		range.setEnd(arguments[2], arguments[3]);
-	}
-	if (arguments.length == 2) {
-		flags = arguments[1];
-	}
-	if (arguments.length == 5) {
-		flags = arguments[4];
-	}
-
-	var blockMerging = "blockMerging" in flags ? !!flags.blockMerging : true;
-	var stripWrappers = "stripWrappers" in flags ? !!flags.stripWrappers : true;
-
-	// "If range is null, abort these steps and do nothing."
-	if (!range) {
+// The flags argument is a dictionary that can have blockMerging,
+// stripWrappers, and/or direction as keys.
+function deleteSelection(flags) {
+	if (flags === undefined) {
+		flags = {};
+	}
+
+	var blockMerging = "blockMerging" in flags ? Boolean(flags.blockMerging) : true;
+	var stripWrappers = "stripWrappers" in flags ? Boolean(flags.stripWrappers) : true;
+	var direction = "direction" in flags ? flags.direction : "forward";
+
+	// "If the active range is null, abort these steps and do nothing."
+	if (!getActiveRange()) {
 		return;
 	}
 
-	// "Let start node, start offset, end node, and end offset be range's start
-	// and end nodes and offsets."
-	var startNode = range.startContainer;
-	var startOffset = range.startOffset;
-	var endNode = range.endContainer;
-	var endOffset = range.endOffset;
+	// "Let start node, start offset, end node, and end offset be the active
+	// range's start and end nodes and offsets."
+	var startNode = getActiveRange().startContainer;
+	var startOffset = getActiveRange().startOffset;
+	var endNode = getActiveRange().endContainer;
+	var endOffset = getActiveRange().endOffset;
 
 	// "While start node has at least one child:"
 	while (startNode.hasChildNodes()) {
@@ -4467,10 +4459,21 @@
 		endOffset = getNodeLength(referenceNode);
 	}
 
-	// "If (end node, end offset) is not after (start node, start offset), set
-	// range's end to its start and abort these steps."
+	// "If (end node, end offset) is not after (start node, start offset):"
 	if (getPosition(endNode, endOffset, startNode, startOffset) !== "after") {
-		range.setEnd(range.startContainer, range.startOffset);
+		// "If direction is "forward", call collapseToStart() on the context
+		// object's Selection."
+		if (direction == "forward") {
+			getSelection().collapseToStart();
+			getActiveRange().collapse(true);
+
+		// "Otherwise, call collapseToEnd() on the context object's Selection."
+		} else {
+			getSelection().collapseToEnd();
+			getActiveRange().collapse(false);
+		}
+
+		// "Abort these steps."
 		return;
 	}
 
@@ -4490,13 +4493,17 @@
 		endNode = endNode.parentNode;
 	}
 
-	// "Set range's start to (start node, start offset) and its end to (end
-	// node, end offset)."
-	range.setStart(startNode, startOffset);
-	range.setEnd(endNode, endOffset);
-
-	// "Let start block be the start node of range."
-	var startBlock = range.startContainer;
+	// "Call collapse(start node, start offset) on the context object's
+	// Selection."
+	getSelection().collapse(startNode, startOffset);
+	getActiveRange().setStart(startNode, startOffset);
+
+	// "Call extend(end node, end offset) on the context object's Selection."
+	getSelection().extend(endNode, endOffset);
+	getActiveRange().setEnd(endNode, endOffset);
+
+	// "Let start block be the active range's start node."
+	var startBlock = getActiveRange().startContainer;
 
 	// "While start block's parent is in the same editing host and start block
 	// is an inline node, set start block to its parent."
@@ -4514,8 +4521,8 @@
 		startBlock = null;
 	}
 
-	// "Let end block be the end node of range."
-	var endBlock = range.endContainer;
+	// "Let end block be the active range's end node."
+	var endBlock = getActiveRange().endContainer;
 
 	// "While end block's parent is in the same editing host and end block is
 	// an inline node, set end block to its parent."
@@ -4548,8 +4555,22 @@
 		// "Canonicalize whitespace at (start node, start offset)."
 		canonicalizeWhitespace(startNode, startOffset);
 
-		// "Set range's end to its start."
-		range.setEnd(range.startContainer, range.startOffset);
+		// "If direction is "forward", call collapseToStart() on the context
+		// object's Selection."
+		//
+		// Work around WebKit bug where the selection might have no ranges, by
+		// checking rangeCount.
+		if (direction == "forward") {
+			if (getSelection().rangeCount) {
+				getSelection().collapseToStart();
+			}
+			getActiveRange().collapse(true);
+
+		// "Otherwise, call collapseToEnd() on the context object's Selection."
+		} else {
+			getSelection().collapseToEnd();
+			getActiveRange().collapse(false);
+		}
 
 		// "Restore states and values from overrides."
 		restoreStatesAndValues(overrides);
@@ -4568,10 +4589,10 @@
 
 	// "Let node list be a list of nodes, initially empty."
 	//
-	// "For each node contained in range, append node to node list if the last
-	// member of node list (if any) is not an ancestor of node; node is
-	// editable; and node is not a thead, tbody, tfoot, tr, th, or td."
-	var nodeList = getContainedNodes(range,
+	// "For each node contained in the active range, append node to node list
+	// if the last member of node list (if any) is not an ancestor of node;
+	// node is editable; and node is not a thead, tbody, tfoot, tr, th, or td."
+	var nodeList = getContainedNodes(getActiveRange(),
 		function(node) {
 			return isEditable(node)
 				&& !isHtmlElement(node, ["thead", "tbody", "tfoot", "tr", "th", "td"]);
@@ -4620,11 +4641,11 @@
 		endNode.deleteData(0, endOffset);
 	}
 
-	// "Canonicalize whitespace at range's start."
-	canonicalizeWhitespace(range.startContainer, range.startOffset);
-
-	// "Canonicalize whitespace at range's end."
-	canonicalizeWhitespace(range.endContainer, range.endOffset);
+	// "Canonicalize whitespace at the active range's start."
+	canonicalizeWhitespace(getActiveRange().startContainer, getActiveRange().startOffset);
+
+	// "Canonicalize whitespace at the active range's end."
+	canonicalizeWhitespace(getActiveRange().endContainer, getActiveRange().endOffset);
 
 	// "If block merging is false, or start block or end block is null, or
 	// start block is not in the same editing host as end block, or start block
@@ -4634,8 +4655,23 @@
 	|| !endBlock
 	|| !inSameEditingHost(startBlock, endBlock)
 	|| startBlock == endBlock) {
-		// "Set range's end to its start."
-		range.setEnd(range.startContainer, range.startOffset);
+		// "If direction is "forward", call collapseToStart() on the context
+		// object's Selection."
+		if (direction == "forward") {
+			// Work around WebKit bug: sometimes it will remove the selection's
+			// range.
+			if (getSelection().rangeCount) {
+				getSelection().collapseToStart();
+			}
+			getActiveRange().collapse(true);
+
+		// "Otherwise, call collapseToEnd() on the context object's Selection."
+		} else {
+			if (getSelection().rangeCount) {
+				getSelection().collapseToEnd();
+			}
+			getActiveRange().collapse(false);
+		}
 
 		// "Restore states and values from overrides."
 		restoreStatesAndValues(overrides);
@@ -4651,13 +4687,6 @@
 		startBlock.removeChild(startBlock.firstChild);
 	}
 
-	// "If end block has one child, which is a collapsed block prop, remove its
-	// child from it."
-	if (endBlock.children.length == 1
-	&& isCollapsedBlockProp(endBlock.firstChild)) {
-		endBlock.removeChild(endBlock.firstChild);
-	}
-
 	// "If start block is an ancestor of end block:"
 	if (isAncestor(startBlock, endBlock)) {
 		// "Let reference node be end block."
@@ -4669,10 +4698,12 @@
 			referenceNode = referenceNode.parentNode;
 		}
 
-		// "Set the start and end of range to (start block, index of reference
-		// node)."
-		range.setStart(startBlock, getNodeIndex(referenceNode));
-		range.setEnd(startBlock, getNodeIndex(referenceNode));
+		// "Call collapse() on the context object's Selection, with first
+		// argument start block and second argument the index of reference
+		// node."
+		getSelection().collapse(startBlock, getNodeIndex(referenceNode));
+		getActiveRange().setStart(startBlock, getNodeIndex(referenceNode));
+		getActiveRange().collapse(true);
 
 		// "If end block has no children:"
 		if (!endBlock.hasChildNodes()) {
@@ -4750,10 +4781,11 @@
 
 	// "Otherwise, if start block is a descendant of end block:"
 	} else if (isDescendant(startBlock, endBlock)) {
-		// "Set the start and end of range to (start block, length of start
-		// block)."
-		range.setStart(startBlock, getNodeLength(startBlock));
-		range.setEnd(startBlock, getNodeLength(startBlock));
+		// "Call collapse() on the context object's Selection, with first
+		// argument start block and second argument start block's length."
+		getSelection().collapse(startBlock, getNodeLength(startBlock));
+		getActiveRange().setStart(startBlock, getNodeLength(startBlock));
+		getActiveRange().collapse(true);
 
 		// "Let reference node be start block."
 		var referenceNode = startBlock;
@@ -4774,20 +4806,19 @@
 		// "Let nodes to move be a list of nodes, initially empty."
 		var nodesToMove = [];
 
-		// "If reference node's nextSibling is neither null nor a br nor a
-		// block node, append it to nodes to move."
+		// "If reference node's nextSibling is neither null nor a block node,
+		// append it to nodes to move."
 		if (referenceNode.nextSibling
-		&& !isHtmlElement(referenceNode.nextSibling, "br")
 		&& !isBlockNode(referenceNode.nextSibling)) {
 			nodesToMove.push(referenceNode.nextSibling);
 		}
 
-		// "While nodes to move is nonempty and its last member's nextSibling
-		// is neither null nor a br nor a block node, append it to nodes to
-		// move."
+		// "While nodes to move is nonempty and its last member isn't a br and
+		// its last member's nextSibling is neither null nor a block node,
+		// append its last member's nextSibling to nodes to move."
 		if (nodesToMove.length
+		&& !isHtmlElement(nodesToMove[nodesToMove.length - 1], "br")
 		&& nodesToMove[nodesToMove.length - 1].nextSibling
-		&& !isHtmlElement(nodesToMove[nodesToMove.length - 1].nextSibling, "br")
 		&& !isBlockNode(nodesToMove[nodesToMove.length - 1].nextSibling)) {
 			nodesToMove.push(nodesToMove[nodesToMove.length - 1].nextSibling);
 		}
@@ -4801,18 +4832,13 @@
 			movePreservingRanges(node, startBlock, -1);
 		});
 
-		// "If the nextSibling of reference node is a br, remove it from its
-		// parent."
-		if (isHtmlElement(referenceNode.nextSibling, "br")) {
-			referenceNode.parentNode.removeChild(referenceNode.nextSibling);
-		}
-
 	// "Otherwise:"
 	} else {
-		// "Set the start and end of range to (start block, length of start
-		// block)."
-		range.setStart(startBlock, getNodeLength(startBlock));
-		range.setEnd(startBlock, getNodeLength(startBlock));
+		// "Call collapse() on the context object's Selection, with first
+		// argument start block and second argument start block's length."
+		getSelection().collapse(startBlock, getNodeLength(startBlock));
+		getActiveRange().setStart(startBlock, getNodeLength(startBlock));
+		getActiveRange().collapse(true);
 
 		// "If end block's firstChild is an inline node and start block's
 		// lastChild is a br, remove start block's lastChild from it."
@@ -4850,6 +4876,9 @@
 		startBlock.appendChild(document.createElement("br"));
 	}
 
+	// "Remove extraneous line breaks at the end of start block."
+	removeExtraneousLineBreaksAtTheEndOf(startBlock);
+
 	// "Restore states and values from overrides."
 	restoreStatesAndValues(overrides);
 }
@@ -5834,10 +5863,10 @@
 //@{
 commands["delete"] = {
 	action: function() {
-		// "If the active range is not collapsed, delete the contents of the
-		// active range and abort these steps."
+		// "If the active range is not collapsed, delete the selection and
+		// abort these steps."
 		if (!getActiveRange().collapsed) {
-			deleteContents(getActiveRange());
+			deleteSelection();
 			return;
 		}
 
@@ -5903,15 +5932,28 @@
 			}
 		}
 
-		// "If node is a Text node and offset is not zero, call collapse(node,
-		// offset) on the Selection. Then delete the contents of the range with
-		// start (node, offset − 1) and end (node, offset) and abort these
-		// steps."
-		if (node.nodeType == Node.TEXT_NODE
-		&& offset != 0) {
-			getActiveRange().setStart(node, offset);
+		// "If node is a Text node and offset is not zero, or if node is a
+		// block node that has a child with index offset − 1 and that child is
+		// a br or hr or img:"
+		if ((node.nodeType == Node.TEXT_NODE
+		&& offset != 0)
+		|| (isBlockNode(node)
+		&& 0 <= offset - 1
+		&& offset - 1 < node.childNodes.length
+		&& isHtmlElement(node.childNodes[offset - 1], ["br", "hr", "img"]))) {
+			// "Call collapse(node, offset) on the context object's Selection."
+			getSelection().collapse(node, offset);
 			getActiveRange().setEnd(node, offset);
-			deleteContents(node, offset - 1, node, offset);
+
+			// "Call extend(node, offset − 1) on the context object's
+			// Selection."
+			getSelection().extend(node, offset - 1);
+			getActiveRange().setStart(node, offset - 1);
+
+			// "Delete the selection."
+			deleteSelection();
+
+			// "Abort these steps."
 			return;
 		}
 
@@ -5920,19 +5962,6 @@
 			return;
 		}
 
-		// "If node has a child with index offset − 1 and that child is a br or
-		// hr or img, call collapse(node, offset) on the Selection. Then delete
-		// the contents of the range with start (node, offset − 1) and end
-		// (node, offset) and abort these steps."
-		if (0 <= offset - 1
-		&& offset - 1 < node.childNodes.length
-		&& isHtmlElement(node.childNodes[offset - 1], ["br", "hr", "img"])) {
-			getActiveRange().setStart(node, offset);
-			getActiveRange().setEnd(node, offset);
-			deleteContents(node, offset - 1, node, offset);
-			return;
-		}
-
 		// "If node is an li or dt or dd and is the first child of its parent,
 		// and offset is zero:"
 		if (isHtmlElement(node, ["li", "dt", "dd"])
@@ -6057,10 +6086,12 @@
 		&& isHtmlElement(startNode.childNodes[startOffset - 1], "table")) {
 			// "Call collapse(start node, start offset − 1) on the context
 			// object's Selection."
+			getSelection().collapse(startNode, startOffset - 1);
 			getActiveRange().setStart(startNode, startOffset - 1);
 
 			// "Call extend(start node, start offset) on the context object's
 			// Selection."
+			getSelection().extend(startNode, startOffset);
 			getActiveRange().setEnd(startNode, startOffset);
 
 			// "Abort these steps."
@@ -6080,13 +6111,23 @@
 				)
 			)
 		)) {
+			// "Call collapse(start node, start offset − 1) on the context
+			// object's Selection."
+			getSelection().collapse(startNode, startOffset - 1);
+			getActiveRange().setStart(startNode, startOffset - 1);
+
+			// "Call extend(start node, start offset) on the context object's
+			// Selection."
+			getSelection().extend(startNode, startOffset);
+			getActiveRange().setEnd(startNode, startOffset);
+
+			// "Delete the selection."
+			deleteSelection();
+
 			// "Call collapse(node, offset) on the Selection."
+			getSelection().collapse(node, offset);
 			getActiveRange().setStart(node, offset);
-			getActiveRange().setEnd(node, offset);
-
-			// "Delete the contents of the range with start (start node, start
-			// offset − 1) and end (start node, start offset)."
-			deleteContents(startNode, startOffset - 1, startNode, startOffset);
+			getActiveRange().collapse(true);
 
 			// "Abort these steps."
 			return;
@@ -6118,44 +6159,83 @@
 			}
 		}
 
-		// "If the child of start node with index start offset is an li or dt
-		// or dd, and its previousSibling is also an li or dt or dd, set start
-		// node to its child with index start offset − 1, then set start offset
-		// to start node's length, then set node to start node's nextSibling,
-		// then set offset to 0."
+		// "If start node's child with index start offset is an li or dt or dd,
+		// and that child's previousSibling is also an li or dt or dd:"
 		if (isHtmlElement(startNode.childNodes[startOffset], ["li", "dt", "dd"])
-		&& isHtmlElement(startNode.childNodes[startOffset - 1], ["li", "dt", "dd"])) {
+		&& isHtmlElement(startNode.childNodes[startOffset].previousSibling, ["li", "dt", "dd"])) {
+			// "Call cloneRange() on the active range, and let original range
+			// be the result."
+			//
+			// We need to add it to extraRanges so it will actually get updated
+			// when moving preserving ranges.
+			var originalRange = getActiveRange().cloneRange();
+			extraRanges.push(originalRange);
+
+			// "Set start node to its child with index start offset − 1."
 			startNode = startNode.childNodes[startOffset - 1];
+
+			// "Set start offset to start node's length."
 			startOffset = getNodeLength(startNode);
+
+			// "Set node to start node's nextSibling."
 			node = startNode.nextSibling;
-			offset = 0;
-
-		// "Otherwise, while start node has a child with index start offset
-		// minus one:"
-		} else {
-			while (0 <= startOffset - 1
-			&& startOffset - 1 < startNode.childNodes.length) {
-				// "If start node's child with index start offset minus one is
-				// editable and invisible, remove it from start node, then
-				// subtract one from start offset."
-				if (isEditable(startNode.childNodes[startOffset - 1])
-				&& isInvisible(startNode.childNodes[startOffset - 1])) {
-					startNode.removeChild(startNode.childNodes[startOffset - 1]);
-					startOffset--;
-
-				// "Otherwise, set start node to its child with index start
-				// offset minus one, then set start offset to the length of
-				// start node."
-				} else {
-					startNode = startNode.childNodes[startOffset - 1];
-					startOffset = getNodeLength(startNode);
-				}
+
+			// "Call collapse(start node, start offset) on the context object's
+			// Selection."
+			getSelection().collapse(startNode, startOffset);
+			getActiveRange().setStart(startNode, startOffset);
+
+			// "Call extend(node, 0) on the context object's Selection."
+			getSelection().extend(node, 0);
+			getActiveRange().setEnd(node, 0);
+
+			// "Delete the selection."
+			deleteSelection();
+
+			// "Call removeAllRanges() on the context object's Selection."
+			getSelection().removeAllRanges();
+
+			// "Call addRange(original range) on the context object's
+			// Selection."
+			getSelection().addRange(originalRange);
+			getActiveRange().setStart(originalRange.startContainer, originalRange.startOffset);
+			getActiveRange().setEnd(originalRange.endContainer, originalRange.endOffset);
+
+			// "Abort these steps."
+			extraRanges.pop();
+			return;
+		}
+
+		// "While start node has a child with index start offset minus one:"
+		while (0 <= startOffset - 1
+		&& startOffset - 1 < startNode.childNodes.length) {
+			// "If start node's child with index start offset minus one is
+			// editable and invisible, remove it from start node, then subtract
+			// one from start offset."
+			if (isEditable(startNode.childNodes[startOffset - 1])
+			&& isInvisible(startNode.childNodes[startOffset - 1])) {
+				startNode.removeChild(startNode.childNodes[startOffset - 1]);
+				startOffset--;
+
+			// "Otherwise, set start node to its child with index start offset
+			// minus one, then set start offset to the length of start node."
+			} else {
+				startNode = startNode.childNodes[startOffset - 1];
+				startOffset = getNodeLength(startNode);
 			}
 		}
 
-		// "Delete the contents of the range with start (start node, start
-		// offset) and end (node, offset)."
-		deleteContents(startNode, startOffset, node, offset);
+		// "Call collapse(start node, start offset) on the context object's
+		// Selection."
+		getSelection().collapse(startNode, startOffset);
+		getActiveRange().setStart(startNode, startOffset);
+
+		// "Call extend(node, offset) on the context object's Selection."
+		getSelection().extend(node, offset);
+		getActiveRange().setEnd(node, offset);
+
+		// "Delete the selection, with direction "backward"."
+		deleteSelection({direction: "backward"});
 	}
 };
 
@@ -6389,10 +6469,10 @@
 //@{
 commands.forwarddelete = {
 	action: function() {
-		// "If the active range is not collapsed, delete the contents of the
-		// active range and abort these steps."
+		// "If the active range is not collapsed, delete the selection and
+		// abort these steps."
 		if (!getActiveRange().collapsed) {
-			deleteContents(getActiveRange());
+			deleteSelection();
 			return;
 		}
 
@@ -6421,12 +6501,6 @@
 			&& isInvisible(node.childNodes[offset])) {
 				node.removeChild(node.childNodes[offset]);
 
-			// "Otherwise, if node has a child with index offset and that child
-			// is a collapsed block prop, add one to offset."
-			} else if (offset < node.childNodes.length
-			&& isCollapsedBlockProp(node.childNodes[offset])) {
-				offset++;
-
 			// "Otherwise, if offset is the length of node and node is an
 			// inline node, or if node is invisible, set offset to one plus the
 			// index of node, then set node to its parent."
@@ -6437,11 +6511,12 @@
 				node = node.parentNode;
 
 			// "Otherwise, if node has a child with index offset and that child
-			// is not a block node or a br or an img, set node to that child,
-			// then set offset to zero."
+			// is neither a block node nor a br nor an img nor a collapsed
+			// block prop, set node to that child, then set offset to zero."
 			} else if (offset < node.childNodes.length
 			&& !isBlockNode(node.childNodes[offset])
-			&& !isHtmlElement(node.childNodes[offset], ["br", "img"])) {
+			&& !isHtmlElement(node.childNodes[offset], ["br", "img"])
+			&& !isCollapsedBlockProp(node.childNodes[offset])) {
 				node = node.childNodes[offset];
 				offset = 0;
 
@@ -6454,10 +6529,6 @@
 		// "If node is a Text node and offset is not node's length:"
 		if (node.nodeType == Node.TEXT_NODE
 		&& offset != getNodeLength(node)) {
-			// "Call collapse(node, offset) on the Selection."
-			getActiveRange().setStart(node, offset);
-			getActiveRange().setEnd(node, offset);
-
 			// "Let end offset be offset plus one."
 			var endOffset = offset + 1;
 
@@ -6474,9 +6545,17 @@
 				endOffset++;
 			}
 
-			// "Delete the contents of the range with start (node, offset) and
-			// end (node, end offset)."
-			deleteContents(node, offset, node, endOffset);
+			// "Call collapse(node, offset) on the context object's Selection."
+			getSelection().collapse(node, offset);
+			getActiveRange().setStart(node, offset);
+
+			// "Call extend(node, end offset) on the context object's
+			// Selection."
+			getSelection().extend(node, endOffset);
+			getActiveRange().setEnd(node, endOffset);
+
+			// "Delete the selection."
+			deleteSelection();
 
 			// "Abort these steps."
 			return;
@@ -6488,14 +6567,23 @@
 		}
 
 		// "If node has a child with index offset and that child is a br or hr
-		// or img, call collapse(node, offset) on the Selection. Then delete
-		// the contents of the range with start (node, offset) and end (node,
-		// offset + 1) and abort these steps."
+		// or img, but is not a collapsed block prop:"
 		if (offset < node.childNodes.length
-		&& isHtmlElement(node.childNodes[offset], ["br", "hr", "img"])) {
+		&& isHtmlElement(node.childNodes[offset], ["br", "hr", "img"])
+		&& !isCollapsedBlockProp(node.childNodes[offset])) {
+			// "Call collapse(node, offset) on the context object's Selection."
+			getSelection().collapse(node, offset);
 			getActiveRange().setStart(node, offset);
-			getActiveRange().setEnd(node, offset);
-			deleteContents(node, offset, node, offset + 1);
+
+			// "Call extend(node, offset + 1) on the context object's
+			// Selection."
+			getSelection().extend(node, offset + 1);
+			getActiveRange().setEnd(node, offset + 1);
+
+			// "Delete the selection."
+			deleteSelection();
+
+			// "Abort these steps."
 			return;
 		}
 
@@ -6503,6 +6591,13 @@
 		var endNode = node;
 		var endOffset = offset;
 
+		// "If end node has a child with index end offset, and that child is a
+		// collapsed block prop, add one to end offset."
+		if (endOffset < endNode.childNodes.length
+		&& isCollapsedBlockProp(endNode.childNodes[endOffset])) {
+			endOffset++;
+		}
+
 		// "Repeat the following steps:"
 		while (true) {
 			// "If end offset is the length of end node, set end offset to one
@@ -6534,10 +6629,12 @@
 		if (isHtmlElement(endNode.childNodes[endOffset], "table")) {
 			// "Call collapse(end node, end offset) on the context object's
 			// Selection."
+			getSelection().collapse(endNode, endOffset);
 			getActiveRange().setStart(endNode, endOffset);
 
 			// "Call extend(end node, end offset + 1) on the context object's
 			// Selection."
+			getSelection().extend(endNode, endOffset + 1);
 			getActiveRange().setEnd(endNode, endOffset + 1);
 
 			// "Abort these steps."
@@ -6548,13 +6645,23 @@
 		// index end offset is an hr or br:"
 		if (offset == getNodeLength(node)
 		&& isHtmlElement(endNode.childNodes[endOffset], ["br", "hr"])) {
+			// "Call collapse(end node, end offset) on the context object's
+			// Selection."
+			getSelection().collapse(endNode, endOffset);
+			getActiveRange().setStart(endNode, endOffset);
+
+			// "Call extend(end node, end offset + 1) on the context object's
+			// Selection."
+			getSelection().extend(endNode, endOffset + 1);
+			getActiveRange().setEnd(endNode, endOffset + 1);
+
+			// "Delete the selection."
+			deleteSelection();
+
 			// "Call collapse(node, offset) on the Selection."
+			getSelection().collapse(node, offset);
 			getActiveRange().setStart(node, offset);
-			getActiveRange().setEnd(node, offset);
-
-			// "Delete the contents of the range with end (end node, end
-			// offset) and end (end node, end offset + 1)."
-			deleteContents(endNode, endOffset, endNode, endOffset + 1);
+			getActiveRange().collapse(true);
 
 			// "Abort these steps."
 			return;
@@ -6576,9 +6683,17 @@
 			}
 		}
 
-		// "Delete the contents of the range with start (node, offset) and end
-		// (end node, end offset)."
-		deleteContents(node, offset, endNode, endOffset);
+		// "Call collapse(node, offset) on the context object's Selection."
+		getSelection().collapse(node, offset);
+		getActiveRange().setStart(node, offset);
+
+		// "Call extend(end node, end offset) on the context object's
+		// Selection."
+		getSelection().extend(endNode, endOffset);
+		getActiveRange().setEnd(endNode, endOffset);
+
+		// "Delete the selection."
+		deleteSelection();
 	}
 };
 
@@ -6665,27 +6780,43 @@
 //@{
 commands.inserthorizontalrule = {
 	action: function() {
-		// "Let range be the active range."
-		var range = getActiveRange();
-
-		// "While range's start offset is 0 and its start node's parent is not
-		// null, set range's start to (parent of start node, index of start
-		// node)."
-		while (range.startOffset == 0
-		&& range.startContainer.parentNode) {
-			range.setStart(range.startContainer.parentNode, getNodeIndex(range.startContainer));
-		}
-
-		// "While range's end offset is the length of its end node, and its end
-		// node's parent is not null, set range's end to (parent of end node, 1
-		// + index of start node)."
-		while (range.endOffset == getNodeLength(range.endContainer)
-		&& range.endContainer.parentNode) {
-			range.setEnd(range.endContainer.parentNode, 1 + getNodeIndex(range.endContainer));
-		}
-
-		// "Delete the contents of range, with block merging false."
-		deleteContents(range, {blockMerging: false});
+		// "Let start node, start offset, end node, and end offset be the
+		// active range's start and end nodes and offsets."
+		var startNode = getActiveRange().startContainer;
+		var startOffset = getActiveRange().startOffset;
+		var endNode = getActiveRange().endContainer;
+		var endOffset = getActiveRange().endOffset;
+
+		// "While start offset is 0 and start node's parent is not null, set
+		// start offset to start node's index, then set start node to its
+		// parent."
+		while (startOffset == 0
+		&& startNode.parentNode) {
+			startOffset = getNodeIndex(startNode);
+			startNode = startNode.parentNode;
+		}
+
+		// "While end offset is end node's length, and end node's parent is not
+		// null, set end offset to one plus end node's index, then set end node
+		// to its parent."
+		while (endOffset == getNodeLength(endNode)
+		&& endNode.parentNode) {
+			endOffset = 1 + getNodeIndex(endNode);
+			endNode = endNode.parentNode;
+		}
+
+		// "Call collapse(start node, start offset) on the context object's
+		// Selection."
+		getSelection().collapse(startNode, startOffset);
+		getActiveRange().setStart(startNode, startOffset);
+
+		// "Call extend(end node, end offset) on the context object's
+		// Selection."
+		getSelection().extend(endNode, endOffset);
+		getActiveRange().setEnd(endNode, endOffset);
+
+		// "Delete the selection, with block merging false."
+		deleteSelection({blockMerging: false});
 
 		// "If the active range's start node is neither editable nor an editing
 		// host, abort these steps."
@@ -6695,20 +6826,29 @@
 		}
 
 		// "If the active range's start node is a Text node and its start
-		// offset is zero, set the active range's start and end to (parent of
-		// start node, index of start node)."
+		// offset is zero, call collapse() on the context object's Selection,
+		// with first argument the active range's start node's parent and
+		// second argument the active range's start node's index."
 		if (getActiveRange().startContainer.nodeType == Node.TEXT_NODE
 		&& getActiveRange().startOffset == 0) {
-			getActiveRange().setStart(getActiveRange().startContainer.parentNode, getNodeIndex(getActiveRange().startContainer));
+			var newNode = getActiveRange().startContainer.parentNode;
+			var newOffset = getNodeIndex(getActiveRange().startContainer);
+			getSelection().collapse(newNode, newOffset);
+			getActiveRange().setStart(newNode, newOffset);
 			getActiveRange().collapse(true);
 		}
 
 		// "If the active range's start node is a Text node and its start
-		// offset is the length of its start node, set the active range's start
-		// and end to (parent of start node, 1 + index of start node)."
+		// offset is the length of its start node, call collapse() on the
+		// context object's Selection, with first argument the active range's
+		// start node's parent, and the second argument one plus the active
+		// range's start node's index."
 		if (getActiveRange().startContainer.nodeType == Node.TEXT_NODE
 		&& getActiveRange().startOffset == getNodeLength(getActiveRange().startContainer)) {
-			getActiveRange().setStart(getActiveRange().startContainer.parentNode, 1 + getNodeIndex(getActiveRange().startContainer));
+			var newNode = getActiveRange().startContainer.parentNode;
+			var newOffset = 1 + getNodeIndex(getActiveRange().startContainer);
+			getSelection().collapse(newNode, newOffset);
+			getActiveRange().setStart(newNode, newOffset);
 			getActiveRange().collapse(true);
 		}
 
@@ -6716,23 +6856,18 @@
 		// context object."
 		var hr = document.createElement("hr");
 
-		// "Run insertNode(hr) on the range."
-		range.insertNode(hr);
+		// "Run insertNode(hr) on the active range."
+		getActiveRange().insertNode(hr);
 
 		// "Fix disallowed ancestors of hr."
 		fixDisallowedAncestors(hr);
 
-		// "Run collapse() on the Selection, with first argument equal to the
-		// parent of hr and the second argument equal to one plus the index of
-		// hr."
-		//
-		// Not everyone actually supports collapse(), so we do it manually
-		// instead.  Also, we need to modify the actual range we're given as
-		// well, for the sake of autoimplementation.html's range-filling-in.
-		range.setStart(hr.parentNode, 1 + getNodeIndex(hr));
-		range.setEnd(hr.parentNode, 1 + getNodeIndex(hr));
-		getSelection().removeAllRanges();
-		getSelection().addRange(range);
+		// "Run collapse() on the context object's Selection, with first
+		// argument hr's parent and the second argument equal to one plus hr's
+		// index."
+		getSelection().collapse(hr.parentNode, 1 + getNodeIndex(hr));
+		getActiveRange().setStart(hr.parentNode, 1 + getNodeIndex(hr));
+		getActiveRange().collapse(true);
 	}
 };
 
@@ -6741,8 +6876,8 @@
 //@{
 commands.inserthtml = {
 	action: function(value) {
-		// "Delete the contents of the active range."
-		deleteContents(getActiveRange());
+		// "Delete the selection."
+		deleteSelection();
 
 		// "If the active range's start node is neither editable nor an editing
 		// host, abort these steps."
@@ -6817,12 +6952,12 @@
 			return;
 		}
 
+		// "Delete the selection, with strip wrappers false."
+		deleteSelection({stripWrappers: false});
+
 		// "Let range be the active range."
 		var range = getActiveRange();
 
-		// "Delete the contents of range, with strip wrappers false."
-		deleteContents(range, {stripWrappers: false});
-
 		// "If the active range's start node is neither editable nor an editing
 		// host, abort these steps."
 		if (!isEditable(getActiveRange().startContainer)
@@ -6873,8 +7008,8 @@
 //@{
 commands.insertlinebreak = {
 	action: function(value) {
-		// "Delete the contents of the active range, with strip wrappers false."
-		deleteContents(getActiveRange(), {stripWrappers: false});
+		// "Delete the selection, with strip wrappers false."
+		deleteSelection({stripWrappers: false});
 
 		// "If the active range's start node is neither editable nor an editing
 		// host, abort these steps."
@@ -6971,8 +7106,8 @@
 //@{
 commands.insertparagraph = {
 	action: function() {
-		// "Delete the contents of the active range."
-		deleteContents(getActiveRange());
+		// "Delete the selection."
+		deleteSelection();
 
 		// "If the active range's start node is neither editable nor an editing
 		// host, abort these steps."
@@ -7276,9 +7411,8 @@
 //@{
 commands.inserttext = {
 	action: function(value) {
-		// "Delete the contents of the active range, with strip wrappers
-		// false."
-		deleteContents(getActiveRange(), {stripWrappers: false});
+		// "Delete the selection, with strip wrappers false."
+		deleteSelection({stripWrappers: false});
 
 		// "If the active range's start node is neither editable nor an editing
 		// host, abort these steps."
--- a/preprocess	Mon Aug 29 14:42:53 2011 -0600
+++ b/preprocess	Tue Aug 30 13:52:24 2011 -0600
@@ -26,8 +26,10 @@
     'cdlength': '<code data-anolis-spec=domcore title=dom-CharacterData-length>length</code>',
     'child': '<span data-anolis-spec=domcore title=concept-tree-child>child</span>',
     'children': '<span data-anolis-spec=domcore title=concept-tree-child>children</span>',
+    'clonerange': '<code data-anolis-spec=domrange title=dom-Range-cloneRange>cloneRange()</code>',
     'codeunit': '<a href=http://dev.w3.org/2006/webapi/WebIDL/#dfn-code-unit>code unit</a>',
     'collapsetoend': '<code data-anolis-spec=domrange title=dom-Selection-collapseToEnd>collapseToEnd()</code>',
+    'collapsetostart': '<code data-anolis-spec=domrange title=dom-Selection-collapseToStart>collapseToStart()</code>',
     'collection': '<span data-anolis-spec=domcore title=concept-collection>collection</span>',
     'contained': '<span data-anolis-spec=domrange>contained</span>',
     'comment': '<code data-anolis-spec=domcore>Comment</code>',
@@ -132,6 +134,7 @@
     s = s.replace("[[" + key.capitalize() + "]]", capreplace)
 
 fnreplace = {
+    'addrange': '<code data-anolis-spec=domrange title=dom-Selection-addRange>addRange(\\1)</code>',
     'appendchild': '<code data-anolis-spec=domcore title=dom-Node-appendChild>appendChild(\\1)</code>',
     'createelement': '<code data-anolis-spec=domcore title=dom-Document-createElement>createElement(\\1)</code>',
     'deletedata': '<code data-anolis-spec=domcore title=dom-CharacterData-deleteData>deleteData(\\1)</code>',
--- a/source.html	Mon Aug 29 14:42:53 2011 -0600
+++ b/source.html	Tue Aug 30 13:52:24 2011 -0600
@@ -1269,7 +1269,18 @@
   [[treeorder]].
 
   <li>If <var>ref</var> is an <span>editable</span> <span>extraneous line
-  break</span>, remove it from its [[parent]].
+  break</span>:
+
+  <ol>
+    <li>
+    <p class=comments>If the block ends with {{code|<span><br></span>}}, for
+    instance, we want to remove the span too.
+
+    <p>While <var>ref</var>'s [[parent]] is <span>editable</span> and
+    <span>invisible</span>, set <var>ref</var> to its [[parent]].
+
+    <li>Remove <var>ref</var> from its [[parent]].
+  </ol>
 </ol>
 
 <p>To <dfn>remove extraneous line breaks from</dfn> a [[node]], first
@@ -4432,35 +4443,33 @@
 </ol>
 
 <[email protected]}-->
-<h3>Deleting the contents of a range</h3>
+<h3>Deleting the selection</h3>
 <!-- @{ -->
 <p class=comments>TODO: Consider what should happen for block merging in corner
 cases like display: inline-table.
 
-<p>To <dfn>delete the contents</dfn> of a [[range]] <var>range</var>, given a
-<var>block merging</var> flag that defaults to true and a <var>strip
-wrappers</var> flag that defaults to true:
+<p>To <dfn>delete the selection</dfn>, given a <var>block merging</var> flag
+that defaults to true, a <var>strip wrappers</var> flag that defaults to
+true, and a string <var>direction</var> that defaults to "forward":
 
 <div class=note>
 <p>The idea behind this algorithm is self-explanatory, but the details wind up
 being remarkably complicated.
 
-<p>First, any editable nodes inside the range will be deleted, and the range
-will be collapsed.  By way of contrast, <span>effectively contained</span>
-tries to expand the range to include as much as possible, so <code
-title>&lt;p>[foo]&lt;/p></code> contains the <code title>&lt;p></code>.  What
-we do here is contract the range to include as little as possible, so <code
-title>{&lt;p>foo&lt;/p>}</code> contains only <code title>foo</code> and
-doesn't delete the paragraph.
-
-<p>After that, if the range originally started and ended in different blocks,
-and the <var>block merging</var> flag is true, the end block will get merged
-into the start block.  This is needed so if the user selects text on several
-lines and deletes it, the text immediately that was before the selection winds
-up on the same line as the text immediately after it.  For example, <code
-title>&lt;p>fo[o&lt;/p>&lt;div>b]ar&lt;/div></code> becomes <code
-title>&lt;p>fo[]ar&lt;/p></code>.  This procedure winds up being tricky, and
-takes up a large chunk of the logic.
+<p>First, any editable nodes inside the selection will be deleted, and the
+selection will be collapsed.  By way of contrast, <span>effectively
+contained</span> tries to expand the range to include as much as possible, so
+{{code|<p>[foo]</p>}} contains the {{code|<p>}}.  What we do here is contract
+the range to include as little as possible, so {{code|{<p>foo</p>} }} contains
+only {{code|foo}} and doesn't delete the paragraph.
+
+<p>After that, if the selection originally started and ended in different
+blocks, and the <var>block merging</var> flag is true, the end block will get
+merged into the start block.  This is needed so if the user selects text on
+several lines and deletes it, the text immediately that was before the
+selection winds up on the same line as the text immediately after it.  For
+example, {{code|<p>fo[o</p><div>b]ar</div>}} becomes {{code|<p>fo[]ar</p>}}.
+This procedure winds up being tricky, and takes up a large chunk of the logic.
 
 <p>Tables are a notable special case.  If an entire table is contained in the
 range, it will be deleted.  If it's anything less, only the contents of the
@@ -4482,11 +4491,12 @@
 </div>
 
 <ol>
-  <li>If <var>range</var> is null, abort these steps and do nothing.
+  <li>If the <span>active range</span> is null, abort these steps and do
+  nothing.
 
   <li>Let <var>start node</var>, <var>start offset</var>, <var>end node</var>,
-  and <var>end offset</var> be <var>range</var>'s [[rangestart]] and
-  [[rangeend]] [[bpnodes]] and [[bpoffsets]].
+  and <var>end offset</var> be the <span>active range</span>'s [[rangestart]]
+  and [[rangeend]] [[bpnodes]] and [[bpoffsets]].
 
   <li>
   <div class=comments>
@@ -4502,7 +4512,7 @@
 -> foo&lt;br />{bar]
 -> foo&lt;br />[bar]</pre>
 
-  <p>and we deselected the &lt;br>.
+  <p>and we deselected the {{code|<br>}}.
   </div>
 
   <p>While <var>start node</var> has at least one [[child]]:
@@ -4516,7 +4526,7 @@
 -> &lt;b>foo{&lt;/b>&lt;i>bar]&lt;/i>
 -> &lt;b>foo&lt;/b>{&lt;i>bar]&lt;/i></pre>
 
-    <p>Then the next step will make it &lt;b>foo&lt;/b>&lt;i>[bar]&lt;/i>.
+    <p>Then the next step will make it {{code|<b>foo</b><i>[bar]</i>}}.
 
     <p>We don't want to do this for block nodes, because that would lead to
     something like
@@ -4524,7 +4534,7 @@
       <pre>&lt;p>foo[&lt;/p>&lt;p>]bar&lt;p></pre>
 
     <p>ultimately collapsing, which is wrong.  Once we do the deletion, it
-    needs to wind up &lt;p>foo[]bar&lt;/p>, whereas an actually collapsed
+    needs to wind up {{code|<p>foo[]bar</p>}}, whereas an actually collapsed
     selection should do nothing.
     </div>
 
@@ -4589,8 +4599,17 @@
   </ol>
 
   <li>If (<var>end node</var>, <var>end offset</var>) is not [[bpafter]]
-  (<var>start node</var>, <var>start offset</var>), set <var>range</var>'s
-  [[rangeend]] to its [[rangestart]] and abort these steps.
+  (<var>start node</var>, <var>start offset</var>):
+
+  <ol>
+    <li>If <var>direction</var> is "forward", call [[collapsetostart]] on the
+    [[contextobject]]'s [[selection]].
+
+    <li>Otherwise, call [[collapsetoend]] on the [[contextobject]]'s
+    [[selection]].
+
+    <li>Abort these steps.
+  </ol>
 
   <li>If <var>start node</var> is a [[text]] node and <var>start offset</var>
   is 0, set <var>start offset</var> to the [[index]] of <var>start node</var>,
@@ -4600,9 +4619,11 @@
   its [[nodelength]], set <var>end offset</var> to one plus the [[index]] of
   <var>end node</var>, then set <var>end node</var> to its [[parent]].
 
-  <li>Set <var>range</var>'s [[rangestart]] to (<var>start node</var>,
-  <var>start offset</var>) and its [[rangeend]] to (<var>end node</var>,
-  <var>end offset</var>).
+  <li>Call [[selcollapse|<var>start node</var>, <var>start offset</var>]] on
+  the [[contextobject]]'s [[selection]].
+
+  <li>Call [[extend|<var>end node</var>, <var>end offset</var>]] on the
+  [[contextobject]]'s [[selection]].
 
   <li>
   <div class=comments>
@@ -4616,8 +4637,8 @@
   anything.
   </div>
 
-  <p>Let <var>start block</var> be the [[rangestart]] [[bpnode]] of
-  <var>range</var>.
+  <p>Let <var>start block</var> be the <span>active range</span>'s
+  [[startnode]].
 
   <li>While <var>start block</var>'s [[parent]] is <span>in the same editing
   host</span> and <var>start block</var> is an <span>inline node</span>, set
@@ -4653,8 +4674,7 @@
   <var>start block</var>, or <var>start block</var> is a [[td]] or [[th]], set
   <var>start block</var> to null.
 
-  <li>Let <var>end block</var> be the [[rangeend]] [[bpnode]] of
-  <var>range</var>.
+  <li>Let <var>end block</var> be the <span>active range</span>'s [[endnode]].
 
   <li>While <var>end block</var>'s [[parent]] is <span>in the same editing
   host</span> and <var>end block</var> is an <span>inline node</span>, set
@@ -4696,7 +4716,11 @@
     <li><span>Canonicalize whitespace</span> at (<var>start node</var>,
     <var>start offset</var>).
 
-    <li>Set <var>range</var>'s [[rangeend]] to its [[rangestart]].
+    <li>If <var>direction</var> is "forward", call [[collapsetostart]] on the
+    [[contextobject]]'s [[selection]].
+
+    <li>Otherwise, call [[collapsetoend]] on the [[contextobject]]'s
+    [[selection]].
 
     <li>
     <p class=comments>This is needed to restore any overrides that would
@@ -4724,9 +4748,9 @@
   cell-selection mode when you try to select between cells, at least in some
   cases, instead of selecting letter-by-letter.
 
-  <p>For each <var>node</var> [[contained]] in <var>range</var>, append
-  <var>node</var> to <var>node list</var> if the last member of <var>node
-  list</var> (if any) is not an [[ancestor]] of <var>node</var>;
+  <p>For each <var>node</var> [[contained]] in the <span>active range</span>,
+  append <var>node</var> to <var>node list</var> if the last member of
+  <var>node list</var> (if any) is not an [[ancestor]] of <var>node</var>;
   <var>node</var> is <span>editable</span>; and <var>node</var> is not a
   [[thead]], [[tbody]], [[tfoot]], [[tr]], [[th]], or [[td]].
 
@@ -4765,10 +4789,11 @@
   <li>If <var>end node</var> is an <span>editable</span> [[text]] node, call
   [[deletedata|0, <var>end offset</var>]] on it.
 
-  <li><span>Canonicalize whitespace</span> at <var>range</var>'s
+  <li><span>Canonicalize whitespace</span> at the <span>active range</span>'s
   [[rangestart]].
 
-  <li><span>Canonicalize whitespace</span> at <var>range</var>'s [[rangeend]].
+  <li><span>Canonicalize whitespace</span> at the <span>active range</span>'s
+  [[rangeend]].
 
   <li>
   <div class=comments>
@@ -4801,7 +4826,11 @@
   and <var>end block</var> are the same:
 
   <ol>
-    <li>Set <var>range</var>'s [[rangeend]] to its [[rangestart]].
+    <li>If <var>direction</var> is "forward", call [[collapsetostart]] on the
+    [[contextobject]]'s [[selection]].
+
+    <li>Otherwise, call [[collapsetoend]] on the [[contextobject]]'s
+    [[selection]].
 
     <li><span>Restore states and values</span> from <var>overrides</var>.
 
@@ -4818,9 +4847,6 @@
   <p>If <var>start block</var> has one [[child]], which is a <span>collapsed
   block prop</span>, remove its [[child]] from it.
 
-  <li>If <var>end block</var> has one [[child]], which is a <span>collapsed
-  block prop</span>, remove its [[child]] from it.
-
   <li>
   <p class=comments>Just repeatedly blow up the end block in this case.
 
@@ -4832,8 +4858,9 @@
     <li>While <var>reference node</var> is not a [[child]] of <var>start
     block</var>, set <var>reference node</var> to its [[parent]].
 
-    <li>Set the [[rangestart]] and [[rangeend]] of <var>range</var> to
-    (<var>start block</var>, [[index]] of <var>reference node</var>).
+    <li>Call [[selcollapse|]] on the [[contextobject]]'s [[selection]], with
+    first argument <var>start block</var> and second argument the [[index]] of
+    <var>reference node</var>.
 
     <li>If <var>end block</var> has no [[children]]:
 
@@ -4890,8 +4917,9 @@
   block</var>:
 
   <ol>
-    <li>Set the [[rangestart]] and [[rangeend]] of <var>range</var> to
-    (<var>start block</var>, [[nodelength]] of <var>start block</var>).
+    <li>Call [[selcollapse|]] on the [[contextobject]]'s [[selection]], with
+    first argument <var>start block</var> and second argument <var>start
+    block</var>'s [[nodelength]].
 
     <li>Let <var>reference node</var> be <var>start block</var>.
 
@@ -4905,12 +4933,12 @@
     <li>Let <var>nodes to move</var> be a list of [[nodes]], initially empty.
 
     <li>If <var>reference node</var>'s [[nextsibling]] is neither null nor a
-    [[br]] nor a <span>block node</span>, append it to <var>nodes to
-    move</var>.
-
-    <li>While <var>nodes to move</var> is nonempty and its last member's
-    [[nextsibling]] is neither null nor a [[br]] nor a <span>block node</span>,
-    append it to <var>nodes to move</var>.
+    <span>block node</span>, append it to <var>nodes to move</var>.
+
+    <li>While <var>nodes to move</var> is nonempty and its last member isn't a
+    [[br]] and its last member's [[nextsibling]] is neither null nor a
+    <span>block node</span>, append its last member's [[nextsibling]] to
+    <var>nodes to move</var>.
 
     <li><span>Record the values</span> of <var>nodes to move</var>, and let
     <var>values</var> be the result.
@@ -4918,9 +4946,6 @@
     <li>For each <var>node</var> in <var>nodes to move</var>, append
     <var>node</var> as the last [[child]] of <var>start block</var>,
     <span>preserving ranges</span>.
-
-    <li>If the [[nextsibling]] of <var>reference node</var> is a [[br]], remove
-    it from its [[parent]].
   </ol>
 
   <li>
@@ -4931,8 +4956,9 @@
   <p>Otherwise:
 
   <ol>
-    <li>Set the [[rangestart]] and [[rangeend]] of <var>range</var> to
-    (<var>start block</var>, [[nodelength]] of <var>start block</var>).
+    <li>Call [[selcollapse|]] on the [[contextobject]]'s [[selection]], with
+    first argument <var>start block</var> and second argument <var>start
+    block</var>'s [[nodelength]].
 
     <li>If <var>end block</var>'s [[firstchild]] is an <span>inline node</span>
     and <var>start block</var>'s [[lastchild]] is a [[br]], remove <var>start
@@ -4956,6 +4982,9 @@
   [[createelement|"br"]] on the [[contextobject]] and append the result as the
   last [[child]] of <var>start block</var>.
 
+  <li><span>Remove extraneous line breaks at the end of</span> <var>start
+  block</var>.
+
   <li><span>Restore states and values</span> from <var>overrides</var>.
 </ol>
 
@@ -6607,7 +6636,7 @@
 <div class=note>
 <p>This is the same as hitting backspace (see <a
 href=#additional-requirements>Additional requirements</a>).  The easy part is
-if the selection isn't collapsed: just <span>delete the contents</span>.  But
+if the selection isn't collapsed: just <span>delete the selection</span>.  But
 it turns out rich-text editors have a lot of special behaviors for hitting
 backspace with a collapsed selection.  Most obviously, if there's a text node
 right before the cursor (maybe wrapped in some inline elements), we delete its
@@ -6651,8 +6680,8 @@
 
 <ol>
   <li>If the <span>active range</span> is not <code data-anolis-spec=domrange
-  title=dom-Range-collapsed>collapsed</code>, <span>delete the contents</span>
-  of the <span>active range</span> and abort these steps.
+  title=dom-Range-collapsed>collapsed</code>, <span>delete the selection</span>
+  and abort these steps.
 
   <li>
   <p class=comments>Needed so that if there are multiple consecutive spaces we
@@ -6742,10 +6771,21 @@
   </div>
 
   <p>If <var>node</var> is a [[text]] node and <var>offset</var> is not zero,
-  call [[selcollapse|<var>node</var>, <var>offset</var>]] on the [[selection]].
-  Then <span>delete the contents</span> of the [[range]] with [[rangestart]]
-  (<var>node</var>, <var>offset</var> &minus; 1) and [[rangeend]]
-  (<var>node</var>, <var>offset</var>) and abort these steps.
+  or if <var>node</var> is a <span>block node</span> that has a [[child]] with
+  [[index]] <var>offset</var> &minus; 1 and that [[child]] is a [[br]] or
+  [[hr]] or [[img]]:
+
+  <ol>
+    <li>Call [[selcollapse|<var>node</var>, <var>offset</var>]] on the
+    [[contextobject]]'s [[selection]].
+
+    <li>Call [[extend|<var>node</var>, <var>offset</var> &minus; 1]] on the
+    [[contextobject]]'s [[selection]].
+
+    <li><span>Delete the selection</span>.
+
+    <li>Abort these steps.
+  </ol>
 
   <li>
   <p class=comments>At the time of this writing, this should be impossible.
@@ -6753,13 +6793,6 @@
 
   <p>If <var>node</var> is an <span>inline node</span>, abort these steps.
 
-  <li>If <var>node</var> has a [[child]] with [[index]] <var>offset</var>
-  &minus; 1 and that [[child]] is a [[br]] or [[hr]] or [[img]], call
-  [[selcollapse|<var>node</var>, <var>offset</var>]] on the [[selection]].
-  Then <span>delete the contents</span> of the [[range]] with [[rangestart]]
-  (<var>node</var>, <var>offset</var> &minus; 1) and [[rangeend]]
-  (<var>node</var>, <var>offset</var>) and abort these steps.
-
   <li>
   <p class=comments> If we're at the beginning of a list, we want to outdent
   the first list item.  This doesn't actually match anyone or anything.  Word
@@ -6906,13 +6939,17 @@
   an <span>inline node</span>:
 
   <ol>
+    <li>Call [[selcollapse|<var>start node</var>, <var>start offset</var>
+    &minus; 1]] on the [[contextobject]]'s [[selection]].
+
+    <li>Call [[extend|<var>start node</var>, <var>start offset</var>]] on the
+    [[contextobject]]'s [[selection]].
+
+    <li><span>Delete the selection</span>.
+
     <li>Call [[selcollapse|<var>node</var>, <var>offset</var>]] on the
     [[selection]].
 
-    <li><span>Delete the contents</span> of the [[range]] with [[rangestart]]
-    (<var>start node</var>, <var>start offset</var> &minus; 1) and [[rangeend]]
-    (<var>start node</var>, <var>start offset</var>).
-
     <li>Abort these steps.
   </ol>
 
@@ -6961,22 +6998,49 @@
   <li>
   <p class=comments>When merging adjacent list items, make sure we only merge
   the items themselves, not any block children.  We want
-  &lt;li>&lt;p>foo&lt;li>&lt;p>bar to become &lt;li>&lt;p>foo&lt;p>bar, not
-  &lt;li>&lt;p>foo&lt;br>bar or &lt;li>&lt;p>foobar.
-
-  <p>If the [[child]] of <var>start node</var> with [[index]] <var>start
-  offset</var> is an [[li]] or [[dt]] or [[dd]], and its [[previoussibling]] is
-  also an [[li]] or [[dt]] or [[dd]], set <var>start node</var> to its
-  [[child]] with [[index]] <var>start offset</var> &minus; 1, then set
-  <var>start offset</var> to <var>start node</var>'s [[nodelength]], then set
-  <var>node</var> to <var>start node</var>'s [[nextsibling]], then set
-  <var>offset</var> to 0.
+  {{code|<li><p>foo<li><p>[]bar}} to become {{code|<li><p>foo<p>[]bar}}, not
+  {{code|<li><p>foo<br>[]bar}} or {{code|<li><p>foo[]bar}}.  To do the
+  deletion, we need to wipe out the current selection, so we save it as a
+  range.  Saving it as a node/offset pair isn't enough, because it might be
+  invalid after we do the deletion.  A range will update according to the range
+  mutation rules.
+
+  <p>If <var>start node</var>'s [[child]] with [[index]] <var>start
+  offset</var> is an [[li]] or [[dt]] or [[dd]], and that [[child]]'s
+  [[previoussibling]] is also an [[li]] or [[dt]] or [[dd]]:
+
+  <ol>
+    <li>Call [[clonerange]] on the <span>active range</span>, and let
+    <var>original range</var> be the result.
+
+    <li>Set <var>start node</var> to its [[child]] with [[index]] <var>start
+    offset</var> &minus; 1.
+
+    <li>Set <var>start offset</var> to <var>start node</var>'s [[nodelength]].
+
+    <li>Set <var>node</var> to <var>start node</var>'s [[nextsibling]].
+
+    <li>Call [[selcollapse|<var>start node</var>, <var>start offset</var>]] on
+    the [[contextobject]]'s [[selection]].
+
+    <li>Call [[extend|<var>node</var>, 0]] on the [[contextobject]]'s
+    [[selection]].
+
+    <li><span>Delete the selection</span>.
+
+    <li>Call [[removeallranges]] on the [[contextobject]]'s [[selection]].
+
+    <li>Call [[addrange|<var>original range</var>]] on the [[contextobject]]'s
+    [[selection]].
+
+    <li>Abort these steps.
+  </ol>
 
   <li>
   <p class=comments>General block-merging case.
 
-  <p>Otherwise, while <var>start node</var> has a [[child]] with [[index]]
-  <var>start offset</var> minus one:
+  <p>While <var>start node</var> has a [[child]] with [[index]] <var>start
+  offset</var> minus one:
 
   <ol>
     <li>If <var>start node</var>'s [[child]] with [[index]] <var>start
@@ -6989,9 +7053,13 @@
     [[nodelength]] of <var>start node</var>.
   </ol>
 
-  <li><span>Delete the contents</span> of the [[range]] with [[rangestart]]
-  (<var>start node</var>, <var>start offset</var>) and [[rangeend]]
-  (<var>node</var>, <var>offset</var>).
+  <li>Call [[selcollapse|<var>start node</var>, <var>start offset</var>]] on
+  the [[contextobject]]'s [[selection]].
+
+  <li>Call [[extend|<var>node</var>, <var>offset</var>]] on the
+  [[contextobject]]'s [[selection]].
+
+  <li><span>Delete the selection</span>, with <var>direction</var> "backward".
 </ol>
 
 <!-- @} -->
@@ -7347,8 +7415,8 @@
 
 <ol>
   <li>If the <span>active range</span> is not <code data-anolis-spec=domrange
-  title=dom-Range-collapsed>collapsed</code>, <span>delete the contents</span>
-  of the <span>active range</span> and abort these steps.
+  title=dom-Range-collapsed>collapsed</code>, <span>delete the selection</span>
+  and abort these steps.
 
   <li><span>Canonicalize whitespace</span> at (<span>active range</span>'s
   [[startnode]], <span>active range</span>'s [[startoffset]]).
@@ -7369,10 +7437,6 @@
     <span>invisible</span> [[node]], remove that [[child]] from
     <var>node</var>.
 
-    <li>Otherwise, if <var>node</var> has a [[child]] with [[index]]
-    <var>offset</var> and that [[child]] is a <span>collapsed block
-    prop</span>, add one to <var>offset</var>.
-
     <li>Otherwise, if <var>offset</var> is the [[nodelength]] of
     <var>node</var> and <var>node</var> is an <span>inline node</span>, or if
     <var>node</var> is <span>invisible</span>, set <var>offset</var> to one
@@ -7384,9 +7448,9 @@
     delete.
 
     <p>Otherwise, if <var>node</var> has a [[child]] with [[index]]
-    <var>offset</var> and that [[child]] is not a <span>block node</span> or a
-    [[br]] or an [[img]], set <var>node</var> to that [[child]], then set
-    <var>offset</var> to zero.
+    <var>offset</var> and that [[child]] is neither a <span>block node</span>
+    nor a [[br]] nor an [[img]] nor a <span>collapsed block prop</span>, set
+    <var>node</var> to that [[child]], then set <var>offset</var> to zero.
 
     <li>Otherwise, break from this loop.
   </ol>
@@ -7395,9 +7459,6 @@
   <var>node</var>'s [[nodelength]]:
 
   <ol>
-    <li>Call [[selcollapse|<var>node</var>, <var>offset</var>]] on the
-    [[selection]].
-
     <li>Let <var>end offset</var> be <var>offset</var> plus one.
 
     <li>
@@ -7428,9 +7489,13 @@
     general category M when interpreted as a Unicode code point, add one to
     <var>end offset</var>.
 
-    <li><span>Delete the contents</span> of the [[range]] with [[rangestart]]
-    (<var>node</var>, <var>offset</var>) and [[rangeend]] (<var>node</var>,
-    <var>end offset</var>).
+    <li>Call [[selcollapse|<var>node</var>, <var>offset</var>]] on the
+    [[contextobject]]'s [[selection]].
+
+    <li>Call [[extend|<var>node</var>, <var>end offset</var>]] on the
+    [[contextobject]]'s [[selection]].
+
+    <li><span>Delete the selection</span>.
 
     <li>Abort these steps.
   </ol>
@@ -7438,11 +7503,20 @@
   <li>If <var>node</var> is an <span>inline node</span>, abort these steps.
 
   <li>If <var>node</var> has a [[child]] with [[index]] <var>offset</var> and
-  that [[child]] is a [[br]] or [[hr]] or [[img]], call
-  [[selcollapse|<var>node</var>, <var>offset</var>]] on the [[selection]].
-  Then <span>delete the contents</span> of the [[range]] with [[rangestart]]
-  (<var>node</var>, <var>offset</var>) and [[rangeend]] (<var>node</var>,
-  <var>offset</var> + 1) and abort these steps.
+  that [[child]] is a [[br]] or [[hr]] or [[img]], but is not a
+  <span>collapsed block prop</span>:
+
+  <ol>
+    <li>Call [[selcollapse|<var>node</var>, <var>offset</var>]] on the
+    [[contextobject]]'s [[selection]].
+
+    <li>Call [[extend|<var>node</var>, <var>offset</var> + 1]] on the
+    [[contextobject]]'s [[selection]].
+
+    <li><span>Delete the selection</span>.
+
+    <li>Abort these steps.
+  </ol>
 
   <li>
   <p class=comments>No special list-item behavior for forwardDelete here,
@@ -7451,6 +7525,10 @@
   <p>Let <var>end node</var> equal <var>node</var> and let <var>end
   offset</var> equal <var>offset</var>.
 
+  <li>If <var>end node</var> has a [[child]] with [[index]] <var>end
+  offset</var>, and that [[child]] is a <span>collapsed block prop</span>, add
+  one to <var>end offset</var>.
+
   <li>Repeat the following steps:
 
   <ol>
@@ -7458,7 +7536,7 @@
     <var>end offset</var> to one plus the [[index]] of <var>end node</var> and
     then set <var>end node</var> to its [[parent]].
 
-    <li>Otherwise, if <var>end node</var> has a an <span>editable</span>
+    <li>Otherwise, if <var>end node</var> has an <span>editable</span>
     <span>invisible</span> [[child]] with [[index]] <var>end offset</var>,
     remove it from <var>end node</var>.
 
@@ -7494,13 +7572,17 @@
   [[hr]] or [[br]]:
 
   <ol>
+    <li>Call [[selcollapse|<var>end node</var>, <var>end offset</var>]] on the
+    [[contextobject]]'s [[selection]].
+
+    <li>Call [[extend|<var>end node</var>, <var>end offset</var> + 1]] on the
+    [[contextobject]]'s [[selection]].
+
+    <li><span>Delete the selection</span>.
+
     <li>Call [[selcollapse|<var>node</var>, <var>offset</var>]] on the
     [[selection]].
 
-    <li><span>Delete the contents</span> of the [[range]] with [[rangeend]]
-    (<var>end node</var>, <var>end offset</var>) and [[rangeend]] (<var>end
-    node</var>, <var>end offset</var> + 1).
-
     <li>Abort these steps.
   </ol>
 
@@ -7520,9 +7602,13 @@
     <var>end offset</var> and set <var>end offset</var> to zero.
   </ol>
 
-  <li><span>Delete the contents</span> of the [[range]] with [[rangestart]]
-  (<var>node</var>, <var>offset</var>) and [[rangeend]] (<var>end node</var>,
-  <var>end offset</var>).
+  <li>Call [[selcollapse|<var>node</var>, <var>offset</var>]] on the
+  [[contextobject]]'s [[selection]].
+
+  <li>Call [[extend|<var>end node</var>, <var>end offset</var>]] on the
+  [[contextobject]]'s [[selection]].
+
+  <li><span>Delete the selection</span>.
 </ol>
 
 <!-- @} -->
@@ -7647,19 +7733,26 @@
 <p><span>Action</span>:
 
 <ol>
-  <li>Let <var>range</var> be the <span>active range</span>.
-
-  <li>While <var>range</var>'s [[startoffset]] is 0 and its [[startnode]]'s
-  [[parent]] is not null, set <var>range</var>'s [[rangestart]] to ([[parent]]
-  of [[startnode]], [[index]] of [[startnode]]).
-
-  <li>While <var>range</var>'s [[endoffset]] is the [[nodelength]] of its
-  [[endnode]], and its [[endnode]]'s [[parent]] is not null, set
-  <var>range</var>'s [[rangeend]] to ([[parent]] of [[endnode]], 1 + [[index]]
-  of [[startnode]]).
-
-  <li><span>Delete the contents</span> of <var>range</var>, with <var>block
-  merging</var> false.
+  <li>Let <var>start node</var>, <var>start offset</var>, <var>end node</var>,
+  and <var>end offset</var> be the <span>active range</span>'s [[rangestart]]
+  and [[rangeend]] [[bpnodes]] and [[bpoffsets]].
+
+  <li>While <var>start offset</var> is 0 and <var>start node</var>'s
+  [[parent]] is not null, set <var>start offset</var> to <var>start
+  node</var>'s [[index]], then set <var>start node</var> to its [[parent]].
+
+  <li>While <var>end offset</var> is <var>end node</var>'s [[nodelength]], and
+  <var>end node</var>'s [[parent]] is not null, set <var>end offset</var> to
+  one plus <var>end node</var>'s [[index]], then set <var>end node</var> to its
+  [[parent]].
+
+  <li>Call [[selcollapse|<var>start node</var>, <var>start offset</var>]] on
+  the [[contextobject]]'s [[selection]].
+
+  <li>Call [[extend|<var>end node</var>, <var>end offset</var>]] on the
+  [[contextobject]]'s [[selection]].
+
+  <li><span>Delete the selection</span>, with <var>block merging</var> false.
 
   <li>If the <span>active range</span>'s [[startnode]] is neither
   <span>editable</span> nor an <span>editing host</span>, abort these steps.
@@ -7669,19 +7762,22 @@
   text node, because that will leave an empty text node.
 
   <p>If the <span>active range</span>'s [[startnode]] is a [[text]] node and
-  its [[startoffset]] is zero, set the <span>active range</span>'s
-  [[rangestart]] and [[rangeend]] to ([[parent]] of [[startnode]], [[index]] of
-  [[startnode]]).
+  its [[startoffset]] is zero, call [[selcollapse|]] on the [[contextobject]]'s
+  [[selection]], with first argument the <span>active range</span>'s
+  [[startnode]]'s [[parent]] and second argument the <span>active
+  range</span>'s [[startnode]]'s [[index]].
 
   <li>If the <span>active range</span>'s [[startnode]] is a [[text]] node and
-  its [[startoffset]] is the [[length]] of its [[startnode]], set the
-  <span>active range</span>'s [[rangestart]] and [[rangeend]] to ([[parent]] of
-  [[startnode]], 1 + [[index]] of [[startnode]]).
+  its [[startoffset]] is the [[length]] of its [[startnode]], call
+  [[selcollapse|]] on the [[contextobject]]'s [[selection]], with first
+  argument the <span>active range</span>'s [[startnode]]'s [[parent]], and the
+  second argument one plus the <span>active range</span>'s [[startnode]]'s
+  [[index]].
 
   <li>Let <var>hr</var> be the result of calling [[createelement|"hr"]] on the
   [[contextobject]].
 
-  <li>Run [[insertnode|<var>hr</var>]] on <var>range</var>.
+  <li>Run [[insertnode|<var>hr</var>]] on the <span>active range</span>.
 
   <li>
   <p class=comments>IE9 and Chrome 13 dev seem to never break up any ancestors,
@@ -7694,12 +7790,9 @@
 
   <p><span>Fix disallowed ancestors</span> of <var>hr</var>.
 
-  <li>Let <var>selection</var> be the result of running [[getselection]] on the
-  [[contextobject]].
-
-  <li>Run [[selcollapse|]] on <var>selection</var>, with first argument equal
-  to the [[parent]] of <var>hr</var> and the second argument equal to one plus
-  the [[index]] of <var>hr</var>.
+  <li>Run [[selcollapse|]] on the [[contextobject]]'s [[selection]], with first
+  argument <var>hr</var>'s [[parent]] and the second argument equal to one plus
+  <var>hr</var>'s [[index]].
 </ol>
 
 <!-- @} -->
@@ -7754,7 +7847,7 @@
   true.
   </div>
 
-  <p><span>Delete the contents</span> of the <span>active range</span>.
+  <p><span>Delete the selection</span>.
 
   <li>If the <span>active range</span>'s [[startnode]] is neither
   <span>editable</span> nor an <span>editing host</span>, abort these steps.
@@ -7859,8 +7952,6 @@
   <p>If <var>value</var> is the empty string, abort these steps and do
   nothing.
 
-  <li>Let <var>range</var> be the <span>active range</span>.
-
   <li>
   <p class=comments>Firefox 7.0a2 seems to strip the wrapper or not depending
   on the exact positioning of the selection: &lt;b>{foo}&lt;/b> yes,
@@ -7870,8 +7961,9 @@
   the board because they might be meaningful: e.g., a background-color when the
   image is small or not fully opaque.
 
-  <p><span>Delete the contents</span> of <var>range</var>, with <var>strip
-  wrappers</var> false.
+  <p><span>Delete the selection</span>, with <var>strip wrappers</var> false.
+
+  <li>Let <var>range</var> be the <span>active range</span>.
 
   <li>If the <span>active range</span>'s [[startnode]] is neither
   <span>editable</span> nor an <span>editing host</span>, abort these steps.
@@ -7942,8 +8034,7 @@
   endpoints.  Chrome 14 dev strips wrappers but recreates any styles using new
   wrappers.  Opera 11.50 strips all wrappers.
 
-  <p><span>Delete the contents</span> of the <span>active range</span>, with
-  <var>strip wrappers</var> false.
+  <p><span>Delete the selection</span>, with <var>strip wrappers</var> false.
 
   <li>If the <span>active range</span>'s [[startnode]] is neither
   <span>editable</span> nor an <span>editing host</span>, abort these steps.
@@ -8073,7 +8164,7 @@
 <p><span>Action</span>:
 
 <ol>
-  <li><span>Delete the contents</span> of the <span>active range</span>.
+  <li><span>Delete the selection</span>.
 
   <li>If the <span>active range</span>'s [[startnode]] is neither
   <span>editable</span> nor an <span>editing host</span>, abort these steps.
@@ -8481,8 +8572,7 @@
   deletion at all).  This behavior seems to closely match IE9.
   </div>
 
-  <p><span>Delete the contents</span> of the <span>active range</span>, with
-  <var>strip wrappers</var> false.
+  <p><span>Delete the selection</span>, with <var>strip wrappers</var> false.
 
   <li>If the <span>active range</span>'s [[startnode]] is neither
   <span>editable</span> nor an <span>editing host</span>, abort these steps.
@@ -8887,10 +8977,10 @@
 <p class=comments>See comment for <a href=#the-copy-command>copy</a>.
 
 <p><span>Action</span>: The user agent must either <span>delete the
-contents</span> of the <span>active range</span> and then paste the clipboard's
-contents to the current cursor position, as though the user had requested it,
-or raise a [[SECURITY_ERR]] exception.  This specification does not define
-exactly how the clipboard is to be converted to HTML for pasting, but the <a
+selection</span> and then paste the clipboard's contents to the current cursor
+position, as though the user had requested it, or raise a [[SECURITY_ERR]]
+exception.  This specification does not define exactly how the clipboard is to
+be converted to HTML for pasting, but the <a
 href=http://dev.w3.org/2006/webapi/clipops/clipops.html>Clipboard API and
 events</a> specification might be useful.