Bug 1213589 part.5 Redesign the rules to create range in ContentEventHandler::SetRangeFromFlatTextOffset() r=smaug
authorMasayuki Nakano <masayuki@d-toybox.com>
Wed, 02 Dec 2015 13:20:00 +0900
changeset 275084 afae79e8f7d2cbd4a0cdd18d8309053d4d8c8173
parent 275083 b7191f6c21ae13a810b89041da3adc4d5c153fc3
child 275085 23e3c6bf330f3e77834c2c08f40642a9731885ad
push id68758
push usermasayuki@d-toybox.com
push dateWed, 02 Dec 2015 04:20:12 +0000
treeherdermozilla-inbound@4434a5a96375 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs1213589
milestone45.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1213589 part.5 Redesign the rules to create range in ContentEventHandler::SetRangeFromFlatTextOffset() r=smaug
dom/events/ContentEventHandler.cpp
dom/events/ContentEventHandler.h
widget/tests/window_composition_text_querycontent.xul
--- a/dom/events/ContentEventHandler.cpp
+++ b/dom/events/ContentEventHandler.cpp
@@ -35,16 +35,66 @@ namespace mozilla {
 
 using namespace dom;
 using namespace widget;
 
 /******************************************************************/
 /* ContentEventHandler                                            */
 /******************************************************************/
 
+// NOTE
+//
+// ContentEventHandler *creates* ranges as following rules:
+// 1. Start of range:
+//   1.1. Cases: [textNode or text[Node or textNode[
+//        When text node is start of a range, start node is the text node and
+//        start offset is any number between 0 and the length of the text.
+//   1.2. Case: [<element>
+//        When before an element node is start of a range, start node is parent
+//        of the element and start offset is the element's index in the parent.
+//   1.3. Case: <element/>[
+//        When after an empty element node is start of a range, start node is
+//        parent of the element and start offset is the element's index in the
+//        parent + 1.
+//   1.4. Case: <element>[
+//        When start of a non-empty element is start of a range, start node is
+//        the element and start offset is 0.
+//   1.5. Case: [</root>
+//        When start of a range is out of bounds, start node is the root node
+//        and start offset is number of the children.
+// 2. End of range:
+//   2.1. Cases: ]textNode or text]Node or textNode]
+//        When a text node is end of a range, end node is the text node and
+//        end offset is any number between 0 and the length of the text.
+//   2.2. Case: ]<element>
+//        When before an element node (meaning before the open tag of the
+//        element) is end of a range, end node is previous node causing text.
+//        Note that this case shouldn't be handled directly.  If rule 2.1 and
+//        2.3 are handled correctly, the loop with nsContentIterator shouldn't
+//        reach the element node since the loop should've finished already at
+//        handling the last node which caused some text.
+//   2.3. Case: </element>]
+//        When after an element node is end of a range, end node is parent of
+//        the element node and end offset is the element's index in the parent
+//        + 1.
+//   2.4. Case: ]</root>
+//        When end of a range is out of bounds, end node is the root node and
+//        end offset is number of the children.
+//
+// ContentEventHandler *treats* ranges as following additional rules:
+// 1. When the start node is an element node which doesn't have children,
+//    it includes a line break caused before itself (i.e., includes its open
+//    tag).  For example, if start position is { <br>, 0 }, the line break
+//    caused by <br> should be included into the flatten text.
+// 2. When the end node is an element node which doesn't have children,
+//    it includes the end (i.e., includes its close tag except empty element).
+//    Although, currently, any close tags don't cause line break, this also
+//    includes its open tag.  For example, if end position is { <br>, 0 }, the
+//    line break caused by the <br> should be included into the flatten text.
+
 ContentEventHandler::ContentEventHandler(nsPresContext* aPresContext)
   : mPresContext(aPresContext)
   , mPresShell(aPresContext->GetPresShell())
   , mSelection(nullptr)
   , mFirstSelectedRange(nullptr)
   , mRootContent(nullptr)
 {
 }
@@ -409,16 +459,20 @@ static uint32_t ConvertToXPOffset(nsICon
 
 nsresult
 ContentEventHandler::GenerateFlatTextContent(nsRange* aRange,
                                              nsAFlatString& aString,
                                              LineBreakType aLineBreakType)
 {
   NS_ASSERTION(aString.IsEmpty(), "aString must be empty string");
 
+  if (aRange->Collapsed()) {
+    return NS_OK;
+  }
+
   nsINode* startNode = aRange->GetStartParent();
   nsINode* endNode = aRange->GetEndParent();
   if (NS_WARN_IF(!startNode) || NS_WARN_IF(!endNode)) {
     return NS_ERROR_FAILURE;
   }
 
   if (startNode == endNode && startNode->IsNodeOfType(nsINode::eTEXT)) {
     nsIContent* content = startNode->AsContent();
@@ -575,16 +629,20 @@ ContentEventHandler::AppendFontRanges(Fo
 /* static */ nsresult
 ContentEventHandler::GenerateFlatFontRanges(nsRange* aRange,
                                             FontRangeArray& aFontRanges,
                                             uint32_t& aLength,
                                             LineBreakType aLineBreakType)
 {
   MOZ_ASSERT(aFontRanges.IsEmpty(), "aRanges must be empty array");
 
+  if (aRange->Collapsed()) {
+    return NS_OK;
+  }
+
   nsINode* startNode = aRange->GetStartParent();
   nsINode* endNode = aRange->GetEndParent();
   if (NS_WARN_IF(!startNode) || NS_WARN_IF(!endNode)) {
     return NS_ERROR_FAILURE;
   }
 
   // baseOffset is the flattened offset of each content node.
   int32_t baseOffset = 0;
@@ -691,130 +749,197 @@ ContentEventHandler::SetRangeFromFlatTex
                                                 LineBreakType aLineBreakType,
                                                 bool aExpandToClusterBoundaries,
                                                 uint32_t* aNewOffset)
 {
   if (aNewOffset) {
     *aNewOffset = aOffset;
   }
 
+  // Special case like <br contenteditable>
+  if (!mRootContent->HasChildren()) {
+    nsresult rv = aRange->SetStart(mRootContent, 0);
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      return rv;
+    }
+    rv = aRange->SetEnd(mRootContent, 0);
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      return rv;
+    }
+  }
+
   nsCOMPtr<nsIContentIterator> iter = NS_NewPreContentIterator();
   nsresult rv = iter->Init(mRootContent);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   uint32_t offset = 0;
   uint32_t endOffset = aOffset + aLength;
   bool startSet = false;
   for (; !iter->IsDone(); iter->Next()) {
     nsINode* node = iter->GetCurrentNode();
     if (NS_WARN_IF(!node)) {
       break;
     }
-    if (!node->IsContent()) {
+    // FYI: mRootContent shouldn't cause any text. So, we can skip it simply.
+    if (node == mRootContent || !node->IsContent()) {
       continue;
     }
     nsIContent* content = node->AsContent();
 
     uint32_t textLength =
       content->IsNodeOfType(nsINode::eTEXT) ?
         GetTextLength(content, aLineBreakType) :
         (IsContentBR(content) ? GetBRLength(aLineBreakType) : 0);
     if (!textLength) {
       continue;
     }
 
-    if (offset <= aOffset && aOffset < offset + textLength) {
-      uint32_t xpOffset;
-      if (!content->IsNodeOfType(nsINode::eTEXT)) {
-        xpOffset = 0;
-      } else {
-        xpOffset = aOffset - offset;
+    // When the start offset is in between accumulated offset and the last
+    // offset of the node, the node is the start node of the range.
+    if (!startSet && aOffset <= offset + textLength) {
+      nsINode* startNode = nullptr;
+      int32_t startNodeOffset = -1;
+      if (content->IsNodeOfType(nsINode::eTEXT)) {
+        // Rule #1.1: [textNode or text[Node or textNode[
+        uint32_t xpOffset = aOffset - offset;
         if (aLineBreakType == LINE_BREAK_TYPE_NATIVE) {
           xpOffset = ConvertToXPOffset(content, xpOffset);
         }
 
         if (aExpandToClusterBoundaries) {
           uint32_t oldXPOffset = xpOffset;
           rv = ExpandToClusterBoundary(content, false, &xpOffset);
           if (NS_WARN_IF(NS_FAILED(rv))) {
             return rv;
           }
           if (aNewOffset) {
             // This is correct since a cluster shouldn't include line break.
             *aNewOffset -= (oldXPOffset - xpOffset);
           }
         }
+        startNode = content;
+        startNodeOffset = static_cast<int32_t>(xpOffset);
+      } else if (aOffset < offset + textLength) {
+        // Rule #1.2 [<element>
+        startNode = content->GetParent();
+        if (NS_WARN_IF(!startNode)) {
+          return NS_ERROR_FAILURE;
+        }
+        startNodeOffset = startNode->IndexOf(content);
+        if (NS_WARN_IF(startNodeOffset == -1)) {
+          // The content is being removed from the parent!
+          return NS_ERROR_FAILURE;
+        }
+      } else if (!content->HasChildren()) {
+        // Rule #1.3: <element/>[
+        startNode = content->GetParent();
+        if (NS_WARN_IF(!startNode)) {
+          return NS_ERROR_FAILURE;
+        }
+        startNodeOffset = startNode->IndexOf(content) + 1;
+        if (NS_WARN_IF(startNodeOffset == 0)) {
+          // The content is being removed from the parent!
+          return NS_ERROR_FAILURE;
+        }
+      } else {
+        // Rule #1.4: <element>[
+        startNode = content;
+        startNodeOffset = 0;
       }
-
-      rv = aRange->SetStart(content, int32_t(xpOffset));
+      NS_ASSERTION(startNode, "startNode must not be nullptr");
+      NS_ASSERTION(startNodeOffset >= 0,
+                   "startNodeOffset must not be negative");
+      rv = aRange->SetStart(startNode, startNodeOffset);
       if (NS_WARN_IF(NS_FAILED(rv))) {
         return rv;
       }
       startSet = true;
-      if (aLength == 0) {
-        // Ensure that the end offset and the start offset are same.
-        rv = aRange->SetEnd(content, int32_t(xpOffset));
+
+      if (!aLength) {
+        rv = aRange->SetEnd(startNode, startNodeOffset);
         if (NS_WARN_IF(NS_FAILED(rv))) {
           return rv;
         }
         return NS_OK;
       }
     }
+
+    // When the end offset is in the content, the node is the end node of the
+    // range.
     if (endOffset <= offset + textLength) {
-      nsINode* endNode = content;
-      uint32_t xpOffset;
+      MOZ_ASSERT(startSet,
+        "The start of the range should've been set already");
       if (content->IsNodeOfType(nsINode::eTEXT)) {
-        xpOffset = endOffset - offset;
+        // Rule #2.1: ]textNode or text]Node or textNode]
+        uint32_t xpOffset = endOffset - offset;
         if (aLineBreakType == LINE_BREAK_TYPE_NATIVE) {
           xpOffset = ConvertToXPOffset(content, xpOffset);
         }
         if (aExpandToClusterBoundaries) {
           rv = ExpandToClusterBoundary(content, true, &xpOffset);
           if (NS_WARN_IF(NS_FAILED(rv))) {
             return rv;
           }
         }
-      } else {
-        // Use first position of next node, because the end node is ignored
-        // by ContentIterator when the offset is zero.
-        xpOffset = 0;
-        iter->Next();
-        if (iter->IsDone()) {
-          break;
+        NS_ASSERTION(xpOffset <= INT32_MAX,
+          "The end node offset is too large");
+        rv = aRange->SetEnd(content, static_cast<int32_t>(xpOffset));
+        if (NS_WARN_IF(NS_FAILED(rv))) {
+          return rv;
         }
-        endNode = iter->GetCurrentNode();
+        return NS_OK;
       }
 
-      rv = aRange->SetEnd(endNode, int32_t(xpOffset));
+      if (endOffset == offset) {
+        // Rule #2.2: ]<element>
+        // NOTE: Please don't crash on release builds because it must be
+        //       overreaction but we shouldn't allow this bug when some
+        //       automated tests find this.
+        MOZ_ASSERT(false, "This case should've already been handled at "
+                          "the last node which caused some text");
+        return NS_ERROR_FAILURE;
+      }
+
+      // Rule #2.3: </element>]
+      nsINode* endNode = content->GetParent();
+      if (NS_WARN_IF(!endNode)) {
+        return NS_ERROR_FAILURE;
+      }
+      int32_t indexInParent = endNode->IndexOf(content);
+      if (NS_WARN_IF(indexInParent == -1)) {
+        // The content is being removed from the parent!
+        return NS_ERROR_FAILURE;
+      }
+      rv = aRange->SetEnd(endNode, indexInParent + 1);
       if (NS_WARN_IF(NS_FAILED(rv))) {
         return rv;
       }
       return NS_OK;
     }
 
     offset += textLength;
   }
 
-  if (offset < aOffset) {
-    return NS_ERROR_FAILURE;
-  }
-
   if (!startSet) {
+    // Rule #1.5: [</root>
     MOZ_ASSERT(!mRootContent->IsNodeOfType(nsINode::eTEXT));
-    rv = aRange->SetStart(mRootContent, int32_t(mRootContent->GetChildCount()));
+    rv = aRange->SetStart(mRootContent,
+                          static_cast<int32_t>(mRootContent->GetChildCount()));
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
     if (aNewOffset) {
       *aNewOffset = offset;
     }
   }
-  rv = aRange->SetEnd(mRootContent, int32_t(mRootContent->GetChildCount()));
+  // Rule #2.4: ]</root>
+  rv = aRange->SetEnd(mRootContent,
+                      static_cast<int32_t>(mRootContent->GetChildCount()));
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
   return NS_OK;
 }
 
 /* static */ LineBreakType
 ContentEventHandler::GetLineBreakType(WidgetQueryContentEvent* aEvent)
@@ -1445,16 +1570,21 @@ ContentEventHandler::GetFlatTextLengthIn
                        LineBreakType aLineBreakType,
                        bool aIsRemovingNode /* = false */)
 {
   if (NS_WARN_IF(!aRootContent) || NS_WARN_IF(!aStartPosition.IsValid()) ||
       NS_WARN_IF(!aEndPosition.IsValid()) || NS_WARN_IF(!aLength)) {
     return NS_ERROR_INVALID_ARG;
   }
 
+  if (aStartPosition == aEndPosition) {
+    *aLength = 0;
+    return NS_OK;
+  }
+
   // Don't create nsContentIterator instance until it's really necessary since
   // destroying without initializing causes unexpected NS_ASSERTION() call.
   nsCOMPtr<nsIContentIterator> iter;
 
   // This may be called for retrieving the text of removed nodes.  Even in this
   // case, the node thinks it's still in the tree because UnbindFromTree() will
   // be called after here.  However, the node was already removed from the
   // array of children of its parent.  So, be careful to handle this case.
@@ -1650,43 +1780,46 @@ ContentEventHandler::ConvertToRootRelati
 }
 
 static void AdjustRangeForSelection(nsIContent* aRoot,
                                     nsINode** aNode,
                                     int32_t* aNodeOffset)
 {
   nsINode* node = *aNode;
   int32_t nodeOffset = *aNodeOffset;
-  if (aRoot != node && node->GetParent()) {
-    if (node->IsNodeOfType(nsINode::eTEXT)) {
-      // When the offset is at the end of the text node, set it to after the
-      // text node, to make sure the caret is drawn on a new line when the last
-      // character of the text node is '\n'
-      int32_t nodeLength =
-        static_cast<int32_t>(static_cast<nsIContent*>(node)->TextLength());
-      MOZ_ASSERT(nodeOffset <= nodeLength, "Offset is past length of text node");
-      if (nodeOffset == nodeLength) {
-        node = node->GetParent();
-        nodeOffset = node->IndexOf(*aNode) + 1;
-      }
-    } else {
-      node = node->GetParent();
-      nodeOffset = node->IndexOf(*aNode) + (nodeOffset ? 1 : 0);
-    }
+  if (aRoot == node || NS_WARN_IF(!node->GetParent()) ||
+      !node->IsNodeOfType(nsINode::eTEXT)) {
+    return;
+  }
+
+  // When the offset is at the end of the text node, set it to after the
+  // text node, to make sure the caret is drawn on a new line when the last
+  // character of the text node is '\n' in <textarea>.
+  int32_t textLength =
+    static_cast<int32_t>(static_cast<nsIContent*>(node)->TextLength());
+  MOZ_ASSERT(nodeOffset <= textLength, "Offset is past length of text node");
+  if (nodeOffset != textLength) {
+    return;
   }
 
-  nsIContent* brContent = node->GetChildAt(nodeOffset - 1);
-  while (brContent && brContent->IsHTMLElement()) {
-    if (!brContent->IsHTMLElement(nsGkAtoms::br) || IsContentBR(brContent)) {
-      break;
-    }
-    brContent = node->GetChildAt(--nodeOffset - 1);
+  nsIContent* aRootParent = aRoot->GetParent();
+  if (NS_WARN_IF(!aRootParent)) {
+    return;
   }
-  *aNode = node;
-  *aNodeOffset = std::max(nodeOffset, 0);
+  // If the root node is not an anonymous div of <textarea>, we don't need to
+  // do this hack.  If you did this, ContentEventHandler couldn't distinguish
+  // if the range includes open tag of the next node in some cases, e.g.,
+  // textNode]<p></p> vs. textNode<p>]</p>
+  if (!aRootParent->IsHTMLElement(nsGkAtoms::textarea)) {
+    return;
+  }
+
+  *aNode = node->GetParent();
+  MOZ_ASSERT((*aNode)->IndexOf(node) != -1);
+  *aNodeOffset = (*aNode)->IndexOf(node) + 1;
 }
 
 nsresult
 ContentEventHandler::OnSelectionEvent(WidgetSelectionEvent* aEvent)
 {
   aEvent->mSucceeded = false;
 
   // Get selection to manipulate
--- a/dom/events/ContentEventHandler.h
+++ b/dom/events/ContentEventHandler.h
@@ -102,16 +102,21 @@ public:
     }
 
     explicit NodePosition(const nsIFrame::ContentOffsets& aContentOffsets)
       : mNode(aContentOffsets.content)
       , mOffset(aContentOffsets.offset)
     {
     }
 
+    bool operator==(const NodePosition& aOther) const
+    {
+      return mNode == aOther.mNode && mOffset == aOther.mOffset;
+    }
+
     bool IsValid() const
     {
       return mNode && mOffset >= 0;
     }
     bool OffsetIsValid() const
     {
       return IsValid() && static_cast<uint32_t>(mOffset) <= mNode->Length();
     }
--- a/widget/tests/window_composition_text_querycontent.xul
+++ b/widget/tests/window_composition_text_querycontent.xul
@@ -2322,692 +2322,688 @@ function runSetSelectionEventTest()
 
   var selection = windowOfContenteditable.getSelection();
 
   // #1
   contenteditable.innerHTML = "abc<br>def";
 
   synthesizeSelectionSet(0, 6 + kLFLen);
   is(selection.anchorNode, contenteditable.firstChild,
-     "runSetSelectionEventTest #1 (0, 6+kLFLen): selection anchor node should be the first text node");
+     "runSetSelectionEventTest #1 (0, 6+kLFLen), \"" + contenteditable.innerHTML + "\": selection anchor node should be the first text node");
   is(selection.anchorOffset, 0,
-     "runSetSelectionEventTest #1 (0, 6+kLFLen): selection anchor offset should be 0");
-  is(selection.focusNode, contenteditable,
-     "runSetSelectionEventTest #1 (0, 6+kLFLen): selection focus node should be the root node of the editor");
-  is(selection.focusOffset, contenteditable.childNodes.length,
-     "runSetSelectionEventTest #1 (0, 6+kLFLen): selection focus offset should be the count of children");
-  checkSelection(0, "abc" + kLF + "def", "runSetSelectionEventTest #1 (0, 6+kLFLen)");
+     "runSetSelectionEventTest #1 (0, 6+kLFLen), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 0");
+  is(selection.focusNode, contenteditable.lastChild,
+     "runSetSelectionEventTest #1 (0, 6+kLFLen), \"" + contenteditable.innerHTML + "\": selection focus node should be the last text node of the editor");
+  is(selection.focusOffset, contenteditable.lastChild.wholeText.length,
+     "runSetSelectionEventTest #1 (0, 6+kLFLen), \"" + contenteditable.innerHTML + "\": selection focus offset should be the length of the last text node");
+  checkSelection(0, "abc" + kLF + "def", "runSetSelectionEventTest #1 (0, 6+kLFLen), \"" + contenteditable.innerHTML + "\"");
 
   synthesizeSelectionSet(0, 100);
   is(selection.anchorNode, contenteditable.firstChild,
-     "runSetSelectionEventTest #1 (0, 100): selection anchor node should be the first text node");
+     "runSetSelectionEventTest #1 (0, 100), \"" + contenteditable.innerHTML + "\": selection anchor node should be the first text node");
   is(selection.anchorOffset, 0,
-     "runSetSelectionEventTest #1 (0, 100): selection anchor offset should be 0");
+     "runSetSelectionEventTest #1 (0, 100), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 0");
   is(selection.focusNode, contenteditable,
-     "runSetSelectionEventTest #1 (0, 100): selection focus node should be the root node of the editor");
+     "runSetSelectionEventTest #1 (0, 100), \"" + contenteditable.innerHTML + "\": selection focus node should be the root node of the editor");
   is(selection.focusOffset, contenteditable.childNodes.length,
-     "runSetSelectionEventTest #1 (0, 100): selection focus offset should be the count of children");
-  checkSelection(0, "abc" + kLF + "def", "runSetSelectionEventTest #1 (0, 100)");
+     "runSetSelectionEventTest #1 (0, 100), \"" + contenteditable.innerHTML + "\": selection focus offset should be the count of children");
+  checkSelection(0, "abc" + kLF + "def", "runSetSelectionEventTest #1 (0, 100), \"" + contenteditable.innerHTML + "\"");
 
   synthesizeSelectionSet(2, 2 + kLFLen);
   is(selection.anchorNode, contenteditable.firstChild,
-     "runSetSelectionEventTest #1 (2, 2+kLFLen): selection anchor node should be the first text node");
+     "runSetSelectionEventTest #1 (2, 2+kLFLen), \"" + contenteditable.innerHTML + "\": selection anchor node should be the first text node");
   is(selection.anchorOffset, 2,
-     "runSetSelectionEventTest #1 (2, 2+kLFLen): selection anchor offset should be 2");
+     "runSetSelectionEventTest #1 (2, 2+kLFLen), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 2");
   is(selection.focusNode, contenteditable.lastChild,
-     "runSetSelectionEventTest #1 (2, 2+kLFLen): selection focus node should be the last text node");
+     "runSetSelectionEventTest #1 (2, 2+kLFLen), \"" + contenteditable.innerHTML + "\": selection focus node should be the last text node");
   is(selection.focusOffset, 1,
-     "runSetSelectionEventTest #1 (2, 2+kLFLen): selection focus offset should be 1");
-  checkSelection(2, "c" + kLF + "d", "runSetSelectionEventTest #1 (2, 2+kLFLen)");
+     "runSetSelectionEventTest #1 (2, 2+kLFLen), \"" + contenteditable.innerHTML + "\": selection focus offset should be 1");
+  checkSelection(2, "c" + kLF + "d", "runSetSelectionEventTest #1 (2, 2+kLFLen), \"" + contenteditable.innerHTML + "\"");
 
   synthesizeSelectionSet(1, 2);
   is(selection.anchorNode, contenteditable.firstChild,
-     "runSetSelectionEventTest #1 (1, 2): selection anchor node should be the first text node");
+     "runSetSelectionEventTest #1 (1, 2), \"" + contenteditable.innerHTML + "\": selection anchor node should be the first text node");
   is(selection.anchorOffset, 1,
-     "runSetSelectionEventTest #1 (1, 2): selection anchor offset should be 1");
-  is(selection.focusNode, contenteditable,
-     "runSetSelectionEventTest #1 (1, 2): selection focus node should be the root node of the editor");
-  is(selection.focusOffset, 1,
-     "runSetSelectionEventTest #1 (1, 2): selection focus offset should be 1");
-  checkSelection(1, "bc", "runSetSelectionEventTest #1 (1, 2)");
+     "runSetSelectionEventTest #1 (1, 2), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 1");
+  is(selection.focusNode, contenteditable.firstChild,
+     "runSetSelectionEventTest #1 (1, 2), \"" + contenteditable.innerHTML + "\": selection focus node should be the first text node");
+  is(selection.focusOffset, contenteditable.firstChild.wholeText.length,
+     "runSetSelectionEventTest #1 (1, 2), \"" + contenteditable.innerHTML + "\": selection focus offset should be the length of the text node");
+  checkSelection(1, "bc", "runSetSelectionEventTest #1 (1, 2), \"" + contenteditable.innerHTML + "\"");
 
   synthesizeSelectionSet(3, kLFLen);
