Begin refactoring inline stuff
authorAryeh Gregor <AryehGregor+gitcommit@gmail.com>
Sun, 22 May 2011 13:38:03 -0600
changeset 157 257bb7b1473a
parent 156 654d90186940
child 158 719673d5b3e0
child 159 aeeb4b72f93e
child 160 a048a4793c97
Begin refactoring inline stuff
editcommands.html
implementation.js
source.html
--- a/editcommands.html	Sun May 22 13:02:16 2011 -0600
+++ b/editcommands.html	Sun May 22 13:38:03 2011 -0600
@@ -1536,8 +1536,8 @@
 
 
 <h3 id=setting-the-value-of-a-node><span class=secno>6.7 </span>Setting the value of a node</h3>
-<p>To <dfn id=set-the-value>set the value</dfn> of 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> <var title="">node</var> to <var title="">new
-value</var>:
+<p>To <dfn id=set-the-value>set the value</dfn> of a list <var title="">node list</var> 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> to
+<var title="">new value</var>:
 
 <div class=note>
 <p>The effect of this algorithm is to ensure that the node and all its
@@ -1608,14 +1608,8 @@
 <ol>
   <li>Let <var title="">command</var> be the current <a href=#command>command</a>.
 
-  <li>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#document>Document</a></code>, <a href=#set-the-value>set the value</a> of its
-  <code class=external data-anolis-spec=domcore><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#element>Element</a></code> <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> (if it has one) and abort this algorithm.
-
-  <li>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#documentfragment>DocumentFragment</a></code>, let <var title="">children</var> be
-  a list of 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>children</a>.  <a href=#set-the-value>Set the value</a> of each member of
-  <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>, then abort this algorithm.
-
-  <li>If <var title="">node</var> is not <a href=#editable>editable</a>:
+  <li>While there is some member of <var title="">node list</var> that is not
+  <a href=#editable>editable</a>:
   <!--
   IE9: Allows everything to be modified by execCommand(), regardless of whether
     it's editable.
@@ -1651,36 +1645,51 @@
   -->
 
   <ol>
-    <li>Let <var title="">children</var> be 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>children</a> of <var title="">node</var>.
-
-    <li><a href=#set-the-value>Set the value</a> of each member of <var title="">children</var>.
-
-    <li>Abort this algorithm.
+    <li>Let <var title="">node</var> be the first non-<a href=#editable>editable</a> member of
+    <var title="">node list</var>.
+
+    <li>Remove <var title="">node</var> from <var title="">node list</var>, and insert 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>children</a> in its former place.
   </ol>
 
-  <li>If <var title="">node</var> is an <code class=external data-anolis-spec=domcore><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#element>Element</a></code>:
+  <li>Let <var title="">sublists</var> be the <a href=#adjacent-sibling-runs>adjacent sibling runs</a> of
+  <var title="">node list</var>.
+
+  <li>For each <var title="">sublist</var> in <var title="">sublists</var>:
 
   <ol>
-    <li><a href=#clear-the-value>Clear the value</a> of <var title="">node</var>, and let <var title="">new
-    nodes</var> be the result.
-
-    <li>For each <var title="">new node</var> in <var title="">new nodes</var>,
-    <a href=#set-the-value>set the value</a> of <var title="">new node</var>.
-
-    <li>If <var title="">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 null, abort this algorithm.
+    <li>For each <var title="">node</var> in <var title="">sublist</var>:
+
+    <ol>
+      <li>If <var title="">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 null, continue with the next
+      <var title="">node</var>.
+      <!-- Maybe it got eaten by a previous iteration. -->
+
+      <li>If <var title="">node</var> is an <code class=external data-anolis-spec=domcore><a href=http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#element>Element</a></code>:
+
+      <ol>
+        <li><a href=#clear-the-value>Clear the value</a> of <var title="">node</var>, and let <var title="">new
+        nodes</var> be the result.
+
+        <li><a href=#set-the-value>Set the value</a> of <var title="">new nodes</var>.
+
+        <li>If <var title="">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 null, continue with the next
+        <var title="">node</var>.
+      </ol>
+
+      <li><a href=#push-down-values>Push down values</a> on <var title="">node</var>.
+
+      <li><a href=#force-the-value>Force the value</a> of <var title="">node</var>.
+
+      <li>Let <var title="">children</var> be 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>children</a> of <var title="">node</var>.
+
+      <li><a href=#set-the-value>Set the value</a> of <var title="">children</var>.
+
+      <p class=note>Styling a node involves clearing its styles, which can
+      remove it from the tree.  Implementers should be careful to compute the
+      list of children in full before they begin styling.
+    </ol>
   </ol>
