Merge inbound to central, a=merge CLOSED TREE
authorWes Kocher <wkocher@mozilla.com>
Tue, 31 Jan 2017 15:13:44 -0800
changeset 331870 1d025ac534a6333a8170a59a95a8a3673d4028ee
parent 331831 c22bc80b4d44f8b710c154eed2b52a73a167b037 (current diff)
parent 331869 895ddf282ead4d4533313c43b7cfa0aa218981e3 (diff)
child 331889 644f861ed41a52b4616de33c9c7ce189810e4ea9
child 331944 41503051063a3f2a629521379e204725283f7034
push id31289
push userkwierso@gmail.com
push dateTue, 31 Jan 2017 23:13:55 +0000
treeherdermozilla-central@1d025ac534a6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone54.0a1
first release with
nightly linux32
1d025ac534a6 / 54.0a1 / 20170201110031 / files
nightly linux64
1d025ac534a6 / 54.0a1 / 20170201110031 / files
nightly mac
1d025ac534a6 / 54.0a1 / 20170201030207 / files
nightly win32
1d025ac534a6 / 54.0a1 / 20170201030207 / files
nightly win64
1d025ac534a6 / 54.0a1 / 20170201030207 / 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 inbound to central, a=merge CLOSED TREE MozReview-Commit-ID: EznJuwqcCfw
gfx/graphite2/ChangeLog
gfx/graphite2/include/graphite2/XmlLog.h
gfx/graphite2/src/Bidi.cpp
gfx/graphite2/src/GlyphFaceCache.cpp
gfx/graphite2/src/MozGrMalloc.h
gfx/graphite2/src/Rule.cpp
gfx/graphite2/src/XmlTraceLog.cpp
gfx/graphite2/src/XmlTraceLogTags.cpp
gfx/graphite2/src/inc/Bidi.h
gfx/graphite2/src/inc/GlyphFaceCache.h
gfx/graphite2/src/inc/Shrinker.h
gfx/graphite2/src/moz.build
--- a/accessible/windows/msaa/AccessibleWrap.cpp
+++ b/accessible/windows/msaa/AccessibleWrap.cpp
@@ -1250,25 +1250,35 @@ AccessibleWrap::GetChildIDFor(Accessible
 
 HWND
 AccessibleWrap::GetHWNDFor(Accessible* aAccessible)
 {
   if (!aAccessible) {
     return nullptr;
   }
 
-  // Accessibles in child processes are said to have the HWND of the window
-  // their tab is within.  Popups are always in the parent process, and so
-  // never proxied, which means this is basically correct.
   if (aAccessible->IsProxy()) {
     ProxyAccessible* proxy = aAccessible->Proxy();
     if (!proxy) {
       return nullptr;
     }
 
+    // If window emulation is enabled, retrieve the emulated window from the
+    // containing document document proxy.
+    if (nsWinUtils::IsWindowEmulationStarted()) {
+      DocAccessibleParent* doc = proxy->Document();
+      HWND hWnd = doc->GetEmulatedWindowHandle();
+      if (hWnd) {
+        return hWnd;
+      }
+    }
+
+    // Accessibles in child processes are said to have the HWND of the window
+    // their tab is within.  Popups are always in the parent process, and so
+    // never proxied, which means this is basically correct.
     Accessible* outerDoc = proxy->OuterDocOfRemoteBrowser();
     NS_ASSERTION(outerDoc, "no outer doc for accessible remote tab!");
     if (!outerDoc) {
       return nullptr;
     }
 
     return GetHWNDFor(outerDoc);
   }
--- a/browser/base/content/test/urlbar/browser.ini
+++ b/browser/base/content/test/urlbar/browser.ini
@@ -24,17 +24,16 @@ support-files =
 [browser_bug1024133-switchtab-override-keynav.js]
 [browser_bug1025195_switchToTabHavingURI_aOpenParams.js]
 [browser_bug1070778.js]
 [browser_bug1225194-remotetab.js]
 [browser_bug304198.js]
 [browser_bug556061.js]
 subsuite = clipboard
 [browser_bug562649.js]
-skip-if = e10s # Bug 1315042
 [browser_bug623155.js]
 support-files =
   redirect_bug623155.sjs
 [browser_bug783614.js]
 [browser_canonizeURL.js]
 [browser_dragdropURL.js]
 [browser_locationBarCommand.js]
 [browser_locationBarExternalLoad.js]
--- a/browser/base/content/test/urlbar/browser_bug562649.js
+++ b/browser/base/content/test/urlbar/browser_bug562649.js
@@ -4,21 +4,21 @@ function test() {
                            null,
                            Ci.nsIBrowserDOMWindow.OPEN_NEWTAB,
                            Ci.nsIBrowserDOMWindow.OPEN_EXTERNAL);
 
   is(gBrowser.userTypedValue, URI, "userTypedValue matches test URI");
   is(gURLBar.value, URI, "location bar value matches test URI");
 
   gBrowser.selectedTab = gBrowser.addTab();
-  gBrowser.removeCurrentTab();
+  gBrowser.removeCurrentTab({ skipPermitUnload: true });
   is(gBrowser.userTypedValue, URI, "userTypedValue matches test URI after switching tabs");
   is(gURLBar.value, URI, "location bar value matches test URI after switching tabs");
 
   waitForExplicitFinish();
   BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser).then(() => {
     is(gBrowser.userTypedValue, null, "userTypedValue is null as the page has loaded");
     is(gURLBar.value, URI, "location bar value matches test URI as the page has loaded");
 
-    gBrowser.removeCurrentTab();
+    gBrowser.removeCurrentTab({ skipPermitUnload: true });
     finish();
   });
 }
--- a/devtools/client/framework/options-panel.css
+++ b/devtools/client/framework/options-panel.css
@@ -105,12 +105,17 @@
 #devtools-sourceeditor-keybinding-select {
   min-width: 130px;
 }
 
 #devtools-sourceeditor-tabsize-select {
   min-width: 80px;
 }
 
+#screenshot-icon {
+  vertical-align: middle;
+  min-width: 0;
+  padding: 5px;
+}
+
 #screenshot-icon::before {
   background-image: url(chrome://devtools/skin/images/command-screenshot.svg);
-  margin-inline-start: 5px;
 }
--- a/devtools/client/framework/toolbox-options.xhtml
+++ b/devtools/client/framework/toolbox-options.xhtml
@@ -105,17 +105,17 @@
           <input type="checkbox"
                  data-pref="devtools.styleeditor.autocompletion-enabled"/>
           <span>&options.stylesheetAutocompletion.label;</span>
         </label>
       </fieldset>
 
       <fieldset id="screenshot-options" class="options-groupbox">
         <legend>&options.screenshot.label;
-          <span id="screenshot-icon" class="devtools-button"></span>
+          <button id="screenshot-icon" disabled="true" class="devtools-button"></button>
         </legend>
         <label title="&options.screenshot.clipboard.tooltip;">
           <input type="checkbox"
                  id="devtools-screenshot-clipboard"
                  data-pref="devtools.screenshot.clipboard.enabled"/>
           <span>&options.screenshot.clipboard.label;</span>
         </label>
         <label title="&options.screenshot.audio.tooltip;">
--- a/dom/base/crashtests/crashtests.list
+++ b/dom/base/crashtests/crashtests.list
@@ -163,18 +163,18 @@ load 815500.html
 load 816253.html
 load 819014.html
 load 822691.html
 load 822723.html
 load 824719.html
 load 827190.html
 load 828054.html
 load 828903.html
-asserts-if(stylo,2) load 829428.html # bug 1324669
-asserts-if(stylo,2) load 830098.html # bug 1324669
+load 829428.html
+load 830098.html
 load 831287.html
 load 832644.html
 load 836890.html
 load 838489-1.html
 load 838489-2.html
 load 841205.html
 load 844404.html
 load 845093-1.html
--- a/dom/canvas/CanvasRenderingContext2D.cpp
+++ b/dom/canvas/CanvasRenderingContext2D.cpp
@@ -5605,79 +5605,82 @@ CanvasRenderingContext2D::GetImageDataAr
     if (!readback || !readback->Map(DataSourceSurface::READ, &rawData)) {
       return NS_ERROR_OUT_OF_MEMORY;
     }
   }
 
   IntRect dstWriteRect = srcReadRect;
   dstWriteRect.MoveBy(-aX, -aY);
 
