Revert incorrectly committed changes ab657569f554 and a396f4262479
authorRobert O'Callahan <robert@ocallahan.org>
Sat, 24 Oct 2015 22:38:22 +1300
changeset 304553 b70e89c03c5656ba5eff891fd0bcbb3ec044aa91
parent 304552 a396f4262479a5695c918f59bacd542ba21448b0
child 304554 f5ed98fdc16eb2395b41f5a3f5d91076e4705fc0
push id1001
push userraliiev@mozilla.com
push dateMon, 18 Jan 2016 19:06:03 +0000
treeherdermozilla-release@8b89261f3ac4 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone44.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
Revert incorrectly committed changes ab657569f554 and a396f4262479
accessible/base/NotificationController.cpp
accessible/base/nsAccessibilityService.cpp
accessible/base/nsTextEquivUtils.cpp
accessible/generic/Accessible.cpp
accessible/generic/HyperTextAccessible.cpp
accessible/tests/mochitest/jsat/test_traversal.html
accessible/tests/mochitest/pivot/test_virtualcursor.html
accessible/tests/mochitest/text/test_doc.html
accessible/tests/mochitest/text/test_hypertext.html
accessible/tests/mochitest/text/test_lineboundary.html
accessible/tests/mochitest/text/test_wordboundary.html
accessible/tests/mochitest/tree/test_txtcntr.html
dom/base/FragmentOrElement.cpp
dom/base/nsRange.cpp
dom/base/nsRange.h
dom/html/nsGenericHTMLElement.cpp
dom/html/nsGenericHTMLElement.h
dom/webidl/HTMLElement.webidl
gfx/tests/gtest/TestSkipChars.cpp
gfx/thebes/gfxSkipChars.h
layout/generic/nsIFrame.h
layout/generic/nsTextFrame.cpp
layout/generic/nsTextFrame.h
testing/web-platform/meta/MANIFEST.json
testing/web-platform/tests/innerText/getter-tests.js
testing/web-platform/tests/innerText/getter.html
testing/web-platform/tests/innerText/setter-tests.js
testing/web-platform/tests/innerText/setter.html
--- a/accessible/base/NotificationController.cpp
+++ b/accessible/base/NotificationController.cpp
@@ -223,21 +223,22 @@ NotificationController::WillRefresh(mozi
       NS_ASSERTION(!textAcc,
                    "Text node isn't rendered but accessible is kept alive!");
       continue;
     }
 
     nsIContent* containerElm = containerNode->IsElement() ?
       containerNode->AsElement() : nullptr;
 
-    nsIFrame::RenderedText text = textFrame->GetRenderedText();
+    nsAutoString text;
+    textFrame->GetRenderedText(&text);
 
     // Remove text accessible if rendered text is empty.
     if (textAcc) {
-      if (text.mString.IsEmpty()) {
+      if (text.IsEmpty()) {
   #ifdef A11Y_LOG
         if (logging::IsEnabled(logging::eTree | logging::eText)) {
           logging::MsgBegin("TREE", "text node lost its content");
           logging::Node("container", containerElm);
           logging::Node("content", textNode);
           logging::MsgEnd();
         }
   #endif
@@ -250,27 +251,27 @@ NotificationController::WillRefresh(mozi
   #ifdef A11Y_LOG
       if (logging::IsEnabled(logging::eText)) {
         logging::MsgBegin("TEXT", "text may be changed");
         logging::Node("container", containerElm);
         logging::Node("content", textNode);
         logging::MsgEntry("old text '%s'",
                           NS_ConvertUTF16toUTF8(textAcc->AsTextLeaf()->Text()).get());
         logging::MsgEntry("new text: '%s'",
-                          NS_ConvertUTF16toUTF8(text.mString).get());
+                          NS_ConvertUTF16toUTF8(text).get());
         logging::MsgEnd();
       }
   #endif
 
-      TextUpdater::Run(mDocument, textAcc->AsTextLeaf(), text.mString);
+      TextUpdater::Run(mDocument, textAcc->AsTextLeaf(), text);
       continue;
     }
 
     // Append an accessible if rendered text is not empty.
-    if (!text.mString.IsEmpty()) {
+    if (!text.IsEmpty()) {
   #ifdef A11Y_LOG
       if (logging::IsEnabled(logging::eTree | logging::eText)) {
         logging::MsgBegin("TREE", "text node gains new content");
         logging::Node("container", containerElm);
         logging::Node("content", textNode);
         logging::MsgEnd();
       }
   #endif
--- a/accessible/base/nsAccessibilityService.cpp
+++ b/accessible/base/nsAccessibilityService.cpp
@@ -1086,33 +1086,34 @@ nsAccessibilityService::GetOrCreateAcces
                "Image map manages the area accessible creation!");
 #endif
 
   // Attempt to create an accessible based on what we know.
   RefPtr<Accessible> newAcc;
 
   // Create accessible for visible text frames.
   if (content->IsNodeOfType(nsINode::eTEXT)) {
-    nsIFrame::RenderedText text = frame->GetRenderedText();
+    nsAutoString text;
+    frame->GetRenderedText(&text, nullptr, nullptr, 0, UINT32_MAX);
     // Ignore not rendered text nodes and whitespace text nodes between table
     // cells.
-    if (text.mString.IsEmpty() ||
-        (aContext->IsTableRow() && nsCoreUtils::IsWhitespaceString(text.mString))) {
+    if (text.IsEmpty() ||
+        (aContext->IsTableRow() && nsCoreUtils::IsWhitespaceString(text))) {
       if (aIsSubtreeHidden)
         *aIsSubtreeHidden = true;
 
       return nullptr;
     }
 
     newAcc = CreateAccessibleByFrameType(frame, content, aContext);
     if (!aContext->IsAcceptableChild(newAcc))
       return nullptr;
 
     document->BindToDocument(newAcc, nullptr);
-    newAcc->AsTextLeaf()->SetText(text.mString);
+    newAcc->AsTextLeaf()->SetText(text);
     return newAcc;
   }
 
   if (content->IsHTMLElement(nsGkAtoms::map)) {
     // Create hyper text accessible for HTML map if it is used to group links
     // (see http://www.w3.org/TR/WCAG10-HTML-TECHS/#group-bypass). If the HTML
     // map rect is empty then it is used for links grouping. Otherwise it should
     // be used in conjunction with HTML image element and in this case we don't
--- a/accessible/base/nsTextEquivUtils.cpp
+++ b/accessible/base/nsTextEquivUtils.cpp
@@ -134,18 +134,18 @@ nsTextEquivUtils::AppendTextEquivFromTex
           }
         }
       }
     }
     
     if (aContent->TextLength() > 0) {
       nsIFrame *frame = aContent->GetPrimaryFrame();
       if (frame) {
-        nsIFrame::RenderedText text = frame->GetRenderedText();
-        aString->Append(text.mString);
+        nsresult rv = frame->GetRenderedText(aString);
+        NS_ENSURE_SUCCESS(rv, rv);
       } else {
         // If aContent is an object that is display: none, we have no a frame.
         aContent->AppendTextTo(*aString);
       }
       if (isHTMLBlock && !aString->IsEmpty()) {
         aString->Append(char16_t(' '));
       }
     }
--- a/accessible/generic/Accessible.cpp
+++ b/accessible/generic/Accessible.cpp
@@ -389,20 +389,20 @@ Accessible::VisibilityState()
   // Zero area rects can occur in the first frame of a multi-frame text flow,
   // in which case the rendered text is not empty and the frame should not be
   // marked invisible.
   // XXX Can we just remove this check? Why do we need to mark empty
   // text invisible?
   if (frame->GetType() == nsGkAtoms::textFrame &&
       !(frame->GetStateBits() & NS_FRAME_OUT_OF_FLOW) &&
       frame->GetRect().IsEmpty()) {
-    nsIFrame::RenderedText text = frame->GetRenderedText();
-    if (text.mString.IsEmpty()) {
+    nsAutoString renderedText;
+    frame->GetRenderedText(&renderedText, nullptr, nullptr, 0, 1);
+    if (renderedText.IsEmpty())
       return states::INVISIBLE;
-    }
   }
 
   return 0;
 }
 
 uint64_t
 Accessible::NativeState()
 {
--- a/accessible/generic/HyperTextAccessible.cpp
+++ b/accessible/generic/HyperTextAccessible.cpp
@@ -1979,19 +1979,27 @@ HyperTextAccessible::ContentToRenderedOf
     return NS_OK;
   }
 
   NS_ASSERTION(aFrame->GetType() == nsGkAtoms::textFrame,
                "Need text frame for offset conversion");
   NS_ASSERTION(aFrame->GetPrevContinuation() == nullptr,
                "Call on primary frame only");
 