-  is(selection.anchorNode, contenteditable,
-     "runSetSelectionEventTest #1 (3, kLFLen): selection anchor node should be the root node of the editor");
-  is(selection.anchorOffset, 1,
-     "runSetSelectionEventTest #1 (3, kLFLen): selection anchor offset should be 1");
-  is(selection.focusNode, contenteditable.lastChild,
-     "runSetSelectionEventTest #1 (3, kLFLen): selection focus node should be the last text node");
-  is(selection.focusOffset, 0,
-     "runSetSelectionEventTest #1 (3, kLFLen): selection focus offset should be 0");
-  checkSelection(3, kLF, "runSetSelectionEventTest #1 (3, kLFLen)");
+  is(selection.anchorNode, contenteditable.firstChild,
+     "runSetSelectionEventTest #1 (3, kLFLen), \"" + contenteditable.innerHTML + "\": selection anchor node should be the first text node");
+  is(selection.anchorOffset, contenteditable.firstChild.wholeText.length,
+     "runSetSelectionEventTest #1 (3, kLFLen), \"" + contenteditable.innerHTML + "\": selection anchor offset should be the length of the first text node");
+  is(selection.focusNode, contenteditable,
+     "runSetSelectionEventTest #1 (3, kLFLen), \"" + contenteditable.innerHTML + "\": selection focus node should be the root node");
+  is(selection.focusOffset, 2,
+     "runSetSelectionEventTest #1 (3, kLFLen), \"" + contenteditable.innerHTML + "\": selection focus offset should be the index of the last text node");
+  checkSelection(3, kLF, "runSetSelectionEventTest #1 (3, kLFLen), \"" + contenteditable.innerHTML + "\"");
 
   synthesizeSelectionSet(6+kLFLen, 0);