-
-  <li><a href=#push-down-values>Push down values</a> on <var title="">node</var>.
-
-  <li><a href=#force-the-value>Force the value</a> of <var title="">node</var>.
-
-  <li>Let <var title="">children</var> be 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>children</a> of <var title="">node</var>.
-
-  <li><a href=#set-the-value>Set the value</a> of each member of <var title="">children</var>.
-
-  <p class=note>Styling a node involves clearing its styles, which can remove
-  it from the tree.  Implementers should be careful to compute the list of
-  children in full before they begin styling.
 </ol>
 
 
@@ -1735,8 +1744,8 @@
 nothing if the selection is empty.  Why strikethrough?  I don't know. -->
 
 <p><a href=#action>Action</a>: <a href=#decompose>Decompose</a> the <a href=#active-range>active range</a>.
-If the <a href=#state>state</a> is then false, <a href=#set-the-value>set the value</a> of each
-returned <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> to "bold", otherwise <a href=#set-the-value>set the value</a> to "normal".
+If the <a href=#state>state</a> is then false, <a href=#set-the-value>set the value</a> of the
+result to "bold", otherwise <a href=#set-the-value>set the value</a> to "normal".
 
 <p><a href=#state>State</a>: True if every <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 that
 is <a href=#effectively-contained>effectively contained</a> in the <a href=#active-range>active range</a> has
@@ -1819,7 +1828,7 @@
 <h3 id=the-fontname-command><span class=secno>6.11 </span><dfn>The <code title="">fontName</code> command</dfn></h3>
 
 <p><a href=#action>Action</a>: <a href=#decompose>Decompose</a> the <a href=#active-range>active range</a>,
-then <a href=#set-the-value>set the value</a> of each returned <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> to <var title="">value</var>.
+then <a href=#set-the-value>set the value</a> of the result to <var title="">value</var>.
 <!-- UAs differ a bit in the details here:
 
 IE 9 RC: Empty string sets <font face="">
@@ -1966,7 +1975,7 @@
   sizes, I don't think.
 
   <li><a href=#decompose>Decompose</a> the <a href=#active-range>active range</a>, then <a href=#set-the-value>set the
-  value</a> of each returned <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> to <var title="">value</var>.
+  value</a> of the result to <var title="">value</var>.
 </ol>
 
 <p><a href=#relevant-css-property>Relevant CSS property</a>: "font-size"
@@ -2041,7 +2050,7 @@
   confuse the algorithm, and doesn't seem very useful anyway. -->
 
   <li><a href=#decompose>Decompose</a> the <a href=#active-range>active range</a>, then <a href=#set-the-value>set the
-  value</a> of each returned <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> to <var title="">value</var>.
+  value</a> of the result to <var title="">value</var>.
 </ol>
 
 <p><a href=#state>State</a>: Always false.
@@ -2088,7 +2097,7 @@
   algorithm, so ban it for now anyway. -->
 
   <li><a href=#decompose>Decompose</a> the <a href=#active-range>active range</a>, then <a href=#set-the-value>set the
-  value</a> of each returned <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> to <var title="">value</var>.
+  value</a> of the result to <var title="">value</var>.
 </ol>
 
 <p><a href=#state>State</a>: Always false.