-  nsIFrame::RenderedText text = aFrame->GetRenderedText(aContentOffset,
-      aContentOffset + 1);
-  *aRenderedOffset = text.mOffsetWithinNodeRenderedText;
+  gfxSkipChars skipChars;
+  gfxSkipCharsIterator iter;
+  // Only get info up to original offset, we know that will be larger than skipped offset
+  nsresult rv = aFrame->GetRenderedText(nullptr, &skipChars, &iter, 0, aContentOffset);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  uint32_t ourRenderedStart = iter.GetSkippedOffset();
+  int32_t ourContentStart = iter.GetOriginalOffset();
+
+  *aRenderedOffset = iter.ConvertOriginalToSkipped(aContentOffset + ourContentStart) -
+                    ourRenderedStart;
 
   return NS_OK;
 }
 
 nsresult
 HyperTextAccessible::RenderedToContentOffset(nsIFrame* aFrame, uint32_t aRenderedOffset,
                                              int32_t* aContentOffset) const
 {
@@ -2003,19 +2011,26 @@ HyperTextAccessible::RenderedToContentOf
   *aContentOffset = 0;
   NS_ENSURE_TRUE(aFrame, NS_ERROR_FAILURE);
 
   NS_ASSERTION(aFrame->GetType() == nsGkAtoms::textFrame,
                "Need text frame for offset conversion");
   NS_ASSERTION(aFrame->GetPrevContinuation() == nullptr,
                "Call on primary frame only");
 
-  nsIFrame::RenderedText text = aFrame->GetRenderedText(aRenderedOffset,
-      aRenderedOffset + 1, nsIFrame::TextOffsetType::OFFSETS_IN_RENDERED_TEXT);
-  *aContentOffset = text.mOffsetWithinNodeText;
+  gfxSkipChars skipChars;
+  gfxSkipCharsIterator iter;
+  // We only need info up to skipped offset -- that is what we're converting to original offset
+  nsresult rv = aFrame->GetRenderedText(nullptr, &skipChars, &iter, 0, aRenderedOffset);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  uint32_t ourRenderedStart = iter.GetSkippedOffset();
+  int32_t ourContentStart = iter.GetOriginalOffset();
+
+  *aContentOffset = iter.ConvertSkippedToOriginal(aRenderedOffset + ourRenderedStart) - ourContentStart;
 
   return NS_OK;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // HyperTextAccessible public
 
 int32_t
--- a/accessible/tests/mochitest/jsat/test_traversal.html
+++ b/accessible/tests/mochitest/jsat/test_traversal.html
@@ -108,28 +108,28 @@
                               'Or me! ', 'Value 1', 'Value 2', 'Value 3',
                               'Electronic mailing address:', 'input-1-5',
                               'button-1-3', 'heading-2', 'heading-3',
                               'button-2-1', 'button-2-2', 'button-2-3',
                               'button-2-4', 'Programming Language',
                               'A esoteric weapon wielded by only the most ' +
                               'formidable warriors, for its unrelenting strict' +
                               ' power is unfathomable.',
-                              '• Lists of Programming Languages', 'Lisp',
+                              '• Lists of Programming Languages', 'Lisp ',
                               '1. Scheme', '2. Racket', '3. Clojure',
                               '4. Standard Lisp', 'link-0', ' Lisp',
                               'checkbox-1-5', ' LeLisp', '• JavaScript',
                               'heading-5', 'image-2', 'image-3',
                               'Not actually an image', 'link-1', 'anchor-1',
                               'link-2', 'anchor-2', 'link-3', '3', '1', '4',
                               '1', 'Sunday', 'M', 'Week 1', '3', '4', '7', '2',
                               '5 8', 'gridcell4', 'Just an innocuous separator',
                               'Dirty Words', 'Meaning', 'Mud', 'Wet Dirt',
                               'Dirt', 'Messy Stuff', 'statusbar-1', 'statusbar-2',
-                              'switch-1', 'This is a MathML formula', 'math-1',
+                              'switch-1', 'This is a MathML formula ', 'math-1',
                               'with some text after.']);
 
       queueTraversalSequence(gQueue, docAcc, TraversalRules.Landmark, null,
                              ['header-1', 'main-1', 'footer-1']);
 
 
       queueTraversalSequence(gQueue, docAcc, TraversalRules.Control, null,
                              ['input-1-1', 'label-1-2', 'button-1-1',
--- a/accessible/tests/mochitest/pivot/test_virtualcursor.html
+++ b/accessible/tests/mochitest/pivot/test_virtualcursor.html
@@ -47,17 +47,17 @@
 
       queueTraversalSequence(gQueue, docAcc, HeadersTraversalRule, null,
                              ['heading-1-1', 'heading-2-1', 'heading-2-2']);
 
       queueTraversalSequence(
         gQueue, docAcc, ObjectTraversalRule, null,
         ['Main Title', 'Lorem ipsum ',
          'dolor', ' sit amet. Integer vitae urna leo, id ',
-         'semper', ' nulla.', 'Second Section Title',
+         'semper', ' nulla. ', 'Second Section Title',
          'Sed accumsan luctus lacus, vitae mollis arcu tristique vulputate.',
          'An ', 'embedded', ' document.', 'Hide me', 'Link 1', 'Link 2',
          'Link 3', 'Hello', 'World']);
 
       // Just a random smoke test to see if our setTextRange works.
       gQueue.push(
         new setVCRangeInvoker(
           docAcc,
@@ -85,17 +85,17 @@
       // Attempting a coordinate outside any header, should move to null
       gQueue.push(new moveVCCoordInvoker(docAcc, x - 1, y - 1, false,
                                          HeadersTraversalRule, null));
 
       queueTraversalSequence(
         gQueue, docAcc, ObjectTraversalRule,
         getAccessible(doc.getElementById('paragraph-1')),
         ['Lorem ipsum ', 'dolor', ' sit amet. Integer vitae urna leo, id ',
-         'semper', ' nulla.']);
+         'semper', ' nulla. ']);
 
       gQueue.push(new setModalRootInvoker(docAcc, docAcc.parent,
                                           NS_ERROR_INVALID_ARG));
 
       // Put cursor in an ignored subtree
       // set isFromUserInput to false, just to test..
       gQueue.push(new setVCPosInvoker(docAcc, null, null,
                                       getAccessible(doc.getElementById("hidden-link")),
--- a/accessible/tests/mochitest/text/test_doc.html
+++ b/accessible/tests/mochitest/text/test_doc.html
@@ -11,18 +11,18 @@
           src="../common.js"></script>
   <script type="application/javascript"
           src="../text.js"></script>
   <script type="application/javascript">
     
     function doTest()
     {
       var iframeDoc = [ getNode("iframe").contentDocument ];
-      testCharacterCount(iframeDoc, 13);
-      testText(iframeDoc, 0, 13, "outbodyinbody");
+      testCharacterCount(iframeDoc, 15);
+      testText(iframeDoc, 0, 15, "outbody inbody ");
 
       SimpleTest.finish();
     }
 
     SimpleTest.waitForExplicitFinish();
     addA11yLoadEvent(doTest);
   </script>
 </head>
--- a/accessible/tests/mochitest/text/test_hypertext.html
+++ b/accessible/tests/mochitest/text/test_hypertext.html
@@ -53,17 +53,17 @@
       testText(IDs, 0, 1, "h");
       testText(IDs, 5, 7, " " + kEmbedChar);
       testText(IDs, 10, 13, "e " + kEmbedChar);
       testText(IDs, 0, 13, "hello " + kEmbedChar + " see " + kEmbedChar);
 
       ////////////////////////////////////////////////////////////////////////
       // getTextAtOffset line boundary
 
-      testTextAtOffset(0, BOUNDARY_LINE_START, "line", 0, 4,
+      testTextAtOffset(0, BOUNDARY_LINE_START, "line ", 0, 5,
                        "hypertext3", kOk, kOk, kOk);
 
       // XXX: see bug 634202.
       testTextAtOffset(0, BOUNDARY_LINE_START, "line ", 0, 5,
                        "hypertext4", kTodo, kOk, kTodo);
 
       //////////////////////////////////////////////////////////////////////////
       // list
@@ -117,17 +117,17 @@
 
   <p id="display"></p>
   <div id="content" style="display: none"></div>
   <pre id="test">
   </pre>
 
   <div id="nulltext"></div>
 
-  <div id="hypertext">hello <a>friend</a> see <img src="about:blank"></div>
+  <div id="hypertext">hello <a>friend</a> see <img></div>
   <div id="hypertext2">hello <a>friend</a> see <input></div>
   <ol id="list">
     <li id="listitem">foo</li>
     <li id="listitemnone">bar</li>
   </ol>
 
   <div id="hypertext3">line
 <!-- haha -->
--- a/accessible/tests/mochitest/text/test_lineboundary.html
+++ b/accessible/tests/mochitest/text/test_lineboundary.html
@@ -9,19 +9,19 @@
   <script type="application/javascript"
           src="../common.js"></script>
   <script type="application/javascript"
           src="../text.js"></script>
   <script type="application/javascript">
     function doTest()
     {
       testTextAtOffset("line_test_1", BOUNDARY_LINE_START,
-                       [[0, 5, "Line 1", 0, 6],
-                        [6, 6, "", 6, 6],
-                        [7, 13, "Line 3", 7, 13]]);
+                       [[0, 6, "Line 1 ", 0, 7],
+                        [7, 7, "", 7, 7],
+                        [8, 15, "Line 3 ", 8, 15]]);
 
       //////////////////////////////////////////////////////////////////////////
       // __h__e__l__l__o__ __m__y__ __f__r__i__e__n__d__
       //  0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15
 
       var IDs = [ "input", "div", "editable", "textarea",
                   getNode("ta", getNode("ta_cntr").contentDocument) ];
 
@@ -109,20 +109,20 @@
       testTextAtOffset([ getAccessible("ht_2").firstChild.firstChild ],
                        BOUNDARY_LINE_START,
                        [ [ 0, 3, "foo", 0, 3 ] ]);
       testTextAtOffset([ getAccessible("ht_3").firstChild.firstChild ],
                        BOUNDARY_LINE_START,
                        [ [ 0, 3, "foo\n", 0, 4 ], [ 4, 4, "", 4, 4 ] ]);
 
       //////////////////////////////////////////////////////////////////////////
-      // 'Hello world'
+      // 'Hello world ' (\n is rendered as space)
 
       testTextAtOffset([ "ht_4" ], BOUNDARY_LINE_START,
-                       [ [ 0, 11, "Hello world", 0, 11 ] ]);
+                       [ [ 0, 12, "Hello world ", 0, 12 ] ]);
 
       //////////////////////////////////////////////////////////////////////////
       // list items
 
       testTextAtOffset([ "li1" ], BOUNDARY_LINE_START,
                        [ [ 0, 6, kDiscBulletText + "Item", 0, 6 ] ]);
       testTextAtOffset([ "li2" ], BOUNDARY_LINE_START,
                        [ [ 0, 2, kDiscBulletText, 0, 2 ] ]);
--- a/accessible/tests/mochitest/text/test_wordboundary.html
+++ b/accessible/tests/mochitest/text/test_wordboundary.html
@@ -37,30 +37,37 @@
       // "hello "
       // __h__e__l__l__o__ __
       //  0  1  2  3  4  5  6
       var ids = [ "i2", "d2", "e2", "t2" ];
       testTextBeforeOffset(ids, BOUNDARY_WORD_START,
                            [ [ 0, 6, "", 0, 0 ] ]);
       testTextBeforeOffset(ids, BOUNDARY_WORD_END,
                            [ [ 0, 5, "", 0, 0 ],
-                             [ 6, 6, "hello", 0, 5 ]
+                             [ 6, 6, "hello", 0, 5,
+                               [ [6, "e2", kTodo, kOk, kTodo ] ]
+                             ]
                            ]);
 
       testTextAtOffset(ids, BOUNDARY_WORD_START,
                        [ [ 0, 6, "hello ", 0, 6 ] ]);
       testTextAtOffset(ids, BOUNDARY_WORD_END,
                        [ [ 0, 4, "hello", 0, 5 ],
-                         [ 5, 6, " ", 5, 6 ]
+                         [ 5, 6, " ", 5, 6,
+                           [ [ 5, "e2", kTodo, kTodo, kOk ],
+                             [ 6, "e2", kTodo, kTodo, kOk ] ]
+                         ]
                        ]);
 
       testTextAfterOffset(ids, BOUNDARY_WORD_START,
                           [ [ 0, 6, "", 6, 6 ] ]);
       testTextAfterOffset(ids, BOUNDARY_WORD_END,
-                          [ [ 0, 5, " ", 5, 6 ],
+                          [ [ 0, 5, " ", 5, 6,
+                              [ [ 5, "e2", kTodo, kTodo, kOk ] ]
+                            ],
                             [ 6, 6, "", 6, 6 ]
                           ]);
 
       // "hello all"
       // __h__e__l__l__o__ __a__l__l__
       //  0  1  2  3  4  5  6  7  8  9
       ids = [ "i6", "d6", "e6", "t6" ];
       testTextBeforeOffset(ids, BOUNDARY_WORD_START,
@@ -244,17 +251,17 @@
 
   <input id="i1" value="hello"/>
   <div id="d1">hello</div>
   <div id="e1" contenteditable="true">hello</div>
   <textarea id="t1">hello</textarea>
 
   <input id="i2" value="hello "/>
   <pre><div id="d2">hello </div></pre>
-  <div id="e2" contenteditable="true" style='white-space:pre'>hello </div>
+  <div id="e2" contenteditable="true">hello </div>
   <textarea id="t2">hello </textarea>
 
   <input id="i6" value="hello all"/>
   <div id="d6">hello all</div>
   <div id="e6" contenteditable="true">hello all</div>
   <textarea id="t6">hello all</textarea>
 
   <input id="i7" value="hello my friend"/>
--- a/accessible/tests/mochitest/tree/test_txtcntr.html
+++ b/accessible/tests/mochitest/tree/test_txtcntr.html
@@ -44,52 +44,52 @@
             role: ROLE_TEXT_LEAF,
             name: "Hello2"
           },
           {
             role: ROLE_SEPARATOR
           },
           {
             role: ROLE_TEXT_LEAF,
-            name: "Hello3"
+            name: "Hello3 "
           },
           {
             role: ROLE_PARAGRAPH,
             children: [
               {
                 role: ROLE_TEXT_LEAF,
-                name: "Hello4"
+                name: "Hello4 "
               }
             ]
           }
         ]
       };
 
       testAccessibleTree("c3", accTree);
 
       // contentEditable div
       accTree = {
         role: ROLE_SECTION,
         children: [
           {
             role: ROLE_TEXT_LEAF,
-            name: "helllo"
+            name: "helllo "
           },
           {
             role: ROLE_PARAGRAPH,
             children: [
               {
                 role: ROLE_TEXT_LEAF,
                 name: "blabla"
               }
             ]
           },
           {
             role: ROLE_TEXT_LEAF,
-            name: "hello"
+            name: "hello "
           }
         ]
       };
 
       testAccessibleTree("c4", accTree);
 
       // blockquote
       accTree = {
--- a/dom/base/FragmentOrElement.cpp
+++ b/dom/base/FragmentOrElement.cpp
@@ -1154,17 +1154,17 @@ FragmentOrElement::RemoveChildAt(uint32_
     doRemoveChildAt(aIndex, aNotify, oldKid, mAttrsAndChildren);
   }
 }
 
 void
 FragmentOrElement::GetTextContentInternal(nsAString& aTextContent,
                                           ErrorResult& aError)
 {
-  if (!nsContentUtils::GetNodeTextContent(this, true, aTextContent, fallible)) {
+  if(!nsContentUtils::GetNodeTextContent(this, true, aTextContent, fallible)) {
     aError.Throw(NS_ERROR_OUT_OF_MEMORY);
   }
 }
 
 void
 FragmentOrElement::SetTextContentInternal(const nsAString& aTextContent,
                                           ErrorResult& aError)
 {
--- a/dom/base/nsRange.cpp
+++ b/dom/base/nsRange.cpp
@@ -30,19 +30,16 @@
 #include "mozilla/dom/DocumentType.h"
 #include "mozilla/dom/RangeBinding.h"
 #include "mozilla/dom/DOMRect.h"
 #include "mozilla/dom/ShadowRoot.h"
 #include "mozilla/dom/Selection.h"
 #include "mozilla/Telemetry.h"
 #include "mozilla/Likely.h"
 #include "nsCSSFrameConstructor.h"
-#include "nsStyleStruct.h"
-#include "nsStyleStructInlines.h"
-#include "nsComputedDOMStyle.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 JSObject*
 nsRange::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
 {
   return RangeBinding::Wrap(aCx, this, aGivenProto);
@@ -3191,241 +3188,8 @@ nsRange::ExcludeNonSelectableNodes(nsTAr
         }
       }
       if (iter->IsDone()) {
         return;
       }
     }
   }
 }
-
-struct InnerTextAccumulator {
-  nsString& mString;
-  int8_t mRequiredLineBreakCount;
-  InnerTextAccumulator(mozilla::dom::DOMString& aValue)
-    : mString(aValue.AsAString()), mRequiredLineBreakCount(0) {}
-  void FlushLineBreaks()
-  {
-    while (mRequiredLineBreakCount > 0) {
-      // Required line breaks at the start of the text are suppressed.
-      if (!mString.IsEmpty()) {
-        mString.Append('\n');
-      }
-      --mRequiredLineBreakCount;
-    }
-  }
-  void Append(char ch)
-  {
-    Append(nsAutoString(ch));
-  }
-  void Append(const nsAString& aString)
-  {
-    if (aString.IsEmpty()) {
-      return;
-    }
-    FlushLineBreaks();
-    mString.Append(aString);
-  }
-  void AddRequiredLineBreakCount(int8_t aCount)
-  {
-    mRequiredLineBreakCount = std::max(mRequiredLineBreakCount, aCount);
-  }
-};
-
-static bool
-IsVisibleAndNotInReplacedElement(nsIFrame* aFrame)
-{
-  if (!aFrame || !aFrame->StyleVisibility()->IsVisible()) {
-    return false;
-  }
-  for (nsIFrame* f = aFrame->GetParent(); f; f = f->GetParent()) {
-    if (f->GetContent() && f->GetContent()->IsHTMLElement(nsGkAtoms::button)) {
-      continue;
-    }
-    if (f->IsFrameOfType(nsIFrame::eReplaced)) {
-      return false;
-    }
-  }
-  return true;
-}
-
-static bool
-ElementIsVisible(nsIContent* aContent)
-{
-  Element* elem = aContent->AsElement();
-  if (!elem) {
-    return false;
-  }
-  RefPtr<nsStyleContext> sc = nsComputedDOMStyle::GetStyleContextForElement(
-      elem, nullptr, nullptr);
-  return sc && sc->StyleVisibility()->IsVisible();
-}
-
-static void
-AppendTransformedText(InnerTextAccumulator& aResult,
-                      nsGenericDOMDataNode* aTextNode,
-                      int32_t aStart, int32_t aEnd)
-{
-  nsIFrame* frame = aTextNode->GetPrimaryFrame();
-  if (!IsVisibleAndNotInReplacedElement(frame)) {
-    return;
-  }
-  nsIFrame::RenderedText text = frame->GetRenderedText(aStart, aEnd);
-  aResult.Append(text.mString);
-}
-
-enum TreeTraversalState {
-  AT_NODE,
-  AFTER_NODE
-};
-
-static int8_t
-GetRequiredInnerTextLineBreakCount(nsIFrame* aFrame)
-{
-  if (aFrame->GetContent()->IsHTMLElement(nsGkAtoms::p)) {
-    return 2;
-  }
-  const nsStyleDisplay* styleDisplay = aFrame->StyleDisplay();
-  if (styleDisplay->IsBlockOutside(aFrame) ||
-      styleDisplay->mDisplay == NS_STYLE_DISPLAY_TABLE_CAPTION) {
-    return 1;
-  }
-  return 0;
-}
-
-static bool
-IsLastCellOfRow(nsIFrame* aFrame)
-{
-  nsIAtom* type = aFrame->GetType();
-  if (type != nsGkAtoms::tableCellFrame &&
-      type != nsGkAtoms::bcTableCellFrame) {
-    return true;
-  }
-  for (nsIFrame* c = aFrame; c; c = c->GetNextContinuation()) {
-    if (c->GetNextSibling()) {
-      return false;
-    }
-  }
-  return true;
-}
-
-static bool
-IsLastRowOfRowGroup(nsIFrame* aFrame)
-{
-  if (aFrame->GetType() != nsGkAtoms::tableRowFrame) {
-    return true;
-  }
-  for (nsIFrame* c = aFrame; c; c = c->GetNextContinuation()) {
-    if (c->GetNextSibling()) {
-      return false;
-    }
-  }
-  return true;
-}
-
-static bool
-IsLastNonemptyRowGroupOfTable(nsIFrame* aFrame)
-{
-  if (aFrame->GetType() != nsGkAtoms::tableRowGroupFrame) {
-    return true;
-  }
-  for (nsIFrame* c = aFrame; c; c = c->GetNextContinuation()) {
-    for (nsIFrame* next = c->GetNextSibling(); next; next = next->GetNextSibling()) {
-      if (next->GetFirstPrincipalChild()) {
-        return false;
-      }
-    }
-  }
-  return true;
-}
-
-void
-nsRange::GetInnerTextNoFlush(mozilla::dom::DOMString& aValue,
-                             mozilla::ErrorResult& aError)
-{
-  InnerTextAccumulator result(aValue);
-  nsIContent* currentNode = mStartParent->AsContent();
-  TreeTraversalState currentState = AFTER_NODE;
-  if (mStartParent->IsNodeOfType(nsINode::eTEXT)) {
-    auto t = static_cast<nsGenericDOMDataNode*>(mStartParent.get());
-    if (mStartParent == mEndParent) {
-      AppendTransformedText(result, t, mStartOffset, mEndOffset);
-      return;
-    }
-    AppendTransformedText(result, t, mStartOffset, t->TextLength());
-  } else {
-    if (uint32_t(mStartOffset) < mStartParent->GetChildCount()) {
-      currentNode = mStartParent->GetChildAt(mStartOffset);
-      currentState = AT_NODE;
-    }
-  }
-
-  nsIContent* endNode = mEndParent->AsContent();
-  TreeTraversalState endState = AFTER_NODE;
-  if (mEndParent->IsNodeOfType(nsINode::eTEXT)) {
-    endState = AT_NODE;
-  } else {
-    if (uint32_t(mEndOffset) < mEndParent->GetChildCount()) {
-      endNode = mEndParent->GetChildAt(mEndOffset);
-      endState = AT_NODE;
-    }
-  }
-
-  while (currentNode != endNode || currentState != endState) {
-    nsIFrame* f = currentNode->GetPrimaryFrame();
-    bool isVisibleAndNotReplaced = IsVisibleAndNotInReplacedElement(f);
-    if (currentState == AT_NODE) {
-      bool isText = currentNode->IsNodeOfType(nsINode::eTEXT);
-      if (isText && currentNode->GetParent()->IsHTMLElement(nsGkAtoms::rp) &&
-          ElementIsVisible(currentNode->GetParent())) {
-        nsAutoString str;
-        currentNode->GetTextContent(str, aError);
-        result.Append(str);
-      } else if (isVisibleAndNotReplaced) {
-        result.AddRequiredLineBreakCount(GetRequiredInnerTextLineBreakCount(f));
-        if (isText) {
-          nsIFrame::RenderedText text = f->GetRenderedText();
-          result.Append(text.mString);
-        }
-      }
-      nsIContent* child = currentNode->GetFirstChild();
-      if (child) {
-        currentNode = child;
-      } else {
-        currentState = AFTER_NODE;
-      }
-    } else {
-      if (isVisibleAndNotReplaced) {
-        if (currentNode->IsHTMLElement(nsGkAtoms::br)) {
-          result.Append('\n');
-        }
-        switch (f->StyleDisplay()->mDisplay) {
-        case NS_STYLE_DISPLAY_TABLE_CELL:
-          if (!IsLastCellOfRow(f)) {
-            result.Append('\t');
-          }
-          break;
-        case NS_STYLE_DISPLAY_TABLE_ROW:
-          if (!IsLastRowOfRowGroup(f) ||
-              !IsLastNonemptyRowGroupOfTable(f->GetParent())) {
-            result.Append('\n');
-          }
-          break;
-        }
-        result.AddRequiredLineBreakCount(GetRequiredInnerTextLineBreakCount(f));
-      }
-      nsIContent* next = currentNode->GetNextSibling();
-      if (next) {
-        currentNode = next;
-        currentState = AT_NODE;
-      } else {
-        currentNode = currentNode->GetParent();
-      }
-    }
-  }
-
-  if (mEndParent->IsNodeOfType(nsINode::eTEXT)) {
-    nsGenericDOMDataNode* t = static_cast<nsGenericDOMDataNode*>(mEndParent.get());
-    AppendTransformedText(result, t, 0, mEndOffset);
-  }
-  // Do not flush trailing line breaks! Required breaks at the end of the text
-  // are suppressed.
-}
--- a/dom/base/nsRange.h
+++ b/dom/base/nsRange.h
@@ -207,18 +207,16 @@ public:
   void SetStart(nsINode& aNode, uint32_t aOffset, ErrorResult& aErr);
   void SetStartAfter(nsINode& aNode, ErrorResult& aErr);
   void SetStartBefore(nsINode& aNode, ErrorResult& aErr);
   void SurroundContents(nsINode& aNode, ErrorResult& aErr);
   already_AddRefed<DOMRect> GetBoundingClientRect(bool aClampToEdge = true,
                                                   bool aFlushLayout = true);
   already_AddRefed<DOMRectList> GetClientRects(bool aClampToEdge = true,
                                                bool aFlushLayout = true);
-  void GetInnerTextNoFlush(mozilla::dom::DOMString& aValue,
-                           mozilla::ErrorResult& aError);
 
   nsINode* GetParentObject() const { return mOwner; }
   virtual JSObject* WrapObject(JSContext* cx, JS::Handle<JSObject*> aGivenProto) override final;
 
 private:
   // no copy's or assigns
   nsRange(const nsRange&);
   nsRange& operator=(const nsRange&);
--- a/dom/html/nsGenericHTMLElement.cpp
+++ b/dom/html/nsGenericHTMLElement.cpp
@@ -79,18 +79,16 @@
 #include "nsIEditor.h"
 #include "nsIEditorIMESupport.h"
 #include "nsLayoutUtils.h"
 #include "mozAutoDocUpdate.h"
 #include "nsHtml5Module.h"
 #include "nsITextControlElement.h"
 #include "mozilla/dom/Element.h"
 #include "HTMLFieldSetElement.h"
-#include "nsTextNode.h"
-#include "HTMLBRElement.h"
 #include "HTMLMenuElement.h"
 #include "nsDOMMutationObserver.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/dom/FromParser.h"
 #include "mozilla/dom/Link.h"
 #include "mozilla/dom/UndoManager.h"
 #include "mozilla/BloomFilter.h"
 
@@ -101,17 +99,16 @@
 #include "nsTextFragment.h"
 #include "mozilla/dom/BindingUtils.h"
 #include "mozilla/dom/TouchEvent.h"
 #include "mozilla/ErrorResult.h"
 #include "nsHTMLDocument.h"
 #include "nsGlobalWindow.h"
 #include "mozilla/dom/HTMLBodyElement.h"
 #include "imgIContainer.h"
-#include "nsComputedDOMStyle.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 /**
  * nsAutoFocusEvent is used to dispatch a focus event when a
  * nsGenericHTMLFormElement is binded to the tree with the autofocus attribute
  * enabled.
@@ -3292,110 +3289,8 @@ nsGenericHTMLElement::NewURIFromString(c
     // document. Fail here instead of returning the recursive URI
     // and waiting for the subsequent load to fail.
     NS_RELEASE(*aURI);
     return NS_ERROR_DOM_INVALID_STATE_ERR;
   }
 
   return NS_OK;
 }
-
-void
-nsGenericHTMLElement::GetInnerText(mozilla::dom::DOMString& aValue,
-                                   mozilla::ErrorResult& aError)
-{
-  if (!GetPrimaryFrame(Flush_Layout)) {
-    RefPtr<nsStyleContext> sc =
-        nsComputedDOMStyle::GetStyleContextForElementNoFlush(this, nullptr, nullptr);
-    if (!sc || sc->StyleDisplay()->mDisplay == NS_STYLE_DISPLAY_NONE ||
-        !GetCurrentDoc()) {
-      GetTextContentInternal(aValue, aError);
-      return;
-    }
-  }
-
-  RefPtr<nsRange> range;
-  nsresult rv = nsRange::CreateRange(static_cast<nsINode*>(this), 0, this,
-      GetChildCount(), getter_AddRefs(range));
-  if (NS_FAILED(rv)) {
-    aError.Throw(rv);
-    return;
-  }
-
-  range->GetInnerTextNoFlush(aValue, aError);
-}
-
-void
-nsGenericHTMLElement::SetInnerText(const nsAString& aValue)
-{
-  // Fire DOMNodeRemoved mutation events before we do anything else.
-  nsCOMPtr<nsIContent> kungFuDeathGrip;
-
-  // Batch possible DOMSubtreeModified events.
-  mozAutoSubtreeModified subtree(nullptr, nullptr);
-
-  // Scope firing mutation events so that we don't carry any state that
-  // might be stale
-  {
-    // We're relying on mozAutoSubtreeModified to keep a strong reference if
-    // needed.
-    nsIDocument* doc = OwnerDoc();
-
-    // Optimize the common case of there being no observers
-    if (nsContentUtils::HasMutationListeners(doc, NS_EVENT_BITS_MUTATION_NODEREMOVED)) {
-      subtree.UpdateTarget(doc, nullptr);
-      // Keep "this" alive during mutation listener firing
-      kungFuDeathGrip = this;
-      nsCOMPtr<nsINode> child;
-      for (child = nsINode::GetFirstChild();
-           child && child->GetParentNode() == this;
-           child = child->GetNextSibling()) {
-        nsContentUtils::MaybeFireNodeRemoved(child, this, doc);
-      }
-    }
-  }
-
-  // Might as well stick a batch around this since we're performing several
-  // mutations.
-  mozAutoDocUpdate updateBatch(GetComposedDoc(),
-    UPDATE_CONTENT_MODEL, true);
-  nsAutoMutationBatch mb;
-
-  uint32_t childCount = GetChildCount();
-
-  mb.Init(this, true, false);
-  for (uint32_t i = 0; i < childCount; ++i) {
-    RemoveChildAt(0, true);
-  }
-  mb.RemovalDone();
-
-  nsString str;
-  const char16_t* s = aValue.BeginReading();
-  const char16_t* end = aValue.EndReading();
-  while (true) {
-    if (s != end && *s == '\r' && s + 1 != end && s[1] == '\n') {
-      // a \r\n pair should only generate one <br>, so just skip the \r
-      ++s;
-    }
-    if (s == end || *s == '\r' || *s == '\n') {
-      if (!str.IsEmpty()) {
-        RefPtr<nsTextNode> textContent =
-            new nsTextNode(NodeInfo()->NodeInfoManager());
-        textContent->SetText(str, true);
-        AppendChildTo(textContent, true);
-      }
-      if (s == end) {
-        break;
-      }
-      str.SetLength(0);
-      already_AddRefed<mozilla::dom::NodeInfo> ni =
-          NodeInfo()->NodeInfoManager()->GetNodeInfo(nsGkAtoms::br,
-                      nullptr, kNameSpaceID_XHTML, nsIDOMNode::ELEMENT_NODE);
-      RefPtr<HTMLBRElement> br = new HTMLBRElement(ni);
-      AppendChildTo(br, true);
-    } else {
-      str.Append(*s);
-    }
-    ++s;
-  }
-
-  mb.NodesAdded();
-}
--- a/dom/html/nsGenericHTMLElement.h
+++ b/dom/html/nsGenericHTMLElement.h
@@ -236,19 +236,16 @@ public:
   {
     return mScrollgrab;
   }
   void SetScrollgrab(bool aValue)
   {
     mScrollgrab = aValue;
   }
 
-  void GetInnerText(mozilla::dom::DOMString& aValue, mozilla::ErrorResult& aError);
-  void SetInnerText(const nsAString& aValue);
-
   /**
    * Determine whether an attribute is an event (onclick, etc.)
    * @param aName the attribute
    * @return whether the name is an event handler name
    */
   virtual bool IsEventAttributeName(nsIAtom* aName) override;
 
 #define EVENT(name_, id_, type_, struct_) /* nothing; handled by nsINode */
--- a/dom/webidl/HTMLElement.webidl
+++ b/dom/webidl/HTMLElement.webidl
@@ -17,19 +17,16 @@ interface HTMLElement : Element {
            attribute DOMString title;
            attribute DOMString lang;
   //         attribute boolean translate;
   [SetterThrows, Pure]
            attribute DOMString dir;
   [Constant]
   readonly attribute DOMStringMap dataset;
 
-  [GetterThrows, Pure]
-           attribute DOMString innerText;
-
   // microdata 
   [SetterThrows, Pure]
            attribute boolean itemScope;
   [PutForwards=value,Constant] readonly attribute DOMSettableTokenList itemType;
   [SetterThrows, Pure]
            attribute DOMString itemId;
   [PutForwards=value,Constant] readonly attribute DOMSettableTokenList itemRef;
   [PutForwards=value,Constant] readonly attribute DOMSettableTokenList itemProp;
--- a/gfx/tests/gtest/TestSkipChars.cpp
+++ b/gfx/tests/gtest/TestSkipChars.cpp
@@ -77,17 +77,17 @@ TestIterator()
      9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
     18, 19, 20, 21, 22, 23, 24, 25, 26, 27 };
 
   for (uint32_t i = 0; i < mozilla::ArrayLength(expectSkipped1); i++) {
     EXPECT_TRUE(iter1.ConvertOriginalToSkipped(i) == expectSkipped1[i]) <<
       "[4] Check mapping of original to skipped for " << i;
   }
 
-  int32_t expectOriginal1[] =
+  uint32_t expectOriginal1[] =
   {  0,  1,  2,  3,  4,  5,  6,  7,  8,
     10, 11, 12, 13, 14, 15, 16, 17, 18,
     20, 21, 22, 23, 24, 25, 26, 27, 28 };
 
   for (uint32_t i = 0; i < mozilla::ArrayLength(expectOriginal1); i++) {
     EXPECT_TRUE(iter1.ConvertSkippedToOriginal(i) == expectOriginal1[i]) <<
       "[5] Check mapping of skipped to original for " << i;
   }
@@ -131,17 +131,17 @@ TestIterator()
      1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
      2,  2,  2,  2,  2,  2,  2,  2,  2,  2 };
 
   for (uint32_t i = 0; i < mozilla::ArrayLength(expectSkipped2); i++) {
     EXPECT_TRUE(iter2.ConvertOriginalToSkipped(i) == expectSkipped2[i]) <<
       "[9] Check mapping of original to skipped for " << i;
   }
 