-  JS::AutoCheckCannotGC nogc;
-  bool isShared;
-  uint8_t* data = JS_GetUint8ClampedArrayData(darray, &isShared, nogc);
-  MOZ_ASSERT(!isShared);        // Should not happen, data was created above
-
-  uint8_t* src;
-  uint32_t srcStride;
-  if (readback) {
-    srcStride = rawData.mStride;
-    src = rawData.mData + srcReadRect.y * srcStride + srcReadRect.x * 4;
-  } else {
-    src = data;
-    srcStride = aWidth * 4;
-  }
-
-  uint8_t* dst = data + dstWriteRect.y * (aWidth * 4) + dstWriteRect.x * 4;
-
-  if (mOpaque) {
-    for (int32_t j = 0; j < dstWriteRect.height; ++j) {
-      for (int32_t i = 0; i < dstWriteRect.width; ++i) {
-        // XXX Is there some useful swizzle MMX we can use here?
+  {
+    JS::AutoCheckCannotGC nogc;
+    bool isShared;
+    uint8_t* data = JS_GetUint8ClampedArrayData(darray, &isShared, nogc);
+    MOZ_ASSERT(!isShared);        // Should not happen, data was created above
+
+    uint8_t* src;
+    uint32_t srcStride;
+    if (readback) {
+      srcStride = rawData.mStride;
+      src = rawData.mData + srcReadRect.y * srcStride + srcReadRect.x * 4;
+    } else {
+      src = data;
+      srcStride = aWidth * 4;
+    }
+
+    uint8_t* dst = data + dstWriteRect.y * (aWidth * 4) + dstWriteRect.x * 4;
+
+    if (mOpaque) {
+      for (int32_t j = 0; j < dstWriteRect.height; ++j) {
+        for (int32_t i = 0; i < dstWriteRect.width; ++i) {
+          // XXX Is there some useful swizzle MMX we can use here?
 #if MOZ_LITTLE_ENDIAN
-        uint8_t b = *src++;
-        uint8_t g = *src++;
-        uint8_t r = *src++;
-        src++;
+          uint8_t b = *src++;
+          uint8_t g = *src++;
+          uint8_t r = *src++;
+          src++;
 #else
-        src++;
-        uint8_t r = *src++;
-        uint8_t g = *src++;
-        uint8_t b = *src++;
+          src++;
+          uint8_t r = *src++;
+          uint8_t g = *src++;
+          uint8_t b = *src++;
 #endif
-        *dst++ = r;
-        *dst++ = g;
-        *dst++ = b;
-        *dst++ = 255;
+          *dst++ = r;
+          *dst++ = g;
+          *dst++ = b;
+          *dst++ = 255;
+        }
+        src += srcStride - (dstWriteRect.width * 4);
+        dst += (aWidth * 4) - (dstWriteRect.width * 4);
       }
-      src += srcStride - (dstWriteRect.width * 4);
-      dst += (aWidth * 4) - (dstWriteRect.width * 4);
-    }
-  } else
-  for (int32_t j = 0; j < dstWriteRect.height; ++j) {
-    for (int32_t i = 0; i < dstWriteRect.width; ++i) {
-      // XXX Is there some useful swizzle MMX we can use here?
+    } else {
+      for (int32_t j = 0; j < dstWriteRect.height; ++j) {
+        for (int32_t i = 0; i < dstWriteRect.width; ++i) {
+          // XXX Is there some useful swizzle MMX we can use here?
 #if MOZ_LITTLE_ENDIAN
-      uint8_t b = *src++;
-      uint8_t g = *src++;
-      uint8_t r = *src++;
-      uint8_t a = *src++;
+          uint8_t b = *src++;
+          uint8_t g = *src++;
+          uint8_t r = *src++;
+          uint8_t a = *src++;
 #else
-      uint8_t a = *src++;
-      uint8_t r = *src++;
-      uint8_t g = *src++;
-      uint8_t b = *src++;
+          uint8_t a = *src++;
+          uint8_t r = *src++;
+          uint8_t g = *src++;
+          uint8_t b = *src++;
 #endif
-      // Convert to non-premultiplied color
-      *dst++ = gfxUtils::sUnpremultiplyTable[a * 256 + r];
-      *dst++ = gfxUtils::sUnpremultiplyTable[a * 256 + g];
-      *dst++ = gfxUtils::sUnpremultiplyTable[a * 256 + b];
-      *dst++ = a;
+          // Convert to non-premultiplied color
+          *dst++ = gfxUtils::sUnpremultiplyTable[a * 256 + r];
+          *dst++ = gfxUtils::sUnpremultiplyTable[a * 256 + g];
+          *dst++ = gfxUtils::sUnpremultiplyTable[a * 256 + b];
+          *dst++ = a;
+        }
+        src += srcStride - (dstWriteRect.width * 4);
+        dst += (aWidth * 4) - (dstWriteRect.width * 4);
+      }
     }
-    src += srcStride - (dstWriteRect.width * 4);
-    dst += (aWidth * 4) - (dstWriteRect.width * 4);
   }
 
   if (readback) {
     readback->Unmap();
   }
 
   *aRetval = darray;
   return NS_OK;
--- a/dom/canvas/ImageBitmap.cpp
+++ b/dom/canvas/ImageBitmap.cpp
@@ -911,17 +911,17 @@ ImageBitmap::CreateInternal(nsIGlobalObj
   // If the HTMLCanvasElement's rendering context is WebGL, then the snapshot
   // we got from the HTMLCanvasElement is a DataSourceSurface which is a copy
   // of the rendering context. We handle cropping in this case.
   bool needToReportMemoryAllocation = false;
   if ((aCanvasEl.GetCurrentContextType() == CanvasContextType::WebGL1 ||
        aCanvasEl.GetCurrentContextType() == CanvasContextType::WebGL2) &&
       aCropRect.isSome()) {
     // The _surface_ must be a DataSourceSurface.
-    MOZ_ASSERT(surface->GetType() == SurfaceType::DATA,
+    MOZ_ASSERT(surface->IsDataSourceSurface(),
                "The snapshot SourceSurface from WebGL rendering contest is not \
                DataSourceSurface.");
     RefPtr<DataSourceSurface> dataSurface = surface->GetDataSurface();
     croppedSurface = CropAndCopyDataSourceSurface(dataSurface, cropRect);
     cropRect.MoveTo(0, 0);
     needToReportMemoryAllocation = true;
   }
   else {
new file mode 100644
--- /dev/null
+++ b/dom/canvas/crashtests/1334366-1.html
@@ -0,0 +1,8 @@
+<script>
+Logger={}; Logger.JSError=function(e){};
+try { o0 = document.createElement('canvas'); } catch(e) { Logger.JSError(e); }
+try { (document.body || document.documentElement).appendChild(o0) } catch(e) { Logger.JSError(e); }
+try { o1 = o0.getContext('2d'); } catch(e) { Logger.JSError(e); }
+try { o1.translate(1152921504606847000, 0.919677262874245) } catch(e) { Logger.JSError(e); }
+try { o1.fillText("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",0.6494016751296356,-16,0.5988693960474034) } catch(e) { Logger.JSError(e); }
+</script>
new file mode 100644
--- /dev/null
+++ b/dom/canvas/crashtests/1334647-1.html
@@ -0,0 +1,8 @@
+<script>
+Logger={}; Logger.JSError=function(e){};
+try { o0 = document.createElement('canvas'); } catch(e) { Logger.JSError(e); }
+try { (document.body || document.documentElement).appendChild(o0) } catch(e) { Logger.JSError(e); }
+try { o1 = o0.getContext('2d'); } catch(e) { Logger.JSError(e); }
+try { o0.width = 311853383.455201; } catch(e) { Logger.JSError(e); }
+try { o1.drawImage(o0, -0.906275445340731, 0.3679144809413502, 2, 32) } catch(e) { Logger.JSError(e); }
+</script>
--- a/dom/canvas/crashtests/crashtests.list
+++ b/dom/canvas/crashtests/crashtests.list
@@ -34,9 +34,11 @@ skip-if(d2d) load 1287515-1.html
 asserts-if(stylo,1) load 1287652-1.html # bug 1324700
 asserts-if(stylo,1) load 1288872-1.html # bug 1324700
 load 1290628-1.html
 asserts-if(stylo,1) load 1283113-1.html # bug 1324700
 load 1286458-1.html
 load 1299062-1.html
 load 1305312-1.html
 load 1298576-1.html
+load 1334366-1.html
+load 1334647-1.html
 
--- a/dom/canvas/test/reftest/filters/reftest-stylo.list
+++ b/dom/canvas/test/reftest/filters/reftest-stylo.list
@@ -1,31 +1,31 @@
 # DO NOT EDIT! This is a auto-generated temporary list for Stylo testing
 default-preferences pref(canvas.filters.enabled,true)
 
-fails == default-color.html default-color.html
+fails asserts-if(stylo,2) == default-color.html default-color.html # bug 1324700
 # == drop-shadow.html drop-shadow.html
-fails == drop-shadow-transformed.html drop-shadow-transformed.html
-fails == global-alpha.html global-alpha.html
-fails == global-composite-operation.html global-composite-operation.html
-fails == liveness.html liveness.html
-fails == multiple-drop-shadows.html multiple-drop-shadows.html
-fails == shadow.html shadow.html
-fails == subregion-fill-paint.html subregion-fill-paint.html
-fails == subregion-stroke-paint.html subregion-stroke-paint.html
-fails == svg-bbox.html svg-bbox.html
-fails == svg-inline.html svg-inline.html
-fails == svg-liveness.html svg-liveness.html
-fails == svg-off-screen.html svg-off-screen.html
-fails == units.html units.html
-fails == units-em.html units-em.html
-fails == units-ex.html units-ex.html
-fails == units-off-screen.html units-off-screen.html
-fails == fillText-with-filter-opacity-1.html fillText-with-filter-opacity-1.html
-fails == fillText-with-filter-opacity-2.html fillText-with-filter-opacity-2.html
-fails == strokeText-with-filter-grayscale-1.html strokeText-with-filter-grayscale-1.html
-fails == strokeText-with-filter-grayscale-2.html strokeText-with-filter-grayscale-2.html
-fails == fillText-with-shadow-1.html fillText-with-shadow-1.html
-fails == fillText-with-shadow-2.html fillText-with-shadow-2.html
-fails == fillText-with-filter-grayscale-1.html fillText-with-filter-grayscale-1.html
-fails == fillText-with-filter-grayscale-2.html fillText-with-filter-grayscale-2.html
-fails == strokeText-with-shadow-1.html strokeText-with-shadow-1.html
-fails == strokeText-with-shadow-2.html strokeText-with-shadow-2.html
+fails asserts-if(stylo,2) == drop-shadow-transformed.html drop-shadow-transformed.html # bug 1324700
+fails asserts-if(stylo,2) == global-alpha.html global-alpha.html # bug 1324700
+fails asserts-if(stylo,2) == global-composite-operation.html global-composite-operation.html # bug 1324700
+fails asserts-if(stylo,1) == liveness.html liveness.html # bug 1324700
+fails asserts-if(stylo,2) == multiple-drop-shadows.html multiple-drop-shadows.html # bug 1324700
+fails asserts-if(stylo,2) == shadow.html shadow.html # bug 1324700
+fails asserts-if(stylo,2) == subregion-fill-paint.html subregion-fill-paint.html # bug 1324700
+fails asserts-if(stylo,2) == subregion-stroke-paint.html subregion-stroke-paint.html # bug 1324700
+fails asserts-if(stylo,2) == svg-bbox.html svg-bbox.html # bug 1324700
+fails asserts-if(stylo,2) == svg-inline.html svg-inline.html # bug 1324700
+fails asserts-if(stylo,2) == svg-liveness.html svg-liveness.html # bug 1324700
+fails asserts-if(stylo,2) == svg-off-screen.html svg-off-screen.html # bug 1324700
+fails asserts-if(stylo,2) == units.html units.html # bug 1324700
+fails asserts-if(stylo,1) == units-em.html units-em.html # bug 1324700
+fails asserts-if(stylo,1) == units-ex.html units-ex.html # bug 1324700
+fails asserts-if(stylo,2) == units-off-screen.html units-off-screen.html # bug 1324700
+fails asserts-if(stylo,2) == fillText-with-filter-opacity-1.html fillText-with-filter-opacity-1.html # bug 1324700
+fails asserts-if(stylo,2) == fillText-with-filter-opacity-2.html fillText-with-filter-opacity-2.html # bug 1324700
+fails asserts-if(stylo,2) == strokeText-with-filter-grayscale-1.html strokeText-with-filter-grayscale-1.html # bug 1324700
+fails asserts-if(stylo,2) == strokeText-with-filter-grayscale-2.html strokeText-with-filter-grayscale-2.html # bug 1324700
+fails asserts-if(stylo,1) == fillText-with-shadow-1.html fillText-with-shadow-1.html # bug 1324700
+fails asserts-if(stylo,1) == fillText-with-shadow-2.html fillText-with-shadow-2.html # bug 1324700
+fails asserts-if(stylo,2) == fillText-with-filter-grayscale-1.html fillText-with-filter-grayscale-1.html # bug 1324700
+fails asserts-if(stylo,2) == fillText-with-filter-grayscale-2.html fillText-with-filter-grayscale-2.html # bug 1324700
+fails asserts-if(stylo,1) == strokeText-with-shadow-1.html strokeText-with-shadow-1.html # bug 1324700
+fails asserts-if(stylo,1) == strokeText-with-shadow-2.html strokeText-with-shadow-2.html # bug 1324700
--- a/dom/canvas/test/reftest/reftest-stylo.list
+++ b/dom/canvas/test/reftest/reftest-stylo.list
@@ -150,25 +150,25 @@ skip-if(!winWidget) pref(webgl.disable-a
 # Do we correctly handle multiple clip paths?
 == clip-multiple-paths.html clip-multiple-paths.html
 
 # Bug 1255062
 == clip-multiple-move-1.html clip-multiple-move-1.html
 == clip-multiple-move-2.html clip-multiple-move-2.html
 
 # Bug 815648
-fails == stroketext-shadow.html stroketext-shadow.html
+fails asserts-if(stylo,1) == stroketext-shadow.html stroketext-shadow.html # bug 1324700
 
 # focus rings
-pref(canvas.focusring.enabled,true) skip-if(cocoaWidget) skip-if(winWidget) needs-focus == drawFocusIfNeeded.html drawFocusIfNeeded.html
-pref(canvas.customfocusring.enabled,true) skip-if(Android||cocoaWidget||winWidget) fuzzy-if(gtkWidget,64,410) needs-focus == drawCustomFocusRing.html drawCustomFocusRing.html
+pref(canvas.focusring.enabled,true) skip-if(cocoaWidget) skip-if(winWidget) asserts-if(stylo,6) needs-focus == drawFocusIfNeeded.html drawFocusIfNeeded.html # bug 1324671
+pref(canvas.customfocusring.enabled,true) skip-if(Android||cocoaWidget||winWidget) fuzzy-if(gtkWidget,64,410) asserts-if(stylo,6) needs-focus == drawCustomFocusRing.html drawCustomFocusRing.html # bug 1324671
 
 # Check that captureStream() displays in a local video element
 == capturestream.html capturestream.html
 
-fails == 1177726-text-stroke-bounds.html 1177726-text-stroke-bounds.html
+fails asserts-if(stylo,1) == 1177726-text-stroke-bounds.html 1177726-text-stroke-bounds.html # bug 1324700
 
 # Canvas Filter Reftests
 include filters/reftest-stylo.list
 
 # Bug 1305963
 == mozCurrentTransform.html mozCurrentTransform.html
 == mozCurrentTransformInverse.html mozCurrentTransformInverse.html
--- a/dom/filesystem/GetFilesHelper.cpp
+++ b/dom/filesystem/GetFilesHelper.cpp
@@ -20,22 +20,23 @@ class ReleaseRunnable final : public Run
 {
 public:
   static void
   MaybeReleaseOnMainThread(nsTArray<RefPtr<Promise>>& aPromises,
                            nsTArray<RefPtr<GetFilesCallback>>& aCallbacks,
                            Sequence<RefPtr<File>>& aFiles,
                            already_AddRefed<nsIGlobalObject> aGlobal)
   {
+    nsCOMPtr<nsIGlobalObject> global(aGlobal);
     if (NS_IsMainThread()) {
       return;
     }
 
     RefPtr<ReleaseRunnable> runnable =
-      new ReleaseRunnable(aPromises, aCallbacks, aFiles, Move(aGlobal));
+      new ReleaseRunnable(aPromises, aCallbacks, aFiles, global.forget());
     NS_DispatchToMainThread(runnable);
   }
 
   NS_IMETHOD
   Run() override
   {
     MOZ_ASSERT(NS_IsMainThread());
 
--- a/dom/html/crashtests/crashtests.list
+++ b/dom/html/crashtests/crashtests.list
@@ -51,17 +51,17 @@ load 680922-1.xul
 load 682058.xhtml
 load 682460.html
 load 738744.xhtml
 asserts-if(stylo,6-30) load 741218.json # bug 1324634
 load 741250.xhtml
 load 795221-1.html
 asserts-if(stylo,1) load 795221-2.html # bug 1324702
 load 795221-3.html
-asserts-if(stylo,2) load 795221-4.html # bug 1324669
+load 795221-4.html
 load 795221-5.xml
 load 811226.html
 load 819745.html
 load 828180.html
 pref(dom.experimental_forms,true) load 828472.html
 load 837033.html
 asserts-if(stylo,3) load 838256-1.html # bug 1324671
 load 862084.html
--- a/dom/ipc/TabParent.cpp
+++ b/dom/ipc/TabParent.cpp
@@ -975,17 +975,17 @@ a11y::DocAccessibleParent*
 TabParent::GetTopLevelDocAccessible() const
 {
 #ifdef ACCESSIBILITY
   // XXX Consider managing non top level PDocAccessibles with their parent
   // document accessible.
   const ManagedContainer<PDocAccessibleParent>& docs = ManagedPDocAccessibleParent();
   for (auto iter = docs.ConstIter(); !iter.Done(); iter.Next()) {
     auto doc = static_cast<a11y::DocAccessibleParent*>(iter.Get()->GetKey());
-    if (!doc->ParentDoc()) {
+    if (doc->IsTopLevel()) {
       return doc;
     }
   }
 
   MOZ_ASSERT(docs.Count() == 0, "If there isn't a top level accessible doc "
                                 "there shouldn't be an accessible doc at all!");
 #endif
   return nullptr;
--- a/dom/media/tests/mochitest/mochitest.ini
+++ b/dom/media/tests/mochitest/mochitest.ini
@@ -163,17 +163,17 @@ skip-if = (android_version == '18') # an
 [test_peerConnection_noTrickleOfferAnswer.html]
 skip-if = (android_version == '18') # android(Bug 1189784, timeouts on 4.3 emulator)
 [test_peerConnection_offerRequiresReceiveAudio.html]
 skip-if = (android_version == '18') # android(Bug 1189784, timeouts on 4.3 emulator)
 [test_peerConnection_offerRequiresReceiveVideo.html]
 [test_peerConnection_offerRequiresReceiveVideoAudio.html]
 skip-if = (android_version == '18') # android(Bug 1189784, timeouts on 4.3 emulator)
 [test_peerConnection_promiseSendOnly.html]
-skip-if = (android_version == '18' && debug) # android(Bug 1189784, timeouts on 4.3 emulator)
+skip-if = (android_version == '18') # android(Bug 1189784, 1318809 timeouts on 4.3 emulator)
 [test_peerConnection_renderAfterRenegotiation.html]
 skip-if = (android_version == '18') # android(Bug 1189784, 1326005 timeouts on 4.3 emulator)
 [test_peerConnection_restartIce.html]
 skip-if = android_version
 [test_peerConnection_restartIceNoBundle.html]
 skip-if = android_version
 [test_peerConnection_restartIceNoBundleNoRtcpMux.html]
 skip-if = android_version
--- a/dom/smil/crashtests/crashtests.list
+++ b/dom/smil/crashtests/crashtests.list
@@ -18,23 +18,23 @@ load 554202-2.svg
 load 555026-1.svg
 load 556841-1.svg
 load 572938-1.svg
 load 572938-2.svg
 load 572938-3.svg
 load 572938-4.svg
 load 588287-1.svg
 load 588287-2.svg
-asserts-if(stylo,2) load 590425-1.html # bug 1324669
-asserts-if(stylo,1-27) load 592477-1.xhtml # bug 1324669
+load 590425-1.html
+load 592477-1.xhtml
 load 594653-1.svg
 load 596796-1.svg
 load 605345-1.svg
 load 606101-1.svg
-asserts-if(stylo,2) load 608295-1.html # bug 1324689
+asserts-if(stylo,1) load 608295-1.html # bug 1324689
 load 608549-1.svg
 load 611927-1.svg
 load 615002-1.svg
 load 615872-1.svg
 load 641388-1.html
 load 641388-2.html
 load 650732-1.svg
 load 665334-1.svg
--- a/dom/smil/nsSMILAnimationController.cpp
+++ b/dom/smil/nsSMILAnimationController.cpp
@@ -318,17 +318,17 @@ nsSMILAnimationController::DoSample(bool
     NS_ERROR("Shouldn't be recursively sampling");
     return;
   }
 
   bool isStyleFlushNeeded = mResampleNeeded;
   mResampleNeeded = false;
 
   if (mDocument->IsStyledByServo()) {
-    NS_ERROR("stylo: SMIL animations not supported yet");
+    NS_WARNING("stylo: SMIL animations not supported yet");
     return;
   }
 
   // Set running sample flag -- do this before flushing styles so that when we
   // flush styles we don't end up requesting extra samples
   AutoRestore<bool> autoRestoreRunningSample(mRunningSample);
   mRunningSample = true;
 
--- a/dom/svg/crashtests/crashtests.list
+++ b/dom/svg/crashtests/crashtests.list
@@ -1,15 +1,15 @@
 asserts(0-6) load 307322-1.svg # bug 563481
 load 327705-1.svg
 load 336994-1.html
 load 344888-1.svg
 load 345445-1.svg
 load 360836-1.svg
-asserts-if(stylo,2) load 367357-1.xhtml # bug 1324669
+load 367357-1.xhtml
 load 369051-1.svg
 load 369249-1.svg
 load 369291-1.svg
 load 369291-2.svg
 load 369568-1.svg
 load 372046-1.svg
 load 372046-2.svg
 load 374882-1.svg
@@ -70,21 +70,21 @@ load 880544-1.svg
 load 880544-2.svg
 load 880544-3.svg
 load 880544-4.svg
 load 880544-5.svg
 load 898915-1.svg
 load 1035248-1.svg
 load 1035248-2.svg
 load 1244898-1.xhtml
-asserts-if(stylo,2) load 1250725.html # bug 1324669
+load 1250725.html
 load 1267272-1.svg
 load 1282985-1.svg
 # Disabled for now due to it taking a very long time to run - bug 1259356
 #load long-clipPath-reference-chain.svg
 load zero-size-image.svg
-asserts-if(stylo,2) load 1322286.html # bug 1324669
+load 1322286.html
 load 1329849-1.svg
 load 1329849-2.svg
 load 1329849-3.svg
 load 1329849-4.svg
 load 1329849-5.svg
 load 1329849-6.svg
--- a/dom/workers/ServiceWorkerClients.cpp
+++ b/dom/workers/ServiceWorkerClients.cpp
@@ -480,35 +480,69 @@ NS_IMPL_CYCLE_COLLECTION(WebProgressList
                          mServiceWorkerPrivate, mWindow)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(WebProgressListener)
   NS_INTERFACE_MAP_ENTRY(nsIWebProgressListener)
   NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
 NS_INTERFACE_MAP_END
 
 class OpenWindowRunnable final : public Runnable
+                               , public nsIObserver
+                               , public nsSupportsWeakReference
 {
   RefPtr<PromiseWorkerProxy> mPromiseProxy;
   nsString mUrl;
   nsString mScope;
 
 public:
+  NS_DECL_ISUPPORTS_INHERITED
+  // Note: |OpenWindowRunnable| cannot be cycle collected because it inherits
+  // thread safe reference counting from |mozilla::Runnable|. On Fennec, we
+  // might use |ServiceWorkerPrivate::StoreISupports| to keep this object alive
+  // while waiting for an event from the observer service. As such, to avoid
+  // creating a cycle that will leak, |OpenWindowRunnable| must not hold a strong
+  // reference to |ServiceWorkerPrivate|.
+
   OpenWindowRunnable(PromiseWorkerProxy* aPromiseProxy,
                      const nsAString& aUrl,
                      const nsAString& aScope)
     : mPromiseProxy(aPromiseProxy)
     , mUrl(aUrl)
     , mScope(aScope)
   {
     MOZ_ASSERT(aPromiseProxy);
     MOZ_ASSERT(aPromiseProxy->GetWorkerPrivate());
     aPromiseProxy->GetWorkerPrivate()->AssertIsOnWorkerThread();
   }
 
   NS_IMETHOD
+  Observe(nsISupports* aSubject, const char* aTopic, const char16_t* /* aData */) override
+  {
+    AssertIsOnMainThread();
+
+    nsCString topic(aTopic);
+    if (!topic.Equals(NS_LITERAL_CSTRING("BrowserChrome:Ready"))) {
+      MOZ_ASSERT(false, "Unexpected topic.");
+      return NS_ERROR_FAILURE;
+    }
+
+    nsCOMPtr<nsIObserverService> os = services::GetObserverService();
+    NS_ENSURE_STATE(os);
+    os->RemoveObserver(this, "BrowserChrome:Ready");
+
+    RefPtr<ServiceWorkerPrivate> swp = GetServiceWorkerPrivate();
+    NS_ENSURE_STATE(swp);
+
+    MOZ_ALWAYS_SUCCEEDS(NS_DispatchToMainThread(this));
+    swp->RemoveISupports(static_cast<nsIObserver*>(this));
+
+    return NS_OK;
+  }
+
+  NS_IMETHOD
   Run() override
   {
     AssertIsOnMainThread();
 
     MutexAutoLock lock(mPromiseProxy->Lock());
     if (mPromiseProxy->CleanedUp()) {
       return NS_OK;
     }
@@ -541,92 +575,91 @@ public:
 
       nsCOMPtr<nsIDocShell> docShell = window->GetDocShell();
       nsCOMPtr<nsIWebProgress> webProgress = do_GetInterface(docShell);
 
       if (!webProgress) {
         return NS_ERROR_FAILURE;
       }
 
-      RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
-      if (!swm) {
-        // browser shutdown
-        return NS_ERROR_FAILURE;
-      }
-
-      nsCOMPtr<nsIPrincipal> principal = workerPrivate->GetPrincipal();
-      MOZ_ASSERT(principal);
-      RefPtr<ServiceWorkerRegistrationInfo> registration =
-        swm->GetRegistration(principal, NS_ConvertUTF16toUTF8(mScope));
-      if (NS_WARN_IF(!registration)) {
-        return NS_ERROR_FAILURE;
-      }
-      RefPtr<ServiceWorkerInfo> serviceWorkerInfo =
-        registration->GetServiceWorkerInfoById(workerPrivate->ServiceWorkerID());
-      if (NS_WARN_IF(!serviceWorkerInfo)) {
-        return NS_ERROR_FAILURE;
-      }
+      RefPtr<ServiceWorkerPrivate> swp = GetServiceWorkerPrivate();
+      NS_ENSURE_STATE(swp);
 
       nsCOMPtr<nsIWebProgressListener> listener =
-        new WebProgressListener(mPromiseProxy, serviceWorkerInfo->WorkerPrivate(),
-                                window, baseURI);
+        new WebProgressListener(mPromiseProxy, swp, window, baseURI);
 
       rv = webProgress->AddProgressListener(listener,
                                             nsIWebProgress::NOTIFY_STATE_DOCUMENT);
       MOZ_ASSERT(NS_SUCCEEDED(rv));
       return NS_OK;
     }
 #ifdef MOZ_WIDGET_ANDROID
     else if (rv == NS_ERROR_NOT_AVAILABLE) {
       // We couldn't get a browser window, so Fennec must not be running.
       // Send an Intent to launch Fennec and wait for "BrowserChrome:Ready"
       // to try opening a window again.
+      RefPtr<ServiceWorkerPrivate> swp = GetServiceWorkerPrivate();
+      NS_ENSURE_STATE(swp);
+
       nsCOMPtr<nsIObserverService> os = services::GetObserverService();
       NS_ENSURE_STATE(os);
 
-      WorkerPrivate* workerPrivate = mPromiseProxy->GetWorkerPrivate();
-      MOZ_ASSERT(workerPrivate);
-
-      RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
-      if (!swm) {
-        // browser shutdown
-        return NS_ERROR_FAILURE;
-      }
-
-      nsCOMPtr<nsIPrincipal> principal = workerPrivate->GetPrincipal();
-      MOZ_ASSERT(principal);
+      rv = os->AddObserver(this, "BrowserChrome:Ready", /* weakRef */ true);
+      NS_ENSURE_SUCCESS(rv, rv);
 
-      RefPtr<ServiceWorkerRegistrationInfo> registration =
-        swm->GetRegistration(principal, NS_ConvertUTF16toUTF8(mScope));
-      if (NS_WARN_IF(!registration)) {
-        return NS_ERROR_FAILURE;
-      }
+      swp->StoreISupports(static_cast<nsIObserver*>(this));
 
-      RefPtr<ServiceWorkerInfo> serviceWorkerInfo =
-        registration->GetServiceWorkerInfoById(workerPrivate->ServiceWorkerID());
-      if (NS_WARN_IF(!serviceWorkerInfo)) {
-        return NS_ERROR_FAILURE;
-      }
-
-      os->AddObserver(static_cast<nsIObserver*>(serviceWorkerInfo->WorkerPrivate()),
-                      "BrowserChrome:Ready", true);
-      serviceWorkerInfo->WorkerPrivate()->AddPendingWindow(this);
       return NS_OK;
     }
 #endif
 
     RefPtr<ResolveOpenWindowRunnable> resolveRunnable =
       new ResolveOpenWindowRunnable(mPromiseProxy, nullptr, rv);
 
     Unused << NS_WARN_IF(!resolveRunnable->Dispatch());
 
     return NS_OK;
   }
 
 private:
+  ~OpenWindowRunnable()
+  { }
+
+  ServiceWorkerPrivate*
+  GetServiceWorkerPrivate() const
+  {
+    AssertIsOnMainThread();
+
+    RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
+    if (!swm) {
+      // browser shutdown
+      return nullptr;
+    }
+
+    WorkerPrivate* workerPrivate = mPromiseProxy->GetWorkerPrivate();
+    MOZ_ASSERT(workerPrivate);
+
+    nsCOMPtr<nsIPrincipal> principal = workerPrivate->GetPrincipal();
+    MOZ_DIAGNOSTIC_ASSERT(principal);
+
+    RefPtr<ServiceWorkerRegistrationInfo> registration =
+      swm->GetRegistration(principal, NS_ConvertUTF16toUTF8(mScope));
+    if (NS_WARN_IF(!registration)) {
+      return nullptr;
+    }
+
+    RefPtr<ServiceWorkerInfo> serviceWorkerInfo =
+      registration->GetServiceWorkerInfoById(workerPrivate->ServiceWorkerID());
+    if (NS_WARN_IF(!serviceWorkerInfo)) {
+      return nullptr;
+    }
+
+    return serviceWorkerInfo->WorkerPrivate();
+  }
+
   nsresult
   OpenWindow(nsPIDOMWindowOuter** aWindow)
   {
     MOZ_DIAGNOSTIC_ASSERT(aWindow);
     WorkerPrivate* workerPrivate = mPromiseProxy->GetWorkerPrivate();
 
     // [[1. Let url be the result of parsing url with entry settings object's API
     //   base URL.]]
@@ -725,16 +758,26 @@ private:
     nsCOMPtr<nsPIDOMWindowOuter> pWin = nsPIDOMWindowOuter::From(win);
     pWin.forget(aWindow);
     MOZ_DIAGNOSTIC_ASSERT(*aWindow);
 
     return NS_OK;
   }
 };
 
+NS_IMPL_ADDREF_INHERITED(OpenWindowRunnable, Runnable)                                    \
+NS_IMPL_RELEASE_INHERITED(OpenWindowRunnable, Runnable)
+
+NS_INTERFACE_MAP_BEGIN(OpenWindowRunnable)
+NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
+NS_INTERFACE_MAP_ENTRY(nsIObserver)
+NS_INTERFACE_MAP_ENTRY(nsIRunnable)
+NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIObserver)
+NS_INTERFACE_MAP_END
+
 } // namespace
 
 already_AddRefed<Promise>
 ServiceWorkerClients::Get(const nsAString& aClientId, ErrorResult& aRv)
 {
   WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
   MOZ_ASSERT(workerPrivate);
   workerPrivate->AssertIsOnWorkerThread();
--- a/dom/workers/ServiceWorkerManager.cpp
+++ b/dom/workers/ServiceWorkerManager.cpp
@@ -3195,38 +3195,38 @@ ServiceWorkerManager::GetRegistration(co
   if (!mRegistrationInfos.Get(aScopeKey, &data)) {
     return reg.forget();
   }
 
   data->mInfos.Get(aScope, getter_AddRefs(reg));
   return reg.forget();
 }
 
-ServiceWorkerRegistrationInfo*
+already_AddRefed<ServiceWorkerRegistrationInfo>
 ServiceWorkerManager::CreateNewRegistration(const nsCString& aScope,
                                             nsIPrincipal* aPrincipal,
                                             nsLoadFlags aLoadFlags)
 {
 #ifdef DEBUG
   AssertIsOnMainThread();
   nsCOMPtr<nsIURI> scopeURI;
   nsresult rv = NS_NewURI(getter_AddRefs(scopeURI), aScope, nullptr, nullptr);
   MOZ_ASSERT(NS_SUCCEEDED(rv));
 
   RefPtr<ServiceWorkerRegistrationInfo> tmp =
     GetRegistration(aPrincipal, aScope);
   MOZ_ASSERT(!tmp);
 #endif
 
-  ServiceWorkerRegistrationInfo* registration =
+  RefPtr<ServiceWorkerRegistrationInfo> registration =
     new ServiceWorkerRegistrationInfo(aScope, aPrincipal, aLoadFlags);
   // From now on ownership of registration is with
   // mServiceWorkerRegistrationInfos.
   AddScopeAndRegistration(aScope, registration);
-  return registration;
+  return registration.forget();
 }
 
 void
 ServiceWorkerManager::MaybeRemoveRegistration(ServiceWorkerRegistrationInfo* aRegistration)
 {
   MOZ_ASSERT(aRegistration);
   RefPtr<ServiceWorkerInfo> newest = aRegistration->Newest();
   if (!newest && HasScope(aRegistration->mPrincipal, aRegistration->mScope)) {
--- a/dom/workers/ServiceWorkerManager.h
+++ b/dom/workers/ServiceWorkerManager.h
@@ -182,17 +182,17 @@ public:
   PropagateRemoveAll();
 
   void
   RemoveAll();
 
   already_AddRefed<ServiceWorkerRegistrationInfo>
   GetRegistration(nsIPrincipal* aPrincipal, const nsACString& aScope) const;
 
-  ServiceWorkerRegistrationInfo*
+  already_AddRefed<ServiceWorkerRegistrationInfo>
   CreateNewRegistration(const nsCString& aScope,
                         nsIPrincipal* aPrincipal,
                         nsLoadFlags aLoadFlags);
 
   void
   RemoveRegistration(ServiceWorkerRegistrationInfo* aRegistration);
 
   void StoreRegistration(nsIPrincipal* aPrincipal,
--- a/dom/workers/ServiceWorkerPrivate.cpp
+++ b/dom/workers/ServiceWorkerPrivate.cpp
@@ -32,24 +32,22 @@
 #include "mozilla/dom/RequestBinding.h"
 #include "mozilla/Unused.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 BEGIN_WORKERS_NAMESPACE
 
-NS_IMPL_CYCLE_COLLECTING_ADDREF(ServiceWorkerPrivate)
-NS_IMPL_CYCLE_COLLECTING_RELEASE(ServiceWorkerPrivate)
+NS_IMPL_CYCLE_COLLECTING_NATIVE_ADDREF(ServiceWorkerPrivate)
+NS_IMPL_CYCLE_COLLECTING_NATIVE_RELEASE(ServiceWorkerPrivate)
 NS_IMPL_CYCLE_COLLECTION(ServiceWorkerPrivate, mSupportsArray)
 
-NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ServiceWorkerPrivate)
-  NS_INTERFACE_MAP_ENTRY(nsISupports)
-  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIObserver)
-NS_INTERFACE_MAP_END
+NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(ServiceWorkerPrivate, AddRef)
+NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(ServiceWorkerPrivate, Release)
 
 // Tracks the "dom.disable_open_click_delay" preference.  Modified on main
 // thread, read on worker threads.
 // It is updated every time a "notificationclick" event is dispatched. While
 // this is done without synchronization, at the worst, the thread will just get
 // an older value within which a popup is allowed to be displayed, which will
 // still be a valid value since it was set prior to dispatching the runnable.
 Atomic<uint32_t> gDOMDisableOpenClickDelay(0);
@@ -1861,17 +1859,17 @@ ServiceWorkerPrivate::TerminateWorker()
   AssertIsOnMainThread();
 
   mIdleWorkerTimer->Cancel();
   mIdleKeepAliveToken = nullptr;
   if (mWorkerPrivate) {
     if (Preferences::GetBool("dom.serviceWorkers.testing.enabled")) {
       nsCOMPtr<nsIObserverService> os = services::GetObserverService();
       if (os) {
-        os->NotifyObservers(this, "service-worker-shutdown", nullptr);
+        os->NotifyObservers(nullptr, "service-worker-shutdown", nullptr);
       }
     }
 
     Unused << NS_WARN_IF(!mWorkerPrivate->Terminate());
     mWorkerPrivate = nullptr;
     mSupportsArray.Clear();
 
     // Any pending events are never going to fire on this worker.  Cancel
@@ -2092,48 +2090,16 @@ ServiceWorkerPrivate::CreateEventKeepAli
   AssertIsOnMainThread();
   MOZ_ASSERT(mWorkerPrivate);
   MOZ_ASSERT(mIdleKeepAliveToken);
   RefPtr<KeepAliveToken> ref = new KeepAliveToken(this);
   return ref.forget();
 }
 
 void
-ServiceWorkerPrivate::AddPendingWindow(Runnable* aPendingWindow)
-{
-  AssertIsOnMainThread();
-  pendingWindows.AppendElement(aPendingWindow);
-}
-
-nsresult
-ServiceWorkerPrivate::Observe(nsISupports* aSubject, const char* aTopic, const char16_t* aData)
-{
-  AssertIsOnMainThread();
-
-  nsCString topic(aTopic);
-  if (!topic.Equals(NS_LITERAL_CSTRING("BrowserChrome:Ready"))) {
-    MOZ_ASSERT(false, "Unexpected topic.");
-    return NS_ERROR_FAILURE;
-  }
-
-  nsCOMPtr<nsIObserverService> os = services::GetObserverService();
-  NS_ENSURE_STATE(os);
-  os->RemoveObserver(static_cast<nsIObserver*>(this), "BrowserChrome:Ready");
-
-  size_t len = pendingWindows.Length();
-  for (int i = len-1; i >= 0; i--) {
-    RefPtr<Runnable> runnable = pendingWindows[i];
-    MOZ_ALWAYS_SUCCEEDS(NS_DispatchToMainThread(runnable));
-    pendingWindows.RemoveElementAt(i);
-  }
-
-  return NS_OK;
-}
-
-void
 ServiceWorkerPrivate::SetHandlesFetch(bool aValue)
 {
   AssertIsOnMainThread();
 
   if (NS_WARN_IF(!mInfo)) {
     return;
   }
 
--- a/dom/workers/ServiceWorkerPrivate.h
+++ b/dom/workers/ServiceWorkerPrivate.h
@@ -57,25 +57,32 @@ public:
 // 2. If the worker stopped controlling documents and it is not handling push
 // events.
 // 3. The content process is shutting down.
 //
 // Adding an API function for a new event requires calling |SpawnWorkerIfNeeded|
 // with an appropriate reason before any runnable is dispatched to the worker.
 // If the event is extendable then the runnable should inherit
 // ExtendableEventWorkerRunnable.
-class ServiceWorkerPrivate final : public nsIObserver
+class ServiceWorkerPrivate final
 {
   friend class KeepAliveToken;
 
 public:
-  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
-  NS_DECL_CYCLE_COLLECTION_CLASS(ServiceWorkerPrivate)
-  NS_DECL_NSIOBSERVER
+  NS_IMETHOD_(MozExternalRefCountType) AddRef();
+  NS_IMETHOD_(MozExternalRefCountType) Release();
+  NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(ServiceWorkerPrivate)
+
+  typedef mozilla::FalseType HasThreadSafeRefCnt;
 
+protected:
+  nsCycleCollectingAutoRefCnt mRefCnt;
+  NS_DECL_OWNINGTHREAD
+
+public:
   explicit ServiceWorkerPrivate(ServiceWorkerInfo* aInfo);
 
   nsresult
   SendMessageEvent(JSContext* aCx, JS::Handle<JS::Value> aMessage,
                    const Optional<Sequence<JS::Value>>& aTransferable,
                    UniquePtr<ServiceWorkerClientInfo>&& aClientInfo);
 
   // This is used to validate the worker script and continue the installation
@@ -146,19 +153,16 @@ public:
 
   nsresult
   DetachDebugger();
 
   bool
   IsIdle() const;
 
   void
-  AddPendingWindow(Runnable* aPendingWindow);
-
-  void
   SetHandlesFetch(bool aValue);
 
 private:
   enum WakeUpReason {
     FetchEvent = 0,
     PushEvent,
     PushSubscriptionChangeEvent,
     MessageEvent,
@@ -223,17 +227,15 @@ private:
   // on the main thread. Access to this array is provided through
   // |StoreISupports| and |RemoveISupports|. Note that the array is also
   // cleared whenever the worker is terminated.
   nsTArray<nsCOMPtr<nsISupports>> mSupportsArray;
 
   // Array of function event worker runnables that are pending due to
   // the worker activating.  Main thread only.
   nsTArray<RefPtr<WorkerRunnable>> mPendingFunctionalEvents;
-
-  nsTArray<Runnable*> pendingWindows;
 };
 
 } // namespace workers
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_workers_serviceworkerprivate_h
--- a/dom/xhr/XMLHttpRequestMainThread.cpp
+++ b/dom/xhr/XMLHttpRequestMainThread.cpp
@@ -736,16 +736,25 @@ XMLHttpRequestMainThread::SetResponseTyp
 
   if (mFlagSynchronous &&
       (aResponseType == XMLHttpRequestResponseType::Moz_chunked_text ||
        aResponseType == XMLHttpRequestResponseType::Moz_chunked_arraybuffer)) {
     aRv.Throw(NS_ERROR_DOM_INVALID_STATE_XHR_CHUNKED_RESPONSETYPES_UNSUPPORTED_FOR_SYNC);
     return;
   }
 
+  // We want to get rid of this moz-only types. Bug 1335365.
+  if (aResponseType == XMLHttpRequestResponseType::Moz_blob) {
+    Telemetry::Accumulate(Telemetry::MOZ_BLOB_IN_XHR, 1);
+  } else if (aResponseType == XMLHttpRequestResponseType::Moz_chunked_text) {
+    Telemetry::Accumulate(Telemetry::MOZ_CHUNKED_TEXT_IN_XHR, 1);
+  } else if (aResponseType == XMLHttpRequestResponseType::Moz_chunked_arraybuffer) {
+    Telemetry::Accumulate(Telemetry::MOZ_CHUNKED_ARRAYBUFFER_IN_XHR, 1);
+  }
+
   // Set the responseType attribute's value to the given value.
   mResponseType = aResponseType;
 }
 
 NS_IMETHODIMP
 XMLHttpRequestMainThread::GetResponse(JSContext *aCx, JS::MutableHandle<JS::Value> aResult)
 {
   ErrorResult rv;
--- a/editor/libeditor/crashtests/crashtests.list
+++ b/editor/libeditor/crashtests/crashtests.list
@@ -1,10 +1,10 @@
 load 336081-1.xhtml
-asserts-if(stylo,2-3) load 336104.html # bug 1324669
+load 336104.html
 load 382527-1.html
 load 382778-1.html
 load 402172-1.html
 load 403965-1.xhtml
 load 407074-1.html
 load 407079-1.html
 load 407256-1.html
 load 407277-1.html
--- a/editor/reftests/reftest-stylo.list
+++ b/editor/reftests/reftest-stylo.list
@@ -97,17 +97,17 @@ fails == 462758-grabbers-resizers.html 4
 fails == readwrite-non-editable.html readwrite-non-editable.html
 fails == readwrite-editable.html readwrite-editable.html
 fails == readonly-non-editable.html readonly-non-editable.html
 fails == readonly-editable.html readonly-editable.html
 fails == dynamic-overflow-change.html dynamic-overflow-change.html
 fails == 694880-1.html 694880-1.html
 fails == 694880-2.html 694880-2.html
 fails == 694880-3.html 694880-3.html
-fails == 388980-1.html 388980-1.html
+fails asserts-if(stylo,1) == 388980-1.html 388980-1.html # bug 1324683
 fails needs-focus == spellcheck-superscript-1.html spellcheck-superscript-1.html
 fails == spellcheck-superscript-2.html spellcheck-superscript-2.html
 == 824080-1.html 824080-1.html
 # == 824080-2.html 824080-2.html
 # == 824080-3.html 824080-3.html
 # needs-focus == 824080-2.html 824080-2.html
 # == 824080-4.html 824080-4.html
 # == 824080-5.html 824080-5.html
@@ -129,10 +129,10 @@ fails needs-focus pref(layout.accessible
 == spellcheck-contenteditable-property-dynamic.html spellcheck-contenteditable-property-dynamic.html
 # == spellcheck-contenteditable-property-dynamic-inherit.html spellcheck-contenteditable-property-dynamic-inherit.html
 # == spellcheck-contenteditable-attr-dynamic-override.html spellcheck-contenteditable-attr-dynamic-override.html
 == spellcheck-contenteditable-attr-dynamic-override-inherit.html spellcheck-contenteditable-attr-dynamic-override-inherit.html
 # == spellcheck-contenteditable-property-dynamic-override.html spellcheck-contenteditable-property-dynamic-override.html
 == spellcheck-contenteditable-property-dynamic-override-inherit.html spellcheck-contenteditable-property-dynamic-override-inherit.html
 # == 911201.html 911201.html
 fails needs-focus == 969773.html 969773.html
-fails == 997805.html 997805.html
-fails == 1088158.html 1088158.html
+fails asserts-if(stylo,2) == 997805.html 997805.html # bug 1324671
+fails asserts-if(stylo,1) == 1088158.html 1088158.html # bug 1324671
--- a/gfx/2d/2D.h
+++ b/gfx/2d/2D.h
@@ -348,16 +348,26 @@ public:
   /** This returns false if some event has made this source surface invalid for
    * usage with current DrawTargets. For example in the case of Direct2D this
    * could return false if we have switched devices since this surface was
    * created.
    */
   virtual bool IsValid() const { return true; }
 
   /**
+   * This function will return true if the surface type matches that of a
+   * DataSourceSurface and if GetDataSurface will return the same object.
+   */
+  bool IsDataSourceSurface() const {
+    SurfaceType type = GetType();
+    return type == SurfaceType::DATA ||
+           type == SurfaceType::DATA_SHARED;
+  }
+
+  /**
    * This function will get a DataSourceSurface for this surface, a
    * DataSourceSurface's data can be accessed directly.
    */
   virtual already_AddRefed<DataSourceSurface> GetDataSurface() = 0;
 
   /** Tries to get this SourceSurface's native surface.  This will fail if aType
    * is not the type of this SourceSurface's native surface.
    */
@@ -490,16 +500,34 @@ public:
   }
 
   /**
    * Returns a DataSourceSurface with the same data as this one, but
    * guaranteed to have surface->GetType() == SurfaceType::DATA.
    */
   virtual already_AddRefed<DataSourceSurface> GetDataSurface() override;
 
+  /**
+   * Add the size of the underlying data buffer to the aggregate.
+   */
+  virtual void AddSizeOfExcludingThis(MallocSizeOf aMallocSizeOf,
+                                      size_t& aHeapSizeOut,
+                                      size_t& aNonHeapSizeOut) const
+  {
+  }
+
+  /**
+   * Returns whether or not the data was allocated on the heap. This should
+   * be used to determine if the memory needs to be cleared to 0.
+   */
+  virtual bool OnHeap() const
+  {
+    return true;
+  }
+
 protected:
   bool mIsMapped;
 };
 
 /** This is an abstract object that accepts path segments. */
 class PathSink : public RefCounted<PathSink>
 {
 public:
--- a/gfx/2d/DataSourceSurface.cpp
+++ b/gfx/2d/DataSourceSurface.cpp
@@ -8,14 +8,14 @@
 
 namespace mozilla {
 namespace gfx {
 
 already_AddRefed<DataSourceSurface>
 DataSourceSurface::GetDataSurface()
 {
   RefPtr<DataSourceSurface> surface =
-    (GetType() == SurfaceType::DATA) ? this : new DataSourceSurfaceWrapper(this);
+    IsDataSourceSurface() ? this : new DataSourceSurfaceWrapper(this);
   return surface.forget();
 }
 
 } // namespace gfx
 } // namespace mozilla
--- a/gfx/2d/HelpersD2D.h
+++ b/gfx/2d/HelpersD2D.h
@@ -612,16 +612,21 @@ CreatePartialBitmapForSurface(DataSource
   } else if (rect.x >= 0 && rect.XMost() < size.width) {
     uploadRect.x = rect.x;
     uploadRect.width = rect.width;
   } else if (rect.y >= 0 && rect.YMost() < size.height) {
     uploadRect.y = rect.y;
     uploadRect.height = rect.height;
   }
 
+  if (uploadRect.IsEmpty()) {
+    // Nothing to be drawn.
+    return nullptr;
+  }
+
   if (uploadRect.width <= aRT->GetMaximumBitmapSize() &&
       uploadRect.height <= aRT->GetMaximumBitmapSize()) {
     {
       // Scope to auto-Unmap() |mapping|.
       DataSourceSurface::ScopedMap mapping(aSurface, DataSourceSurface::READ);
       if (MOZ2D_WARN_IF(!mapping.IsMapped())) {
         return nullptr;
       }
--- a/gfx/2d/Logging.h
+++ b/gfx/2d/Logging.h
@@ -460,16 +460,19 @@ public:
           mMessage << "SurfaceType::D2D1_1_IMAGE";
           break;
         case SurfaceType::RECORDING:
           mMessage << "SurfaceType::RECORDING";
           break;
         case SurfaceType::TILED:
           mMessage << "SurfaceType::TILED";
           break;
+        case SurfaceType::DATA_SHARED:
+          mMessage << "SurfaceType::DATA_SHARED";
+          break;
         default:
           mMessage << "Invalid SurfaceType (" << (int)aType << ")";
           break;
       }
     }
     return *this;
   }
 
--- a/gfx/2d/Types.h
+++ b/gfx/2d/Types.h
@@ -24,17 +24,18 @@ enum class SurfaceType : int8_t {
   CAIRO, /* Surface wrapping a cairo surface */
   CAIRO_IMAGE, /* Data surface wrapping a cairo image surface */
   COREGRAPHICS_IMAGE, /* Surface wrapping a CoreGraphics Image */
   COREGRAPHICS_CGCONTEXT, /* Surface wrapping a CG context */
   SKIA, /* Surface wrapping a Skia bitmap */
   DUAL_DT, /* Snapshot of a dual drawtarget */
   D2D1_1_IMAGE, /* A D2D 1.1 ID2D1Image SourceSurface */
   RECORDING, /* Surface used for recording */
-  TILED /* Surface from a tiled DrawTarget */
+  TILED, /* Surface from a tiled DrawTarget */
+  DATA_SHARED, /* Data surface using shared memory */
 };
 
 enum class SurfaceFormat : int8_t {
   // The following values are named to reflect layout of colors in memory, from
   // lowest byte to highest byte. The 32-bit value layout depends on machine
   // endianness.
   //               in-memory            32-bit LE value   32-bit BE value
   B8G8R8A8,     // [BB, GG, RR, AA]     0xAARRGGBB        0xBBGGRRAA
old mode 100644
new mode 100755
--- a/gfx/graphite2/ChangeLog
+++ b/gfx/graphite2/ChangeLog
@@ -1,8 +1,35 @@
+1.3.9
+    . Add Collision COLL_ISSPACE to allow for visible spaces in collision avoidance
+    . Add segment and pass direction information to tracing output
+    . Bug fix rule length testing in 32-bit
+    . Increase slanted margin distances for collision avoidance
+    . Change kerning algorithm to simple outline expansion. Seems to make no visible difference.
+    . Add trace2svg to test tools
+
+1.3.8
+    . Various bug fixes arising from fuzzing
+    . Fix regression that stopped piglatin from working
+    . Make collision avoidance kerning give more regular results
+    . Minor modification to clustering algorithm to handle variable width chars
+
+1.3.7
+    . Bug fixes
+    . Start to deprecate SegCache. This will be going away in a later release.
+
+1.3.6
+    . Bug fixes
+
+1.3.5
+    . Bug fixes
+        . Security bug fix
+        . Fix ARM misalignment problem
+        . Track latest cmake
+
 1.3.4
     . Transition from Mercurial to Git
     . Bug fixes
         . Fix Collision Kerning ignoring some diacritics
         . Handle pass bits 16-31 to speed up fonts with > 16 passes
         . Various minor fuzz bug fixes
         . Make Coverity happy
         . Add GR_FALLTHROUGH macro for clang c++11
--- a/gfx/graphite2/README.mozilla
+++ b/gfx/graphite2/README.mozilla
@@ -1,6 +1,3 @@
-This directory contains the Graphite2 library release 1.3.8 from
-https://github.com/silnrsi/graphite/releases/download/1.3.8/graphite2-minimal-1.3.8.tgz
+This directory contains the Graphite2 library release 1.3.9 from
+https://github.com/silnrsi/graphite/releases/download/1.3.9/graphite2-minimal-1.3.9.tgz
 See gfx/graphite2/moz-gr-update.sh for update procedure.
-
-Cherry-picked post-1.3.8 commit 56157cf9845d13452068c297205f96b946126cc2 to fix
-https://bugzilla.mozilla.org/show_bug.cgi?id=1261135.
--- a/gfx/graphite2/include/graphite2/Font.h
+++ b/gfx/graphite2/include/graphite2/Font.h
@@ -25,17 +25,17 @@
     either version 2 of the License or (at your option) any later version.
 */
 #pragma once
 
 #include "graphite2/Types.h"
 
 #define GR2_VERSION_MAJOR   1
 #define GR2_VERSION_MINOR   3
-#define GR2_VERSION_BUGFIX  8
+#define GR2_VERSION_BUGFIX  9
 
 #ifdef __cplusplus
 extern "C"
 {
 #endif
 
 typedef struct gr_face          gr_face;
 typedef struct gr_font          gr_font;
deleted file mode 100644
--- a/gfx/graphite2/include/graphite2/XmlLog.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/*  GRAPHITE2 LICENSING
-
-    Copyright 2010, SIL International
-    All rights reserved.
-
-    This library is free software; you can redistribute it and/or modify
-    it under the terms of the GNU Lesser General Public License as published
-    by the Free Software Foundation; either version 2.1 of License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-    Lesser General Public License for more details.
-
-    You should also have received a copy of the GNU Lesser General Public
-    License along with this library in the file named "LICENSE".
-    If not, write to the Free Software Foundation, 51 Franklin Street,
-    Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
-    internet at http://www.fsf.org/licenses/lgpl.html.
-
-    Alternatively, the contents of this file may be used under the terms
-    of the Mozilla Public License (http://mozilla.org/MPL) or the GNU
-    General Public License, as published by the Free Software Foundation,
-    either version 2 of the License or (at your option) any later version.
-*/
-#pragma once
-
-#include <graphite2/Types.h>
-#include <stdio.h>
-
-typedef enum {
-    GRLOG_NONE = 0x0,
-    GRLOG_FACE = 0x01,
-    GRLOG_SEGMENT = 0x02,
-    GRLOG_PASS = 0x04,
-    GRLOG_CACHE = 0x08,
-    
-    GRLOG_OPCODE = 0x80,
-    GRLOG_ALL = 0xFF
-} GrLogMask;
-
-// If startGraphiteLogging returns true, logging is enabled and the FILE handle
-// will be closed by graphite when stopGraphiteLogging is called.
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
-GR2_API bool graphite_start_logging(FILE * logFile, GrLogMask mask);		//may not do anthing if disabled in the implementation of the engine.
-GR2_API void graphite_stop_logging();
-
-#ifdef __cplusplus
-}
-#endif
deleted file mode 100644
--- a/gfx/graphite2/src/Bidi.cpp
+++ /dev/null
@@ -1,826 +0,0 @@
-/*  GRAPHITE2 LICENSING
-
-    Copyright 2011, SIL International
-    All rights reserved.
-
-    This library is free software; you can redistribute it and/or modify
-    it under the terms of the GNU Lesser General Public License as published
-    by the Free Software Foundation; either version 2.1 of License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-    Lesser General Public License for more details.
-
-    You should also have received a copy of the GNU Lesser General Public
-    License along with this library in the file named "LICENSE".
-    If not, write to the Free Software Foundation, 51 Franklin Street,
-    suite 500, Boston, MA 02110-1335, USA or visit their web page on the 
-    internet at http://www.fsf.org/licenses/lgpl.html.
-
-Alternatively, the contents of this file may be used under the terms of the
-Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
-License, as published by the Free Software Foundation, either version 2
-of the License or (at your option) any later version.
-*/
-#include "inc/Main.h"
-#include "inc/Slot.h"
-#include "inc/Segment.h"
-#include "inc/Bidi.h"
-
-using namespace graphite2;
-
-enum DirCode {  // Hungarian: dirc
-        Unk        = -1,
-        N          =  0,   // other neutrals (default) - ON
-        L          =  1,   // left-to-right, strong - L
-        R          =  2,   // right-to-left, strong - R
-        AL         =  3,   // Arabic letter, right-to-left, strong, AR
-        EN         =  4,   // European number, left-to-right, weak - EN
-        EUS        =  5,   // European separator, left-to-right, weak - ES
-        ET         =  6,   // European number terminator, left-to-right, weak - ET
-        AN         =  7,   // Arabic number, left-to-right, weak - AN
-        CUS        =  8,   // Common number separator, left-to-right, weak - CS
-        WS         =  9,   // white space, neutral - WS
-        BN         = 10,   // boundary neutral - BN
-
-        LRO        = 11,   // LTR override
-        RLO        = 12,   // RTL override
-        LRE        = 13,   // LTR embedding
-        RLE        = 14,   // RTL embedding
-        PDF        = 15,   // pop directional format
-        NSM        = 16,   // non-space mark
-        LRI        = 17,   // LRI isolate
-        RLI        = 18,   // RLI isolate
-        FSI        = 19,   // FSI isolate
-        PDI        = 20,   // pop isolate
-        OPP        = 21,   // opening paired parenthesis
-        CPP        = 22,   // closing paired parenthesis
-
-        ON = N
-};
-
-enum DirMask {
-        WSflag = int8(1 << 7),     // keep track of WS for eos handling
-        WSMask = int8(~(1 << 7))
-};
-
-inline uint8    BaseClass(Slot *s)   { return s->getBidiClass() & WSMask; }
-
-unsigned int bidi_class_map[] = { 0, 1, 2, 5, 4, 8, 9, 3, 7, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0 };
-// Algorithms based on Unicode reference standard code. Thanks Asmus Freitag.
-
-void resolveWeak(Slot *start, int sos, int eos);
-void resolveNeutrals(Slot *s, int baseLevel, int sos, int eos);
-void processParens(Slot *s, Segment *seg, uint8 aMirror, int level, BracketPairStack &stack);
-
-inline int calc_base_level(Slot *s)
-{
-    int count = 0;
-    for ( ; s; s = s->next())
-    {
-        int cls = s->getBidiClass();
-        if (count)
-        {
-            switch(cls)
-            {
-            case LRI :
-            case RLI :
-            case FSI :
-                ++count;
-                break;
-            case PDI :
-                --count;
-            }
-        }
-        else
-        {
-            switch(cls)
-            {
-            case L :
-                return 0;
-            case R :
-            case AL :
-                return 1;
-            case LRI :
-            case RLI :
-            case FSI :
-                ++count;
-            }
-        }
-    }
-    return 0;
-}
-
-// inline or not?
-void do_resolves(Slot *start, int level, int sos, int eos, int &bmask, Segment *seg, uint8 aMirror, BracketPairStack &stack)
-{
-    if (bmask & 0x1F1178)
-        resolveWeak(start, sos, eos);
-    if (bmask & 0x200000)
-        processParens(start, seg, aMirror, level, stack);
-    if (bmask & 0x7E0361)
-        resolveNeutrals(start, level, sos, eos);
-    bmask = 0;
-}
-
-enum maxs
-{
-    MAX_LEVEL = 125,
-};
-
-// returns where we are up to in processing
-Slot *process_bidi(Slot *start, int level, int prelevel, int &nextLevel, int dirover, int isol, int &cisol, int &isolerr, int &embederr, int init, Segment *seg, uint8 aMirror, BracketPairStack &bstack)
-{
-    int bmask = 0;
-    Slot *s = start;
-    Slot *slast = start;
-    Slot *scurr = 0;
-    Slot *stemp;
-    int lnextLevel = nextLevel;
-    int newLevel;
-    int empty = 1;
-    for ( ; s; s = s ? s->next() : s)
-    {
-        int cls = s->getBidiClass();
-        bmask |= (1 << cls);
-        s->setBidiLevel(level);
-        // we keep s->prev() pointing backwards for PDI repeating
-        
-        switch (cls)
-        {
-        case BN :
-            if (slast == s) slast = s->next();      // ignore if at front of text
-            continue;
-        case LRE :
-        case LRO :
-        case RLE :
-        case RLO :
-            switch (cls)
-            {
-            case LRE :
-            case LRO :
-                newLevel = level + (level & 1 ? 1 : 2);
-                break;
-            case RLE :
-            case RLO :
-                newLevel = level + (level & 1 ? 2 : 1);
-                break;
-            }
-            s->setBidiClass(BN);
-            if (isolerr || newLevel > MAX_LEVEL || embederr)
-            {
-                if (!isolerr) ++embederr;
-                break;
-            }
-            stemp = scurr;
-            if (scurr)
-                scurr->prev(0);         // don't include control in string
-            lnextLevel = newLevel;
-            scurr = s;
-            s->setBidiLevel(newLevel); // to make it vanish
-            // recurse for the new subsequence. A sequence only contains text at the same level
-            s = process_bidi(s->next(), newLevel, level, lnextLevel, cls < LRE, 0, cisol, isolerr, embederr, 0, seg, aMirror, bstack);
-            // s points at PDF or end of sequence
-            // try to keep extending the run and not process it until we have to
-            if (lnextLevel != level || !s)      // if the subsequence really had something in it, or we are at the end of the run
-            {
-                if (slast != scurr)             // process the run now, don't try to extend it
-                {
-                    // process text preceeding embedding
-                    do_resolves(slast, level, (prelevel > level ? prelevel : level) & 1, lnextLevel & 1, bmask, seg, aMirror, bstack);
-                    empty = 0;
-                    nextLevel = level;
-                }
-                else if (lnextLevel != level)   // the subsequence had something
-                {
-                    empty = 0;                  // so we aren't empty either
-                    nextLevel = lnextLevel;     // but since we really are empty, pass back our level from the subsequence
-                }
-                if (s)                          // if still more to process
-                {
-                    prelevel = lnextLevel;      // future text starts out with sos of the higher subsequence
-                    lnextLevel = level;         // and eos is our level
-                }
-                slast = s ? s->next() : s;
-            }
-            else if (stemp)
-                stemp->prev(s);
-            break;
-
-        case PDF :
-            s->setBidiClass(BN);
-            s->prev(0);                         // unstitch us since we skip final stitching code when we return
-            if (isol || isolerr || init)        // boundary error conditions
-                break;
-            if (embederr)
-            {
-                --embederr;
-                break;
-            }
-            if (slast != s)
-            {
-                scurr->prev(0);     // if slast, then scurr. Terminate before here
-                do_resolves(slast, level, level & 1, level & 1, bmask, seg, aMirror, bstack);
-                empty = 0;
-            }
-            if (empty)
-            {
-                nextLevel = prelevel;       // no contents? set our level to that of parent
-                s->setBidiLevel(prelevel);
-            }
-            return s;
-
-        case FSI :
-        case LRI :
-        case RLI :
-            switch (cls)
-            {
-            case FSI :
-                if (calc_base_level(s->next()))
-                    newLevel = level + (level & 1 ? 2 : 1);
-                else
-                    newLevel = level + (level & 1 ? 1 : 2);
-                break;
-            case LRI :
-                newLevel = level + (level & 1 ? 1 : 2);
-                break;
-            case RLI :
-                newLevel = level + (level & 1 ? 2 : 1);
-                break;
-            }
-            if (newLevel > MAX_LEVEL || isolerr)
-            {
-                ++isolerr;
-                s->setBidiClass(ON | WSflag);
-                break;
-            }
-            ++cisol;
-            if (scurr) scurr->prev(s);
-            scurr = s;  // include FSI
-            lnextLevel = newLevel;
-            // recurse for the new sub sequence
-            s = process_bidi(s->next(), newLevel, newLevel, lnextLevel, 0, 1, cisol, isolerr, embederr, 0, seg, aMirror, bstack);
-            // s points at PDI
-            if (s)
-            {
-                bmask |= 1 << BaseClass(s);     // include the PDI in the mask
-                s->setBidiLevel(level);         // reset its level to our level
-            }
-            lnextLevel = level;
-            break;
-
-        case PDI :
-            if (isolerr)
-            {
-                --isolerr;
-                s->setBidiClass(ON | WSflag);
-                break;
-            }
-            if (init || !cisol)
-            {
-                s->setBidiClass(ON | WSflag);
-                break;
-            }
-            embederr = 0;
-            if (!isol)                  // we are in an embedded subsequence, we have to return through all those
-            {
-                if (empty)              // if empty, reset the level to tell embedded parent
-                    nextLevel = prelevel;
-                return s->prev();       // keep working up the stack pointing at this PDI until we get to an isolate entry
-            }
-            else                        // we are terminating an isolate sequence
-            {
-                if (slast != s)         // process any remaining content in this subseqence
-                {
-                    scurr->prev(0);
-                    do_resolves(slast, level, prelevel & 1, level & 1, bmask, seg, aMirror, bstack);
-                }
-                --cisol;                // pop the isol sequence from the stack
-                return s;
-            }
-
-        default :
-            if (dirover)
-                s->setBidiClass((level & 1 ? R : L) | (WSflag * (cls == WS)));
-        }
-        if (s) s->prev(0);      // unstitch us
-        if (scurr)              // stitch in text for processing
-            scurr->prev(s);
-        scurr = s;              // add us to text to process
-    }
-    if (slast != s)
-    {
-        do_resolves(slast, level, (level > prelevel ? level : prelevel) & 1, lnextLevel & 1, bmask, seg, aMirror, bstack);
-        empty = 0;
-    }
-    if (empty || isol)
-        nextLevel = prelevel;
-    return s;
-}
-
-// === RESOLVE WEAK TYPES ================================================
-
-enum bidi_state // possible states
-{
-        xa,             //      arabic letter
-        xr,             //      right leter
-        xl,             //      left letter
-
-        ao,             //      arabic lett. foll by ON
-        ro,             //      right lett. foll by ON
-        lo,             //      left lett. foll by ON
-
-        rt,             //      ET following R
-        lt,             //      ET following L
-
-        cn,             //      EN, AN following AL
-        ra,             //      arabic number foll R
-        re,             //      european number foll R
-        la,             //      arabic number foll L
-        le,             //      european number foll L
-
-        ac,             //      CS following cn
-        rc,             //      CS following ra
-        rs,             //      CS,ES following re
-        lc,             //      CS following la
-        ls,             //      CS,ES following le
-
-        ret,            //      ET following re
-        let,            //      ET following le
-} ;
-
-const bidi_state stateWeak[][10] =
-{
-        //      N,  L,  R,  AN, EN, AL,NSM, CS, ES, ET,
-{ /*xa*/        ao, xl, xr, cn, cn, xa, xa, ao, ao, ao, /* arabic letter          */ },
-{ /*xr*/        ro, xl, xr, ra, re, xa, xr, ro, ro, rt, /* right letter           */ },
-{ /*xl*/        lo, xl, xr, la, le, xa, xl, lo, lo, lt, /* left letter            */ },
-
-{ /*ao*/        ao, xl, xr, cn, cn, xa, ao, ao, ao, ao, /* arabic lett. foll by ON*/ },
-{ /*ro*/        ro, xl, xr, ra, re, xa, ro, ro, ro, rt, /* right lett. foll by ON */ },
-{ /*lo*/        lo, xl, xr, la, le, xa, lo, lo, lo, lt, /* left lett. foll by ON  */ },
-
-{ /*rt*/        ro, xl, xr, ra, re, xa, rt, ro, ro, rt, /* ET following R         */ },
-{ /*lt*/        lo, xl, xr, la, le, xa, lt, lo, lo, lt, /* ET following L         */ },
-
-{ /*cn*/        ao, xl, xr, cn, cn, xa, cn, ac, ao, ao, /* EN, AN following AL    */ },
-{ /*ra*/        ro, xl, xr, ra, re, xa, ra, rc, ro, rt, /* arabic number foll R   */ },
-{ /*re*/        ro, xl, xr, ra, re, xa, re, rs, rs,ret, /* european number foll R */ },
-{ /*la*/        lo, xl, xr, la, le, xa, la, lc, lo, lt, /* arabic number foll L   */ },
-{ /*le*/        lo, xl, xr, la, le, xa, le, ls, ls,let, /* european number foll L */ },
-
-{ /*ac*/        ao, xl, xr, cn, cn, xa, ao, ao, ao, ao, /* CS following cn        */ },
-{ /*rc*/        ro, xl, xr, ra, re, xa, ro, ro, ro, rt, /* CS following ra        */ },
-{ /*rs*/        ro, xl, xr, ra, re, xa, ro, ro, ro, rt, /* CS,ES following re     */ },
-{ /*lc*/        lo, xl, xr, la, le, xa, lo, lo, lo, lt, /* CS following la        */ },
-{ /*ls*/        lo, xl, xr, la, le, xa, lo, lo, lo, lt, /* CS,ES following le     */ },
-
-{ /*ret*/       ro, xl, xr, ra, re, xa,ret, ro, ro,ret, /* ET following re        */ },
-{ /*let*/       lo, xl, xr, la, le, xa,let, lo, lo,let, /* ET following le        */ },
-
-
-};
-
-enum bidi_action // possible actions
-{
-        // primitives
-        IX = 0x100,                     // increment
-        XX = 0xF,                       // no-op
-
-        // actions
-        xxx = (XX << 4) + XX,           // no-op
-        xIx = IX + xxx,                         // increment run
-        xxN = (XX << 4) + ON,           // set current to N
-        xxE = (XX << 4) + EN,           // set current to EN
-        xxA = (XX << 4) + AN,           // set current to AN
-        xxR = (XX << 4) + R,            // set current to R
-        xxL = (XX << 4) + L,            // set current to L
-        Nxx = (ON << 4) + 0xF,          // set run to neutral
-        Axx = (AN << 4) + 0xF,          // set run to AN
-        ExE = (EN << 4) + EN,           // set run to EN, set current to EN
-        NIx = (ON << 4) + 0xF + IX,     // set run to N, increment
-        NxN = (ON << 4) + ON,           // set run to N, set current to N
-        NxR = (ON << 4) + R,            // set run to N, set current to R
-        NxE = (ON << 4) + EN,           // set run to N, set current to EN
-
-        AxA = (AN << 4) + AN,           // set run to AN, set current to AN
-        NxL = (ON << 4) + L,            // set run to N, set current to L
-        LxL = (L << 4) + L,             // set run to L, set current to L
-};
-
-
-const bidi_action actionWeak[][10] =
-{
-    //   N,.. L,   R,   AN,  EN,  AL,  NSM, CS,..ES,  ET,
-{ /*xa*/ xxx, xxx, xxx, xxx, xxA, xxR, xxR, xxN, xxN, xxN, /* arabic letter             */ },
-{ /*xr*/ xxx, xxx, xxx, xxx, xxE, xxR, xxR, xxN, xxN, xIx, /* right leter               */ },
-{ /*xl*/ xxx, xxx, xxx, xxx, xxL, xxR, xxL, xxN, xxN, xIx, /* left letter               */ },
-
-{ /*ao*/ xxx, xxx, xxx, xxx, xxA, xxR, xxN, xxN, xxN, xxN, /* arabic lett. foll by ON   */ },
-{ /*ro*/ xxx, xxx, xxx, xxx, xxE, xxR, xxN, xxN, xxN, xIx, /* right lett. foll by ON    */ },
-{ /*lo*/ xxx, xxx, xxx, xxx, xxL, xxR, xxN, xxN, xxN, xIx, /* left lett. foll by ON     */ },
-
-{ /*rt*/ Nxx, Nxx, Nxx, Nxx, ExE, NxR, xIx, NxN, NxN, xIx, /* ET following R            */ },
-{ /*lt*/ Nxx, Nxx, Nxx, Nxx, LxL, NxR, xIx, NxN, NxN, xIx, /* ET following L            */ },
-
-{ /*cn*/ xxx, xxx, xxx, xxx, xxA, xxR, xxA, xIx, xxN, xxN, /* EN, AN following  AL      */ },
-{ /*ra*/ xxx, xxx, xxx, xxx, xxE, xxR, xxA, xIx, xxN, xIx, /* arabic number foll R      */ },
-{ /*re*/ xxx, xxx, xxx, xxx, xxE, xxR, xxE, xIx, xIx, xxE, /* european number foll R    */ },
-{ /*la*/ xxx, xxx, xxx, xxx, xxL, xxR, xxA, xIx, xxN, xIx, /* arabic number foll L      */ },
-{ /*le*/ xxx, xxx, xxx, xxx, xxL, xxR, xxL, xIx, xIx, xxL, /* european number foll L    */ },
-
-{ /*ac*/ Nxx, Nxx, Nxx, Axx, AxA, NxR, NxN, NxN, NxN, NxN, /* CS following cn           */ },
-{ /*rc*/ Nxx, Nxx, Nxx, Axx, NxE, NxR, NxN, NxN, NxN, NIx, /* CS following ra           */ },
-{ /*rs*/ Nxx, Nxx, Nxx, Nxx, ExE, NxR, NxN, NxN, NxN, NIx, /* CS,ES following re        */ },
-{ /*lc*/ Nxx, Nxx, Nxx, Axx, NxL, NxR, NxN, NxN, NxN, NIx, /* CS following la           */ },
-{ /*ls*/ Nxx, Nxx, Nxx, Nxx, LxL, NxR, NxN, NxN, NxN, NIx, /* CS,ES following le        */ },
-
-{ /*ret*/xxx, xxx, xxx, xxx, xxE, xxR, xxE, xxN, xxN, xxE, /* ET following re           */ },
-{ /*let*/xxx, xxx, xxx, xxx, xxL, xxR, xxL, xxN, xxN, xxL, /* ET following le           */ },
-};
-
-inline uint8    GetDeferredType(bidi_action a)          { return (a >> 4) & 0xF; }
-inline uint8    GetResolvedType(bidi_action a)          { return a & 0xF; }
-inline DirCode  EmbeddingDirection(int l)               { return l & 1 ? R : L; }
-
-// Neutrals
-enum neutral_action
-{
-        // action to resolve previous input
-        nL = L,         // resolve EN to L
-        En = 3 << 4,    // resolve neutrals run to embedding level direction
-        Rn = R << 4,    // resolve neutrals run to strong right
-        Ln = L << 4,    // resolved neutrals run to strong left
-        In = (1<<8),    // increment count of deferred neutrals
-        LnL = (1<<4)+L, // set run and EN to L
-};
-
-// ->prev() here means ->next()
-void SetDeferredRunClass(Slot *s, Slot *sRun, int nval)
-{
-    if (!sRun || s == sRun) return;
-    for (Slot *p = sRun; p != s; p = p->prev())
-        if (p->getBidiClass() == WS) p->setBidiClass(nval | WSflag);
-        else if (BaseClass(p) != BN) p->setBidiClass(nval | (p->getBidiClass() & WSflag));
-}
-
-void SetThisDeferredRunClass(Slot *s, Slot *sRun, int nval)
-{
-    if (!sRun) return;
-    for (Slot *p = sRun, *e = s->prev(); p != e; p = p->prev())
-        if (p->getBidiClass() == WS) p->setBidiClass(nval | WSflag);
-        else if (BaseClass(p) != BN) p->setBidiClass(nval | (p->getBidiClass() & WSflag));
-}
-
-void resolveWeak(Slot *start, int sos, int eos)
-{
-    int state = (sos & 1) ? xr : xl;
-    int cls;
-    Slot *s = start;
-    Slot *sRun = NULL;
-    Slot *sLast = s;
-
-    for ( ; s; s = s->prev())
-    {
-        sLast = s;
-        cls = BaseClass(s);
-        switch (cls)
-        {
-        case BN :
-            if (s == start) start = s->prev();  // skip initial BNs for NSM resolving
-            continue;
-        case LRI :
-        case RLI :
-        case FSI :
-        case PDI :
-            {
-                Slot *snext = s->prev();
-                if (snext && snext->getBidiClass() == NSM)
-                    snext->setBidiClass(ON);
-                s->setBidiClass(ON | WSflag);
-            }
-            break;
-
-        case NSM :
-            if (s == start)
-            {
-                cls = EmbeddingDirection(sos);
-                s->setBidiClass(cls);
-            }
-            break;
-        }
-        
-        bidi_action action = actionWeak[state][bidi_class_map[cls]];
-        int clsRun = GetDeferredType(action);
-        if (clsRun != XX)
-        {
-            SetDeferredRunClass(s, sRun, clsRun);
-            sRun = NULL;
-        }
-        int clsNew = GetResolvedType(action);
-        if (clsNew != XX)
-            s->setBidiClass(clsNew);
-        if (!sRun && (IX & action))
-            sRun = s;
-        state = stateWeak[state][bidi_class_map[cls]];
-    }
-
-    cls = EmbeddingDirection(eos);
-    int clsRun = GetDeferredType(actionWeak[state][bidi_class_map[cls]]);
-    if (clsRun != XX)
-        SetThisDeferredRunClass(sLast, sRun, clsRun);
-}
-
-void processParens(Slot *s, Segment *seg, uint8 aMirror, int level, BracketPairStack &stack)
-{
-    uint8 mask = 0;
-    int8 lastDir = -1;
-    BracketPair *p;
-    for ( ; s; s = s->prev())       // walk the sequence
-    {
-        uint16 ogid = seg->glyphAttr(s->gid(), aMirror) || s->gid();
-        int cls = BaseClass(s);
-        
-        switch(cls)
-        {
-        case OPP :
-            stack.orin(mask);
-            stack.push(ogid, s, lastDir, lastDir != CPP);
-            mask = 0;
-            lastDir = OPP;
-            break;
-        case CPP :
-            stack.orin(mask);
-            p = stack.scan(s->gid());
-            if (!p) break;
-            mask = 0;
-            stack.close(p, s);
-            lastDir = CPP;
-            break;
-        case L :
-            lastDir = L;
-            mask |= 1;
-            break;
-        case R :
-        case AL :
-        case AN :
-        case EN :
-            lastDir = R;
-            mask |= 2;
-        }
-    }
-    if (stack.size())
-    {
-        for (p = stack.start(); p; p =p->next())      // walk the stack
-        {
-            if (p->close() && p->mask())
-            {
-                int dir = (level & 1) + 1;
-                if (p->mask() & dir)
-                { }
-                else if (p->mask() & (1 << (~level & 1)))  // if inside has strong other embedding
-                {
-                    int ldir = p->before();
-                    if ((p->before() == OPP || p->before() == CPP) && p->prev())
-                    {
-                        for (BracketPair *q = p->prev(); q; q = q->prev())
-                        {
-                            ldir = q->open()->getBidiClass();
-                            if (ldir < 3) break;
-                            ldir = q->before();
-                            if (ldir < 3) break;
-                        }
-                        if (ldir > 2) ldir = 0;
-                    }
-                    if (ldir > 0 && (ldir - 1) != (level & 1))     // is dir given opp. to level dir (ldir == R or L)
-                        dir = (~level & 1) + 1;
-                }
-                p->open()->setBidiClass(dir);
-                p->close()->setBidiClass(dir);
-            }
-        }
-        stack.clear();
-    }
-}
-
-int GetDeferredNeutrals(int action, int level)
-{
-        action = (action >> 4) & 0xF;
-        if (action == (En >> 4))
-            return EmbeddingDirection(level);
-        else
-            return action;
-}
-
-int GetResolvedNeutrals(int action)
-{
-        return action & 0xF;
-}
-
-// state values
-enum neutral_state
-{
-        // new temporary class
-        r,  // R and characters resolved to R
-        l,  // L and characters resolved to L
-        rn, // N preceded by right
-        ln, // N preceded by left
-        a,  // AN preceded by left (the abbrev 'la' is used up above)
-        na, // N preceeded by a
-} ;
-
-const uint8 neutral_class_map[] = { 0, 1, 2, 0, 4, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
-
-const int actionNeutrals[][5] =
-{
-// cls= N,   L,  R, AN, EN,        state =
-{       In,  0,  0,  0,  0, },  // r    right
-{       In,  0,  0,  0,  L, },  // l    left
-
-{       In, En, Rn, Rn, Rn, },  // rn   N preceded by right
-{       In, Ln, En, En, LnL, }, // ln   N preceded by left
-
-{       In,  0,  0,  0,  L, },  // a   AN preceded by left
-{       In, En, Rn, Rn, En, },  // na   N  preceded by a
-} ;
-
-const int stateNeutrals[][5] =
-{
-// cls= N,  L,  R,      AN,     EN              state =
-{       rn, l,  r,      r,      r, },           // r   right
-{       ln, l,  r,      a,      l, },           // l   left
-
-{       rn, l,  r,      r,      r, },           // rn  N preceded by right
-{       ln, l,  r,      a,      l, },           // ln  N preceded by left
-
-{       na, l,  r,      a,      l, },           // a  AN preceded by left
-{       na, l,  r,      a,      l, },           // na  N preceded by la
-} ;
-
-void resolveNeutrals(Slot *s, int baseLevel, int sos, int eos)
-{
-    int state = (sos & 1) ? r : l;
-    int cls;
-    Slot *sRun = NULL;
-    Slot *sLast = s;
-    int level = baseLevel;
-
-    for ( ; s; s = s->prev())
-    {
-        sLast = s;
-        cls = BaseClass(s);
-        switch (cls)
-        {
-        case BN :
-            continue;
-        case LRI :
-        case RLI :
-        case FSI :
-            s->setBidiClass(BN | WSflag);
-            continue;
-
-        default :
-            int action = actionNeutrals[state][neutral_class_map[cls]];
-            int clsRun = GetDeferredNeutrals(action, level);
-            if (clsRun != N)
-            {
-                SetDeferredRunClass(s, sRun, clsRun);
-                sRun = NULL;
-            }
-            int clsNew = GetResolvedNeutrals(action);
-            if (clsNew != N)
-                s->setBidiClass(clsNew);
-            if (!sRun && (action & In))
-                sRun = s;
-            state = stateNeutrals[state][neutral_class_map[cls]];
-        }
-    }
-    cls = EmbeddingDirection(eos);
-    int clsRun = GetDeferredNeutrals(actionNeutrals[state][neutral_class_map[cls]], level);
-    if (clsRun != N)
-        SetThisDeferredRunClass(sLast, sRun, clsRun);
-}
-
-const int addLevel[][4] =
-{
-        //  cls = L,    R,      AN,     EN         level =
-/* even */      { 0,    1,      2,      2, },   // EVEN
-/* odd  */      { 1,    0,      1,      1, },   // ODD
-
-};
-
-void resolveImplicit(Slot *s, Segment *seg, uint8 aMirror)
-{
-    bool rtl = seg->dir() & 1;
-    int level = rtl;
-    Slot *slast = 0;
-    for ( ; s; s = s->next())
-    {
-        int cls = BaseClass(s);
-        s->prev(slast);         // restitch the prev() side of the doubly linked list
-        slast = s;
-        if (cls == AN)
-            cls = AL;   // use AL value as the index for AN, no property change
-        if (cls < 5 && cls > 0)
-        {
-            level = s->getBidiLevel();
-            level += addLevel[level & 1][cls - 1];
-            s->setBidiLevel(level);
-        }
-        if (aMirror)
-        {
-            int hasChar = seg->glyphAttr(s->gid(), aMirror + 1);
-            if ( ((level & 1) && (!(seg->dir() & 4) || !hasChar)) 
-              || ((rtl ^ (level & 1)) && (seg->dir() & 4) && hasChar) )
-            {
-                unsigned short g = seg->glyphAttr(s->gid(), aMirror);
-                if (g) s->setGlyph(seg, g);
-            }
-        }
-    }
-}
-
-void resolveWhitespace(int baseLevel, Slot *s)
-{
-    for ( ; s; s = s->prev())
-    {
-        int8 cls = s->getBidiClass();
-        if (cls == WS || (cls & WSflag))
-            s->setBidiLevel(baseLevel);
-        else if (cls != BN)
-            break;
-    }
-}
-
-
-/*
-Stitch two spans together to make another span (with ends tied together).
-If the level is odd then swap the order of the two spans
-*/
-inline
-Slot * join(int level, Slot * a, Slot * b)
-{
-    if (!a) return b;
-    if (level & 1)  { Slot * const t = a; a = b; b = t; }
-    Slot * const t = b->prev();
-    a->prev()->next(b); b->prev(a->prev()); // splice middle
-    t->next(a); a->prev(t);                 // splice ends
-    return a;
-}
-
-/*
-Given the first slot in a run of slots with the same bidi level, turn the run
-into it's own little doubly linked list ring (a span) with the two ends joined together.
-If the run is rtl then reverse its direction.
-Returns the first slot after the span
-*/
-Slot * span(Slot * & cs, const bool rtl)
-{
-    Slot * r = cs, * re = cs; cs = cs->next();
-    if (rtl)
-    {
-        Slot * t = r->next(); r->next(r->prev()); r->prev(t);
-        for (int l = r->getBidiLevel(); cs && (l == cs->getBidiLevel() || cs->getBidiClass() == BN); cs = cs->prev())
-        {
-            re = cs;
-            t = cs->next(); cs->next(cs->prev()); cs->prev(t);
-        }
-        r->next(re);
-        re->prev(r);
-        r = re;
-    }
-    else
-    {
-        for (int l = r->getBidiLevel(); cs && (l == cs->getBidiLevel() || cs->getBidiClass() == BN); cs = cs->next())
-            re = cs;
-        r->prev(re);
-        re->next(r);
-    }
-    if (cs) cs->prev(0);
-    return r;
-}
-
-inline int getlevel(const Slot *cs, const int level)
-{
-    while (cs && cs->getBidiClass() == BN)
-    { cs = cs->next(); }
-    if (cs)
-        return cs->getBidiLevel();
-    else
-        return level;
-}
-
-Slot *resolveOrder(Slot * & cs, const bool reordered, const int level)
-{
-    Slot * r = 0;
-    int ls;
-    while (cs && level <= (ls = getlevel(cs, level) - reordered))
-    {
-        r = join(level, r, level < ls
-                                ? resolveOrder(/* updates */cs, reordered, level+1) // find span of heighest level
-                                : span(/* updates */cs, level & 1));
-    }
-    return r;
-}
--- a/gfx/graphite2/src/Collider.cpp
+++ b/gfx/graphite2/src/Collider.cpp
@@ -301,16 +301,17 @@ bool ShiftCollider::mergeSlot(Segment *s
         const float ts = tx + ty;
         const SlantBox &sb = gc.getBoundingSlantBox(gid);
         const unsigned short tgid = _target->gid();
         const BBox &tbb = gc.getBoundingBBox(tgid);
         const SlantBox &tsb = gc.getBoundingSlantBox(tgid);
         float seq_above_wt = cslot->seqAboveWt();
         float seq_below_wt = cslot->seqBelowWt();
         float seq_valign_wt = cslot->seqValignWt();
+        float lmargin = _margin;
         // if isAfter, invert orderFlags for diagonal orders.
         if (isAfter)
         {
             // invert appropriate bits
             orderFlags ^= (sameClass ? 0x3F : 0x3);
             // consider 2 bits at a time, non overlapping. If both bits set, clear them
             orderFlags = orderFlags ^ ((((orderFlags >> 1) & orderFlags) & 0x15) * 3);
         }
@@ -329,51 +330,55 @@ bool ShiftCollider::mergeSlot(Segment *s
                     vmax = min(min(bb.xa - tbb.xi + sx, sb.da - tsb.di + ty + sd), sb.sa - tsb.si - ty + ss);
                     otmin = tbb.yi + ty;
                     otmax = tbb.ya + ty;
                     omin = bb.yi + sy;
                     omax = bb.ya + sy;
                     torg = _currOffset.x;
                     cmin = _limit.bl.x + torg;
                     cmax = _limit.tr.x - tbb.xi + tbb.xa + torg;
+                    lmargin = _margin;
                     break;
                 case 1 :	// y direction
                     vmin = max(max(bb.yi - tbb.ya + sy, tsb.di - sb.da + tx - sd), sb.si - tsb.sa - tx + ss);
                     vmax = min(min(bb.ya - tbb.yi + sy, tsb.da - sb.di + tx - sd), sb.sa - tsb.si - tx + ss);
                     otmin = tbb.xi + tx;
                     otmax = tbb.xa + tx;
                     omin = bb.xi + sx;
                     omax = bb.xa + sx;
                     torg = _currOffset.y;
                     cmin = _limit.bl.y + torg;
                     cmax = _limit.tr.y - tbb.yi + tbb.ya + torg;
+                    lmargin = _margin;
                     break;
                 case 2 :    // sum - moving along the positively-sloped vector, so the boundaries are the
                             // negatively-sloped boundaries.
                     vmin = max(max(sb.si - tsb.sa + ss, 2 * (bb.yi - tbb.ya + sy) + td), 2 * (bb.xi - tbb.xa + sx) - td);
                     vmax = min(min(sb.sa - tsb.si + ss, 2 * (bb.ya - tbb.yi + sy) + td), 2 * (bb.xa - tbb.xi + sx) - td);
                     otmin = tsb.di + td;
                     otmax = tsb.da + td;
                     omin = sb.di + sd;
                     omax = sb.da + sd;
                     torg = _currOffset.x + _currOffset.y;
                     cmin = _limit.bl.x + _limit.bl.y + torg;
                     cmax = _limit.tr.x + _limit.tr.y - tsb.si + tsb.sa + torg;
+                    lmargin = _margin / ISQRT2;
                     break;
                 case 3 :    // diff - moving along the negatively-sloped vector, so the boundaries are the
                             // positively-sloped boundaries.
                     vmin = max(max(sb.di - tsb.da + sd, 2 * (bb.xi - tbb.xa + sx) - ts), -2 * (bb.ya - tbb.yi + sy) + ts);
                     vmax = min(min(sb.da - tsb.di + sd, 2 * (bb.xa - tbb.xi + sx) - ts), -2 * (bb.yi - tbb.ya + sy) + ts);
                     otmin = tsb.si + ts;
                     otmax = tsb.sa + ts;
                     omin = sb.si + ss;
                     omax = sb.sa + ss;
                     torg = _currOffset.x - _currOffset.y;
                     cmin = _limit.bl.x - _limit.tr.y + torg;
                     cmax = _limit.tr.x - _limit.bl.y - tsb.di + tsb.da + torg;
+                    lmargin = _margin / ISQRT2;
                     break;
                 default :
                     continue;
             }
             
 #if !defined GRAPHITE2_NTRACING
             if (dbgout)
                 dbgout->setenv(1, reinterpret_cast<void *>(-1));
@@ -465,17 +470,17 @@ bool ShiftCollider::mergeSlot(Segment *s
                         removeBox(Rect(Position(bb.xa - tbb.xi + sx, bb.yi - tbb.ya + sy),
                                         Position(xpinf, bb.ya - tbb.yi + sy)), tbb, tsb, org, i);
                         break;
                     default :
                         break;
                 }
             }
 
-            if (vmax < cmin - _margin || vmin > cmax + _margin || omax < otmin - _margin || omin > otmax + _margin)
+            if (vmax < cmin - lmargin || vmin > cmax + lmargin || omax < otmin - lmargin || omin > otmax + lmargin)
                 continue;
 
             // Process sub-boxes that are defined for this glyph.
             // We only need to do this if there was in fact a collision with the main octabox.
             uint8 numsub = gc.numSubBounds(gid);
             if (numsub > 0)
             {
                 bool anyhits = false;
@@ -504,49 +509,49 @@ bool ShiftCollider::mergeSlot(Segment *s
                             break;
                         case 3 :    // diff
                             vmin = max(max(ssb.di-tsb.da+sd, 2*(sbb.xi-tbb.xa+sx)-ts), -2*(sbb.ya-tbb.yi+sy)+ts);
                             vmax = min(min(ssb.da-tsb.di+sd, 2*(sbb.xa-tbb.xi+sx)-ts), -2*(sbb.yi-tbb.ya+sy)+ts);
                             omin = ssb.si + ss;
                             omax = ssb.sa + ss;
                             break;
                     }
-                    if (vmax < cmin - _margin || vmin > cmax + _margin || omax < otmin - _margin || omin > otmax + _margin)
+                    if (vmax < cmin - lmargin || vmin > cmax + lmargin || omax < otmin - lmargin || omin > otmax + lmargin)
                         continue;
 
 #if !defined GRAPHITE2_NTRACING
                     if (dbgout)
                         dbgout->setenv(1, reinterpret_cast<void *>(j));
 #endif
                     if (omin > otmax)
-                        _ranges[i].weightedAxis(i, vmin - _margin, vmax + _margin, 0, 0, 0, 0, 0,
-                                                sqr(_margin - omin + otmax) * _marginWt, false);
+                        _ranges[i].weightedAxis(i, vmin - lmargin, vmax + lmargin, 0, 0, 0, 0, 0,
+                                                sqr(lmargin - omin + otmax) * _marginWt, false);
                     else if (omax < otmin)
-                        _ranges[i].weightedAxis(i, vmin - _margin, vmax + _margin, 0, 0, 0, 0, 0,
-                                                sqr(_margin - otmin + omax) * _marginWt, false);
+                        _ranges[i].weightedAxis(i, vmin - lmargin, vmax + lmargin, 0, 0, 0, 0, 0,
+                                                sqr(lmargin - otmin + omax) * _marginWt, false);
                     else
                         _ranges[i].exclude_with_margins(vmin, vmax, i);
                     anyhits = true;
                 }
                 if (anyhits)
                     isCol = true;
             }
             else // no sub-boxes
             {
 #if !defined GRAPHITE2_NTRACING
                     if (dbgout)
                         dbgout->setenv(1, reinterpret_cast<void *>(-1));
 #endif
                 isCol = true;
                 if (omin > otmax)
-                    _ranges[i].weightedAxis(i, vmin - _margin, vmax + _margin, 0, 0, 0, 0, 0,
-                                            sqr(_margin - omin + otmax) * _marginWt, false);
+                    _ranges[i].weightedAxis(i, vmin - lmargin, vmax + lmargin, 0, 0, 0, 0, 0,
+                                            sqr(lmargin - omin + otmax) * _marginWt, false);
                 else if (omax < otmin)
-                    _ranges[i].weightedAxis(i, vmin - _margin, vmax + _margin, 0, 0, 0, 0, 0,
-                                            sqr(_margin - otmin + omax) * _marginWt, false);
+                    _ranges[i].weightedAxis(i, vmin - lmargin, vmax + lmargin, 0, 0, 0, 0, 0,
+                                            sqr(lmargin - otmin + omax) * _marginWt, false);
                 else
                     _ranges[i].exclude_with_margins(vmin, vmax, i);
 
             }
         }
     }
     bool res = true;
     if (cslot->exclGlyph() > 0 && gc.check(cslot->exclGlyph()) && !isExclusion)
@@ -747,69 +752,69 @@ static float localmin(float al, float au
 {
     if (bl > al)
     { if (bu > au) return bl > x ? bl : x; }
     else if (au > bu) return al > x ? al : x;
     return x;        
 }
 
 // Return the given edge of the glyph at height y, taking any slant box into account.
-static float get_edge(Segment *seg, const Slot *s, const Position &shift, float y, float width, bool isRight)
+static float get_edge(Segment *seg, const Slot *s, const Position &shift, float y, float width, float margin, bool isRight)
 {
     const GlyphCache &gc = seg->getFace()->glyphs();
     unsigned short gid = s->gid();
     float sx = s->origin().x + shift.x;
     float sy = s->origin().y + shift.y;
     uint8 numsub = gc.numSubBounds(gid);
     float res = isRight ? (float)-1e38 : (float)1e38;
 
     if (numsub > 0)
     {
         for (int i = 0; i < numsub; ++i)
         {
             const BBox &sbb = gc.getSubBoundingBBox(gid, i);
             const SlantBox &ssb = gc.getSubBoundingSlantBox(gid, i);
-            if (sy + sbb.yi > y + width / 2 || sy + sbb.ya < y - width / 2)
+            if (sy + sbb.yi - margin > y + width / 2 || sy + sbb.ya + margin < y - width / 2)
                 continue;
             if (isRight)
             {
-                float x = sx + sbb.xa;
+                float x = sx + sbb.xa + margin;
                 if (x > res)
                 {
-                    float td = sx - sy + ssb.da + y;
-                    float ts = sx + sy + ssb.sa - y;
+                    float td = sx - sy + ssb.da + margin + y;
+                    float ts = sx + sy + ssb.sa + margin - y;
                     x = localmax(td - width / 2, td + width / 2,  ts - width / 2, ts + width / 2, x);
                     if (x > res)
                         res = x;
                 }
             }
             else
             {
-                float x = sx + sbb.xi;
+                float x = sx + sbb.xi - margin;
                 if (x < res)
                 {
-                    float td = sx - sy + ssb.di + y;
-                    float ts = sx + sy + ssb.si - y;
+                    float td = sx - sy + ssb.di - margin + y;
+                    float ts = sx + sy + ssb.si - margin - y;
                     x = localmin(td - width / 2, td + width / 2, ts - width / 2, ts + width / 2, x);
                     if (x < res)
                         res = x;
                 }
             }
         }
     }
     else
     {
         const BBox &bb = gc.getBoundingBBox(gid);
         const SlantBox &sb = gc.getBoundingSlantBox(gid);
         float td = sx - sy + y;
         float ts = sx + sy - y;
         if (isRight)
-            res = localmax(td + sb.da - width / 2, td + sb.da + width / 2, ts + sb.sa - width / 2, ts + sb.sa + width / 2, sx + bb.xa);
+            res = localmax(td + sb.da - width / 2, td + sb.da + width / 2, ts + sb.sa - width / 2, ts + sb.sa + width / 2, sx + bb.xa) + margin;
         else
-            res = localmin(td + sb.di - width / 2, td + sb.di + width / 2, ts + sb.si - width / 2, ts + sb.si + width / 2, sx + bb.xi);
+            res = localmin(td + sb.di - width / 2, td + sb.di + width / 2, ts + sb.si - width / 2, ts + sb.si + width / 2, sx + bb.xi) - margin;
     }
     return res;
 }
 
 
 bool KernCollider::initSlot(Segment *seg, Slot *aSlot, const Rect &limit, float margin,
     const Position &currShift, const Position &offsetPrev, int dir,
     float ymin, float ymax, GR_MAYBE_UNUSED json * const dbgout)
@@ -860,16 +865,17 @@ bool KernCollider::initSlot(Segment *seg
             if (numSlices > (int)_edges.size())
                 _edges.insert(_edges.end(), numSlices - _edges.size(), (dir & 1) ? 1e38f : -1e38f);
             else if (numSlices < (int)_edges.size())   // this shouldn't fire since we always grow the range
             {
                 while ((int)_edges.size() > numSlices)
                     _edges.pop_back();
             }
         }
+        goto done;
     }
     numSlices = _edges.size();
 
 #if !defined GRAPHITE2_NTRACING
     // Debugging
     _seg = seg;
     _slotNear.clear();
     _slotNear.insert(_slotNear.begin(), numSlices, NULL);
@@ -891,36 +897,37 @@ bool KernCollider::initSlot(Segment *seg
         int smin = max(0, int((bs.yi + toffset) / _sliceWidth));
         int smax = min(numSlices - 1, int((bs.ya + toffset) / _sliceWidth + 1));
         for (int i = smin; i <= smax; ++i)
         {
             float t;
             float y = _miny - 1 + (i + .5f) * _sliceWidth; // vertical center of slice
             if ((dir & 1) && x < _edges[i])
             {
-                t = get_edge(seg, s, c->shift(), y, _sliceWidth, false);
+                t = get_edge(seg, s, c->shift(), y, _sliceWidth, margin, false);
                 if (t < _edges[i])
                 {
                     _edges[i] = t;
                     if (t < _xbound)
                         _xbound = t;
                 }
             }
             else if (!(dir & 1) && x > _edges[i])
             {
-                t = get_edge(seg, s, c->shift(), y, _sliceWidth, true);
+                t = get_edge(seg, s, c->shift(), y, _sliceWidth, margin, true);
                 if (t > _edges[i])
                 {
                     _edges[i] = t;
                     if (t > _xbound)
                         _xbound = t;
                 }
             }
         }
     }
+    done:
     _mingap = (float)1e38;
     _target = aSlot;
     _margin = margin;
     _currShift = currShift;
     return true;
 }   // end of KernCollider::initSlot
 
 
@@ -941,69 +948,62 @@ bool KernCollider::mergeSlot(Segment *se
         return false;
 
     const float sy = slot->origin().y + currShift.y;
     int smin = max(1, int((bb.bl.y + (1 - _miny + sy)) / _sliceWidth + 1)) - 1;
     int smax = min((int)_edges.size() - 2, int((bb.tr.y + (1 - _miny + sy)) / _sliceWidth + 1)) + 1;
     if (smin > smax)
         return false;
     bool collides = false;
-    float below = smin > 0 ? _edges[smin-1] * rtl : 1e38f;
-    float here = _edges[smin] * rtl;
-    float above = smin < (int)_edges.size() - 1 ? _edges[smin+1] * rtl : 1e38f;
 
     for (int i = smin; i <= smax; ++i)
     {
         float t;
+        float here = _edges[i] * rtl;
         float y = (float)(_miny - 1 + (i + .5f) * _sliceWidth);  // vertical center of slice
-        if (    (x > here - _mingap - currSpace)
-             || (x > below - _mingap - currSpace)
-             || (x > above - _mingap - currSpace))
+        if (    (x > here - _mingap - currSpace) )
         {
             // 2 * currSpace to account for the space that is already separating them and the space we want to add
-            float m = get_edge(seg, slot, currShift, y, _sliceWidth, rtl > 0) * rtl + 2 * currSpace;
-            // Check slices above and below (if any).
-            t = min(min(here, below), above) - m;
+            float m = get_edge(seg, slot, currShift, y, _sliceWidth, 0., rtl > 0) * rtl + 2 * currSpace;
+            t = here - m;
             // _mingap is positive to shrink
             if (t < _mingap)
             {
                 _mingap = t;
                 collides = true;
             }
 #if !defined GRAPHITE2_NTRACING
             // Debugging - remember the closest neighboring edge for this slice.
             if (m > rtl * _nearEdges[i])
             {
                 _slotNear[i] = slot;
                 _nearEdges[i] = m * rtl;
             }
 #endif
         }
-        below = here; here = above;
-        above = i < (int)_edges.size() - 2 ? _edges[i+2] * rtl : 1e38f;
     }
     return collides;   // note that true is not a necessarily reliable value
     
 }   // end of KernCollider::mergeSlot
 
 
 // Return the amount to kern by.
 Position KernCollider::resolve(GR_MAYBE_UNUSED Segment *seg, GR_MAYBE_UNUSED Slot *slot,
-        int dir, float margin, GR_MAYBE_UNUSED json * const dbgout)
+        int dir, GR_MAYBE_UNUSED json * const dbgout)
 {
-    float resultNeeded = (1 - 2 * (dir & 1)) * (_mingap - margin);
+    float resultNeeded = (1 - 2 * (dir & 1)) * _mingap;
+    // float resultNeeded = (1 - 2 * (dir & 1)) * (_mingap - margin);
     float result = min(_limit.tr.x - _offsetPrev.x, max(resultNeeded, _limit.bl.x - _offsetPrev.x));
 
 #if !defined GRAPHITE2_NTRACING
     if (dbgout)
     {
         *dbgout << json::object // slot
                 << "slot" << objectid(dslot(seg, _target))
 				<< "gid" << _target->gid()
-                << "margin" << _margin
                 << "limit" << _limit
                 << "miny" << _miny
                 << "maxy" << _maxy
                 << "slicewidth" << _sliceWidth
                 << "target" << json::object
                     << "origin" << _target->origin()
                     //<< "currShift" << _currShift
                     << "offsetPrev" << _offsetPrev
@@ -1088,8 +1088,12 @@ void SlotCollision::initFromSlot(Segment
 float SlotCollision::getKern(int dir) const
 {
     if ((_flags & SlotCollision::COLL_KERN) != 0)
         return float(_shift.x * ((dir & 1) ? -1 : 1));
     else
     	return 0;
 }
 
+bool SlotCollision::ignore() const
+{
+	return ((flags() & SlotCollision::COLL_IGNORE) || (flags() & SlotCollision::COLL_ISSPACE));
+}
--- a/gfx/graphite2/src/Face.cpp
+++ b/gfx/graphite2/src/Face.cpp
@@ -185,19 +185,20 @@ bool Face::runGraphite(Segment *seg, con
             res &= seg->initCollisions();
         if (res)
             res &= aSilf->runGraphite(seg, aSilf->positionPass(), aSilf->numPasses(), false);
     }
 
 #if !defined GRAPHITE2_NTRACING
     if (dbgout)
 {
-        seg->positionSlots(0, 0, 0, aSilf->dir());
+        seg->positionSlots(0, 0, 0, seg->currdir());
         *dbgout             << json::item
                             << json::close // Close up the passes array
+                << "outputdir" << (seg->currdir() ? "rtl" : "ltr")
                 << "output" << json::array;
         for(Slot * s = seg->first(); s; s = s->next())
             *dbgout     << dslot(seg, s);
         *dbgout         << json::close
                 << "advance" << seg->advance()
                 << "chars"   << json::array;
         for(size_t i = 0, n = seg->charInfoCount(); i != n; ++i)
             *dbgout     << json::flat << *seg->charinfo(i);
deleted file mode 100644
--- a/gfx/graphite2/src/GlyphFaceCache.cpp
+++ /dev/null
@@ -1,149 +0,0 @@
-/*  GRAPHITE2 LICENSING
-
-    Copyright 2010, SIL International
-    All rights reserved.
-
-    This library is free software; you can redistribute it and/or modify
-    it under the terms of the GNU Lesser General Public License as published
-    by the Free Software Foundation; either version 2.1 of License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-    Lesser General Public License for more details.
-
-    You should also have received a copy of the GNU Lesser General Public
-    License along with this library in the file named "LICENSE".
-    If not, write to the Free Software Foundation, 51 Franklin Street, 
-    Suite 500, Boston, MA 02110-1335, USA or visit their web page on the 
-    internet at http://www.fsf.org/licenses/lgpl.html.
-
-Alternatively, the contents of this file may be used under the terms of the
-Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
-License, as published by the Free Software Foundation, either version 2
-of the License or (at your option) any later version.
-*/
-#include "inc/GlyphFaceCache.h"
-#include "graphite2/Font.h"
-#include "inc/Face.h"     //for the tags
-#include "inc/Endian.h"
-
-using namespace graphite2;
-
-/*virtual*/ bool GlyphFaceCacheHeader::initialize(const Face & face, const bool dumb_font)    //return result indicates success. Do not use if failed.
-{
-    if ((m_pLoca = face.getTable(Tag::loca, &m_lLoca)) == NULL) return false;
-    if ((m_pHead = face.getTable(Tag::head)) == NULL) return false;
-    if ((m_pGlyf = face.getTable(Tag::glyf, &m_lGlyf)) == NULL) return false;
-    if ((m_pHmtx = face.getTable(Tag::hmtx, &m_lHmtx)) == NULL) return false;
-    if ((m_pHHea = face.getTable(Tag::hhea)) == NULL) return false;
-
-    const void* pMaxp = face.getTable(Tag::maxp);
-    if (pMaxp == NULL) return false;
-    m_nGlyphs = m_nGlyphsWithGraphics = (unsigned short)TtfUtil::GlyphCount(pMaxp);
-    if (TtfUtil::LocaLookup(m_nGlyphs-1, m_pLoca, m_lLoca, m_pHead) == size_t(-1))
-    	return false; // This will fail if m_nGlyphs is wildly out of range.
-
-    if (!dumb_font)
-    {
-		if ((m_pGlat = face.getTable(Tag::Glat, &m_lGlat)) == NULL) return false;
-		m_fGlat = be::peek<uint32>(m_pGlat);
-		size_t lGloc;
-		if ((m_pGloc = face.getTable(Tag::Gloc, &lGloc)) == NULL) return false;
-		if (lGloc < 6) return false;
-		int version = be::read<uint32>(m_pGloc);
-		if (version != 0x00010000) return false;
-
-		const uint16 locFlags = be::read<uint16>(m_pGloc);
-		m_numAttrs = be::read<uint16>(m_pGloc);
-		if (m_numAttrs > 0x1000) return false;                  // is this hard limit appropriate?
-
-		if (locFlags & 1)
-		{
-			m_locFlagsUse32Bit = true;
-			m_nGlyphsWithAttributes = (unsigned short)((lGloc - 12) / 4);
-		}
-		else
-		{
-			m_locFlagsUse32Bit = false;
-			m_nGlyphsWithAttributes = (unsigned short)((lGloc - 10) / 2);
-		}
-
-		if (m_nGlyphsWithAttributes > m_nGlyphs)
-	        m_nGlyphs = m_nGlyphsWithAttributes;
-    }
-
-    return true;
-}
-
-GlyphFaceCache* GlyphFaceCache::makeCache(const GlyphFaceCacheHeader& hdr)
-{
-    return new (hdr) GlyphFaceCache(hdr);
-}
-
-GlyphFaceCache::GlyphFaceCache(const GlyphFaceCacheHeader& hdr)
-:   GlyphFaceCacheHeader(hdr)
-{
-    unsigned int nGlyphs = numGlyphs();
-    
-    for (unsigned int i = 0; i < nGlyphs; i++)
-    {
-         *glyphPtrDirect(i) = NULL;
-    }
-}
-
-GlyphFaceCache::~GlyphFaceCache()
-{
-    unsigned int nGlyphs = numGlyphs();
-    int deltaPointers = (*glyphPtrDirect(nGlyphs-1u) - *glyphPtrDirect(0u));
-    if ((nGlyphs > 0u) && (deltaPointers == static_cast<int>(nGlyphs - 1)))
-    {
-        for (unsigned int i=0 ; i<nGlyphs; ++i)
-        {
-            GlyphFace *p = *glyphPtrDirect(i);
-            assert (p);
-            p->~GlyphFace();
-        }
-        free (*glyphPtrDirect(0));
-    }
-    else
-    {
-        for (unsigned int i=0 ; i<nGlyphs; ++i)
-        {
-            GlyphFace *p = *glyphPtrDirect(i);
-            if (p)
-            {
-                p->~GlyphFace();
-                free(p);
-            }
-        }
-    }
-}
-
-void GlyphFaceCache::loadAllGlyphs()
-{
-    unsigned int nGlyphs = numGlyphs();
-//    size_t sparse_size = 0;
-    GlyphFace * glyphs = gralloc<GlyphFace>(nGlyphs);
-    for (unsigned short glyphid = 0; glyphid < nGlyphs; glyphid++)
-    {
-        GlyphFace **p = glyphPtrDirect(glyphid);
-        *p = &(glyphs[glyphid]);
-        new(*p) GlyphFace(*this, glyphid);
-//        sparse_size += (*p)->m_attrs._sizeof();
-    }
-//    const size_t flat_size = nGlyphs*(sizeof(uint16*) + sizeof(uint16)*numAttrs());
-//    assert(sparse_size <= flat_size);
-}
-
-/*virtual*/ const GlyphFace *GlyphFaceCache::glyph(unsigned short glyphid) const      //result may be changed by subsequent call with a different glyphid
-{ 
-    GlyphFace **p = glyphPtrDirect(glyphid);
-    if (*p)
-        return *p;
-
-    *p = (GlyphFace*)malloc(sizeof(GlyphFace));
-    new(*p) GlyphFace(*this, glyphid);
-    return *p;
-}
--- a/gfx/graphite2/src/Intervals.cpp
+++ b/gfx/graphite2/src/Intervals.cpp
@@ -54,31 +54,36 @@ inline
 Zones::Exclusion & Zones::Exclusion::operator += (Exclusion const & rhs) {
     c += rhs.c; sm += rhs.sm; smx += rhs.smx; open = false;
     return *this;
 }
 
 inline
 uint8 Zones::Exclusion::outcode(float val) const {
     float p = val;
-    return ((p >= xm) << 1) | (p < x);
+    //float d = std::numeric_limits<float>::epsilon();
+    float d = 0.;
+    return ((p - xm >= d) << 1) | (x - p > d);
 }
 
 void Zones::exclude_with_margins(float xmin, float xmax, int axis) {
     remove(xmin, xmax);
     weightedAxis(axis, xmin-_margin_len, xmin, 0, 0, _margin_weight, xmin-_margin_len, 0, 0, false);
     weightedAxis(axis, xmax, xmax+_margin_len, 0, 0, _margin_weight, xmax+_margin_len, 0, 0, false);
 }
 
 namespace
 {
 
 inline
 bool separated(float a, float b) {
     return a != b;
+    //int exp;
+    //float res = frexpf(fabs(a - b), &exp);
+    //return (*(unsigned int *)(&res) > 4);
     //return std::fabs(a-b) > std::numeric_limits<float>::epsilon(); // std::epsilon may not work. but 0.5 fails exising 64 bit tests
     //return std::fabs(a-b) > 0.5f;
 }
 
 }
 
 void Zones::insert(Exclusion e)
 {
old mode 100644
new mode 100755
--- a/gfx/graphite2/src/Pass.cpp
+++ b/gfx/graphite2/src/Pass.cpp
@@ -518,17 +518,17 @@ void Pass::findNDoRule(Slot * & slot, Ma
         {
             if (fsm.rules.size() != 0)
             {
                 *fsm.dbgout << json::item << json::object;
                 dumpRuleEventConsidered(fsm, *r);
                 if (r != re)
                 {
                     const int adv = doAction(r->rule->action, slot, m);
-                    dumpRuleEventOutput(fsm, m, *r->rule, slot);
+                    dumpRuleEventOutput(fsm, *r->rule, slot);
                     if (r->rule->action->deletes()) fsm.slots.collectGarbage(slot);
                     adjustSlot(adv, slot, fsm.slots);
                     *fsm.dbgout << "cursor" << objectid(dslot(&fsm.slots.segment, slot))
                             << json::close; // Close RuelEvent object
 
                     return;
                 }
                 else
@@ -574,17 +574,17 @@ void Pass::dumpRuleEventConsidered(const
                         << "start" << objectid(dslot(&fsm.slots.segment, input_slot(fsm.slots, -r->rule->preContext)))
                         << "length" << r->rule->sort
                         << json::close  // close "input"
                     << json::close; // close Rule object
     }
 }
 
 
-void Pass::dumpRuleEventOutput(const FiniteStateMachine & fsm, Machine & m, const Rule & r, Slot * const last_slot) const
+void Pass::dumpRuleEventOutput(const FiniteStateMachine & fsm, const Rule & r, Slot * const last_slot) const
 {
     *fsm.dbgout     << json::item << json::flat << json::object
                         << "id"     << &r - m_rules
                         << "failed" << false
                         << "input" << json::flat << json::object
                             << "start" << objectid(dslot(&fsm.slots.segment, input_slot(fsm.slots, 0)))
                             << "length" << r.sort - r.preContext
                             << json::close // close "input"
@@ -592,17 +592,17 @@ void Pass::dumpRuleEventOutput(const Fin
                 << json::close // close considered array
                 << "output" << json::object
                     << "range" << json::flat << json::object
                         << "start"  << objectid(dslot(&fsm.slots.segment, input_slot(fsm.slots, 0)))
                         << "end"    << objectid(dslot(&fsm.slots.segment, last_slot))
                     << json::close // close "input"
                     << "slots"  << json::array;
     const Position rsb_prepos = last_slot ? last_slot->origin() : fsm.slots.segment.advance();
-    fsm.slots.segment.positionSlots(0, 0, 0, m.slotMap().dir());
+    fsm.slots.segment.positionSlots(0, 0, 0, fsm.slots.segment.currdir());
 
     for(Slot * slot = output_slot(fsm.slots, 0); slot != last_slot; slot = slot->next())
         *fsm.dbgout     << dslot(&fsm.slots.segment, slot);
     *fsm.dbgout         << json::close  // close "slots"
                     << "postshift"  << (last_slot ? last_slot->origin() : fsm.slots.segment.advance()) - rsb_prepos
                 << json::close;         // close "output" object
 
 }
@@ -874,18 +874,21 @@ bool Pass::collisionKern(Segment *seg, i
 
     for (Slot *s = seg->first(); s; s = s->next())
     {
         if (!gc.check(s->gid()))
             return false;
         const SlotCollision * c = seg->collisionInfo(s);
         const Rect &bbox = seg->theGlyphBBoxTemporary(s->gid());
         float y = s->origin().y + c->shift().y;
-        ymax = max(y + bbox.tr.y, ymax);
-        ymin = min(y + bbox.bl.y, ymin);
+        if (!(c->flags() & SlotCollision::COLL_ISSPACE))
+        {
+            ymax = max(y + bbox.tr.y, ymax);
+            ymin = min(y + bbox.bl.y, ymin);
+        }
         if (start && (c->flags() & (SlotCollision::COLL_KERN | SlotCollision::COLL_FIX))
                         == (SlotCollision::COLL_KERN | SlotCollision::COLL_FIX))
             resolveKern(seg, s, start, dir, ymin, ymax, dbgout);
         if (c->flags() & SlotCollision::COLL_END)
             start = NULL;
         if (c->flags() & SlotCollision::COLL_START)
             start = s;
     }
@@ -957,18 +960,18 @@ bool Pass::resolveCollisions(Segment *se
         base = base->attachedTo();
     Position zero(0., 0.);
     
     // Look for collisions with the neighboring glyphs.
     for (nbor = start; nbor; nbor = isRev ? nbor->prev() : nbor->next())
     {
         SlotCollision *cNbor = seg->collisionInfo(nbor);
         bool sameCluster = nbor->isChildOf(base);
-        if (nbor != slotFix         // don't process if this is the slot of interest
-                      && !(cNbor->flags() & SlotCollision::COLL_IGNORE)    // don't process if ignoring
+        if (nbor != slotFix         						// don't process if this is the slot of interest
+                      && !(cNbor->ignore())    				// don't process if ignoring
                       && (nbor == base || sameCluster       // process if in the same cluster as slotFix
                             || !inKernCluster(seg, nbor)    // or this cluster is not to be kerned
                             || (rtl ^ ignoreForKern))       // or it comes before(ltr) or after(rtl)
                       && (!isRev    // if processing forwards then good to merge otherwise only:
                             || !(cNbor->flags() & SlotCollision::COLL_FIX)     // merge in immovable stuff
                             || ((cNbor->flags() & SlotCollision::COLL_KERN) && !sameCluster)     // ignore other kernable clusters
                             || (cNbor->flags() & SlotCollision::COLL_ISCOL))   // test against other collided glyphs
                       && !coll.mergeSlot(seg, nbor, cNbor->shift(), !ignoreForKern, sameCluster, collides, false, dbgout))
@@ -1047,31 +1050,31 @@ float Pass::resolveKern(Segment *seg, Sl
     for (nbor = slotFix->next(); nbor; nbor = nbor->next())
     {
         if (nbor->isChildOf(base))
             continue;
         if (!gc.check(nbor->gid()))
             return 0.;
         const Rect &bb = seg->theGlyphBBoxTemporary(nbor->gid());
         SlotCollision *cNbor = seg->collisionInfo(nbor);
-        if (bb.bl.y == 0.f && bb.tr.y == 0.f)
+        if ((bb.bl.y == 0.f && bb.tr.y == 0.f) || (cNbor->flags() & SlotCollision::COLL_ISSPACE))
         {
             if (m_kernColls == InWord)
                 break;
             // Add space for a space glyph.
             currSpace += nbor->advance();
             ++space_count;
         }
         else
         {
             space_count = 0; 
             float y = nbor->origin().y + cNbor->shift().y;
             ymax = max(y + bb.tr.y, ymax);
             ymin = min(y + bb.bl.y, ymin);
-            if (nbor != slotFix && !(cNbor->flags() & SlotCollision::COLL_IGNORE))
+            if (nbor != slotFix && !cNbor->ignore())
             {
                 seenEnd = true;
                 if (!isInit)
                 {
                     if (!coll.initSlot(seg, slotFix, cFix->limit(), cFix->margin(),
                                     cFix->shift(), cFix->offset(), dir, ymin, ymax, dbgout))
                         return 0.;
                     isInit = true;
@@ -1084,17 +1087,17 @@ float Pass::resolveKern(Segment *seg, Sl
             if (seenEnd && space_count < 2)
                 break;
             else
                 seenEnd = true;
         }
     }
     if (collides)
     {
-        Position mv = coll.resolve(seg, slotFix, dir, cFix->margin(), dbgout);
+        Position mv = coll.resolve(seg, slotFix, dir, dbgout);
         coll.shift(mv, dir);
         Position delta = slotFix->advancePos() + mv - cFix->shift();
         slotFix->advance(delta);
         cFix->setShift(mv);
         return mv.x;
     }
     return 0.;
 }
deleted file mode 100644
--- a/gfx/graphite2/src/Rule.cpp
+++ /dev/null
@@ -1,31 +0,0 @@
-/*  GRAPHITE2 LICENSING
-
-    Copyright 2011, SIL International
-    All rights reserved.
-
-    This library is free software; you can redistribute it and/or modify
-    it under the terms of the GNU Lesser General Public License as published
-    by the Free Software Foundation; either version 2.1 of License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-    Lesser General Public License for more details.
-
-    You should also have received a copy of the GNU Lesser General Public
-    License along with this library in the file named "LICENSE".
-    If not, write to the Free Software Foundation, 51 Franklin Street, 
-    Suite 500, Boston, MA 02110-1335, USA or visit their web page on the 
-    internet at http://www.fsf.org/licenses/lgpl.html.
-
-Alternatively, the contents of this file may be used under the terms of the
-Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
-License, as published by the Free Software Foundation, either version 2
-of the License or (at your option) any later version.
-*/
-
-#include "inc/Rule.h"
-#include "inc/Segment.h"
-
-using namespace graphite2;
--- a/gfx/graphite2/src/Segment.cpp
+++ b/gfx/graphite2/src/Segment.cpp
@@ -407,18 +407,19 @@ void Segment::linkClusters(Slot *s, Slot
     }
 }
 
 Position Segment::positionSlots(const Font *font, Slot * iStart, Slot * iEnd, bool isRtl, bool isFinal)
 {
     Position currpos(0., 0.);
     float clusterMin = 0.;
     Rect bbox;
+    bool reorder = (currdir() != isRtl);
 
-    if (currdir() != isRtl)
+    if (reorder)
     {
         Slot *temp;
         reverseSlots();
         temp = iStart;
         iStart = iEnd;
         iEnd = temp;
     }
     if (!iStart)    iStart = m_first;
@@ -438,16 +439,18 @@ Position Segment::positionSlots(const Fo
     else
     {
         for (Slot * s = iStart, * const end = iEnd->next(); s && s != end; s = s->next())
         {
             if (s->isBase())
                 currpos = s->finalise(this, font, currpos, bbox, 0, clusterMin = currpos.x, isRtl, isFinal);
         }
     }
+    if (reorder)
+        reverseSlots();
     return currpos;
 }
 
 
 void Segment::associateChars(int offset, int numChars)
 {
     int i = 0, j = 0;
     CharInfo *c, *cend;
--- a/gfx/graphite2/src/Silf.cpp
+++ b/gfx/graphite2/src/Silf.cpp
@@ -379,19 +379,22 @@ bool Silf::runGraphite(Segment *seg, uin
     {
         // bidi and mirroring
         if (i == lbidi)
         {
 #if !defined GRAPHITE2_NTRACING
             if (dbgout)
             {
                 *dbgout << json::item << json::object
+//							<< "pindex" << i   // for debugging
                             << "id"     << -1
+                            << "slotsdir" << (seg->currdir() ? "rtl" : "ltr")
+                            << "passdir" << (m_dir & 1 ? "rtl" : "ltr")
                             << "slots"  << json::array;
-                seg->positionSlots(0, 0, 0, m_dir);
+                seg->positionSlots(0, 0, 0, seg->currdir());
                 for(Slot * s = seg->first(); s; s = s->next())
                     *dbgout     << dslot(seg, s);
                 *dbgout         << json::close
                             << "rules"  << json::array << json::close
                             << json::close;
             }
 #endif
             if (seg->currdir() != (m_dir & 1))
@@ -403,19 +406,22 @@ bool Silf::runGraphite(Segment *seg, uin
         --lastPass;
         continue;
         }
 
 #if !defined GRAPHITE2_NTRACING
         if (dbgout)
         {
             *dbgout << json::item << json::object
+//						<< "pindex" << i   // for debugging
                         << "id"     << i+1
+                        << "slotsdir" << (seg->currdir() ? "rtl" : "ltr")
+                        << "passdir" << ((m_dir & 1) ^ m_passes[i].reverseDir() ? "rtl" : "ltr")
                         << "slots"  << json::array;
-            seg->positionSlots(0, 0, 0, m_dir);
+            seg->positionSlots(0, 0, 0, seg->currdir());
             for(Slot * s = seg->first(); s; s = s->next())
                 *dbgout     << dslot(seg, s);
             *dbgout         << json::close;
         }
 #endif
 
         // test whether to reorder, prepare for positioning
         bool reverse = (lbidi == 0xFF) && (seg->currdir() != ((m_dir & 1) ^ m_passes[i].reverseDir()));
deleted file mode 100644
--- a/gfx/graphite2/src/XmlTraceLog.cpp
+++ /dev/null
@@ -1,219 +0,0 @@
-/*  GRAPHITE2 LICENSING
-
-    Copyright 2010, SIL International
-    All rights reserved.
-
-    This library is free software; you can redistribute it and/or modify
-    it under the terms of the GNU Lesser General Public License as published
-    by the Free Software Foundation; either version 2.1 of License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-    Lesser General Public License for more details.
-
-    You should also have received a copy of the GNU Lesser General Public
-    License along with this library in the file named "LICENSE".
-    If not, write to the Free Software Foundation, 51 Franklin Street, 
-    Suite 500, Boston, MA 02110-1335, USA or visit their web page on the 
-    internet at http://www.fsf.org/licenses/lgpl.html.
-
-Alternatively, the contents of this file may be used under the terms of the
-Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
-License, as published by the Free Software Foundation, either version 2
-of the License or (at your option) any later version.
-*/
-
-#include <cstring>
-#include <cstdarg>
-#include "Main.h"
-#include "XmlTraceLog.h"
-
-
-using namespace graphite2;
-
-#ifndef DISABLE_TRACING
-
-/*static*/ XmlTraceLog XmlTraceLog::sm_NullLog(NULL, NULL, GRLOG_NONE);
-XmlTraceLog * XmlTraceLog::sLog = &sm_NullLog;
-
-XmlTraceLog::XmlTraceLog(FILE * file, const char * ns, GrLogMask logMask)
-                         : m_file(file), m_depth(0), m_mask(logMask)
-{
-    if (!m_file) return;
-    int deep = 0;
-#ifdef ENABLE_DEEP_TRACING
-    deep = 1;
-#endif
-    fprintf(m_file, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<%s xmlns=\"%s\" mask=\"%x\" deep=\"%d\">",
-            xmlTraceLogElements[ElementTopLevel].mName, ns, logMask, deep);
-    m_elementStack[m_depth++] = ElementTopLevel;
-    m_elementEmpty = true;
-    m_inElement = false;
-    m_lastNodeText = false;
-}
-
-XmlTraceLog::~XmlTraceLog()
-{
-    if (m_file && m_file != stdout && m_file != stderr)
-    {
-        assert(m_depth == 1);
-        while (m_depth > 0)
-        {
-            closeElement(m_elementStack[m_depth-1]);
-        }
-        fclose(m_file);
-        m_file = NULL;
-    }
-}
-
-void XmlTraceLog::addSingleElement(XmlTraceLogElement eId, const int value)
-{
-    if (!m_file) return;
-    if (m_inElement)
-    {
-        if (xmlTraceLogElements[m_elementStack[m_depth-1]].mFlags & m_mask)
-            fprintf(m_file, ">");
-    }
-    if (xmlTraceLogElements[eId].mFlags & m_mask)
-    {
-        if (!m_lastNodeText)
-        {
-            fprintf(m_file, "\n");
-            for (size_t i = 0; i < m_depth; i++)
-            {
-                fprintf(m_file, " ");
-            }
-        }
-        fprintf(m_file, "<%s val=\"%d\"/>", xmlTraceLogElements[eId].mName, value);
-    }
-    m_inElement = false;
-    m_lastNodeText = false;
-}
-    
-void XmlTraceLog::writeElementArray(XmlTraceLogElement eId, XmlTraceLogAttribute aId, int16 values [], size_t length)
-{
-    if (!m_file) return;
-    if (xmlTraceLogElements[eId].mFlags & m_mask)
-    {
-        if(m_inElement && xmlTraceLogElements[m_elementStack[m_depth-1]].mFlags & m_mask)
-        {
-            fprintf(m_file, ">");
-            m_inElement = false;
-        }
-        // line break after 5 columns
-        for (size_t i = 0; i < length; i++)
-        {
-            if (i % 5 == 0)
-            {
-                fprintf(m_file, "\n");
-                for (size_t j = 0; j < m_depth; j++)
-                {
-                    fprintf(m_file, " ");
-                }
-            }
-            fprintf(m_file, "<%s index=\"%d\" %s=\"%d\"/>", xmlTraceLogElements[eId].mName, int(i),
-                xmlTraceLogAttributes[aId], (int)values[i]);
-        }
-    }
-}
-
-void XmlTraceLog::writeText(const char * utf8)
-{
-    if (!m_file) return;
-    if (m_inElement)
-    {
-        if (xmlTraceLogElements[m_elementStack[m_depth-1]].mFlags & m_mask)
-        {
-            fprintf(m_file, ">");
-        }
-        m_inElement = false;
-    }
-    if (xmlTraceLogElements[m_elementStack[m_depth-1]].mFlags & m_mask)
-    {
-        escapeIfNeeded(utf8);
-    }
-    m_lastNodeText = true;
-}
-
-void XmlTraceLog::writeUnicode(const uint32 code)
-{
-    if (!m_file) return;
-    if (m_inElement)
-    {
-        if (xmlTraceLogElements[m_elementStack[m_depth-1]].mFlags & m_mask)
-        {
-            fprintf(m_file, ">");
-        }
-        m_inElement = false;
-    }
-    if (xmlTraceLogElements[m_elementStack[m_depth-1]].mFlags & m_mask)
-    {
-        fprintf(m_file, "&#x%02x;", code);
-    }
-    m_lastNodeText = true;
-}
-
-void XmlTraceLog::escapeIfNeeded(const char * data)
-{
-    size_t length = strlen(data);
-    for (size_t i = 0; i < length; i++)
-    {
-        switch (data[i])
-        {
-            case '<':
-                fprintf(m_file, "&lt;");
-                break;
-            case '>':
-                fprintf(m_file, "&gt;");
-                break;
-            case '&':
-                fprintf(m_file, "&amp;");
-                break;
-            case '"':
-                fprintf(m_file, "&#34;");
-                break;
-            default:
-                fprintf(m_file, "%c", data[i]);
-        }
-    }
-}
-
-static const int MAX_MSG_LEN = 1024;
-
-void XmlTraceLog::error(const char * msg, ...)
-{
-    if (!m_file) return;
-    openElement(ElementError);
-    va_list args;
-    va_start(args, msg);
-    char buffer[MAX_MSG_LEN];
-#ifndef NDEBUG
-    int len =
-#endif
-        vsnprintf(buffer, MAX_MSG_LEN, msg, args);
-    assert(len + 1 < MAX_MSG_LEN);
-    writeText(buffer);
-    va_end(args);
-    closeElement(ElementError);
-}
-
-void XmlTraceLog::warning(const char * msg, ...)
-{
-    if (!m_file) return;
-    openElement(ElementWarning);
-    va_list args;
-    va_start(args, msg);
-    char buffer[MAX_MSG_LEN];
-#ifndef NDEBUG
-    int len =
-#endif
-        vsnprintf(buffer, MAX_MSG_LEN, msg, args);
-    assert(len + 1 < MAX_MSG_LEN);
-    writeText(buffer);
-    va_end(args);
-    closeElement(ElementWarning);
-}
-
-#endif		//!DISABLE_TRACING
deleted file mode 100644
--- a/gfx/graphite2/src/XmlTraceLogTags.cpp
+++ /dev/null
@@ -1,169 +0,0 @@
-/*  GRAPHITE2 LICENSING
-
-    Copyright 2010, SIL International
-    All rights reserved.
-
-    This library is free software; you can redistribute it and/or modify
-    it under the terms of the GNU Lesser General Public License as published
-    by the Free Software Foundation; either version 2.1 of License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-    Lesser General Public License for more details.
-
-    You should also have received a copy of the GNU Lesser General Public
-    License along with this library in the file named "LICENSE".
-    If not, write to the Free Software Foundation, 51 Franklin Street, 
-    Suite 500, Boston, MA 02110-1335, USA or visit their web page on the 
-    internet at http://www.fsf.org/licenses/lgpl.html.
-
-Alternatively, the contents of this file may be used under the terms of the
-Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
-License, as published by the Free Software Foundation, either version 2
-of the License or (at your option) any later version.
-*/
-#include "Main.h"
-#include "XmlTraceLogTags.h"
-
-
-using namespace graphite2;
-
-#ifndef DISABLE_TRACING
-
-
-// start this at same line number as in XmlTraceLogTags.h
-const XmlTraceLogTag graphite2::xmlTraceLogElements[NumElements] = {
-    XmlTraceLogTag("Graphite2Log", GRLOG_ALL),
-    XmlTraceLogTag("Face", GRLOG_FACE | GRLOG_PASS),
-    XmlTraceLogTag("Glyphs", GRLOG_FACE),
-    XmlTraceLogTag("GlyphFace", GRLOG_FACE),
-    XmlTraceLogTag("Attr", GRLOG_FACE),
-    XmlTraceLogTag("Silf", GRLOG_FACE | GRLOG_PASS),
-    XmlTraceLogTag("SilfSub", GRLOG_FACE | GRLOG_PASS),
-    XmlTraceLogTag("Pass", GRLOG_FACE | GRLOG_PASS),
-    XmlTraceLogTag("Pseudo", GRLOG_FACE | GRLOG_PASS),
-    XmlTraceLogTag("ClassMap", GRLOG_FACE | GRLOG_PASS),
-    XmlTraceLogTag("LookupClass", GRLOG_FACE | GRLOG_PASS),
-    XmlTraceLogTag("Lookup", GRLOG_FACE | GRLOG_PASS),
-    XmlTraceLogTag("Range", GRLOG_PASS),
-    XmlTraceLogTag("RuleMap", GRLOG_PASS),
-    XmlTraceLogTag("Rule", GRLOG_PASS),
-    XmlTraceLogTag("StartState", GRLOG_PASS),
-    XmlTraceLogTag("StateTransitions", GRLOG_PASS),
-    XmlTraceLogTag("TR", GRLOG_PASS),
-    XmlTraceLogTag("TD", GRLOG_PASS),
-    XmlTraceLogTag("Constraint", GRLOG_PASS),
-    XmlTraceLogTag("Constraints", GRLOG_PASS),
-    XmlTraceLogTag("Actions", GRLOG_PASS),
-    XmlTraceLogTag("Action", GRLOG_PASS),
-    XmlTraceLogTag("Features", GRLOG_PASS),
-    XmlTraceLogTag("Feature", GRLOG_PASS),
-    XmlTraceLogTag("FeatureSetting", GRLOG_PASS),
-    XmlTraceLogTag("Segment", GRLOG_SEGMENT),
-    XmlTraceLogTag("Slot", GRLOG_SEGMENT),
-    XmlTraceLogTag("Text", GRLOG_SEGMENT),
-    XmlTraceLogTag("OpCode", GRLOG_OPCODE),
-    XmlTraceLogTag("TestRule", GRLOG_OPCODE),
-    XmlTraceLogTag("DoRule", GRLOG_OPCODE),
-    XmlTraceLogTag("RunPass", GRLOG_OPCODE),
-    XmlTraceLogTag("Params", GRLOG_OPCODE),
-    XmlTraceLogTag("Push", GRLOG_OPCODE),
-    XmlTraceLogTag("SubSeg", GRLOG_SEGMENT),
-    XmlTraceLogTag("SegCache", GRLOG_CACHE),
-    XmlTraceLogTag("SegCacheEntry", GRLOG_CACHE),
-    XmlTraceLogTag("Glyph", GRLOG_CACHE),
-    XmlTraceLogTag("PassResult", GRLOG_OPCODE),
-
-    XmlTraceLogTag("Error", GRLOG_ALL),
-    XmlTraceLogTag("Warning", GRLOG_ALL)
-    // Nothing corresponds to NumElements
-};
-
-
-
-// start this at same line number as in XmlTraceLogTags.h
-const char * graphite2::xmlTraceLogAttributes[NumAttributes] = {
-    "index",
-    "version",
-    "major",
-    "minor",
-    "num",
-    "glyphId",
-    "advance",
-    "advanceX",
-    "advanceY",
-    "attrId",
-    "attrVal",
-    "compilerMajor",
-    "compilerMinor",
-    "numPasses",//AttrNumPasses,
-    "subPass",//AttrSubPass,
-    "posPass",//AttrPosPass,
-    "justPass",//AttrJustPass,
-    "bidiPass",//AttrBidiPass,
-    "preContext",//AttrPreContext,
-    "postContext",//AttrPostContext,
-    "pseudoGlyph",//AttrPseudoGlyph,
-    "breakWeight",//AttrBreakWeight,
-    "directionality",//AttrDirectionality,
-    "numJustLevels",//AttrNumJustLevels,
-    "numLigCompAttr",//AttrLigComp,
-    "numUserDefinedAttr",//AttrUserDefn,
-    "maxNumLigComp",//AttrNumLigComp,
-    "numCriticalFeatures",//AttrNumCritFeatures,
-    "numScripts",//AttrNumScripts
-    "lineBreakglyph",//,AttrLBGlyph,
-    "numPseudo",
-    "numClasses",
-    "numLinear",
-    "passId",//AttrPassId,
-    "flags",//AttrFlags,
-    "maxRuleLoop",//AttrMaxRuleLoop,
-    "maxRuleContext",//AttrMaxRuleContext,
-    "maxBackup",//AttrMaxBackup,
-    "numRules",//AttrNumRules,
-    "numRows",//AttrNumRows,
-    "numTransitionStates",//AttrNumTransition,
-    "numSuccessStates",//AttrNumSuccess,
-    "numColumns",//AttrNumColumns,
-    "numRanges",//AttrNumRanges,
-    "minPrecontext",//AttrMinPrecontext,
-    "maxPrecontext",//AttrMaxPrecontext,
-    "firstId",
-    "lastId",
-    "colId",
-    "successId",
-    "ruleId",
-    "contextLength",
-    "state",
-    "value",
-    "sortKey",
-    "precontext",
-    "action",
-    "actionCode",
-    "arg1",
-    "arg2",
-    "arg3",
-    "arg4",
-    "arg5",
-    "arg6",
-    "arg7",
-    "arg8",
-    "label",
-    "length",
-    "x",
-    "y",
-    "before",
-    "after",
-    "encoding",
-    "name",
-    "result",
-    "default",
-    "accessCount",
-    "lastAccess",
-    "misses"
-};
-
-#endif
deleted file mode 100644
--- a/gfx/graphite2/src/inc/Bidi.h
+++ /dev/null
@@ -1,126 +0,0 @@
-/*  GRAPHITE2 LICENSING
-
-    Copyright 2013, SIL International
-    All rights reserved.
-
-    This library is free software; you can redistribute it and/or modify
-    it under the terms of the GNU Lesser General Public License as published
-    by the Free Software Foundation; either version 2.1 of License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-    Lesser General Public License for more details.
-
-    You should also have received a copy of the GNU Lesser General Public
-    License along with this library in the file named "LICENSE".
-    If not, write to the Free Software Foundation, 51 Franklin Street,
-    Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
-    internet at http://www.fsf.org/licenses/lgpl.html.
-
-Alternatively, the contents of this file may be used under the terms of the
-Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
-License, as published by the Free Software Foundation, either version 2
-of the License or (at your option) any later version.
-*/
-#pragma once
-
-namespace graphite2
-{
-
-class BracketPair
-{
-public:
-    BracketPair(uint16 g, Slot *s, uint8 b, BracketPair *p, BracketPair *l) : _open(s), _close(0), _parent(p), _next(0), _prev(l), _gid(g), _mask(0), _before(b) {};
-    uint16 gid() const { return _gid; }
-    Slot *open() const { return _open; }
-    Slot *close() const { return _close; }
-    uint8 mask() const { return _mask; }
-    int8 before() const { return _before; }
-    BracketPair *parent() const { return _parent; }
-    void close(Slot *s) { _close = s; }
-    BracketPair *next() const { return _next; }
-    BracketPair *prev() const { return _prev; }
-    void next(BracketPair *n) { _next = n; }
-    void orin(uint8 m) { _mask |= m; }
-private:
-    Slot        *   _open;          // Slot of opening paren
-    Slot        *   _close;         // Slot of closing paren
-    BracketPair *   _parent;        // pair this pair is in or NULL
-    BracketPair *   _next;          // next pair along the string
-    BracketPair *   _prev;          // pair that closed last before we opened
-    uint16          _gid;           // gid of closing paren
-    uint8           _mask;          // bitmap (2 bits) of directions within the pair
-    int8            _before;        // most recent strong type (L, R, OPP, CPP)
-};
-
-class BracketPairStack
-{
-public:
-    BracketPairStack(int s) : _stack(grzeroalloc<BracketPair>(s)), _ip(_stack - 1), _top(0), _last(0), _lastclose(0), _size(s) {}
-    ~BracketPairStack() { free(_stack); }
-
-public:
-    BracketPair *scan(uint16 gid);
-    void close(BracketPair *tos, Slot *s);
-    BracketPair *push(uint16 gid, Slot *pos, uint8 before, int prevopen);
-    void orin(uint8 mask);
-    void clear() { _ip = _stack - 1; _top = 0; _last = 0; _lastclose = 0; }
-    int size() const { return _size; }
-    BracketPair *start() const { return _stack; }
-
-    CLASS_NEW_DELETE
-
-private:
-
-    BracketPair *_stack;        // start of storage
-    BracketPair *_ip;           // where to add the next pair
-    BracketPair *_top;          // current parent
-    BracketPair *_last;         // end of next() chain
-    BracketPair *_lastclose;    // last pair to close
-    int          _size;         // capacity
-};
-
-inline BracketPair *BracketPairStack::scan(uint16 gid)
-{
-    BracketPair *res = _top;
-    while (res >= _stack)
-    {
-        if (res->gid() == gid)
-            return res;
-        res = res->parent();
-    }
-    return 0;
-}
-
-inline void BracketPairStack::close(BracketPair *tos, Slot *s) 
-{
-    for ( ; _last && _last != tos && !_last->close(); _last = _last->parent())
-    { }
-    tos->close(s);
-    _last->next(NULL);
-    _lastclose = tos;
-    _top = tos->parent();
-}
-
-inline BracketPair *BracketPairStack::push(uint16 gid, Slot *pos, uint8 before, int prevopen)
-{
-    if (++_ip - _stack < _size && _stack)
-    {
-        ::new (_ip) BracketPair(gid, pos, before, _top, prevopen ? _last : _lastclose);
-        if (_last) _last->next(_ip);
-        _last = _ip;
-    }
-    _top = _ip;
-    return _ip;
-}
-
-inline void BracketPairStack::orin(uint8 mask)
-{
-    BracketPair *t = _top;
-    for ( ; t; t = t->parent())
-        t->orin(mask);
-}
-
-}
--- a/gfx/graphite2/src/inc/Collider.h
+++ b/gfx/graphite2/src/inc/Collider.h
@@ -49,17 +49,18 @@ public:
     //  COLL_TESTONLY = 0,  // default - test other glyphs for collision with this one, but don't move this one
         COLL_FIX = 1,       // fix collisions involving this glyph
         COLL_IGNORE = 2,    // ignore this glyph altogether
         COLL_START = 4,     // start of range of possible collisions
         COLL_END = 8,       // end of range of possible collisions
         COLL_KERN = 16,     // collisions with this glyph are fixed by adding kerning space after it
         COLL_ISCOL = 32,    // this glyph has a collision
         COLL_KNOWN = 64,    // we've figured out what's happening with this glyph
-        COLL_TEMPLOCK = 128,    // Lock glyphs that have been given priority positioning
+        COLL_ISSPACE = 128,		// treat this glyph as a space with regard to kerning
+        COLL_TEMPLOCK = 256,    // Lock glyphs that have been given priority positioning
         ////COLL_JUMPABLE = 128,    // moving glyphs may jump this stationary glyph in any direction - DELETE
         ////COLL_OVERLAP = 256,    // use maxoverlap to restrict - DELETE
     };
     
     // Behavior for the collision.order attribute. To GDL this is an enum, to us it's a bitfield, with only 1 bit set
     // Allows for easier inversion.
     enum {
         SEQ_ORDER_LEFTDOWN = 1,
@@ -88,16 +89,17 @@ public:
     SLOTCOLSETINTPROP(seqAboveXoff, setSeqAboveXoff)
     SLOTCOLSETUINTPROP(seqAboveWt, setSeqAboveWt)
     SLOTCOLSETINTPROP(seqBelowXlim, setSeqBelowXlim)
     SLOTCOLSETUINTPROP(seqBelowWt, setSeqBelowWt)
     SLOTCOLSETUINTPROP(seqValignHt, setSeqValignHt)
     SLOTCOLSETUINTPROP(seqValignWt, setSeqValignWt)
 
     float getKern(int dir) const;
+    bool ignore() const;
     
 private:
     Rect        _limit;
     Position    _shift;     // adjustment within the given pass
     Position    _offset;    // total adjustment for collisions
     Position    _exclOffset;
     uint16		_margin;
     uint16		_marginWt;
@@ -186,17 +188,17 @@ class KernCollider
 {
 public:
     KernCollider(json *dbg);
     ~KernCollider() throw() { };
     bool initSlot(Segment *seg, Slot *aSlot, const Rect &constraint, float margin,
             const Position &currShift, const Position &offsetPrev, int dir,
             float ymin, float ymax, json * const dbgout);
     bool mergeSlot(Segment *seg, Slot *slot, const Position &currShift, float currSpace, int dir, json * const dbgout);
-    Position resolve(Segment *seg, Slot *slot, int dir, float margin, json * const dbgout);
+    Position resolve(Segment *seg, Slot *slot, int dir, json * const dbgout);
     void shift(const Position &mv, int dir);
 
     CLASS_NEW_DELETE;
 
 private:
     Slot *  _target;        // the glyph to fix
     Rect    _limit;
     float   _margin;
deleted file mode 100644
--- a/gfx/graphite2/src/inc/GlyphFaceCache.h
+++ /dev/null
@@ -1,103 +0,0 @@
-/*  GRAPHITE2 LICENSING
-
-    Copyright 2010, SIL International
-    All rights reserved.
-
-    This library is free software; you can redistribute it and/or modify
-    it under the terms of the GNU Lesser General Public License as published
-    by the Free Software Foundation; either version 2.1 of License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-    Lesser General Public License for more details.
-
-    You should also have received a copy of the GNU Lesser General Public
-    License along with this library in the file named "LICENSE".
-    If not, write to the Free Software Foundation, 51 Franklin Street, 
-    Suite 500, Boston, MA 02110-1335, USA or visit their web page on the 
-    internet at http://www.fsf.org/licenses/lgpl.html.
-
-Alternatively, the contents of this file may be used under the terms of the
-Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
-License, as published by the Free Software Foundation, either version 2
-of the License or (at your option) any later version.
-*/
-#pragma once
-
-#include "inc/GlyphFace.h"
-#include "graphite2/Font.h"
-
-namespace graphite2 {
-
-class Segment;
-class Face;
-class FeatureVal;
-
-
-class GlyphFaceCacheHeader
-{
-public:
-    bool initialize(const Face & face, const bool dumb_font);    //return result indicates success. Do not use if failed.
-    unsigned short numGlyphs() const { return m_nGlyphs; }
-    unsigned short numAttrs() const { return m_numAttrs; }
-
-private:
-friend class Face;
-friend class GlyphFace;
-    const byte* m_pHead,
-    		  * m_pHHea,
-    		  * m_pHmtx,
-    		  * m_pGlat,
-    		  * m_pGloc,
-    		  * m_pGlyf,
-    		  * m_pLoca;
-    size_t		m_lHmtx,
-    			m_lGlat,
-    			m_lGlyf,
-    			m_lLoca;
-
-    uint32			m_fGlat;
-    unsigned short 	m_numAttrs,					// number of glyph attributes per glyph
-    				m_nGlyphsWithGraphics,		//i.e. boundary box and advance
-    				m_nGlyphsWithAttributes,
-    				m_nGlyphs;					// number of glyphs in the font. Max of the above 2.
-    bool 			m_locFlagsUse32Bit;
-};
-
-class GlyphFaceCache : public GlyphFaceCacheHeader
-{
-public:
-    static GlyphFaceCache* makeCache(const GlyphFaceCacheHeader& hdr /*, EGlyphCacheStrategy requested */);
-
-    GlyphFaceCache(const GlyphFaceCacheHeader& hdr);
-    ~GlyphFaceCache();
-
-    const GlyphFace *glyphSafe(unsigned short glyphid) const { return glyphid<numGlyphs()?glyph(glyphid):NULL; }
-    uint16 glyphAttr(uint16 gid, uint8 gattr) const { if (gattr>=numAttrs()) return 0; const GlyphFace*p=glyphSafe(gid); return p?p->getAttr(gattr):0; }
-
-    void * operator new (size_t s, const GlyphFaceCacheHeader& hdr)
-    {
-        return malloc(s + sizeof(GlyphFace*)*hdr.numGlyphs());
-    }
-    // delete in case an exception is thrown in constructor
-    void operator delete(void* p, const GlyphFaceCacheHeader& ) throw()
-    {
-        free(p);
-    }
-
-    const GlyphFace *glyph(unsigned short glyphid) const;      //result may be changed by subsequent call with a different glyphid
-    void loadAllGlyphs();
-
-    CLASS_NEW_DELETE
-    
-private:
-    GlyphFace **glyphPtrDirect(unsigned short glyphid) const { return (GlyphFace **)((const char*)(this)+sizeof(GlyphFaceCache)+sizeof(GlyphFace*)*glyphid);}
-
-private:      //defensive
-    GlyphFaceCache(const GlyphFaceCache&);
-    GlyphFaceCache& operator=(const GlyphFaceCache&);
-};
-
-} // namespace graphite2
--- a/gfx/graphite2/src/inc/Pass.h
+++ b/gfx/graphite2/src/inc/Pass.h
@@ -69,17 +69,17 @@ private:
                      const uint16 * o_constraint, const byte *constraint_data, 
                      const uint16 * o_action, const byte * action_data,
                      Face &, enum passtype pt, Error &e);
     bool    readStates(const byte * starts, const byte * states, const byte * o_rule_map, Face &, Error &e);
     bool    readRanges(const byte * ranges, size_t num_ranges, Error &e);
     uint16  glyphToCol(const uint16 gid) const;
     bool    runFSM(FiniteStateMachine & fsm, Slot * slot) const;
     void    dumpRuleEventConsidered(const FiniteStateMachine & fsm, const RuleEntry & re) const;
-    void    dumpRuleEventOutput(const FiniteStateMachine & fsm, vm::Machine & m, const Rule & r, Slot * os) const;
+    void    dumpRuleEventOutput(const FiniteStateMachine & fsm, const Rule & r, Slot * os) const;
     void    adjustSlot(int delta, Slot * & slot_out, SlotMap &) const;
     bool    collisionShift(Segment *seg, int dir, json * const dbgout) const;
     bool    collisionKern(Segment *seg, int dir, json * const dbgout) const;
     bool    collisionFinish(Segment *seg, GR_MAYBE_UNUSED json * const dbgout) const;
     bool    resolveCollisions(Segment *seg, Slot *slot, Slot *start, ShiftCollider &coll, bool isRev,
                      int dir, bool &moved, bool &hasCol, json * const dbgout) const;
     float   resolveKern(Segment *seg, Slot *slot, Slot *start, int dir,
                      float &ymin, float &ymax, json *const dbgout) const;
deleted file mode 100644
--- a/gfx/graphite2/src/inc/Shrinker.h
+++ /dev/null
@@ -1,119 +0,0 @@
-/*  Copyright (c) 2012, Siyuan Fu <fusiyuan2010@gmail.com>
-    Copyright (c) 2015, SIL International
-    All rights reserved.
-    
-    Redistribution and use in source and binary forms, with or without
-    modification, are permitted provided that the following conditions are met:
-    
-    1. Redistributions of source code must retain the above copyright notice,
-       this list of conditions and the following disclaimer.
-    
-    2. Redistributions in binary form must reproduce the above copyright
-       notice, this list of conditions and the following disclaimer in the
-       documentation and/or other materials provided with the distribution.
-    
-    3. Neither the name of the copyright holder nor the names of its
-       contributors may be used to endorse or promote products derived from
-       this software without specific prior written permission.
-    
-    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-    AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
-    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
-    ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 
-    LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
-    CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
-    SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
-    INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
-    CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
-    ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
-    POSSIBILITY OF SUCH DAMAGE.
-*/
-
-#pragma once
-
-#include <cassert>
-#include <cstddef>
-#include <cstring>
-
-#include <iterator>
-
-//the code from LZ4
-#if (GCC_VERSION >= 302) || (__INTEL_COMPILER >= 800) || defined(__clang__)
-# define expect(expr,value)    (__builtin_expect ((expr),(value)) )
-#else
-# define expect(expr,value)    (expr)
-#endif
-#define likely(expr)     expect((expr) != 0, 1)
-#define unlikely(expr)   expect((expr) != 0, 0)
-////////////////////
-
-
-namespace
-{
-
-#if defined(_MSC_VER)
-typedef unsigned __int8 u8;
-typedef unsigned __int16 u16;
-typedef unsigned __int32 u32;
-typedef unsigned __int64 u64;
-#else
-#include <stdint.h>
-typedef uint8_t u8;
-typedef uint16_t u16;
-typedef uint32_t u32;
-typedef uint64_t u64;
-#endif
-
-ptrdiff_t const     MINMATCH  = 4;
-
-template<int S>
-inline 
-void unaligned_copy(void * d, void const * s) {
-  ::memcpy(d, s, S);
-}
-
-inline
-u8 * memcpy_nooverlap(u8 * d, u8 const * s, size_t n) {
-    size_t const WS = sizeof(unsigned long);
-    u8 const * e = s + n;
-    do 
-    {
-        unaligned_copy<WS>(d, s);
-        d += WS;
-        s += WS;
-    }
-    while (s < e);
-    d-=(s-e);
-    
-    return d;
-}
-
-
-inline
-u8 * memcpy_nooverlap_surpass(u8 * d, u8 const * s, size_t n) {
-    size_t const WS = sizeof(unsigned long);
-    size_t wn = n/WS;
-    while (wn--) 
-    {
-        unaligned_copy<WS>(d, s);
-        d += WS;
-        s += WS;
-    }
-    n &= WS-1;
-    while (n--) {*d++ = *s++; }
-    
-    return d;
-}
-
-
-inline 
-u8 * memcpy_(u8 * d, u8 const * s, size_t n) {
-    if (likely(d>s+sizeof(unsigned long)))
-        return memcpy_nooverlap(d,s,n);
-    else while (n--) *d++ = *s++;
-    return d;
-}
-
-} // end of anonymous namespace
-
-
old mode 100644
new mode 100755
--- a/gfx/graphite2/src/moz.build
+++ b/gfx/graphite2/src/moz.build
@@ -18,17 +18,16 @@ if CONFIG['GNU_CC']:
     ]
 else:
     UNIFIED_SOURCES += [
         'call_machine.cpp'
     ]
 
 # This should contain all of the _SOURCES from files.mk, except *_machine.cpp
 UNIFIED_SOURCES += [
-    'Bidi.cpp',
     'CachedFace.cpp',
     'CmapCache.cpp',
     'Code.cpp',
     'Collider.cpp',
     'Decompressor.cpp',
     'Face.cpp',
     'FeatureMap.cpp',
     'FileFace.cpp',
--- a/gfx/layers/LayersLogging.cpp
+++ b/gfx/layers/LayersLogging.cpp
@@ -343,16 +343,18 @@ AppendToString(std::stringstream& aStrea
   case SurfaceType::DUAL_DT:
     aStream << "SurfaceType::DUAL_DT"; break;
   case SurfaceType::D2D1_1_IMAGE:
     aStream << "SurfaceType::D2D1_1_IMAGE"; break;
   case SurfaceType::RECORDING:
     aStream << "SurfaceType::RECORDING"; break;
   case SurfaceType::TILED:
     aStream << "SurfaceType::TILED"; break;
+  case SurfaceType::DATA_SHARED:
+    aStream << "SurfaceType::DATA_SHARED"; break;
   default:
     NS_ERROR("unknown surface type");
     aStream << "???";
   }
   aStream << sfx;
 }
 
 
new file mode 100644
--- /dev/null
+++ b/gfx/layers/SourceSurfaceSharedData.cpp
@@ -0,0 +1,140 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * 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 "SourceSurfaceSharedData.h"
+
+#include "mozilla/Likely.h"
+#include "mozilla/Types.h" // for decltype
+
+namespace mozilla {
+namespace gfx {
+
+bool
+SourceSurfaceSharedData::Init(const IntSize &aSize,
+                              int32_t aStride,
+                              SurfaceFormat aFormat)
+{
+  mSize = aSize;
+  mStride = aStride;
+  mFormat = aFormat;
+
+  size_t len = GetAlignedDataLength();
+  mBuf = new SharedMemoryBasic();
+  if (NS_WARN_IF(!mBuf->Create(len)) ||
+      NS_WARN_IF(!mBuf->Map(len))) {
+    mBuf = nullptr;
+    return false;
+  }
+
+  return true;
+}
+
+void
+SourceSurfaceSharedData::GuaranteePersistance()
+{
+  // Shared memory is not unmapped until we release SourceSurfaceSharedData.
+}
+
+void
+SourceSurfaceSharedData::AddSizeOfExcludingThis(MallocSizeOf aMallocSizeOf,
+                                                size_t& aHeapSizeOut,
+                                                size_t& aNonHeapSizeOut) const
+{
+  if (mBuf) {
+    aNonHeapSizeOut += GetAlignedDataLength();
+  }
+}
+
+uint8_t*
+SourceSurfaceSharedData::GetDataInternal() const
+{
+  mMutex.AssertCurrentThreadOwns();
+
+  // If we have an old buffer lingering, it is because we get reallocated to
+  // get a new handle to share, but there were still active mappings.
+  if (MOZ_UNLIKELY(mOldBuf)) {
+    MOZ_ASSERT(mMapCount > 0);
+    MOZ_ASSERT(mFinalized);
+    return static_cast<uint8_t*>(mOldBuf->memory());
+  }
+  return static_cast<uint8_t*>(mBuf->memory());
+}
+
+nsresult
+SourceSurfaceSharedData::ShareToProcess(base::ProcessId aPid,
+                                        SharedMemoryBasic::Handle& aHandle)
+{
+  MutexAutoLock lock(mMutex);
+
+  if (mClosed) {
+    return NS_ERROR_NOT_AVAILABLE;
+  }
+
+  bool shared = mBuf->ShareToProcess(aPid, &aHandle);
+  if (MOZ_UNLIKELY(!shared)) {
+    return NS_ERROR_FAILURE;
+  }
+
+  return NS_OK;
+}
+
+void
+SourceSurfaceSharedData::CloseHandleInternal()
+{
+  mMutex.AssertCurrentThreadOwns();
+
+  if (mClosed) {
+    return;
+  }
+
+  if (mFinalized && mShared) {
+    mBuf->CloseHandle();
+    mClosed = true;
+  }
+}
+
+bool
+SourceSurfaceSharedData::ReallocHandle()
+{
+  MutexAutoLock lock(mMutex);
+  MOZ_ASSERT(mClosed);
+  MOZ_ASSERT(mFinalized);
+
+  size_t len = GetAlignedDataLength();
+  RefPtr<SharedMemoryBasic> buf = new SharedMemoryBasic();
+  if (NS_WARN_IF(!buf->Create(len)) ||
+      NS_WARN_IF(!buf->Map(len))) {
+    return false;
+  }
+
+  size_t copyLen = GetDataLength();
+  memcpy(buf->memory(), mBuf->memory(), copyLen);
+  buf->Protect(static_cast<char*>(buf->memory()), len, RightsRead);
+
+  if (mMapCount > 0 && !mOldBuf) {
+    mOldBuf = Move(mBuf);
+  }
+  mBuf = Move(buf);
+  mClosed = false;
+  mShared = false;
+  return true;
+}
+
+void
+SourceSurfaceSharedData::Finalize()
+{
+  MutexAutoLock lock(mMutex);
+  MOZ_ASSERT(!mClosed);
+  MOZ_ASSERT(!mFinalized);
+
+  size_t len = GetAlignedDataLength();
+  mBuf->Protect(static_cast<char*>(mBuf->memory()), len, RightsRead);
+
+  mFinalized = true;
+  CloseHandleInternal();
+}
+
+} // namespace gfx
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/gfx/layers/SourceSurfaceSharedData.h
@@ -0,0 +1,168 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * 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_GFX_SOURCESURFACESHAREDDATA_H_
+#define MOZILLA_GFX_SOURCESURFACESHAREDDATA_H_
+
+#include "mozilla/gfx/2D.h"
+#include "mozilla/Mutex.h"
+#include "mozilla/ipc/SharedMemoryBasic.h"
+
+namespace mozilla {
+namespace gfx {
+
+/**
+ * This class is used to wrap shared (as in process) data buffers used by a
+ * source surface.
+ */
+class SourceSurfaceSharedData final : public DataSourceSurface
+{
+  typedef mozilla::ipc::SharedMemoryBasic SharedMemoryBasic;
+
+public:
+  MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(SourceSurfaceSharedData, override)
+
+  SourceSurfaceSharedData()
+    : mMutex("SourceSurfaceSharedData")
+    , mStride(0)
+    , mMapCount(0)
+    , mFormat(SurfaceFormat::UNKNOWN)
+    , mClosed(false)
+    , mFinalized(false)
+    , mShared(false)
+  {
+  }
+
+  bool Init(const IntSize &aSize,
+            int32_t aStride,
+            SurfaceFormat aFormat);
+
+  uint8_t* GetData() override
+  {
+    MutexAutoLock lock(mMutex);
+    return GetDataInternal();
+  }
+
+  int32_t Stride() override { return mStride; }
+
+  SurfaceType GetType() const override { return SurfaceType::DATA_SHARED; }
+  IntSize GetSize() const override { return mSize; }
+  SurfaceFormat GetFormat() const override { return mFormat; }
+
+  void GuaranteePersistance() override;
+
+  void AddSizeOfExcludingThis(MallocSizeOf aMallocSizeOf,
+                              size_t& aHeapSizeOut,
+                              size_t& aNonHeapSizeOut) const override;
+
+  bool OnHeap() const override
+  {
+    return false;
+  }
+
+  /**
+   * Although Map (and Moz2D in general) isn't normally threadsafe,
+   * we want to allow it for SourceSurfaceSharedData since it should
+   * always be fine (for reading at least).
+   *
+   * This is the same as the base class implementation except using
+   * mMapCount instead of mIsMapped since that breaks for multithread.
+   *
+   * Additionally if a reallocation happened while there were active
+   * mappings, then we guarantee that GetData will continue to return
+   * the same data pointer by retaining the old shared buffer until
+   * the last mapping is freed via Unmap.
+   */
+  bool Map(MapType, MappedSurface *aMappedSurface) override
+  {
+    MutexAutoLock lock(mMutex);
+    ++mMapCount;
+    aMappedSurface->mData = GetDataInternal();
+    aMappedSurface->mStride = mStride;
+    return true;
+  }
+
+  void Unmap() override
+  {
+    MutexAutoLock lock(mMutex);
+    MOZ_ASSERT(mMapCount > 0);
+    if (--mMapCount == 0) {
+      mOldBuf = nullptr;
+    }
+  }
+
+  /**
+   * Get a handle to share to another process for this buffer. Returns:
+   *   NS_OK -- success, aHandle is valid.
+   *   NS_ERROR_NOT_AVAILABLE -- handle was closed, need to reallocate.
+   *   NS_ERROR_FAILURE -- failed to create a handle to share.
+   */
+  nsresult ShareToProcess(base::ProcessId aPid,
+                          SharedMemoryBasic::Handle& aHandle);
+
+  /**
+   * Indicates the buffer is not expected to be shared with any more processes.
+   * May release the handle if possible (see CloseHandleInternal). */
+  void FinishedSharing()
+  {
+    MutexAutoLock lock(mMutex);
+    mShared = true;
+    CloseHandleInternal();
+  }
+
+  /**
+   * Allocate a new shared memory buffer so that we can get a new handle for
+   * sharing to new processes. ShareToProcess must have failed with
+   * NS_ERROR_NOT_AVAILABLE in order for this to be safe to call. Returns true
+   * if the operation succeeds. If it fails, there is no state change.
+   */
+  bool ReallocHandle();
+
+  /**
+   * Indicates we have finished writing to the buffer and it may be marked as
+   * read only. May release the handle if possible (see CloseHandleInternal).
+   */
+  void Finalize();
+
+private:
+  ~SourceSurfaceSharedData() override
+  {
+    MOZ_ASSERT(mMapCount == 0);
+  }
+
+  uint8_t* GetDataInternal() const;
+
+  size_t GetDataLength() const
+  {
+    return static_cast<size_t>(mStride) * mSize.height;
+  }
+
+  size_t GetAlignedDataLength() const
+  {
+    return mozilla::ipc::SharedMemory::PageAlignedSize(GetDataLength());
+  }
+
+  /**
+   * Attempt to close the handle. Only if the buffer has been both finalized
+   * and we have completed sharing will it be released.
+   */
+  void CloseHandleInternal();
+
+  Mutex mMutex;
+  int32_t mStride;
+  int32_t mMapCount;
+  IntSize mSize;
+  RefPtr<SharedMemoryBasic> mBuf;
+  RefPtr<SharedMemoryBasic> mOldBuf;
+  SurfaceFormat mFormat;
+  bool mClosed : 1;
+  bool mFinalized : 1;
+  bool mShared : 1;
+};
+
+} // namespace gfx
+} // namespace mozilla
+
+#endif /* MOZILLA_GFX_SOURCESURFACESHAREDDATA_H_ */
new file mode 100644
--- /dev/null
+++ b/gfx/layers/SourceSurfaceVolatileData.cpp
@@ -0,0 +1,52 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * 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 "SourceSurfaceVolatileData.h"
+
+#include "gfxAlphaRecovery.h"
+#include "mozilla/Likely.h"
+#include "mozilla/Types.h" // for decltype
+
+namespace mozilla {
+namespace gfx {
+
+bool
+SourceSurfaceVolatileData::Init(const IntSize &aSize,
+                                int32_t aStride,
+                                SurfaceFormat aFormat)
+{
+  mSize = aSize;
+  mStride = aStride;
+  mFormat = aFormat;
+
+  size_t alignment = size_t(1) << gfxAlphaRecovery::GoodAlignmentLog2();
+  mVBuf = new VolatileBuffer();
+  if (MOZ_UNLIKELY(!mVBuf->Init(aStride * aSize.height, alignment))) {
+    mVBuf = nullptr;
+    return false;
+  }
+
+  return true;
+}
+
+void
+SourceSurfaceVolatileData::GuaranteePersistance()
+{
+  MOZ_ASSERT_UNREACHABLE("Should use SourceSurfaceRawData wrapper!");
+}
+
+void
+SourceSurfaceVolatileData::AddSizeOfExcludingThis(MallocSizeOf aMallocSizeOf,
+                                                  size_t& aHeapSizeOut,
+                                                  size_t& aNonHeapSizeOut) const
+{
+  if (mVBuf) {
+    aHeapSizeOut += mVBuf->HeapSizeOfExcludingThis(aMallocSizeOf);
+    aNonHeapSizeOut += mVBuf->NonHeapSizeOfExcludingThis();
+  }
+}
+
+} // namespace gfx
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/gfx/layers/SourceSurfaceVolatileData.h
@@ -0,0 +1,108 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * 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_GFX_SOURCESURFACEVOLATILEDATA_H_
+#define MOZILLA_GFX_SOURCESURFACEVOLATILEDATA_H_
+
+#include "mozilla/gfx/2D.h"
+#include "mozilla/Mutex.h"
+#include "mozilla/VolatileBuffer.h"
+
+namespace mozilla {
+namespace gfx {
+
+/**
+ * This class is used to wrap volatile data buffers used for source surfaces.
+ * The Map and Unmap semantics are used to guarantee that the volatile data
+ * buffer is not freed by the operating system while the surface is in active
+ * use. If GetData is expected to return a non-null value without a
+ * corresponding Map call (and verification of the result), the surface data
+ * should be wrapped in a temporary SourceSurfaceRawData with a ScopedMap
+ * closure.
+ */
+class SourceSurfaceVolatileData : public DataSourceSurface
+{
+public:
+  MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(SourceSurfaceVolatileData, override)
+
+  SourceSurfaceVolatileData()
+    : mMutex("SourceSurfaceVolatileData")
+    , mStride(0)
+    , mMapCount(0)
+    , mFormat(SurfaceFormat::UNKNOWN)
+  {
+  }
+
+  bool Init(const IntSize &aSize,
+            int32_t aStride,
+            SurfaceFormat aFormat);
+
+  uint8_t *GetData() override { return mVBufPtr; }
+  int32_t Stride() override { return mStride; }
+
+  SurfaceType GetType() const override { return SurfaceType::DATA; }
+  IntSize GetSize() const override { return mSize; }
+  SurfaceFormat GetFormat() const override { return mFormat; }
+
+  void GuaranteePersistance() override;
+
+  void AddSizeOfExcludingThis(MallocSizeOf aMallocSizeOf,
+                              size_t& aHeapSizeOut,
+                              size_t& aNonHeapSizeOut) const override;
+
+  bool OnHeap() const override
+  {
+    return mVBuf->OnHeap();
+  }
+
+  // Althought Map (and Moz2D in general) isn't normally threadsafe,
+  // we want to allow it for SourceSurfaceVolatileData since it should
+  // always be fine (for reading at least).
+  //
+  // This is the same as the base class implementation except using
+  // mMapCount instead of mIsMapped since that breaks for multithread.
+  bool Map(MapType, MappedSurface *aMappedSurface) override
+  {
+    MutexAutoLock lock(mMutex);
+    if (mMapCount == 0) {
+      mVBufPtr = mVBuf;
+    }
+    if (mVBufPtr.WasBufferPurged()) {
+      return false;
+    }
+    aMappedSurface->mData = mVBufPtr;
+    aMappedSurface->mStride = mStride;
+    ++mMapCount;
+    return true;
+  }
+
+  void Unmap() override
+  {
+    MutexAutoLock lock(mMutex);
+    MOZ_ASSERT(mMapCount > 0);
+    if (--mMapCount == 0) {
+      mVBufPtr = nullptr;
+    }
+  }
+
+private:
+  ~SourceSurfaceVolatileData() override
+  {
+    MOZ_ASSERT(mMapCount == 0);
+  }
+
+  Mutex mMutex;
+  int32_t mStride;
+  int32_t mMapCount;
+  IntSize mSize;
+  RefPtr<VolatileBuffer> mVBuf;
+  VolatileBufferPtr<uint8_t> mVBufPtr;
+  SurfaceFormat mFormat;
+};
+
+} // namespace gfx
+} // namespace mozilla
+
+#endif /* MOZILLA_GFX_SOURCESURFACEVOLATILEDATA_H_ */
--- a/gfx/layers/apz/src/GestureEventListener.cpp
+++ b/gfx/layers/apz/src/GestureEventListener.cpp
@@ -3,16 +3,17 @@
 /* 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 "GestureEventListener.h"
 #include <math.h>                       // for fabsf
 #include <stddef.h>                     // for size_t
 #include "AsyncPanZoomController.h"     // for AsyncPanZoomController
+#include "InputBlockState.h"            // for TouchBlockState
 #include "base/task.h"                  // for CancelableTask, etc
 #include "gfxPrefs.h"                   // for gfxPrefs
 #include "mozilla/SizePrintfMacros.h"   // for PRIuSIZE
 #include "nsDebug.h"                    // for NS_WARNING
 #include "nsMathUtils.h"                // for NS_hypot
 
 #define GEL_LOG(...)
 // #define GEL_LOG(...) printf_stderr("GEL: " __VA_ARGS__)
--- a/gfx/layers/moz.build
+++ b/gfx/layers/moz.build
@@ -196,16 +196,18 @@ EXPORTS.mozilla.layers += [
     'opengl/CompositingRenderTargetOGL.h',
     'opengl/CompositorOGL.h',
     'opengl/MacIOSurfaceTextureClientOGL.h',
     'opengl/MacIOSurfaceTextureHostOGL.h',
     'opengl/TextureClientOGL.h',
     'opengl/TextureHostOGL.h',
     'PersistentBufferProvider.h',
     'RenderTrace.h',
+    'SourceSurfaceSharedData.h',
+    'SourceSurfaceVolatileData.h',
     'TextureWrapperImage.h',
     'TransactionIdAllocator.h',
 ]
 
 if CONFIG['MOZ_X11']:
     EXPORTS.mozilla.layers += [
         'basic/TextureClientX11.h',
         'basic/X11TextureSourceBasic.h',
@@ -368,16 +370,18 @@ UNIFIED_SOURCES += [
     'opengl/TextureClientOGL.cpp',
     'opengl/TextureHostOGL.cpp',
     'opengl/TexturePoolOGL.cpp',
     'protobuf/LayerScopePacket.pb.cc',
     'ReadbackProcessor.cpp',
     'RenderTrace.cpp',
     'RotatedBuffer.cpp',
     'ShareableCanvasLayer.cpp',
+    'SourceSurfaceSharedData.cpp',
+    'SourceSurfaceVolatileData.cpp',
     'TextureWrapperImage.cpp',
 ]
 
 SOURCES += [
     'basic/BasicImageLayer.cpp',
     'ImageContainer.cpp',
     'Layers.cpp',
     'LayerTreeInvalidation.cpp',
--- a/gfx/tests/crashtests/crashtests.list
+++ b/gfx/tests/crashtests/crashtests.list
@@ -109,27 +109,27 @@ load 768079-1.html
 asserts-if(stylo,2) load 783041-1.html # bug 1324661
 load 783041-2.html
 asserts-if(stylo,1) load 783041-3.html # bug 1324671
 load 783041-4.html
 load 798853.html # bug 868792
 load 805760-1.html
 skip-if(Android) load 815489.html # bug 1216304
 load 836225-1.html
-asserts-if(stylo,2) load 839745-1.html # bug 1324669
+load 839745-1.html
 load 856784-1.html
 load 893572-1.html
 load 893572-2.html
 load 893572-3.html
 load 893572-4.html
 pref(layers.force-active,true) load 914457-1.html
 load 944579.svg
-asserts-if(stylo,2) load 944579.html # bug 1324669
+load 944579.html
 asserts-if(stylo,1) pref(security.fileuri.strict_origin_policy,false) load 950000.html # bug 1324700
 load 1034403-1.html
 load 1205900.html
 load 1134549-1.svg
 load balinese-letter-spacing.html
 load 1216832-1.html
 load 1225125-1.html
-asserts-if(stylo,2) load 1308394.html # bug 1324669
+load 1308394.html
 skip-if(stylo) load 1317403-1.html # bug 1331533
 load 1325159-1.html
--- a/gfx/thebes/gfxFont.cpp
+++ b/gfx/thebes/gfxFont.cpp
@@ -42,17 +42,16 @@
 #include "gfx2DGlue.h"
 
 #include "GreekCasing.h"
 
 #include "cairo.h"
 
 #include "harfbuzz/hb.h"
 #include "harfbuzz/hb-ot.h"
-#include "graphite2/Font.h"
 
 #include <algorithm>
 #include <limits>
 #include <cmath>
 
 using namespace mozilla;
 using namespace mozilla::gfx;
 using namespace mozilla::unicode;
--- a/gfx/thebes/gfxUtils.cpp
+++ b/gfx/thebes/gfxUtils.cpp
@@ -880,17 +880,17 @@ gfxUtils::GfxRectToIntRect(const gfxRect
 gfxUtils::CopySurfaceToDataSourceSurfaceWithFormat(SourceSurface* aSurface,
                                                    SurfaceFormat aFormat)
 {
   MOZ_ASSERT(aFormat != aSurface->GetFormat(),
              "Unnecessary - and very expersive - surface format conversion");
 
   Rect bounds(0, 0, aSurface->GetSize().width, aSurface->GetSize().height);
 
-  if (aSurface->GetType() != SurfaceType::DATA) {
+  if (!aSurface->IsDataSourceSurface()) {
     // If the surface is NOT of type DATA then its data is not mapped into main
     // memory. Format conversion is probably faster on the GPU, and by doing it
     // there we can avoid any expensive uploads/readbacks except for (possibly)
     // a single readback due to the unavoidable GetDataSurface() call. Using
     // CreateOffscreenContentDrawTarget ensures the conversion happens on the
     // GPU.
     RefPtr<DrawTarget> dt = gfxPlatform::GetPlatform()->
       CreateOffscreenContentDrawTarget(aSurface->GetSize(), aFormat);
--- a/image/SurfaceCache.cpp
+++ b/image/SurfaceCache.cpp
@@ -10,19 +10,19 @@
 #include "SurfaceCache.h"
 
 #include <algorithm>
 #include "mozilla/Assertions.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/DebugOnly.h"
 #include "mozilla/Likely.h"
 #include "mozilla/Move.h"
-#include "mozilla/Mutex.h"
 #include "mozilla/Pair.h"
 #include "mozilla/RefPtr.h"
+#include "mozilla/StaticMutex.h"
 #include "mozilla/StaticPtr.h"
 #include "mozilla/Tuple.h"
 #include "nsIMemoryReporter.h"
 #include "gfx2DGlue.h"
 #include "gfxPlatform.h"
 #include "gfxPrefs.h"
 #include "imgFrame.h"
 #include "Image.h"
@@ -50,16 +50,19 @@ class SurfaceCacheImpl;
 
 ///////////////////////////////////////////////////////////////////////////////
 // Static Data
 ///////////////////////////////////////////////////////////////////////////////
 
 // The single surface cache instance.
 static StaticRefPtr<SurfaceCacheImpl> sInstance;
 
+// The mutex protecting the surface cache.
+static StaticMutex sInstanceMutex;
+
 ///////////////////////////////////////////////////////////////////////////////
 // SurfaceCache Implementation
 ///////////////////////////////////////////////////////////////////////////////
 
 /**
  * Cost models the cost of storing a surface in the cache. Right now, this is
  * simply an estimate of the size of the surface in bytes, but in the future it
  * may be worth taking into account the cost of rematerializing the surface as
@@ -386,17 +389,16 @@ class SurfaceCacheImpl final : public ns
 public:
   NS_DECL_ISUPPORTS
 
   SurfaceCacheImpl(uint32_t aSurfaceCacheExpirationTimeMS,
                    uint32_t aSurfaceCacheDiscardFactor,
                    uint32_t aSurfaceCacheSize)
     : mExpirationTracker(aSurfaceCacheExpirationTimeMS)
     , mMemoryPressureObserver(new MemoryPressureObserver)
-    , mMutex("SurfaceCache")
     , mDiscardFactor(aSurfaceCacheDiscardFactor)
     , mMaxCost(aSurfaceCacheSize)
     , mAvailableCost(aSurfaceCacheSize)
     , mLockedCost(0)
     , mOverflowCount(0)
   {
     nsCOMPtr<nsIObserverService> os = services::GetObserverService();
     if (os) {
@@ -413,18 +415,16 @@ private:
     }
 
     UnregisterWeakMemoryReporter(this);
   }
 
 public:
   void InitMemoryReporter() { RegisterWeakMemoryReporter(this); }
 
-  Mutex& GetMutex() { return mMutex; }
-
   InsertOutcome Insert(NotNull<ISurfaceProvider*> aProvider,
                        bool                       aSetAvailable)
   {
     // If this is a duplicate surface, refuse to replace the original.
     // XXX(seth): Calling Lookup() and then RemoveEntry() does the lookup
     // twice. We'll make this more efficient in bug 1185137.
     LookupResult result = Lookup(aProvider->GetImageKey(),
                                  aProvider->GetSurfaceKey(),
@@ -781,17 +781,17 @@ public:
     StartTracking(aSurface);
   }
 
   NS_IMETHOD
   CollectReports(nsIHandleReportCallback* aHandleReport,
                  nsISupports*             aData,
                  bool                     aAnonymize) override
   {
-    MutexAutoLock lock(mMutex);
+    StaticMutexAutoLock lock(sInstanceMutex);
 
     // We have explicit memory reporting for the surface cache which is more
     // accurate than the cost metrics we report here, but these metrics are
     // still useful to report, since they control the cache's behavior.
     MOZ_COLLECT_REPORT(
       "imagelib-surface-cache-estimated-total",
       KIND_OTHER, UNITS_BYTES, (mMaxCost - mAvailableCost),
 "Estimated total memory used by the imagelib surface cache.");
@@ -889,48 +889,47 @@ private:
     explicit SurfaceTracker(uint32_t aSurfaceCacheExpirationTimeMS)
       : nsExpirationTracker<CachedSurface, 2>(aSurfaceCacheExpirationTimeMS,
                                               "SurfaceTracker")
     { }
 
   protected:
     virtual void NotifyExpired(CachedSurface* aSurface) override
     {
+      StaticMutexAutoLock lock(sInstanceMutex);
       if (sInstance) {
-        MutexAutoLock lock(sInstance->GetMutex());
         sInstance->Remove(WrapNotNull(aSurface));
       }
     }
   };
 
   struct MemoryPressureObserver : public nsIObserver
   {
     NS_DECL_ISUPPORTS
 
     NS_IMETHOD Observe(nsISupports*,
                        const char* aTopic,
                        const char16_t*) override
     {
+      StaticMutexAutoLock lock(sInstanceMutex);
       if (sInstance && strcmp(aTopic, "memory-pressure") == 0) {
-        MutexAutoLock lock(sInstance->GetMutex());
         sInstance->DiscardForMemoryPressure();
       }
       return NS_OK;
     }
 
   private:
     virtual ~MemoryPressureObserver() { }
   };
 
   nsTArray<CostEntry>                     mCosts;
   nsRefPtrHashtable<nsPtrHashKey<Image>,
     ImageSurfaceCache> mImageCaches;
   SurfaceTracker                          mExpirationTracker;
   RefPtr<MemoryPressureObserver>        mMemoryPressureObserver;
-  Mutex                                   mMutex;
   const uint32_t                          mDiscardFactor;
   const Cost                              mMaxCost;
   Cost                                    mAvailableCost;
   Cost                                    mLockedCost;
   size_t                                  mOverflowCount;
 };
 
 NS_IMPL_ISUPPORTS(SurfaceCacheImpl, nsIMemoryReporter)
@@ -994,151 +993,154 @@ SurfaceCache::Initialize()
                                    surfaceCacheDiscardFactor,
                                    finalSurfaceCacheSizeBytes);
   sInstance->InitMemoryReporter();
 }
 
 /* static */ void
 SurfaceCache::Shutdown()
 {
+  StaticMutexAutoLock lock(sInstanceMutex);
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(sInstance, "No singleton - was Shutdown() called twice?");
   sInstance = nullptr;
 }
 
 /* static */ LookupResult
 SurfaceCache::Lookup(const ImageKey         aImageKey,
                      const SurfaceKey&      aSurfaceKey)
 {
+  StaticMutexAutoLock lock(sInstanceMutex);
   if (!sInstance) {
     return LookupResult(MatchType::NOT_FOUND);
   }
 
-  MutexAutoLock lock(sInstance->GetMutex());
   return sInstance->Lookup(aImageKey, aSurfaceKey);
 }
 
 /* static */ LookupResult
 SurfaceCache::LookupBestMatch(const ImageKey         aImageKey,
                               const SurfaceKey&      aSurfaceKey)
 {
+  StaticMutexAutoLock lock(sInstanceMutex);
   if (!sInstance) {
     return LookupResult(MatchType::NOT_FOUND);
   }
 
-  MutexAutoLock lock(sInstance->GetMutex());
   return sInstance->LookupBestMatch(aImageKey, aSurfaceKey);
 }
 
 /* static */ InsertOutcome
 SurfaceCache::Insert(NotNull<ISurfaceProvider*> aProvider)
 {
+  StaticMutexAutoLock lock(sInstanceMutex);
   if (!sInstance) {
     return InsertOutcome::FAILURE;
   }
 
-  MutexAutoLock lock(sInstance->GetMutex());
   return sInstance->Insert(aProvider, /* aSetAvailable = */ false);
 }
 
 /* static */ bool
 SurfaceCache::CanHold(const IntSize& aSize, uint32_t aBytesPerPixel /* = 4 */)
 {
+  StaticMutexAutoLock lock(sInstanceMutex);
   if (!sInstance) {
     return false;
   }
 
   Cost cost = ComputeCost(aSize, aBytesPerPixel);
   return sInstance->CanHold(cost);
 }
 
 /* static */ bool
 SurfaceCache::CanHold(size_t aSize)
 {
+  StaticMutexAutoLock lock(sInstanceMutex);
   if (!sInstance) {
     return false;
   }
 
   return sInstance->CanHold(aSize);
 }
 
 /* static */ void
 SurfaceCache::SurfaceAvailable(NotNull<ISurfaceProvider*> aProvider)
 {
+  StaticMutexAutoLock lock(sInstanceMutex);
   if (!sInstance) {
     return;
   }
 
-  MutexAutoLock lock(sInstance->GetMutex());
   sInstance->SurfaceAvailable(aProvider);
 }
 
 /* static */ void
 SurfaceCache::LockImage(const ImageKey aImageKey)
 {
+  StaticMutexAutoLock lock(sInstanceMutex);
   if (sInstance) {
-    MutexAutoLock lock(sInstance->GetMutex());
     return sInstance->LockImage(aImageKey);
   }
 }
 
 /* static */ void
 SurfaceCache::UnlockImage(const ImageKey aImageKey)
 {
+  StaticMutexAutoLock lock(sInstanceMutex);
   if (sInstance) {
-    MutexAutoLock lock(sInstance->GetMutex());
     return sInstance->UnlockImage(aImageKey);
   }
 }
 
 /* static */ void
 SurfaceCache::UnlockEntries(const ImageKey aImageKey)
 {
+  StaticMutexAutoLock lock(sInstanceMutex);
   if (sInstance) {
-    MutexAutoLock lock(sInstance->GetMutex());
     return sInstance->UnlockEntries(aImageKey);
   }
 }
 
 /* static */ void
 SurfaceCache::RemoveImage(const ImageKey aImageKey)
 {
+  StaticMutexAutoLock lock(sInstanceMutex);
   if (sInstance) {
-    MutexAutoLock lock(sInstance->GetMutex());
     sInstance->RemoveImage(aImageKey);
   }
 }
 
 /* static */ void
 SurfaceCache::DiscardAll()
 {
+  StaticMutexAutoLock lock(sInstanceMutex);
   if (sInstance) {
-    MutexAutoLock lock(sInstance->GetMutex());
     sInstance->DiscardAll();
   }
 }
 
 /* static */ void
 SurfaceCache::CollectSizeOfSurfaces(const ImageKey                  aImageKey,
                                     nsTArray<SurfaceMemoryCounter>& aCounters,
                                     MallocSizeOf                    aMallocSizeOf)
 {
+  StaticMutexAutoLock lock(sInstanceMutex);
   if (!sInstance) {
     return;
   }
 
-  MutexAutoLock lock(sInstance->GetMutex());
   return sInstance->CollectSizeOfSurfaces(aImageKey, aCounters, aMallocSizeOf);
 }
 
 /* static */ size_t
 SurfaceCache::MaximumCapacity()
 {
+  StaticMutexAutoLock lock(sInstanceMutex);
   if (!sInstance) {
     return 0;
   }
 
-  MutexAutoLock lock(sInstance->GetMutex());
   return sInstance->MaximumCapacity();
 }
 
 } // namespace image
 } // namespace mozilla
--- a/image/test/gtest/TestDecodeToSurface.cpp
+++ b/image/test/gtest/TestDecodeToSurface.cpp
@@ -42,17 +42,17 @@ public:
   void Go()
   {
     mSurface =
       ImageOps::DecodeToSurface(mInputStream,
                                 nsDependentCString(mTestCase.mMimeType),
                                 imgIContainer::DECODE_FLAGS_DEFAULT);
     ASSERT_TRUE(mSurface != nullptr);
 
-    EXPECT_EQ(SurfaceType::DATA, mSurface->GetType());
+    EXPECT_TRUE(mSurface->IsDataSourceSurface());
     EXPECT_TRUE(mSurface->GetFormat() == SurfaceFormat::B8G8R8X8 ||
                 mSurface->GetFormat() == SurfaceFormat::B8G8R8A8);
     EXPECT_EQ(mTestCase.mSize, mSurface->GetSize());
 
     EXPECT_TRUE(IsSolidColor(mSurface, BGRAColor::Green(),
                              mTestCase.mFlags & TEST_CASE_IS_FUZZY ? 1 : 0));
   }
 
--- a/image/test/gtest/TestDecoders.cpp
+++ b/image/test/gtest/TestDecoders.cpp
@@ -59,17 +59,17 @@ CheckDecoderState(const ImageTestCase& a
   EXPECT_EQ(aTestCase.mSize.height, size.height);
 
   // Get the current frame, which is always the first frame of the image
   // because CreateAnonymousDecoder() forces a first-frame-only decode.
   RawAccessFrameRef currentFrame = aDecoder->GetCurrentFrameRef();
   RefPtr<SourceSurface> surface = currentFrame->GetSourceSurface();
 
   // Verify that the resulting surfaces matches our expectations.
-  EXPECT_EQ(SurfaceType::DATA, surface->GetType());
+  EXPECT_TRUE(surface->IsDataSourceSurface());
   EXPECT_TRUE(surface->GetFormat() == SurfaceFormat::B8G8R8X8 ||
               surface->GetFormat() == SurfaceFormat::B8G8R8A8);
   EXPECT_EQ(aTestCase.mOutputSize, surface->GetSize());
 
   return surface.forget();
 }
 
 static void
--- a/js/src/builtin/Intl.cpp
+++ b/js/src/builtin/Intl.cpp
@@ -3498,17 +3498,16 @@ CreatePluralRulesPrototype(JSContext* cx
 js::GlobalObject::addPluralRulesConstructor(JSContext* cx, HandleObject intl)
 {
     Handle<GlobalObject*> global = cx->global();
 
     {
         const HeapSlot& slot = global->getReservedSlotRef(PLURAL_RULES_PROTO);
         if (!slot.isUndefined()) {
             MOZ_ASSERT(slot.isObject());
-            MOZ_ASSERT(slot.toObject().is<PluralRulesObject>());
             JS_ReportErrorASCII(cx,
                                 "the PluralRules constructor can't be added "
                                 "multiple times in the same global");
             return false;
         }
     }
 
     JSObject* pluralRulesProto = CreatePluralRulesPrototype(cx, intl, global);
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/auto-regress/bug1334573.js
@@ -0,0 +1,6 @@
+// |jit-test| error:Error
+
+if (this.Intl) {
+    addIntlExtras(Intl);
+    addIntlExtras(Intl);
+}
--- a/layout/base/crashtests/crashtests.list
+++ b/layout/base/crashtests/crashtests.list
@@ -217,17 +217,17 @@ load 404721-1.xhtml
 load 404721-2.xhtml
 load 405049-1.xul
 load 405184-1.xhtml
 asserts-if(stylo,2) load 405186-1.xhtml # bug 1324661
 load 406675-1.html
 load 408292.html
 load 408299.html
 load 408450-1.xhtml
-asserts-if(stylo,2) load 409461-1.xhtml # bug 1324669
+load 409461-1.xhtml
 load 409513.html
 load 410967.html
 load 411870-1.html
 load 412651-1.html
 load 413587-1.svg
 load 414058-1.html
 load 414175-1.xul
 load 415503.xhtml
@@ -238,17 +238,17 @@ load 420213-1.html
 skip-if(stylo) load 420219-1.html # bug 1323652
 load 420651-1.xhtml
 load 421203-1.xul
 load 421432.html
 load 422276.html
 asserts(0-1) load 423107-1.xhtml # bug 866955
 load 425981-1.html
 asserts-if(stylo,1) load 428113.xhtml # bug 1329454
-asserts-if(stylo,1) load 428138-1.html # bug 1324669
+load 428138-1.html
 load 428448-1.html
 load 429088-1.html
 load 429088-2.html
 load 429780-1.xhtml
 load 429865-1.html
 load 429881.html
 load 430569-1.html
 load 430569-2.html
@@ -320,17 +320,17 @@ load 496011-1.xhtml
 load 497519-1.xhtml
 load 497519-2.xhtml
 load 497519-3.xhtml
 load 497519-4.xhtml
 load 499741-1.xhtml
 load 499841-1.xhtml
 load 499858-1.xhtml
 load 500467-1.html
-asserts-if(stylo,2) load 501878-1.html # bug 1324669
+load 501878-1.html
 asserts-if(stylo,4) load 503936-1.html # bug 1324658
 load 507119.html
 load 514104-1.xul
 load 522374-1.html
 load 522374-2.html
 load 526378-1.xul
 load 534367-1.xhtml
 load 534368-1.xhtml
@@ -371,17 +371,17 @@ load 580834-1.xhtml
 asserts-if(stylo,25) load 589787.html # bug 1324665
 load 591075-1.html
 load 591998-1.html
 load 595039-1.html
 load 597924-1.html
 load 606432-1.html
 load 609821-1.xhtml
 load 613817-1.svg
-asserts-if(stylo,2) load 615146-1.html # bug 1324669
+load 615146-1.html
 load 615781-1.xhtml
 load 616495-single-side-composite-color-border.html
 load 629035-1.html
 load 629908-1.html
 load 635329.html
 load 636229-1.html
 == 640272.html 640272-ref.html
 load 645193.html
@@ -457,17 +457,17 @@ load 931464.html
 load 935765-1.html
 load 936988-1.html
 load 942690.html
 load 973390-1.html
 load 1001237.html
 load 1009036.html
 asserts-if(stylo,1) load 1043163-1.html # bug 1324647
 load 1061028.html
-asserts-if(stylo,2-3) load 1107508-1.html # bug 1324669
+load 1107508-1.html
 load 1116104.html
 load 1127198-1.html
 load 1140198.html
 load 1143535.html
 pref(layout.css.grid.enabled,true) load 1156588.html
 load 1162813.xul
 load 1163583.html
 load 1234622-1.html
--- a/layout/forms/crashtests/crashtests.list
+++ b/layout/forms/crashtests/crashtests.list
@@ -58,12 +58,12 @@ load 865602.html
 asserts-if(stylo,6) load 893332-1.html # bug 1324671
 asserts-if(stylo,1) load 944198.html # bug 1324671
 skip-if(stylo) load 949891.xhtml # bug 1323693
 load 959311.html
 load 960277-2.html
 load 997709-1.html
 load 1102791.html
 skip-if(stylo) load 1140216.html # bug 1323693
-asserts-if(stylo,11) load 1182414.html # bug 1324687
+asserts-if(stylo,9) load 1182414.html # bug 1324687
 load 1212688.html
 load 1228670.xhtml
 asserts-if(stylo,4-5) load 1279354.html # bug 1324671
--- a/layout/generic/crashtests/crashtests.list
+++ b/layout/generic/crashtests/crashtests.list
@@ -181,18 +181,18 @@ asserts(0-2) load 398332-3.html # bug 43
 load 399407-1.xhtml
 load 399412-1.html
 load 399843-1.html
 load 400078-1.html
 load 400190.html
 skip-if(stylo) load 400223-1.html # bug 1323652
 load 400232-1.html
 load 400244-1.html
-asserts-if(stylo,2) load 400768-1.xhtml # bug 1324669
-asserts-if(stylo,2) load 400768-2.xhtml # bug 1324669
+load 400768-1.xhtml
+load 400768-2.xhtml
 load 401042-1.xhtml
 load 402380-1.html
 load 402380-2.html
 load 402872-1.html
 load 402872-2.html
 load 403004.html
 skip-if(stylo) load 403143-1.html # bug 1323652
 load 403576-1.html
@@ -237,17 +237,17 @@ skip-if(stylo) load 413712-1.xhtml # bug
 load 414061-1.html
 load 414180-1.xul
 load 414719-1.html
 load 415685-1.html
 load 416165.html
 load 416264-1.html
 load 416476-1.html
 load 417109-1.xhtml
-asserts-if(stylo,2) load 417848-1.xhtml # bug 1324669
+load 417848-1.xhtml
 load 417902-1.html
 load 417902-2.html
 load 418532-1.html
 asserts-if(stylo,2) load 418932-1.html # bug 1324665
 load 419352.html
 asserts-if(stylo,2) load 420000-1.html # bug 1330259
 load 420718.html
 load 420785-1.xhtml
@@ -277,17 +277,17 @@ load 431260-1.html
 load 431260-2.html
 load 435529.html
 load 436194-1.html
 load 436602-1.html
 load 436822-1.html
 load 436823.html
 load 436969-1.html
 skip-if(stylo) load 437156-1.html # bug 1323652
-asserts-if(stylo,2) load 437565-1.xhtml # bug 1324669
+load 437565-1.xhtml
 load 437565-2.xhtml
 load 437565-3.xhtml
 load 438259-1.html
 load 438266-1.html
 skip load 438509-1.html # bug 511234
 load 442860-1.xul
 load 443528-1.html
 load 444230-1.html
@@ -419,32 +419,32 @@ asserts(0-4) load 578977.html # bug 7573
 load 580504-1.xhtml
 load 585598-1.xhtml
 load 586806-1.html
 load 586806-2.html
 load 586806-3.html
 load 586973-1.html
 load 589002-1.html
 load 590404.html
-asserts-if(stylo,2) load 591141.html # bug 1324669
+load 591141.html
 load 592118.html
 load 594808-1.html
 asserts-if(stylo,4) load 595435-1.xhtml # bug 1324640
 load 595740-1.html
 load 597240-1.xhtml
 pref(layout.float-fragments-inside-column.enabled,true) load 600100.xhtml
 pref(layout.float-fragments-inside-column.enabled,false) load 600100.xhtml
 load 603490-1.html
 load 603510-1.html
 load 604314-1.html
 load 604843.html
 load 605340.html
 load 606642.xhtml
 load 613455-1.svg
-asserts-if(stylo,2) load 613629-1.xhtml # bug 1324669
+load 613629-1.xhtml
 load 616052-1.html
 load 619021.html
 load 621424-1.html
 load 621841-1.html
 load 622596.html
 load 641724.html
 load 645072-1.html
 load 645072-2.html
@@ -460,17 +460,17 @@ load 656130-2.html
 load 660416.html
 asserts-if(stylo,2) load 665853.html # bug 1324634
 load 667025.html
 skip-if(stylo) load 673770.html # bug 1323652
 load 679933-1.html
 load 681489-1.html
 load 682649-1.html
 load 683702-1.xhtml
-asserts-if(stylo,2) load 683712.html # bug 1324669
+load 683712.html
 load 688996-1.html
 load 688996-2.html
 load 691210.html
 load 700031.xhtml
 load 718516.html
 load 723108.html
 load 724235.html
 skip-if(Android&&isDebugBuild) load 724978.xhtml # bug 1263300 - slow
@@ -547,17 +547,17 @@ needs-focus pref(accessibility.browsewit
 asserts(0-5) load 876074-1.html # bug 876749
 load 876155.html
 load 885009-1.html
 load 893496-1.html
 load 893523.html
 asserts(0-3) load 898871.html # bug 479160 - mostly OSX, sometimes Windows
 asserts(0-3) load 914501.html # bug 1144852 - all platforms
 load 914891.html
-asserts-if(stylo,2) load 915475.xhtml # bug 1324669
+load 915475.xhtml
 load 927558.html
 load 943509-1.html
 asserts(2-8) asserts-if(stylo,0) load 944909-1.html
 load 946167-1.html
 load 947158.html
 load 949932.html
 asserts-if(Android,0-1) load 964078.html # bug 989718
 load 970710.html
@@ -567,18 +567,18 @@ load 986899.html
 load 1001233.html
 load 1001258-1.html
 load 1003441.xul
 pref(layout.css.grid.enabled,true) load 1015562.html
 asserts(1-2) asserts-if(stylo,0) load 1015563-1.html
 asserts(1-2) asserts-if(stylo,0) load 1015563-2.html
 asserts(0-300) load 1015844.html # bug 574889
 pref(font.size.inflation.minTwips,200) load 1032450.html
-asserts-if(stylo,0-3) load 1032613-1.svg # bug 1324669
-asserts-if(stylo,2-6) load 1032613-2.html # bug 1324669
+load 1032613-1.svg
+load 1032613-2.html
 load 1037903.html
 asserts-if(stylo,1) load 1039454-1.html # bug 1324647
 load 1042489.html
 asserts-if(stylo,1) load 1054010-1.html # bug 1324647
 load 1058954-1.html
 load 1134531.html
 load 1134667.html
 load 1137723-1.html
--- a/layout/reftests/bidi/reftest-stylo.list
+++ b/layout/reftests/bidi/reftest-stylo.list
@@ -75,18 +75,18 @@ fails == 263359-1a.html 263359-1a.html
 fails == 263359-1b.html 263359-1b.html
 fails == 263359-2.html 263359-2.html
 == 263359-3.html 263359-3.html
 fails == 263359-4.html 263359-4.html
 fails == 267459-1.html 267459-1.html
 fails == 267459-2.html 267459-2.html
 == 299065-1.html 299065-1.html
 == 305643-1.html 305643-1.html
-fails == 332655-1.html 332655-1.html
-fails == 332655-2.html 332655-2.html
+fails asserts-if(stylo,7) == 332655-1.html 332655-1.html # bug 1335314
+fails asserts-if(stylo,7) == 332655-2.html 332655-2.html # bug 1335314
 fails == 381279-1.html 381279-1.html
 fails == 386339.html 386339.html
 fails == 409375.html 409375.html
 == 413542-1.html 413542-1.html
 == 413542-2.html 413542-2.html
 fails == 413928-1.html 413928-1.html
 fails == 413928-2.html 413928-2.html
 == 425338-1a.html 425338-1a.html
--- a/layout/reftests/bugs/reftest-stylo.list
+++ b/layout/reftests/bugs/reftest-stylo.list
@@ -196,18 +196,18 @@ fails == 201293-1d.html 201293-1d.html
 fails == 206516-1.html 206516-1.html
 == 206631-1.html 206631-1.html
 == 206802.html 206802.html
 fails == 210094-1a.html 210094-1a.html
 fails == 210094-1b.html 210094-1b.html
 fails == 210094-1c.html 210094-1c.html
 fails == 210876-1.html 210876-1.html
 == 211931-1.html 211931-1.html
-fails == 212563-1.html 212563-1.html
-== 212563-2.html 212563-2.html
+fails asserts-if(stylo,1) == 212563-1.html 212563-1.html # bug 1324683
+asserts-if(stylo,1) == 212563-2.html 212563-2.html # bug 1324683
 fails == 213834-1.html 213834-1.html
 fails == 214077-1a.html 214077-1a.html
 fails == 214077-1b.html 214077-1b.html
 == 218473-1.html 218473-1.html
 fuzzy-if(skiaContent,1,4) == 220165-1.svg 220165-1.svg
 fails == 223809-1.html 223809-1.html
 == 228856-1.html 228856-1.html
 == 228856-2.html 228856-2.html
@@ -569,17 +569,17 @@ fails == 364066-1.html 364066-1.html
 == 364318-1.xhtml 364318-1.xhtml
 == 364861-1.html 364861-1.html
 fails == 364862-1.html 364862-1.html
 == 364968-1.xul 364968-1.xul
 fails == 364989-1.html 364989-1.html
 fails == 365173-1.html 365173-1.html
 == 366207-1.xul 366207-1.xul
 == 366616-1.xul 366616-1.xul
-fails == 367220-1.html 367220-1.html
+fails asserts-if(stylo,30) == 367220-1.html 367220-1.html # bug 1324704
 == 367247-s-visible.html 367247-s-visible.html
 == 367247-s-hidden.html 367247-s-hidden.html
 == 367247-s-auto.html 367247-s-auto.html
 == 367247-l-visible.html 367247-l-visible.html
 == 367247-l-hidden.html 367247-l-hidden.html
 fails == 367247-l-scroll.html 367247-l-scroll.html
 == 367332-1a.html 367332-1a.html
 == 367332-1b.html 367332-1b.html
@@ -600,29 +600,29 @@ fails == 367612-1c.html 367612-1c.html
 == 367612-1e.html 367612-1e.html
 fails == 367612-1f.html 367612-1f.html
 == 367612-1g.html 367612-1g.html
 fails == 368020-1.html 368020-1.html
 fails == 368020-2.html 368020-2.html
 fails == 368020-3.html 368020-3.html
 fails pref(layout.css.box-decoration-break.enabled,true) == 368020-5.html 368020-5.html
 == 368155-1.xhtml 368155-1.xhtml
-fails asserts(4) == 368155-negative-margins-1.html 368155-negative-margins-1.html
+fails asserts(4-8) == 368155-negative-margins-1.html 368155-negative-margins-1.html
 # we can't test this because there's antialiasing involved, and our comparison
 # is too exact
 # == 368247-1.html 368247-1.html
 == 368247-2.html 368247-2.html
 fails == 368504-1.html 368504-1.html
 fails == 368504-2.html 368504-2.html
 == 368504-3a.html 368504-3a.html
 == 368504-3b.html 368504-3b.html
 == 368504-4.html 368504-4.html
 == 368504-5.html 368504-5.html
 fails == 368504-6.html 368504-6.html
-fails == 368622-1.html 368622-1.html
+fails asserts-if(stylo,2) == 368622-1.html 368622-1.html # bug 1324704
 fails == 368651-1.html 368651-1.html
 == 369361-1.html 369361-1.html
 == 369361-2.html 369361-2.html
 == 369882.xul 369882.xul
 fails == 369975-1.html 369975-1.html
 == 370353-1.html 370353-1.html
 fails == 370422-1.html 370422-1.html
 # == 370525-1.html 370525-1.html
@@ -674,17 +674,17 @@ random-if(d2d) == 374719-1.xul 374719-1.
 fails == 375508-1.html 375508-1.html
 == 375716-1.html 375716-1.html
 == 375827-1.html 375827-1.html
 fails == 376375-1.html 376375-1.html
 == 376484-1.html 376484-1.html
 == 376532-1.html 376532-1.html
 == 376532-2.html 376532-2.html
 == 376532-3.html 376532-3.html
-fails == 377603-1.html 377603-1.html
+fails asserts-if(stylo,2) == 377603-1.html 377603-1.html # bug 1324661
 == 377918.html 377918.html
 == 378535-1.html 378535-1.html
 fails == 378933-1.html 378933-1.html
 fails == 378935-1.html 378935-1.html
 fails == 378937-1.html 378937-1.html
 == 379178-xhtml.xhtml 379178-xhtml.xhtml
 fails == 379178-html.html 379178-html.html
 == 379178-svg.svg 379178-svg.svg
@@ -766,17 +766,17 @@ fails == 386470-1b.html 386470-1b.html
 == 387876-1.html 387876-1.html
 == 387876-2.html 387876-2.html
 == 387876-3a.html 387876-3a.html
 == 387876-3b.html 387876-3b.html
 == 388026-1.html 388026-1.html
 fails == 389074-1.html 389074-1.html
 # == 389224-1.html 389224-1.html
 # == 389224-2.html 389224-2.html
-fails == 389468-1.html 389468-1.html
+fails asserts-if(stylo,5) == 389468-1.html 389468-1.html # bug 1324661
 == 389623-1.html 389623-1.html
 == 389636-1.html 389636-1.html
 # == 389924-1a.html 389924-1a.html
 == 389924-1b.html 389924-1b.html
 # == 389924-1a.html 389924-1a.html
 == 390318-1a.html 390318-1a.html
 == 390318-1b.html 390318-1b.html
 == 390318-1c.html 390318-1c.html
@@ -1009,17 +1009,17 @@ fails == 420790-1.xhtml 420790-1.xhtml
 == 421203-5.xul 421203-5.xul
 == 421203-6.xul 421203-6.xul
 == 421234-1.html 421234-1.html
 == 421239-1.html 421239-1.html
 == 421239-2.html 421239-2.html
 == 421419-1.html 421419-1.html
 == 421436-1a.html 421436-1a.html
 == 421436-1b.html 421436-1b.html
-fails == 421632-1.html 421632-1.html
+fails asserts-if(stylo,4) == 421632-1.html 421632-1.html # bug 1335314
 fails == 421710-1.html 421710-1.html
 fails-if(Android) fails-if(usesRepeatResampling) == 421885-1.xml 421885-1.xml
 == 421955-1.html 421955-1.html
 fails == 422249-1.html 422249-1.html
 fails == 422394-1.html 422394-1.html
 fails == 422678-1.html 422678-1.html
 == 423130-1.html 423130-1.html
 == 423385-1.html 423385-1.html
@@ -1044,17 +1044,17 @@ fails == 424236-11.html 424236-11.html
 fails == 424465-1.html 424465-1.html
 == 424631-1.html 424631-1.html
 == 424710-1.html 424710-1.html
 fails == 424766-1.html 424766-1.html
 # == 425972-1.html 425972-1.html
 fails == 425972-2.html 425972-2.html
 # == 425972-1.html 425972-1.html
 fails == 426629-1.html 426629-1.html
-asserts(3) == 427017-1.xhtml 427017-1.xhtml
+asserts(3-6) == 427017-1.xhtml 427017-1.xhtml
 == 427129-scrollframe.html 427129-scrollframe.html
 == 427129-table.html 427129-table.html
 == 427129-image.html 427129-image.html
 == 427129-table-caption.html 427129-table-caption.html
 == 427370-1.html 427370-1.html
 fails == 427730-1.html 427730-1.html
 == 428278.html 428278.html
 == 428423-1a.html 428423-1a.html
@@ -1155,37 +1155,37 @@ fails == 440149-1.html 440149-1.html
 == 441259-1.html 441259-1.html
 == 441259-2.html 441259-2.html
 fails == 442542-1.html 442542-1.html
 fails == 444015-1.html 444015-1.html
 == 444375-1.html 444375-1.html
 fails == 444928-1.html 444928-1.html
 fails == 444928-2.html 444928-2.html
 fails == 444928-3.html 444928-3.html
-fails random == 445004-1.html 445004-1.html
+fails random asserts-if(stylo,2) == 445004-1.html 445004-1.html # bug 1324683
 == 445142-1a.html 445142-1a.html
 == 445142-1b.html 445142-1b.html
 == 445142-1c.html 445142-1c.html
 == 445142-2a.html 445142-2a.html
 == 445142-2b.html 445142-2b.html
 fails-if(usesRepeatResampling) == 446100-1a.html 446100-1a.html
 fails-if(Android) fails-if(usesRepeatResampling) == 446100-1b.html 446100-1b.html
 fails-if(Android) fails-if(usesRepeatResampling) == 446100-1c.html 446100-1c.html
 fails-if(usesRepeatResampling) == 446100-1d.html 446100-1d.html
 fails-if(usesRepeatResampling) == 446100-1e.html 446100-1e.html
 == 446100-1f.html 446100-1f.html
 fails-if(usesRepeatResampling) fails-if(Android) == 446100-1g.html 446100-1g.html
 == 446100-1h.html 446100-1h.html
 fails == 447749-1.html 447749-1.html
 fuzzy(127,2) == 448193.html 448193.html
-fails == 449149-1a.html 449149-1a.html
-fails == 449149-1b.html 449149-1b.html
+fails asserts-if(stylo,8) == 449149-1a.html 449149-1a.html # bug 1324671
+fails asserts-if(stylo,8) == 449149-1b.html 449149-1b.html # bug 1324671
 # Retry the above with XBL scopes
-fails test-pref(dom.use_xbl_scopes_for_remote_xul,true) == 449149-1a.html 449149-1a.html
-fails test-pref(dom.use_xbl_scopes_for_remote_xul,true) == 449149-1b.html 449149-1b.html
+fails test-pref(dom.use_xbl_scopes_for_remote_xul,true) asserts-if(stylo,8) == 449149-1a.html 449149-1a.html # bug 1324671
+fails test-pref(dom.use_xbl_scopes_for_remote_xul,true) asserts-if(stylo,8) == 449149-1b.html 449149-1b.html # bug 1324671
 == 449149-2.html 449149-2.html
 == 449171-1.html 449171-1.html
 fails == 449362-1.html 449362-1.html
 == 449519-1.html 449519-1.html
 == 450670-1.html 450670-1.html
 fails == 451168-1.html 451168-1.html
 == 451876-1.html 451876-1.html
 == 451876-2.html 451876-2.html
@@ -1322,18 +1322,18 @@ fails-if(Android) == 481024-1c.html 4810
 fails == 481948-1.html 481948-1.html
 == 481948-2.html 481948-2.html
 fails-if(Android) random-if(winWidget) fails-if(gtkWidget) == 481948-3.html 481948-3.html
 == 482398-1.html 482398-1.html
 fails == 482592-1a.xhtml 482592-1a.xhtml
 fails == 482592-1b.xhtml 482592-1b.xhtml
 == 482659-1a.html 482659-1a.html
 == 482659-1b.html 482659-1b.html
-== 482659-1c.html 482659-1c.html
-== 482659-1d.html 482659-1d.html
+asserts-if(stylo,1) == 482659-1c.html 482659-1c.html # bug 1324683
+asserts-if(stylo,1) == 482659-1d.html 482659-1d.html # bug 1324683
 == 483565.xul 483565.xul
 == 484256-1.html 484256-1.html
 == 484256-2.html 484256-2.html
 == 485012-1.html 485012-1.html
 fails == 485275-1.html 485275-1.html
 fails == 485275-1.svg 485275-1.svg
 == 486052-1.html 486052-1.html
 == 486052-2a.html 486052-2a.html
@@ -1357,17 +1357,17 @@ fails == 490173-2.html 490173-2.html
 == 490177-1.svg 490177-1.svg
 fails == 490182-1a.html 490182-1a.html
 fails == 490182-1b.html 490182-1b.html
 pref(browser.display.focus_ring_width,1) == 491180-1.html 491180-1.html
 pref(browser.display.focus_ring_width,1) == 491180-2.html 491180-2.html
 == 491323-1.xul 491323-1.xul
 == 492239-1.xul 492239-1.xul
 == 492661-1.html 492661-1.html
-== 493968-1.html 493968-1.html
+asserts-if(stylo,1) == 493968-1.html 493968-1.html # bug 1324702
 == 494667-1.html 494667-1.html
 == 494667-2.html 494667-2.html
 == 495274-1.html 495274-1.html
 fails == 495354-1a.xhtml 495354-1a.xhtml
 fails == 495354-1b.xhtml 495354-1b.xhtml
 == 495385-1a.html 495385-1a.html
 == 495385-1b.html 495385-1b.html
 == 495385-1c.html 495385-1c.html
@@ -1398,17 +1398,17 @@ fails == 501627-1.html 501627-1.html
 fails == 502447-1.html 502447-1.html
 fails == 502795-1.html 502795-1.html
 == 502942-1.html 502942-1.html
 == 503364-1a.html 503364-1a.html
 == 503364-1b.html 503364-1b.html
 # Reftest for bug 503531 marked as failing; should be re-enabled when
 # bug 607548 gets resolved.
 # needs-focus fails == 503531-1.html 503531-1.html
-== 504032-1.html 504032-1.html
+asserts-if(stylo,1) == 504032-1.html 504032-1.html # bug 1324702
 == 505743-1.html 505743-1.html
 fails == 506481-1.html 506481-1.html
 fails == 507187-1.html 507187-1.html
 == 507487-1.html 507487-1.html
 == 507487-2.xhtml 507487-2.xhtml
 == 507762-1.html 507762-1.html
 == 507762-2.html 507762-2.html
 == 507762-3.html 507762-3.html
@@ -1618,17 +1618,17 @@ fails == 602200-4.html 602200-4.html
 == 603423-1.html 603423-1.html
 fails == 604737.html 604737.html
 fails == 605138-1.html 605138-1.html
 fails == 605157-1.xhtml 605157-1.xhtml
 == 607267-1.html 607267-1.html
 fails == 608636-1.html 608636-1.html
 == 608756-1a.html 608756-1a.html
 == 608756-1b.html 608756-1b.html
-== 608756-2.html 608756-2.html
+asserts-if(stylo,4) == 608756-2.html 608756-2.html # bug 1324633
 == 609272-1.html 609272-1.html
 # == 613433-1.html 613433-1.html
 # == 613433-1.html 613433-1.html
 # == 613433-1.html 613433-1.html
 # == 613433-2.html 613433-2.html
 # == 613433-2.html 613433-2.html
 # == 613433-2.html 613433-2.html
 # == 613433-3.html 613433-3.html
@@ -1762,17 +1762,17 @@ fails == 825999.html 825999.html
 == 827577-1a.html 827577-1a.html
 == 827577-1b.html 827577-1b.html
 fails == 827799-1.html 827799-1.html
 == 829958.html 829958.html
 == 836844-1.html 836844-1.html
 == 841192-1.html 841192-1.html
 fails == 844178.html 844178.html
 == 846144-1.html 846144-1.html
-== 847850-1.html 847850-1.html
+asserts-if(stylo,1) == 847850-1.html 847850-1.html # bug 1324671
 fails == 848421-1.html 848421-1.html
 fails == 849407-1.html 849407-1.html
 == 849996-1.html 849996-1.html
 == 858803-1.html 858803-1.html
 == 860242-1.html 860242-1.html
 fails == 860370.html 860370.html
 == 871338-1.html 871338-1.html
 == 875060-1.html 875060-1.html
@@ -1803,17 +1803,17 @@ fails == 942672-1.html 942672-1.html
 fuzzy-if(skiaContent,1,5) == 956513-1.svg 956513-1.svg
 fails == 944291-1.html 944291-1.html
 fails == 950436-1.html 950436-1.html
 == 957770-1.svg 957770-1.svg
 fails == 960277-1.html 960277-1.html
 == 961887-1.html 961887-1.html
 == 961887-2.html 961887-2.html
 == 961887-3.html 961887-3.html
-fails == 966992-1.html 966992-1.html
+fails asserts-if(stylo,1) == 966992-1.html 966992-1.html # bug 1324671
 fails == 966510-1.html 966510-1.html
 fails == 966510-2.html 966510-2.html
 fuzzy-if(skiaContent,1,123) == 978911-1.svg 978911-1.svg
 == 983084-1.html 983084-1.html
 # == 983084-2.html 983084-2.html
 # == 983084-3.html 983084-3.html
 fails == 983691-1.html 983691-1.html
 HTTP(..) == 983985-1.html 983985-1.html
--- a/layout/reftests/canvas/reftest-stylo.list
+++ b/layout/reftests/canvas/reftest-stylo.list
@@ -4,70 +4,70 @@ fails == size-1.html size-1.html
 
 == empty-transaction-1.html empty-transaction-1.html
 
 fails == image-rendering-test.html image-rendering-test.html
 == image-shadow.html image-shadow.html
 
 fails == size-change-1.html size-change-1.html
 
-== subpixel-1.html subpixel-1.html
+asserts-if(stylo,1) == subpixel-1.html subpixel-1.html # bug 1324700
 
-== text-ltr-left.html text-ltr-left.html
-== text-ltr-right.html text-ltr-right.html
-== text-rtl-left.html text-rtl-left.html
-== text-rtl-right.html text-rtl-right.html
+asserts-if(stylo,1) == text-ltr-left.html text-ltr-left.html # bug 1324700
+asserts-if(stylo,1) == text-ltr-right.html text-ltr-right.html # bug 1324700
+asserts-if(stylo,1) == text-rtl-left.html text-rtl-left.html # bug 1324700
+asserts-if(stylo,1) == text-rtl-right.html text-rtl-right.html # bug 1324700
 
-== text-ltr-start.html text-ltr-start.html
-== text-ltr-end.html text-ltr-end.html
-== text-ltr-left.html text-ltr-left.html
-== text-rtl-start.html text-rtl-start.html
-== text-rtl-end.html text-rtl-end.html
-== text-rtl-left.html text-rtl-left.html
+asserts-if(stylo,1) == text-ltr-start.html text-ltr-start.html # bug 1324700
+asserts-if(stylo,1) == text-ltr-end.html text-ltr-end.html # bug 1324700
+asserts-if(stylo,1) == text-ltr-left.html text-ltr-left.html # bug 1324700
+asserts-if(stylo,1) == text-rtl-start.html text-rtl-start.html # bug 1324700
+asserts-if(stylo,1) == text-rtl-end.html text-rtl-end.html # bug 1324700
+asserts-if(stylo,1) == text-rtl-left.html text-rtl-left.html # bug 1324700
 
-== text-ltr-left.html text-ltr-left.html
+asserts-if(stylo,1) == text-ltr-left.html text-ltr-left.html # bug 1324700
 
-fails == text-ltr-alignment-test.html text-ltr-alignment-test.html
-fails == text-rtl-alignment-test.html text-rtl-alignment-test.html
+fails asserts-if(stylo,1) == text-ltr-alignment-test.html text-ltr-alignment-test.html # bug 1324700
+fails asserts-if(stylo,1) == text-rtl-alignment-test.html text-rtl-alignment-test.html # bug 1324700
 
-== text-horzline-with-bottom.html text-horzline-with-bottom.html
-fails-if(azureSkia&&OSX>=1008) == text-horzline-with-top.html text-horzline-with-top.html
+asserts-if(stylo,1) == text-horzline-with-bottom.html text-horzline-with-bottom.html # bug 1324700
+fails-if(azureSkia&&OSX>=1008) asserts-if(stylo,1) == text-horzline-with-top.html text-horzline-with-top.html # bug 1324700
 
 # == text-big-stroke.html text-big-stroke.html
 # == text-big-stroke.html text-big-stroke.html
 
-fails == text-context-state-test.html text-context-state-test.html
-fails == text-font-inherit.html text-font-inherit.html
-fails == text-space-replace-test.html text-space-replace-test.html
+fails asserts-if(stylo,1) == text-context-state-test.html text-context-state-test.html # bug 1324700
+fails asserts-if(stylo,1) == text-font-inherit.html text-font-inherit.html # bug 1324700
+fails asserts-if(stylo,1) == text-space-replace-test.html text-space-replace-test.html # bug 1324700
 
-fails == text-no-frame-test.html text-no-frame-test.html
-fails == text-no-frame-2-test.html text-no-frame-2-test.html
-fails == text-not-in-doc-test.html text-not-in-doc-test.html
+fails asserts-if(stylo,1) == text-no-frame-test.html text-no-frame-test.html # bug 1324700
+fails asserts-if(stylo,1) == text-no-frame-2-test.html text-no-frame-2-test.html # bug 1324700
+fails asserts-if(stylo,1) == text-not-in-doc-test.html text-not-in-doc-test.html # bug 1324700
 
 # == text-bidi-ltr-test.html text-bidi-ltr-test.html
 # == text-bidi-ltr-test.html text-bidi-ltr-test.html
-fails == text-bidi-rtl-test.html text-bidi-rtl-test.html
+fails asserts-if(stylo,1) == text-bidi-rtl-test.html text-bidi-rtl-test.html # bug 1324700
 
-fails == text-font-lang.html text-font-lang.html
+fails asserts-if(stylo,4) == text-font-lang.html text-font-lang.html # bug 1324700
 
-fails == text-measure.html text-measure.html
-fails == text-small-caps-1.html text-small-caps-1.html
+fails asserts-if(stylo,1) == text-measure.html text-measure.html # bug 1324700
+fails asserts-if(stylo,1) == text-small-caps-1.html text-small-caps-1.html # bug 1324700
 
-fails == text-subpixel-1.html text-subpixel-1.html
+fails asserts-if(stylo,1) == text-subpixel-1.html text-subpixel-1.html # bug 1324700
 
-fails == strokeText-path.html strokeText-path.html
+fails asserts-if(stylo,1) == strokeText-path.html strokeText-path.html # bug 1324700
 
 # check that emoji character renders as something non-blank (for Apple Color Emoji font, bug 715798)
 # apparently fails on some 10.7 systems for unknown reasons, bug 804522.
 ## Currently fails most places due to partial backout of bug 808288, see bug 837461.
 ## (Marking "random" rather than "fails" because it would pass for people
 ## if they have an Emoji font installed when running the tests.)
 ## WAS: random-if(OSX==1007) == text-emoji.html text-emoji.html
 # With Skia canvas on OS X (bug 932958) it fails even on 10.8 and 10.10.
-random-if(cocoaWidget&&azureSkia) random-if(!cocoaWidget||OSX==1006||OSX==1007) == text-emoji.html text-emoji.html
+random-if(cocoaWidget&&azureSkia) random-if(!cocoaWidget||OSX==1006||OSX==1007) asserts-if(stylo,1) == text-emoji.html text-emoji.html # bug 1324700
 
 # azure quartz uses CGDrawLinearGradient instead of DrawShading
 # so we have less control over degenerate behaviour as tested by this
 # test
 # fails-if((azureSkia&&!azureSkiaGL)||azureQuartz||(azureSkiaGL&&Android)) == linear-gradient-1a.html linear-gradient-1a.html
 
 # this passes with cairo on 10.7 and 10.8 but not with azure for reasons unknown
 # fails-if((azureSkia&&!azureSkiaGL)||azureQuartz||(azureSkiaGL&&Android)) == linear-gradient-1b.html linear-gradient-1b.html
@@ -82,33 +82,33 @@ random-if(cocoaWidget&&azureSkia) random
 
 == ctm-sanity.html ctm-sanity.html
 == ctm-singular-sanity.html ctm-singular-sanity.html
 == ctm-1.html ctm-1.html
 
 fails-if(azureQuartz&&OSX==1006) == 672646-alpha-radial-gradient.html 672646-alpha-radial-gradient.html
 fails == 674003-alpha-radial-gradient-superlum.html 674003-alpha-radial-gradient-superlum.html
 
-fails == 693610-1.html 693610-1.html
+fails asserts-if(stylo,1) == 693610-1.html 693610-1.html # bug 1324700
 
 == 726951-shadow-clips.html 726951-shadow-clips.html
 
 == transformed-clip.html transformed-clip.html
 fuzzy-if(azureSkia,1,15) fuzzy-if(skiaContent,1,20) == transformed-gradient.html transformed-gradient.html
 == transformed-path.html transformed-path.html
 
 == 749467-1.html 749467-1.html
 
 # You get a little bit of rounding fuzz on OSX from transforming the paths between user space and device space
 == 784573-1.html 784573-1.html
 
-fails == 802658-1.html 802658-1.html
+fails asserts-if(stylo,1) == 802658-1.html 802658-1.html # bug 1324700
 == 1074733-1.html 1074733-1.html
-fails == 1107096-invisibles.html 1107096-invisibles.html
+fails asserts-if(stylo,1) == 1107096-invisibles.html 1107096-invisibles.html # bug 1324700
 == 1151821-1.html 1151821-1.html
 == 1201272-1.html 1201272-1.html
 == 1224976-1.html 1224976-1.html
 == 1238795-1.html 1238795-1.html
 == 1303534-1.html 1303534-1.html
 
-fails == 1304353-text-global-alpha-1.html 1304353-text-global-alpha-1.html
-fails == 1304353-text-global-alpha-2.html 1304353-text-global-alpha-2.html
-fails == 1304353-text-global-composite-op-1.html 1304353-text-global-composite-op-1.html
+fails asserts-if(stylo,1) == 1304353-text-global-alpha-1.html 1304353-text-global-alpha-1.html # bug 1324700
+fails asserts-if(stylo,1) == 1304353-text-global-alpha-2.html 1304353-text-global-alpha-2.html # bug 1324700
+fails asserts-if(stylo,1) == 1304353-text-global-composite-op-1.html 1304353-text-global-composite-op-1.html # bug 1324700
--- a/layout/reftests/css-animations/reftest-stylo.list
+++ b/layout/reftests/css-animations/reftest-stylo.list
@@ -10,19 +10,19 @@ fails == animate-preserves3d.html animat
 # == partially-out-of-view-animation.html partially-out-of-view-animation.html
 # == animate-display-table-opacity.html animate-display-table-opacity.html
 # We need to run 100% opacity test case when OMTA is disabled to check that the animation creates a stacking context even if the animation is not running on the compositor
 # test-pref(layers.offmainthreadcomposition.async-animations,false) == stacking-context-opacity-1-animation.html stacking-context-opacity-1-animation.html
 # We need to run transform:none test case when OMTA is disabled to check that the animation creates a stacking context even if the animation is not running on the compositor
 # test-pref(layers.offmainthreadcomposition.async-animations,false) == stacking-context-transform-none-animation.html stacking-context-transform-none-animation.html
 # == no-stacking-context-opacity-removing-animation-in-delay.html no-stacking-context-opacity-removing-animation-in-delay.html
 == no-stacking-context-transform-removing-animation-in-delay.html no-stacking-context-transform-removing-animation-in-delay.html
-== stacking-context-lose-opacity-1.html stacking-context-lose-opacity-1.html
+# == stacking-context-lose-opacity-1.html stacking-context-lose-opacity-1.html
 fails == stacking-context-lose-transform-none.html stacking-context-lose-transform-none.html
-== stacking-context-opacity-win-in-delay.html stacking-context-opacity-win-in-delay.html
+# == stacking-context-opacity-win-in-delay.html stacking-context-opacity-win-in-delay.html
 == stacking-context-opacity-win-in-delay-on-main-thread.html stacking-context-opacity-win-in-delay-on-main-thread.html
 == stacking-context-opacity-wins-over-transition.html stacking-context-opacity-wins-over-transition.html
 fails == stacking-context-transform-win-in-delay.html stacking-context-transform-win-in-delay.html
 fails == stacking-context-transform-win-in-delay-on-main-thread.html stacking-context-transform-win-in-delay-on-main-thread.html
 fails == stacking-context-transform-wins-over-transition.html stacking-context-transform-wins-over-transition.html
 # == stacking-context-opacity-1-animation.html stacking-context-opacity-1-animation.html
 == stacking-context-opacity-1-with-fill-backwards.html stacking-context-opacity-1-with-fill-backwards.html
 == stacking-context-opacity-1-with-fill-forwards.html stacking-context-opacity-1-with-fill-forwards.html
--- a/layout/reftests/css-grid/reftest-stylo.list
+++ b/layout/reftests/css-grid/reftest-stylo.list
@@ -170,17 +170,17 @@ fails == grid-repeat-auto-fill-fit-003.h
 fails == grid-repeat-auto-fill-fit-004.html grid-repeat-auto-fill-fit-004.html
 fails == grid-repeat-auto-fill-fit-005.html grid-repeat-auto-fill-fit-005.html
 fails == grid-repeat-auto-fill-fit-006.html grid-repeat-auto-fill-fit-006.html
 fails == grid-repeat-auto-fill-fit-007.html grid-repeat-auto-fill-fit-007.html
 fails == grid-repeat-auto-fill-fit-008.html grid-repeat-auto-fill-fit-008.html
 fails == grid-repeat-auto-fill-fit-009.html grid-repeat-auto-fill-fit-009.html
 fails == grid-repeat-auto-fill-fit-010.html grid-repeat-auto-fill-fit-010.html
 fails == grid-repeat-auto-fill-fit-011.html grid-repeat-auto-fill-fit-011.html
-fails == grid-item-blockifying-001.html grid-item-blockifying-001.html
+fails asserts-if(stylo,144) == grid-item-blockifying-001.html grid-item-blockifying-001.html # bug 1335339
 fails == grid-fragmentation-001.html grid-fragmentation-001.html
 fails == grid-fragmentation-002.html grid-fragmentation-002.html
 fails == grid-fragmentation-003.html grid-fragmentation-003.html
 fails == grid-fragmentation-004.html grid-fragmentation-004.html
 fails == grid-fragmentation-005.html grid-fragmentation-005.html
 fails == grid-fragmentation-006.html grid-fragmentation-006.html
 fails == grid-fragmentation-007.html grid-fragmentation-007.html
 fails == grid-fragmentation-008.html grid-fragmentation-008.html
@@ -191,17 +191,17 @@ fails == grid-fragmentation-012.html gri
 fails == grid-fragmentation-013.html grid-fragmentation-013.html
 fails == grid-fragmentation-014.html grid-fragmentation-014.html
 fails asserts(0-10) == grid-fragmentation-015.html grid-fragmentation-015.html
 fails == grid-fragmentation-016.html grid-fragmentation-016.html
 fails == grid-fragmentation-017.html grid-fragmentation-017.html
 fails == grid-fragmentation-018.html grid-fragmentation-018.html
 fails == grid-fragmentation-019.html grid-fragmentation-019.html
 fails == grid-fragmentation-020.html grid-fragmentation-020.html
-fails == grid-fragmentation-021.html grid-fragmentation-021.html
+fails asserts-if(stylo,93) == grid-fragmentation-021.html grid-fragmentation-021.html # bug 1324704
 fails == grid-fragmentation-022.html grid-fragmentation-022.html
 fails == grid-fragmentation-023.html grid-fragmentation-023.html
 fails == grid-fragmentation-024.html grid-fragmentation-024.html
 fails == grid-fragmentation-025.html grid-fragmentation-025.html
 fails == grid-fragmentation-026.html grid-fragmentation-026.html
 fails == grid-fragmentation-027.html grid-fragmentation-027.html
 fails == grid-fragmentation-028.html grid-fragmentation-028.html
 fails == grid-fragmentation-029.html grid-fragmentation-029.html
--- a/layout/reftests/forms/button/reftest-stylo.list
+++ b/layout/reftests/forms/button/reftest-stylo.list
@@ -34,9 +34,9 @@ fails == disabled-6.html disabled-6.html
 
 # == width-auto-size-em-ltr.html width-auto-size-em-ltr.html
 # == width-auto-size-ltr.html width-auto-size-ltr.html
 # == width-exact-fit-ltr.html width-exact-fit-ltr.html
 # == width-auto-size-em-rtl.html width-auto-size-em-rtl.html
 # == width-auto-size-rtl.html width-auto-size-rtl.html
 # == width-exact-fit-rtl.html width-exact-fit-rtl.html
 fails == display-grid-flex-columnset.html display-grid-flex-columnset.html
-== 1317351.html 1317351.html
+asserts-if(stylo,1) == 1317351.html 1317351.html # bug 1324671
--- a/layout/reftests/forms/input/color/reftest-stylo.list
+++ b/layout/reftests/forms/input/color/reftest-stylo.list
@@ -1,15 +1,15 @@
 # DO NOT EDIT! This is a auto-generated temporary list for Stylo testing
 # Simple test. Should fail on platforms where input type color isn't activated
 # yet. The missing platform is Android (bug 875750).
-fails == input-color-1.html input-color-1.html
+fails asserts-if(stylo,4) == input-color-1.html input-color-1.html # bug 1324671
 
 default-preferences pref(dom.forms.color,true)
 
 # Despite the "default-preferences" line above, Android is still
 # excluded from some style in forms.css, which makes the following tests fail.
-fails == margin-padding-1.html margin-padding-1.html
-fails == block-invalidate-1.html block-invalidate-1.html
-fails == block-invalidate-2.html block-invalidate-2.html
-fails == transformations-1.html transformations-1.html
-fails == custom-style-1.html custom-style-1.html
-fails == custom-style-2.html custom-style-2.html
+fails asserts-if(stylo,16) == margin-padding-1.html margin-padding-1.html # bug 1324671
+fails asserts-if(stylo,1) == block-invalidate-1.html block-invalidate-1.html # bug 1324671
+fails asserts-if(stylo,1) == block-invalidate-2.html block-invalidate-2.html # bug 1324671
+fails asserts-if(stylo,14) == transformations-1.html transformations-1.html # bug 1324671
+fails asserts-if(stylo,1) == custom-style-1.html custom-style-1.html # bug 1324671
+fails asserts-if(stylo,1) == custom-style-2.html custom-style-2.html # bug 1324671
--- a/layout/reftests/forms/placeholder/reftest-stylo.list
+++ b/layout/reftests/forms/placeholder/reftest-stylo.list
@@ -4,33 +4,33 @@
 # text colour without changing the caret which means that the tested page has
 # a black caret with a grey text and the reference has a grey caret with grey
 # text. The only thing that is doable is to make the caret grey in the tested
 # page but that would make the test moot because a failure wouldn't be seen.
 # A real way to fix this would be to be able to style the caret or to implement
 # ::value (bug 648643), depending of the ::value behaviour (it could change the
 # caret colour and the text colour or just the text colour).
 
-fails == placeholder-1-text.html placeholder-1-text.html
-fails == placeholder-1-password.html placeholder-1-password.html
-fails == placeholder-1-textarea.html placeholder-1-textarea.html
+fails asserts-if(stylo,1) == placeholder-1-text.html placeholder-1-text.html # bug 1324671
+fails asserts-if(stylo,1) == placeholder-1-password.html placeholder-1-password.html # bug 1324671
+fails asserts-if(stylo,1) == placeholder-1-textarea.html placeholder-1-textarea.html # bug 1324671
 fails == placeholder-2.html placeholder-2.html
 fails == placeholder-2-textarea.html placeholder-2-textarea.html
-fails == placeholder-3.html placeholder-3.html
-fails == placeholder-4.html placeholder-4.html
-fails == placeholder-5.html placeholder-5.html
-fails == placeholder-6.html placeholder-6.html
-fails == placeholder-6-textarea.html placeholder-6-textarea.html
+fails asserts-if(stylo,1) == placeholder-3.html placeholder-3.html # bug 1324671
+fails asserts-if(stylo,1) == placeholder-4.html placeholder-4.html # bug 1324671
+fails asserts-if(stylo,1) == placeholder-5.html placeholder-5.html # bug 1324671
+fails asserts-if(stylo,1) == placeholder-6.html placeholder-6.html # bug 1324671
+fails asserts-if(stylo,1) == placeholder-6-textarea.html placeholder-6-textarea.html # bug 1324671
 # needs-focus == placeholder-7.html placeholder-7.html
 # needs-focus == placeholder-8.html placeholder-8.html
 # needs-focus == placeholder-9.html placeholder-9.html
-fails needs-focus == placeholder-10.html placeholder-10.html
-fails == placeholder-11.html placeholder-11.html
-fails == placeholder-12.html placeholder-12.html
+fails needs-focus asserts-if(stylo,1) == placeholder-10.html placeholder-10.html # bug 1324671
+fails asserts-if(stylo,1) == placeholder-11.html placeholder-11.html # bug 1324671
+fails asserts-if(stylo,1) == placeholder-12.html placeholder-12.html # bug 1324671
 fails == placeholder-13.html placeholder-13.html
 fails == placeholder-14.html placeholder-14.html
-fails == placeholder-18.html placeholder-18.html
+fails asserts-if(stylo,1) == placeholder-18.html placeholder-18.html # bug 1324671
 random-if(winWidget) == placeholder-19.xul placeholder-19.xul
 # needs-focus == placeholder-20.html placeholder-20.html
 # needs-focus == placeholder-21.html placeholder-21.html
-fails needs-focus == placeholder-22.html placeholder-22.html
+fails asserts-if(stylo,1) needs-focus == placeholder-22.html placeholder-22.html # bug 1324671
 # == placeholder-rtl.html placeholder-rtl.html
-fails pref(dom.placeholder.show_on_focus,false) needs-focus == placeholder-focus-pref.html placeholder-focus-pref.html
+fails pref(dom.placeholder.show_on_focus,false) asserts-if(stylo,1) needs-focus == placeholder-focus-pref.html placeholder-focus-pref.html # bug 1324671
--- a/layout/reftests/forms/progress/reftest-stylo.list
+++ b/layout/reftests/forms/progress/reftest-stylo.list
@@ -23,17 +23,17 @@
 
 # Tests for bugs:
 # == block-invalidate.html block-invalidate.html
 # == in-cells.html in-cells.html
 # == max-height.html max-height.html
 
 # Tests for block and inline orientation in combination with writing-mode
 # == progress-orient-horizontal.html progress-orient-horizontal.html
-fails-if(!cocoaWidget||OSX==1010) == progress-orient-vertical.html progress-orient-vertical.html
+fails-if(!cocoaWidget||OSX==1010) asserts-if(stylo,1) == progress-orient-vertical.html progress-orient-vertical.html # bug 1324671
 # == progress-orient-block.html progress-orient-block.html
 # == progress-orient-inline.html progress-orient-inline.html
 # == progress-vlr.html progress-vlr.html
 # == progress-vlr-orient-block.html progress-vlr-orient-block.html
 # == progress-vlr-orient-inline.html progress-vlr-orient-inline.html
 # == progress-vlr-orient-horizontal.html progress-vlr-orient-horizontal.html
 # == progress-vlr-orient-vertical.html progress-vlr-orient-vertical.html
 # == progress-vrl.html progress-vrl.html
--- a/layout/reftests/scoped-style/reftest-stylo.list
+++ b/layout/reftests/scoped-style/reftest-stylo.list
@@ -29,22 +29,22 @@ fails == scoped-style-important-002.html
 == scoped-style-important-004.html scoped-style-important-004.html
 == scoped-style-important-005.html scoped-style-important-005.html
 == scoped-style-important-006.html scoped-style-important-006.html
 == scoped-style-important-007.html scoped-style-important-007.html
 fails == scoped-style-dynamic-001.html scoped-style-dynamic-001.html
 fails == scoped-style-dynamic-002.html scoped-style-dynamic-002.html
 fails == scoped-style-dynamic-003.html scoped-style-dynamic-003.html
 fails == scoped-style-dynamic-004.html scoped-style-dynamic-004.html
-== scoped-style-dynamic-005.html scoped-style-dynamic-005.html
-fails == scoped-style-dynamic-006.html scoped-style-dynamic-006.html
+asserts-if(stylo,1) == scoped-style-dynamic-005.html scoped-style-dynamic-005.html # bug 1335340
+fails asserts-if(stylo,1) == scoped-style-dynamic-006.html scoped-style-dynamic-006.html # bug 1335340
 fails == scoped-style-dynamic-007.html scoped-style-dynamic-007.html
 fails == scoped-style-dynamic-008.html scoped-style-dynamic-008.html
-fails == scoped-style-dynamic-009.html scoped-style-dynamic-009.html
-== scoped-style-dynamic-010.html scoped-style-dynamic-010.html
+fails asserts-if(stylo,1) == scoped-style-dynamic-009.html scoped-style-dynamic-009.html # bug 1335340
+asserts-if(stylo,1) == scoped-style-dynamic-010.html scoped-style-dynamic-010.html # bug 1335340
 fails == scoped-style-dynamic-011.html scoped-style-dynamic-011.html
 == scoped-style-dynamic-012.svg scoped-style-dynamic-012.svg
 == scoped-style-dynamic-013.svg scoped-style-dynamic-013.svg
 == scoped-style-dynamic-014.svg scoped-style-dynamic-014.svg
 == scoped-style-dynamic-015.svg scoped-style-dynamic-015.svg
 fails == scoped-style-import.html scoped-style-import.html
 fails == scoped-style-media.html scoped-style-media.html
 fails == scoped-style-namespace.html scoped-style-namespace.html
--- a/layout/reftests/selection/reftest-stylo.list
+++ b/layout/reftests/selection/reftest-stylo.list
@@ -28,11 +28,11 @@ fuzzy-if(skiaContent,1,700) == extend-3i
 # these 3 random-if(Android) are a difference of Native & Xul, see bug 739714
 fails == pseudo-element-of-native-anonymous.html pseudo-element-of-native-anonymous.html
 # These tests uses Highlight and HighlightText color keywords, they are not same as text selection color on Mac.
 fails == non-themed-widget.html non-themed-widget.html
 fails == themed-widget.html themed-widget.html
 == addrange-1.html addrange-1.html
 == addrange-2.html addrange-2.html
 fails == splitText-normalize.html splitText-normalize.html
-fails == modify-range.html modify-range.html
+fails asserts-if(stylo,13) == modify-range.html modify-range.html # bug 1324683
 fails == dom-mutations.html dom-mutations.html
 == trailing-space-1.html trailing-space-1.html
--- a/layout/reftests/table-bordercollapse/reftest-stylo.list
+++ b/layout/reftests/table-bordercollapse/reftest-stylo.list
@@ -11,19 +11,19 @@
 == bc_dyn_rg2.html bc_dyn_rg2.html
 == bc_dyn_rg3.html bc_dyn_rg3.html
 == bc_dyn_col1.html bc_dyn_col1.html
 == bc_dyn_col2.html bc_dyn_col2.html
 == bc_dyn_col3.html bc_dyn_col3.html
 == bc_dyn_cg1.html bc_dyn_cg1.html
 == bc_dyn_cg2.html bc_dyn_cg2.html
 == bc_dyn_cg3.html bc_dyn_cg3.html
-fails == bc_dyn_table1.html bc_dyn_table1.html
-fails == bc_dyn_table2.html bc_dyn_table2.html
-fails == bc_dyn_table3.html bc_dyn_table3.html
+fails asserts-if(stylo,2) == bc_dyn_table1.html bc_dyn_table1.html # bug 1324661
+fails asserts-if(stylo,2) == bc_dyn_table2.html bc_dyn_table2.html # bug 1324661
+fails asserts-if(stylo,2) == bc_dyn_table3.html bc_dyn_table3.html # bug 1324661
 == bc_borderoffset1.html bc_borderoffset1.html
 == bc_borderoffset2.html bc_borderoffset2.html
 == frame_above_rules_all.html frame_above_rules_all.html
 == frame_above_rules_cols.html frame_above_rules_cols.html
 == frame_above_rules_groups.html frame_above_rules_groups.html
 == frame_above_rules_none.html frame_above_rules_none.html
 == frame_above_rules_rows.html frame_above_rules_rows.html
 == frame_below_rules_all.html frame_below_rules_all.html
--- a/layout/reftests/text-overflow/reftest-stylo.list
+++ b/layout/reftests/text-overflow/reftest-stylo.list
@@ -1,17 +1,17 @@
 # DO NOT EDIT! This is a auto-generated temporary list for Stylo testing
 fails == ellipsis-font-fallback.html ellipsis-font-fallback.html
 fails == line-clipping.html line-clipping.html
 fails == marker-basic.html marker-basic.html
 fails HTTP(..) == marker-string.html marker-string.html
 # == bidi-simple.html bidi-simple.html
 fails == bidi-simple-scrolled.html bidi-simple-scrolled.html
 fails == scroll-rounding.html scroll-rounding.html
-fuzzy(2,453) fuzzy-if(skiaContent,9,2100) fails-if(gtkWidget) HTTP(..) == anonymous-block.html anonymous-block.html
+fuzzy(2,453) fuzzy-if(skiaContent,9,2100) fails-if(gtkWidget) asserts-if(stylo,4) HTTP(..) == anonymous-block.html anonymous-block.html # bug 1324671
 fails HTTP(..) == false-marker-overlap.html false-marker-overlap.html
 fails HTTP(..) == visibility-hidden.html visibility-hidden.html
 # == block-padding.html block-padding.html
 fails HTTP(..) == quirks-decorations.html quirks-decorations.html
 fails HTTP(..) == quirks-line-height.html quirks-line-height.html
 fails HTTP(..) == standards-decorations.html standards-decorations.html
 fails HTTP(..) == standards-line-height.html standards-line-height.html
 fails == selection.html selection.html
--- a/layout/reftests/web-animations/reftest-stylo.list
+++ b/layout/reftests/web-animations/reftest-stylo.list
@@ -1,12 +1,12 @@
 # DO NOT EDIT! This is a auto-generated temporary list for Stylo testing
 test-pref(dom.animations-api.core.enabled,true) == 1246046-1.html 1246046-1.html
 test-pref(dom.animations-api.core.enabled,true) == 1267937-1.html 1267937-1.html
-fails test-pref(dom.animations-api.core.enabled,true) == 1298742-1.html 1298742-1.html
+fails test-pref(dom.animations-api.core.enabled,true) asserts-if(stylo,8) == 1298742-1.html 1298742-1.html # bug 1335342
 fails test-pref(dom.animations-api.core.enabled,true) == stacking-context-transform-none-animation-before-appending-element.html stacking-context-transform-none-animation-before-appending-element.html
 # test-pref(dom.animations-api.core.enabled,true) == stacking-context-opacity-changing-keyframe.html stacking-context-opacity-changing-keyframe.html
 # test-pref(dom.animations-api.core.enabled,true) == stacking-context-opacity-changing-keyframe-in-delay.html stacking-context-opacity-changing-keyframe-in-delay.html
 # test-pref(dom.animations-api.core.enabled,true) == stacking-context-opacity-changing-target.html stacking-context-opacity-changing-target.html
 # test-pref(dom.animations-api.core.enabled,true) == stacking-context-opacity-changing-target-in-delay.html stacking-context-opacity-changing-target-in-delay.html
 # test-pref(dom.animations-api.core.enabled,true) == stacking-context-opacity-changing-effect.html stacking-context-opacity-changing-effect.html
 # test-pref(dom.animations-api.core.enabled,true) == stacking-context-opacity-losing-css-animation-in-delay.html stacking-context-opacity-losing-css-animation-in-delay.html
 # test-pref(dom.animations-api.core.enabled,true) == stacking-context-transform-changing-keyframe.html stacking-context-transform-changing-keyframe.html
--- a/layout/reftests/writing-mode/reftest-stylo.list
+++ b/layout/reftests/writing-mode/reftest-stylo.list
@@ -11,18 +11,18 @@ fails == 1083848-3-inline-background-rep
 == 1086883-1a.html 1086883-1a.html
 == 1086883-1b.html 1086883-1b.html
 # == 1088025-1.html 1088025-1.html
 # == 1089388-1.html 1089388-1.html
 # == 1089388-2.html 1089388-2.html
 # == 1090159-1.html 1090159-1.html
 # == 1090168-1.html 1090168-1.html
 # == 1090168-1.html 1090168-1.html
-fails == 1090168-2.html 1090168-2.html
-fails == 1090168-3.html 1090168-3.html
+fails asserts-if(stylo,1) == 1090168-2.html 1090168-2.html # bug 1324700
+fails asserts-if(stylo,1) == 1090168-3.html 1090168-3.html # bug 1324700
 # == 1091058-1.html 1091058-1.html
 fails == 1094434-1.html 1094434-1.html
 fails == 1094434-2.html 1094434-2.html
 == 1094914-1a.html 1094914-1a.html
 == 1094914-1b.html 1094914-1b.html
 == 1096224-1a.html 1096224-1a.html
 == 1096224-1b.html 1096224-1b.html
 # == 1102175-1a.html 1102175-1a.html
@@ -64,17 +64,17 @@ fails == ua-style-sheet-size-2.html ua-s
 
 # == ua-style-sheet-fieldset-1.html ua-style-sheet-fieldset-1.html
 # == ua-style-sheet-textarea-1.html ua-style-sheet-textarea-1.html
 # == ua-style-sheet-textarea-1.html ua-style-sheet-textarea-1.html
 # == ua-style-sheet-textarea-1.html ua-style-sheet-textarea-1.html
 # == ua-style-sheet-checkbox-radio-1.html ua-style-sheet-checkbox-radio-1.html
 # == ua-style-sheet-button-1.html ua-style-sheet-button-1.html
 # == ua-style-sheet-button-1.html ua-style-sheet-button-1.html
-fails == ua-style-sheet-input-color-1.html ua-style-sheet-input-color-1.html
+fails asserts-if(stylo,6) == ua-style-sheet-input-color-1.html ua-style-sheet-input-color-1.html # bug 1324671
 # fuzzy-if(gtkWidget,1,15) == ua-style-sheet-input-number-1.html ua-style-sheet-input-number-1.html
 
 # HTTP(..) == 1127488-align-default-horizontal-tb-ltr.html 1127488-align-default-horizontal-tb-ltr.html
 # HTTP(..) == 1127488-align-start-horizontal-tb-ltr.html 1127488-align-start-horizontal-tb-ltr.html
 # HTTP(..) == 1127488-align-end-horizontal-tb-ltr.html 1127488-align-end-horizontal-tb-ltr.html
 # HTTP(..) == 1127488-align-left-horizontal-tb-ltr.html 1127488-align-left-horizontal-tb-ltr.html
 # HTTP(..) == 1127488-align-right-horizontal-tb-ltr.html 1127488-align-right-horizontal-tb-ltr.html
 # HTTP(..) == 1127488-align-default-horizontal-tb-rtl.html 1127488-align-default-horizontal-tb-rtl.html
--- a/layout/reftests/writing-mode/tables/reftest-stylo.list
+++ b/layout/reftests/writing-mode/tables/reftest-stylo.list
@@ -3,17 +3,17 @@
 == vertical-table-1b.html vertical-table-1b.html
 == vertical-table-2a.html vertical-table-2a.html
 == vertical-table-2b.html vertical-table-2b.html
 == vertical-table-rowspan-1.html vertical-table-rowspan-1.html
 == vertical-table-rowspan-2.html vertical-table-rowspan-2.html
 == vertical-table-colspan-1.html vertical-table-colspan-1.html
 == vertical-table-colspan-2.html vertical-table-colspan-2.html
 == vertical-table-specified-width-1.html vertical-table-specified-width-1.html
-asserts(1) == vertical-table-specified-width-2.html vertical-table-specified-width-2.html
+asserts(1-2) == vertical-table-specified-width-2.html vertical-table-specified-width-2.html
 == vertical-border-collapse-1.html vertical-border-collapse-1.html
 == vertical-border-collapse-2.html vertical-border-collapse-2.html
 
 # == fixed-table-layout-002-vlr.html fixed-table-layout-002-vlr.html
 # == fixed-table-layout-003-vlr.html fixed-table-layout-003-vlr.html
 # == fixed-table-layout-004-vlr.html fixed-table-layout-004-vlr.html
 # == fixed-table-layout-005-vlr.html fixed-table-layout-005-vlr.html
 # == fixed-table-layout-006-vlr.html fixed-table-layout-006-vlr.html
--- a/layout/style/crashtests/crashtests.list
+++ b/layout/style/crashtests/crashtests.list
@@ -71,25 +71,25 @@ load 592698-1.html
 asserts-if(stylo,2) load 601437-1.html # bug 1324634
 load 601439-1.html
 load 605689-1.html
 load 611922-1.html
 load 621596-1.html
 load 622314-1.xhtml
 load 637242.xhtml
 load 645142.html
-fails-if(stylo) asserts-if(stylo,3-4) == 645951-1.html 645951-1-ref.html # bug 1324621
+fails-if(stylo) == 645951-1.html 645951-1-ref.html
 load 652976-1.svg
 load 665209-1.html
 load 671799-1.html
 load 671799-2.html
 skip-if(stylo) load 690990-1.html # bug 1323708
 load 696188-1.html
 load 696869-1.html
-asserts-if(stylo,4) load 700116.html # bug 1324635
+asserts-if(stylo,2) load 700116.html # bug 1324635
 load 729126-1.html
 load 729126-2.html
 load 786108-1.html
 load 786108-2.html
 load 788836.html
 load 806310-1.html
 load 812824.html
 load 822766-1.html
@@ -149,23 +149,23 @@ load font-face-truncated-src.html
 load large_border_image_width.html
 load long-url-list-stack-overflow.html
 pref(layout.css.background-clip-text.enabled,true) load 1264949.html
 pref(layout.css.background-clip-text.enabled,true) load 1270795.html
 pref(layout.css.background-clip-text.enabled,true) load 1275026.html
 load 1278463-1.html
 skip-if(stylo) pref(dom.animations-api.core.enabled,true) load 1277908-1.html # bug 1323652
 skip-if(stylo) load 1277908-2.html # bug 1323652
-asserts-if(stylo,2-62) load 1282076-1.html # bug 1324669
-asserts-if(stylo,2) pref(dom.animations-api.core.enabled,true) load 1282076-2.html # bug 1324686
+load 1282076-1.html
+pref(dom.animations-api.core.enabled,true) load 1282076-2.html
 pref(dom.animations-api.core.enabled,true) load 1290994-1.html
 pref(dom.animations-api.core.enabled,true) load 1290994-2.html
 pref(dom.animations-api.core.enabled,true) load 1290994-3.html
 load 1290994-4.html
 load 1314531.html
 load 1315889-1.html
 load 1315894-1.html
 skip-if(stylo) load 1319072-1.html # bug 1323733
 HTTP load 1320423-1.html
-asserts-if(stylo,5-28) load 1321357-1.html # bug 1324669
+load 1321357-1.html
 load 1328535-1.html
 load 1331272.html
-asserts-if(stylo,4) HTTP load 1333001-1.html
+asserts-if(stylo,1) HTTP load 1333001-1.html # bug 1324702
--- a/layout/svg/crashtests/crashtests.list
+++ b/layout/svg/crashtests/crashtests.list
@@ -15,64 +15,64 @@ load 325427-1.svg
 load 326495-1.svg
 load 326974-1.svg
 load 327706-1.svg
 load 327709-1.svg
 load 327711-1.svg
 load 328137-1.svg
 load 329848-1.svg
 load 337408-1.xul
-asserts-if(stylo,2) load 338301-1.xhtml # bug 1324669
-asserts-if(stylo,2) load 338312-1.xhtml # bug 1324669
+load 338301-1.xhtml
+load 338312-1.xhtml
 load 340083-1.svg
 asserts-if(stylo,1) load 340945-1.svg # bug 1324647
 load 342923-1.html
-asserts-if(stylo,2) load 343221-1.xhtml # bug 1324669
+load 343221-1.xhtml
 load 344749-1.svg
 load 344887-1.svg
 load 344892-1.svg
 load 344898-1.svg
 load 344904-1.svg
 load 345418-1.svg
-asserts-if(stylo,2) load 348982-1.xhtml # bug 1324669
-asserts-if(stylo,1) load 354777-1.xhtml # bug 1324669
+load 348982-1.xhtml
+load 354777-1.xhtml
 load 359516-1.svg
 load 361015-1.svg
 asserts-if(stylo,0-2) load 361587-1.svg # bug 1324677
-asserts-if(stylo,2) load 363611-1.xhtml # bug 1324669
+load 363611-1.xhtml
 load 364688-1.svg
 load 366956-1.svg
 load 366956-2.svg
 load 367111-1.svg
-asserts-if(stylo,2) load 367368-1.xhtml # bug 1324669
+load 367368-1.xhtml
 load 369233-1.svg
 load 369438-1.svg
 load 369438-2.svg
-asserts-if(stylo,2) load 371463-1.xhtml # bug 1324669
-asserts-if(stylo,2) load 371563-1.xhtml # bug 1324669
+load 371463-1.xhtml
+load 371563-1.xhtml
 load 375775-1.svg
 load 378716.svg
 load 380691-1.svg
 load 384391-1.xhtml
 load 384499-1.svg
 load 384637-1.svg
 load 384728-1.svg
 load 385246-1.svg
 load 385246-2.svg
 load 385552-1.svg
 load 385552-2.svg
 load 385840-1.svg
 load 385852-1.svg
-asserts-if(stylo,2) load 386475-1.xhtml # bug 1324669
+load 386475-1.xhtml
 load 386566-1.svg
 load 386690-1.svg
 load 387290-1.svg
 load 402408-1.svg
-asserts-if(stylo,2) load 404677-1.xhtml # bug 1324669
-asserts-if(stylo,2) load 409565-1.xhtml # bug 1324669
+load 404677-1.xhtml
+load 409565-1.xhtml
 load 409573-1.svg
 load 420697-1.svg
 load 420697-2.svg
 load 429774-1.svg
 load 441368-1.svg
 load 453754-1.svg
 load 455314-1.xhtml
 load 458453.html
@@ -101,17 +101,17 @@ load 522394-1.svg
 load 522394-2.svg
 load 522394-3.svg
 load 566216-1.svg
 load 587336-1.html
 load 590291-1.svg
 load 601999-1.html
 load 605626-1.svg
 asserts(2) asserts-if(stylo,0) load 606914.xhtml # bug 606914
-asserts-if(stylo,2) load 610594-1.html # bug 1324669
+load 610594-1.html
 load 610954-1.html
 load 612662-1.svg
 load 612662-2.svg
 load 612736-1.svg
 load 612736-2.svg
 load 614367-1.svg
 load 620034-1.html
 load 621598-1.svg
@@ -134,23 +134,23 @@ load 725918-1.svg
 load 732836-1.svg
 load 740627-1.svg
 load 740627-2.svg
 load 743469.svg
 load 757704-1.svg
 load 757718-1.svg
 load 757751-1.svg
 load 767056-1.svg
-asserts-if(stylo,3) load 767535-1.xhtml # bug 1324669
-asserts-if(stylo,1-2) load 768087-1.html # bug 1324669
+load 767535-1.xhtml
+load 768087-1.html
 load 768351.svg
 load 778492-1.svg
 load 779971-1.svg
 load 780764-1.svg
-asserts-if(stylo,2) load 780963-1.html # bug 1324669
+load 780963-1.html
 load 782141-1.svg
 load 784061-1.svg
 load 788831-1.svg
 skip-if(stylo) load 789390-1.html # bug 1323652
 load 790072.svg
 load 791826-1.svg
 load 808318-1.svg
 load 803562-1.svg
@@ -176,26 +176,26 @@ load 885608-1.svg
 load 890782-1.svg
 load 890783-1.svg
 load 893510-1.svg
 load 895311-1.svg
 load 897342-1.svg
 load 898909-1.svg
 load 898951-1.svg
 load 913990.html
-asserts-if(stylo,2) load 919371-1.xhtml # bug 1324669
+load 919371-1.xhtml
 load 950324-1.svg
 load 952270-1.svg
 load 963086-1.svg
 load 974746-1.svg
 load 975773-1.svg
 load 979407-1.svg
 load 979407-2.svg
 load 993443.svg
 load 1016145.svg
 load 1028512.svg
 load 1140080-1.svg
 load 1149542-1.svg
 load 1156581-1.svg
-asserts-if(stylo,1) load 1182496-1.html # bug 1324669
+load 1182496-1.html
 load 1209525-1.svg
 load 1223281-1.svg
 load extref-test-1.xhtml
--- a/parser/htmlparser/tests/crashtests/crashtests.list
+++ b/parser/htmlparser/tests/crashtests/crashtests.list
@@ -40,17 +40,17 @@ asserts-if(stylo,1) load 502869.html # b
 load 515278-1.html
 load 515533-1.html
 load 515816-1.html
 load 522326-1.html
 load 525229-1.html
 load 536097-1.html
 load 555462.html
 load 563514-1.html
-asserts-if(stylo,2) load 574884-1.html # bug 1324669
+load 574884-1.html
 load 574884-2.html
 load 591330-1.html
 load 650501-1.xhtml
 asserts-if(stylo,1) load 696651-1.html # bug 1324683
 asserts-if(stylo,2) load view-source:699347-1.xml # bug 1324704
 load 721313-1.html
 asserts-if(stylo,5) load view-source:742414-1.html # bug 1324704
 load 981279-1.html
--- a/parser/htmlparser/tests/reftest/reftest-stylo.list
+++ b/parser/htmlparser/tests/reftest/reftest-stylo.list
@@ -1,27 +1,27 @@
 # DO NOT EDIT! This is a auto-generated temporary list for Stylo testing
 == bug535530-1.html bug535530-1.html
-fails == view-source:bug535530-2.html view-source:bug535530-2.html
+fails asserts-if(stylo,15) == view-source:bug535530-2.html view-source:bug535530-2.html # bug 1335312
 == bug566280-1.html bug566280-1.html
 == bug569229-1.xml bug569229-1.xml
 fails == bug577418-1.html bug577418-1.html
 == bug582788-1.html bug582788-1.html
 fails == bug582940-1.html bug582940-1.html
 == bug592656-1.html bug592656-1.html
 fails == bug599320-1.html bug599320-1.html
-== bug608373-1.html bug608373-1.html
-fails == view-source:bug482921-1.html view-source:bug482921-1.html
-fails == view-source:bug482921-2.xhtml view-source:bug482921-2.xhtml
+asserts-if(stylo,1) == bug608373-1.html bug608373-1.html # bug 1324683
+fails asserts-if(stylo,25) == view-source:bug482921-1.html view-source:bug482921-1.html # bug 1324704
+fails asserts-if(stylo,26) == view-source:bug482921-2.xhtml view-source:bug482921-2.xhtml # bug 1324704
 == bug659763-1.html bug659763-1.html
 == bug659763-2.html bug659763-2.html
 == bug659763-3.html bug659763-3.html
 == bug659763-4.html bug659763-4.html
 == bug659763-5.html bug659763-5.html
 == bug659763-6.html bug659763-6.html
-fails == view-source:bug673094-1.html view-source:bug673094-1.html
+fails asserts-if(stylo,10) == view-source:bug673094-1.html view-source:bug673094-1.html # bug 1324704
 == bug696651-1.html bug696651-1.html
 == bug696651-2.html bug696651-2.html
-fails == view-source:bug700260-1.html view-source:bug700260-1.html
-fails == view-source:bug704667-1.html view-source:bug704667-1.html
-fails == view-source:bug731234-1.html view-source:bug731234-1.html
+fails asserts-if(stylo,4) == view-source:bug700260-1.html view-source:bug700260-1.html # bug 1324704
+fails asserts-if(stylo,2) == view-source:bug704667-1.html view-source:bug704667-1.html # bug 1324704
+fails asserts-if(stylo,28) == view-source:bug731234-1.html view-source:bug731234-1.html # bug 1324704
 == bug820508-1.html bug820508-1.html
-fails == view-source:bug910588-1.html view-source:bug910588-1.html
+fails asserts-if(stylo,2) == view-source:bug910588-1.html view-source:bug910588-1.html # bug 1324704
--- a/taskcluster/ci/build/linux.yml
+++ b/taskcluster/ci/build/linux.yml
@@ -343,8 +343,34 @@ linux64-ccov/opt:
         config:
             - builds/releng_base_linux_64_builds.py
             - balrog/production.py
         script: "mozharness/scripts/fx_desktop_build.py"
         secrets: true
         custom-build-variant-cfg: code-coverage
         tooltool-downloads: public
         need-xvfb: true
+
+linux64-add-on-devel/opt:
+    description: "Linux64 add-on-devel"
+    index:
+        product: firefox
+        job-name: linux64-add-on-devel
+    treeherder:
+        platform: linux64-add-on-devel/opt
+        symbol: tc(B)
+        tier: 2
+    worker-type: aws-provisioner-v1/gecko-{level}-b-linux
+    worker:
+        implementation: docker-worker
+        max-run-time: 36000
+    run:
+        using: mozharness
+        actions: [get-secrets build check-test generate-build-stats update]
+        config:
+            - builds/releng_base_linux_64_builds.py
+            - balrog/production.py
+        script: "mozharness/scripts/fx_desktop_build.py"
+        secrets: true
+        custom-build-variant-cfg: add-on-devel
+        tooltool-downloads: public
+        need-xvfb: true
+    run-on-projects: [ 'mozilla-beta', 'mozilla-release', 'mozilla-esr45' ]
--- a/taskcluster/taskgraph/transforms/gecko_v2_whitelist.py
+++ b/taskcluster/taskgraph/transforms/gecko_v2_whitelist.py
@@ -46,16 +46,17 @@ JOB_NAME_WHITELIST = set([
     'linux64-stylo-opt',
     'linux64-valgrind-opt',
     'linux-debug',
     'linux-opt',
     'linux-pgo',
     'linux32-nightly-opt',
     'linux32-l10n-opt',
     'linux32-nightly-l10n-opt',
+    'linux64-add-on-devel',
     'macosx64-clang-tidy',
     'macosx64-debug',
     'macosx64-opt',
     'macosx64-st-an-opt',
     'nexus-5-l-eng-debug',
     'nexus-5-l-eng-opt',
     'osx-10-10',
     'shell-haz-debug',
--- a/toolkit/components/telemetry/Histograms.json
+++ b/toolkit/components/telemetry/Histograms.json
@@ -10716,10 +10716,34 @@
     "alert_emails": ["wmccloskey@mozilla.com"],
     "expires_in_version": "60",
     "kind": "exponential",
     "keyed": true,
     "high": 10000,
     "n_buckets": 10,
     "bug_numbers": [1331804],
     "description": "The time a given main thread runnable took to run (in milliseconds). The key comes from the runnables nsINamed::name value."
+  },
+  "MOZ_BLOB_IN_XHR": {
+    "alert_emails": ["amarchesini@mozilla.com"],
+    "expires_in_version": "58",
+    "kind": "boolean",
+    "bug_numbers": [1335365],
+    "releaseChannelCollection": "opt-out",
+    "description": "XMLHttpRequest.responseType set to moz-blob"
+  },
+  "MOZ_CHUNKED_TEXT_IN_XHR": {
+    "alert_emails": ["amarchesini@mozilla.com"],
+    "expires_in_version": "58",
+    "kind": "boolean",
+    "bug_numbers": [1335365],
+    "releaseChannelCollection": "opt-out",
+    "description": "XMLHttpRequest.responseType set to moz-chunked-text"
+  },
+  "MOZ_CHUNKED_ARRAYBUFFER_IN_XHR": {
+    "alert_emails": ["amarchesini@mozilla.com"],
+    "expires_in_version": "58",
+    "kind": "boolean",
+    "bug_numbers": [1335365],
+    "releaseChannelCollection": "opt-out",
+    "description": "XMLHttpRequest.responseType set to moz-chunked-arraybuffer"
   }
 }
--- a/toolkit/components/telemetry/TelemetryScalar.cpp
+++ b/toolkit/components/telemetry/TelemetryScalar.cpp
@@ -89,16 +89,17 @@ enum class ScalarResult : uint8_t {
   CannotRecordInProcess,
   CannotRecordDataset,
   KeyedTypeMismatch,
   UnknownScalar,
   OperationNotSupported,
   InvalidType,
   InvalidValue,
   // Keyed Scalar Errors
+  KeyIsEmpty,
   KeyTooLong,
   TooManyKeys,
   // String Scalar Errors
   StringTooLong,
   // Unsigned Scalar Errors
   UnsignedNegativeValue,
   UnsignedTruncatedValue
 };
@@ -688,16 +689,20 @@ KeyedScalar::GetValue(nsTArray<KeyValueP
 /**
  * Get the scalar for the referenced key.
  * If there's no such key, instantiate a new Scalar object with the
  * same type of the Keyed scalar and create the key.
  */
 ScalarResult
 KeyedScalar::GetScalarForKey(const nsAString& aKey, ScalarBase** aRet)
 {
+  if (aKey.IsEmpty()) {
+    return ScalarResult::KeyIsEmpty;
+  }
+
   if (aKey.Length() >= kMaximumKeyStringLength) {
     return ScalarResult::KeyTooLong;
   }
 
   if (mScalarKeys.Count() >= kMaximumNumberOfKeys) {
     return ScalarResult::TooManyKeys;
   }
 
@@ -816,16 +821,19 @@ internal_LogScalarError(const nsACString
       errorMessage.Append(NS_LITERAL_STRING(" - Attempted to set the scalar to an invalid data type."));
       break;
     case ScalarResult::InvalidValue:
       errorMessage.Append(NS_LITERAL_STRING(" - Attempted to set the scalar to an incompatible value."));
       break;
     case ScalarResult::StringTooLong:
       errorMessage.Append(NS_LITERAL_STRING(" - Truncating scalar value to 50 characters."));
       break;
+    case ScalarResult::KeyIsEmpty:
+      errorMessage.Append(NS_LITERAL_STRING(" - The key must not be empty."));
+      break;
     case ScalarResult::KeyTooLong:
       errorMessage.Append(NS_LITERAL_STRING(" - The key length must be limited to 70 characters."));
       break;
     case ScalarResult::TooManyKeys:
       errorMessage.Append(NS_LITERAL_STRING(" - Keyed scalars cannot have more than 100 keys."));
       break;
     case ScalarResult::UnsignedNegativeValue:
       errorMessage.Append(NS_LITERAL_STRING(" - Trying to set an unsigned scalar to a negative number."));
--- a/toolkit/components/telemetry/TelemetrySession.jsm
+++ b/toolkit/components/telemetry/TelemetrySession.jsm
@@ -729,18 +729,16 @@ var Impl = {
    * Gets a series of simple measurements (counters). At the moment, this
    * only returns startup data from nsIAppStartup.getStartupInfo().
    * @param {Boolean} isSubsession True if this is a subsession, false otherwise.
    * @param {Boolean} clearSubsession True if a new subsession is being started, false otherwise.
    *
    * @return simple measurements as a dictionary.
    */
   getSimpleMeasurements: function getSimpleMeasurements(forSavedSession, isSubsession, clearSubsession) {
-    this._log.trace("getSimpleMeasurements");
-
     let si = Services.startup.getStartupInfo();
 
     // Measurements common to chrome and content processes.
     let elapsedTime = Date.now() - si.process;
     var ret = {
       totalTime: Math.round(elapsedTime / 1000), // totalTime, in seconds
       uptime: Math.round(elapsedTime / 60000) // uptime in minutes
     }
@@ -884,19 +882,16 @@ var Impl = {
    * @return {Integer} A value from nsITelemetry.DATASET_*.
    */
   getDatasetType() {
     return Telemetry.canRecordExtended ? Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN
                                        : Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTOUT;
   },
 
   getHistograms: function getHistograms(subsession, clearSubsession) {
-    this._log.trace("getHistograms - subsession: " + subsession +
-                    ", clearSubsession: " + clearSubsession);
-
     let registered =
       Telemetry.registeredHistograms(this.getDatasetType(), []);
     if (this._testing == false) {
       // Omit telemetry test histograms outside of tests.
       registered = registered.filter(n => !n.startsWith("TELEMETRY_TEST_"));
     }
     registered = registered.concat(registered.map(n => "STARTUP_" + n));
 
@@ -914,18 +909,16 @@ var Impl = {
         }
       }
     }
 
     return ret;
   },
 
   getAddonHistograms: function getAddonHistograms() {
-    this._log.trace("getAddonHistograms");
-
     let ahs = Telemetry.addonHistogramSnapshots;
     let ret = {};
 
     for (let addonName in ahs) {
       let addonHistograms = ahs[addonName];
       let packedHistograms = {};
       for (let name in addonHistograms) {
         packedHistograms[name] = this.packHistogram(addonHistograms[name]);
@@ -933,19 +926,16 @@ var Impl = {
       if (Object.keys(packedHistograms).length != 0)
         ret[addonName] = packedHistograms;
     }
 
     return ret;
   },
 
   getKeyedHistograms(subsession, clearSubsession) {
-    this._log.trace("getKeyedHistograms - subsession: " + subsession +
-                    ", clearSubsession: " + clearSubsession);
-
     let registered =
       Telemetry.registeredKeyedHistograms(this.getDatasetType(), []);
     if (this._testing == false) {
       // Omit telemetry test histograms outside of tests.
       registered = registered.filter(id => !id.startsWith("TELEMETRY_TEST_"));
     }
     let ret = {};
 
@@ -984,35 +974,31 @@ var Impl = {
    * @param {subsession} If true, then we collect the data for a subsession.
    * @param {clearSubsession} If true, we  need to clear the subsession.
    * @param {keyed} Take a snapshot of keyed or non keyed scalars.
    * @return {Object} The scalar data as a Javascript object, including the
    *         data from child processes, in the following format:
    *            {'content': { 'scalarName': ... }, 'gpu': { ... } }
    */
   getScalars(subsession, clearSubsession, keyed) {
-    this._log.trace("getScalars - subsession: " + subsession + ", clearSubsession: " +
-                    clearSubsession + ", keyed: " + keyed);
-
     if (!subsession) {
       // We only support scalars for subsessions.
       this._log.trace("getScalars - We only support scalars in subsessions.");
       return {};
     }
 
     let scalarsSnapshot = keyed ?
       Telemetry.snapshotKeyedScalars(this.getDatasetType(), clearSubsession) :
       Telemetry.snapshotScalars(this.getDatasetType(), clearSubsession);
 
     // Don't return the test scalars.
     let ret = {};
     for (let processName in scalarsSnapshot) {
       for (let name in scalarsSnapshot[processName]) {
         if (name.startsWith("telemetry.test") && this._testing == false) {
-          this._log.trace("getScalars - Skipping test scalar: " + name);
           continue;
         }
         // Finally arrange the data in the returned object.
         if (!(processName in ret)) {
           ret[processName] = {};
         }
         ret[processName][name] = scalarsSnapshot[processName][name];
       }
@@ -1035,18 +1021,16 @@ var Impl = {
     if (!this._testing) {
       events = events.filter(e => !e[1].startsWith("telemetry.test"));
     }
 
     return events;
   },
 
   getThreadHangStats: function getThreadHangStats(stats) {
-    this._log.trace("getThreadHangStats");
-
     stats.forEach((thread) => {
       thread.activity = this.packHistogram(thread.activity);
       thread.hangs.forEach((hang) => {
         hang.histogram = this.packHistogram(hang.histogram);
       });
     });
     return stats;
   },
@@ -1055,18 +1039,16 @@ var Impl = {
    * Descriptive metadata
    *
    * @param  reason
    *         The reason for the telemetry ping, this will be included in the
    *         returned metadata,
    * @return The metadata as a JS object
    */
   getMetadata: function getMetadata(reason) {
-    this._log.trace("getMetadata - Reason " + reason);
-
     const sessionStartDate = Utils.toLocalTimeISOString(Utils.truncateToDays(this._sessionStartDate));
     const subsessionStartDate = Utils.toLocalTimeISOString(Utils.truncateToDays(this._subsessionStartDate));
     const monotonicNow = Policy.monotonicNow();
 
     let ret = {
       reason,
       revision: AppConstants.SOURCE_REVISION_URL,
       asyncPluginInit: Preferences.get(PREF_ASYNC_PLUGIN_INIT, false),
@@ -1107,22 +1089,19 @@ var Impl = {
     return ret;
   },
 
   /**
    * Pull values from about:memory into corresponding histograms
    */
   gatherMemory: function gatherMemory() {
     if (!Telemetry.canRecordExtended) {
-      this._log.trace("gatherMemory - Extended data recording disabled, skipping.");
       return;
     }
 
-    this._log.trace("gatherMemory");
-
     let mgr;
     try {
       mgr = Cc["@mozilla.org/memory-reporter-manager;1"].
             getService(Ci.nsIMemoryReporterManager);
     } catch (e) {
       // OK to skip memory reporters in xpcshell
       return;
     }
@@ -1605,17 +1584,16 @@ var Impl = {
         GCTelemetry.init();
       }
     }.bind(this), testing ? TELEMETRY_TEST_DELAY : TELEMETRY_DELAY);
 
     delayedTask.arm();
   },
 
   getFlashVersion: function getFlashVersion() {
-    this._log.trace("getFlashVersion");
     let host = Cc["@mozilla.org/plugin/host;1"].getService(Ci.nsIPluginHost);
     let tags = host.getPluginTags();
 
     for (let i = 0; i < tags.length; i++) {
       if (tags[i].name == "Shockwave Flash")
         return tags[i].version;
     }
 
@@ -1775,18 +1753,17 @@ var Impl = {
                                 .catch(e => this._log.error("saveShutdownPings - failed to submit saved-session ping", e)));
     }
 
     // Wait on pings to be saved.
     return Promise.all(p);
   },
 
 
-  testSavePendingPing: function testSaveHistograms() {
-    this._log.trace("testSaveHistograms");
+  testSavePendingPing() {
     let payload = this.getSessionPayload(REASON_SAVED_SESSION, false);
     let options = {
       addClientId: true,
       addEnvironment: true,
       overwrite: true,
     };
     return TelemetryController.addPendingPing(getPingType(payload), payload, options);
   },
--- a/toolkit/components/telemetry/TelemetryStorage.jsm
+++ b/toolkit/components/telemetry/TelemetryStorage.jsm
@@ -685,18 +685,16 @@ var TelemetryStorageImpl = {
 
   /**
    * Load an archived ping from disk.
    *
    * @param {string} id The pings id.
    * @return {promise<object>} Promise that is resolved with the ping data.
    */
   loadArchivedPing: Task.async(function*(id) {
-    this._log.trace("loadArchivedPing - id: " + id);
-
     const data = this._archivedPings.get(id);
     if (!data) {
       this._log.trace("loadArchivedPing - no ping with id: " + id);
       return Promise.reject(new Error("TelemetryStorage.loadArchivedPing - no ping with id " + id));
     }
 
     const path = getArchivedPingPath(id, new Date(data.timestampCreated), data.type);
     const pathCompressed = path + "lz4";
@@ -1728,17 +1726,16 @@ var TelemetryStorageImpl = {
         } else {
           this._log.error("removeDeletionPing - error removing ping", ex)
         }
       }
     }.bind(this)));
   }),
 
   isDeletionPing(aPingId) {
-    this._log.trace("isDeletionPing - id: " + aPingId);
     let pingInfo = this._pendingPings.get(aPingId);
     if (!pingInfo) {
       return false;
     }
 
     if (pingInfo.path != gDeletionPingFilePath) {
       return false;
     }
--- a/toolkit/components/telemetry/tests/unit/test_TelemetryScalars.js
+++ b/toolkit/components/telemetry/tests/unit/test_TelemetryScalars.js
@@ -468,27 +468,32 @@ add_task(function* test_keyed_keys_lengt
   // Set the value for a key within the length limits.
   Telemetry.keyedScalarSet(KEYED_UINT_SCALAR, NORMAL_KEY, 1);
 
   // Now try to set and modify the value for a very long key (must not throw).
   Telemetry.keyedScalarAdd(KEYED_UINT_SCALAR, LONG_KEY_STRING, 10);
   Telemetry.keyedScalarSet(KEYED_UINT_SCALAR, LONG_KEY_STRING, 1);
   Telemetry.keyedScalarSetMaximum(KEYED_UINT_SCALAR, LONG_KEY_STRING, 10);
 
+  // Also attempt to set the value for an empty key.
+  Telemetry.keyedScalarSet(KEYED_UINT_SCALAR, "", 1);
+
   // Make sure the key with the right length contains the expected value.
   let keyedScalars =
     getParentProcessScalars(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN, true);
   Assert.equal(Object.keys(keyedScalars[KEYED_UINT_SCALAR]).length, 1,
                "The keyed scalar must contain exactly 1 key.");
   Assert.ok(NORMAL_KEY in keyedScalars[KEYED_UINT_SCALAR],
             "The keyed scalar must contain the expected key.");
   Assert.equal(keyedScalars[KEYED_UINT_SCALAR][NORMAL_KEY], 1,
                "The key must contain the expected value.");
   Assert.ok(!(LONG_KEY_STRING in keyedScalars[KEYED_UINT_SCALAR]),
             "The data for the long key should not have been recorded.");
+  Assert.ok(!("" in keyedScalars[KEYED_UINT_SCALAR]),
+            "The data for the empty key should not have been recorded.");
 });
 
 add_task(function* test_keyed_max_keys() {
   Telemetry.clearScalars();
 
   // Generate the names for the first 100 keys.
   let keyNamesSet = new Set();
   for (let k = 0; k < 100; k++) {