@@ -2172,9 +2181,8 @@
 <h3 id=the-italic-command><span class=secno>6.17 </span><dfn>The <code title="">italic</code> command</dfn></h3>
 
 <p><a href=#action>Action</a>: <a href=#decompose>Decompose</a> the <a href=#active-range>active range</a>.
-If the <a href=#state>state</a> is then false, <a href=#set-the-value>set the value</a> of each
-returned <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> to "italic", otherwise <a href=#set-the-value>set the value</a> to
-"normal".
+If the <a href=#state>state</a> is then false, <a href=#set-the-value>set the value</a> of the
+result to "italic", otherwise <a href=#set-the-value>set the value</a> to "normal".
 
 <p><a href=#state>State</a>: True if every <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 that
 is <a href=#effectively-contained>effectively contained</a> in the <a href=#active-range>active range</a> has
@@ -2281,7 +2289,7 @@
 
   <li>For each of the entries in the following table, in the given order:
   <a href=#decompose>decompose</a> the <a href=#active-range>active range</a> again; then <a href=#set-the-value>set
-  the value</a> of the resulting <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>, with <var title="">command</var> and
+  the value</a> of the result, with <var title="">command</var> and
   <var title="">new value</var> as given.
 
   <p class=XXX>This has no relationship to what browsers actually do, although
@@ -2309,9 +2317,8 @@
 <h3 id=the-strikethrough-command><span class=secno>6.19 </span><dfn>The <code title="">strikethrough</code> command</dfn></h3>
 
 <p><a href=#action>Action</a>: <a href=#decompose>Decompose</a> the <a href=#active-range>active range</a>.
-If the <a href=#state>state</a> is then false, <a href=#set-the-value>set the value</a> of each
-returned <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> to "line-through", otherwise <a href=#set-the-value>set the value</a> to
-null.
+If the <a href=#state>state</a> is then false, <a href=#set-the-value>set the value</a> of the
+result to "line-through", otherwise <a href=#set-the-value>set the value</a> to null.
 
 <p class=XXX>Has all the same problems as <a href=#the-underline-command>the <code title="">underline</code> command</a>.
 
@@ -2332,12 +2339,10 @@
   
   <li>Let <var title="">state</var> be the <a href=#state>state</a>.
   
-  <li><a href=#set-the-value>Set the value</a> of each <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> in <var title="">node list</var> to
-  "baseline".
+  <li><a href=#set-the-value>Set the value</a> of <var title="">node list</var> to "baseline".
 
   <li>If <var title="">state</var> is false, <a href=#decompose>decompose</a> the <a href=#active-range>active
-  range</a> again and <a href=#set-the-value>set the value</a> of each returned <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>
-  to "sub".
+  range</a> again and <a href=#set-the-value>set the value</a> of the result to "sub".
 </ol>
 
 <p><a href=#state>State</a>: True if every <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 that
@@ -2357,12 +2362,10 @@
   
   <li>Let <var title="">state</var> be the <a href=#state>state</a>.
   
-  <li><a href=#set-the-value>Set the value</a> of each <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> in <var title="">node list</var> to
-  "baseline".
+  <li><a href=#set-the-value>Set the value</a> of <var title="">node list</var> to "baseline".
 
   <li>If <var title="">state</var> is false, <a href=#decompose>decompose</a> the <a href=#active-range>active
-  range</a> again and <a href=#set-the-value>set the value</a> of each returned <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>
-  to "super".
+  range</a> again and <a href=#set-the-value>set the value</a> of the result to "super".
 </ol>
 
 <p><a href=#state>State</a>: True if every <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 that
@@ -2375,8 +2378,8 @@
 <h3 id=the-underline-command><span class=secno>6.22 </span><dfn>The <code title="">underline</code> command</dfn></h3>
 
 <p><a href=#action>Action</a>: <a href=#decompose>Decompose</a> the <a href=#active-range>active range</a>.
