Merge mozilla-inbound to mozilla-central. a=merge
authorDaniel Varga <dvarga@mozilla.com>
Mon, 31 Dec 2018 23:24:52 +0200
changeset 509315 595b7807fb110bbb87717938a2f85bd083b608f3
parent 509304 d96e39ed615b40b9b1ccb661f72b29c81b34fe34 (current diff)
parent 509314 4688c503e2eeec9de9b3e3055f9a56220c032f42 (diff)
child 509326 2f42b03f9e8fc93439c11c6d65a066325b1c3796
child 509334 c19c61fee4ec323972ab846c915d6f86774980e5
push id10547
push userffxbld-merge
push dateMon, 21 Jan 2019 13:03:58 +0000
treeherdermozilla-beta@24ec1916bffe [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone66.0a1
first release with
nightly linux32
595b7807fb11 / 66.0a1 / 20181231212755 / files
nightly linux64
595b7807fb11 / 66.0a1 / 20181231212755 / files
nightly mac
595b7807fb11 / 66.0a1 / 20181231212755 / files
nightly win32
595b7807fb11 / 66.0a1 / 20181231212755 / files
nightly win64
595b7807fb11 / 66.0a1 / 20181231212755 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge mozilla-inbound to mozilla-central. a=merge
dom/svg/nsSVGFeatures.cpp
dom/svg/nsSVGFeatures.h
--- a/dom/base/nsDOMMutationObserver.cpp
+++ b/dom/base/nsDOMMutationObserver.cpp
@@ -51,17 +51,20 @@ nsINodeList* nsDOMMutationRecord::Remove
 }
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsDOMMutationRecord)
   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
   NS_INTERFACE_MAP_ENTRY(nsISupports)
 NS_INTERFACE_MAP_END
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsDOMMutationRecord)
-NS_IMPL_CYCLE_COLLECTING_RELEASE(nsDOMMutationRecord)
+// Break down the linked list so that cycle collector can delete the
+// objects sooner.
+NS_IMPL_CYCLE_COLLECTING_RELEASE_WITH_LAST_RELEASE(nsDOMMutationRecord,
+                                                   mNext = nullptr)
 
 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(nsDOMMutationRecord, mTarget,
                                       mPreviousSibling, mNextSibling,
                                       mAddedNodes, mRemovedNodes,
                                       mAddedAnimations, mRemovedAnimations,
                                       mChangedAnimations, mNext, mOwner)
 
 // Observer