-  is(selection.anchorNode, contenteditable,
-     "runSetSelectionEventTest #1 (6+kLFLen, 0): selection anchor node should be the root node of the editor");
-  is(selection.anchorOffset, contenteditable.childNodes.length,
-     "runSetSelectionEventTest #1 (6+kLFLen, 0): selection anchor offset should be the count of children");
-  is(selection.focusNode, contenteditable,
-     "runSetSelectionEventTest #1 (6+kLFLen, 0): selection focus node should be the root node of the editor");
-  is(selection.anchorOffset, contenteditable.childNodes.length,
-     "runSetSelectionEventTest #1 (6+kLFLen, 0): selection focus offset should be the count of children");
-  checkSelection(6 + kLFLen, "", "runSetSelectionEventTest #1 (6+kLFLen, 0)");
+  is(selection.anchorNode, contenteditable.lastChild,
+     "runSetSelectionEventTest #1 (6+kLFLen, 0), \"" + contenteditable.innerHTML + "\": selection anchor node should be the last text node");
+  is(selection.anchorOffset, contenteditable.lastChild.wholeText.length,
+     "runSetSelectionEventTest #1 (6+kLFLen, 0), \"" + contenteditable.innerHTML + "\": selection anchor offset should be the length of the last text node");
+  is(selection.focusNode, contenteditable.lastChild,
+     "runSetSelectionEventTest #1 (6+kLFLen, 0), \"" + contenteditable.innerHTML + "\": selection focus node should be the last text node");
+  is(selection.anchorOffset, contenteditable.lastChild.wholeText.length,
+     "runSetSelectionEventTest #1 (6+kLFLen, 0), \"" + contenteditable.innerHTML + "\": selection focus offset should be the length of the last text node");
+  checkSelection(6 + kLFLen, "", "runSetSelectionEventTest #1 (6+kLFLen, 0), \"" + contenteditable.innerHTML + "\"");
 
   synthesizeSelectionSet(100, 0);
   is(selection.anchorNode, contenteditable,
-     "runSetSelectionEventTest #1 (100, 0): selection anchor node should be the root node of the editor");
+     "runSetSelectionEventTest #1 (100, 0), \"" + contenteditable.innerHTML + "\": selection anchor node should be the root node of the editor");
   is(selection.anchorOffset, contenteditable.childNodes.length,
-     "runSetSelectionEventTest #1 (100, 0): selection anchor offset should be the count of children");
+     "runSetSelectionEventTest #1 (100, 0), \"" + contenteditable.innerHTML + "\": selection anchor offset should be the count of children");
   is(selection.focusNode, contenteditable,
-     "runSetSelectionEventTest #1 (100, 0): selection focus node should be the root node of the editor");
+     "runSetSelectionEventTest #1 (100, 0), \"" + contenteditable.innerHTML + "\": selection focus node should be the root node of the editor");
   is(selection.focusOffset, contenteditable.childNodes.length,
-     "runSetSelectionEventTest #1 (100, 0): selection focus offset should be the count of children");
-  checkSelection(6 + kLFLen, "", "runSetSelectionEventTest #1 (100, 0)");
+     "runSetSelectionEventTest #1 (100, 0), \"" + contenteditable.innerHTML + "\": selection focus offset should be the count of children");
+  checkSelection(6 + kLFLen, "", "runSetSelectionEventTest #1 (100, 0), \"" + contenteditable.innerHTML + "\"");
 
   // #2
   contenteditable.innerHTML = "<p>a<b>b</b>c</p><p>def</p>";
 
   synthesizeSelectionSet(0, 4);
   is(selection.anchorNode, contenteditable.firstChild.firstChild,
-     "runSetSelectionEventTest #2 (0, 4): selection anchor node should be the first text node");
+     "runSetSelectionEventTest #2 (0, 4), \"" + contenteditable.innerHTML + "\": selection anchor node should be the first text node");
   is(selection.anchorOffset, 0,
-     "runSetSelectionEventTest #2 (0, 4): selection anchor offset should be 0");
+     "runSetSelectionEventTest #2 (0, 4), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 0");
   is(selection.focusNode, contenteditable.lastChild.firstChild,
-     "runSetSelectionEventTest #2 (0, 4): selection focus node should be the text node in the second <p> node");
+     "runSetSelectionEventTest #2 (0, 4), \"" + contenteditable.innerHTML + "\": selection focus node should be the text node in the second <p> node");
   is(selection.focusOffset, 1,
-     "runSetSelectionEventTest #2 (0, 4): selection focus offset should be 1");
-  checkSelection(0, "abcd", "runSetSelectionEventTest #2 (0, 4)");
+     "runSetSelectionEventTest #2 (0, 4), \"" + contenteditable.innerHTML + "\": selection focus offset should be 1");
+  checkSelection(0, "abcd", "runSetSelectionEventTest #2 (0, 4), \"" + contenteditable.innerHTML + "\"");
 
   synthesizeSelectionSet(0, 2);
   is(selection.anchorNode, contenteditable.firstChild.firstChild,
-     "runSetSelectionEventTest #2 (0, 2): selection anchor node should be the first text node");
+     "runSetSelectionEventTest #2 (0, 2), \"" + contenteditable.innerHTML + "\": selection anchor node should be the first text node");
   is(selection.anchorOffset, 0,
-     "runSetSelectionEventTest #2 (0, 2): selection anchor offset should be 0");
-  is(selection.focusNode, contenteditable.firstChild.childNodes.item(1),
-     "runSetSelectionEventTest #2 (0, 2): selection focus node should be the <b> node");
-  is(selection.focusOffset, contenteditable.firstChild.childNodes.item(1).childNodes.length,
-     "runSetSelectionEventTest #2 (0, 2): selection focus offset should be the count of the <b>'s children");
-  checkSelection(0, "ab", "runSetSelectionEventTest #2 (0, 2)");
+     "runSetSelectionEventTest #2 (0, 2), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 0");
+  is(selection.focusNode, contenteditable.firstChild.childNodes.item(1).firstChild,
+     "runSetSelectionEventTest #2 (0, 2), \"" + contenteditable.innerHTML + "\": selection focus node should be the text node in the <b> node");
+  is(selection.focusOffset, contenteditable.firstChild.childNodes.item(1).firstChild.wholeText.length,
+     "runSetSelectionEventTest #2 (0, 2), \"" + contenteditable.innerHTML + "\": selection focus offset should be the length of the text node in the <b> node");
+  checkSelection(0, "ab", "runSetSelectionEventTest #2 (0, 2), \"" + contenteditable.innerHTML + "\"");
 
   synthesizeSelectionSet(1, 2);
-  is(selection.anchorNode, contenteditable.firstChild.childNodes.item(1).firstChild,
-     "runSetSelectionEventTest #2 (1, 2): selection anchor node should be the text node in the <b> node");
-  is(selection.anchorOffset, 0,
-     "runSetSelectionEventTest #2 (1, 2): selection anchor offset should be 0");
-  is(selection.focusNode, contenteditable.firstChild,
-     "runSetSelectionEventTest #2 (1, 2): selection focus node should be the first <p> node");
-  is(selection.focusOffset, contenteditable.firstChild.childNodes.length,
-     "runSetSelectionEventTest #2 (1, 2): selection focus offset should be the count of last <p>'s children");
-  checkSelection(1, "bc", "runSetSelectionEventTest #2 (1, 2)");
+  is(selection.anchorNode, contenteditable.firstChild.firstChild,
+     "runSetSelectionEventTest #2 (1, 2), \"" + contenteditable.innerHTML + "\": selection anchor node should be the first text node");
+  is(selection.anchorOffset, 1,
+     "runSetSelectionEventTest #2 (1, 2), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 1");
+  is(selection.focusNode, contenteditable.firstChild.lastChild,
+     "runSetSelectionEventTest #2 (1, 2), \"" + contenteditable.innerHTML + "\": selection focus node should be the last text node in the first <p> node");
+  is(selection.focusOffset, contenteditable.firstChild.lastChild.wholeText.length,
+     "runSetSelectionEventTest #2 (1, 2), \"" + contenteditable.innerHTML + "\": selection focus offset should be the length of the last text node in the first <p> node");
+  checkSelection(1, "bc", "runSetSelectionEventTest #2 (1, 2), \"" + contenteditable.innerHTML + "\"");
 
   synthesizeSelectionSet(2, 2);
-  is(selection.anchorNode, contenteditable.firstChild.lastChild,
-     "runSetSelectionEventTest #2 (2, 2): selection anchor node should be the last text node in the first <p> node");
-  is(selection.anchorOffset, 0,
-     "runSetSelectionEventTest #2 (2, 2): selection anchor offset should be 0");
+  is(selection.anchorNode, contenteditable.firstChild.childNodes.item(1).firstChild,
+     "runSetSelectionEventTest #2 (2, 2), \"" + contenteditable.innerHTML + "\": selection anchor node should be the text node in the <b> node");
+  is(selection.anchorOffset, contenteditable.firstChild.childNodes.item(1).firstChild.wholeText.length,
+     "runSetSelectionEventTest #2 (2, 2), \"" + contenteditable.innerHTML + "\": selection anchor offset should be the length of the text node in the <b> node");
   is(selection.focusNode, contenteditable.lastChild.firstChild,
-     "runSetSelectionEventTest #2 (2, 2): selection focus node should be the text node in the last <p> node");
+     "runSetSelectionEventTest #2 (2, 2), \"" + contenteditable.innerHTML + "\": selection focus node should be the text node in the last <p> node");
   is(selection.focusOffset, 1,
-     "runSetSelectionEventTest #2 (2, 2): selection focus offset should be 1");
-  checkSelection(2, "cd", "runSetSelectionEventTest #2 (2, 2)");
+     "runSetSelectionEventTest #2 (2, 2), \"" + contenteditable.innerHTML + "\": selection focus offset should be 1");
+  checkSelection(2, "cd", "runSetSelectionEventTest #2 (2, 2), \"" + contenteditable.innerHTML + "\"");
 
   synthesizeSelectionSet(3, 1);
-  is(selection.anchorNode, contenteditable.lastChild.firstChild,
-     "runSetSelectionEventTest #2 (3, 1): selection anchor node should be the text node in the second <p> node");
-  is(selection.anchorOffset, 0,
-     "runSetSelectionEventTest #2 (3, 1): selection anchor offset should be 0");
+  is(selection.anchorNode, contenteditable.firstChild.lastChild,
+     "runSetSelectionEventTest #2 (3, 1), \"" + contenteditable.innerHTML + "\": selection anchor node should be the last text node in the first <p> node");
+  is(selection.anchorOffset, contenteditable.firstChild.lastChild.wholeText.length,
+     "runSetSelectionEventTest #2 (3, 1), \"" + contenteditable.innerHTML + "\": selection anchor offset should be the length of the last text node in the first <p> node");
   is(selection.focusNode, contenteditable.lastChild.firstChild,
-     "runSetSelectionEventTest #2 (3, 1): selection focus node should be the text node in the second <p> node");
+     "runSetSelectionEventTest #2 (3, 1), \"" + contenteditable.innerHTML + "\": selection focus node should be the text node in the second <p> node");
   is(selection.focusOffset, 1,
-     "runSetSelectionEventTest #2 (3, 1): selection focus offset should be 1");
-  checkSelection(3, "d", "runSetSelectionEventTest #2 (3, 1)");
+     "runSetSelectionEventTest #2 (3, 1), \"" + contenteditable.innerHTML + "\": selection focus offset should be 1");
+  checkSelection(3, "d", "runSetSelectionEventTest #2 (3, 1), \"" + contenteditable.innerHTML + "\"");
 
   // #3
   contenteditable.innerHTML = "<div>abc<p>def</p></div>";
 
   synthesizeSelectionSet(1, 2);
   is(selection.anchorNode, contenteditable.firstChild.firstChild,
-     "runSetSelectionEventTest #3 (1, 2): selection anchor node should be the first text node");
+     "runSetSelectionEventTest #3 (1, 2), \"" + contenteditable.innerHTML + "\": selection anchor node should be the first text node");
   is(selection.anchorOffset, 1,
-     "runSetSelectionEventTest #3 (1, 2): selection anchor offset should be 1");
-  is(selection.focusNode, contenteditable.firstChild,
-     "runSetSelectionEventTest #3 (1, 2): selection focus node should be the <div> node");
-  is(selection.focusOffset, 1,
-     "runSetSelectionEventTest #3 (1, 2): selection focus offset should be 1");
-  checkSelection(1, "bc", "runSetSelectionEventTest #3 (1, 2)");
+     "runSetSelectionEventTest #3 (1, 2), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 1");
+  is(selection.focusNode, contenteditable.firstChild.firstChild,
+     "runSetSelectionEventTest #3 (1, 2), \"" + contenteditable.innerHTML + "\": selection focus node should be the first text node");
+  is(selection.focusOffset, contenteditable.firstChild.firstChild.wholeText.length,
+     "runSetSelectionEventTest #3 (1, 2), \"" + contenteditable.innerHTML + "\": selection focus offset should be the length of the first text node");
+  checkSelection(1, "bc", "runSetSelectionEventTest #3 (1, 2), \"" + contenteditable.innerHTML + "\"");
 
   synthesizeSelectionSet(1, 3);
   is(selection.anchorNode, contenteditable.firstChild.firstChild,
-     "runSetSelectionEventTest #3 (1, 3): selection anchor node should be the first text node");
+     "runSetSelectionEventTest #3 (1, 3), \"" + contenteditable.innerHTML + "\": selection anchor node should be the first text node");
   is(selection.anchorOffset, 1,
-     "runSetSelectionEventTest #3 (1, 3): selection anchor offset should be 1");
+     "runSetSelectionEventTest #3 (1, 3), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 1");
   is(selection.focusNode, contenteditable.firstChild.lastChild.firstChild,
-     "runSetSelectionEventTest #3 (1, 3): selection focus node should be the text node in the <p> node");
+     "runSetSelectionEventTest #3 (1, 3), \"" + contenteditable.innerHTML + "\": selection focus node should be the text node in the <p> node");
   is(selection.focusOffset, 1,
-     "runSetSelectionEventTest #3 (1, 3): selection focus offset should be 1");
-  checkSelection(1, "bcd", "runSetSelectionEventTest #3 (1, 3)");
+     "runSetSelectionEventTest #3 (1, 3), \"" + contenteditable.innerHTML + "\": selection focus offset should be 1");
+  checkSelection(1, "bcd", "runSetSelectionEventTest #3 (1, 3), \"" + contenteditable.innerHTML + "\"");
 
   synthesizeSelectionSet(3, 0);
