Backed out 10 changesets (bug 1141931) for mochitest-5 failures CLOSED TREE
authorWes Kocher <wkocher@mozilla.com>
Tue, 07 Apr 2015 14:23:57 -0700
changeset 238028 44c475f5adc1d5c0706d98c26a422490d8c0e204
parent 238027 e2b6c74dac8a7a309290c3ca55f7120fb7ed8919
child 238029 5ab8bc709c1bbf2695becfe07894be8f11c1a4e3
push id58091
push userkwierso@gmail.com
push dateTue, 07 Apr 2015 21:24:01 +0000
treeherdermozilla-inbound@44c475f5adc1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1141931
milestone40.0a1
backs outc90940067de6b3099932640b008b53b0fd1d4555
96b48288abab4fd77bfae5a9d16fc63fec1302d4
87281c7ded34ab72a731c5d7a832b416802ef2c1
6a914ba0b8ecbdfb11ba96e9776892aa9466b3ac
9cfea55b5e952ce1e09908dc58721fce21c80e4d
f432612b6475043f68d405eb5e38aad1be936b2e
48cf9568a4b18c834dc4f7e72d9f1df7d01352f4
f1ab848b3fa6cb2f1af40f949922b3eadd2e6de2
8a3c71a3b5256bb5a6870be01017d5ccd4744eeb
119d3c0fd0f60076f0a1014e9db1dc7ba63b1b9e
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
Backed out 10 changesets (bug 1141931) for mochitest-5 failures CLOSED TREE Backed out changeset c90940067de6 (bug 1141931) Backed out changeset 96b48288abab (bug 1141931) Backed out changeset 87281c7ded34 (bug 1141931) Backed out changeset 6a914ba0b8ec (bug 1141931) Backed out changeset 9cfea55b5e95 (bug 1141931) Backed out changeset f432612b6475 (bug 1141931) Backed out changeset 48cf9568a4b1 (bug 1141931) Backed out changeset f1ab848b3fa6 (bug 1141931) Backed out changeset 8a3c71a3b525 (bug 1141931) Backed out changeset 119d3c0fd0f6 (bug 1141931)
layout/base/nsBidiPresUtils.cpp
layout/base/nsBidiPresUtils.h
layout/generic/RubyUtils.cpp
layout/generic/RubyUtils.h
layout/generic/moz.build
layout/generic/nsLineLayout.cpp
layout/generic/nsRubyBaseContainerFrame.cpp
layout/generic/nsRubyBaseContainerFrame.h
layout/generic/nsRubyFrame.cpp
layout/generic/nsRubyTextContainerFrame.h
layout/reftests/css-ruby/bidi-2-ref.html
layout/reftests/css-ruby/bidi-2.html
layout/reftests/css-ruby/common.css
layout/reftests/css-ruby/reftest.list
layout/reftests/w3c-css/submitted/ruby/support/rbc.css
layout/style/html.css
layout/style/nsStyleContext.cpp
layout/style/ua.css
--- a/layout/base/nsBidiPresUtils.cpp
+++ b/layout/base/nsBidiPresUtils.cpp
@@ -14,22 +14,16 @@
 #include "nsInlineFrame.h"
 #include "nsPlaceholderFrame.h"
 #include "nsFirstLetterFrame.h"
 #include "nsUnicodeProperties.h"
 #include "nsTextFrame.h"
 #include "nsBlockFrame.h"
 #include "nsIFrameInlines.h"
 #include "nsStyleStructInlines.h"
-#include "RubyUtils.h"
-#include "nsRubyFrame.h"
-#include "nsRubyBaseFrame.h"
-#include "nsRubyTextFrame.h"
-#include "nsRubyBaseContainerFrame.h"
-#include "nsRubyTextContainerFrame.h"
 #include <algorithm>
 
 #undef NOISY_BIDI
 #undef REALLY_NOISY_BIDI
 
 using namespace mozilla;
 
 static const char16_t kSpace            = 0x0020;
@@ -1224,21 +1218,21 @@ nsBidiPresUtils::ResolveParagraphWithinB
                                              BidiParagraphData* aBpd)
 {
   aBpd->ClearBidiControls();
   ResolveParagraph(aBlockFrame, aBpd);
   aBpd->ResetData();
 }
 
 void
