Merge inbound to central, a=merge CLOSED TREE
authorWes Kocher <wkocher@mozilla.com>
Tue, 31 Jan 2017 15:13:44 -0800
changeset 468867 1d025ac534a6333a8170a59a95a8a3673d4028ee
parent 468828 c22bc80b4d44f8b710c154eed2b52a73a167b037 (current diff)
parent 468866 895ddf282ead4d4533313c43b7cfa0aa218981e3 (diff)
child 468868 7c3d24adb510d5fe159c63317aa40afeb408eac7
child 468875 a2ab9a94c28b626d4b3220f62987b39bb192c400
child 468878 def83f2468e024f518f504060eec0e1d7e60e03c
child 468911 42d74486a292f1348bcf5b77060174689e0ccd0a
child 468925 e160b7f04647b0be4d35a8608cf163c2247b7b95
child 468926 85da0608e024a19417c12ae8bf740ff63c21bd6d
child 468929 d68b5930fc82075e7a2f1c8bd3b2bf92bf629f20
child 468943 ea137ba5664287fe5871e51ce8ad65f77eb45f3b
child 468973 644f861ed41a52b4616de33c9c7ce189810e4ea9
child 469028 41503051063a3f2a629521379e204725283f7034
child 469060 c57d277f969d4997a8717908ba1a6afbfd826fd6
child 469081 49392c4e10a94572cc51f0f6776268f32507e3b5
child 469126 bde2b8c739d2d4b41fbd5fe5ae91848e34af97a0
child 469159 78a413a72a05560400fb4f97e2722ce4ad82341b
child 469160 7856c5539652fba2d1013f173c3ab5f84119b34b
child 469161 e99bb5cb3d5c57909caa244003952ea9914d21f2
child 469185 26b43ec3990306c9720ad7d4f053583239862f89
child 469221 9e0a3f4c1d426997dc5613b62ed6d87abfb06917
child 469222 45e1670c108259eb1124a35675f49cf642c0f3c9
child 469223 7167be7cbedf81adef2f15c679381d3e5dc46f13
child 469224 f82ea2f8e4f9b658bc7ee6ed6e61a1f5c3365487
child 469234 9acebcda093378f4b54049d018a6d71aad960897
child 469235 a7afe7a46a94e1a0e52fa6d3ee2d1b7319d8c763
child 469315 f55918f76117abb0f120b21a742c3705c2640225
child 469343 444d1ce8d640477da962ef5dea9cd29b11595d28
child 469345 932549d62ccb3cb05880ae4f29a48a2a773c2c89
child 469441 5537d0c2cdd5365030061564816e8818a963ad38
child 469463 c527928d3d5a53322f7d5f742781ffa1fba577f0
child 469494 e70825c26c5a8e20ba8642f9cd6393cf8843b81e
child 469534 d696fbd4c722c711bfb73e10b728039a949ed1c4
child 469535 7d6ac4c3f41c96e1ff9edd801aff42c9a643cbe1
child 469537 d302be60d91b977d28b8bfb956fac5beccb504c6
child 469630 dec9a2aa573808e22b71c15407e4c72325a19d5c
child 470512 b9ea1b7d8a5d236d5ac81e43ff93760221e52699
child 483023 290b93ea105716041059981efb1136ff90deb9f3
push id43551
push userbmo:kgilbert@mozilla.com
push dateTue, 31 Jan 2017 23:27:06 +0000
reviewersmerge
milestone54.0a1
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++) {