-  is(selection.anchorNode, contenteditable.firstChild,
-     "runSetSelectionEventTest #3 (3, 0): selection anchor node should be the <div> node");
-  is(selection.anchorOffset, 1,
-     "runSetSelectionEventTest #3 (3, 0): selection anchor offset should be 1");
-  is(selection.focusNode, contenteditable.firstChild,
-     "runSetSelectionEventTest #3 (3, 0): selection focus node should be the <div> node");
-  is(selection.focusOffset, 1,
-     "runSetSelectionEventTest #3 (3, 0): selection focus offset should be 1");
-  checkSelection(3, "", "runSetSelectionEventTest #3 (3, 0)");
+  is(selection.anchorNode, contenteditable.firstChild.firstChild,
+     "runSetSelectionEventTest #3 (3, 0), \"" + contenteditable.innerHTML + "\": selection anchor node should be the first text node");
+  is(selection.anchorOffset, contenteditable.firstChild.firstChild.wholeText.length,
+     "runSetSelectionEventTest #3 (3, 0), \"" + contenteditable.innerHTML + "\": selection anchor offset should be the length of the first text node");
+  is(selection.focusNode, contenteditable.firstChild.firstChild,
+     "runSetSelectionEventTest #3 (3, 0), \"" + contenteditable.innerHTML + "\": selection focus node should be the first text node");
+  is(selection.focusOffset, contenteditable.firstChild.firstChild.wholeText.length,
+     "runSetSelectionEventTest #3 (3, 0), \"" + contenteditable.innerHTML + "\": selection focus offset should be the length of the first text node");
+  checkSelection(3, "", "runSetSelectionEventTest #3 (3, 0), \"" + contenteditable.innerHTML + "\"");
 
   synthesizeSelectionSet(0, 6);
   is(selection.anchorNode, contenteditable.firstChild.firstChild,
-     "runSetSelectionEventTest #3 (0, 6): selection anchor node should be the first text node");
+     "runSetSelectionEventTest #3 (0, 6), \"" + contenteditable.innerHTML + "\": selection anchor node should be the first text node");
   is(selection.anchorOffset, 0,
-     "runSetSelectionEventTest #3 (0, 6): selection anchor offset should be 0");
-  is(selection.focusNode, contenteditable.firstChild.lastChild,
-     "runSetSelectionEventTest #3 (0, 6): selection focus node should be the <p> node");
-  is(selection.focusOffset, contenteditable.firstChild.lastChild.childNodes.length,
-     "runSetSelectionEventTest #3 (0, 6): selection focus offset should be the count of the <p>'s children");
-  checkSelection(0, "abcdef", "runSetSelectionEventTest #3 (0, 6)");
+     "runSetSelectionEventTest #3 (0, 6), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 0");
+  is(selection.focusNode, contenteditable.firstChild.lastChild.firstChild,
+     "runSetSelectionEventTest #3 (0, 6), \"" + contenteditable.innerHTML + "\": selection focus node should be the last text node");
+  is(selection.focusOffset, contenteditable.firstChild.lastChild.firstChild.wholeText.length,
+     "runSetSelectionEventTest #3 (0, 6), \"" + contenteditable.innerHTML + "\": selection focus offset should be the length of the last text node");
+  checkSelection(0, "abcdef", "runSetSelectionEventTest #3 (0, 6), \"" + contenteditable.innerHTML + "\"");
 
   synthesizeSelectionSet(0, 100);
   is(selection.anchorNode, contenteditable.firstChild.firstChild,
-     "runSetSelectionEventTest #3 (0, 100): selection anchor node should be the first text node");
+     "runSetSelectionEventTest #3 (0, 100), \"" + contenteditable.innerHTML + "\": selection anchor node should be the first text node");
   is(selection.anchorOffset, 0,
-     "runSetSelectionEventTest #3 (0, 100): selection anchor offset should be 0");
+     "runSetSelectionEventTest #3 (0, 100), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 0");
   is(selection.focusNode, contenteditable,
-     "runSetSelectionEventTest #3 (0, 100): selection focus node should be the root node");
+     "runSetSelectionEventTest #3 (0, 100), \"" + contenteditable.innerHTML + "\": selection focus node should be the root node");
   is(selection.focusOffset, contenteditable.childNodes.length,
-     "runSetSelectionEventTest #3 (0, 100): selection focus offset should be the count of the root's children");
-  checkSelection(0, "abcdef", "runSetSelectionEventTest #3 (0, 100)");
+     "runSetSelectionEventTest #3 (0, 100), \"" + contenteditable.innerHTML + "\": selection focus offset should be the count of the root's children");
+  checkSelection(0, "abcdef", "runSetSelectionEventTest #3 (0, 100), \"" + contenteditable.innerHTML + "\"");
 
   synthesizeSelectionSet(4, 2);
   is(selection.anchorNode, contenteditable.firstChild.lastChild.firstChild,
-     "runSetSelectionEventTest #3 (4, 2): selection anchor node should be the text node in the <p> node");
+     "runSetSelectionEventTest #3 (4, 2), \"" + contenteditable.innerHTML + "\": selection anchor node should be the last text node");
   is(selection.anchorOffset, 1,
-     "runSetSelectionEventTest #3 (4, 2): selection anchor offset should be 1");
-  is(selection.focusNode, contenteditable.firstChild.lastChild,
-     "runSetSelectionEventTest #3 (4, 2): selection focus node should be the <p> node");
-  is(selection.focusOffset, contenteditable.firstChild.lastChild.childNodes.length,
-     "runSetSelectionEventTest #3 (4, 2): selection focus offset should be the count of the <p>'s children");
-  checkSelection(4, "ef", "runSetSelectionEventTest #3 (4, 2)");
+     "runSetSelectionEventTest #3 (4, 2), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 1");
+  is(selection.focusNode, contenteditable.firstChild.lastChild.firstChild,
+     "runSetSelectionEventTest #3 (4, 2), \"" + contenteditable.innerHTML + "\": selection focus node should be the last text node");
+  is(selection.focusOffset, contenteditable.firstChild.lastChild.firstChild.wholeText.length,
+     "runSetSelectionEventTest #3 (4, 2), \"" + contenteditable.innerHTML + "\": selection focus offset should be the length of the last text node");
+  checkSelection(4, "ef", "runSetSelectionEventTest #3 (4, 2), \"" + contenteditable.innerHTML + "\"");
 
   synthesizeSelectionSet(4, 100);
   is(selection.anchorNode, contenteditable.firstChild.lastChild.firstChild,
-     "runSetSelectionEventTest #3 (4, 100): selection anchor node should be the text node in the <p> node");
+     "runSetSelectionEventTest #3 (4, 100), \"" + contenteditable.innerHTML + "\": selection anchor node should be the last text node");
   is(selection.anchorOffset, 1,
-     "runSetSelectionEventTest #3 (4, 100): selection anchor offset should be 1");
+     "runSetSelectionEventTest #3 (4, 100), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 1");
   is(selection.focusNode, contenteditable,
-     "runSetSelectionEventTest #3 (4, 100): selection focus node should be the root node");
+     "runSetSelectionEventTest #3 (4, 100), \"" + contenteditable.innerHTML + "\": selection focus node should be the root node");
   is(selection.focusOffset, contenteditable.childNodes.length,
-     "runSetSelectionEventTest #3 (4, 100): selection focus offset should be the count of the root's children");
-  checkSelection(4, "ef", "runSetSelectionEventTest #3 (4, 100)");
+     "runSetSelectionEventTest #3 (4, 100), \"" + contenteditable.innerHTML + "\": selection focus offset should be the count of the root's children");
+  checkSelection(4, "ef", "runSetSelectionEventTest #3 (4, 100), \"" + contenteditable.innerHTML + "\"");
 
   synthesizeSelectionSet(6, 0);
-  is(selection.anchorNode, contenteditable.firstChild.lastChild,
-     "runSetSelectionEventTest #3 (6, 0): selection anchor node should be the <p> node");
-  is(selection.anchorOffset, contenteditable.firstChild.lastChild.childNodes.length,
-     "runSetSelectionEventTest #3 (6, 0): selection anchor offset should be the count of the <p>'s children");
-  is(selection.focusNode, contenteditable.firstChild.lastChild,
-     "runSetSelectionEventTest #3 (6, 0): selection focus node should be the <p> node");
-  is(selection.focusOffset, contenteditable.firstChild.lastChild.childNodes.length,
-     "runSetSelectionEventTest #3 (6, 0): selection focus offset should be the count of the <p>'s children");
-  checkSelection(6, "", "runSetSelectionEventTest #3 (6, 0)");
+  is(selection.anchorNode, contenteditable.firstChild.lastChild.firstChild,
+     "runSetSelectionEventTest #3 (6, 0), \"" + contenteditable.innerHTML + "\": selection anchor node should be the last text node");
+  is(selection.anchorOffset, contenteditable.firstChild.lastChild.firstChild.wholeText.length,
+     "runSetSelectionEventTest #3 (6, 0), \"" + contenteditable.innerHTML + "\": selection anchor offset should be the length of the last text node");
+  is(selection.focusNode, contenteditable.firstChild.lastChild.firstChild,
+     "runSetSelectionEventTest #3 (6, 0), \"" + contenteditable.innerHTML + "\": selection focus node should be the last text node");
+  is(selection.focusOffset, contenteditable.firstChild.lastChild.firstChild.wholeText.length,
+     "runSetSelectionEventTest #3 (6, 0), \"" + contenteditable.innerHTML + "\": selection focus offset should be the length of the last text node");
+  checkSelection(6, "", "runSetSelectionEventTest #3 (6, 0), \"" + contenteditable.innerHTML + "\"");
 
   synthesizeSelectionSet(6, 1);