-nsBidiPresUtils::ReorderFrames(nsIFrame* aFirstFrameOnLine,
-                               int32_t aNumFramesOnLine,
-                               WritingMode aLineWM,
+nsBidiPresUtils::ReorderFrames(nsIFrame*     aFirstFrameOnLine,
+                               int32_t       aNumFramesOnLine,
+                               WritingMode   aLineWM,
                                const nsSize& aContainerSize,
-                               nscoord aStart)
+                               nscoord       aStart)
 {
   // If this line consists of a line frame, reorder the line frame's children.
   if (aFirstFrameOnLine->GetType() == nsGkAtoms::lineFrame) {
     aFirstFrameOnLine = aFirstFrameOnLine->GetFirstPrincipalChild();
     if (!aFirstFrameOnLine)
       return;
     // All children of the line frame are on the first line. Setting aNumFramesOnLine
     // to -1 makes InitLogicalArrayFromLine look at all of them.
@@ -1282,21 +1276,21 @@ nsBidiPresUtils::GetFrameBaseLevel(nsIFr
   nsIFrame* firstLeaf = aFrame;
   while (!IsBidiLeaf(firstLeaf)) {
     firstLeaf = firstLeaf->GetFirstPrincipalChild();
   }
   return NS_GET_BASE_LEVEL(firstLeaf);
 }
 
 void
-nsBidiPresUtils::IsFirstOrLast(nsIFrame* aFrame,
-                               const nsContinuationStates* aContinuationStates,
-                               bool aSpanDirMatchesLineDir,
-                               bool& aIsFirst /* out */,
-                               bool& aIsLast /* out */)
+nsBidiPresUtils::IsFirstOrLast(nsIFrame*             aFrame,
+                               nsContinuationStates* aContinuationStates,
+                               bool                  aSpanDirMatchesLineDir,
+                               bool&                 aIsFirst /* out */,
+                               bool&                 aIsLast /* out */)
 {
   /*
    * Since we lay out frames in the line's direction, visiting a frame with
    * 'mFirstVisualFrame == nullptr', means it's the first appearance of one
    * of its continuation chain frames on the line.
    * To determine if it's the last visual frame of its continuation chain on
    * the line or not, we count the number of frames of the chain on the line,
    * and then reduce it when we lay out a frame of the chain. If this value
@@ -1397,106 +1391,26 @@ nsBidiPresUtils::IsFirstOrLast(nsIFrame*
     if (aIsLast) {
       aFrame->AddStateBits(NS_INLINE_FRAME_BIDI_VISUAL_IS_LAST);
     } else {
       aFrame->RemoveStateBits(NS_INLINE_FRAME_BIDI_VISUAL_IS_LAST);
     }
   }
 }
 
-/* static */ nscoord
-nsBidiPresUtils::RepositionRubyFrame(
-  nsIFrame* aFrame,
-  const nsContinuationStates* aContinuationStates,
-  const WritingMode aContainerWM,
-  const LogicalMargin& aBorderPadding)
+void
+nsBidiPresUtils::RepositionFrame(nsIFrame*             aFrame,
+                                 bool                  aIsEvenLevel,
+                                 nscoord&              aStart,
+                                 nsContinuationStates* aContinuationStates,
+                                 WritingMode           aContainerWM,
+                                 const nsSize&         aContainerSize)
 {
-  nsIAtom* frameType = aFrame->GetType();
-  MOZ_ASSERT(frameType == nsGkAtoms::rubyFrame ||
-             frameType == nsGkAtoms::rubyBaseFrame ||
-             frameType == nsGkAtoms::rubyTextFrame ||
-             frameType == nsGkAtoms::rubyBaseContainerFrame ||
-             frameType == nsGkAtoms::rubyTextContainerFrame);
-
-  nscoord icoord = 0;
-  WritingMode frameWM = aFrame->GetWritingMode();
-  bool isLTR = frameWM.IsBidiLTR();
-  nsSize frameSize = aFrame->GetSize();
-  if (frameType == nsGkAtoms::rubyFrame) {
-    icoord += aBorderPadding.IStart(frameWM);
-    // Reposition ruby segments in a ruby container
-    for (RubySegmentEnumerator e(static_cast<nsRubyFrame*>(aFrame));
-          !e.AtEnd(); e.Next()) {
-      nsRubyBaseContainerFrame* rbc = e.GetBaseContainer();
-      AutoRubyTextContainerArray textContainers(rbc);
-
-      nscoord segmentISize = RepositionFrame(rbc, isLTR, icoord,
-                                             aContinuationStates,
-                                             frameWM, false, frameSize);
-      for (nsRubyTextContainerFrame* rtc : textContainers) {
-        nscoord isize = RepositionFrame(rtc, isLTR, icoord, aContinuationStates,
-                                        frameWM, false, frameSize);
-        segmentISize = std::max(segmentISize, isize);
-      }
-      icoord += segmentISize;
-    }
-    icoord += aBorderPadding.IEnd(frameWM);
-  } else if (frameType == nsGkAtoms::rubyBaseContainerFrame) {
-    // Reposition ruby columns in a ruby segment
-    auto rbc = static_cast<nsRubyBaseContainerFrame*>(aFrame);
-    AutoRubyTextContainerArray textContainers(rbc);
-
-    for (RubyColumnEnumerator e(rbc, textContainers); !e.AtEnd(); e.Next()) {
-      RubyColumn column;
-      e.GetColumn(column);
-
-      nscoord columnISize = RepositionFrame(column.mBaseFrame, isLTR, icoord,
-                                            aContinuationStates,
-                                            frameWM, false, frameSize);
-      for (nsRubyTextFrame* rt : column.mTextFrames) {
-        nscoord isize = RepositionFrame(rt, isLTR, icoord, aContinuationStates,
-                                        frameWM, false, frameSize);
-        columnISize = std::max(columnISize, isize);
-      }
-      icoord += columnISize;
-    }
-  } else {
-    if (frameType == nsGkAtoms::rubyBaseFrame ||
-        frameType == nsGkAtoms::rubyTextFrame) {
-      // Reorder the children.
-      // XXX It currently doesn't work properly because we do not
-      // resolve frames inside ruby content frames.
-      const nsFrameList& childList = aFrame->PrincipalChildList();
-      ReorderFrames(childList.FirstChild(), childList.GetLength(),
-                    frameWM, frameSize, aBorderPadding.IStart(frameWM));
-    }
-    // Note that, ruby text container is not present in all conditions
-    // above. It is intended, because the children of rtc are reordered
-    // with the children of ruby base container simultaneously. We only
-    // need to return its isize here, as it should not be changed.
-    icoord += aFrame->ISize(aContainerWM);
-  }
-  return icoord;
-}
-
-/* static */ nscoord
-nsBidiPresUtils::RepositionFrame(nsIFrame* aFrame,
-                                 bool aIsEvenLevel,
-                                 nscoord aStartOrEnd,
-                                 const nsContinuationStates* aContinuationStates,
-                                 WritingMode aContainerWM,
-                                 bool aContainerReverseDir,
-                                 const nsSize& aContainerSize)
-{
-  nscoord lineSize = aContainerWM.IsVertical() ?
-    aContainerSize.height : aContainerSize.width;
-  NS_ASSERTION(lineSize != NS_UNCONSTRAINEDSIZE,
-               "Unconstrained inline line size in bidi frame reordering");
   if (!aFrame)
-    return 0;
+    return;
 
   bool isFirst, isLast;
   WritingMode frameWM = aFrame->GetWritingMode();
   IsFirstOrLast(aFrame,
                 aContinuationStates,
                 aContainerWM.IsBidiLTR() == frameWM.IsBidiLTR(),
                 isFirst /* out */,
                 isLast /* out */);
@@ -1506,98 +1420,99 @@ nsBidiPresUtils::RepositionFrame(nsIFram
   // container's writing mode. To get the right values, we set start and
   // end margins on a logical margin in the frame's writing mode, and
   // then convert the margin to the container's writing mode to set the
   // coordinates.
 
   // This method is called from nsBlockFrame::PlaceLine via the call to
   // bidiUtils->ReorderFrames, so this is guaranteed to be after the inlines
   // have been reflowed, which is required for GetUsedMargin/Border/Padding
-  nscoord frameISize = aFrame->ISize();
   LogicalMargin frameMargin = aFrame->GetLogicalUsedMargin(frameWM);
   LogicalMargin borderPadding = aFrame->GetLogicalUsedBorderAndPadding(frameWM);
-  // Since the visual order of frame could be different from the
-  // continuation order, we need to remove any border/padding first,
-  // so that we can get the correct isize of the current frame.
-  if (!aFrame->GetPrevContinuation()) {
-    frameISize -= borderPadding.IStart(frameWM);
-  }
-  if (!aFrame->GetNextContinuation()) {
-    frameISize -= borderPadding.IEnd(frameWM);
-  }
   if (!isFirst) {
     frameMargin.IStart(frameWM) = 0;
     borderPadding.IStart(frameWM) = 0;
   }
   if (!isLast) {
     frameMargin.IEnd(frameWM) = 0;
     borderPadding.IEnd(frameWM) = 0;
   }
-  frameISize += borderPadding.IStartEnd(frameWM);
+  LogicalMargin margin = frameMargin.ConvertTo(aContainerWM, frameWM);
+  aStart += margin.IStart(aContainerWM);
 
-  nscoord icoord = 0;
+  nscoord start = aStart;
+
   if (!IsBidiLeaf(aFrame)) {
-    bool reverseDir = aIsEvenLevel != frameWM.IsBidiLTR();
-    icoord += reverseDir ?
-      borderPadding.IEnd(frameWM) : borderPadding.IStart(frameWM);
-    LogicalSize logicalSize(frameWM, frameISize, aFrame->BSize());
-    nsSize frameSize = logicalSize.GetPhysicalSize(frameWM);
+    // If the resolved direction of the container is different from the
+    // direction of the frame, we need to traverse the child list in reverse
+    // order, to make it O(n) we store the list locally and iterate the list
+    // in reverse
+    bool reverseOrder = aIsEvenLevel != frameWM.IsBidiLTR();
+    nsTArray<nsIFrame*> childList;
+    nsIFrame *frame = aFrame->GetFirstPrincipalChild();
+    if (frame && reverseOrder) {
+      childList.AppendElement((nsIFrame*)nullptr);
+      while (frame) {
+        childList.AppendElement(frame);
+        frame = frame->GetNextSibling();
+      }
+      frame = childList[childList.Length() - 1];
+    }
+
     // Reposition the child frames
-    for (nsFrameList::Enumerator e(aFrame->PrincipalChildList());
-         !e.AtEnd(); e.Next()) {
-      icoord += RepositionFrame(e.get(), aIsEvenLevel, icoord,
-                                aContinuationStates,
-                                frameWM, reverseDir, frameSize);
+    int32_t index = 0;
+    nscoord iCoord = borderPadding.IStart(frameWM);
+
+    while (frame) {
+      RepositionFrame(frame,
+                      aIsEvenLevel,
+                      iCoord,
+                      aContinuationStates,
+                      frameWM,
+                      aFrame->GetSize());
+      index++;
+      frame = reverseOrder ?
+                childList[childList.Length() - index - 1] :
+                frame->GetNextSibling();
     }
-    icoord += reverseDir ?
-      borderPadding.IStart(frameWM) : borderPadding.IEnd(frameWM);
-  } else if (aFrame->StyleDisplay()->IsRubyDisplayType()) {
-    icoord += RepositionRubyFrame(aFrame, aContinuationStates,
-                                  aContainerWM, borderPadding);
+
+    aStart += iCoord + borderPadding.IEnd(frameWM);
   } else {
-    icoord +=
-      frameWM.IsOrthogonalTo(aContainerWM) ? aFrame->BSize() : frameISize;
+    aStart += aFrame->ISize(aContainerWM);
   }
 
   // LogicalRect doesn't correctly calculate the vertical position
   // in vertical writing modes with right-to-left direction (Bug 1131451).
   // This does the correct calculation ad hoc pending the fix for that.
   nsRect rect = aFrame->GetRect();
+  nscoord lineSize = aContainerWM.IsVertical()
+    ? aContainerSize.height : aContainerSize.width;
+  NS_ASSERTION(aContainerWM.IsBidiLTR() || lineSize != NS_UNCONSTRAINEDSIZE,
+               "Unconstrained inline line size in bidi frame reordering");
 
-  LogicalMargin margin = frameMargin.ConvertTo(aContainerWM, frameWM);
-  // In the following variables, if aContainerReverseDir is true, i.e.
-  // the container is positioning its children in reverse of its logical
-  // direction, the "StartOrEnd" refers to the distance from the frame
-  // to the inline end edge of the container, elsewise, it refers to the
-  // distance to the inline start edge.
-  nscoord marginStartOrEnd = aContainerReverseDir ?
-    margin.IEnd(aContainerWM) : margin.IStart(aContainerWM);
-  nscoord frameStartOrEnd = aStartOrEnd + marginStartOrEnd;
-  // Whether we are placing frames from right to left.
-  // e.g. If the frames are placed reversely in LTR mode, they are
-  // actually placed from right to left.
-  bool orderingRTL = aContainerReverseDir == aContainerWM.IsBidiLTR();
-  (aContainerWM.IsVertical() ? rect.y : rect.x) = orderingRTL ?
-    lineSize - (frameStartOrEnd + icoord) : frameStartOrEnd;
-  (aContainerWM.IsVertical() ? rect.height : rect.width) = icoord;
+  nscoord frameIStart = aContainerWM.IsBidiLTR() ? start : lineSize - aStart;
+  nscoord frameISize = aStart - start;
+
+  (aContainerWM.IsVertical() ? rect.y : rect.x) = frameIStart;
+  (aContainerWM.IsVertical() ? rect.height : rect.width) = frameISize;
+
   aFrame->SetRect(rect);
 
-  return icoord + margin.IStartEnd(aContainerWM);
+  aStart += margin.IEnd(aContainerWM);
 }
 
 void
 nsBidiPresUtils::InitContinuationStates(nsIFrame*              aFrame,
                                         nsContinuationStates*  aContinuationStates)
 {
   nsFrameContinuationState* state = aContinuationStates->PutEntry(aFrame);
   state->mFirstVisualFrame = nullptr;
   state->mFrameCount = 0;
 
-  if (!IsBidiLeaf(aFrame) ||
-      aFrame->StyleDisplay()->IsRubyDisplayType()) {
+  if (!IsBidiLeaf(aFrame)) {
     // Continue for child frames
     nsIFrame* frame;
     for (frame = aFrame->GetFirstPrincipalChild();
          frame;
          frame = frame->GetNextSibling()) {
       InitContinuationStates(frame,
                              aContinuationStates);
     }
@@ -1631,20 +1546,22 @@ nsBidiPresUtils::RepositionInlineFrames(
     limit = count;
   } else {
     index = count - 1;
     step = -1;
     limit = -1;
   }
   for (; index != limit; index += step) {
     frame = aBld->VisualFrameAt(index);
-    start += RepositionFrame(
-      frame, !(IS_LEVEL_RTL(aBld->mLevels[aBld->mIndexMap[index]])),
-      start, &continuationStates,
-      aLineWM, false, aContainerSize);
+    RepositionFrame(frame,
+                    !(IS_LEVEL_RTL(aBld->mLevels[aBld->mIndexMap[index]])),
+                    start,
+                    &continuationStates,
+                    aLineWM,
+                    aContainerSize);
   }
 }
 
 bool
 nsBidiPresUtils::CheckLineOrder(nsIFrame*  aFirstFrameOnLine,
                                 int32_t    aNumFramesOnLine,
                                 nsIFrame** aFirstVisual,
                                 nsIFrame** aLastVisual)
--- a/layout/base/nsBidiPresUtils.h
+++ b/layout/base/nsBidiPresUtils.h
@@ -22,20 +22,17 @@ class nsFontMetrics;
 class nsIFrame;
 class nsBlockFrame;
 class nsPresContext;
 class nsRenderingContext;
 class nsBlockInFlowLineIterator;
 class nsStyleContext;
 struct nsSize;
 template<class T> class nsTHashtable;
-namespace mozilla {
-  class WritingMode;
-  class LogicalMargin;
-}
+namespace mozilla { class WritingMode; }
 
 /**
  * A structure representing some continuation state for each frame on the line,
  * used to determine the first and the last continuation frame for each
  * continuation chain on the line.
  */
 struct nsFrameContinuationState : public nsVoidPtrHashKey
 {
@@ -157,21 +154,21 @@ public:
                                           BidiParagraphData* aBpd);
 
   /**
    * Reorder this line using Bidi engine.
    * Update frame array, following the new visual sequence.
    * 
    * @lina 05/02/2000
    */
-  static void ReorderFrames(nsIFrame* aFirstFrameOnLine,
-                            int32_t aNumFramesOnLine,
+  static void ReorderFrames(nsIFrame*            aFirstFrameOnLine,
+                            int32_t              aNumFramesOnLine,
                             mozilla::WritingMode aLineWM,
-                            const nsSize& aContainerSize,
-                            nscoord aStart);
+                            const nsSize&        aContainerSize,
+                            nscoord              aStart);
 
   /**
    * Format Unicode text, taking into account bidi capabilities
    * of the platform. The formatting includes: reordering, Arabic shaping,
    * symmetric and numeric swapping, removing control characters.
    *
    * @lina 06/18/2000 
    */
@@ -411,47 +408,35 @@ private:
    *  point.
    */
   static void TraverseFrames(nsBlockFrame*              aBlockFrame,
                              nsBlockInFlowLineIterator* aLineIter,
                              nsIFrame*                  aCurrentFrame,
                              BidiParagraphData*         aBpd);
 
   /*
-   * Position ruby frames. Called from RepositionFrame.
-   */
-  static nscoord RepositionRubyFrame(
-    nsIFrame* aFrame,
-    const nsContinuationStates* aContinuationStates,
-    const mozilla::WritingMode aContainerWM,
-    const mozilla::LogicalMargin& aBorderPadding);
-
-  /*
    * Position aFrame and its descendants to their visual places. Also if aFrame
    * is not leaf, resize it to embrace its children.
    *
    * @param aFrame               The frame which itself and its children are
    *                             going to be repositioned
    * @param aIsEvenLevel         TRUE means the embedding level of this frame
    *                             is even (LTR)
-   * @param aStartOrEnd          The distance to the start or the end of aFrame
-   *                             without considering its inline margin. If the
-   *                             container is reordering frames in reverse
-   *                             direction, it's the distance to the end,
-   *                             otherwise, it's the distance to the start.
+   * @param[in,out] aStart       IN value is the starting position of aFrame
+   *                             (without considering its inline-start margin)
+   *                             OUT value will be the ending position of aFrame
+   *                             (after adding its inline-end margin)
    * @param aContinuationStates  A map from nsIFrame* to nsFrameContinuationState
-   * @return                     The isize aFrame takes, including margins.
    */
-  static nscoord RepositionFrame(nsIFrame* aFrame,
-                                 bool aIsEvenLevel,
-                                 nscoord aStartOrEnd,
-                                 const nsContinuationStates* aContinuationStates,
-                                 mozilla::WritingMode aContainerWM,
-                                 bool aContainerReverseOrder,
-                                 const nsSize& aContainerSize);
+  static void RepositionFrame(nsIFrame*              aFrame,
+                              bool                   aIsEvenLevel,
+                              nscoord&               aStart,
+                              nsContinuationStates*  aContinuationStates,
+                              mozilla::WritingMode   aContainerWM,
+                              const nsSize&          aContainerSize);
 
   /*
    * Initialize the continuation state(nsFrameContinuationState) to
    * (nullptr, 0) for aFrame and its descendants.
    *
    * @param aFrame               The frame which itself and its descendants will
    *                             be initialized
    * @param aContinuationStates  A map from nsIFrame* to nsFrameContinuationState
@@ -478,21 +463,21 @@ private:
    * @param[in] aSpanDirMatchesLineDir TRUE means that the inline
    *                                    direction of aFrame is the same
    *                                    as its container
    * @param[out] aIsFirst              TRUE means aFrame is first frame
    *                                    or continuation
    * @param[out] aIsLast               TRUE means aFrame is last frame
    *                                    or continuation
    */
-   static void IsFirstOrLast(nsIFrame* aFrame,
-                             const nsContinuationStates* aContinuationStates,
-                             bool aSpanInLineOrder /* in */,
-                             bool& aIsFirst /* out */,
-                             bool& aIsLast /* out */);
+   static void IsFirstOrLast(nsIFrame*              aFrame,
+                             nsContinuationStates*  aContinuationStates,
+                             bool                   aSpanInLineOrder /* in */,
+                             bool&                  aIsFirst /* out */,
+                             bool&                  aIsLast /* out */);
 
   /**
    *  Adjust frame positions following their visual order
    *
    *  @param aFirstChild the first kid
    *
    *  @lina 04/11/2000
    */
--- a/layout/generic/RubyUtils.cpp
+++ b/layout/generic/RubyUtils.cpp
@@ -1,20 +1,15 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "RubyUtils.h"
-#include "nsRubyFrame.h"
-#include "nsRubyBaseFrame.h"
-#include "nsRubyTextFrame.h"
-#include "nsRubyBaseContainerFrame.h"
-#include "nsRubyTextContainerFrame.h"
 
 using namespace mozilla;
 
 NS_DECLARE_FRAME_PROPERTY(ReservedISize, nullptr);
 
 union NSCoordValue
 {
   nscoord mCoord;
@@ -42,143 +37,24 @@ RubyUtils::ClearReservedISize(nsIFrame* 
 RubyUtils::GetReservedISize(nsIFrame* aFrame)
 {
   MOZ_ASSERT(IsExpandableRubyBox(aFrame));
   NSCoordValue value;
   value.mPointer = aFrame->Properties().Get(ReservedISize());
   return value.mCoord;
 }
 
-AutoRubyTextContainerArray::AutoRubyTextContainerArray(
+RubyTextContainerIterator::RubyTextContainerIterator(
   nsRubyBaseContainerFrame* aBaseContainer)
 {
-  for (nsIFrame* frame = aBaseContainer->GetNextSibling();
-       frame && frame->GetType() == nsGkAtoms::rubyTextContainerFrame;
-       frame = frame->GetNextSibling()) {
-    AppendElement(static_cast<nsRubyTextContainerFrame*>(frame));
-  }
-}
-
-RubySegmentEnumerator::RubySegmentEnumerator(nsRubyFrame* aRubyFrame)
-{
-  nsIFrame* frame = aRubyFrame->GetFirstPrincipalChild();
-  MOZ_ASSERT(!frame ||
-             frame->GetType() == nsGkAtoms::rubyBaseContainerFrame);
-  mBaseContainer = static_cast<nsRubyBaseContainerFrame*>(frame);
+  mFrame = aBaseContainer;
+  Next();
 }
 
 void
-RubySegmentEnumerator::Next()
-{
-  MOZ_ASSERT(mBaseContainer);
-  nsIFrame* frame = mBaseContainer->GetNextSibling();
-  while (frame && frame->GetType() != nsGkAtoms::rubyBaseContainerFrame) {
-    frame = frame->GetNextSibling();
-  }
-  mBaseContainer = static_cast<nsRubyBaseContainerFrame*>(frame);
-}
-
-RubyColumnEnumerator::RubyColumnEnumerator(
-  nsRubyBaseContainerFrame* aBaseContainer,
-  const AutoRubyTextContainerArray& aTextContainers)
-  : mAtIntraLevelWhitespace(false)
+RubyTextContainerIterator::Next()
 {
-  const uint32_t rtcCount = aTextContainers.Length();
-  mFrames.SetCapacity(rtcCount + 1);
-
-  nsIFrame* rbFrame = aBaseContainer->GetFirstPrincipalChild();
-  MOZ_ASSERT(!rbFrame || rbFrame->GetType() == nsGkAtoms::rubyBaseFrame);
-  mFrames.AppendElement(static_cast<nsRubyContentFrame*>(rbFrame));
-  for (uint32_t i = 0; i < rtcCount; i++) {
-    nsRubyTextContainerFrame* container = aTextContainers[i];
-    // If the container is for span, leave a nullptr here.
-    // Spans do not take part in pairing.
-    nsIFrame* rtFrame = !container->IsSpanContainer() ?
-      container->GetFirstPrincipalChild() : nullptr;
-    MOZ_ASSERT(!rtFrame || rtFrame->GetType() == nsGkAtoms::rubyTextFrame);
-    mFrames.AppendElement(static_cast<nsRubyContentFrame*>(rtFrame));
-  }
-
-  // We have to init mAtIntraLevelWhitespace to be correct for the
-  // first column. There are two ways we could end up with intra-level
-  // whitespace in our first colum:
-  // 1. The current segment itself is an inter-segment whitespace;
-  // 2. If our ruby segment is split across multiple lines, and some
-  //    intra-level whitespace happens to fall right after a line-break.
-  //    Each line will get its own nsRubyBaseContainerFrame, and the
-  //    container right after the line-break will end up with its first
-  //    column containing that intra-level whitespace.
-  for (uint32_t i = 0, iend = mFrames.Length(); i < iend; i++) {
-    nsRubyContentFrame* frame = mFrames[i];
-    if (frame && frame->IsIntraLevelWhitespace()) {
-      mAtIntraLevelWhitespace = true;
-      break;
-    }
+  MOZ_ASSERT(mFrame, "Should have checked AtEnd()");
+  mFrame = mFrame->GetNextSibling();
+  if (mFrame && mFrame->GetType() != nsGkAtoms::rubyTextContainerFrame) {
+    mFrame = nullptr;
   }
 }
-
-void
-RubyColumnEnumerator::Next()
-{
-  bool advancingToIntraLevelWhitespace = false;
-  for (uint32_t i = 0, iend = mFrames.Length(); i < iend; i++) {
-    nsRubyContentFrame* frame = mFrames[i];
-    // If we've got intra-level whitespace frames at some levels in the
-    // current ruby column, we "faked" an anonymous box for all other
-    // levels for this column. So when we advance off this column, we
-    // don't advance any of the frames in those levels, because we're
-    // just advancing across the "fake" frames.
-    if (frame && (!mAtIntraLevelWhitespace ||
-                  frame->IsIntraLevelWhitespace())) {
-      nsIFrame* nextSibling = frame->GetNextSibling();
-      MOZ_ASSERT(!nextSibling || nextSibling->GetType() == frame->GetType(),
-                 "Frame type should be identical among a level");
-      mFrames[i] = frame = static_cast<nsRubyContentFrame*>(nextSibling);
-      if (!advancingToIntraLevelWhitespace &&
-          frame && frame->IsIntraLevelWhitespace()) {
-        advancingToIntraLevelWhitespace = true;
-      }
-    }
-  }
-  MOZ_ASSERT(!advancingToIntraLevelWhitespace || !mAtIntraLevelWhitespace,
-             "Should never have adjacent intra-level whitespace columns");
-  mAtIntraLevelWhitespace = advancingToIntraLevelWhitespace;
-}
-
-bool
-RubyColumnEnumerator::AtEnd() const
-{
-  for (uint32_t i = 0, iend = mFrames.Length(); i < iend; i++) {
-    if (mFrames[i]) {
-      return false;
-    }
-  }
-  return true;
-}
-
-nsRubyContentFrame*
-RubyColumnEnumerator::GetFrameAtLevel(uint32_t aIndex) const
-{
-  // If the current ruby column is for intra-level whitespaces, we
-  // return nullptr for any levels that do not have an actual intra-
-  // level whitespace frame in this column.  This nullptr represents
-  // an anonymous empty intra-level whitespace box.  (In this case,
-  // it's important that we NOT return mFrames[aIndex], because it's
-  // really part of the next column, not the current one.)
-  nsRubyContentFrame* frame = mFrames[aIndex];
-  return !mAtIntraLevelWhitespace ||
-         (frame && frame->IsIntraLevelWhitespace()) ? frame : nullptr;
-}
-
-void
-RubyColumnEnumerator::GetColumn(RubyColumn& aColumn) const
-{
-  nsRubyContentFrame* rbFrame = GetFrameAtLevel(0);
-  MOZ_ASSERT(!rbFrame || rbFrame->GetType() == nsGkAtoms::rubyBaseFrame);
-  aColumn.mBaseFrame = static_cast<nsRubyBaseFrame*>(rbFrame);
-  aColumn.mTextFrames.ClearAndRetainStorage();
-  for (uint32_t i = 1, iend = mFrames.Length(); i < iend; i++) {
-    nsRubyContentFrame* rtFrame = GetFrameAtLevel(i);
-    MOZ_ASSERT(!rtFrame || rtFrame->GetType() == nsGkAtoms::rubyTextFrame);
-    aColumn.mTextFrames.AppendElement(static_cast<nsRubyTextFrame*>(rtFrame));
-  }
-  aColumn.mIsIntraLevelWhitespace = mAtIntraLevelWhitespace;
-}
--- a/layout/generic/RubyUtils.h
+++ b/layout/generic/RubyUtils.h
@@ -2,27 +2,19 @@
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_RubyUtils_h_
 #define mozilla_RubyUtils_h_
 
-#include "nsTArray.h"
 #include "nsGkAtoms.h"
-
-#define RTC_ARRAY_SIZE 1
-
-class nsRubyFrame;
-class nsRubyBaseFrame;
-class nsRubyTextFrame;
-class nsRubyContentFrame;
-class nsRubyBaseContainerFrame;
-class nsRubyTextContainerFrame;
+#include "nsRubyBaseContainerFrame.h"
+#include "nsRubyTextContainerFrame.h"
 
 namespace mozilla {
 
 /**
  * Reserved ISize
  *
  * With some exceptions, each ruby internal box has two isizes, which
  * are the reflowed isize and the final isize. The reflowed isize is
@@ -63,79 +55,30 @@ public:
   }
 
   static void SetReservedISize(nsIFrame* aFrame, nscoord aISize);
   static void ClearReservedISize(nsIFrame* aFrame);
   static nscoord GetReservedISize(nsIFrame* aFrame);
 };
 
 /**
- * This array stores all ruby text containers of the ruby segment
- * of the given ruby base container.
+ * This class iterates all ruby text containers paired with
+ * the given ruby base container.
  */
-class MOZ_STACK_CLASS AutoRubyTextContainerArray final
-  : public nsAutoTArray<nsRubyTextContainerFrame*, RTC_ARRAY_SIZE>
+class MOZ_STACK_CLASS RubyTextContainerIterator
 {
 public:
-  explicit AutoRubyTextContainerArray(nsRubyBaseContainerFrame* aBaseContainer);
-};
-
-/**
- * This enumerator enumerates each ruby segment.
- */
-class MOZ_STACK_CLASS RubySegmentEnumerator
-{
-public:
-  explicit RubySegmentEnumerator(nsRubyFrame* aRubyFrame);
+  explicit RubyTextContainerIterator(nsRubyBaseContainerFrame* aBaseContainer);
 
   void Next();
-  bool AtEnd() const { return !mBaseContainer; }
-
-  nsRubyBaseContainerFrame* GetBaseContainer() const
+  bool AtEnd() const { return !mFrame; }
+  nsRubyTextContainerFrame* GetTextContainer() const
   {
-    return mBaseContainer;
+    return static_cast<nsRubyTextContainerFrame*>(mFrame);
   }
 
 private:
-  nsRubyBaseContainerFrame* mBaseContainer;
-};
-
-/**
- * Ruby column is a unit consists of one ruby base and all ruby
- * annotations paired with it.
- * See http://dev.w3.org/csswg/css-ruby/#ruby-pairing
- */
-struct MOZ_STACK_CLASS RubyColumn
-{
-  nsRubyBaseFrame* mBaseFrame;
-  nsAutoTArray<nsRubyTextFrame*, RTC_ARRAY_SIZE> mTextFrames;
-  bool mIsIntraLevelWhitespace;
-  RubyColumn() : mBaseFrame(nullptr), mIsIntraLevelWhitespace(false) { }
-};
-
-/**
- * This enumerator enumerates ruby columns in a segment.
- */
-class MOZ_STACK_CLASS RubyColumnEnumerator
-{
-public:
-  RubyColumnEnumerator(nsRubyBaseContainerFrame* aRBCFrame,
-                       const AutoRubyTextContainerArray& aRTCFrames);
-
-  void Next();
-  bool AtEnd() const;
-
-  uint32_t GetLevelCount() const { return mFrames.Length(); }
-  nsRubyContentFrame* GetFrameAtLevel(uint32_t aIndex) const;
-  void GetColumn(RubyColumn& aColumn) const;
-
-private:
-  // Frames in this array are NOT necessary part of the current column.
-  // When in doubt, use GetFrameAtLevel to access it.
-  // See GetFrameAtLevel() and Next() for more info.
-  nsAutoTArray<nsRubyContentFrame*, RTC_ARRAY_SIZE + 1> mFrames;
-  // Whether we are on a column for intra-level whitespaces
-  bool mAtIntraLevelWhitespace;
+  nsIFrame* mFrame;
 };
 
 }
 
 #endif /* !defined(mozilla_RubyUtils_h_) */
--- a/layout/generic/moz.build
+++ b/layout/generic/moz.build
@@ -81,25 +81,19 @@ EXPORTS += [
     'nsILineIterator.h',
     'nsIObjectFrame.h',
     'nsIPageSequenceFrame.h',
     'nsIScrollableFrame.h',
     'nsIScrollPositionListener.h',
     'nsIStatefulFrame.h',
     'nsPluginFrame.h',
     'nsQueryFrame.h',
-    'nsRubyBaseContainerFrame.h',
-    'nsRubyBaseFrame.h',
-    'nsRubyFrame.h',
-    'nsRubyTextContainerFrame.h',
-    'nsRubyTextFrame.h',
     'nsSplittableFrame.h',
     'nsSubDocumentFrame.h',
     'nsTextRunTransformations.h',
-    'RubyUtils.h',
     'ScrollbarActivity.h',
 ]
 
 EXPORTS.mozilla += [
     'WritingModes.h',
 ]
 
 EXPORTS.mozilla.dom += [
--- a/layout/generic/nsLineLayout.cpp
+++ b/layout/generic/nsLineLayout.cpp
@@ -20,17 +20,16 @@
 #include "nsPresContext.h"
 #include "nsGkAtoms.h"
 #include "nsIContent.h"
 #include "nsLayoutUtils.h"
 #include "nsTextFrame.h"
 #include "nsStyleStructInlines.h"
 #include "nsBidiPresUtils.h"
 #include "nsRubyFrame.h"
-#include "nsRubyTextFrame.h"
 #include "RubyUtils.h"
 #include <algorithm>
 
 #ifdef DEBUG
 #undef  NOISY_INLINEDIR_ALIGN
 #undef  NOISY_BLOCKDIR_ALIGN
 #undef  REALLY_NOISY_BLOCKDIR_ALIGN
 #undef  NOISY_REFLOW
--- a/layout/generic/nsRubyBaseContainerFrame.cpp
+++ b/layout/generic/nsRubyBaseContainerFrame.cpp
@@ -2,19 +2,17 @@
 /* vim: set ts=2 et sw=2 tw=80: */
 /* This Source Code is subject to the terms of the Mozilla Public License
  * version 2.0 (the "License"). You can obtain a copy of the License at
  * http://mozilla.org/MPL/2.0/. */
 
 /* rendering object for CSS "display: ruby-base-container" */
 
 #include "nsRubyBaseContainerFrame.h"
-#include "nsRubyTextContainerFrame.h"
-#include "nsRubyBaseFrame.h"
-#include "nsRubyTextFrame.h"
+
 #include "mozilla/DebugOnly.h"
 #include "mozilla/Maybe.h"
 #include "mozilla/WritingModes.h"
 #include "nsContentUtils.h"
 #include "nsLineLayout.h"
 #include "nsPresContext.h"
 #include "nsStyleContext.h"
 #include "nsStyleStructInlines.h"
@@ -56,16 +54,158 @@ nsRubyBaseContainerFrame::GetType() cons
 #ifdef DEBUG_FRAME_DUMP
 nsresult
 nsRubyBaseContainerFrame::GetFrameName(nsAString& aResult) const
 {
   return MakeFrameName(NS_LITERAL_STRING("RubyBaseContainer"), aResult);
 }
 #endif
 
+/**
+ * Ruby column is a unit consists of one ruby base and all ruby
+ * annotations paired with it.
+ * See http://dev.w3.org/csswg/css-ruby/#ruby-pairing
+ */
+struct MOZ_STACK_CLASS mozilla::RubyColumn
+{
+  nsRubyBaseFrame* mBaseFrame;
+  nsAutoTArray<nsRubyTextFrame*, RTC_ARRAY_SIZE> mTextFrames;
+  bool mIsIntraLevelWhitespace;
+  RubyColumn() : mBaseFrame(nullptr), mIsIntraLevelWhitespace(false) { }
+};
+
+class MOZ_STACK_CLASS RubyColumnEnumerator
+{
+public:
+  RubyColumnEnumerator(nsRubyBaseContainerFrame* aRBCFrame,
+                       const nsTArray<nsRubyTextContainerFrame*>& aRTCFrames);
+
+  void Next();
+  bool AtEnd() const;
+
+  uint32_t GetLevelCount() const { return mFrames.Length(); }
+  nsRubyContentFrame* GetFrameAtLevel(uint32_t aIndex) const;
+  void GetColumn(RubyColumn& aColumn) const;
+
+private:
+  // Frames in this array are NOT necessary part of the current column.
+  // When in doubt, use GetFrameAtLevel to access it.
+  // See GetFrameAtLevel() and Next() for more info.
+  nsAutoTArray<nsRubyContentFrame*, RTC_ARRAY_SIZE + 1> mFrames;
+  // Whether we are on a column for intra-level whitespaces
+  bool mAtIntraLevelWhitespace;
+};
+
+RubyColumnEnumerator::RubyColumnEnumerator(
+  nsRubyBaseContainerFrame* aBaseContainer,
+  const nsTArray<nsRubyTextContainerFrame*>& aTextContainers)
+  : mAtIntraLevelWhitespace(false)
+{
+  const uint32_t rtcCount = aTextContainers.Length();
+  mFrames.SetCapacity(rtcCount + 1);
+
+  nsIFrame* rbFrame = aBaseContainer->GetFirstPrincipalChild();
+  MOZ_ASSERT(!rbFrame || rbFrame->GetType() == nsGkAtoms::rubyBaseFrame);
+  mFrames.AppendElement(static_cast<nsRubyContentFrame*>(rbFrame));
+  for (uint32_t i = 0; i < rtcCount; i++) {
+    nsRubyTextContainerFrame* container = aTextContainers[i];
+    // If the container is for span, leave a nullptr here.
+    // Spans do not take part in pairing.
+    nsIFrame* rtFrame = !container->IsSpanContainer() ?
+      container->GetFirstPrincipalChild() : nullptr;
+    MOZ_ASSERT(!rtFrame || rtFrame->GetType() == nsGkAtoms::rubyTextFrame);
+    mFrames.AppendElement(static_cast<nsRubyContentFrame*>(rtFrame));
+  }
+
+  // We have to init mAtIntraLevelWhitespace to be correct for the
+  // first column. There are two ways we could end up with intra-level
+  // whitespace in our first colum:
+  // 1. The current segment itself is an inter-segment whitespace;
+  // 2. If our ruby segment is split across multiple lines, and some
+  //    intra-level whitespace happens to fall right after a line-break.
+  //    Each line will get its own nsRubyBaseContainerFrame, and the
+  //    container right after the line-break will end up with its first
+  //    column containing that intra-level whitespace.
+  for (uint32_t i = 0, iend = mFrames.Length(); i < iend; i++) {
+    nsRubyContentFrame* frame = mFrames[i];
+    if (frame && frame->IsIntraLevelWhitespace()) {
+      mAtIntraLevelWhitespace = true;
+      break;
+    }
+  }
+}
+
+void
+RubyColumnEnumerator::Next()
+{
+  bool advancingToIntraLevelWhitespace = false;
+  for (uint32_t i = 0, iend = mFrames.Length(); i < iend; i++) {
+    nsRubyContentFrame* frame = mFrames[i];
+    // If we've got intra-level whitespace frames at some levels in the
+    // current ruby column, we "faked" an anonymous box for all other
+    // levels for this column. So when we advance off this column, we
+    // don't advance any of the frames in those levels, because we're
+    // just advancing across the "fake" frames.
+    if (frame && (!mAtIntraLevelWhitespace ||
+                  frame->IsIntraLevelWhitespace())) {
+      nsIFrame* nextSibling = frame->GetNextSibling();
+      MOZ_ASSERT(!nextSibling || nextSibling->GetType() == frame->GetType(),
+                 "Frame type should be identical among a level");
+      mFrames[i] = frame = static_cast<nsRubyContentFrame*>(nextSibling);
+      if (!advancingToIntraLevelWhitespace &&
+          frame && frame->IsIntraLevelWhitespace()) {
+        advancingToIntraLevelWhitespace = true;
+      }
+    }
+  }
+  MOZ_ASSERT(!advancingToIntraLevelWhitespace || !mAtIntraLevelWhitespace,
+             "Should never have adjacent intra-level whitespace columns");
+  mAtIntraLevelWhitespace = advancingToIntraLevelWhitespace;
+}
+
+bool
+RubyColumnEnumerator::AtEnd() const
+{
+  for (uint32_t i = 0, iend = mFrames.Length(); i < iend; i++) {
+    if (mFrames[i]) {
+      return false;
+    }
+  }
+  return true;
+}
+
+nsRubyContentFrame*
+RubyColumnEnumerator::GetFrameAtLevel(uint32_t aIndex) const
+{
+  // If the current ruby column is for intra-level whitespaces, we
+  // return nullptr for any levels that do not have an actual intra-
+  // level whitespace frame in this column.  This nullptr represents
+  // an anonymous empty intra-level whitespace box.  (In this case,
+  // it's important that we NOT return mFrames[aIndex], because it's
+  // really part of the next column, not the current one.)
+  nsRubyContentFrame* frame = mFrames[aIndex];
+  return !mAtIntraLevelWhitespace ||
+         (frame && frame->IsIntraLevelWhitespace()) ? frame : nullptr;
+}
+
+void
+RubyColumnEnumerator::GetColumn(RubyColumn& aColumn) const
+{
+  nsRubyContentFrame* rbFrame = GetFrameAtLevel(0);
+  MOZ_ASSERT(!rbFrame || rbFrame->GetType() == nsGkAtoms::rubyBaseFrame);
+  aColumn.mBaseFrame = static_cast<nsRubyBaseFrame*>(rbFrame);
+  aColumn.mTextFrames.ClearAndRetainStorage();
+  for (uint32_t i = 1, iend = mFrames.Length(); i < iend; i++) {
+    nsRubyContentFrame* rtFrame = GetFrameAtLevel(i);
+    MOZ_ASSERT(!rtFrame || rtFrame->GetType() == nsGkAtoms::rubyTextFrame);
+    aColumn.mTextFrames.AppendElement(static_cast<nsRubyTextFrame*>(rtFrame));
+  }
+  aColumn.mIsIntraLevelWhitespace = mAtIntraLevelWhitespace;
+}
+
 static gfxBreakPriority
 LineBreakBefore(nsIFrame* aFrame,
                 nsRenderingContext* aRenderingContext,
                 nsIFrame* aLineContainerFrame,
                 const nsLineList::iterator* aLine)
 {
   for (nsIFrame* child = aFrame; child;
        child = child->GetFirstPrincipalChild()) {
@@ -148,17 +288,18 @@ CalculateColumnPrefISize(nsRenderingCont
 
 // FIXME Currently we use pref isize of ruby content frames for
 //       computing min isize of ruby frame, which may cause problem.
 //       See bug 1134945.
 /* virtual */ void
 nsRubyBaseContainerFrame::AddInlineMinISize(
   nsRenderingContext *aRenderingContext, nsIFrame::InlineMinISizeData *aData)
 {
-  AutoRubyTextContainerArray textContainers(this);
+  AutoTextContainerArray textContainers;
+  GetTextContainers(textContainers);
 
   for (uint32_t i = 0, iend = textContainers.Length(); i < iend; i++) {
     if (textContainers[i]->IsSpanContainer()) {
       // Since spans are not breakable internally, use our pref isize
       // directly if there is any span.
       nsIFrame::InlinePrefISizeData data;
       AddInlinePrefISize(aRenderingContext, &data);
       aData->currentLine += data.currentLine;
@@ -196,17 +337,18 @@ nsRubyBaseContainerFrame::AddInlineMinIS
     }
   }
 }
 
 /* virtual */ void
 nsRubyBaseContainerFrame::AddInlinePrefISize(
   nsRenderingContext *aRenderingContext, nsIFrame::InlinePrefISizeData *aData)
 {
-  AutoRubyTextContainerArray textContainers(this);
+  AutoTextContainerArray textContainers;
+  GetTextContainers(textContainers);
 
   nscoord sum = 0;
   for (nsIFrame* frame = this; frame; frame = frame->GetNextInFlow()) {
     RubyColumnEnumerator enumerator(
       static_cast<nsRubyBaseContainerFrame*>(frame), textContainers);
     for (; !enumerator.AtEnd(); enumerator.Next()) {
       sum += CalculateColumnPrefISize(aRenderingContext, enumerator);
     }
@@ -228,16 +370,25 @@ nsRubyBaseContainerFrame::IsFrameOfType(
 {
   if (aFlags & eSupportsCSSTransforms) {
     return false;
   }
   return nsContainerFrame::IsFrameOfType(aFlags &
          ~(nsIFrame::eLineParticipant));
 }
 
+void
+nsRubyBaseContainerFrame::GetTextContainers(TextContainerArray& aTextContainers)
+{
+  MOZ_ASSERT(aTextContainers.IsEmpty());
+  for (RubyTextContainerIterator iter(this); !iter.AtEnd(); iter.Next()) {
+    aTextContainers.AppendElement(iter.GetTextContainer());
+  }
+}
+
 /* virtual */ bool
 nsRubyBaseContainerFrame::CanContinueTextRun() const
 {
   return true;
 }
 
 /* virtual */ LogicalSize
 nsRubyBaseContainerFrame::ComputeSize(nsRenderingContext *aRenderingContext,
@@ -259,17 +410,17 @@ nsRubyBaseContainerFrame::GetLogicalBase
 {
   return mBaseline;
 }
 
 struct nsRubyBaseContainerFrame::ReflowState
 {
   bool mAllowInitialLineBreak;
   bool mAllowLineBreak;
-  const AutoRubyTextContainerArray& mTextContainers;
+  const TextContainerArray& mTextContainers;
   const nsHTMLReflowState& mBaseReflowState;
   const nsTArray<UniquePtr<nsHTMLReflowState>>& mTextReflowStates;
 };
 
 /* virtual */ void
 nsRubyBaseContainerFrame::Reflow(nsPresContext* aPresContext,
                                  nsHTMLReflowMetrics& aDesiredSize,
                                  const nsHTMLReflowState& aReflowState,
@@ -282,19 +433,21 @@ nsRubyBaseContainerFrame::Reflow(nsPresC
 
   if (!aReflowState.mLineLayout) {
     NS_ASSERTION(
       aReflowState.mLineLayout,
       "No line layout provided to RubyBaseContainerFrame reflow method.");
     return;
   }
 
+  AutoTextContainerArray textContainers;
+  GetTextContainers(textContainers);
+
   MoveOverflowToChildList();
   // Ask text containers to drain overflows
-  AutoRubyTextContainerArray textContainers(this);
   const uint32_t rtcCount = textContainers.Length();
   for (uint32_t i = 0; i < rtcCount; i++) {
     textContainers[i]->MoveOverflowToChildList();
   }
 
   WritingMode lineWM = aReflowState.mLineLayout->GetWritingMode();
   LogicalSize availSize(lineWM, aReflowState.AvailableISize(),
                         aReflowState.AvailableBSize());
@@ -315,18 +468,17 @@ nsRubyBaseContainerFrame::Reflow(nsPresC
   bool hasSpan = false;
   for (uint32_t i = 0; i < rtcCount; i++) {
     nsRubyTextContainerFrame* textContainer = textContainers[i];
     if (textContainer->IsSpanContainer()) {
       hasSpan = true;
     }
 
     nsHTMLReflowState* reflowState = new nsHTMLReflowState(
-      aPresContext, *aReflowState.parentReflowState, textContainer,
-      availSize.ConvertTo(textContainer->GetWritingMode(), lineWM));
+      aPresContext, *aReflowState.parentReflowState, textContainer, availSize);
     reflowStates.AppendElement(reflowState);
     nsLineLayout* lineLayout = new nsLineLayout(aPresContext,
                                                 reflowState->mFloatManager,
                                                 reflowState, nullptr,
                                                 aReflowState.mLineLayout);
     lineLayout->SetSuppressLineWrap(true);
     lineLayouts.AppendElement(lineLayout);
 
@@ -423,20 +575,20 @@ nsRubyBaseContainerFrame::Reflow(nsPresC
  * This struct stores the continuations after this frame and
  * corresponding text containers. It is used to speed up looking
  * ahead for nonempty continuations.
  */
 struct MOZ_STACK_CLASS nsRubyBaseContainerFrame::PullFrameState
 {
   ContinuationTraversingState mBase;
   nsAutoTArray<ContinuationTraversingState, RTC_ARRAY_SIZE> mTexts;
-  const AutoRubyTextContainerArray& mTextContainers;
+  const TextContainerArray& mTextContainers;
 
   PullFrameState(nsRubyBaseContainerFrame* aBaseContainer,
-                 const AutoRubyTextContainerArray& aTextContainers);
+                 const TextContainerArray& aTextContainers);
 };
 
 nscoord
 nsRubyBaseContainerFrame::ReflowColumns(const ReflowState& aReflowState,
                                         nsReflowStatus& aStatus)
 {
   nsLineLayout* lineLayout = aReflowState.mBaseReflowState.mLineLayout;
   const uint32_t rtcCount = aReflowState.mTextContainers.Length();
@@ -677,34 +829,33 @@ nsRubyBaseContainerFrame::ReflowOneColum
     }
   }
 
   return columnISize;
 }
 
 nsRubyBaseContainerFrame::PullFrameState::PullFrameState(
     nsRubyBaseContainerFrame* aBaseContainer,
-    const AutoRubyTextContainerArray& aTextContainers)
+    const TextContainerArray& aTextContainers)
   : mBase(aBaseContainer)
   , mTextContainers(aTextContainers)
 {
   const uint32_t rtcCount = aTextContainers.Length();
   for (uint32_t i = 0; i < rtcCount; i++) {
     mTexts.AppendElement(aTextContainers[i]);
   }
 }
 
 void
 nsRubyBaseContainerFrame::PullOneColumn(nsLineLayout* aLineLayout,
                                         PullFrameState& aPullFrameState,
                                         RubyColumn& aColumn,
                                         bool& aIsComplete)
 {
-  const AutoRubyTextContainerArray& textContainers =
-    aPullFrameState.mTextContainers;
+  const TextContainerArray& textContainers = aPullFrameState.mTextContainers;
   const uint32_t rtcCount = textContainers.Length();
 
   nsIFrame* nextBase = GetNextInFlowChild(aPullFrameState.mBase);
   MOZ_ASSERT(!nextBase || nextBase->GetType() == nsGkAtoms::rubyBaseFrame);
   aColumn.mBaseFrame = static_cast<nsRubyBaseFrame*>(nextBase);
   aIsComplete = !aColumn.mBaseFrame;
   bool pullingIntraLevelWhitespace =
     aColumn.mBaseFrame && aColumn.mBaseFrame->IsIntraLevelWhitespace();
--- a/layout/generic/nsRubyBaseContainerFrame.h
+++ b/layout/generic/nsRubyBaseContainerFrame.h
@@ -5,16 +5,21 @@
  * http://mozilla.org/MPL/2.0/. */
 
 /* rendering object for CSS "display: ruby-base-container" */
 
 #ifndef nsRubyBaseContainerFrame_h___
 #define nsRubyBaseContainerFrame_h___
 
 #include "nsContainerFrame.h"
+#include "nsRubyTextContainerFrame.h"
+#include "nsRubyBaseFrame.h"
+#include "nsRubyTextFrame.h"
+
+#define RTC_ARRAY_SIZE 1
 
 /**
  * Factory function.
  * @return a newly allocated nsRubyBaseContainerFrame (infallible)
  */
 nsContainerFrame* NS_NewRubyBaseContainerFrame(nsIPresShell* aPresShell,
                                                nsStyleContext* aContext);
 
@@ -59,16 +64,20 @@ public:
 #endif
 
 protected:
   friend nsContainerFrame*
     NS_NewRubyBaseContainerFrame(nsIPresShell* aPresShell,
                                  nsStyleContext* aContext);
   explicit nsRubyBaseContainerFrame(nsStyleContext* aContext) : nsContainerFrame(aContext) {}
 
+  typedef nsTArray<nsRubyTextContainerFrame*> TextContainerArray;
+  typedef nsAutoTArray<nsRubyTextContainerFrame*, RTC_ARRAY_SIZE> AutoTextContainerArray;
+  void GetTextContainers(TextContainerArray& aTextContainers);
+
   struct ReflowState;
   nscoord ReflowColumns(const ReflowState& aReflowState,
                         nsReflowStatus& aStatus);
   nscoord ReflowOneColumn(const ReflowState& aReflowState,
                           uint32_t aColumnIndex,
                           const mozilla::RubyColumn& aColumn,
                           nsReflowStatus& aStatus);
   nscoord ReflowSpans(const ReflowState& aReflowState);
--- a/layout/generic/nsRubyFrame.cpp
+++ b/layout/generic/nsRubyFrame.cpp
@@ -60,34 +60,73 @@ nsRubyFrame::IsFrameOfType(uint32_t aFla
 #ifdef DEBUG_FRAME_DUMP
 nsresult
 nsRubyFrame::GetFrameName(nsAString& aResult) const
 {
   return MakeFrameName(NS_LITERAL_STRING("Ruby"), aResult);
 }
 #endif
 
+/**
+ * This enumerator enumerates each segment.
+ */
+class MOZ_STACK_CLASS SegmentEnumerator
+{
+public:
+  explicit SegmentEnumerator(nsRubyFrame* aRubyFrame);
+
+  void Next();
+  bool AtEnd() const { return !mBaseContainer; }
+
+  nsRubyBaseContainerFrame* GetBaseContainer() const
+  {
+    return mBaseContainer;
+  }
+
+private:
+  nsRubyBaseContainerFrame* mBaseContainer;
+};
+
+SegmentEnumerator::SegmentEnumerator(nsRubyFrame* aRubyFrame)
+{
+  nsIFrame* frame = aRubyFrame->GetFirstPrincipalChild();
+  MOZ_ASSERT(!frame ||
+             frame->GetType() == nsGkAtoms::rubyBaseContainerFrame);
+  mBaseContainer = static_cast<nsRubyBaseContainerFrame*>(frame);
+}
+
+void
+SegmentEnumerator::Next()
+{
+  MOZ_ASSERT(mBaseContainer);
+  nsIFrame* frame = mBaseContainer->GetNextSibling();
+  while (frame && frame->GetType() != nsGkAtoms::rubyBaseContainerFrame) {
+    frame = frame->GetNextSibling();
+  }
+  mBaseContainer = static_cast<nsRubyBaseContainerFrame*>(frame);
+}
+
 /* virtual */ void
 nsRubyFrame::AddInlineMinISize(nsRenderingContext *aRenderingContext,
                                nsIFrame::InlineMinISizeData *aData)
 {
   for (nsIFrame* frame = this; frame; frame = frame->GetNextInFlow()) {
-    for (RubySegmentEnumerator e(static_cast<nsRubyFrame*>(frame));
+    for (SegmentEnumerator e(static_cast<nsRubyFrame*>(frame));
          !e.AtEnd(); e.Next()) {
       e.GetBaseContainer()->AddInlineMinISize(aRenderingContext, aData);
     }
   }
 }
 
 /* virtual */ void
 nsRubyFrame::AddInlinePrefISize(nsRenderingContext *aRenderingContext,
                                 nsIFrame::InlinePrefISizeData *aData)
 {
   for (nsIFrame* frame = this; frame; frame = frame->GetNextInFlow()) {
-    for (RubySegmentEnumerator e(static_cast<nsRubyFrame*>(frame));
+    for (SegmentEnumerator e(static_cast<nsRubyFrame*>(frame));
          !e.AtEnd(); e.Next()) {
       e.GetBaseContainer()->AddInlinePrefISize(aRenderingContext, aData);
     }
   }
 }
 
 /* virtual */ void
 nsRubyFrame::Reflow(nsPresContext* aPresContext,
@@ -125,17 +164,17 @@ nsRubyFrame::Reflow(nsPresContext* aPres
   NS_ASSERTION(aReflowState.AvailableISize() != NS_UNCONSTRAINEDSIZE,
                "should no longer use available widths");
   nscoord availableISize = aReflowState.AvailableISize();
   availableISize -= startEdge + borderPadding.IEnd(frameWM);
   aReflowState.mLineLayout->BeginSpan(this, &aReflowState,
                                       startEdge, availableISize, &mBaseline);
 
   aStatus = NS_FRAME_COMPLETE;
-  for (RubySegmentEnumerator e(this); !e.AtEnd(); e.Next()) {
+  for (SegmentEnumerator e(this); !e.AtEnd(); e.Next()) {
     ReflowSegment(aPresContext, aReflowState, e.GetBaseContainer(), aStatus);
 
     if (NS_INLINE_IS_BREAK(aStatus)) {
       // A break occurs when reflowing the segment.
       // Don't continue reflowing more segments.
       break;
     }
   }
@@ -168,21 +207,21 @@ void
 nsRubyFrame::ReflowSegment(nsPresContext* aPresContext,
                            const nsHTMLReflowState& aReflowState,
                            nsRubyBaseContainerFrame* aBaseContainer,
                            nsReflowStatus& aStatus)
 {
   WritingMode lineWM = aReflowState.mLineLayout->GetWritingMode();
   LogicalSize availSize(lineWM, aReflowState.AvailableISize(),
                         aReflowState.AvailableBSize());
-  WritingMode rubyWM = GetWritingMode();
-  NS_ASSERTION(!rubyWM.IsOrthogonalTo(lineWM),
-               "Ruby frame writing-mode shouldn't be orthogonal to its line");
 
-  AutoRubyTextContainerArray textContainers(aBaseContainer);
+  nsAutoTArray<nsRubyTextContainerFrame*, RTC_ARRAY_SIZE> textContainers;
+  for (RubyTextContainerIterator iter(aBaseContainer); !iter.AtEnd(); iter.Next()) {
+    textContainers.AppendElement(iter.GetTextContainer());
+  }
   const uint32_t rtcCount = textContainers.Length();
 
   nsHTMLReflowMetrics baseMetrics(aReflowState);
   bool pushedFrame;
   aReflowState.mLineLayout->ReflowFrame(aBaseContainer, aStatus,
                                         &baseMetrics, pushedFrame);
 
   if (NS_INLINE_IS_BREAK_BEFORE(aStatus)) {
@@ -261,40 +300,38 @@ nsRubyFrame::ReflowSegment(nsPresContext
   // lines, so we use 0 instead. (i.e. we assume that the base container
   // is adjacent to the ruby frame's block-start edge.)
   // XXX We may need to add border/padding here. See bug 1055667.
   baseRect.BStart(lineWM) = 0;
   // The rect for offsets of text containers.
   LogicalRect offsetRect = baseRect;
   for (uint32_t i = 0; i < rtcCount; i++) {
     nsRubyTextContainerFrame* textContainer = textContainers[i];
-    WritingMode rtcWM = textContainer->GetWritingMode();
     nsReflowStatus textReflowStatus;
     nsHTMLReflowMetrics textMetrics(aReflowState);
-    nsHTMLReflowState textReflowState(aPresContext, aReflowState, textContainer,
-                                      availSize.ConvertTo(rtcWM, lineWM));
+    nsHTMLReflowState textReflowState(aPresContext, aReflowState,
+                                      textContainer, availSize);
     // FIXME We probably shouldn't be using the same nsLineLayout for
     //       the text containers. But it should be fine now as we are
     //       not actually using this line layout to reflow something,
     //       but just read the writing mode from it.
     textReflowState.mLineLayout = aReflowState.mLineLayout;
     textContainer->Reflow(aPresContext, textMetrics,
                           textReflowState, textReflowStatus);
     // Ruby text containers always return NS_FRAME_COMPLETE even when
     // they have continuations, because the breaking has already been
     // handled when reflowing the base containers.
     NS_ASSERTION(textReflowStatus == NS_FRAME_COMPLETE,
                  "Ruby text container must not break itself inside");
-    // The metrics is initialized with reflow state of this ruby frame,
-    // hence the writing-mode is tied to rubyWM instead of rtcWM.
-    LogicalSize size = textMetrics.Size(rubyWM).ConvertTo(lineWM, rubyWM);
-    textContainer->SetSize(lineWM, size);
+    nscoord isize = textMetrics.ISize(lineWM);
+    nscoord bsize = textMetrics.BSize(lineWM);
+    textContainer->SetSize(LogicalSize(lineWM, isize, bsize));
 
     nscoord reservedISize = RubyUtils::GetReservedISize(textContainer);
-    segmentISize = std::max(segmentISize, size.ISize(lineWM) + reservedISize);
+    segmentISize = std::max(segmentISize, isize + reservedISize);
 
     uint8_t rubyPosition = textContainer->StyleText()->mRubyPosition;
     MOZ_ASSERT(rubyPosition == NS_STYLE_RUBY_POSITION_OVER ||
                rubyPosition == NS_STYLE_RUBY_POSITION_UNDER);
     Maybe<LogicalSide> side;
     if (rubyPosition == NS_STYLE_RUBY_POSITION_OVER) {
       side.emplace(lineWM.LogicalSideForLineRelativeDir(eLineRelativeDirOver));
     } else if (rubyPosition == NS_STYLE_RUBY_POSITION_UNDER) {
@@ -302,23 +339,23 @@ nsRubyFrame::ReflowSegment(nsPresContext
     } else {
       // XXX inter-character support in bug 1055672
       MOZ_ASSERT_UNREACHABLE("Unsupported ruby-position");
     }
 
     LogicalPoint position(lineWM);
     if (side.isSome()) {
       if (side.value() == eLogicalSideBStart) {
-        offsetRect.BStart(lineWM) -= size.BSize(lineWM);
-        offsetRect.BSize(lineWM) += size.BSize(lineWM);
+        offsetRect.BStart(lineWM) -= bsize;
+        offsetRect.BSize(lineWM) += bsize;
         position = offsetRect.Origin(lineWM);
       } else if (side.value() == eLogicalSideBEnd) {
         position = offsetRect.Origin(lineWM) +
           LogicalPoint(lineWM, 0, offsetRect.BSize(lineWM));
-        offsetRect.BSize(lineWM) += size.BSize(lineWM);
+        offsetRect.BSize(lineWM) += bsize;
       } else {
         MOZ_ASSERT_UNREACHABLE("???");
       }
     }
     // Container width is set to zero here. We will fix it in
     // nsLineLayout after the whole line get reflowed.
     FinishReflowChild(textContainer, aPresContext, textMetrics,
                       &textReflowState, lineWM, position, 0, 0);
--- a/layout/generic/nsRubyTextContainerFrame.h
+++ b/layout/generic/nsRubyTextContainerFrame.h
@@ -5,16 +5,19 @@
  * http://mozilla.org/MPL/2.0/. */
 
 /* rendering object for CSS "display: ruby-text-container" */
 
 #ifndef nsRubyTextContainerFrame_h___
 #define nsRubyTextContainerFrame_h___
 
 #include "nsBlockFrame.h"
+#include "nsRubyBaseFrame.h"
+#include "nsRubyTextFrame.h"
+#include "nsLineLayout.h"
 
 typedef nsContainerFrame nsRubyTextContainerFrameSuper;
 
 /**
  * Factory function.
  * @return a newly allocated nsRubyTextContainerFrame (infallible)
  */
 nsContainerFrame* NS_NewRubyTextContainerFrame(nsIPresShell* aPresShell,
deleted file mode 100644
--- a/layout/reftests/css-ruby/bidi-2-ref.html
+++ /dev/null
@@ -1,38 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-<head>
-  <meta charset="UTF-8">
-  <title>Bug 1141931 - Bidi reordering of ruby</title>
-  <link rel="stylesheet" href="common.css">
-</head>
-<body>
-  <p>
-    <ruby>
-      <rb>base1</rb><rb>base2</rb>
-      <rt>text1</rt><rt>text2</rt>
-      <rb>base4</rb><rb>base3</rb>
-      <rt>text4</rt><rt>text3</rt>
-    </ruby>
-    <ruby>
-      <rb>base7</rb><rb>base8</rb>
-      <rt>text7</rt><rt>text8</rt>
-      <rb>base6</rb><rb>base5</rb>
-      <rt>text6</rt><rt>text5</rt>
-    </ruby>
-  </p>
-  <p style="text-align: right">
-    <ruby>
-      <rb>base5</rb><rb>base6</rb>
-      <rt>text5</rt><rt>text6</rt>
-      <rb>base8</rb><rb>base7</rb>
-      <rt>text8</rt><rt>text7</rt>
-    </ruby>
-    <ruby>
-      <rb>base3</rb><rb>base4</rb>
-      <rt>text3</rt><rt>text4</rt>
-      <rb>base2</rb><rb>base1</rb>
-      <rt>text2</rt><rt>text1</rt>
-    </ruby>
-  </p>
-</body>
-</html>
deleted file mode 100644
--- a/layout/reftests/css-ruby/bidi-2.html
+++ /dev/null
@@ -1,50 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-<head>
-  <meta charset="UTF-8">
-  <title>Bug 1141931 - Bidi reordering of ruby</title>
-  <link rel="stylesheet" href="common.css">
-</head>
-<body>
-  <p>
-    <ruby>
-      <rb>base1</rb><rb>base2</rb>
-      <rtc dir="rtl">
-        <rt>text1</rt><rt>text2</rt>
-      </rtc>
-      <rbc dir="rtl">
-        <rb>base3</rb><rb>base4</rb>
-      </rbc>
-      <rt>text3</rt><rt>text4</rt>
-    </ruby>
-    <ruby dir="rtl">
-      <rb>base5</rb><rb>base6</rb>
-      <rt>text5</rt><rt>text6</rt>
-      <rbc dir="ltr">
-        <rb>base7</rb><rb>base8</rb>
-      </rbc>
-      <rt>text7</rt><rt>text8</rt>
-    </ruby>
-  </p>
-  <p dir="rtl">
-    <ruby>
-      <rb>base1</rb><rb>base2</rb>
-      <rtc dir="ltr">
-        <rt>text1</rt><rt>text2</rt>
-      </rtc>
-      <rbc dir="ltr">
-        <rb>base3</rb><rb>base4</rb>
-      </rbc>
-      <rt>text3</rt><rt>text4</rt>
-    </ruby>
-    <ruby dir="ltr">
-      <rb>base5</rb><rb>base6</rb>
-      <rt>text5</rt><rt>text6</rt>
-      <rbc dir="rtl">
-        <rb>base7</rb><rb>base8</rb>
-      </rbc>
-      <rt>text7</rt><rt>text8</rt>
-    </ruby>
-  </p>
-</body>
-</html>
--- a/layout/reftests/css-ruby/common.css
+++ b/layout/reftests/css-ruby/common.css
@@ -1,15 +1,14 @@
 @font-face {
   font-family: Ahem;
   src: url(../fonts/Ahem.ttf);
 }
 rbc {
   display: ruby-base-container;
-  unicode-bidi: -moz-isolate;
 }
 [pseudo] {
   font-size: inherit;
   line-height: inherit;
 }
 [pseudo] > rt {
   font-size: 50%;
 }
--- a/layout/reftests/css-ruby/reftest.list
+++ b/layout/reftests/css-ruby/reftest.list
@@ -1,12 +1,11 @@
 default-preferences pref(layout.css.ruby.enabled,true)
 
 == bidi-1.html bidi-1-ref.html
-== bidi-2.html bidi-2-ref.html
 == box-generation-1.html box-generation-1-ref.html
 == box-generation-2.html box-generation-2-ref.html
 == box-generation-3.html box-generation-3-ref.html
 == box-generation-4.html box-generation-4-ref.html
 == box-generation-5.html box-generation-5-ref.html
 == box-properties-1.html box-properties-1-ref.html
 == box-properties-2.html box-properties-2-ref.html
 == box-properties-3.html box-properties-3-ref.html
--- a/layout/reftests/w3c-css/submitted/ruby/support/rbc.css
+++ b/layout/reftests/w3c-css/submitted/ruby/support/rbc.css
@@ -1,4 +1,3 @@
 rbc {
   display: ruby-base-container;
-  unicode-bidi: isolate;
 }
--- a/layout/style/html.css
+++ b/layout/style/html.css
@@ -817,12 +817,12 @@ marquee[direction="up"], marquee[directi
     ruby-align: center;
   }
   rtc:lang(zh-TW), rt:lang(zh-TW) {
     font-size: 30%; /* bopomofo */
   }
   rtc > rt {
     font-size: inherit;
   }
-  ruby, rb, rt, rtc {
-    unicode-bidi: -moz-isolate;
+  ruby, rb, rt, rbc, rtc {
+    unicode-bidi: isolate;
   }
 }
--- a/layout/style/nsStyleContext.cpp
+++ b/layout/style/nsStyleContext.cpp
@@ -442,17 +442,16 @@ nsStyleContext::GetUniqueStyleData(const
 #define UNIQUE_CASE(c_)                                                       \
   case eStyleStruct_##c_:                                                     \
     result = new (presContext) nsStyle##c_(                                   \
       * static_cast<const nsStyle##c_ *>(current));                           \
     break;
 
   UNIQUE_CASE(Display)
   UNIQUE_CASE(Text)
-  UNIQUE_CASE(TextReset)
 
 #undef UNIQUE_CASE
 
   default:
     NS_ERROR("Struct type not supported.  Please find another way to do this if you can!");
     return nullptr;
   }
 
@@ -702,34 +701,16 @@ nsStyleContext::ApplyStyleFixups(bool aS
   }
 
   // Suppress border/padding of ruby level containers
   if (disp->mDisplay == NS_STYLE_DISPLAY_RUBY_BASE_CONTAINER ||
       disp->mDisplay == NS_STYLE_DISPLAY_RUBY_TEXT_CONTAINER) {
     CreateEmptyStyleData(eStyleStruct_Border);
     CreateEmptyStyleData(eStyleStruct_Padding);
   }
-  if (disp->IsRubyDisplayType()) {
-    // Per CSS Ruby spec section Bidi Reordering, for all ruby boxes,
-    // the 'normal' and 'embed' values of 'unicode-bidi' should compute to
-    // 'isolate', and 'bidi-override' should compute to 'isolate-override'.
-    const nsStyleTextReset* textReset = StyleTextReset();
-    uint8_t unicodeBidi = textReset->mUnicodeBidi;
-    if (unicodeBidi == NS_STYLE_UNICODE_BIDI_NORMAL ||
-        unicodeBidi == NS_STYLE_UNICODE_BIDI_EMBED) {
-      unicodeBidi = NS_STYLE_UNICODE_BIDI_ISOLATE;
-    } else if (unicodeBidi == NS_STYLE_UNICODE_BIDI_OVERRIDE) {
-      unicodeBidi = NS_STYLE_UNICODE_BIDI_ISOLATE_OVERRIDE;
-    }
-    if (unicodeBidi != textReset->mUnicodeBidi) {
-      auto mutableTextReset = static_cast<nsStyleTextReset*>(
-        GetUniqueStyleData(eStyleStruct_TextReset));
-      mutableTextReset->mUnicodeBidi = unicodeBidi;
-    }
-  }
 
   // Elements with display:inline whose writing-mode is orthogonal to their
   // parent's mode will be converted to display:inline-block.
   if (disp->mDisplay == NS_STYLE_DISPLAY_INLINE && mParent) {
     // We don't need the full mozilla::WritingMode value (incorporating dir and
     // text-orientation) here, all we care about is vertical vs horizontal.
     bool thisHorizontal =
       StyleVisibility()->mWritingMode == NS_STYLE_WRITING_MODE_HORIZONTAL_TB;
--- a/layout/style/ua.css
+++ b/layout/style/ua.css
@@ -71,33 +71,28 @@
   display: table-cell !important;
   white-space: inherit;
 }
 
 /* Ruby */
 @supports (display:ruby) {
   *|*::-moz-ruby {
     display: ruby;
-    unicode-bidi: -moz-isolate;
   }
   *|*::-moz-ruby-base {
     display: ruby-base;
-    unicode-bidi: -moz-isolate;
   }
   *|*::-moz-ruby-text {
     display: ruby-text;
-    unicode-bidi: -moz-isolate;
   }
   *|*::-moz-ruby-base-container {
     display: ruby-base-container;
-    unicode-bidi: -moz-isolate;
   }
   *|*::-moz-ruby-text-container {
     display: ruby-text-container;
-    unicode-bidi: -moz-isolate;
   }
 }
 
 /* Lists */
 
 *|*::-moz-list-bullet, *|*::-moz-list-number {
   display: inline;
   vertical-align: baseline;