-If the <a href=#state>state</a> is then false, <a href=#set-the-value>set the value</a> of each
-returned <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> to "underline", otherwise <a href=#set-the-value>set the value</a> to null.
+If the <a href=#state>state</a> is then false, <a href=#set-the-value>set the value</a> of the
+result to "underline", otherwise <a href=#set-the-value>set the value</a> to null.
 
 <div class=XXX>
 <p>There are a lot of problems with underline color and thickness, because
--- a/implementation.js	Sun May 22 13:02:16 2011 -0600
+++ b/implementation.js	Sun May 22 13:38:03 2011 -0600
@@ -2184,81 +2184,68 @@
 	}
 }
 
-function setNodeValue(node, command, newValue) {
-	// "If node is a Document, set the value of its Element child (if it has
-	// one) and abort this algorithm."
-	if (node.nodeType == Node.DOCUMENT_NODE) {
-		for (var i = 0; i < node.childNodes.length; i++) {
-			if (node.childNodes[i].nodeType == Node.ELEMENT_NODE) {
-				setNodeValue(node.childNodes[i], command, newValue);
+function setNodeValue(nodeList, command, newValue) {
+	// "While there is some member of node list that is not editable:"
+	while (true) {
+		// "Let node be the first non-editable member of node list."
+		for (var i = 0; i < nodeList.length; i++) {
+			if (!isEditable(nodeList[i])) {
 				break;
 			}
 		}
-		return;
-	}
-
-	// "If node is a DocumentFragment, let children be a list of its children.
-	// Set the value of each member of children, then abort this algorithm."
-	if (node.nodeType == Node.DOCUMENT_FRAGMENT_NODE) {
-		var children = [];
-		for (var i = 0; i < node.childNodes.length; i++) {
-			children.push(node.childNodes[i]);
-		}
-		for (var i = 0; i < children.length; i++) {
-			setNodeValue(children[i], command, newValue);
-		}
-		return;
-	}
-
-	// "If node's parent is null, or if node is a DocumentType, abort this
-	// algorithm."
-	if (!node.parentNode || node.nodeType == Node.DOCUMENT_TYPE_NODE) {
-		return;
-	}
-
-	// "If node is not editable:"
-	if (!isEditable(node)) {
-		// "Let children be the children of node."
-		var children = Array.prototype.slice.call(node.childNodes);
-
-		// "Set the value of each member of children."
-		for (var i = 0; i < children.length; i++) {
-			setNodeValue(children[i], command, newValue);
+		if (i == nodeList.length) {
+			break;
 		}
 
-		// "Abort this algorithm."
-		return;
+		// "Remove node from node list, and insert its children in its former
+		// place."
+		nodeList = nodeList.slice(0, i)
+			.concat([].slice.call(nodeList[i].childNodes))
+			.concat(nodeList.slice(i + 1));
 	}
 
-	// "If node is an Element:"
-	if (node.nodeType == Node.ELEMENT_NODE) {
-		// "Clear the value of node, and let new nodes be the result."
-		var newNodes = clearValue(node, command);
-
-		// "For each new node in new nodes, set the value of new node, with the
-		// same inputs as this invocation of the algorithm."
-		for (var i = 0; i < newNodes.length; i++) {
-			setNodeValue(newNodes[i], command, newValue);
+	// "Let sublists be the adjacent sibling runs of node list."
+	var sublists = getAdjacentSiblingRuns(nodeList);
+
+	// "For each sublist in sublists:"
+	for (var i = 0; i < sublists.length; i++) {
+		var sublist = sublists[i];
+
+		// "For each node in sublist:"
+		for (var j = 0; j < sublist.length; j++) {
+			var node = sublist[j];
+
+			// "If node's parent is null, continue with the next node."
+			if (!node.parentNode) {
+				continue;
+			}
+
+			// "If node is an Element:"
+			if (node.nodeType == Node.ELEMENT_NODE) {
+				// "Clear the value of node, and let new nodes be the result."
+				var newNodes = clearValue(node, command);
+
+				// "Set the value of new nodes."
+				setNodeValue(newNodes, command, newValue);
+
+				// "If node's parent is null, continue with the next node."
+				if (!node.parentNode) {
+					continue;
+				}
+			}
+
+			// "Push down values on node."
+			pushDownValues(node, command, newValue);
+
+			// "Force the value of node."
+			forceValue(node, command, newValue);
+
+			// "Let children be the children of node."
+			var children = [].slice.call(node.childNodes);
+
+			// "Set the value of children."
+			setNodeValue(children, command, newValue);
 		}
-
-		// "If node's parent is null, abort this algorithm."
-		if (!node.parentNode) {
-			return;
-		}
-	}
-
-	// "Push down values on node."
-	pushDownValues(node, command, newValue);
-
-	// "Force the value of node."
-	forceValue(node, command, newValue);
-
-	// "Let children be the children of node."
-	var children = Array.prototype.slice.call(node.childNodes);
-
-	// "Set the value of each member of children."
-	for (var i = 0; i < children.length; i++) {
-		setNodeValue(children[i], command, newValue);
 	}
 }
 
@@ -2305,9 +2292,7 @@
 		// "normal". Otherwise, set their value with new value "bold"."
 		var nodeList = decomposeRange(range);
 		var newValue = getState("bold", range) ? "normal" : "bold";
-		for (var i = 0; i < nodeList.length; i++) {
-			setNodeValue(nodeList[i], command, newValue);
-		}
+		setNodeValue(nodeList, command, newValue);
 		break;
 
 		case "createlink":
@@ -2334,18 +2319,15 @@
 		}
 
 		// "Set the value of each node in node list to value."
-		for (var i = 0; i < nodeList.length; i++) {
-			setNodeValue(nodeList[i], command, value);
-		}
+		setNodeValue(nodeList, command, value);
+
 		break;
 
 		case "fontname":
 		// "Decompose the range, then set the value of each returned node with
 		// new value equal to value."
 		var nodeList = decomposeRange(range);
-		for (var i = 0; i < nodeList.length; i++) {
-			setNodeValue(nodeList[i], command, value);
-		}
+		setNodeValue(nodeList, command, value);
 		break;
 
 		case "fontsize":
@@ -2433,9 +2415,7 @@
 		// "Decompose the range, then set the value of each returned node to
 		// value."
 		var nodeList = decomposeRange(range);
-		for (var i = 0; i < nodeList.length; i++) {
-			setNodeValue(nodeList[i], command, value);
-		}
+		setNodeValue(nodeList, command, value);
 		break;
 
 		case "forecolor":
@@ -2461,9 +2441,7 @@
 		// "Decompose the range, then set the value of each returned node to
 		// value."
 		var nodeList = decomposeRange(range);
-		for (var i = 0; i < nodeList.length; i++) {
-			setNodeValue(nodeList[i], command, value);
-		}
+		setNodeValue(nodeList, command, value);
 		break;
 
 		case "indent":
@@ -2855,9 +2833,7 @@
 		// "normal". Otherwise, set their value with new value "italic"."
 		var nodeList = decomposeRange(range);
 		var newValue = getState("italic", range) ? "normal" : "italic";
-		for (var i = 0; i < nodeList.length; i++) {
-			setNodeValue(nodeList[i], command, newValue);
-		}
+		setNodeValue(nodeList, command, newValue);
 		break;
 
 		case "outdent":
@@ -3028,9 +3004,7 @@
 		};
 		for (var command in table) {
 			var nodeList = decomposeRange(range);
-			for (var i = 0; i < nodeList.length; i++) {
-				setNodeValue(nodeList[i], command, table[command]);
-			}
+			setNodeValue(nodeList, command, table[command]);
 		}
 		break;
 
@@ -3040,9 +3014,7 @@
 		// set their value to "line-through"."
 		var nodeList = decomposeRange(range);
 		var newValue = getState(command, range) ? null : "line-through";
-		for (var i = 0; i < nodeList.length; i++) {
-			setNodeValue(nodeList[i], command, newValue);
-		}
+		setNodeValue(nodeList, command, newValue);
 		break;
 
 		case "stylewithcss":
@@ -3059,17 +3031,11 @@
 		// node with new value "sub"."
 		var nodeList = decomposeRange(range);
 		if (getState(command, range)) {
-			for (var i = 0; i < nodeList.length; i++) {
-				setNodeValue(nodeList[i], command, "baseline");
-			}
+			setNodeValue(nodeList, command, "baseline");
 		} else {
-			for (var i = 0; i < nodeList.length; i++) {
-				setNodeValue(nodeList[i], command, "baseline");
-			}
+			setNodeValue(nodeList, command, "baseline");
 			var nodeList = decomposeRange(range);
-			for (var i = 0; i < nodeList.length; i++) {
-				setNodeValue(nodeList[i], command, "sub");
-			}
+			setNodeValue(nodeList, command, "sub");
 		}
 		break;
 
@@ -3081,17 +3047,11 @@
 		// node with new value "super"."
 		var nodeList = decomposeRange(range);
 		if (getState(command, range)) {
-			for (var i = 0; i < nodeList.length; i++) {
-				setNodeValue(nodeList[i], command, "baseline");
-			}
+			setNodeValue(nodeList, command, "baseline");
 		} else {
-			for (var i = 0; i < nodeList.length; i++) {
-				setNodeValue(nodeList[i], command, "baseline");
-			}
+			setNodeValue(nodeList, command, "baseline");
 			var nodeList = decomposeRange(range);
-			for (var i = 0; i < nodeList.length; i++) {
-				setNodeValue(nodeList[i], command, "super");
-			}
+			setNodeValue(nodeList, command, "super");
 		}
 		break;
 
@@ -3101,9 +3061,7 @@
 		// set their value to "underline"."
 		var nodeList = decomposeRange(range);
 		var newValue = getState("underline", range) ? null : "underline";
-		for (var i = 0; i < nodeList.length; i++) {
-			setNodeValue(nodeList[i], command, newValue);
-		}
+		setNodeValue(nodeList, command, newValue);
 		break;
 
 		case "unlink":
--- a/source.html	Sun May 22 13:02:16 2011 -0600
+++ b/source.html	Sun May 22 13:38:03 2011 -0600
@@ -1526,8 +1526,8 @@
 
 
 <h3>Setting the value of a node</h3>
-<p>To <dfn>set the value</dfn> of a [[node]] <var>node</var> to <var>new
-value</var>:
+<p>To <dfn>set the value</dfn> of a list <var>node list</var> of [[nodes]] to
+<var>new value</var>:
 
 <div class=note>
 <p>The effect of this algorithm is to ensure that the node and all its
@@ -1599,14 +1599,8 @@
 <ol>
   <li>Let <var>command</var> be the current <span>command</span>.
 
-  <li>If <var>node</var> is a [[document]], <span>set the value</span> of its
-  [[element]] [[child]] (if it has one) and abort this algorithm.
-
-  <li>If <var>node</var> is a [[documentfragment]], let <var>children</var> be
-  a list of its [[children]].  <span>Set the value</span> of each member of
-  [[children]], then abort this algorithm.
-
-  <li>If <var>node</var> is not <span>editable</span>:
+  <li>While there is some member of <var>node list</var> that is not
+  <span>editable</span>:
   <!--
   IE9: Allows everything to be modified by execCommand(), regardless of whether
     it's editable.
@@ -1642,36 +1636,51 @@
   -->
 
   <ol>
-    <li>Let <var>children</var> be the [[children]] of <var>node</var>.
-
-    <li><span>Set the value</span> of each member of <var>children</var>.
-
-    <li>Abort this algorithm.
+    <li>Let <var>node</var> be the first non-<span>editable</span> member of
+    <var>node list</var>.
+
+    <li>Remove <var>node</var> from <var>node list</var>, and insert its
+    [[children]] in its former place.
   </ol>
 
-  <li>If <var>node</var> is an [[element]]:
+  <li>Let <var>sublists</var> be the <span>adjacent sibling runs</span> of
+  <var>node list</var>.
+
+  <li>For each <var>sublist</var> in <var>sublists</var>:
 
   <ol>
-    <li><span>Clear the value</span> of <var>node</var>, and let <var>new
-    nodes</var> be the result.
-
-    <li>For each <var>new node</var> in <var>new nodes</var>,
-    <span>set the value</span> of <var>new node</var>.
-
-    <li>If <var>node</var>'s [[parent]] is null, abort this algorithm.
+    <li>For each <var>node</var> in <var>sublist</var>:
+
+    <ol>
+      <li>If <var>node</var>'s [[parent]] is null, continue with the next
+      <var>node</var>.
+      <!-- Maybe it got eaten by a previous iteration. -->
+
+      <li>If <var>node</var> is an [[element]]:
+
+      <ol>
+        <li><span>Clear the value</span> of <var>node</var>, and let <var>new
+        nodes</var> be the result.
+
+        <li><span>Set the value</span> of <var>new nodes</var>.
+
+        <li>If <var>node</var>'s [[parent]] is null, continue with the next
+        <var>node</var>.
+      </ol>
+
+      <li><span>Push down values</span> on <var>node</var>.
+
+      <li><span>Force the value</span> of <var>node</var>.
+
+      <li>Let <var>children</var> be the [[children]] of <var>node</var>.
+
+      <li><span>Set the value</span> of <var>children</var>.
+
+      <p class=note>Styling a node involves clearing its styles, which can
+      remove it from the tree.  Implementers should be careful to compute the
+      list of children in full before they begin styling.
+    </ol>
   </ol>
-
-  <li><span>Push down values</span> on <var>node</var>.
-
-  <li><span>Force the value</span> of <var>node</var>.
-
-  <li>Let <var>children</var> be the [[children]] of <var>node</var>.
-
-  <li><span>Set the value</span> of each member of <var>children</var>.
-
-  <p class=note>Styling a node involves clearing its styles, which can remove
-  it from the tree.  Implementers should be careful to compute the list of
-  children in full before they begin styling.
 </ol>
 
 
@@ -1726,8 +1735,8 @@
 nothing if the selection is empty.  Why strikethrough?  I don't know. -->
 
 <p><span>Action</span>: <span>Decompose</span> the <span>active range</span>.
-If the <span>state</span> is then false, <span>set the value</span> of each
-returned [[node]] to "bold", otherwise <span>set the value</span> to "normal".
+If the <span>state</span> is then false, <span>set the value</span> of the
+result to "bold", otherwise <span>set the value</span> to "normal".
 
 <p><span>State</span>: True if every <span>editable</span> [[text]] node that
 is <span>effectively contained</span> in the <span>active range</span> has
@@ -1810,7 +1819,7 @@
 <h3><dfn>The <code title>fontName</code> command</dfn></h3>
 
 <p><span>Action</span>: <span>Decompose</span> the <span>active range</span>,
-then <span>set the value</span> of each returned [[node]] to <var>value</var>.
+then <span>set the value</span> of the result to <var>value</var>.
 <!-- UAs differ a bit in the details here:
 
 IE 9 RC: Empty string sets <font face="">
@@ -1957,7 +1966,7 @@
   sizes, I don't think.
 
   <li><span>Decompose</span> the <span>active range</span>, then <span>set the
-  value</span> of each returned [[node]] to <var>value</var>.
+  value</span> of the result to <var>value</var>.
 </ol>
 
 <p><span>Relevant CSS property</span>: "font-size"
@@ -2032,7 +2041,7 @@
   confuse the algorithm, and doesn't seem very useful anyway. -->
 
   <li><span>Decompose</span> the <span>active range</span>, then <span>set the
-  value</span> of each returned [[node]] to <var>value</var>.
+  value</span> of the result to <var>value</var>.
 </ol>
 
 <p><span>State</span>: Always false.
@@ -2079,7 +2088,7 @@
   algorithm, so ban it for now anyway. -->
 
   <li><span>Decompose</span> the <span>active range</span>, then <span>set the
-  value</span> of each returned [[node]] to <var>value</var>.
+  value</span> of the result to <var>value</var>.
 </ol>
 
 <p><span>State</span>: Always false.
@@ -2176,9 +2185,8 @@
 <h3><dfn>The <code title>italic</code> command</dfn></h3>
 
 <p><span>Action</span>: <span>Decompose</span> the <span>active range</span>.
-If the <span>state</span> is then false, <span>set the value</span> of each
-returned [[node]] to "italic", otherwise <span>set the value</span> to
-"normal".
+If the <span>state</span> is then false, <span>set the value</span> of the
+result to "italic", otherwise <span>set the value</span> to "normal".
 
 <p><span>State</span>: True if every <span>editable</span> [[text]] node that
 is <span>effectively contained</span> in the <span>active range</span> has
@@ -2285,7 +2293,7 @@
 
   <li>For each of the entries in the following table, in the given order:
   <span>decompose</span> the <span>active range</span> again; then <span>set
-  the value</span> of the resulting [[nodes]], with <var>command</var> and
+  the value</span> of the result, with <var>command</var> and
   <var>new value</var> as given.
 
   <p class=XXX>This has no relationship to what browsers actually do, although
@@ -2313,9 +2321,8 @@
 <h3><dfn>The <code title>strikethrough</code> command</dfn></h3>
 
 <p><span>Action</span>: <span>Decompose</span> the <span>active range</span>.
-If the <span>state</span> is then false, <span>set the value</span> of each
-returned [[node]] to "line-through", otherwise <span>set the value</span> to
-null.
+If the <span>state</span> is then false, <span>set the value</span> of the
+result to "line-through", otherwise <span>set the value</span> to null.
 
 <p class=XXX>Has all the same problems as <span>the <code
 title>underline</code> command</span>.
@@ -2337,12 +2344,10 @@
   
   <li>Let <var>state</var> be the <span>state</span>.
   
-  <li><span>Set the value</span> of each [[node]] in <var>node list</var> to
-  "baseline".
+  <li><span>Set the value</span> of <var>node list</var> to "baseline".
 
   <li>If <var>state</var> is false, <span>decompose</span> the <span>active
-  range</span> again and <span>set the value</span> of each returned [[node]]
-  to "sub".
+  range</span> again and <span>set the value</span> of the result to "sub".
 </ol>
 
 <p><span>State</span>: True if every <span>editable</span> [[text]] node that
@@ -2362,12 +2367,10 @@
   
   <li>Let <var>state</var> be the <span>state</span>.
   
-  <li><span>Set the value</span> of each [[node]] in <var>node list</var> to
-  "baseline".
+  <li><span>Set the value</span> of <var>node list</var> to "baseline".
 
   <li>If <var>state</var> is false, <span>decompose</span> the <span>active
-  range</span> again and <span>set the value</span> of each returned [[node]]
-  to "super".
+  range</span> again and <span>set the value</span> of the result to "super".
 </ol>
 
 <p><span>State</span>: True if every <span>editable</span> [[text]] node that
@@ -2380,8 +2383,8 @@
 <h3><dfn>The <code title>underline</code> command</dfn></h3>
 
 <p><span>Action</span>: <span>Decompose</span> the <span>active range</span>.
-If the <span>state</span> is then false, <span>set the value</span> of each
-returned [[node]] to "underline", otherwise <span>set the value</span> to null.
+If the <span>state</span> is then false, <span>set the value</span> of the
+result to "underline", otherwise <span>set the value</span> to null.
 
 <div class=XXX>
 <p>There are a lot of problems with underline color and thickness, because