-  todo_is(selection.anchorNode, contenteditable.firstChild.lastChild,
-     "runSetSelectionEventTest #3 (6, 1): selection anchor node should be the <p> node");
-  is(selection.anchorOffset, contenteditable.firstChild.lastChild.childNodes.length,
-     "runSetSelectionEventTest #3 (6, 1): selection anchor offset should be the count of the <p>'s children");
+  is(selection.anchorNode, contenteditable.firstChild.lastChild.firstChild,
+     "runSetSelectionEventTest #3 (6, 1), \"" + contenteditable.innerHTML + "\": selection anchor node should be the last text node");
+  is(selection.anchorOffset, contenteditable.firstChild.lastChild.firstChild.wholeText.length,
+     "runSetSelectionEventTest #3 (6, 1), \"" + contenteditable.innerHTML + "\": selection anchor offset should be the length of the last text node");
   is(selection.focusNode, contenteditable,
-     "runSetSelectionEventTest #3 (6, 1): selection focus node should be the root node");
+     "runSetSelectionEventTest #3 (6, 1), \"" + contenteditable.innerHTML + "\": selection focus node should be the root node");
   is(selection.focusOffset, contenteditable.childNodes.length,
-     "runSetSelectionEventTest #3 (6, 1): selection focus offset should be the count of the root's children");
-  checkSelection(6, "", "runSetSelectionEventTest #3 (6, 1)");
+     "runSetSelectionEventTest #3 (6, 1), \"" + contenteditable.innerHTML + "\": selection focus offset should be the count of the root's children");
+  checkSelection(6, "", "runSetSelectionEventTest #3 (6, 1), \"" + contenteditable.innerHTML + "\"");
 
   // #4
   contenteditable.innerHTML = "<div><p>abc</p>def</div>";
 
   synthesizeSelectionSet(1, 2);
   is(selection.anchorNode, contenteditable.firstChild.firstChild.firstChild,
-     "runSetSelectionEventTest #4 (1, 2): selection anchor node should be the text node in the <p> node");
+     "runSetSelectionEventTest #4 (1, 2), \"" + contenteditable.innerHTML + "\": selection anchor node should be the text node in the <p> node");
   is(selection.anchorOffset, 1,
-     "runSetSelectionEventTest #4 (1, 2): selection anchor offset should be 1");
-  is(selection.focusNode, contenteditable.firstChild.firstChild,
-     "runSetSelectionEventTest #4 (1, 2): selection focus node should be the <p> node");
-  is(selection.focusOffset, contenteditable.firstChild.firstChild.childNodes.length,
-     "runSetSelectionEventTest #4 (1, 2): selection focus offset should be the count of the <p>'s children");
-  checkSelection(1, "bc", "runSetSelectionEventTest #4 (1, 2)");
+     "runSetSelectionEventTest #4 (1, 2), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 1");
+  is(selection.focusNode, contenteditable.firstChild.firstChild.firstChild,
+     "runSetSelectionEventTest #4 (1, 2), \"" + contenteditable.innerHTML + "\": selection focus node should be the text node in the <p> node");
+  is(selection.focusOffset, contenteditable.firstChild.firstChild.firstChild.wholeText.length,
+     "runSetSelectionEventTest #4 (1, 2), \"" + contenteditable.innerHTML + "\": selection focus offset should be the length of the text node in the <p> node");
+  checkSelection(1, "bc", "runSetSelectionEventTest #4 (1, 2), \"" + contenteditable.innerHTML + "\"");
 
   synthesizeSelectionSet(1, 3);
   is(selection.anchorNode, contenteditable.firstChild.firstChild.firstChild,
-     "runSetSelectionEventTest #4 (1, 3): selection anchor node should be the text node in the <p> node");
+     "runSetSelectionEventTest #4 (1, 3), \"" + contenteditable.innerHTML + "\": selection anchor node should be the text node in the <p> node");
   is(selection.anchorOffset, 1,
-     "runSetSelectionEventTest #4 (1, 3): selection anchor offset should be 1");
+     "runSetSelectionEventTest #4 (1, 3), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 1");
   is(selection.focusNode, contenteditable.firstChild.lastChild,
-     "runSetSelectionEventTest #4 (1, 3): selection focus node should be the last text node");
+     "runSetSelectionEventTest #4 (1, 3), \"" + contenteditable.innerHTML + "\": selection focus node should be the last text node");
   is(selection.focusOffset, 1,
-     "runSetSelectionEventTest #4 (1, 3): selection focus offset should be 1");
-  checkSelection(1, "bcd", "runSetSelectionEventTest #4 (1, 3)");
+     "runSetSelectionEventTest #4 (1, 3), \"" + contenteditable.innerHTML + "\": selection focus offset should be 1");
+  checkSelection(1, "bcd", "runSetSelectionEventTest #4 (1, 3), \"" + contenteditable.innerHTML + "\"");
 
   synthesizeSelectionSet(3, 0);
-  is(selection.anchorNode, contenteditable.firstChild.firstChild,
-     "runSetSelectionEventTest #4 (3, 0): selection anchor node should be the <p> node");
-  is(selection.anchorOffset, contenteditable.firstChild.firstChild.childNodes.length,
-     "runSetSelectionEventTest #4 (3, 0): selection anchor offset should be the count of <p>'s children");
-  is(selection.focusNode, contenteditable.firstChild.firstChild,
-     "runSetSelectionEventTest #4 (3, 0): selection focus node should be the <p> node");
-  is(selection.focusOffset, contenteditable.firstChild.firstChild.childNodes.length,
-     "runSetSelectionEventTest #4 (3, 0): selection focus offset should be the count of <p>'s children");
-  checkSelection(3, "", "runSetSelectionEventTest #4 (3, 0)");
+  is(selection.anchorNode, contenteditable.firstChild.firstChild.firstChild,
+     "runSetSelectionEventTest #4 (3, 0), \"" + contenteditable.innerHTML + "\": selection anchor node should be the text node in the <p> node");
+  is(selection.anchorOffset, contenteditable.firstChild.firstChild.firstChild.wholeText.length,
+     "runSetSelectionEventTest #4 (3, 0), \"" + contenteditable.innerHTML + "\": selection anchor offset should be the length of the text node in the <p> node");
+  is(selection.focusNode, contenteditable.firstChild.firstChild.firstChild,
+     "runSetSelectionEventTest #4 (3, 0), \"" + contenteditable.innerHTML + "\": selection focus node should be the text node in the <p> node");
+  is(selection.focusOffset, contenteditable.firstChild.firstChild.firstChild.wholeText.length,
+     "runSetSelectionEventTest #4 (3, 0), \"" + contenteditable.innerHTML + "\": selection focus offset should be the length of the text node in the <p> node");
+  checkSelection(3, "", "runSetSelectionEventTest #4 (3, 0), \"" + contenteditable.innerHTML + "\"");
 
   synthesizeSelectionSet(0, 6);
   is(selection.anchorNode, contenteditable.firstChild.firstChild.firstChild,
-     "runSetSelectionEventTest #4 (0, 6): selection anchor node should be the text node in the <p> node");
+     "runSetSelectionEventTest #4 (0, 6), \"" + contenteditable.innerHTML + "\": selection anchor node should be the text node in the <p> node");
   is(selection.anchorOffset, 0,
-     "runSetSelectionEventTest #4 (0, 6): selection anchor offset should be 0");
-  is(selection.focusNode, contenteditable.firstChild,
-     "runSetSelectionEventTest #4 (0, 6): selection focus node should be the <div> node");
-  is(selection.focusOffset, contenteditable.firstChild.childNodes.length,
-     "runSetSelectionEventTest #4 (0, 6): selection focus offset should be the count of the <div>'s children");
-  checkSelection(0, "abcdef", "runSetSelectionEventTest #4 (0, 6)");
+     "runSetSelectionEventTest #4 (0, 6), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 0");
+  is(selection.focusNode, contenteditable.firstChild.lastChild,
+     "runSetSelectionEventTest #4 (0, 6), \"" + contenteditable.innerHTML + "\": selection focus node should be the last text node");
+  is(selection.focusOffset, contenteditable.firstChild.lastChild.wholeText.length,
+     "runSetSelectionEventTest #4 (0, 6), \"" + contenteditable.innerHTML + "\": selection focus offset should be the length of the last text node");
+  checkSelection(0, "abcdef", "runSetSelectionEventTest #4 (0, 6), \"" + contenteditable.innerHTML + "\"");
 
   synthesizeSelectionSet(0, 100);
   is(selection.anchorNode, contenteditable.firstChild.firstChild.firstChild,
-     "runSetSelectionEventTest #4 (0, 100): selection anchor node should be the text node in the <p> node");
+     "runSetSelectionEventTest #4 (0, 100), \"" + contenteditable.innerHTML + "\": selection anchor node should be the text node in the <p> node");
   is(selection.anchorOffset, 0,
-     "runSetSelectionEventTest #4 (0, 100): selection anchor offset should be 0");
+     "runSetSelectionEventTest #4 (0, 100), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 0");
   is(selection.focusNode, contenteditable,
-     "runSetSelectionEventTest #4 (0, 100): selection focus node should be the root node");
+     "runSetSelectionEventTest #4 (0, 100), \"" + contenteditable.innerHTML + "\": selection focus node should be the root node");
   is(selection.focusOffset, contenteditable.childNodes.length,
-     "runSetSelectionEventTest #4 (0, 100): selection focus offset should be the count of the root's children");
-  checkSelection(0, "abcdef", "runSetSelectionEventTest #4 (0, 100)");
+     "runSetSelectionEventTest #4 (0, 100), \"" + contenteditable.innerHTML + "\": selection focus offset should be the count of the root's children");
+  checkSelection(0, "abcdef", "runSetSelectionEventTest #4 (0, 100), \"" + contenteditable.innerHTML + "\"");
 
   synthesizeSelectionSet(4, 2);
   is(selection.anchorNode, contenteditable.firstChild.lastChild,
-     "runSetSelectionEventTest #4 (4, 2): selection anchor node should be the last text node");
+     "runSetSelectionEventTest #4 (4, 2), \"" + contenteditable.innerHTML + "\": selection anchor node should be the last text node");
   is(selection.anchorOffset, 1,
-     "runSetSelectionEventTest #4 (4, 2): selection anchor offset should be 1");
-  is(selection.focusNode, contenteditable.firstChild,
-     "runSetSelectionEventTest #4 (4, 2): selection focus node should be the <div> node");
-  is(selection.focusOffset, contenteditable.firstChild.childNodes.length,
-     "runSetSelectionEventTest #4 (4, 2): selection focus offset should be the count of the <div>'s children");
-  checkSelection(4, "ef", "runSetSelectionEventTest #4 (4, 2)");
+     "runSetSelectionEventTest #4 (4, 2), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 1");
+  is(selection.focusNode, contenteditable.firstChild.lastChild,
+     "runSetSelectionEventTest #4 (4, 2), \"" + contenteditable.innerHTML + "\": selection focus node should be the last text node");
+  is(selection.focusOffset, contenteditable.firstChild.lastChild.wholeText.length,
+     "runSetSelectionEventTest #4 (4, 2), \"" + contenteditable.innerHTML + "\": selection focus offset should be the length of the last text node");
+  checkSelection(4, "ef", "runSetSelectionEventTest #4 (4, 2), \"" + contenteditable.innerHTML + "\"");
 
   synthesizeSelectionSet(4, 100);
   is(selection.anchorNode, contenteditable.firstChild.lastChild,
-     "runSetSelectionEventTest #4 (4, 100): selection anchor node should be the last text node");
+     "runSetSelectionEventTest #4 (4, 100), \"" + contenteditable.innerHTML + "\": selection anchor node should be the last text node");
   is(selection.anchorOffset, 1,
-     "runSetSelectionEventTest #4 (4, 100): selection anchor offset should be 1");
+     "runSetSelectionEventTest #4 (4, 100), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 1");
   is(selection.focusNode, contenteditable,
-     "runSetSelectionEventTest #4 (4, 100): selection focus node should be the root node");
+     "runSetSelectionEventTest #4 (4, 100), \"" + contenteditable.innerHTML + "\": selection focus node should be the root node");
   is(selection.focusOffset, contenteditable.childNodes.length,
-     "runSetSelectionEventTest #4 (4, 100): selection focus offset should be the count of the root's children");
-  checkSelection(4, "ef", "runSetSelectionEventTest #4 (4, 100)");
+     "runSetSelectionEventTest #4 (4, 100), \"" + contenteditable.innerHTML + "\": selection focus offset should be the count of the root's children");
+  checkSelection(4, "ef", "runSetSelectionEventTest #4 (4, 100), \"" + contenteditable.innerHTML + "\"");
 
   synthesizeSelectionSet(6, 0);
-  is(selection.anchorNode, contenteditable.firstChild,
-     "runSetSelectionEventTest #4 (6, 0): selection anchor node should be the <div> node");
-  is(selection.anchorOffset, contenteditable.firstChild.childNodes.length,
-     "runSetSelectionEventTest #4 (6, 0): selection anchor offset should be the count of the <div>'s children");
-  is(selection.focusNode, contenteditable.firstChild,
-     "runSetSelectionEventTest #4 (6, 0): selection focus node should be the <div> node");
-  is(selection.focusOffset, contenteditable.firstChild.childNodes.length,
-     "runSetSelectionEventTest #4 (6, 0): selection focus offset should be the count of the <div>'s children");
-  checkSelection(6, "", "runSetSelectionEventTest #4 (6, 0)");
+  is(selection.anchorNode, contenteditable.firstChild.lastChild,
+     "runSetSelectionEventTest #4 (6, 0), \"" + contenteditable.innerHTML + "\": selection anchor node should be the last text node");
+  is(selection.anchorOffset, contenteditable.firstChild.lastChild.wholeText.length,
+     "runSetSelectionEventTest #4 (6, 0), \"" + contenteditable.innerHTML + "\": selection anchor offset should be the length of the last text node");
+  is(selection.focusNode, contenteditable.firstChild.lastChild,
+     "runSetSelectionEventTest #4 (6, 0), \"" + contenteditable.innerHTML + "\": selection focus node should be the last text node");
+  is(selection.focusOffset, contenteditable.firstChild.lastChild.wholeText.length,
+     "runSetSelectionEventTest #4 (6, 0), \"" + contenteditable.innerHTML + "\": selection focus offset should be the length of the last text node");
+  checkSelection(6, "", "runSetSelectionEventTest #4 (6, 0), \"" + contenteditable.innerHTML + "\"");
 
   synthesizeSelectionSet(6, 1);