--- a/dom/svg/SVGTests.cpp
+++ b/dom/svg/SVGTests.cpp
@@ -3,17 +3,16 @@
 /* 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 "mozilla/dom/SVGTests.h"
 #include "DOMSVGStringList.h"
 #include "nsIContent.h"
 #include "nsIContentInlines.h"
-#include "nsSVGFeatures.h"
 #include "mozilla/dom/SVGSwitchElement.h"
 #include "nsCharSeparatedTokenizer.h"
 #include "nsStyleUtil.h"
 #include "mozilla/Preferences.h"
 
 namespace mozilla {
 namespace dom {
 
@@ -37,19 +36,27 @@ already_AddRefed<DOMSVGStringList> SVGTe
                                          AsSVGElement(), true, EXTENSIONS);
 }
 
 already_AddRefed<DOMSVGStringList> SVGTests::SystemLanguage() {
   return DOMSVGStringList::GetDOMWrapper(&mStringListAttributes[LANGUAGE],
                                          AsSVGElement(), true, LANGUAGE);
 }
 
-bool SVGTests::HasExtension(const nsAString& aExtension) {
-  return nsSVGFeatures::HasExtension(aExtension,
-                                     AsSVGElement()->IsInChromeDocument());
+bool SVGTests::HasExtension(const nsAString& aExtension) const {
+#define SVG_SUPPORTED_EXTENSION(str) \
+  if (aExtension.EqualsLiteral(str)) return true;
+  SVG_SUPPORTED_EXTENSION("http://www.w3.org/1999/xhtml")
+  nsNameSpaceManager* nameSpaceManager = nsNameSpaceManager::GetInstance();
+  if (AsSVGElement()->IsInChromeDocument() || !nameSpaceManager->mMathMLDisabled) {
+    SVG_SUPPORTED_EXTENSION("http://www.w3.org/1998/Math/MathML")
+  }
+#undef SVG_SUPPORTED_EXTENSION
+
+  return false;
 }
 
 bool SVGTests::IsConditionalProcessingAttribute(
     const nsAtom* aAttribute) const {
   for (uint32_t i = 0; i < ArrayLength(sStringListNames); i++) {
     if (aAttribute == sStringListNames[i]) {
       return true;
     }
@@ -104,18 +111,17 @@ bool SVGTests::PassesConditionalProcessi
   // go beyond the feature set defined in the SVG specification.
   // Each extension is identified by a URI reference.
   // For now, claim that mozilla's SVG implementation supports XHTML and MathML.
   if (mStringListAttributes[EXTENSIONS].IsExplicitlySet()) {
     if (mStringListAttributes[EXTENSIONS].IsEmpty()) {
       return false;
     }
     for (uint32_t i = 0; i < mStringListAttributes[EXTENSIONS].Length(); i++) {
-      if (!nsSVGFeatures::HasExtension(mStringListAttributes[EXTENSIONS][i],
-                                       AsSVGElement()->IsInChromeDocument())) {
+      if (!HasExtension(mStringListAttributes[EXTENSIONS][i])) {
         return false;
       }
     }
   }
 
   if (aAcceptLangs == kIgnoreSystemLanguage) {
     return true;
   }
--- a/dom/svg/SVGTests.h
+++ b/dom/svg/SVGTests.h
@@ -91,17 +91,17 @@ class SVGTests : public nsISupports {
   void GetAttrValue(uint8_t aAttrEnum, nsAttrValue& aValue) const;
 
   void MaybeInvalidate();
 
   // WebIDL
   already_AddRefed<DOMSVGStringList> RequiredFeatures();
   already_AddRefed<DOMSVGStringList> RequiredExtensions();
   already_AddRefed<DOMSVGStringList> SystemLanguage();
-  bool HasExtension(const nsAString& aExtension);
+  bool HasExtension(const nsAString& aExtension) const;
 
   virtual SVGElement* AsSVGElement() = 0;
 
   const SVGElement* AsSVGElement() const {
     return const_cast<SVGTests*>(this)->AsSVGElement();
   }
 
  protected:
--- a/dom/svg/moz.build
+++ b/dom/svg/moz.build
@@ -6,17 +6,16 @@
 
 with Files("**"):
     BUG_COMPONENT = ("Core", "SVG")
 
 MOCHITEST_MANIFESTS += ['test/mochitest.ini']
 
 EXPORTS += [
     'nsSVGClass.h',
-    'nsSVGFeatures.h',
 ]
 
 EXPORTS.mozilla += [
     'SVGAttrValueWrapper.h',
     'SVGContentUtils.h',
     'SVGPreserveAspectRatio.h',
     'SVGStringList.h',
     'SVGTagList.h',
@@ -126,17 +125,16 @@ UNIFIED_SOURCES += [
     'DOMSVGStringList.cpp',
     'DOMSVGTransform.cpp',
     'DOMSVGTransformList.cpp',
     'nsISVGPoint.cpp',
     'nsSVGAngle.cpp',
     'nsSVGBoolean.cpp',
     'nsSVGClass.cpp',
     'nsSVGEnum.cpp',
-    'nsSVGFeatures.cpp',
     'nsSVGInteger.cpp',
     'nsSVGIntegerPair.cpp',
     'nsSVGLength2.cpp',
     'nsSVGNumber2.cpp',
     'nsSVGNumberPair.cpp',
     'nsSVGString.cpp',
     'nsSVGViewBox.cpp',
     'SVGAElement.cpp',
deleted file mode 100644
--- a/dom/svg/nsSVGFeatures.cpp
+++ /dev/null
@@ -1,35 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; 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/. */
-
-/**
- * This file contains code to help implement the Conditional Processing
- * section of the SVG specification (i.e. the <switch> element and the
- * requiredFeatures, requiredExtensions and systemLanguage attributes).
- *
- *   http://www.w3.org/TR/SVG11/struct.html#ConditionalProcessing
- */
-
-#include "nsSVGFeatures.h"
-#include "nsIContent.h"
-#include "nsIDocument.h"
-#include "nsNameSpaceManager.h"
-#include "mozilla/Preferences.h"
-
-using namespace mozilla;
-
-/*static*/ bool nsSVGFeatures::HasExtension(const nsAString& aExtension,
-                                            const bool aIsInChrome) {
-#define SVG_SUPPORTED_EXTENSION(str) \
-  if (aExtension.EqualsLiteral(str)) return true;
-  SVG_SUPPORTED_EXTENSION("http://www.w3.org/1999/xhtml")
-  nsNameSpaceManager* nameSpaceManager = nsNameSpaceManager::GetInstance();
-  if (aIsInChrome || !nameSpaceManager->mMathMLDisabled) {
-    SVG_SUPPORTED_EXTENSION("http://www.w3.org/1998/Math/MathML")
-  }
-#undef SVG_SUPPORTED_EXTENSION
-
-  return false;
-}
deleted file mode 100644
--- a/dom/svg/nsSVGFeatures.h
+++ /dev/null
@@ -1,23 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; 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/. */
-
-#ifndef __NS_SVGFEATURES_H__
-#define __NS_SVGFEATURES_H__
-
-#include "nsString.h"
-
-class nsSVGFeatures {
- public:
-  /**
-   * Check whether we support the given extension string.
-   *
-   * @param aExtension the URI of an extension. Known extensions are
-   *   "http://www.w3.org/1999/xhtml" and "http://www.w3.org/1998/Math/MathML"
-   */
-  static bool HasExtension(const nsAString& aExtension, const bool aIsInChrome);
-};
-
-#endif  // __NS_SVGFEATURES_H__
--- a/js/src/jit-test/tests/ctypes/conversion-finalizer.js
+++ b/js/src/jit-test/tests/ctypes/conversion-finalizer.js
@@ -1,8 +1,10 @@
+// |jit-test| skip-if: !getBuildConfiguration()['x86'] && !getBuildConfiguration()['x64']
+// Skip on non x86/x64 until Bug 1511615 is fixed for arm7/arm64.
 load(libdir + 'asserts.js');
 
 function test() {
   // non object
   assertTypeErrorMessage(() => { ctypes.CDataFinalizer(0, "foo"); },
                          "expected _a CData object_ of a function pointer type, got the string \"foo\"");
   // non CData object
   assertTypeErrorMessage(() => { ctypes.CDataFinalizer(0, ["foo"]); },
--- a/js/src/jit-test/tests/wasm/atomic.js
+++ b/js/src/jit-test/tests/wasm/atomic.js
@@ -1,9 +1,10 @@
-// |jit-test| skip-if: !wasmThreadsSupported()
+// |jit-test| skip-if: !wasmThreadsSupported() || getBuildConfiguration()['arm64']
+// skip arm64 due to bug 1513231
 
 const oob = /index out of bounds/;
 const unaligned = /unaligned memory access/;
 const RuntimeError = WebAssembly.RuntimeError;
 
 // Check that the output of wasmTextToBinary verifies correctly.
 
 let SHARED = 'shared';
--- a/js/src/jit-test/tests/wasm/baseline-abs-addr-opt.js
+++ b/js/src/jit-test/tests/wasm/baseline-abs-addr-opt.js
@@ -1,8 +1,10 @@
+// |jit-test| skip-if: getBuildConfiguration()['arm64']
+// skip arm64 due to bug 1513231
 // Test bounds checking at the end of memory with a constant base pointer.
 // This is intended to verify a bounds check elimination optimization in
 // the baseline compiler.
 
 // This can be only a functional test, we can't really see whether
 // the optimization is being applied.  However, manual inspection
 // of the generated code has verified that the optimization is
 // being applied.
--- a/js/src/jit-test/tests/wasm/bce.js
+++ b/js/src/jit-test/tests/wasm/bce.js
@@ -1,8 +1,10 @@
+// |jit-test| skip-if: getBuildConfiguration()['arm64']
+// skip arm64 due to bug 1513231
 mem='\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f'+
     '\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff'+
     '\x00'.repeat(65488) +
     '\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff'
 
 let accessWidth = {
   '8_s':  1,
   '8_u':  1,
--- a/js/src/jit-test/tests/wasm/memory.js
+++ b/js/src/jit-test/tests/wasm/memory.js
@@ -1,8 +1,10 @@
+// |jit-test| skip-if: getBuildConfiguration()['arm64']
+// skip arm64 due to bug 1513231
 const RuntimeError = WebAssembly.RuntimeError;
 
 function loadModuleSrc(type, ext, offset, align, drop = false) {
     let maybeResult = drop ? '' : `(result ${type})`;
     let maybeDrop = drop ? 'drop' : '';
     return `(module
        (memory 1)
        (data (i32.const 0) "\\00\\01\\02\\03\\04\\05\\06\\07\\08\\09\\0a\\0b\\0c\\0d\\0e\\0f")
--- a/js/src/jit-test/tests/wasm/spec/float_memory.wast.js
+++ b/js/src/jit-test/tests/wasm/spec/float_memory.wast.js
@@ -1,8 +1,10 @@
+// |jit-test| skip-if: !getBuildConfiguration()['x86'] && !getBuildConfiguration()['x64'] && !getBuildConfiguration()['arm64']
+// skip arm7 due to bug 1513231
 
 // float_memory.wast:5
 let $1 = instance("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x8c\x80\x80\x80\x00\x03\x60\x00\x01\x7d\x60\x00\x01\x7f\x60\x00\x00\x03\x86\x80\x80\x80\x00\x05\x00\x01\x02\x02\x02\x05\x84\x80\x80\x80\x00\x01\x01\x01\x01\x07\xb7\x80\x80\x80\x00\x05\x08\x66\x33\x32\x2e\x6c\x6f\x61\x64\x00\x00\x08\x69\x33\x32\x2e\x6c\x6f\x61\x64\x00\x01\x09\x66\x33\x32\x2e\x73\x74\x6f\x72\x65\x00\x02\x09\x69\x33\x32\x2e\x73\x74\x6f\x72\x65\x00\x03\x05\x72\x65\x73\x65\x74\x00\x04\x0a\xca\x80\x80\x80\x00\x05\x87\x80\x80\x80\x00\x00\x41\x00\x2a\x02\x00\x0b\x87\x80\x80\x80\x00\x00\x41\x00\x28\x02\x00\x0b\x8c\x80\x80\x80\x00\x00\x41\x00\x43\x00\x00\xa0\x7f\x38\x02\x00\x0b\x8d\x80\x80\x80\x00\x00\x41\x00\x41\x80\x80\x80\xfd\x07\x36\x02\x00\x0b\x89\x80\x80\x80\x00\x00\x41\x00\x41\x00\x36\x02\x00\x0b\x0b\x8a\x80\x80\x80\x00\x01\x00\x41\x00\x0b\x04\x00\x00\xa0\x7f");
 
 // float_memory.wast:15
 assert_return(() => call($1, "i32.load", []), 2141192192);
 
 // float_memory.wast:16
--- a/js/src/jit-test/tests/wasm/spec/memory_redundancy.wast.js
+++ b/js/src/jit-test/tests/wasm/spec/memory_redundancy.wast.js
@@ -1,8 +1,10 @@
+// |jit-test| skip-if: !getBuildConfiguration()['x86'] && !getBuildConfiguration()['x64'] && !getBuildConfiguration()['arm64']
+// skip arm7 due to bug 1513231
 
 // memory_redundancy.wast:5
 let $1 = instance("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x8c\x80\x80\x80\x00\x03\x60\x00\x00\x60\x00\x01\x7f\x60\x00\x01\x7d\x03\x85\x80\x80\x80\x00\x04\x00\x01\x01\x02\x05\x84\x80\x80\x80\x00\x01\x01\x01\x01\x07\xd0\x80\x80\x80\x00\x04\x0f\x7a\x65\x72\x6f\x5f\x65\x76\x65\x72\x79\x74\x68\x69\x6e\x67\x00\x00\x12\x74\x65\x73\x74\x5f\x73\x74\x6f\x72\x65\x5f\x74\x6f\x5f\x6c\x6f\x61\x64\x00\x01\x13\x74\x65\x73\x74\x5f\x72\x65\x64\x75\x6e\x64\x61\x6e\x74\x5f\x6c\x6f\x61\x64\x00\x02\x0f\x74\x65\x73\x74\x5f\x64\x65\x61\x64\x5f\x73\x74\x6f\x72\x65\x00\x03\x0a\x8c\x81\x80\x80\x00\x04\x9e\x80\x80\x80\x00\x00\x41\x00\x41\x00\x36\x02\x00\x41\x04\x41\x00\x36\x02\x00\x41\x08\x41\x00\x36\x02\x00\x41\x0c\x41\x00\x36\x02\x00\x0b\x98\x80\x80\x80\x00\x00\x41\x08\x41\x00\x36\x02\x00\x41\x05\x43\x00\x00\x00\x80\x38\x02\x00\x41\x08\x28\x02\x00\x0b\xa2\x80\x80\x80\x00\x01\x02\x7f\x41\x08\x28\x02\x00\x21\x00\x41\x05\x41\x80\x80\x80\x80\x78\x36\x02\x00\x41\x08\x28\x02\x00\x21\x01\x20\x00\x20\x01\x6a\x0b\x9f\x80\x80\x80\x00\x01\x01\x7d\x41\x08\x41\xa3\xc6\x8c\x99\x02\x36\x02\x00\x41\x0b\x2a\x02\x00\x21\x00\x41\x08\x41\x00\x36\x02\x00\x20\x00\x0b");
 
 // memory_redundancy.wast:39
 assert_return(() => call($1, "test_store_to_load", []), 128);
 
 // memory_redundancy.wast:40
--- a/js/src/tests/lib/jittests.py
+++ b/js/src/tests/lib/jittests.py
@@ -507,16 +507,21 @@ def check_output(out, err, rc, timed_out
             return True
 
         # When building with ASan enabled, ASan will convert the -11 returned
         # value to 1. As a work-around we look for the error output which
         # includes the crash reason.
         if rc == 1 and ("Hit MOZ_CRASH" in err or "Assertion failure:" in err):
             return True
 
+        # When running jittests on Android, SEGV results in a return code
+        # of 128+11=139.
+        if rc == 139:
+            return True
+
     if rc != test.expect_status:
         # Tests which expect a timeout check for exit code 6.
         # Sometimes 0 is returned on Windows for unknown reasons.
         # See bug 899697.
         if sys.platform in ['win32', 'cygwin'] and rc == 0:
             return True
 
         # Allow a non-zero exit code if we want to allow OOM, but only if we
--- a/layout/generic/nsTextFrame.cpp
+++ b/layout/generic/nsTextFrame.cpp
@@ -1823,38 +1823,120 @@ bool BuildTextRunsScanner::ContinueTextR
     FrameBidiData data2 = aFrame2->GetBidiData();
     if (data1.embeddingLevel != data2.embeddingLevel ||
         data2.precedingControl != kBidiLevelNone) {
       return false;
     }
   }
 
   ComputedStyle* sc1 = aFrame1->Style();
+  ComputedStyle* sc2 = aFrame2->Style();
+
+  // Any difference in writing-mode/directionality inhibits shaping across
+  // the boundary.
+  WritingMode wm(sc1);
+  if (wm != WritingMode(sc2)) {
+    return false;
+  }
+
   const nsStyleText* textStyle1 = sc1->StyleText();
   // If the first frame ends in a preformatted newline, then we end the textrun
   // here. This avoids creating giant textruns for an entire plain text file.
   // Note that we create a single text frame for a preformatted text node,
   // even if it has newlines in it, so typically we won't see trailing newlines
   // until after reflow has broken up the frame into one (or more) frames per
   // line. That's OK though.
-  if (textStyle1->NewlineIsSignificant(aFrame1) && HasTerminalNewline(aFrame1))
+  if (textStyle1->NewlineIsSignificant(aFrame1) &&
+      HasTerminalNewline(aFrame1)) {
     return false;
+  }
+
+  if (aFrame1->GetParent()->GetContent() !=
+      aFrame2->GetParent()->GetContent()) {
+    // Does aFrame, or any ancestor between it and aAncestor, have a property
+    // that should inhibit cross-element-boundary shaping on aSide?
+    auto PreventCrossBoundaryShaping = [](const nsIFrame* aFrame,
+                                          const nsIFrame* aAncestor,
+                                          Side aSide) {
+      while (aFrame != aAncestor) {
+        ComputedStyle* ctx = aFrame->Style();
+        // According to https://drafts.csswg.org/css-text/#boundary-shaping:
+        //
+        // Text shaping must be broken at inline box boundaries when any of the
+        // following are true for any box whose boundary separates the two
+        // typographic character units:
+        //
+        // 1. Any of margin/border/padding separating the two typographic
+        //    character units in the inline axis is non-zero.
+        const nsStyleCoord& margin = ctx->StyleMargin()->mMargin.Get(aSide);
+        if (!margin.ConvertsToLength() || margin.ToLength() != 0) {
+          return true;
+        }
+        const nsStyleCoord& padding = ctx->StylePadding()->mPadding.Get(aSide);
+        if (!padding.ConvertsToLength() || padding.ToLength() != 0) {
+          return true;
+        }
+        if (ctx->StyleBorder()->GetComputedBorderWidth(aSide) != 0) {
+          return true;
+        }
+
+        // 2. vertical-align is not baseline.
+        const nsStyleCoord& coord = ctx->StyleDisplay()->mVerticalAlign;
+        if (coord.GetUnit() != eStyleUnit_Enumerated ||
+            coord.GetIntValue() != NS_STYLE_VERTICAL_ALIGN_BASELINE) {
+          return true;
+        }
+
+        // 3. The boundary is a bidi isolation boundary.
+        const uint8_t unicodeBidi = ctx->StyleTextReset()->mUnicodeBidi;
+        if (unicodeBidi == NS_STYLE_UNICODE_BIDI_ISOLATE ||
+            unicodeBidi == NS_STYLE_UNICODE_BIDI_ISOLATE_OVERRIDE) {
+          return true;
+        }
+
+        aFrame = aFrame->GetParent();
+      }
+      return false;
+    };
+
+    const nsIFrame* ancestor =
+      nsLayoutUtils::FindNearestCommonAncestorFrame(aFrame1, aFrame2);
+    MOZ_ASSERT(ancestor);
+
+    // Map inline-end and inline-start to physical sides for checking presence
+    // of non-zero margin/border/padding.
+    Side side1 = wm.PhysicalSide(eLogicalSideIEnd);
+    Side side2 = wm.PhysicalSide(eLogicalSideIStart);
+    // If the frames have an embedding level that is opposite to the writing
+    // mode, we need to swap which sides we're checking.
+    if (IS_LEVEL_RTL(aFrame1->GetEmbeddingLevel()) == wm.IsBidiLTR()) {
+      Swap(side1, side2);
+    }
+
+    if (PreventCrossBoundaryShaping(aFrame1, ancestor, side1) ||
+        PreventCrossBoundaryShaping(aFrame2, ancestor, side2)) {
+      return false;
+    }
+  }
 
   if (aFrame1->GetContent() == aFrame2->GetContent() &&
       aFrame1->GetNextInFlow() != aFrame2) {
     // aFrame2 must be a non-fluid continuation of aFrame1. This can happen
     // sometimes when the unicode-bidi property is used; the bidi resolver
     // breaks text into different frames even though the text has the same
     // direction. We can't allow these two frames to share the same textrun
     // because that would violate our invariant that two flows in the same
     // textrun have different content elements.
     return false;
   }
 
-  ComputedStyle* sc2 = aFrame2->Style();
+  if (sc1 == sc2) {
+    return true;
+  }
+
   const nsStyleText* textStyle2 = sc2->StyleText();
   if (sc1 == sc2) return true;
 
   nsPresContext* pc = aFrame1->PresContext();
   MOZ_ASSERT(pc == aFrame2->PresContext());
 
   const nsStyleFont* fontStyle1 = sc1->StyleFont();
   const nsStyleFont* fontStyle2 = sc2->StyleFont();
--- a/layout/reftests/css-ruby/intrinsic-isize-1-ref.html
+++ b/layout/reftests/css-ruby/intrinsic-isize-1-ref.html
@@ -2,16 +2,18 @@
 <html lang="ja">
 <head>
   <meta charset="UTF-8">
   <title>Bug 1134432 - Intrinsic ISize calculation of ruby</title>
   <style>
     div {
       display: inline-block;
       border: 1px solid black;
+      font-kerning: none; /* disable kerning, because in the reference file
+                             it might occur across <span> boundaries */
     }
     span {
       white-space: nowrap;
     }
   </style>
 </head>
 <body>
   <div style="width: min-content">
--- a/layout/reftests/css-ruby/intrinsic-isize-1.html
+++ b/layout/reftests/css-ruby/intrinsic-isize-1.html
@@ -2,16 +2,18 @@
 <html lang="ja">
 <head>
   <meta charset="UTF-8">
   <title>Bug 1134432 - Intrinsic ISize calculation of ruby</title>
   <style>
     div {
       display: inline-block;
       border: 1px solid black;
+      font-kerning: none; /* disable kerning, because in the reference file
+                             it might occur across <span> boundaries */
     }
   </style>
 </head>
 <body>
   <div style="width: min-content">
     <ruby><rb>ABC<rb>DEF</ruby>
   </div>
   <div style="width: max-content">
--- a/testing/mozbase/mozdevice/mozdevice/adb.py
+++ b/testing/mozbase/mozdevice/mozdevice/adb.py
@@ -852,16 +852,17 @@ class ADBDevice(ADBCommand):
 
         return " ".join(quoted_cmd)
 
     @staticmethod
     def _get_exitcode(file_obj):
         """Get the exitcode from the last line of the file_obj for shell
         commands.
         """
+        re_returncode = re.compile(r'adb_returncode=([0-9]+)')
         file_obj.seek(0, os.SEEK_END)
 
         line = ''
         length = file_obj.tell()
         offset = 1
         while length - offset >= 0:
             file_obj.seek(-offset, os.SEEK_END)
             char = file_obj.read(1)
@@ -869,23 +870,38 @@ class ADBDevice(ADBCommand):
                 break
             if char != '\r' and char != '\n':
                 line = char + line
             elif line:
                 # we have collected everything up to the beginning of the line
                 break
             offset += 1
 
-        match = re.match(r'rc=([0-9]+)', line)
+        match = re_returncode.match(line)
         if match:
             exitcode = int(match.group(1))
+            # Set the position in the file to the position of the
+            # adb_returncode and truncate it from the output.
             file_obj.seek(-1, os.SEEK_CUR)
             file_obj.truncate()
         else:
             exitcode = None
+            # We may have a situation where the adb_returncode= is not
+            # at the end of the output. This happens at least in the
+            # failure jit-tests on arm. To work around this
+            # possibility, we can search the entire output for the
+            # appropriate match.
+            file_obj.seek(0, os.SEEK_SET)
+            for line in file_obj:
+                match = re_returncode.search(line)
+                if match:
+                    exitcode = int(match.group(1))
+                    break
+            # Reset the position in the file to the end.
+            file_obj.seek(0, os.SEEK_END)
 
         return exitcode
 
     def is_path_internal_storage(self, path, timeout=None):
         """
         Return True if the path matches an internal storage path
         as defined by either '/sdcard', '/mnt/sdcard', or any of the
         .*_STORAGE environment variables on the device otherwise False.
@@ -1303,17 +1319,17 @@ class ADBDevice(ADBCommand):
 
         # prepend cwd and env to command if necessary
         if cwd:
             cmd = "cd %s && %s" % (cwd, cmd)
         if env:
             envstr = '&& '.join(map(lambda x: 'export %s=%s' %
                                     (x[0], x[1]), env.iteritems()))
             cmd = envstr + "&& " + cmd
-        cmd += "; echo rc=$?"
+        cmd += "; echo adb_returncode=$?"
 
         args = [self._adb_path]
         if self._adb_host:
             args.extend(['-H', self._adb_host])
         if self._adb_port:
             args.extend(['-P', str(self._adb_port)])
         if self._device_serial:
             args.extend(['-s', self._device_serial])
--- a/testing/raptor/raptor/raptor.py
+++ b/testing/raptor/raptor/raptor.py
@@ -2,20 +2,24 @@
 
 # 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/.
 from __future__ import absolute_import
 
 import json
 import os
+import posixpath
+import shutil
 import subprocess
 import sys
+import tempfile
 import time
 
+import mozcrash
 import mozinfo
 
 from mozdevice import ADBDevice
 from mozlog import commandline, get_default_logger
 from mozprofile import create_profile
 from mozrunner import runners
 
 # need this so raptor imports work both from /raptor and via mach
@@ -126,17 +130,18 @@ class Raptor(object):
             # create the desktop browser runner
             self.log.info("creating browser runner using mozrunner")
             self.output_handler = OutputHandler()
             process_args = {
                 'processOutputLine': [self.output_handler],
             }
             runner_cls = runners[app]
             self.runner = runner_cls(
-                binary, profile=self.profile, process_args=process_args)
+                binary, profile=self.profile, process_args=process_args,
+                symbols_path=self.config['symbols_path'])
 
         self.log.info("raptor config: %s" % str(self.config))
 
     @property
     def profile_data_dir(self):
         if 'MOZ_DEVELOPER_REPO_DIR' in os.environ:
             return os.path.join(os.environ['MOZ_DEVELOPER_REPO_DIR'], 'testing', 'profiles')
         if build:
@@ -381,24 +386,19 @@ class Raptor(object):
                 if not self.debug_mode:
                     elapsed_time += 1
                     if elapsed_time > (timeout) - 5:  # stop 5 seconds early
                         self.log.info("application timed out after {} seconds".format(timeout))
                         self.control_server.wait_for_quit()
                         break
         finally:
             if self.config['app'] == "geckoview":
-                # TODO: if on geckoview is there some cleanup here i.e. check for crashes?
                 if self.config['power_test']:
                     finish_geckoview_power_test(self)
-            else:
-                try:
-                    self.runner.check_for_crashes()
-                except NotImplementedError:  # not implemented for Chrome
-                    pass
+            self.check_for_crashes()
 
         if self.playback is not None:
             self.playback.stop()
 
         # remove the raptor webext; as it must be reloaded with each subtest anyway
         self.log.info("removing webext %s" % raptor_webext)
         if self.config['app'] in ["firefox", "geckoview"]:
             self.profile.addons.remove_addon(webext_id)
@@ -450,16 +450,41 @@ class Raptor(object):
             raptor_json_path = os.path.join(os.getcwd(), 'local.json')
 
         self.config['raptor_json_path'] = raptor_json_path
         return self.results_handler.summarize_and_output(self.config)
 
     def get_page_timeout_list(self):
         return self.results_handler.page_timeout_list
 
+    def check_for_crashes(self):
+        if self.config['app'] == "geckoview":
+            logcat = self.device.get_logcat()
+            if logcat:
+                if mozcrash.check_for_java_exception(logcat, "raptor"):
+                    return
+            try:
+                dump_dir = tempfile.mkdtemp()
+                remote_dir = posixpath.join(self.device_profile, 'minidumps')
+                if not self.device.is_dir(remote_dir):
+                    self.log.error("No crash directory (%s) found on remote device" % remote_dir)
+                    return
+                self.device.pull(remote_dir, dump_dir)
+                mozcrash.log_crashes(self.log, dump_dir, self.config['symbols_path'])
+            finally:
+                try:
+                    shutil.rmtree(dump_dir)
+                except Exception:
+                    self.log.warning("unable to remove directory: %s" % dump_dir)
+        else:
+            try:
+                self.runner.check_for_crashes()
+            except NotImplementedError:  # not implemented for Chrome
+                pass
+
     def clean_up(self):
         self.control_server.stop()
         if self.config['app'] != "geckoview":
             self.runner.stop()
         elif self.config['app'] == 'geckoview':
             self.log.info('removing reverse socket connections')
             self.device.remove_socket_connections('reverse')
         else:
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/css/css-text/boundary-shaping/boundary-shaping-004.html.ini
@@ -0,0 +1,3 @@
+[boundary-shaping-004.html]
+  expected:
+    if webrender and (os == "win"): FAIL
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/css/css-text/boundary-shaping/boundary-shaping-005.html.ini
@@ -0,0 +1,3 @@
+[boundary-shaping-005.html]
+  expected:
+    if webrender and (os == "win"): FAIL
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/css/css-text/boundary-shaping/boundary-shaping-010.html.ini
@@ -0,0 +1,4 @@
+[boundary-shaping-010.html]
+  expected:
+    if (os == "mac"): FAIL
+    if (os == "android"): FAIL
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/css/css-text/boundary-shaping/boundary-shaping-001.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>Text shaping must not be broken across inline box boundaries when there is no change in formatting</title>
+<link rel=match href="reference/boundary-shaping-001.ref.html">
+<link rel=help href="https://drafts.csswg.org/css-text/#boundary-shaping">
+<style>
+@font-face {
+  font-family: test;
+  src: url(resources/LinLibertine_Re-4.7.5.woff);
+}
+body {
+  font: 36px test; /* use a font that includes ligatures for "fi" etc */
+}
+.a {
+  /* initial values for these properties should not interrupt shaping */
+  vertical-align: initial;
+  padding: initial;
+  margin: initial;
+  border: initial;
+}
+</style>
+</head>
+<body>
+of<span class=a>f</span>ice
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/css/css-text/boundary-shaping/boundary-shaping-002.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>Text shaping must be broken across inline box boundaries when 'vertical-align' is not 'baseline'</title>
+<link rel=match href="reference/boundary-shaping-002.ref.html">
+<link rel=help href="https://drafts.csswg.org/css-text/#boundary-shaping">
+<style>
+@font-face {
+  font-family: test;
+  src: url(resources/LinLibertine_Re-4.7.5.woff);
+}
+body {
+  font: 36px test; /* use a font that includes ligatures for "fi" etc */
+}
+.a {
+  vertical-align: 0; /* distinct from 'baseline', should break shaping */
+}
+</style>
+</head>
+<body>
+of<span class=a>f</span>ice
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/css/css-text/boundary-shaping/boundary-shaping-003.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>Text shaping must be broken across inline box boundaries when padding is non-zero</title>
+<link rel=match href="reference/boundary-shaping-003.ref.html">
+<link rel=help href="https://drafts.csswg.org/css-text/#boundary-shaping">
+<style>
+@font-face {
+  font-family: test;
+  src: url(resources/LinLibertine_Re-4.7.5.woff);
+}
+body {
+  font: 36px test; /* use a font that includes ligatures for "fi" etc */
+}
+.a {
+  padding-left: 10px;
+}
+</style>
+</head>
+<body>
+of<span class=a>f</span>ice
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/css/css-text/boundary-shaping/boundary-shaping-004.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>Text shaping must be broken across inline box boundaries when margin is non-zero</title>
+<link rel=match href="reference/boundary-shaping-004.ref.html">
+<link rel=help href="https://drafts.csswg.org/css-text/#boundary-shaping">
+<style>
+@font-face {
+  font-family: test;
+  src: url(resources/LinLibertine_Re-4.7.5.woff);
+}
+body {
+  font: 36px test; /* use a font that includes ligatures for "fi" etc */
+}
+.a {
+  margin-right: 10px;
+}
+</style>
+</head>
+<body>
+of<span class=a>f</span>ice
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/css/css-text/boundary-shaping/boundary-shaping-005.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>Text shaping must be broken across inline box boundaries when border is non-zero</title>
+<link rel=match href="reference/boundary-shaping-005.ref.html">
+<link rel=help href="https://drafts.csswg.org/css-text/#boundary-shaping">
+<style>
+@font-face {
+  font-family: test;
+  src: url(resources/LinLibertine_Re-4.7.5.woff);
+}
+body {
+  font: 36px test; /* use a font that includes ligatures for "fi" etc */
+}
+.a {
+  border-right: 10px solid transparent;
+}
+</style>
+</head>
+<body>
+of<span class=a>f</span>ice
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/css/css-text/boundary-shaping/boundary-shaping-006.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>Text shaping must be broken across inline box boundaries when 'vertical-align' is not 'baseline'</title>
+<link rel=match href="reference/boundary-shaping-006.ref.html">
+<link rel=help href="https://drafts.csswg.org/css-text/#boundary-shaping">
+<style>
+@font-face {
+  font-family: test;
+  src: url(resources/LinLibertine_Re-4.7.5.woff);
+}
+body {
+  font: 36px test; /* use a font that includes ligatures for "fi" etc */
+}
+.a {
+  vertical-align: super;
+}
+</style>
+</head>
+<body>
+of<span><span><span class=a><span><span>f</span></span></span></span></span>ice
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/css/css-text/boundary-shaping/boundary-shaping-007.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>Text shaping must be broken across inline box boundaries when padding or margin is non-zero</title>
+<link rel=match href="reference/boundary-shaping-007.ref.html">
+<link rel=help href="https://drafts.csswg.org/css-text/#boundary-shaping">
+<style>
+@font-face {
+  font-family: test;
+  src: url(resources/LinLibertine_Re-4.7.5.woff);
+}
+body {
+  font: 36px test; /* use a font that includes ligatures for "fi" etc */
+}
+.a {
+  padding-left: 10px;
+}
+.b {
+  margin-right: 10px;
+}
+</style>
+</head>
+<body>
+of<span><span class=a><span><span class=b><span>f</span></span></span></span></span>ice
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/css/css-text/boundary-shaping/boundary-shaping-008.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>Text shaping must be broken across inline box boundaries at a bidi isolation boundary</title>
+<link rel=match href="reference/boundary-shaping-008.ref.html">
+<link rel=help href="https://drafts.csswg.org/css-text/#boundary-shaping">
+<style>
+@font-face {
+  font-family: test;
+  src: url(resources/LinLibertine_Re-4.7.5.woff);
+}
+body {
+  font: 36px test; /* use a font that includes ligatures for "fi" etc */
+}
+.a {
+  unicode-bidi: isolate; /* bidi isolation boundaries should break shaping */
+}
+</style>
+</head>
+<body>
+of<span class=a>f</span>ice
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/css/css-text/boundary-shaping/boundary-shaping-009.html
@@ -0,0 +1,57 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>Text shaping must be broken across inline box boundaries when padding or margin is non-zero</title>
+<link rel=match href="reference/boundary-shaping-009.ref.html">
+<link rel=help href="https://drafts.csswg.org/css-text/#boundary-shaping">
+<style>
+body {
+  font: 36px sans-serif;
+}
+div {
+  text-align: center;
+}
+.a {
+  padding-right: 10px;
+}
+.b {
+  margin-left: 10px;
+}
+.c {
+  color: red;
+  padding-left: 10px;
+}
+.d {
+  color: red;
+  margin-right: 10px;
+}
+</style>
+</head>
+<body>
+<div dir=ltr>
+السلام<span class=a>عليكم</span>
+</div>
+<div dir=ltr>
+<span class=b>السلام</span>عليكم
+</div>
+<div dir=rtl>
+السلام<span class=a>عليكم</span>
+</div>
+<div dir=rtl>
+<span class=b>السلام</span>عليكم
+</div>
+<div dir=ltr>
+السلام<span class=c>عليكم</span>
+</div>
+<div dir=ltr>
+<span class=d>السلام</span>عليكم
+</div>
+<div dir=rtl>
+السلام<span class=c>عليكم</span>
+</div>
+<div dir=rtl>
+<span class=d>السلام</span>عليكم
+</div>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/css/css-text/boundary-shaping/boundary-shaping-010.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>Text shaping must not be broken across inline box boundaries when there is no change in formatting</title>
+<link rel=match href="reference/boundary-shaping-010.ref.html">
+<link rel=help href="https://drafts.csswg.org/css-text/#boundary-shaping">
+<style>
+body {
+  font: 36px sans-serif;
+}
+div {
+  text-align: center;
+}
+</style>
+</head>
+<body>
+<div dir=rtl>
+ال<span>سل</span>ام
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/css/css-text/boundary-shaping/reference/boundary-shaping-001.ref.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<style>
+@font-face {
+  font-family: test;
+  src: url(../resources/LinLibertine_Re-4.7.5.woff);
+}
+body {
+  font: 36px test; /* use a font that includes ligatures for "fi" etc */
+}
+</style>
+</head>
+<body>
+office
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/css/css-text/boundary-shaping/reference/boundary-shaping-002.ref.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<style>
+@font-face {
+  font-family: test;
+  src: url(../resources/LinLibertine_Re-4.7.5.woff);
+}
+body {
+  font: 36px test; /* use a font that includes ligatures for "fi" etc */
+}
+.a {
+  display: inline-block;
+}
+</style>
+</head>
+<body>
+of<span class=a>f</span>ice
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/css/css-text/boundary-shaping/reference/boundary-shaping-003.ref.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<style>
+@font-face {
+  font-family: test;
+  src: url(../resources/LinLibertine_Re-4.7.5.woff);
+}
+body {
+  font: 36px test; /* use a font that includes ligatures for "fi" etc */
+}
+.a {
+  display: inline-block;
+  width: 10px;
+}
+</style>
+</head>
+<body>
+of<span class=a>&nbsp;</span>fice
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/css/css-text/boundary-shaping/reference/boundary-shaping-004.ref.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<style>
+@font-face {
+  font-family: test;
+  src: url(../resources/LinLibertine_Re-4.7.5.woff);
+}
+body {
+  font: 36px test; /* use a font that includes ligatures for "fi" etc */
+}
+.a {
+  display: inline-block;
+  width: 10px;
+}
+</style>
+</head>
+<body>
+off<span class=a>&nbsp;</span>ice
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/css/css-text/boundary-shaping/reference/boundary-shaping-005.ref.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<style>
+@font-face {
+  font-family: test;
+  src: url(../resources/LinLibertine_Re-4.7.5.woff);
+}
+body {
+  font: 36px test; /* use a font that includes ligatures for "fi" etc */
+}
+.a {
+  display: inline-block;
+  width: 10px;
+}
+</style>
+</head>
+<body>
+off<span class=a>&nbsp;</span>ice
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/css/css-text/boundary-shaping/reference/boundary-shaping-006.ref.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<style>
+@font-face {
+  font-family: test;
+  src: url(../resources/LinLibertine_Re-4.7.5.woff);
+}
+body {
+  font: 36px test; /* use a font that includes ligatures for "fi" etc */
+}
+.a {
+  vertical-align: super;
+  display: inline-block;
+}
+</style>
+</head>
+<body>
+of<span class=a>f</span>ice
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/css/css-text/boundary-shaping/reference/boundary-shaping-007.ref.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<style>
+@font-face {
+  font-family: test;
+  src: url(../resources/LinLibertine_Re-4.7.5.woff);
+}
+body {
+  font: 36px test; /* use a font that includes ligatures for "fi" etc */
+}
+.a {
+  padding-left: 10px;
+  margin-right: 10px;
+  display: inline-block;
+}
+</style>
+</head>
+<body>
+of<span class=a>f</span>ice
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/css/css-text/boundary-shaping/reference/boundary-shaping-008.ref.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<style>
+@font-face {
+  font-family: test;
+  src: url(../resources/LinLibertine_Re-4.7.5.woff);
+}
+body {
+  font: 36px test; /* use a font that includes ligatures for "fi" etc */
+}
+.a {
+  display: inline-block;
+}
+</style>
+</head>
+<body>
+of<span class=a>f</span>ice
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/css/css-text/boundary-shaping/reference/boundary-shaping-009.ref.html
@@ -0,0 +1,56 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<style>
+body {
+  font: 36px sans-serif;
+}
+div {
+  text-align: center;
+}
+.a {
+  display: inline-block;
+  width: 10px;
+}
+.c1 {
+  padding-left: 10px;
+}
+.c {
+  color: red;
+}
+.d1 {
+  margin-right: 10px;
+}
+.d {
+  color: red;
+}
+</style>
+</head>
+<body>
+<div dir=ltr>
+السلام<span class=a>&nbsp;</span>عليكم
+</div>
+<div dir=ltr>
+السلام<span class=a>&nbsp;</span>عليكم
+</div>
+<div dir=rtl>
+السلام<span class=a>&nbsp;</span>عليكم
+</div>
+<div dir=rtl>
+السلام<span class=a>&nbsp;</span>عليكم
+</div>
+<div dir=ltr>
+<span class=c1>السلام<span class=c>عليكم</span></span>
+</div>
+<div dir=ltr>
+<span class=d1><span class=d>السلام</span>عليكم</span>
+</div>
+<div dir=rtl>
+<span class=c1>السلام<span class=c>عليكم</span></span>
+</div>
+<div dir=rtl>
+<span class=d1><span class=d>السلام</span>عليكم</span>
+</div>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/css/css-text/boundary-shaping/reference/boundary-shaping-010.ref.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<style>
+body {
+  font: 36px sans-serif;
+}
+div {
+  text-align: center;
+}
+</style>
+</head>
+<body>
+<div dir=rtl>
+السلام
+</body>
+</html>
copy from layout/reftests/fonts/LinLibertine_Re-4.7.5.woff
copy to testing/web-platform/tests/css/css-text/boundary-shaping/resources/LinLibertine_Re-4.7.5.woff