-  int32_t expectOriginal2[] = { 9, 19, 29 };
+  uint32_t expectOriginal2[] = { 9, 19, 29 };
 
   for (uint32_t i = 0; i < mozilla::ArrayLength(expectOriginal2); i++) {
     EXPECT_TRUE(iter2.ConvertSkippedToOriginal(i) == expectOriginal2[i]) <<
       "[10] Check mapping of skipped to original for " << i;
   }
 
   bool expectIsOriginalSkipped2[] =
   {  true, true, true, true, true, true, true, true, true, false,
--- a/gfx/thebes/gfxSkipChars.h
+++ b/gfx/thebes/gfxSkipChars.h
@@ -230,17 +230,17 @@ public:
     void SetSkippedOffset(uint32_t aSkippedStringOffset);
 
     uint32_t ConvertOriginalToSkipped(int32_t aOriginalStringOffset)
     {
         SetOriginalOffset(aOriginalStringOffset);
         return GetSkippedOffset();
     }
 
-    int32_t ConvertSkippedToOriginal(uint32_t aSkippedStringOffset)
+    uint32_t ConvertSkippedToOriginal(int32_t aSkippedStringOffset)
     {
         SetSkippedOffset(aSkippedStringOffset);
         return GetOriginalOffset();
     }
 
     /**
      * Test if the character at the current position in the original string
      * is skipped or not. If aRunLength is non-null, then *aRunLength is set
--- a/layout/generic/nsIFrame.h
+++ b/layout/generic/nsIFrame.h
@@ -1888,46 +1888,36 @@ public:
    * @return 
    *    true if we can continue a "text run" through the frame. A
    *    text run is text that should be treated contiguously for line
    *    and word breaking.
    */
   virtual bool CanContinueTextRun() const = 0;
 
   /**
-   * Computes an approximation of the rendered text of the frame and its
-   * continuations. Returns nothing for non-text frames.
+   * Append the rendered text to the passed-in string.
    * The appended text will often not contain all the whitespace from source,
-   * depending on CSS white-space processing.
-   * if aEndOffset goes past end, use the text up to the string's end.
+   * depending on whether the CSS rule "white-space: pre" is active for this frame.
+   * if aStartOffset + aLength goes past end, or if aLength is not specified
+   * then use the text up to the string's end.
    * Call this on the primary frame for a text node.
-   * aStartOffset and aEndOffset can be content offsets or offsets in the
-   * rendered text, depending on aOffsetType.
-   * Returns a string, as well as offsets identifying the start of the text
-   * within the rendered text for the whole node, and within the text content
-   * of the node.
+   * @param aAppendToString   String to append text to, or null if text should not be returned
+   * @param aSkipChars         if aSkipIter is non-null, this must also be non-null.
+   * This gets used as backing data for the iterator so it should outlive the iterator.
+   * @param aSkipIter         Where to fill in the gfxSkipCharsIterator info, or null if not needed by caller
+   * @param aStartOffset       Skipped (rendered text) start offset
+   * @param aSkippedMaxLength  Maximum number of characters to return
+   * The iterator can be used to map content offsets to offsets in the returned string, or vice versa.
    */
-  struct RenderedText {
-    nsString mString;
-    uint32_t mOffsetWithinNodeRenderedText;
-    int32_t mOffsetWithinNodeText;
-    RenderedText() : mOffsetWithinNodeRenderedText(0),
-        mOffsetWithinNodeText(0) {}
-  };
-  enum class TextOffsetType {
-    // Passed-in start and end offsets are within the content text.
-    OFFSETS_IN_CONTENT_TEXT,
-    // Passed-in start and end offsets are within the rendered text.
-    OFFSETS_IN_RENDERED_TEXT
-  };
-  virtual RenderedText GetRenderedText(uint32_t aStartOffset = 0,
-                                       uint32_t aEndOffset = UINT32_MAX,
-                                       TextOffsetType aOffsetType =
-                                           TextOffsetType::OFFSETS_IN_CONTENT_TEXT)
-  { return RenderedText(); }
+  virtual nsresult GetRenderedText(nsAString* aAppendToString = nullptr,
+                                   gfxSkipChars* aSkipChars = nullptr,
+                                   gfxSkipCharsIterator* aSkipIter = nullptr,
+                                   uint32_t aSkippedStartOffset = 0,
+                                   uint32_t aSkippedMaxLength = UINT32_MAX)
+  { return NS_ERROR_NOT_IMPLEMENTED; }
 
   /**
    * Returns true if the frame contains any non-collapsed characters.
    * This method is only available for text frames, and it will return false
    * for all other frame types.
    */
   virtual bool HasAnyNoncollapsedCharacters()
   { return false; }
--- a/layout/generic/nsTextFrame.cpp
+++ b/layout/generic/nsTextFrame.cpp
@@ -3970,18 +3970,19 @@ nsTextPaintStyle::GetResolvedForeColor(n
 
 //-----------------------------------------------------------------------------
 
 #ifdef ACCESSIBILITY
 a11y::AccType
 nsTextFrame::AccessibleType()
 {
   if (IsEmpty()) {
-    RenderedText text = GetRenderedText();
-    if (text.mString.IsEmpty()) {
+    nsAutoString renderedWhitespace;
+    GetRenderedText(&renderedWhitespace, nullptr, nullptr, 0, 1);
+    if (renderedWhitespace.IsEmpty()) {
       return a11y::eNoType;
     }
   }
 
   return a11y::eTextLeafType;
 }
 #endif
 
@@ -4084,16 +4085,23 @@ public:
   virtual nsIFrame* FirstInFlow() const override;
   virtual nsIFrame* FirstContinuation() const override;
 
   virtual void AddInlineMinISize(nsRenderingContext *aRenderingContext,
                                  InlineMinISizeData *aData) override;
   virtual void AddInlinePrefISize(nsRenderingContext *aRenderingContext,
                                   InlinePrefISizeData *aData) override;
   
+  virtual nsresult GetRenderedText(nsAString* aString = nullptr,
+                                   gfxSkipChars* aSkipChars = nullptr,
+                                   gfxSkipCharsIterator* aSkipIter = nullptr,
+                                   uint32_t aSkippedStartOffset = 0,
+                                   uint32_t aSkippedMaxLength = UINT32_MAX) override
+  { return NS_ERROR_NOT_IMPLEMENTED; } // Call on a primary text frame only
+
 protected:
   explicit nsContinuingTextFrame(nsStyleContext* aContext) : nsTextFrame(aContext) {}
   nsIFrame* mPrevContinuation;
 };
 
 void
 nsContinuingTextFrame::Init(nsIContent*       aContent,
                             nsContainerFrame* aParent,
@@ -8869,161 +8877,90 @@ static char16_t TransformChar(nsTextFram
       aChar = ToTitleCase(aChar);
     }
     break;
   }
 
   return aChar;
 }
 
-static bool
-LineEndsInHardLineBreak(nsTextFrame* aFrame)
-{
-  nsIFrame* lineContainer = FindLineContainer(aFrame);
-  nsBlockFrame* block = do_QueryFrame(lineContainer);
-  if (!block) {
-    // Weird situation where we have a line layout without a block.
-    // No soft breaks occur in this situation.
-    return true;
-  }
-  bool foundValidLine;
-  nsBlockInFlowLineIterator iter(block, aFrame, &foundValidLine);
-  if (!foundValidLine) {
-    NS_ERROR("Invalid line!");
-    return true;
-  }
-  return !iter.GetLine()->IsLineWrapped();
-}
-
-nsIFrame::RenderedText
-nsTextFrame::GetRenderedText(uint32_t aStartOffset,
-                             uint32_t aEndOffset,
-                             TextOffsetType aOffsetType)
-{
-  NS_ASSERTION(!GetPrevContinuation(), "Must be called on first-in-flow");
-
-  // The handling of offsets could be more efficient...
-  RenderedText result;
+nsresult nsTextFrame::GetRenderedText(nsAString* aAppendToString,
+                                      gfxSkipChars* aSkipChars,
+                                      gfxSkipCharsIterator* aSkipIter,
+                                      uint32_t aSkippedStartOffset,
+                                      uint32_t aSkippedMaxLength)
+{
+  // The handling of aSkippedStartOffset and aSkippedMaxLength could be more efficient...
+  gfxSkipChars skipChars;
   nsTextFrame* textFrame;
   const nsTextFragment* textFrag = mContent->GetText();
-  uint32_t offsetInRenderedString = 0;
-  bool haveOffsets = false;
-
+  uint32_t keptCharsLength = 0;
+  uint32_t validCharsLength = 0;
+
+  // Build skipChars and copy text, for each text frame in this continuation block
   for (textFrame = this; textFrame;
        textFrame = static_cast<nsTextFrame*>(textFrame->GetNextContinuation())) {
+    // For each text frame continuation in this block ...
+
     if (textFrame->GetStateBits() & NS_FRAME_IS_DIRTY) {
-      // We don't trust dirty frames, especially when computing rendered text.
+      // We don't trust dirty frames, expecially when computing rendered text.
       break;
     }
 
     // Ensure the text run and grab the gfxSkipCharsIterator for it
     gfxSkipCharsIterator iter =
       textFrame->EnsureTextRun(nsTextFrame::eInflated);
-    if (!textFrame->mTextRun) {
-      break;
-    }
-    gfxSkipCharsIterator tmpIter = iter;
+    if (!textFrame->mTextRun)
+      return NS_ERROR_FAILURE;
 
     // Skip to the start of the text run, past ignored chars at start of line
-    TrimmedOffsets trimmedOffsets = textFrame->GetTrimmedOffsets(textFrag,
-       textFrame->IsAtEndOfLine() && LineEndsInHardLineBreak(textFrame));
-    bool trimmedSignificantNewline =
-        trimmedOffsets.GetEnd() < GetContentEnd() &&
-        HasSignificantTerminalNewline();
-    uint32_t skippedToRenderedStringOffset = offsetInRenderedString -
-        tmpIter.ConvertOriginalToSkipped(trimmedOffsets.mStart);
-    uint32_t nextOffsetInRenderedString =
-        tmpIter.ConvertOriginalToSkipped(trimmedOffsets.GetEnd()) +
-        (trimmedSignificantNewline ? 1 : 0) + skippedToRenderedStringOffset;
-
-    if (aOffsetType == TextOffsetType::OFFSETS_IN_RENDERED_TEXT) {
-      if (nextOffsetInRenderedString <= aStartOffset) {
-        offsetInRenderedString = nextOffsetInRenderedString;
-        continue;
-      }
-      if (!haveOffsets) {
-        result.mOffsetWithinNodeText =
-            tmpIter.ConvertSkippedToOriginal(aStartOffset - skippedToRenderedStringOffset);
-        result.mOffsetWithinNodeRenderedText = aStartOffset;
-        haveOffsets = true;
-      }
-      if (offsetInRenderedString >= aEndOffset) {
-        break;
-      }
-    } else {
-      if (uint32_t(textFrame->GetContentEnd()) <= aStartOffset) {
-        offsetInRenderedString = nextOffsetInRenderedString;
-        continue;
-      }
-      if (!haveOffsets) {
-        result.mOffsetWithinNodeText = aStartOffset;
-        // Skip trimmed space when computed the rendered text offset.
-        int32_t clamped = std::max<int32_t>(aStartOffset, trimmedOffsets.mStart);
-        result.mOffsetWithinNodeRenderedText =
-            tmpIter.ConvertOriginalToSkipped(clamped) + skippedToRenderedStringOffset;
-        NS_ASSERTION(result.mOffsetWithinNodeRenderedText >= offsetInRenderedString &&
-                     result.mOffsetWithinNodeRenderedText <= INT32_MAX,
-                     "Bad offset within rendered text");
-        haveOffsets = true;
-      }
-      if (uint32_t(textFrame->mContentOffset) >= aEndOffset) {
-        break;
-      }
-    }
-
-    int32_t startOffset;
-    int32_t endOffset;
-    if (aOffsetType == TextOffsetType::OFFSETS_IN_RENDERED_TEXT) {
-      startOffset =
-        tmpIter.ConvertSkippedToOriginal(aStartOffset - skippedToRenderedStringOffset);
-      endOffset =
-        tmpIter.ConvertSkippedToOriginal(aEndOffset - skippedToRenderedStringOffset);
-    } else {
-      startOffset = aStartOffset;
-      endOffset = std::min<uint32_t>(INT32_MAX, aEndOffset);
-    }
-    trimmedOffsets.mStart = std::max<uint32_t>(trimmedOffsets.mStart,
-        startOffset);
-    trimmedOffsets.mLength = std::min<uint32_t>(trimmedOffsets.GetEnd(),
-        endOffset) - trimmedOffsets.mStart;
-    if (trimmedOffsets.mLength <= 0) {
-      offsetInRenderedString = nextOffsetInRenderedString;
-      continue;
-    }
-
+    // XXX In the future we may decide to trim extra spaces before a hard line
+    // break, in which case we need to accurately detect those sitations and 
+    // call GetTrimmedOffsets() with true to trim whitespace at the line's end
+    TrimmedOffsets trimmedContentOffsets = textFrame->GetTrimmedOffsets(textFrag, false);
+    int32_t startOfLineSkipChars = trimmedContentOffsets.mStart - textFrame->mContentOffset;
+    if (startOfLineSkipChars > 0) {
+      skipChars.SkipChars(startOfLineSkipChars);
+      iter.SetOriginalOffset(trimmedContentOffsets.mStart);
+    }
+
+    // Keep and copy the appropriate chars withing the caller's requested range
     const nsStyleText* textStyle = textFrame->StyleText();
-    iter.SetOriginalOffset(trimmedOffsets.mStart);
-    while (iter.GetOriginalOffset() < trimmedOffsets.GetEnd()) {
-      char16_t ch = textFrag->CharAt(iter.GetOriginalOffset());
-      if (iter.IsOriginalCharSkipped()) {
-        if (ch == CH_SHY) {
-          // We should preserve soft hyphens. They can't be transformed.
-          result.mString.Append(ch);
+    while (iter.GetOriginalOffset() < trimmedContentOffsets.GetEnd() &&
+           keptCharsLength < aSkippedMaxLength) {
+      // For each original char from content text
+      if (iter.IsOriginalCharSkipped() || ++validCharsLength <= aSkippedStartOffset) {
+        skipChars.SkipChar();
+      } else {
+        ++keptCharsLength;
+        skipChars.KeepChar();
+        if (aAppendToString) {
+          aAppendToString->Append(
+              TransformChar(textFrame, textStyle, textFrame->mTextRun,
+                            iter.GetSkippedOffset(),
+                            textFrag->CharAt(iter.GetOriginalOffset())));
         }
-      } else {
-        result.mString.Append(
-              TransformChar(textFrame, textStyle, textFrame->mTextRun,
-                            iter.GetSkippedOffset(), ch));
       }
       iter.AdvanceOriginal(1);
     }
-
-    if (trimmedSignificantNewline && GetContentEnd() <= endOffset) {
-      // A significant newline was trimmed off (we must be
-      // white-space:pre-line). Put it back.
-      result.mString.Append('\n');
-    }
-    offsetInRenderedString = nextOffsetInRenderedString;
-  }
-
-  if (!haveOffsets) {
-    result.mOffsetWithinNodeText = textFrag->GetLength();
-    result.mOffsetWithinNodeRenderedText = offsetInRenderedString;
-  }
-  return result;
+    if (keptCharsLength >= aSkippedMaxLength) {
+      break; // Already past the end, don't build string or gfxSkipCharsIter anymore
+    }
+  }
+  
+  if (aSkipChars) {
+    aSkipChars->TakeFrom(&skipChars); // Copy skipChars into aSkipChars
+    if (aSkipIter) {
+      // Caller must provide both pointers in order to retrieve a gfxSkipCharsIterator,
+      // because the gfxSkipCharsIterator holds a weak pointer to the gfxSkipChars.
+      *aSkipIter = gfxSkipCharsIterator(*aSkipChars, GetContentLength());
+    }
+  }
+
+  return NS_OK;
 }
 
 nsIAtom*
 nsTextFrame::GetType() const
 {
   return nsGkAtoms::textFrame;
 }
 
--- a/layout/generic/nsTextFrame.h
+++ b/layout/generic/nsTextFrame.h
@@ -256,20 +256,21 @@ public:
   struct TrimOutput {
     // true if we trimmed some space or changed metrics in some other way.
     // In this case, we should call RecomputeOverflow on this frame.
     bool mChanged;
     // an amount to *subtract* from the frame's width (zero if !mChanged)
     nscoord      mDeltaWidth;
   };
   TrimOutput TrimTrailingWhiteSpace(nsRenderingContext* aRC);
-  virtual RenderedText GetRenderedText(uint32_t aStartOffset = 0,
-                                       uint32_t aEndOffset = UINT32_MAX,
-                                       TextOffsetType aOffsetType =
-                                           TextOffsetType::OFFSETS_IN_CONTENT_TEXT) override;
+  virtual nsresult GetRenderedText(nsAString* aString = nullptr,
+                                   gfxSkipChars* aSkipChars = nullptr,
+                                   gfxSkipCharsIterator* aSkipIter = nullptr,
+                                   uint32_t aSkippedStartOffset = 0,
+                                   uint32_t aSkippedMaxLength = UINT32_MAX) override;
 
   nsOverflowAreas RecomputeOverflow(nsIFrame* aBlockFrame);
 
   enum TextRunType {
     // Anything in reflow (but not intrinsic width calculation) or
     // painting should use the inflated text run (i.e., with font size
     // inflation applied).
     eInflated,
--- a/testing/web-platform/meta/MANIFEST.json
+++ b/testing/web-platform/meta/MANIFEST.json
@@ -18709,24 +18709,16 @@
         "path": "http/content_length.html",
         "url": "/http/content_length.html"
       },
       {
         "path": "infrastructure/failing-test.html",
         "url": "/infrastructure/failing-test.html"
       },
       {
-        "path": "innerText/getter.html",
-        "url": "/innerText/getter.html"
-      },
-      {
-        "path": "innerText/setter.html",
-        "url": "/innerText/setter.html"
-      },
-      {
         "path": "js/behaviours/SetPrototypeOf-window.html",
         "url": "/js/behaviours/SetPrototypeOf-window.html"
       },
       {
         "path": "js/builtins/Array.DefineOwnProperty.html",
         "url": "/js/builtins/Array.DefineOwnProperty.html"
       },
       {
deleted file mode 100644
--- a/testing/web-platform/tests/innerText/getter-tests.js
+++ /dev/null
@@ -1,322 +0,0 @@
-testText("<div>abc", "abc", "Simplest possible test");
-
-/**** white-space:normal ****/
-
-testText("<div> abc", "abc", "Leading whitespace removed");
-testText("<div>abc ", "abc", "Trailing whitespace removed");
-testText("<div>abc  def", "abc def", "Internal whitespace compressed");
-testText("<div>abc\ndef", "abc def", "\\n converted to space");
-testText("<div>abc\rdef", "abc def", "\\r converted to space");
-testText("<div>abc\tdef", "abc def", "\\t converted to space");
-testText("<div>abc <br>def", "abc\ndef", "Trailing whitespace before hard line break removed");
-
-/**** <pre> ****/
-
-testText("<pre> abc", " abc", "Leading whitespace preserved");
-testText("<pre>abc ", "abc ", "Trailing whitespace preserved");
-testText("<pre>abc  def", "abc  def", "Internal whitespace preserved");
-testText("<pre>abc\ndef", "abc\ndef", "\\n preserved");
-testText("<pre>abc\rdef", "abc\ndef", "\\r converted to newline");
-testText("<pre>abc\tdef", "abc\tdef", "\\t preserved");
-
-/**** <div style="white-space:pre"> ****/
-
-testText("<div style='white-space:pre'> abc", " abc", "Leading whitespace preserved");
-testText("<div style='white-space:pre'>abc ", "abc ", "Trailing whitespace preserved");
-testText("<div style='white-space:pre'>abc  def", "abc  def", "Internal whitespace preserved");
-testText("<div style='white-space:pre'>abc\ndef", "abc\ndef", "\\n preserved");
-testText("<div style='white-space:pre'>abc\rdef", "abc\ndef", "\\r converted to newline");
-testText("<div style='white-space:pre'>abc\tdef", "abc\tdef", "\\t preserved");
-
-/**** <span style="white-space:pre"> ****/
-
-testText("<span style='white-space:pre'> abc", " abc", "Leading whitespace preserved");
-testText("<span style='white-space:pre'>abc ", "abc ", "Trailing whitespace preserved");
-testText("<span style='white-space:pre'>abc  def", "abc  def", "Internal whitespace preserved");
-testText("<span style='white-space:pre'>abc\ndef", "abc\ndef", "\\n preserved");
-testText("<span style='white-space:pre'>abc\rdef", "abc\ndef", "\\r converted to newline");
-testText("<span style='white-space:pre'>abc\tdef", "abc\tdef", "\\t preserved");
-
-/**** <div style="white-space:pre-line"> ****/
-
-testText("<div style='white-space:pre-line'> abc", "abc", "Leading whitespace removed");
-testText("<div style='white-space:pre-line'>abc ", "abc", "Trailing whitespace removed");
-testText("<div style='white-space:pre-line'>abc  def", "abc def", "Internal whitespace collapsed");
-testText("<div style='white-space:pre-line'>abc\ndef", "abc\ndef", "\\n preserved");
-testText("<div style='white-space:pre-line'>abc\rdef", "abc\ndef", "\\r converted to newline");
-testText("<div style='white-space:pre-line'>abc\tdef", "abc def", "\\t converted to space");
-
-/**** Collapsing whitespace across element boundaries ****/
-
-testText("<div><span>abc </span> def", "abc def", "Whitespace collapses across element boundaries");
-testText("<div><span>abc </span><span></span> def", "abc def", "Whitespace collapses across element boundaries");
-testText("<div><span>abc </span><span style='white-space:pre'></span> def", "abc def", "Whitespace collapses across element boundaries");
-
-/**** Soft line breaks ****/
-
-testText("<div style='width:0'>abc def", "abc def", "Soft line breaks ignored");
-
-/**** first-line/first-letter ****/
-
-testText("<div class='first-line-uppercase' style='width:0'>abc def", "ABC def", "::first-line styles applied");
-testText("<div class='first-letter-uppercase' style='width:0'>abc def", "Abc def", "::first-letter styles applied");
-testText("<div class='first-letter-float' style='width:0'>abc def", "abc def", "::first-letter float ignored");
-
-/**** &nbsp; ****/
-
-testText("<div>&nbsp;", "\xA0", "&nbsp; preserved");
-
-/**** display:none ****/
-
-testText("<div style='display:none'>abc", "abc", "display:none container");
-testText("<div style='display:none'>abc  def", "abc  def", "No whitespace compression in display:none container");
-testText("<div style='display:none'> abc def ", " abc def ", "No removal of leading/trailing whitespace in display:none container");
-testText("<div>123<span style='display:none'>abc", "123", "display:none child not rendered");
-
-/**** display:contents ****/
-
-if (CSS.supports("display", "contents")) {
-  testText("<div style='display:contents'>abc", "abc", "display:contents container");
-  testText("<div><div style='display:contents'>abc", "abc", "display:contents container");
-  testText("<div>123<span style='display:contents'>abc", "123abc", "display:contents rendered");
-  testText("<div>123<span style='display:contents'>abc", "123abc", "display:contents rendered");
-  testText("<div style='display:contents'>   ", "", "display:contents not processed via textContent");
-  testText("<div><div style='display:contents'>   ", "", "display:contents not processed via textContent");
-}
-
-/**** visibility:hidden ****/
-
-testText("<div style='visibility:hidden'>abc", "", "visibility:hidden container");
-testText("<div>123<span style='visibility:hidden'>abc", "123", "visibility:hidden child not rendered");
-testText("<div style='visibility:hidden'>123<span style='visibility:visible'>abc", "abc", "visibility:visible child rendered");
-
-/**** visibility:collapse ****/
-
-testText("<table><tbody style='visibility:collapse'><tr><td>abc", "", "visibility:collapse row-group");
-testText("<table><tr style='visibility:collapse'><td>abc", "", "visibility:collapse row");
-testText("<table><tr><td style='visibility:collapse'>abc", "", "visibility:collapse cell");
-testText("<table><tbody style='visibility:collapse'><tr><td style='visibility:visible'>abc", "abc",
-         "visibility:collapse row-group with visible cell");
-testText("<table><tr style='visibility:collapse'><td style='visibility:visible'>abc", "abc",
-         "visibility:collapse row with visible cell");
-testText("<div style='display:flex'><span style='visibility:collapse'>1</span><span>2</span></div>",
-         "2", "visibility:collapse honored on flex item");
-testText("<div style='display:grid'><span style='visibility:collapse'>1</span><span>2</span></div>",
-         "2", "visibility:collapse honored on grid item");
-
-/**** opacity:0 ****/
-
-testText("<div style='opacity:0'>abc", "abc", "opacity:0 container");
-testText("<div style='opacity:0'>abc  def", "abc def", "Whitespace compression in opacity:0 container");
-testText("<div style='opacity:0'> abc def ", "abc def", "Remove leading/trailing whitespace in opacity:0 container");
-testText("<div>123<span style='opacity:0'>abc", "123abc", "opacity:0 child rendered");
-
-/**** generated content ****/
-
-testText("<div class='before'>", "", "Generated content not included");
-testText("<div><div class='before'>", "", "Generated content on child not included");
-
-/**** innerText on replaced elements ****/
-
-testText("<button>abc", "abc", "<button> contents preserved");
-testText("<fieldset>abc", "abc", "<fieldset> contents preserved");
-testText("<fieldset><legend>abc", "abc", "<fieldset> <legend> contents preserved");
-testText("<input type='text' value='abc'>", "", "<input> contents ignored");
-testText("<textarea>abc", "", "<textarea> contents ignored");
-testText("<select size='1'><option>abc</option><option>def", "", "<select size='1'> contents ignored");
-testText("<select size='2'><option>abc</option><option>def", "", "<select size='2'> contents ignored");
-testText("<select size='1'><option id='target'>abc</option><option>def", "", "<select size='1'> contents ignored");
-testText("<select size='2'><option id='target'>abc</option><option>def", "", "<select size='2'> contents ignored");
-testText("<iframe>abc", "", "<iframe> contents ignored");
-testText("<iframe><div id='target'>abc", "", "<iframe> contents ignored");
-testText("<iframe src='data:text/html,abc'>", "","<iframe> subdocument ignored");
-testText("<audio style='display:block'>abc", "", "<audio> contents ignored");
-testText("<audio style='display:block'><source id='target' class='poke' style='display:block'>", "", "<audio> contents ignored");
-testText("<audio style='display:block'><source id='target' class='poke' style='display:none'>", "abc", "<audio> contents ok if display:none");
-testText("<video>abc", "", "<video> contents ignored");
-testText("<video style='display:block'><source id='target' class='poke' style='display:block'>", "", "<video> contents ignored");
-testText("<video style='display:block'><source id='target' class='poke' style='display:none'>", "abc", "<video> contents ok if display:none");
-testText("<canvas>abc", "", "<canvas> contents ignored");
-testText("<canvas><div id='target'>abc", "", "<canvas><div id='target'> contents ignored");
-testText("<img alt='abc'>", "", "<img> alt text ignored");
-testText("<img src='about:blank' class='poke'>", "", "<img> contents ignored");
-
-/**** innerText on replaced element children ****/
-
-testText("<div><button>abc", "abc", "<button> contents preserved");
-testText("<div><fieldset>abc", "abc", "<fieldset> contents preserved");
-testText("<div><fieldset><legend>abc", "abc", "<fieldset> <legend> contents preserved");
-testText("<div><input type='text' value='abc'>", "", "<input> contents ignored");
-testText("<div><textarea>abc", "", "<textarea> contents ignored");
-testText("<div><select size='1'><option>abc</option><option>def", "", "<select size='1'> contents ignored");
-testText("<div><select size='2'><option>abc</option><option>def", "", "<select size='2'> contents ignored");
-testText("<div><iframe>abc", "", "<iframe> contents ignored");
-testText("<div><iframe src='data:text/html,abc'>", ""," <iframe> subdocument ignored");
-testText("<div><audio>abc", "", "<audio> contents ignored");
-testText("<div><video>abc", "", "<video> contents ignored");
-testText("<div><canvas>abc", "", "<canvas> contents ignored");
-testText("<div><img alt='abc'>", "", "<img> alt text ignored");
-
-/**** Lines around blocks ****/
-
-testText("<div>123<div>abc</div>def", "123\nabc\ndef", "Newline at block boundary");
-testText("<div>123<span style='display:block'>abc</span>def", "123\nabc\ndef", "Newline at display:block boundary");
-testText("<div>abc<div></div>def", "abc\ndef", "Empty block induces single line break");
-testText("<div>abc<div></div><div></div>def", "abc\ndef", "Consecutive empty blocks ignored");
-testText("<div><p>abc", "abc", "No blank lines around <p> alone");
-testText("<div><p>abc</p> ", "abc", "No blank lines around <p> followed by only collapsible whitespace");
-testText("<div> <p>abc</p>", "abc", "No blank lines around <p> preceded by only collapsible whitespace");
-testText("<div><p>abc<p>def", "abc\n\ndef", "Blank line between consecutive <p>s");
-testText("<div><p>abc</p> <p>def", "abc\n\ndef", "Blank line between consecutive <p>s separated only by collapsible whitespace");
-testText("<div><p>abc</p><div></div><p>def", "abc\n\ndef", "Blank line between consecutive <p>s separated only by empty block");
-testText("<div><p>abc</p><div>123</div><p>def", "abc\n\n123\n\ndef", "Blank lines between <p>s separated by non-empty block");
-testText("<div>abc<div><p>123</p></div>def", "abc\n\n123\n\ndef", "Blank lines around a <p> in its own block");
-testText("<div>abc<p>def", "abc\n\ndef", "Blank line before <p>");
-testText("<div><p>abc</p>def", "abc\n\ndef", "Blank line after <p>");
-testText("<div><p>abc<p></p><p></p><p>def", "abc\n\ndef", "One blank line between <p>s, ignoring empty <p>s");
-testText("<div style='visibility:hidden'><p><span style='visibility:visible'>abc</span></p>\n<div style='visibility:visible'>def</div>",
-     "abc\ndef", "Invisible <p> doesn't induce extra line breaks");
-testText("<div>abc<div style='margin:2em'>def", "abc\ndef", "No blank lines around <div> with margin");
-testText("<div>123<span style='display:inline-block'>abc</span>def", "123abcdef", "No newlines at display:inline-block boundary");
-testText("<div>123<span style='display:inline-block'> abc </span>def", "123abcdef", "Leading/trailing space removal at display:inline-block boundary");
-
-/**** Spans ****/
-
-testText("<div>123<span>abc</span>def", "123abcdef", "<span> boundaries are irrelevant");
-testText("<div>123<em>abc</em>def", "123abcdef", "<em> gets no special treatment");
-testText("<div>123<b>abc</b>def", "123abcdef", "<b> gets no special treatment");
-testText("<div>123<i>abc</i>def", "123abcdef", "<i> gets no special treatment");
-testText("<div>123<strong>abc</strong>def", "123abcdef", "<strong> gets no special treatment");
-testText("<div>123<tt>abc</tt>def", "123abcdef", "<tt> gets no special treatment");
-testText("<div>123<code>abc</code>def", "123abcdef", "<code> gets no special treatment");
-
-/**** Soft hyphen ****/
-
-testText("<div>abc&shy;def", "abc\xADdef", "soft hyphen preserved");
-testText("<div style='width:0'>abc&shy;def", "abc\xADdef", "soft hyphen preserved");
-
-/**** Tables ****/
-
-testText("<div><table style='white-space:pre'>  <td>abc</td>  </table>", "abc", "Ignoring non-rendered table whitespace");
-testText("<div><table><tr><td>abc<td>def</table>", "abc\tdef", "Tab-separated table cells");
-testText("<div><table><tr><td>abc<td><td>def</table>", "abc\t\tdef", "Tab-separated table cells including empty cells");
-testText("<div><table><tr><td>abc<td><td></table>", "abc\t\t", "Tab-separated table cells including trailing empty cells");
-testText("<div><table><tr><td>abc<tr><td>def</table>", "abc\ndef", "Newline-separated table rows");
-testText("<div>abc<table><td>def</table>ghi", "abc\ndef\nghi", "Newlines around table");
-testText("<div><table style='border-collapse:collapse'><tr><td>abc<td>def</table>", "abc\tdef",
-         "Tab-separated table cells in a border-collapse table");
-testText("<div><table><tfoot>x</tfoot><tbody>y</tbody></table>", "xy", "tfoot not reordered");
-testText("<table><tfoot><tr><td>footer</tfoot><thead><tr><td style='visibility:collapse'>thead</thead><tbody><tr><td>tbody</tbody></table>",
-         "footer\n\ntbody", "");
-
-/**** Table captions ****/
-
-testText("<div><table><tr><td>abc<caption>def</caption></table>", "abc\ndef", "Newline between cells and caption");
-
-/**** display:table ****/
-
-testText("<div><div class='table'><span class='cell'>abc</span>\n<span class='cell'>def</span></div>",
-         "abc\tdef", "Tab-separated table cells");
-testText("<div><div class='table'><span class='row'><span class='cell'>abc</span></span>\n<span class='row'><span class='cell'>def</span></span></div>",
-         "abc\ndef", "Newline-separated table rows");
-testText("<div>abc<div class='table'><span class='cell'>def</span></div>ghi", "abc\ndef\nghi", "Newlines around table");
-
-/**** display:inline-table ****/
-
-testText("<div><div class='itable'><span class='cell'>abc</span>\n<span class='cell'>def</span></div>", "abc\tdef", "Tab-separated table cells");
-testText("<div><div class='itable'><span class='row'><span class='cell'>abc</span></span>\n<span class='row'><span class='cell'>def</span></span></div>",
-         "abc\ndef", "Newline-separated table rows");
-testText("<div>abc<div class='itable'><span class='cell'>def</span></div>ghi", "abcdefghi", "No newlines around inline-table");
-testText("<div>abc<div class='itable'><span class='row'><span class='cell'>def</span></span>\n<span class='row'><span class='cell'>123</span></span></div>ghi",
-         "abcdef\n123ghi", "Single newline in two-row inline-table");
-
-/**** Lists ****/
-
-testText("<div><ol><li>abc", "abc", "<ol> list items get no special treatment");
-testText("<div><ul><li>abc", "abc", "<ul> list items get no special treatment");
-
-/**** Misc elements ****/
-
-testText("<div><script style='display:block'>abc", "abc", "display:block <script> is rendered");
-testText("<div><style style='display:block'>abc", "abc", "display:block <style> is rendered");
-testText("<div><noscript style='display:block'>abc", "", "display:block <noscript> is not rendered (it's not parsed!)");
-testText("<div><template style='display:block'>abc", "",
-         "display:block <template> contents are not rendered (the contents are in a different document)");
-testText("<div>abc<br>def", "abc\ndef", "<br> induces line break");
-testText("<div>abc<br>", "abc\n", "<br> induces line break even at end of block");
-testText("<div><br class='poke'>", "\n", "<br> content ignored");
-testText("<div>abc<hr>def", "abc\ndef", "<hr> induces line break");
-testText("<div>abc<hr><hr>def", "abc\ndef", "<hr><hr> induces just one line break");
-testText("<div>abc<hr><hr><hr>def", "abc\ndef", "<hr><hr><hr> induces just one line break");
-testText("<div><hr class='poke'>", "abc", "<hr> content rendered");
-testText("<div>abc<!--comment-->def", "abcdef", "comment ignored");
-
-/**** text-transform ****/
-
-testText("<div><div style='text-transform:uppercase'>abc", "ABC", "text-transform is applied");
-
-/**** block-in-inline ****/
-
-testText("<div>abc<span>123<div>456</div>789</span>def", "abc123\n456\n789def", "block-in-inline doesn't add unnecessary newlines");
-
-/**** floats ****/
-
-testText("<div>abc<div style='float:left'>123</div>def", "abc\n123\ndef", "floats induce a block boundary");
-testText("<div>abc<span style='float:left'>123</span>def", "abc\n123\ndef", "floats induce a block boundary");
-
-/**** position ****/
-
-testText("<div>abc<div style='position:absolute'>123</div>def", "abc\n123\ndef", "position:absolute induces a block boundary");
-testText("<div>abc<span style='position:absolute'>123</span>def", "abc\n123\ndef", "position:absolute induces a block boundary");
-testText("<div>abc<div style='position:relative'>123</div>def", "abc\n123\ndef", "position:relative has no effect");
-testText("<div>abc<span style='position:relative'>123</span>def", "abc123def", "position:relative has no effect");
-
-/**** text-overflow:ellipsis ****/
-
-testText("<div style='overflow:hidden'>abc", "abc", "overflow:hidden ignored");
-// XXX Chrome skips content with width:0 or height:0 and overflow:hidden;
-// should we spec that?
-testText("<div style='width:0; overflow:hidden'>abc", "abc", "overflow:hidden ignored even with zero width");
-testText("<div style='height:0; overflow:hidden'>abc", "abc", "overflow:hidden ignored even with zero height");
-testText("<div style='width:0; overflow:hidden; text-overflow:ellipsis'>abc", "abc", "text-overflow:ellipsis ignored");
-
-/**** Support on non-HTML elements ****/
-
-testText("<svg>abc", undefined, "innerText not supported on SVG elements");
-testText("<math>abc", undefined, "innerText not supported on MathML elements");
-
-/**** Ruby ****/
-
-testText("<div><ruby>abc<rp>(</rp><rt>def</rt><rp>)</rp></ruby>", "abc(def)", "<rp> rendered");
-testText("<div><rp>abc</rp>", "abc", "Lone <rp> rendered");
-testText("<div><rp style='visibility:hidden'>abc</rp>", "", "visibility:hidden <rp> not rendered");
-testText("<div><rp> abc </rp>", " abc ", "Lone <rp> rendered without whitespace trimming");
-testText("<div><rp style='display:block'>abc</rp>def", "abc\ndef", "display:block <rp> induces line breaks");
-testText("<div><rp style='display:block'> abc </rp>def", " abc \ndef", "display:block <rp> induces line breaks but doesn't trim whitespace");
-// XXX this is not desirable but the spec currently requires it.
-testText("<div><select class='poke-rp'></select>", "abc", "<rp> in a replaced element still renders");
-
-/**** Shadow DOM ****/
-
-if ("createShadowRoot" in document.body) {
-  testText("<div class='shadow'>", "", "Shadow DOM contents ignored");
-  testText("<div><div class='shadow'>", "", "Shadow DOM contents ignored");
-}
-
-/**** Flexbox ****/
-
-if (CSS.supports('display', 'flex')) {
-  testText("<div style='display:flex'><div style='order:1'>1</div><div>2</div></div>",
-           "1\n2", "CSS 'order' property ignored");
-  testText("<div style='display:flex'><span>1</span><span>2</span></div>",
-           "1\n2", "Flex items blockified");
-}
-
-/**** Grid ****/
-
-if (CSS.supports('display', 'grid')) {
-  testText("<div style='display:grid'><div style='order:1'>1</div><div>2</div></div>",
-           "1\n2", "CSS 'order' property ignored");
-  testText("<div style='display:grid'><span>1</span><span>2</span></div>",
-           "1\n2", "Grid items blockified");
-}
deleted file mode 100644
--- a/testing/web-platform/tests/innerText/getter.html
+++ /dev/null
@@ -1,46 +0,0 @@
-<!DOCTYPE html>
-<title>innerText getter test</title>
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<style>
-.before::before { content:'abc'; }
-.table { display:table; }
-.itable { display:inline-table; }
-.row { display:table-row; }
-.cell { display:table-cell; }
-.first-line-uppercase::first-line { text-transform:uppercase; }
-.first-letter-uppercase::first-letter { text-transform:uppercase; }
-.first-letter-float::first-letter { float:left; }
-</style>
-<div id="container"></div>
-<script>
-function testText(html, expectedPlain, msg) {
-  test(function() {
-    container.innerHTML = html;
-    var e = document.getElementById('target');
-    if (!e) {
-      e = container.firstChild;
-    }
-    var pokes = document.getElementsByClassName('poke');
-    for (var i = 0; i < pokes.length; ++i) {
-      pokes[i].textContent = 'abc';
-    }
-    pokes = document.getElementsByClassName('poke-rp');
-    for (var i = 0; i < pokes.length; ++i) {
-      var rp = document.createElement("rp");
-      rp.textContent = "abc";
-      pokes[i].appendChild(rp);
-    }
-    var shadows = document.getElementsByClassName('shadow');
-    for (var i = 0; i < shadows.length; ++i) {
-      var s = shadows[i].createShadowRoot();
-      s.textContent = 'abc';
-    }
-    while (e && e.nodeType != Node.ELEMENT_NODE) {
-      e = e.nextSibling;
-    }
-    assert_equals(e.innerText, expectedPlain);
-  }, msg);
-}
-</script>
-<script src="getter-tests.js"></script>
deleted file mode 100644
--- a/testing/web-platform/tests/innerText/setter-tests.js
+++ /dev/null
@@ -1,24 +0,0 @@
-testText("<div>", "abc", "abc", "Simplest possible test");
-testHTML("<div>", "abc\ndef", "abc<br>def", "Newlines convert to <br> in non-white-space:pre elements");
-testHTML("<pre>", "abc\ndef", "abc<br>def", "Newlines convert to <br> in <pre> element");
-testHTML("<div style='white-space:pre'>", "abc\ndef", "abc<br>def", "Newlines convert to <br> in white-space:pre element");
-testHTML("<div>", "abc\rdef", "abc<br>def", "CRs convert to <br> in non-white-space:pre elements");
-testHTML("<pre>", "abc\rdef", "abc<br>def", "CRs convert to <br> in <pre> element");
-testHTML("<div>", "abc\r\ndef", "abc<br>def", "Newline/CR pair converts to <br> in non-white-space:pre element");
-testHTML("<div>", "abc\n\ndef", "abc<br><br>def", "Newline/newline pair converts to two <br>s in non-white-space:pre element");
-testHTML("<div>", "abc\r\rdef", "abc<br><br>def", "CR/CR pair converts to two <br>s in non-white-space:pre element");
-testHTML("<div style='white-space:pre'>", "abc\rdef", "abc<br>def", "CRs convert to <br> in white-space:pre element");
-testText("<div>", "abc<def", "abc<def", "< preserved");
-testText("<div>", "abc>def", "abc>def", "> preserved");
-testText("<div>", "abc&", "abc&", "& preserved");
-testText("<div>", "abc\"def", "abc\"def", "\" preserved");
-testText("<div>", "abc\'def", "abc\'def", "\' preserved");
-testHTML("<svg>", "abc", "", "innerText not supported on SVG elements");
-testHTML("<math>", "abc", "", "innerText not supported on MathML elements");
-testText("<div>", "abc\0def", "abc\0def", "Null characters preserved");
-testText("<div>", "abc\tdef", "abc\tdef", "Tabs preserved");
-testText("<div>", " abc", " abc", "Leading whitespace preserved");
-testText("<div>", "abc ", "abc ", "Trailing whitespace preserved");
-testText("<div>", "abc  def", "abc  def", "Whitespace not compressed");
-testHTML("<div>abc\n\n", "abc", "abc", "Existing text deleted");
-testHTML("<div><br>", "abc", "abc", "Existing <br> deleted");
deleted file mode 100644
--- a/testing/web-platform/tests/innerText/setter.html
+++ /dev/null
@@ -1,32 +0,0 @@
-<!DOCTYPE html>
-<title>innerText setter test</title>
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<div id="container"></div>
-<script>
-function setupTest(context, plain) {
-  container.innerHTML = context;
-  var e = container.firstChild;
-  while (e && e.nodeType != Node.ELEMENT_NODE) {
-    e = e.nextSibling;
-  }
-  e.innerText = plain;
-  return e;
-}
-function testText(context, plain, expectedText, msg) {
-  test(function(){
-    var e = setupTest(context, plain);
-    assert_not_equals(e.firstChild, null, "Should have a child");
-    assert_equals(e.firstChild.nodeType, Node.TEXT_NODE, "Child should be a text node");
-    assert_equals(e.firstChild.nextSibling, null, "Should have only one child");
-    assert_equals(e.firstChild.data, expectedText);
-  }, msg);
-}
-function testHTML(context, plain, expectedHTML, msg) {
-  test(function(){
-    var e = setupTest(context, plain);
-    assert_equals(e.innerHTML, expectedHTML);
-  }, msg);
-}
-</script>
-<script src="setter-tests.js"></script>