-  todo_is(selection.anchorNode, contenteditable.firstChild,
-     "runSetSelectionEventTest #4 (6, 1): selection anchor node should be the <div> node");
-  todo_is(selection.anchorOffset, contenteditable.firstChild.childNodes.length,
-     "runSetSelectionEventTest #4 (6, 1): selection anchor offset should be the count of the <div>'s children");
+  is(selection.anchorNode, contenteditable.firstChild.lastChild,
+     "runSetSelectionEventTest #4 (6, 1), \"" + contenteditable.innerHTML + "\": selection anchor node should be the last text node");
+  is(selection.anchorOffset, contenteditable.firstChild.lastChild.wholeText.length,
+     "runSetSelectionEventTest #4 (6, 1), \"" + contenteditable.innerHTML + "\": selection anchor offset should be the length of the last text node");
   is(selection.focusNode, contenteditable,
-     "runSetSelectionEventTest #4 (6, 1): selection focus node should be the root node");
+     "runSetSelectionEventTest #4 (6, 1), \"" + contenteditable.innerHTML + "\": selection focus node should be the root node");
   is(selection.focusOffset, contenteditable.childNodes.length,
-     "runSetSelectionEventTest #4 (6, 1): selection focus offset should be the count of the root's children");
-  checkSelection(6, "", "runSetSelectionEventTest #4 (6, 1)");
+     "runSetSelectionEventTest #4 (6, 1), \"" + contenteditable.innerHTML + "\": selection focus offset should be the count of the root's children");
+  checkSelection(6, "", "runSetSelectionEventTest #4 (6, 1), \"" + contenteditable.innerHTML + "\"");
 
   // #5
   contenteditable.innerHTML = "<br>";
 
   synthesizeSelectionSet(0, kLFLen);
   is(selection.anchorNode, contenteditable,
-     "runSetSelectionEventTest #5 (0, kLFLen): selection anchor node should be the root node");
+     "runSetSelectionEventTest #5 (0, kLFLen), \"" + contenteditable.innerHTML + "\": selection anchor node should be the root node");
   is(selection.anchorOffset, 0,
-     "runSetSelectionEventTest #5 (0, kLFLen): selection anchor offset should be 0");
+     "runSetSelectionEventTest #5 (0, kLFLen), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 0");
   is(selection.focusNode, contenteditable,
-     "runSetSelectionEventTest #5 (0, kLFLen): selection focus node should be the root node");
+     "runSetSelectionEventTest #5 (0, kLFLen), \"" + contenteditable.innerHTML + "\": selection focus node should be the root node");
   is(selection.focusOffset, contenteditable.childNodes.length,
-     "runSetSelectionEventTest #5 (0, kLFLen): selection focus offset should be the count of the root's children");
-  checkSelection(0, kLF, "runSetSelectionEventTest #5 (0, kLFLen)");
+     "runSetSelectionEventTest #5 (0, kLFLen), \"" + contenteditable.innerHTML + "\": selection focus offset should be the count of the root's children");
+  checkSelection(0, kLF, "runSetSelectionEventTest #5 (0, kLFLen), \"" + contenteditable.innerHTML + "\"");
 
   synthesizeSelectionSet(kLFLen, 0);
   is(selection.anchorNode, contenteditable,
-     "runSetSelectionEventTest #5 (kLFLen, 0): selection anchor node should be the root node");
-  todo_is(selection.anchorOffset, contenteditable.childNodes.length,
-     "runSetSelectionEventTest #5 (kLFLen, 0): selection anchor offset should be the count of the root's children");
+     "runSetSelectionEventTest #5 (kLFLen, 0), \"" + contenteditable.innerHTML + "\": selection anchor node should be the root node");
+  is(selection.anchorOffset, contenteditable.childNodes.length,
+     "runSetSelectionEventTest #5 (kLFLen, 0), \"" + contenteditable.innerHTML + "\": selection anchor offset should be the count of the root's children");
   is(selection.focusNode, contenteditable,
-     "runSetSelectionEventTest #5 (kLFLen, 0): selection focus node should be the root node");
+     "runSetSelectionEventTest #5 (kLFLen, 0), \"" + contenteditable.innerHTML + "\": selection focus node should be the root node");
   is(selection.focusOffset, contenteditable.childNodes.length,
-     "runSetSelectionEventTest #5 (kLFLen, 0): selection focus offset should be the count of the root's children");
-  // todo
-  // checkSelection(kLFLen, "", "runSetSelectionEventTest #5 (kLFLen, 0)");
+     "runSetSelectionEventTest #5 (kLFLen, 0), \"" + contenteditable.innerHTML + "\": selection focus offset should be the count of the root's children");
+  checkSelection(kLFLen, "", "runSetSelectionEventTest #5 (kLFLen, 0), \"" + contenteditable.innerHTML + "\"");
 
   synthesizeSelectionSet(kLFLen, 1);
   is(selection.anchorNode, contenteditable,
-     "runSetSelectionEventTest #5 (kLFLen, 1): selection anchor node should be the root node");
+     "runSetSelectionEventTest #5 (kLFLen, 1), \"" + contenteditable.innerHTML + "\": selection anchor node should be the root node");
   is(selection.anchorOffset, contenteditable.childNodes.length,
-     "runSetSelectionEventTest #5 (kLFLen, 1): selection anchor offset should be the count of the root's children");
+     "runSetSelectionEventTest #5 (kLFLen, 1), \"" + contenteditable.innerHTML + "\": selection anchor offset should be the count of the root's children");
   is(selection.focusNode, contenteditable,
-     "runSetSelectionEventTest #5 (kLFLen, 1): selection focus node should be the root node");
+     "runSetSelectionEventTest #5 (kLFLen, 1), \"" + contenteditable.innerHTML + "\": selection focus node should be the root node");
   is(selection.focusOffset, contenteditable.childNodes.length,
-     "runSetSelectionEventTest #5 (kLFLen, 1): selection focus offset should be the count of the root's children");
-  checkSelection(kLFLen, "", "runSetSelectionEventTest #5 (kLFLen, 1)");
+     "runSetSelectionEventTest #5 (kLFLen, 1), \"" + contenteditable.innerHTML + "\": selection focus offset should be the count of the root's children");
+  checkSelection(kLFLen, "", "runSetSelectionEventTest #5 (kLFLen, 1), \"" + contenteditable.innerHTML + "\"");
 
   // #6
   contenteditable.innerHTML = "<p><br></p>";
 
   synthesizeSelectionSet(0, kLFLen);
   is(selection.anchorNode, contenteditable.firstChild,
-     "runSetSelectionEventTest #6 (0, kLFLen): selection anchor node should be the <p> node");
+     "runSetSelectionEventTest #6 (0, kLFLen), \"" + contenteditable.innerHTML + "\": selection anchor node should be the <p> node");
   is(selection.anchorOffset, 0,
-     "runSetSelectionEventTest #6 (0, kLFLen): selection anchor offset should be 1");
-  todo_is(selection.focusNode, contenteditable.firstChild,
-     "runSetSelectionEventTest #6 (0, kLFLen): selection focus node should be the <p> node");
+     "runSetSelectionEventTest #6 (0, kLFLen), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 1");
+  is(selection.focusNode, contenteditable.firstChild,
+     "runSetSelectionEventTest #6 (0, kLFLen), \"" + contenteditable.innerHTML + "\": selection focus node should be the <p> node");
   is(selection.focusOffset, contenteditable.firstChild.childNodes.length,
-     "runSetSelectionEventTest #6 (0, kLFLen): selection focus offset should be the count of the <p>'s children");
-  checkSelection(0, kLF, "runSetSelectionEventTest #6 (0, kLFLen)");
+     "runSetSelectionEventTest #6 (0, kLFLen), \"" + contenteditable.innerHTML + "\": selection focus offset should be the count of the <p>'s children");
+  checkSelection(0, kLF, "runSetSelectionEventTest #6 (0, kLFLen), \"" + contenteditable.innerHTML + "\"");
 
   synthesizeSelectionSet(kLFLen, 0);
   is(selection.anchorNode, contenteditable.firstChild,
-     "runSetSelectionEventTest #6 (kLFLen, 0): selection anchor node should be the <p> node");
-  is(selection.anchorOffset, 0,
-     "runSetSelectionEventTest #6 (kLFLen, 0): selection anchor offset should be the count of the root's children");
-  todo_is(selection.focusNode, contenteditable.firstChild,
-     "runSetSelectionEventTest #6 (kLFLen, 0): selection focus node should be the <p> node");
+     "runSetSelectionEventTest #6 (kLFLen, 0), \"" + contenteditable.innerHTML + "\": selection anchor node should be the <p> node");
+  is(selection.anchorOffset, contenteditable.firstChild.childNodes.length,
+     "runSetSelectionEventTest #6 (kLFLen, 0), \"" + contenteditable.innerHTML + "\": selection anchor offset should be the count of the <p>'s children");
+  is(selection.focusNode, contenteditable.firstChild,
+     "runSetSelectionEventTest #6 (kLFLen, 0), \"" + contenteditable.innerHTML + "\": selection focus node should be the <p> node");
   is(selection.focusOffset, contenteditable.firstChild.childNodes.length,
-     "runSetSelectionEventTest #6 (kLFLen, 0): selection focus offset should be the count of the <p>'s children");
-  // todo
-  // checkSelection(kLFLen, "", "runSetSelectionEventTest #6 (kLFLen, 0)");
+     "runSetSelectionEventTest #6 (kLFLen, 0), \"" + contenteditable.innerHTML + "\": selection focus offset should be the count of the <p>'s children");
+  checkSelection(kLFLen, "", "runSetSelectionEventTest #6 (kLFLen, 0), \"" + contenteditable.innerHTML + "\"");
 
   synthesizeSelectionSet(kLFLen, 1);
-  todo_is(selection.anchorNode, contenteditable.firstChild,
-     "runSetSelectionEventTest #6 (kLFLen, 1): selection anchor node should be the <p> node");
+  is(selection.anchorNode, contenteditable.firstChild,
+     "runSetSelectionEventTest #6 (kLFLen, 1), \"" + contenteditable.innerHTML + "\": selection anchor node should be the <p> node");
   is(selection.anchorOffset, contenteditable.firstChild.childNodes.length,
-     "runSetSelectionEventTest #6 (kLFLen, 1): selection anchor offset should be the count of the root's children");
+     "runSetSelectionEventTest #6 (kLFLen, 1), \"" + contenteditable.innerHTML + "\": selection anchor offset should be the count of the root's children");
   is(selection.focusNode, contenteditable,
-     "runSetSelectionEventTest #6 (kLFLen, 1): selection focus node should be the root node");
+     "runSetSelectionEventTest #6 (kLFLen, 1), \"" + contenteditable.innerHTML + "\": selection focus node should be the root node");
   is(selection.focusOffset, contenteditable.childNodes.length,
-     "runSetSelectionEventTest #6 (kLFLen, 1): selection focus offset should be the count of the root's children");
-  checkSelection(kLFLen, "", "runSetSelectionEventTest #6 (kLFLen, 1)");
+     "runSetSelectionEventTest #6 (kLFLen, 1), \"" + contenteditable.innerHTML + "\": selection focus offset should be the count of the root's children");
+  checkSelection(kLFLen, "", "runSetSelectionEventTest #6 (kLFLen, 1), \"" + contenteditable.innerHTML + "\"");
 
   // #7
   contenteditable.innerHTML = "<br><br>";
 
   synthesizeSelectionSet(0, kLFLen);
   is(selection.anchorNode, contenteditable,
-     "runSetSelectionEventTest #7 (0, kLFLen): selection anchor node should be the root node");
+     "runSetSelectionEventTest #7 (0, kLFLen), \"" + contenteditable.innerHTML + "\": selection anchor node should be the root node");
   is(selection.anchorOffset, 0,
-     "runSetSelectionEventTest #7 (0, kLFLen): selection anchor offset should be 0");
+     "runSetSelectionEventTest #7 (0, kLFLen), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 0");
   is(selection.focusNode, contenteditable,
-     "runSetSelectionEventTest #7 (0, kLFLen): selection focus node should be the root node");
+     "runSetSelectionEventTest #7 (0, kLFLen), \"" + contenteditable.innerHTML + "\": selection focus node should be the root node");
   is(selection.focusOffset, 1,
-     "runSetSelectionEventTest #7 (0, kLFLen): selection focus offset should be 1");
-  checkSelection(0, kLF, "runSetSelectionEventTest #7 (0, kLFLen)");
+     "runSetSelectionEventTest #7 (0, kLFLen), \"" + contenteditable.innerHTML + "\": selection focus offset should be 1");
+  checkSelection(0, kLF, "runSetSelectionEventTest #7 (0, kLFLen), \"" + contenteditable.innerHTML + "\"");
 
   synthesizeSelectionSet(0, kLFLen * 2);
   is(selection.anchorNode, contenteditable,
-     "runSetSelectionEventTest #7 (0, kLFLen*2): selection anchor node should be the root node");
+     "runSetSelectionEventTest #7 (0, kLFLen*2), \"" + contenteditable.innerHTML + "\": selection anchor node should be the root node");
   is(selection.anchorOffset, 0,
-     "runSetSelectionEventTest #7 (0, kLFLen*2): selection anchor offset should be 0");
+     "runSetSelectionEventTest #7 (0, kLFLen*2), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 0");
   is(selection.focusNode, contenteditable,
-     "runSetSelectionEventTest #7 (0, kLFLen*2): selection focus node should be the root node");
+     "runSetSelectionEventTest #7 (0, kLFLen*2), \"" + contenteditable.innerHTML + "\": selection focus node should be the root node");
   is(selection.focusOffset, contenteditable.childNodes.length,
-     "runSetSelectionEventTest #7 (0, kLFLen*2): selection focus offset should be the count of the root's children");
-  checkSelection(0, kLF + kLF, "runSetSelectionEventTest #7 (0, kLFLen*2)");
+     "runSetSelectionEventTest #7 (0, kLFLen*2), \"" + contenteditable.innerHTML + "\": selection focus offset should be the count of the root's children");
+  checkSelection(0, kLF + kLF, "runSetSelectionEventTest #7 (0, kLFLen*2), \"" + contenteditable.innerHTML + "\"");
 
   synthesizeSelectionSet(kLFLen, 0);
   is(selection.anchorNode, contenteditable,
-     "runSetSelectionEventTest #7 (kLFLen, 0): selection anchor node should be the root node");
+     "runSetSelectionEventTest #7 (kLFLen, 0), \"" + contenteditable.innerHTML + "\": selection anchor node should be the root node");
   is(selection.anchorOffset, 1,
-     "runSetSelectionEventTest #7 (kLFLen, 0): selection anchor offset should be 1");
+     "runSetSelectionEventTest #7 (kLFLen, 0), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 1");
   is(selection.focusNode, contenteditable,
-     "runSetSelectionEventTest #7 (kLFLen, 0): selection focus node should be the root node");
+     "runSetSelectionEventTest #7 (kLFLen, 0), \"" + contenteditable.innerHTML + "\": selection focus node should be the root node");
   is(selection.focusOffset, 1,
-     "runSetSelectionEventTest #7 (kLFLen, 0): selection focus offset should be 1");
-  checkSelection(kLFLen, "", "runSetSelectionEventTest #7 (kLFLen, 0)");
+     "runSetSelectionEventTest #7 (kLFLen, 0), \"" + contenteditable.innerHTML + "\": selection focus offset should be 1");
+  checkSelection(kLFLen, "", "runSetSelectionEventTest #7 (kLFLen, 0), \"" + contenteditable.innerHTML + "\"");
 
   synthesizeSelectionSet(kLFLen, kLFLen);
   is(selection.anchorNode, contenteditable,
-     "runSetSelectionEventTest #7 (kLFLen, kLFLen): selection anchor node should be the root node");
+     "runSetSelectionEventTest #7 (kLFLen, kLFLen), \"" + contenteditable.innerHTML + "\": selection anchor node should be the root node");
   is(selection.anchorOffset, 1,
-     "runSetSelectionEventTest #7 (kLFLen, kLFLen): selection anchor offset should be 1");
+     "runSetSelectionEventTest #7 (kLFLen, kLFLen), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 1");
   is(selection.focusNode, contenteditable,
      "runSetSelectionEventTest #7 (kLFLen, kLFLen) selection focus node should be the root node");
   is(selection.focusOffset, contenteditable.childNodes.length,
-     "runSetSelectionEventTest #7 (kLFLen, kLFLen): selection focus offset should be the count of the root's children");
-  checkSelection(kLFLen, kLF, "runSetSelectionEventTest #7 (kLFLen, kLFLen)");
+     "runSetSelectionEventTest #7 (kLFLen, kLFLen), \"" + contenteditable.innerHTML + "\": selection focus offset should be the count of the root's children");
+  checkSelection(kLFLen, kLF, "runSetSelectionEventTest #7 (kLFLen, kLFLen), \"" + contenteditable.innerHTML + "\"");
 
   synthesizeSelectionSet(kLFLen * 2, 0);
   is(selection.anchorNode, contenteditable,
-     "runSetSelectionEventTest #7 (kLFLen*2, 0): selection anchor node should be the root node");
-  todo_is(selection.anchorOffset, contenteditable.childNodes.length,
-     "runSetSelectionEventTest #7 (kLFLen*2, 0): selection anchor offset should be the count of the root's children");
+     "runSetSelectionEventTest #7 (kLFLen*2, 0), \"" + contenteditable.innerHTML + "\": selection anchor node should be the root node");
+  is(selection.anchorOffset, contenteditable.childNodes.length,
+     "runSetSelectionEventTest #7 (kLFLen*2, 0), \"" + contenteditable.innerHTML + "\": selection anchor offset should be the count of the root's children");
   is(selection.focusNode, contenteditable,
-     "runSetSelectionEventTest #7 (kLFLen*2, 0): selection focus node should be the root node");
+     "runSetSelectionEventTest #7 (kLFLen*2, 0), \"" + contenteditable.innerHTML + "\": selection focus node should be the root node");
   is(selection.focusOffset, contenteditable.childNodes.length,
-     "runSetSelectionEventTest #7 (kLFLen*2, 0): selection focus offset should be the count of the root's children");
-  // todo
-  // checkSelection(kLFLen * 2, "", "runSetSelectionEventTest #7 (kLFLen*2, 0)");
+     "runSetSelectionEventTest #7 (kLFLen*2, 0), \"" + contenteditable.innerHTML + "\": selection focus offset should be the count of the root's children");
+  checkSelection(kLFLen * 2, "", "runSetSelectionEventTest #7 (kLFLen*2, 0), \"" + contenteditable.innerHTML + "\"");
 
   // #8
   contenteditable.innerHTML = "<p><br><br></p>";
 
   synthesizeSelectionSet(0, kLFLen);
   is(selection.anchorNode, contenteditable.firstChild,
-     "runSetSelectionEventTest #8 (0, kLFLen): selection anchor node should be the <p> node");
+     "runSetSelectionEventTest #8 (0, kLFLen), \"" + contenteditable.innerHTML + "\": selection anchor node should be the <p> node");
   is(selection.anchorOffset, 0,
-     "runSetSelectionEventTest #8 (0, kLFLen): selection anchor offset should be 0");
+     "runSetSelectionEventTest #8 (0, kLFLen), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 0");
   is(selection.focusNode, contenteditable.firstChild,
-     "runSetSelectionEventTest #8 (0, kLFLen): selection focus node should be the <p> node");
+     "runSetSelectionEventTest #8 (0, kLFLen), \"" + contenteditable.innerHTML + "\": selection focus node should be the <p> node");
   is(selection.focusOffset, 1,
-     "runSetSelectionEventTest #8 (0, kLFLen): selection focus offset should be 1");
-  checkSelection(0, kLF, "runSetSelectionEventTest #7 (0, kLFLen)");
+     "runSetSelectionEventTest #8 (0, kLFLen), \"" + contenteditable.innerHTML + "\": selection focus offset should be 1");
+  checkSelection(0, kLF, "runSetSelectionEventTest #7 (0, kLFLen), \"" + contenteditable.innerHTML + "\"");
 
   synthesizeSelectionSet(0, kLFLen * 2);
   is(selection.anchorNode, contenteditable.firstChild,
-     "runSetSelectionEventTest #8 (0, kLFLen*2): selection anchor node should be the <p> node");
+     "runSetSelectionEventTest #8 (0, kLFLen*2), \"" + contenteditable.innerHTML + "\": selection anchor node should be the <p> node");
   is(selection.anchorOffset, 0,
-     "runSetSelectionEventTest #8 (0, kLFLen*2): selection anchor offset should be 0");
-  todo_is(selection.focusNode, contenteditable.firstChild,
-     "runSetSelectionEventTest #8 (0, kLFLen*2): selection focus node should be the <p> node");
-  todo_is(selection.focusOffset, contenteditable.firstChild.childNodes.length,
-     "runSetSelectionEventTest #8 (0, kLFLen*2): selection focus offset should be the count of the <p>'s children");
-  checkSelection(0, kLF + kLF, "runSetSelectionEventTest #8 (0, kLFLen*2)");
+     "runSetSelectionEventTest #8 (0, kLFLen*2), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 0");
+  is(selection.focusNode, contenteditable.firstChild,
+     "runSetSelectionEventTest #8 (0, kLFLen*2), \"" + contenteditable.innerHTML + "\": selection focus node should be the <p> node");
+  is(selection.focusOffset, contenteditable.firstChild.childNodes.length,
+     "runSetSelectionEventTest #8 (0, kLFLen*2), \"" + contenteditable.innerHTML + "\": selection focus offset should be the count of the <p>'s children");
+  checkSelection(0, kLF + kLF, "runSetSelectionEventTest #8 (0, kLFLen*2), \"" + contenteditable.innerHTML + "\"");
 
   synthesizeSelectionSet(kLFLen, 0);
   is(selection.anchorNode, contenteditable.firstChild,
-     "runSetSelectionEventTest #8 (kLFLen, 0): selection anchor node should be the <p> node");
+     "runSetSelectionEventTest #8 (kLFLen, 0), \"" + contenteditable.innerHTML + "\": selection anchor node should be the <p> node");
   is(selection.anchorOffset, 1,
-     "runSetSelectionEventTest #8 (kLFLen, 0): selection anchor offset should be 1");
+     "runSetSelectionEventTest #8 (kLFLen, 0), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 1");
   is(selection.focusNode, contenteditable.firstChild,
-     "runSetSelectionEventTest #8 (kLFLen, 0): selection focus node should be the <p> node");
+     "runSetSelectionEventTest #8 (kLFLen, 0), \"" + contenteditable.innerHTML + "\": selection focus node should be the <p> node");
   is(selection.focusOffset, 1,
-     "runSetSelectionEventTest #8 (kLFLen, 0): selection focus offset should be 1");
-  checkSelection(kLFLen, "", "runSetSelectionEventTest #8 (kLFLen, 0)");
+     "runSetSelectionEventTest #8 (kLFLen, 0), \"" + contenteditable.innerHTML + "\": selection focus offset should be 1");
+  checkSelection(kLFLen, "", "runSetSelectionEventTest #8 (kLFLen, 0), \"" + contenteditable.innerHTML + "\"");
 
   synthesizeSelectionSet(kLFLen, kLFLen);
   is(selection.anchorNode, contenteditable.firstChild,
-     "runSetSelectionEventTest #8 (kLFLen, kLFLen): selection anchor node should be the <p> node");
+     "runSetSelectionEventTest #8 (kLFLen, kLFLen), \"" + contenteditable.innerHTML + "\": selection anchor node should be the <p> node");
   is(selection.anchorOffset, 1,
-     "runSetSelectionEventTest #8 (kLFLen, kLFLen): selection anchor offset should be 1");
-  todo_is(selection.focusNode, contenteditable.firstChild,
+     "runSetSelectionEventTest #8 (kLFLen, kLFLen), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 1");
+  is(selection.focusNode, contenteditable.firstChild,
      "runSetSelectionEventTest #8 (kLFLen, kLFLen) selection focus node should be the <p> node");
-  todo_is(selection.focusOffset, contenteditable.firstChild.childNodes.length,
-     "runSetSelectionEventTest #8 (kLFLen, kLFLen): selection focus offset should be the count of the <p>'s children");
-  checkSelection(kLFLen, kLF, "runSetSelectionEventTest #8 (kLFLen, kLFLen)");
+  is(selection.focusOffset, contenteditable.firstChild.childNodes.length,
+     "runSetSelectionEventTest #8 (kLFLen, kLFLen), \"" + contenteditable.innerHTML + "\": selection focus offset should be the count of the <p>'s children");
+  checkSelection(kLFLen, kLF, "runSetSelectionEventTest #8 (kLFLen, kLFLen), \"" + contenteditable.innerHTML + "\"");
 
   synthesizeSelectionSet(kLFLen * 2, 0);
   is(selection.anchorNode, contenteditable.firstChild,
-     "runSetSelectionEventTest #8 (kLFLen*2, 0): selection anchor node should be the <p> node");
-  todo_is(selection.anchorOffset, contenteditable.firstChild.childNodes.length,
-     "runSetSelectionEventTest #8 (kLFLen*2, 0): selection anchor offset should be the count of the <p>'s children");
-  todo_is(selection.focusNode, contenteditable.firstChild,
-     "runSetSelectionEventTest #8 (kLFLen*2, 0): selection focus node should be the <p> node");
-  todo_is(selection.focusOffset, contenteditable.firstChild.childNodes.length,
-     "runSetSelectionEventTest #8 (kLFLen*2, 0): selection focus offset should be the count of the <p>'s children");
-  // todo
-  // checkSelection(kLFLen * 2, "", "runSetSelectionEventTest #8 (kLFLen*2, 0)");
+     "runSetSelectionEventTest #8 (kLFLen*2, 0), \"" + contenteditable.innerHTML + "\": selection anchor node should be the <p> node");
+  is(selection.anchorOffset, contenteditable.firstChild.childNodes.length,
+     "runSetSelectionEventTest #8 (kLFLen*2, 0), \"" + contenteditable.innerHTML + "\": selection anchor offset should be the count of the <p>'s children");
+  is(selection.focusNode, contenteditable.firstChild,
+     "runSetSelectionEventTest #8 (kLFLen*2, 0), \"" + contenteditable.innerHTML + "\": selection focus node should be the <p> node");
+  is(selection.focusOffset, contenteditable.firstChild.childNodes.length,
+     "runSetSelectionEventTest #8 (kLFLen*2, 0), \"" + contenteditable.innerHTML + "\": selection focus offset should be the count of the <p>'s children");
+  checkSelection(kLFLen * 2, "", "runSetSelectionEventTest #8 (kLFLen*2, 0), \"" + contenteditable.innerHTML + "\"");
 }
 
 function runQueryTextContentEventTest()
 {
   contenteditable.focus();
 
   var result;
 
   // #1
   contenteditable.innerHTML = "abc<br>def";
 
   result = synthesizeQueryTextContent(0, 6 + kLFLen);
-  is(result.text, "abc" + kLF + "def", "runQueryTextContentEventTest #1 (0, 6+kLFLen)");
+  is(result.text, "abc" + kLF + "def", "runQueryTextContentEventTest #1 (0, 6+kLFLen), \"" + contenteditable.innerHTML + "\"");
 
   result = synthesizeQueryTextContent(0, 100);
-  is(result.text, "abc" + kLF + "def", "runQueryTextContentEventTest #1 (0, 100)");
+  is(result.text, "abc" + kLF + "def", "runQueryTextContentEventTest #1 (0, 100), \"" + contenteditable.innerHTML + "\"");
 
   result = synthesizeQueryTextContent(2, 2 + kLFLen);
-  is(result.text, "c" + kLF + "d", "runQueryTextContentEventTest #1 (2, 2+kLFLen)");
+  is(result.text, "c" + kLF + "d", "runQueryTextContentEventTest #1 (2, 2+kLFLen), \"" + contenteditable.innerHTML + "\"");
 
   result = synthesizeQueryTextContent(1, 2);
-  is(result.text, "bc", "runQueryTextContentEventTest #1 (1, 2)");
+  is(result.text, "bc", "runQueryTextContentEventTest #1 (1, 2), \"" + contenteditable.innerHTML + "\"");
 
   result = synthesizeQueryTextContent(3, kLFLen);
-  is(result.text, kLF, "runQueryTextContentEventTest #1 (3, kLFLen)");
+  is(result.text, kLF, "runQueryTextContentEventTest #1 (3, kLFLen), \"" + contenteditable.innerHTML + "\"");
 
   result = synthesizeQueryTextContent(6 + kLFLen, 1);
-  is(result.text, "", "runQueryTextContentEventTest #1 (6 + kLFLen, 0)");
+  is(result.text, "", "runQueryTextContentEventTest #1 (6 + kLFLen, 0), \"" + contenteditable.innerHTML + "\"");
 
   // #2
   contenteditable.innerHTML = "<p>a<b>b</b>c</p><p>def</p>";
 
   result = synthesizeQueryTextContent(0, 4);
-  is(result.text, "abcd", "runQueryTextContentEventTest #2 (0, 4)");
+  is(result.text, "abcd", "runQueryTextContentEventTest #2 (0, 4), \"" + contenteditable.innerHTML + "\"");
 
   result = synthesizeQueryTextContent(0, 2);
-  is(result.text, "ab", "runQueryTextContentEventTest #2 (0, 2)");
+  is(result.text, "ab", "runQueryTextContentEventTest #2 (0, 2), \"" + contenteditable.innerHTML + "\"");
 
   result = synthesizeQueryTextContent(1, 2);
-  is(result.text, "bc", "runQueryTextContentEventTest #2 (1, 2)");
+  is(result.text, "bc", "runQueryTextContentEventTest #2 (1, 2), \"" + contenteditable.innerHTML + "\"");
 
   result = synthesizeQueryTextContent(2, 2);
-  is(result.text, "cd", "runQueryTextContentEventTest #2 (2, 2)");
+  is(result.text, "cd", "runQueryTextContentEventTest #2 (2, 2), \"" + contenteditable.innerHTML + "\"");
 
   result = synthesizeQueryTextContent(3, 1);
-  is(result.text, "d", "runQueryTextContentEventTest #2 (3, 1)");
+  is(result.text, "d", "runQueryTextContentEventTest #2 (3, 1), \"" + contenteditable.innerHTML + "\"");
 
   // #3
   contenteditable.innerHTML = "<div>abc<p>def</p></div>";
 
   result = synthesizeQueryTextContent(1, 2);
-  is(result.text, "bc", "runQueryTextContentEventTest #3 (1, 2)");
+  is(result.text, "bc", "runQueryTextContentEventTest #3 (1, 2), \"" + contenteditable.innerHTML + "\"");
 
   result = synthesizeQueryTextContent(1, 3);
-  is(result.text, "bcd", "runQueryTextContentEventTest #3 (1, 3)");
+  is(result.text, "bcd", "runQueryTextContentEventTest #3 (1, 3), \"" + contenteditable.innerHTML + "\"");
 
   result = synthesizeQueryTextContent(3, 1);
-  is(result.text, "d", "runQueryTextContentEventTest #3 (3, 1)");
+  is(result.text, "d", "runQueryTextContentEventTest #3 (3, 1), \"" + contenteditable.innerHTML + "\"");
 
   result = synthesizeQueryTextContent(0, 6);
-  is(result.text, "abcdef", "runQueryTextContentEventTest #3 (0, 6)");
+  is(result.text, "abcdef", "runQueryTextContentEventTest #3 (0, 6), \"" + contenteditable.innerHTML + "\"");
 
   result = synthesizeQueryTextContent(0, 100);
-  is(result.text, "abcdef", "runQueryTextContentEventTest #3 (0, 100)");
+  is(result.text, "abcdef", "runQueryTextContentEventTest #3 (0, 100), \"" + contenteditable.innerHTML + "\"");
 
   result = synthesizeQueryTextContent(4, 2);
-  is(result.text, "ef", "runQueryTextContentEventTest #3 (4, 2)");
+  is(result.text, "ef", "runQueryTextContentEventTest #3 (4, 2), \"" + contenteditable.innerHTML + "\"");
 
   result = synthesizeQueryTextContent(4, 100);
-  is(result.text, "ef", "runQueryTextContentEventTest #3 (4, 100)");
+  is(result.text, "ef", "runQueryTextContentEventTest #3 (4, 100), \"" + contenteditable.innerHTML + "\"");
 
   result = synthesizeQueryTextContent(6, 1);
-  is(result.text, "", "runQueryTextContentEventTest #3 (6, 1)");
+  is(result.text, "", "runQueryTextContentEventTest #3 (6, 1), \"" + contenteditable.innerHTML + "\"");
 
   // #4
   contenteditable.innerHTML = "<div><p>abc</p>def</div>";
 
   result = synthesizeQueryTextContent(1, 2);
-  is(result.text, "bc", "runQueryTextContentEventTest #4 (1, 2)");
+  is(result.text, "bc", "runQueryTextContentEventTest #4 (1, 2), \"" + contenteditable.innerHTML + "\"");
 
   result = synthesizeQueryTextContent(1, 3);
-  is(result.text, "bcd", "runQueryTextContentEventTest #4 (1, 3)");
+  is(result.text, "bcd", "runQueryTextContentEventTest #4 (1, 3), \"" + contenteditable.innerHTML + "\"");
 
   result = synthesizeQueryTextContent(3, 1);
-  is(result.text, "d", "runQueryTextContentEventTest #4 (3, 1)");
+  is(result.text, "d", "runQueryTextContentEventTest #4 (3, 1), \"" + contenteditable.innerHTML + "\"");
 
   result = synthesizeQueryTextContent(0, 6);
-  is(result.text, "abcdef", "runQueryTextContentEventTest #4 (0, 6)");
+  is(result.text, "abcdef", "runQueryTextContentEventTest #4 (0, 6), \"" + contenteditable.innerHTML + "\"");
 
   result = synthesizeQueryTextContent(0, 100);
-  is(result.text, "abcdef", "runQueryTextContentEventTest #4 (0, 100)");
+  is(result.text, "abcdef", "runQueryTextContentEventTest #4 (0, 100), \"" + contenteditable.innerHTML + "\"");
 
   result = synthesizeQueryTextContent(4, 2);
-  is(result.text, "ef", "runQueryTextContentEventTest #4 (4, 2)");
+  is(result.text, "ef", "runQueryTextContentEventTest #4 (4, 2), \"" + contenteditable.innerHTML + "\"");
 
   result = synthesizeQueryTextContent(4, 100);
-  is(result.text, "ef", "runQueryTextContentEventTest #4 (4, 100)");
+  is(result.text, "ef", "runQueryTextContentEventTest #4 (4, 100), \"" + contenteditable.innerHTML + "\"");
 
   result = synthesizeQueryTextContent(6, 1);
-  is(result.text, "", "runQueryTextContentEventTest #4 (6, 1)");
+  is(result.text, "", "runQueryTextContentEventTest #4 (6, 1), \"" + contenteditable.innerHTML + "\"");
 
   // #5
   contenteditable.innerHTML = "<br>";
 
   result = synthesizeQueryTextContent(0, kLFLen);
-  is(result.text, kLF, "runQueryTextContentEventTest #5 (0, kLFLen)");
+  is(result.text, kLF, "runQueryTextContentEventTest #5 (0, kLFLen), \"" + contenteditable.innerHTML + "\"");
 
   result = synthesizeQueryTextContent(kLFLen, 1);
-  is(result.text, "", "runQueryTextContentEventTest #5 (kLFLen, 1)");
+  is(result.text, "", "runQueryTextContentEventTest #5 (kLFLen, 1), \"" + contenteditable.innerHTML + "\"");
 
   // #6
   contenteditable.innerHTML = "<p><br></p>";
 
   result = synthesizeQueryTextContent(0, kLFLen);
-  is(result.text, kLF, "runQueryTextContentEventTest #6 (0, kLFLen)");
+  is(result.text, kLF, "runQueryTextContentEventTest #6 (0, kLFLen), \"" + contenteditable.innerHTML + "\"");
 
   result = synthesizeQueryTextContent(kLFLen, 1);
-  is(result.text, "", "runQueryTextContentEventTest #5 (kLFLen, 1)");
+  is(result.text, "", "runQueryTextContentEventTest #5 (kLFLen, 1), \"" + contenteditable.innerHTML + "\"");
 
   // #7
   contenteditable.innerHTML = "<br><br>";
 
   result = synthesizeQueryTextContent(0, kLFLen);
-  is(result.text, kLF, "runQueryTextContentEventTest #7 (0, kLFLen)");
+  is(result.text, kLF, "runQueryTextContentEventTest #7 (0, kLFLen), \"" + contenteditable.innerHTML + "\"");
 
   result = synthesizeQueryTextContent(0, kLFLen * 2);
-  is(result.text, kLF + kLF, "runQueryTextContentEventTest #7 (0, kLFLen*2)");
+  is(result.text, kLF + kLF, "runQueryTextContentEventTest #7 (0, kLFLen*2), \"" + contenteditable.innerHTML + "\"");
 
   result = synthesizeQueryTextContent(kLFLen, kLFLen);
-  is(result.text, kLF, "runQueryTextContentEventTest #7 (kLFLen, kLFLen)");
+  is(result.text, kLF, "runQueryTextContentEventTest #7 (kLFLen, kLFLen), \"" + contenteditable.innerHTML + "\"");
 
   result = synthesizeQueryTextContent(kLFLen * 2, 1);
-  is(result.text, "", "runQueryTextContentEventTest #7 (kLFLen*2, 1)");
+  is(result.text, "", "runQueryTextContentEventTest #7 (kLFLen*2, 1), \"" + contenteditable.innerHTML + "\"");
 
   // #8
   contenteditable.innerHTML = "<p><br><br></p>";
 
   result = synthesizeQueryTextContent(0, kLFLen);
-  is(result.text, kLF, "runQueryTextContentEventTest #8 (0, kLFLen)");
+  is(result.text, kLF, "runQueryTextContentEventTest #8 (0, kLFLen), \"" + contenteditable.innerHTML + "\"");
 
   result = synthesizeQueryTextContent(0, kLFLen * 2);
-  is(result.text, kLF + kLF, "runQueryTextContentEventTest #8 (0, kLFLen*2)");
+  is(result.text, kLF + kLF, "runQueryTextContentEventTest #8 (0, kLFLen*2), \"" + contenteditable.innerHTML + "\"");
 
   result = synthesizeQueryTextContent(kLFLen, kLFLen);
-  is(result.text, kLF, "runQueryTextContentEventTest #8 (kLFLen, kLFLen)");
+  is(result.text, kLF, "runQueryTextContentEventTest #8 (kLFLen, kLFLen), \"" + contenteditable.innerHTML + "\"");
 
   result = synthesizeQueryTextContent(kLFLen * 2, 1);
-  is(result.text, "", "runQueryTextContentEventTest #8 (kLFLen*2, 1)");
+  is(result.text, "", "runQueryTextContentEventTest #8 (kLFLen*2, 1), \"" + contenteditable.innerHTML + "\"");
 }
 
 function runCSSTransformTest()
 {
   textarea.focus();
   textarea.value = "some text";
   textarea.selectionStart = textarea.selectionEnd = textarea.value.length;
   var editorRect = synthesizeQueryEditorRect();