merge mozilla-inbound to mozilla-central. r=merge a=merge
authorSebastian Hengst <archaeopteryx@coole-files.de>
Tue, 17 Oct 2017 23:52:28 +0200
changeset 386756 f78d5947333422ab09ec23e3dab0d48538c9d6ad
parent 386755 77d38f80dce684bd6ce7a2235a25f579aad19792 (current diff)
parent 386655 1485df2619bce4f7f424d1f1ff6b883ed7f23b26 (diff)
child 386757 14cf6503b9f5bdd4154ea846ae49f3a509a7d779
child 386774 cb6e476eb2b5af1b5f074461b27d25e885794c0d
child 386837 5d96e43add50b18635bb7104a6aff7b801a3bec7
push id96301
push userarchaeopteryx@coole-files.de
push dateTue, 17 Oct 2017 22:06:44 +0000
treeherdermozilla-inbound@14cf6503b9f5 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge, merge
milestone58.0a1
first release with
nightly linux32
f78d59473334 / 58.0a1 / 20171017220415 / files
nightly linux64
f78d59473334 / 58.0a1 / 20171017220415 / files
nightly mac
f78d59473334 / 58.0a1 / 20171017220415 / files
nightly win32
f78d59473334 / 58.0a1 / 20171017220415 / files
nightly win64
f78d59473334 / 58.0a1 / 20171017220415 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
merge mozilla-inbound to mozilla-central. r=merge a=merge MozReview-Commit-ID: 2KL1o3EPUk
dom/base/test/mochitest.ini
dom/file/tests/test_fileapi.html
dom/file/tests/test_fileapi_slice.html
dom/media/tests/mochitest/mochitest.ini
intl/locales/Makefile.in
js/src/vm/NativeObject-inl.h
layout/painting/nsDisplayList.cpp
modules/libpref/init/all.js
--- a/browser/base/content/browser.css
+++ b/browser/base/content/browser.css
@@ -104,17 +104,17 @@ panelview[mainview] > .panel-header,
 panelview:not([title]) > .panel-header {
   display: none;
 }
 
 tabbrowser {
   -moz-binding: url("chrome://browser/content/tabbrowser.xml#tabbrowser");
 }
 
-.tabbrowser-tabs {
+#tabbrowser-tabs {
   -moz-binding: url("chrome://browser/content/tabbrowser.xml#tabbrowser-tabs");
 }
 
 #tabbrowser-tabs:not([overflow="true"]) ~ #alltabs-button,
 #tabbrowser-tabs[hasadjacentnewtabbutton]:not([overflow="true"]) ~ #new-tab-button,
 #tabbrowser-tabs[overflow="true"] > .tabbrowser-arrowscrollbox > .tabs-newtab-button,
 #tabbrowser-tabs:not([hasadjacentnewtabbutton]) > .tabbrowser-arrowscrollbox > .tabs-newtab-button,
 #TabsToolbar[customizing="true"] > #tabbrowser-tabs > .tabbrowser-arrowscrollbox > .tabs-newtab-button {
@@ -168,39 +168,39 @@ tabbrowser {
 }
 
 .tab-label:not([fadein]),
 .tab-throbber:not([fadein]),
 .tab-icon-image:not([fadein]) {
   display: none;
 }
 
-.tabbrowser-tabs[positionpinnedtabs] > .tabbrowser-tab[pinned] {
+#tabbrowser-tabs[positionpinnedtabs] > .tabbrowser-tab[pinned] {
   position: fixed !important;
   display: block; /* position:fixed already does this (bug 579776), but let's be explicit */
 }
 
-.tabbrowser-tabs[movingtab] > .tabbrowser-tab[selected] {
+#tabbrowser-tabs[movingtab] > .tabbrowser-tab[selected] {
   position: relative;
   z-index: 2;
   pointer-events: none; /* avoid blocking dragover events on scroll buttons */
 }
 
 .tabbrowser-tab[tabdrop-samewindow],
-.tabbrowser-tabs[movingtab] > .tabbrowser-tab[fadein]:not([selected]) {
+#tabbrowser-tabs[movingtab] > .tabbrowser-tab[fadein]:not([selected]) {
   transition: transform 200ms var(--animation-easing-function);
 }
 
 /* The next 3 rules allow dragging tabs slightly outside of the tabstrip
  * to make it easier to drag tabs. */
 #TabsToolbar[movingtab] {
   padding-bottom: 15px;
 }
 
-#TabsToolbar[movingtab] > .tabbrowser-tabs {
+#TabsToolbar[movingtab] > #tabbrowser-tabs {
   padding-bottom: 15px;
   margin-bottom: -15px;
 }
 
 #TabsToolbar[movingtab] + #nav-bar {
   margin-top: -15px;
   pointer-events: none;
 }
--- a/browser/base/content/browser.xul
+++ b/browser/base/content/browser.xul
@@ -629,17 +629,16 @@
              collapsed="true">
 
 #ifdef CAN_DRAW_IN_TITLEBAR
       <hbox class="titlebar-placeholder" type="pre-tabs"
             skipintoolbarset="true"/>
 #endif
 
       <tabs id="tabbrowser-tabs"
-            class="tabbrowser-tabs"
             tabbrowser="content"
             flex="1"
             setfocus="false"
             tooltip="tabbrowser-tab-tooltip"
             stopwatchid="FX_TAB_CLICK_MS">
         <tab class="tabbrowser-tab" selected="true" visuallyselected="true" fadein="true"/>
       </tabs>
 
--- a/browser/base/content/tabbrowser.css
+++ b/browser/base/content/tabbrowser.css
@@ -10,17 +10,17 @@
   -moz-binding: url("chrome://browser/content/tabbrowser.xml#tabbrowser-arrowscrollbox");
 }
 
 .tab-close-button {
   -moz-binding: url("chrome://browser/content/tabbrowser.xml#tabbrowser-close-tab-button");
 }
 
 .tab-close-button[pinned],
-.tabbrowser-tabs[closebuttons="activetab"] > .tabbrowser-tab > .tab-stack > .tab-content > .tab-close-button:not([selected="true"]),
+#tabbrowser-tabs[closebuttons="activetab"] > .tabbrowser-tab > .tab-stack > .tab-content > .tab-close-button:not([selected="true"]),
 .tab-icon-image:not([src]):not([pinned]):not([crashed])[selected],
 .tab-icon-image:not([src]):not([pinned]):not([crashed]):not([sharing]),
 .tab-icon-image[busy],
 .tab-throbber:not([busy]),
 .tab-icon-sound:not([soundplaying]):not([muted]):not([activemedia-blocked]),
 .tab-icon-sound[pinned],
 .tab-sharing-icon-overlay,
 .tab-icon-overlay {
@@ -78,17 +78,17 @@ tabpanels {
     image-rendering: -moz-crisp-edges;
   }
 }
 
 .closing-tabs-spacer {
   pointer-events: none;
 }
 
-.tabbrowser-tabs:not(:hover) > .tabbrowser-arrowscrollbox > .closing-tabs-spacer {
+#tabbrowser-tabs:not(:hover) > .tabbrowser-arrowscrollbox > .closing-tabs-spacer {
   transition: width .15s ease-out;
 }
 
 browser[blank],
 browser[pendingpaint] {
   opacity: 0;
 }
 
--- a/browser/components/preferences/in-content/main.xul
+++ b/browser/components/preferences/in-content/main.xul
@@ -167,20 +167,16 @@
               type="bool"/>
   <preference id="general.smoothScroll"
               name="general.smoothScroll"
               type="bool"/>
   <preference id="layout.spellcheckDefault"
               name="layout.spellcheckDefault"
               type="int"/>
 
-  <preference id="toolkit.telemetry.enabled"
-              name="toolkit.telemetry.enabled"
-              type="bool"/>
-
   <preference id="browser.preferences.defaultPerformanceSettings.enabled"
               name="browser.preferences.defaultPerformanceSettings.enabled"
               type="bool"/>
 
   <preference id="dom.ipc.processCount"
               name="dom.ipc.processCount"
               type="int"/>
 
--- a/browser/themes/shared/tabs.inc.css
+++ b/browser/themes/shared/tabs.inc.css
@@ -33,17 +33,17 @@ tabbrowser {
 
 :root[privatebrowsingmode=temporary] tabbrowser {
   /* Value for --in-content-page-background in aboutPrivateBrowsing.css */
   background-color: #25003e;
 }
 
 #tabbrowser-tabs,
 #tabbrowser-tabs > .tabbrowser-arrowscrollbox,
-.tabbrowser-tabs[positionpinnedtabs] > .tabbrowser-tab[pinned] {
+#tabbrowser-tabs[positionpinnedtabs] > .tabbrowser-tab[pinned] {
   min-height: var(--tab-min-height);
 }
 
 .tab-stack {
   min-height: inherit;
 }
 
 .tabbrowser-tab {
--- a/devtools/client/netmonitor/src/components/timings-panel.js
+++ b/devtools/client/netmonitor/src/components/timings-panel.js
@@ -19,24 +19,22 @@ const TIMINGS_END_PADDING = "80px";
  * Timings panel component
  * Display timeline bars that shows the total wait time for various stages
  */
 function TimingsPanel({ request }) {
   if (!request.eventTimings) {
     return null;
   }
 
-  const { timings, totalTime } = request.eventTimings;
+  const { timings, totalTime, offsets } = request.eventTimings;
   const timelines = types.map((type, idx) => {
     // Determine the relative offset for each timings box. For example, the
     // offset of third timings box will be 0 + blocked offset + dns offset
-    const offset = types
-      .slice(0, idx)
-      .reduce((acc, cur) => (acc + timings[cur] || 0), 0);
-    const offsetScale = offset / totalTime || 0;
+
+    const offsetScale = offsets[type] / totalTime || 0;
     const timelineScale = timings[type] / totalTime || 0;
 
     return div({
       key: type,
       id: `timings-summary-${type}`,
       className: "tabpanel-summary-container timings-container",
     },
       span({ className: "tabpanel-summary-label timings-label" },
--- a/devtools/client/netmonitor/src/utils/l10n.js
+++ b/devtools/client/netmonitor/src/utils/l10n.js
@@ -2,12 +2,10 @@
  * 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/. */
 
 "use strict";
 
 const { LocalizationHelper } = require("devtools/shared/l10n");
 
 const NET_STRINGS_URI = "devtools/client/locales/netmonitor.properties";
-const WEBCONSOLE_STRINGS_URI = "devtools/client/locales/webconsole.properties";
 
 exports.L10N = new LocalizationHelper(NET_STRINGS_URI);
-exports.WEBCONSOLE_L10N = new LocalizationHelper(WEBCONSOLE_STRINGS_URI);
--- a/devtools/server/actors/webconsole.js
+++ b/devtools/server/actors/webconsole.js
@@ -2119,17 +2119,18 @@ NetworkEventActor.prototype =
    *
    * @return object
    *         The response packet - network event timings.
    */
   onGetEventTimings: function () {
     return {
       from: this.actorID,
       timings: this._timings,
-      totalTime: this._totalTime
+      totalTime: this._totalTime,
+      offsets: this._offsets
     };
   },
 
   /** ****************************************************************
    * Listeners for new network event data coming from NetworkMonitor.
    ******************************************************************/
 
   /**
@@ -2328,19 +2329,20 @@ NetworkEventActor.prototype =
   /**
    * Add network event timing information.
    *
    * @param number total
    *        The total time of the network event.
    * @param object timings
    *        Timing details about the network event.
    */
-  addEventTimings: function (total, timings) {
+  addEventTimings: function (total, timings, offsets) {
     this._totalTime = total;
     this._timings = timings;
+    this._offsets = offsets;
 
     let packet = {
       from: this.actorID,
       type: "networkEventUpdate",
       updateType: "eventTimings",
       totalTime: total
     };
 
--- a/devtools/shared/webconsole/network-monitor.js
+++ b/devtools/shared/webconsole/network-monitor.js
@@ -908,17 +908,18 @@ NetworkMonitor.prototype = {
         status: response.status,
         statusText: response.statusText,
         headersSize: 0,
       }, "", true);
 
       // There also is never any timing events, so we can fire this
       // event with zeroed out values.
       let timings = this._setupHarTimings(httpActivity, true);
-      httpActivity.owner.addEventTimings(timings.total, timings.timings);
+      httpActivity.owner.addEventTimings(timings.total, timings.timings,
+                                         timings.offsets);
     }
   },
 
   /**
    * Observe notifications for the http-on-modify-request topic, coming from
    * the nsIObserverService.
    *
    * @private
@@ -1358,17 +1359,18 @@ NetworkMonitor.prototype = {
    * from the list of known open requests.
    *
    * @private
    * @param object httpActivity
    *        The HTTP activity object we work with.
    */
   _onTransactionClose: function (httpActivity) {
     let result = this._setupHarTimings(httpActivity);
-    httpActivity.owner.addEventTimings(result.total, result.timings);
+    httpActivity.owner.addEventTimings(result.total, result.timings,
+                                       result.offsets);
     this.openRequests.delete(httpActivity.channel);
   },
 
   /**
    * Update the HTTP activity object to include timing information as in the HAR
    * spec. The HTTP activity object holds the raw timing information in
    * |timings| - these are timings stored for each activity notification. The
    * HAR timing information is constructed based on these lower level
@@ -1392,22 +1394,41 @@ NetworkMonitor.prototype = {
         timings: {
           blocked: 0,
           dns: 0,
           ssl: 0,
           connect: 0,
           send: 0,
           wait: 0,
           receive: 0
+        },
+        offsets: {
+          blocked: 0,
+          dns: 0,
+          ssl: 0,
+          connect: 0,
+          send: 0,
+          wait: 0,
+          receive: 0
         }
       };
     }
 
     let timings = httpActivity.timings;
     let harTimings = {};
+    // If the TCP Fast Open option or tls1.3 0RTT is used tls and data can
+    // be dispatched in SYN packet and not after tcp socket is connected.
+    // To demostrate this properly we will calculated TLS and send start time
+    // relative to CONNECTING_TO.
+    // Similary if 0RTT is used, data can be sent as soon as a TLS handshake
+    // starts.
+    let secureConnectionStartTime = 0;
+    let secureConnectionStartTimeRelative = false;
+    let startSendingTime = 0;
+    let startSendingTimeRelative = false;
 
     if (timings.STATUS_RESOLVING && timings.STATUS_CONNECTING_TO) {
       harTimings.blocked = timings.STATUS_RESOLVING.first -
                            timings.REQUEST_HEADER.first;
     } else if (timings.STATUS_SENDING_TO) {
       harTimings.blocked = timings.STATUS_SENDING_TO.first -
                            timings.REQUEST_HEADER.first;
     } else {
@@ -1425,45 +1446,120 @@ NetworkMonitor.prototype = {
                            timings.STATUS_CONNECTING_TO.first;
     } else {
       harTimings.connect = -1;
     }
 
     if (timings.STATUS_TLS_STARTING && timings.STATUS_TLS_ENDING) {
       harTimings.ssl = timings.STATUS_TLS_ENDING.last -
                            timings.STATUS_TLS_STARTING.first;
+      if (timings.STATUS_CONNECTING_TO) {
+        secureConnectionStartTime =
+          timings.STATUS_TLS_STARTING.first - timings.STATUS_CONNECTING_TO.first;
+      }
+      if (secureConnectionStartTime < 0) {
+        secureConnectionStartTime = 0;
+      }
+      secureConnectionStartTimeRelative = true;
     } else {
       harTimings.ssl = -1;
     }
 
     // sometimes the connection information events are attached to a speculative
     // channel instead of this one, but necko might glue them back together in the
     // nsITimedChannel interface used by Resource and Navigation Timing
     let timedChannel = httpActivity.channel.QueryInterface(Ci.nsITimedChannel);
 
-    if ((harTimings.connect <= 0) && timedChannel) {
-      if (timedChannel.secureConnectionStartTime > timedChannel.connectStartTime) {
-        harTimings.connect =
-          timedChannel.secureConnectionStartTime - timedChannel.connectStartTime;
-        harTimings.ssl =
-          timedChannel.connectEndTime - timedChannel.secureConnectionStartTime;
-      } else {
-        harTimings.connect =
-          timedChannel.connectEndTime - timedChannel.connectStartTime;
-        harTimings.ssl = -1;
+    let tcTcpConnectEndTime = 0;
+    let tcConnectStartTime = 0;
+    let tcConnectEndTime = 0;
+    let tcSecureConnectionStartTime = 0;
+    let tcDomainLookupEndTime = 0;
+    let tcDomainLookupStartTime = 0;
+
+    if (timedChannel) {
+      tcTcpConnectEndTime = timedChannel.tcpConnectEndTime;
+      tcConnectStartTime = timedChannel.connectStartTime;
+      tcConnectEndTime = timedChannel.connectEndTime;
+      tcSecureConnectionStartTime = timedChannel.secureConnectionStartTime;
+      tcDomainLookupEndTime = timedChannel.domainLookupEndTime;
+      tcDomainLookupStartTime = timedChannel.domainLookupStartTime;
+    }
+
+    // Make sure the above values are at least timedChannel.asyncOpenTime.
+    if (timedChannel && timedChannel.asyncOpenTime) {
+      if ((tcTcpConnectEndTime != 0) &&
+          (tcTcpConnectEndTime < timedChannel.asyncOpenTime)) {
+        tcTcpConnectEndTime = 0;
+      }
+      if ((tcConnectStartTime != 0) &&
+          (tcConnectStartTime < timedChannel.asyncOpenTime)) {
+        tcConnectStartTime = 0;
+      }
+      if ((tcConnectEndTime != 0) &&
+          (tcConnectEndTime < timedChannel.asyncOpenTime)) {
+        tcConnectEndTime = 0;
+      }
+      if ((tcSecureConnectionStartTime != 0) &&
+          (tcSecureConnectionStartTime < timedChannel.asyncOpenTime)) {
+        tcSecureConnectionStartTime = 0;
+      }
+      if ((tcDomainLookupEndTime != 0) &&
+          (tcDomainLookupEndTime < timedChannel.asyncOpenTime)) {
+        tcDomainLookupEndTime = 0;
+      }
+      if ((tcDomainLookupStartTime != 0) &&
+          (tcDomainLookupStartTime < timedChannel.asyncOpenTime)) {
+        tcDomainLookupStartTime = 0;
       }
     }
 
-    if ((harTimings.dns <= 0) && timedChannel) {
-      harTimings.dns =
-        timedChannel.domainLookupEndTime - timedChannel.domainLookupStartTime;
+    if ((harTimings.connect <= 0) && timedChannel &&
+        (tcTcpConnectEndTime != 0) && (tcConnectStartTime != 0)) {
+      harTimings.connect = tcTcpConnectEndTime - tcConnectStartTime;
+      if (tcSecureConnectionStartTime != 0) {
+        harTimings.ssl = tcConnectEndTime - tcSecureConnectionStartTime;
+        secureConnectionStartTime =
+          tcSecureConnectionStartTime - tcConnectStartTime;
+        secureConnectionStartTimeRelative = true;
+      } else {
+        harTimings.ssl = -1;
+      }
+    } else if (timedChannel && timings.STATUS_TLS_STARTING &&
+               (tcSecureConnectionStartTime != 0)) {
+      // It can happen that TCP Fast Open actually have not sent any data and
+      // timings.STATUS_TLS_STARTING.first value will be corrected in
+      // timedChannel.secureConnectionStartTime
+      if (tcSecureConnectionStartTime > timings.STATUS_TLS_STARTING.first) {
+        // TCP Fast Open actually did not sent any data.
+        harTimings.ssl =
+          tcConnectEndTime - tcSecureConnectionStartTime;
+        secureConnectionStartTimeRelative = false;
+      }
+    }
+
+    if ((harTimings.dns <= 0) && timedChannel &&
+        (tcDomainLookupEndTime != 0) && (tcDomainLookupStartTime != 0)) {
+      harTimings.dns = tcDomainLookupEndTime - tcDomainLookupStartTime;
     }
 
     if (timings.STATUS_SENDING_TO) {
-      harTimings.send = timings.STATUS_SENDING_TO.last - timings.STATUS_SENDING_TO.first;
+      harTimings.send =
+        timings.STATUS_SENDING_TO.last - timings.STATUS_SENDING_TO.first;
+      if (timings.STATUS_CONNECTING_TO) {
+        startSendingTime =
+          timings.STATUS_SENDING_TO.first - timings.STATUS_CONNECTING_TO.first;
+        startSendingTimeRelative = true;
+      } else if (tcConnectStartTime != 0) {
+        startSendingTime = timings.STATUS_SENDING_TO.first - tcConnectStartTime;
+        startSendingTimeRelative = true;
+      }
+      if (startSendingTime < 0) {
+        startSendingTime = 0;
+      }
     } else if (timings.REQUEST_HEADER && timings.REQUEST_BODY_SENT) {
       harTimings.send = timings.REQUEST_BODY_SENT.last - timings.REQUEST_HEADER.first;
     } else {
       harTimings.send = -1;
     }
 
     if (timings.RESPONSE_START) {
       harTimings.wait = timings.RESPONSE_START.first -
@@ -1475,28 +1571,82 @@ NetworkMonitor.prototype = {
 
     if (timings.RESPONSE_START && timings.RESPONSE_COMPLETE) {
       harTimings.receive = timings.RESPONSE_COMPLETE.last -
                            timings.RESPONSE_START.first;
     } else {
       harTimings.receive = -1;
     }
 
+    if (secureConnectionStartTimeRelative) {
+      let time = Math.max(Math.round(secureConnectionStartTime / 1000), -1);
+      secureConnectionStartTime = time;
+    }
+    if (startSendingTimeRelative) {
+      let time = Math.max(Math.round(startSendingTime / 1000), -1);
+      startSendingTime = time;
+    }
+
+    let ot = this._calculateOffsetAndTotalTime(harTimings,
+                                               secureConnectionStartTime,
+                                               startSendingTimeRelative,
+                                               secureConnectionStartTimeRelative,
+                                               startSendingTime);
+    return {
+      total: ot.total,
+      timings: harTimings,
+      offsets: ot.offsets
+    };
+  },
+
+  _calculateOffsetAndTotalTime: function (harTimings,
+                                          secureConnectionStartTime,
+                                          startSendingTimeRelative,
+                                          secureConnectionStartTimeRelative,
+                                          startSendingTime) {
     let totalTime = 0;
     for (let timing in harTimings) {
       let time = Math.max(Math.round(harTimings[timing] / 1000), -1);
       harTimings[timing] = time;
-      if (time > -1) {
+      if ((time > -1) && (timing != "connect") && (timing != "ssl")) {
         totalTime += time;
       }
     }
 
+    // connect, ssl and send times can be overlapped.
+    if (startSendingTimeRelative) {
+      totalTime += startSendingTime;
+    } else if (secureConnectionStartTimeRelative) {
+      totalTime += secureConnectionStartTime;
+      totalTime += harTimings.ssl;
+    }
+
+    let offsets = {};
+    offsets.blocked = 0;
+    offsets.dns = harTimings.blocked;
+    offsets.connect = offsets.dns + harTimings.dns;
+    if (secureConnectionStartTimeRelative) {
+      offsets.ssl = offsets.connect + secureConnectionStartTime;
+    } else {
+      offsets.ssl = offsets.connect + harTimings.connect;
+    }
+    if (startSendingTimeRelative) {
+      offsets.send = offsets.connect + startSendingTime;
+      if (!secureConnectionStartTimeRelative) {
+        offsets.ssl = offsets.send - harTimings.ssl;
+      }
+    } else {
+      offsets.send = offsets.ssl + harTimings.ssl;
+    }
+    offsets.wait = offsets.send + harTimings.send;
+    offsets.receive = offsets.wait + harTimings.wait;
+
     return {
       total: totalTime,
-      timings: harTimings,
+      offsets: offsets
     };
   },
 
   /**
    * Suspend Web Console activity. This is called when all Web Consoles are
    * closed.
    */
   destroy: function () {
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -9954,20 +9954,23 @@ nsDocShell::InternalLoad(nsIURI* aURI,
       // an iframe since that's more common.
       contentType = nsIContentPolicy::TYPE_INTERNAL_IFRAME;
     }
   } else {
     contentType = nsIContentPolicy::TYPE_DOCUMENT;
     isTargetTopLevelDocShell = true;
   }
 
+  nsIDocument* doc = mContentViewer ? mContentViewer->GetDocument()
+                                    : nullptr;
   if (!nsContentSecurityManager::AllowTopLevelNavigationToDataURI(
         aURI,
         contentType,
         aTriggeringPrincipal,
+        doc,
         (aLoadType == LOAD_NORMAL_EXTERNAL),
         !aFileName.IsVoid())) {
     // logging to console happens within AllowTopLevelNavigationToDataURI
     return NS_OK;
   }
 
   // If there's no targetDocShell, that means we are about to create a new
   // window (or aWindowTarget is empty). Perform a content policy check before
@@ -10092,18 +10095,16 @@ nsDocShell::InternalLoad(nsIURI* aURI,
 
         nsCOMPtr<nsIDocShellTreeItem> parent;
         treeItem->GetSameTypeParent(getter_AddRefs(parent));
         parent.swap(treeItem);
       } while (treeItem);
     }
   }
 
-  const nsIDocument* doc = mContentViewer ? mContentViewer->GetDocument()
-                                          : nullptr;
   const bool isDocumentAuxSandboxed = doc &&
     (doc->GetSandboxFlags() & SANDBOXED_AUXILIARY_NAVIGATION);
 
   if (aURI && mLoadURIDelegate &&
       (!targetDocShell || targetDocShell == static_cast<nsIDocShell*>(this))) {
     // Dispatch only load requests for the current or a new window to the
     // delegate, e.g., to allow for GeckoView apps to handle the load event
     // outside of Gecko.
--- a/dom/base/nsContentUtils.cpp
+++ b/dom/base/nsContentUtils.cpp
@@ -1038,28 +1038,50 @@ nsContentUtils::Atob(const nsAString& aA
                      nsAString& aBinaryData)
 {
   if (!Is8bit(aAsciiBase64String)) {
     aBinaryData.Truncate();
     return NS_ERROR_DOM_INVALID_CHARACTER_ERR;
   }
 
   const char16_t* start = aAsciiBase64String.BeginReading();
+  const char16_t* cur = start;
   const char16_t* end = aAsciiBase64String.EndReading();
-  nsString trimmedString;
-  if (!trimmedString.SetCapacity(aAsciiBase64String.Length(), fallible)) {
-    return NS_ERROR_DOM_INVALID_CHARACTER_ERR;
-  }
-  while (start < end) {
-    if (!nsContentUtils::IsHTMLWhitespace(*start)) {
-      trimmedString.Append(*start);
-    }
-    start++;
-  }
-  nsresult rv = Base64Decode(trimmedString, aBinaryData);
+  bool hasWhitespace = false;
+
+  while (cur < end) {
+    if (nsContentUtils::IsHTMLWhitespace(*cur)) {
+      hasWhitespace = true;
+      break;
+    }
+    cur++;
+  }
+
+  nsresult rv;
+
+  if (hasWhitespace) {
+    nsString trimmedString;
+
+    if (!trimmedString.SetCapacity(aAsciiBase64String.Length(), fallible)) {
+      return NS_ERROR_DOM_INVALID_CHARACTER_ERR;
+    }
+
+    trimmedString.Append(start, cur - start);
+
+    while (cur < end) {
+      if (!nsContentUtils::IsHTMLWhitespace(*cur)) {
+        trimmedString.Append(*cur);
+      }
+      cur++;
+    }
+    rv = Base64Decode(trimmedString, aBinaryData);
+  } else {
+    rv = Base64Decode(aAsciiBase64String, aBinaryData);
+  }
+
   if (NS_FAILED(rv) && rv == NS_ERROR_INVALID_ARG) {
     return NS_ERROR_DOM_INVALID_CHARACTER_ERR;
   }
   return rv;
 }
 
 bool
 nsContentUtils::IsAutocompleteEnabled(nsIDOMHTMLInputElement* aInput)
--- a/dom/base/test/mochitest.ini
+++ b/dom/base/test/mochitest.ini
@@ -623,16 +623,17 @@ skip-if = toolkit == 'android'
 [test_bug1314032.html]
 [test_bug1318303.html]
 [test_bug1375050.html]
 [test_bug1381710.html]
 [test_bug1384658.html]
 skip-if = toolkit == 'android'
 [test_bug1399603.html]
 [test_bug1399605.html]
+[test_bug1404385.html]
 [test_bug1406102.html]
 [test_caretPositionFromPoint.html]
 [test_change_policy.html]
 [test_clearTimeoutIntervalNoArg.html]
 [test_constructor-assignment.html]
 [test_constructor.html]
 [test_copyimage.html]
 subsuite = clipboard
new file mode 100644
--- /dev/null
+++ b/dom/base/test/test_bug1404385.html
@@ -0,0 +1,31 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1404385
+-->
+<head>
+  <title>Test for Bug 1404385</title>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1404385">Mozilla Bug 1404385</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+/** Test for Bug 1404385 **/
+is(atob("T0s="), "OK", "atob");
+is(atob(" T0s="), "OK", "atob initial space removal");
+is(atob("T0s= "), "OK", "atob final space removal");
+is(atob("T 0s="), "OK", "atob middle space removal");
+is(atob("dGV zdA=="), "test", "atob middle space removal 2");
+is(atob(""), "", "atob empty string");
+is(atob(" "), "", "atob all whitespace");
+
+</script>
+</pre>
+</body>
+</html>
--- a/dom/file/Blob.cpp
+++ b/dom/file/Blob.cpp
@@ -184,21 +184,26 @@ void
 Blob::GetType(nsAString &aType)
 {
   mImpl->GetType(aType);
 }
 
 already_AddRefed<Blob>
 Blob::Slice(const Optional<int64_t>& aStart,
             const Optional<int64_t>& aEnd,
-            const nsAString& aContentType,
+            const Optional<nsAString>& aContentType,
             ErrorResult& aRv)
 {
+  nsAutoString contentType;
+  if (aContentType.WasPassed()) {
+    contentType = aContentType.Value();
+  }
+
   RefPtr<BlobImpl> impl =
-    mImpl->Slice(aStart, aEnd, aContentType, aRv);
+    mImpl->Slice(aStart, aEnd, contentType, aRv);
   if (aRv.Failed()) {
     return nullptr;
   }
 
   RefPtr<Blob> blob = Blob::Create(mParent, impl);
   return blob.forget();
 }
 
--- a/dom/file/Blob.h
+++ b/dom/file/Blob.h
@@ -117,17 +117,17 @@ public:
                                JS::Handle<JSObject*> aGivenProto) override;
 
   uint64_t GetSize(ErrorResult& aRv);
 
   void GetType(nsAString& aType);
 
   already_AddRefed<Blob> Slice(const Optional<int64_t>& aStart,
                                const Optional<int64_t>& aEnd,
-                               const nsAString& aContentType,
+                               const Optional<nsAString>& aContentType,
                                ErrorResult& aRv);
 
   size_t GetAllocationSize() const;
 
 protected:
   // File constructor should never be used directly. Use Blob::Create instead.
   Blob(nsISupports* aParent, BlobImpl* aImpl);
   virtual ~Blob();
--- a/dom/file/FileReader.cpp
+++ b/dom/file/FileReader.cpp
@@ -14,16 +14,17 @@
 
 #include "mozilla/Base64.h"
 #include "mozilla/CheckedInt.h"
 #include "mozilla/dom/DOMException.h"
 #include "mozilla/dom/File.h"
 #include "mozilla/dom/FileReaderBinding.h"
 #include "mozilla/dom/ProgressEvent.h"
 #include "mozilla/Encoding.h"
+#include "nsAlgorithm.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsDOMJSUtils.h"
 #include "nsError.h"
 #include "nsNetCID.h"
 #include "nsNetUtil.h"
 #include "xpcpublic.h"
 
 #include "WorkerPrivate.h"
@@ -182,37 +183,16 @@ FileReader::GetResult(JSContext* aCx,
 
   nsString tmpResult = mResult;
   if (!xpc::StringToJsval(aCx, tmpResult, aResult)) {
     aRv.Throw(NS_ERROR_FAILURE);
     return;
   }
 }
 
-static nsresult
-ReadFuncBinaryString(nsIInputStream* in,
-                     void* closure,
-                     const char* fromRawSegment,
-                     uint32_t toOffset,
-                     uint32_t count,
-                     uint32_t *writeCount)
-{
-  char16_t* dest = static_cast<char16_t*>(closure) + toOffset;
-  char16_t* end = dest + count;
-  const unsigned char* source = (const unsigned char*)fromRawSegment;
-  while (dest != end) {
-    *dest = *source;
-    ++dest;
-    ++source;
-  }
-  *writeCount = count;
-
-  return NS_OK;
-}
-
 void
 FileReader::OnLoadEndArrayBuffer()
 {
   AutoJSAPI jsapi;
   if (!jsapi.Init(GetParentObject())) {
     FreeDataAndDispatchError(NS_ERROR_FAILURE);
     return;
   }
@@ -288,42 +268,66 @@ nsresult
 FileReader::DoReadData(uint64_t aCount)
 {
   MOZ_ASSERT(mAsyncStream);
 
   uint32_t bytesRead = 0;
 
   if (mDataFormat == FILE_AS_BINARY) {
     //Continuously update our binary string as data comes in
-    uint32_t oldLen = mResult.Length();
-    MOZ_ASSERT(mResult.Length() == mDataLen, "unexpected mResult length");
-    if (uint64_t(oldLen) + aCount > UINT32_MAX)
-      return NS_ERROR_OUT_OF_MEMORY;
-    char16_t *buf = nullptr;
-    mResult.GetMutableData(&buf, oldLen + aCount, fallible);
-    NS_ENSURE_TRUE(buf, NS_ERROR_OUT_OF_MEMORY);
+    CheckedInt<uint64_t> size = mResult.Length();
+    size += aCount;
 
-    nsresult rv;
-
-    // nsFileStreams do not implement ReadSegment. In case here we are dealing
-    // with a nsIAsyncInputStream, in content process, we need to wrap a
-    // nsIBufferedInputStream around it.
-    if (!mBufferedStream) {
-      rv = NS_NewBufferedInputStream(getter_AddRefs(mBufferedStream),
-                                     mAsyncStream, 8192);
-      NS_ENSURE_SUCCESS(rv, rv);
+    if (!size.isValid() ||
+        size.value() > UINT32_MAX ||
+        size.value() > mTotal) {
+      return NS_ERROR_OUT_OF_MEMORY;
     }
 
-    rv = mBufferedStream->ReadSegments(ReadFuncBinaryString, buf + oldLen,
-                                       aCount, &bytesRead);
-    if (NS_WARN_IF(NS_FAILED(rv))) {
-      return rv;
+    uint32_t oldLen = mResult.Length();
+    MOZ_ASSERT(oldLen == mDataLen, "unexpected mResult length");
+
+    char16_t* dest = nullptr;
+    mResult.GetMutableData(&dest, size.value(), fallible);
+    NS_ENSURE_TRUE(dest, NS_ERROR_OUT_OF_MEMORY);
+
+    dest += oldLen;
+
+    while (aCount > 0) {
+      char tmpBuffer[4096];
+      uint32_t minCount =
+        XPCOM_MIN(aCount, static_cast<uint64_t>(sizeof(tmpBuffer)));
+      uint32_t read;
+
+      nsresult rv = mAsyncStream->Read(tmpBuffer, minCount, &read);
+      if (rv == NS_BASE_STREAM_CLOSED) {
+        rv = NS_OK;
+      }
+
+      NS_ENSURE_SUCCESS(rv, rv);
+
+      if (read == 0) {
+        // The stream finished too early.
+        return NS_ERROR_OUT_OF_MEMORY;
+      }
+
+      char16_t* end = dest + read;
+      const unsigned char* source = (const unsigned char*)tmpBuffer;
+      while (dest != end) {
+        *dest = *source;
+        ++dest;
+        ++source;
+      }
+
+      aCount -= read;
+      bytesRead += read;
     }
 
-    mResult.Truncate(oldLen + bytesRead);
+    MOZ_ASSERT(size.value() == oldLen + bytesRead);
+    mResult.Truncate(size.value());
   }
   else {
     CheckedInt<uint64_t> size = mDataLen;
     size += aCount;
 
     //Update memory buffer to reflect the contents of the file
     if (!size.isValid() ||
         // PR_Realloc doesn't support over 4GB memory size even if 64-bit OS
@@ -361,17 +365,16 @@ FileReader::ReadFileContent(Blob& aBlob,
   }
 
   mError = nullptr;
 
   SetDOMStringToNull(mResult);
   mResultArrayBuffer = nullptr;
 
   mAsyncStream = nullptr;
-  mBufferedStream = nullptr;
 
   mTransferred = 0;
   mTotal = 0;
   mReadyState = EMPTY;
   FreeFileData();
 
   mBlob = &aBlob;
   mDataFormat = aDataFormat;
@@ -553,33 +556,31 @@ FileReader::ClearProgressEventTimer()
 }
 
 void
 FileReader::FreeDataAndDispatchSuccess()
 {
   FreeFileData();
   mResult.SetIsVoid(false);
   mAsyncStream = nullptr;
-  mBufferedStream = nullptr;
   mBlob = nullptr;
 
   // Dispatch event to signify end of a successful operation
   DispatchProgressEvent(NS_LITERAL_STRING(LOAD_STR));
   DispatchProgressEvent(NS_LITERAL_STRING(LOADEND_STR));
 }
 
 void
 FileReader::FreeDataAndDispatchError()
 {
   MOZ_ASSERT(mError);
 
   FreeFileData();
   mResult.SetIsVoid(true);
   mAsyncStream = nullptr;
-  mBufferedStream = nullptr;
   mBlob = nullptr;
 
   // Dispatch error event to signify load failure
   DispatchProgressEvent(NS_LITERAL_STRING(ERROR_STR));
   DispatchProgressEvent(NS_LITERAL_STRING(LOADEND_STR));
 }
 
 void
@@ -764,17 +765,16 @@ FileReader::Abort()
   // XXX The spec doesn't say this
   mError = DOMException::Create(NS_ERROR_DOM_ABORT_ERR);
 
   // Revert status and result attributes
   SetDOMStringToNull(mResult);
   mResultArrayBuffer = nullptr;
 
   mAsyncStream = nullptr;
-  mBufferedStream = nullptr;
   mBlob = nullptr;
 
   //Clean up memory buffer
   FreeFileData();
 
   // Dispatch the events
   DispatchProgressEvent(NS_LITERAL_STRING(ABORT_STR));
   DispatchProgressEvent(NS_LITERAL_STRING(LOADEND_STR));
@@ -818,21 +818,16 @@ FileReader::Shutdown()
 {
   mReadyState = DONE;
 
   if (mAsyncStream) {
     mAsyncStream->Close();
     mAsyncStream = nullptr;
   }
 
-  if (mBufferedStream) {
-    mBufferedStream->Close();
-    mBufferedStream = nullptr;
-  }
-
   FreeFileData();
   mResultArrayBuffer = nullptr;
 
   if (mWorkerPrivate && mBusyCount != 0) {
     ReleaseWorker();
     mWorkerPrivate = nullptr;
     mBusyCount = 0;
   }
--- a/dom/file/FileReader.h
+++ b/dom/file/FileReader.h
@@ -67,19 +67,24 @@ public:
   // WebIDL
   static already_AddRefed<FileReader>
   Constructor(const GlobalObject& aGlobal, ErrorResult& aRv);
   void ReadAsArrayBuffer(JSContext* aCx, Blob& aBlob, ErrorResult& aRv)
   {
     ReadFileContent(aBlob, EmptyString(), FILE_AS_ARRAYBUFFER, aRv);
   }
 
-  void ReadAsText(Blob& aBlob, const nsAString& aLabel, ErrorResult& aRv)
+  void ReadAsText(Blob& aBlob, const Optional<nsAString>& aLabel,
+                  ErrorResult& aRv)
   {
-    ReadFileContent(aBlob, aLabel, FILE_AS_TEXT, aRv);
+    if (aLabel.WasPassed()) {
+      ReadFileContent(aBlob, aLabel.Value(), FILE_AS_TEXT, aRv);
+    } else {
+      ReadFileContent(aBlob, EmptyString(), FILE_AS_TEXT, aRv);
+    }
   }
 
   void ReadAsDataURL(Blob& aBlob, ErrorResult& aRv)
   {
     ReadFileContent(aBlob, EmptyString(), FILE_AS_DATAURL, aRv);
   }
 
   void Abort();
@@ -178,17 +183,16 @@ private:
 
   JS::Heap<JSObject*> mResultArrayBuffer;
 
   nsCOMPtr<nsITimer> mProgressNotifier;
   bool mProgressEventWasDelayed;
   bool mTimerIsActive;
 
   nsCOMPtr<nsIAsyncInputStream> mAsyncStream;
-  nsCOMPtr<nsIInputStream> mBufferedStream;
 
   RefPtr<DOMException> mError;
 
   eReadyState mReadyState;
 
   uint64_t mTotal;
   uint64_t mTransferred;
 
--- a/dom/html/HTMLLinkElement.cpp
+++ b/dom/html/HTMLLinkElement.cpp
@@ -373,50 +373,37 @@ HTMLLinkElement::GetLinkTarget(nsAString
   GetAttr(kNameSpaceID_None, nsGkAtoms::target, aTarget);
   if (aTarget.IsEmpty()) {
     GetBaseTarget(aTarget);
   }
 }
 
 static const DOMTokenListSupportedToken sSupportedRelValues[] = {
   // Keep this in sync with ToLinkMask in nsStyleLinkElement.cpp.
-  // "import" must come first because it's conditional.
-  "prefetch",
-  "dns-prefetch",
-  "stylesheet",
-  "next",
-  "alternate",
-  "preconnect",
-  "icon",
-  "search",
+  // "preload" must come first because it can be disabled.
   "preload",
-  nullptr
-};
-
-static const DOMTokenListSupportedToken sSupportedRelValuesNoPreload[] = {
-  // Keep this in sync with ToLinkMask in nsStyleLinkElement.cpp.
-  // "import" must come first because it's conditional.
   "prefetch",
   "dns-prefetch",
   "stylesheet",
   "next",
   "alternate",
   "preconnect",
   "icon",
   "search",
   nullptr
 };
+
 nsDOMTokenList*
 HTMLLinkElement::RelList()
 {
   if (!mRelList) {
     if (Preferences::GetBool("network.preload")) {
       mRelList = new nsDOMTokenList(this, nsGkAtoms::rel, sSupportedRelValues);
     } else {
-      mRelList = new nsDOMTokenList(this, nsGkAtoms::rel, sSupportedRelValuesNoPreload);
+      mRelList = new nsDOMTokenList(this, nsGkAtoms::rel, &sSupportedRelValues[1]);
     }
   }
   return mRelList;
 }
 
 already_AddRefed<nsIURI>
 HTMLLinkElement::GetHrefURI() const
 {
--- a/dom/media/mediasource/MediaSourceDemuxer.cpp
+++ b/dom/media/mediasource/MediaSourceDemuxer.cpp
@@ -297,19 +297,19 @@ MediaSourceDemuxer::GetMozDebugReaderDat
   }
   aString += result;
 }
 
 MediaSourceTrackDemuxer::MediaSourceTrackDemuxer(MediaSourceDemuxer* aParent,
                                                  TrackInfo::TrackType aType,
                                                  TrackBuffersManager* aManager)
   : mParent(aParent)
-  , mManager(aManager)
   , mType(aType)
   , mMonitor("MediaSourceTrackDemuxer")
+  , mManager(aManager)
   , mReset(true)
   , mPreRoll(TimeUnit::FromMicroseconds(
       OpusDataDecoder::IsOpus(mParent->GetTrackInfo(mType)->mMimeType)
       ? 80000
       : mParent->GetTrackInfo(mType)->mMimeType.EqualsLiteral("audio/mp4a-latm")
         // AAC encoder delay is by default 2112 audio frames.
         // See https://developer.apple.com/library/content/documentation/QuickTime/QTFF/QTFFAppenG/QTFFAppenG.html
         // So we always seek 2112 frames
@@ -349,16 +349,17 @@ MediaSourceTrackDemuxer::Reset()
   RefPtr<MediaSourceTrackDemuxer> self = this;
   nsCOMPtr<nsIRunnable> task =
     NS_NewRunnableFunction("MediaSourceTrackDemuxer::Reset", [self]() {
       self->mNextSample.reset();
       self->mReset = true;
       if (!self->mManager) {
         return;
       }
+      MOZ_ASSERT(self->OnTaskQueue());
       self->mManager->Seek(self->mType, TimeUnit::Zero(), TimeUnit::Zero());
       {
         MonitorAutoLock mon(self->mMonitor);
         self->mNextRandomAccessPoint = self->mManager->GetNextRandomAccessPoint(
           self->mType, MediaSourceDemuxer::EOS_FUZZ);
       }
     });
   mParent->GetTaskQueue()->Dispatch(task.forget());
@@ -380,42 +381,45 @@ MediaSourceTrackDemuxer::SkipToNextRando
            mParent->GetTaskQueue(), this, __func__,
            &MediaSourceTrackDemuxer::DoSkipToNextRandomAccessPoint,
            aTimeThreshold);
 }
 
 media::TimeIntervals
 MediaSourceTrackDemuxer::GetBuffered()
 {
+  MonitorAutoLock mon(mMonitor);
   if (!mManager) {
     return media::TimeIntervals();
   }
   return mManager->Buffered();
 }
 
 void
 MediaSourceTrackDemuxer::BreakCycles()
 {
   RefPtr<MediaSourceTrackDemuxer> self = this;
   nsCOMPtr<nsIRunnable> task =
     NS_NewRunnableFunction("MediaSourceTrackDemuxer::BreakCycles", [self]() {
+      self->DetachManager();
       self->mParent = nullptr;
-      self->DetachManager();
     });
   mParent->GetTaskQueue()->Dispatch(task.forget());
 }
 
 RefPtr<MediaSourceTrackDemuxer::SeekPromise>
 MediaSourceTrackDemuxer::DoSeek(const TimeUnit& aTime)
 {
   if (!mManager) {
     return SeekPromise::CreateAndReject(
       MediaResult(NS_ERROR_DOM_MEDIA_FATAL_ERR,
                   RESULT_DETAIL("manager is detached.")), __func__);
   }
+
+  MOZ_ASSERT(OnTaskQueue());
   TimeIntervals buffered = mManager->Buffered(mType);
   // Fuzz factor represents a +/- threshold. So when seeking it allows the gap
   // to be twice as big as the fuzz value. We only want to allow EOS_FUZZ gap.
   buffered.SetFuzz(MediaSourceDemuxer::EOS_FUZZ / 2);
   TimeUnit seekTime = std::max(aTime - mPreRoll, TimeUnit::Zero());
 
   if (mManager->IsEnded() && seekTime >= buffered.GetEnd()) {
     // We're attempting to seek past the end time. Cap seekTime so that we seek
@@ -458,16 +462,18 @@ MediaSourceTrackDemuxer::DoSeek(const Ti
 RefPtr<MediaSourceTrackDemuxer::SamplesPromise>
 MediaSourceTrackDemuxer::DoGetSamples(int32_t aNumSamples)
 {
   if (!mManager) {
     return SamplesPromise::CreateAndReject(
       MediaResult(NS_ERROR_DOM_MEDIA_FATAL_ERR,
                   RESULT_DETAIL("manager is detached.")), __func__);
   }
+
+  MOZ_ASSERT(OnTaskQueue());
   if (mReset) {
     // If a seek (or reset) was recently performed, we ensure that the data
     // we are about to retrieve is still available.
     TimeIntervals buffered = mManager->Buffered(mType);
     buffered.SetFuzz(MediaSourceDemuxer::EOS_FUZZ / 2);
 
     if (!buffered.Length() && mManager->IsEnded()) {
       return SamplesPromise::CreateAndReject(NS_ERROR_DOM_MEDIA_END_OF_STREAM,
@@ -511,16 +517,18 @@ RefPtr<MediaSourceTrackDemuxer::SkipAcce
 MediaSourceTrackDemuxer::DoSkipToNextRandomAccessPoint(
   const TimeUnit& aTimeThreadshold)
 {
   if (!mManager) {
     return SkipAccessPointPromise::CreateAndReject(
       SkipFailureHolder(MediaResult(NS_ERROR_DOM_MEDIA_FATAL_ERR,
                         RESULT_DETAIL("manager is detached.")), 0), __func__);
   }
+
+  MOZ_ASSERT(OnTaskQueue());
   uint32_t parsed = 0;
   // Ensure that the data we are about to skip to is still available.
   TimeIntervals buffered = mManager->Buffered(mType);
   buffered.SetFuzz(MediaSourceDemuxer::EOS_FUZZ / 2);
   if (buffered.ContainsWithStrictEnd(aTimeThreadshold)) {
     bool found;
     parsed = mManager->SkipToNextRandomAccessPoint(mType,
                                                    aTimeThreadshold,
@@ -534,18 +542,21 @@ MediaSourceTrackDemuxer::DoSkipToNextRan
     mManager->IsEnded() ? NS_ERROR_DOM_MEDIA_END_OF_STREAM :
                           NS_ERROR_DOM_MEDIA_WAITING_FOR_DATA, parsed);
   return SkipAccessPointPromise::CreateAndReject(holder, __func__);
 }
 
 bool
 MediaSourceTrackDemuxer::HasManager(TrackBuffersManager* aManager) const
 {
+  MOZ_ASSERT(OnTaskQueue());
   return mManager == aManager;
 }
 
 void
 MediaSourceTrackDemuxer::DetachManager()
 {
+  MOZ_ASSERT(OnTaskQueue());
+  MonitorAutoLock mon(mMonitor);
   mManager = nullptr;
 }
 
 } // namespace mozilla
--- a/dom/media/mediasource/MediaSourceDemuxer.h
+++ b/dom/media/mediasource/MediaSourceDemuxer.h
@@ -115,30 +115,43 @@ public:
   {
     return false;
   }
 
   bool HasManager(TrackBuffersManager* aManager) const;
   void DetachManager();
 
 private:
+
+  bool OnTaskQueue() const
+  {
+    MOZ_ASSERT(mParent);
+    auto taskQueue = mParent->GetTaskQueue();
+    MOZ_ASSERT(taskQueue);
+    return taskQueue->IsCurrentThreadIn();
+  }
+
   RefPtr<SeekPromise> DoSeek(const media::TimeUnit& aTime);
   RefPtr<SamplesPromise> DoGetSamples(int32_t aNumSamples);
   RefPtr<SkipAccessPointPromise> DoSkipToNextRandomAccessPoint(
     const media::TimeUnit& aTimeThreadshold);
   already_AddRefed<MediaRawData> GetSample(MediaResult& aError);
   // Return the timestamp of the next keyframe after mLastSampleIndex.
   media::TimeUnit GetNextRandomAccessPoint();
 
   RefPtr<MediaSourceDemuxer> mParent;
-  RefPtr<TrackBuffersManager> mManager;
   TrackInfo::TrackType mType;
   // Monitor protecting members below accessed from multiple threads.
   Monitor mMonitor;
   media::TimeUnit mNextRandomAccessPoint;
+  // Would be accessed in MFR's demuxer proxy task queue and TaskQueue, and
+  // only be set on the TaskQueue. It can be accessed while on TaskQueue without
+  // the need for the lock.
+  RefPtr<TrackBuffersManager> mManager;
+
   Maybe<RefPtr<MediaRawData>> mNextSample;
   // Set to true following a reset. Ensure that the next sample demuxed
   // is available at position 0.
   bool mReset;
 
   // Amount of pre-roll time when seeking.
   // Set to 80ms if track is Opus.
   const media::TimeUnit mPreRoll;
--- a/dom/media/tests/mochitest/mochitest.ini
+++ b/dom/media/tests/mochitest/mochitest.ini
@@ -270,17 +270,17 @@ skip-if = android_version == '18' # andr
 skip-if = (android_version == '18') # android(bug 1240256, intermittent ICE failures starting w/bug 1232082, possibly from timeout)
 [test_peerConnection_addDataChannelNoBundle.html]
 skip-if = (android_version == '18') # android(bug 1240256, intermittent ICE failures starting w/bug 1232082, possibly from timeout) android(Bug 1189784, timeouts on 4.3 emulator)
 [test_peerConnection_verifyAudioAfterRenegotiation.html]
 skip-if = android_version == '18' # android(Bug 1189784, timeouts on 4.3 emulator)
 [test_peerConnection_verifyVideoAfterRenegotiation.html]
 skip-if = android_version == '18' # android(Bug 1189784, timeouts on 4.3 emulator)
 [test_peerConnection_videoCodecs.html]
-skip-if = android_version == '18' # android(Bug 1189784, timeouts on 4.3 emulator)
+skip-if = toolkit == 'android' # android(Bug 1189784, timeouts on 4.3 emulator), android(Bug 1409203, failures on Autophone)
 [test_peerConnection_audioRenegotiationInactiveAnswer.html]
 skip-if = android_version == '18' # android(Bug 1189784, timeouts on 4.3 emulator)
 [test_peerConnection_videoRenegotiationInactiveAnswer.html]
 skip-if = android_version == '18' # android(Bug 1189784, timeouts on 4.3 emulator)
 [test_peerConnection_webAudio.html]
 tags = webaudio webrtc
 skip-if = android_version == '18' # android(Bug 1189784, timeouts on 4.3 emulator)
 [test_peerConnection_localRollback.html]
--- a/dom/security/nsContentSecurityManager.cpp
+++ b/dom/security/nsContentSecurityManager.cpp
@@ -21,16 +21,17 @@ NS_IMPL_ISUPPORTS(nsContentSecurityManag
                   nsIContentSecurityManager,
                   nsIChannelEventSink)
 
 /* static */ bool
 nsContentSecurityManager::AllowTopLevelNavigationToDataURI(
   nsIURI* aURI,
   nsContentPolicyType aContentPolicyType,
   nsIPrincipal* aTriggeringPrincipal,
+  nsIDocument* aDoc,
   bool aLoadFromExternal,
   bool aIsDownLoad)
 {
   // Let's block all toplevel document navigations to a data: URI.
   // In all cases where the toplevel document is navigated to a
   // data: URI the triggeringPrincipal is a codeBasePrincipal, or
   // a NullPrincipal. In other cases, e.g. typing a data: URL into
   // the URL-Bar, the triggeringPrincipal is a SystemPrincipal;
@@ -68,18 +69,17 @@ nsContentSecurityManager::AllowTopLevelN
   if (dataSpec.Length() > 50) {
     dataSpec.Truncate(50);
     dataSpec.AppendLiteral("...");
   }
   NS_ConvertUTF8toUTF16 specUTF16(NS_UnescapeURL(dataSpec));
   const char16_t* params[] = { specUTF16.get() };
   nsContentUtils::ReportToConsole(nsIScriptError::warningFlag,
                                   NS_LITERAL_CSTRING("DATA_URI_BLOCKED"),
-                                  // no doc available, log to browser console
-                                  nullptr,
+                                  aDoc,
                                   nsContentUtils::eSECURITY_PROPERTIES,
                                   "BlockTopLevelDataURINavigation",
                                   params, ArrayLength(params));
   return false;
 }
 
 static nsresult
 ValidateSecurityFlags(nsILoadInfo* aLoadInfo)
@@ -579,16 +579,17 @@ nsContentSecurityManager::AsyncOnChannel
     nsCOMPtr<nsIURI> uri;
     nsresult rv = NS_GetFinalChannelURI(aNewChannel, getter_AddRefs(uri));
     NS_ENSURE_SUCCESS(rv, rv);
     nsCOMPtr<nsIPrincipal> nullTriggeringPrincipal = NullPrincipal::Create();
     if (!nsContentSecurityManager::AllowTopLevelNavigationToDataURI(
           uri,
           newLoadInfo->GetExternalContentPolicyType(),
           nullTriggeringPrincipal,
+          nullptr, // no doc available, log to browser console
           false,
           false)) {
         // logging to console happens within AllowTopLevelNavigationToDataURI
       aOldChannel->Cancel(NS_ERROR_DOM_BAD_URI);
       return NS_ERROR_DOM_BAD_URI;
     }
   }
 
--- a/dom/security/nsContentSecurityManager.h
+++ b/dom/security/nsContentSecurityManager.h
@@ -7,16 +7,17 @@
 #ifndef nsContentSecurityManager_h___
 #define nsContentSecurityManager_h___
 
 #include "nsIContentSecurityManager.h"
 #include "nsIChannel.h"
 #include "nsIChannelEventSink.h"
 
 class nsIStreamListener;
+class nsIDocument;
 
 #define NS_CONTENTSECURITYMANAGER_CONTRACTID "@mozilla.org/contentsecuritymanager;1"
 // cdcc1ab8-3cea-4e6c-a294-a651fa35227f
 #define NS_CONTENTSECURITYMANAGER_CID \
 { 0xcdcc1ab8, 0x3cea, 0x4e6c, \
   { 0xa2, 0x94, 0xa6, 0x51, 0xfa, 0x35, 0x22, 0x7f } }
 
 class nsContentSecurityManager : public nsIContentSecurityManager
@@ -30,16 +31,17 @@ public:
   nsContentSecurityManager() {}
 
   static nsresult doContentSecurityCheck(nsIChannel* aChannel,
                                          nsCOMPtr<nsIStreamListener>& aInAndOutListener);
 
   static bool AllowTopLevelNavigationToDataURI(nsIURI* aURI,
                                                nsContentPolicyType aContentPolicyType,
                                                nsIPrincipal* aTriggeringPrincipal,
+                                               nsIDocument* aDoc,
                                                bool aLoadFromExternal,
                                                bool aIsDownload);
 
 private:
   static nsresult CheckChannel(nsIChannel* aChannel);
 
   virtual ~nsContentSecurityManager() {}
 
--- a/dom/u2f/U2FManager.cpp
+++ b/dom/u2f/U2FManager.cpp
@@ -244,20 +244,19 @@ U2FManager::Register(nsPIDOMWindowInner*
                                         aExcludeList))) {
     return U2FPromise::CreateAndReject(ErrorCode::OTHER_ERROR, __func__).forget();
   }
 
   RefPtr<MozPromise<nsresult, nsresult, false>> p = GetOrCreateBackgroundActor();
   p->Then(GetMainThreadSerialEventTarget(), __func__,
           []() {
             U2FManager* mgr = U2FManager::Get();
-            if (!mgr) {
-              return;
+            if (mgr && mgr->mChild) {
+              mgr->mChild->SendRequestRegister(mgr->mInfo.ref());
             }
-            mgr->StartRegister();
           },
           []() {
             // This case can't actually happen, we'll have crashed if the child
             // failed to create.
           });
 
   // Only store off the promise if we've succeeded in sending the IPC event.
   RefPtr<U2FPromise> promise = mTransactionPromise.Ensure(__func__);
@@ -282,56 +281,34 @@ U2FManager::Sign(nsPIDOMWindowInner* aPa
                                         aAllowList))) {
     return U2FPromise::CreateAndReject(ErrorCode::OTHER_ERROR, __func__).forget();
   }
 
   RefPtr<MozPromise<nsresult, nsresult, false>> p = GetOrCreateBackgroundActor();
   p->Then(GetMainThreadSerialEventTarget(), __func__,
           []() {
             U2FManager* mgr = U2FManager::Get();
-            if (!mgr) {
-              return;
+            if (mgr && mgr->mChild) {
+              mgr->mChild->SendRequestSign(mgr->mInfo.ref());
             }
-            mgr->StartSign();
           },
           []() {
             // This case can't actually happen, we'll have crashed if the child
             // failed to create.
           });
 
   // Only store off the promise if we've succeeded in sending the IPC event.
   RefPtr<U2FPromise> promise = mTransactionPromise.Ensure(__func__);
   mClientData = Some(aClientDataJSON);
   mCurrentParent = aParent;
   ListenForVisibilityEvents(aParent, this);
   return promise.forget();
 }
 
 void
-U2FManager::StartRegister() {
-  if (mChild) {
-    mChild->SendRequestRegister(mInfo.ref());
-  }
-}
-
-void
-U2FManager::StartSign() {
-  if (mChild) {
-    mChild->SendRequestSign(mInfo.ref());
-  }
-}
-
-void
-U2FManager::StartCancel() {
-  if (mChild) {
-    mChild->SendRequestCancel();
-  }
-}
-
-void
 U2FManager::FinishRegister(nsTArray<uint8_t>& aRegBuffer)
 {
   MOZ_ASSERT(!mTransactionPromise.IsEmpty());
   MOZ_ASSERT(mInfo.isSome());
 
   CryptoBuffer clientDataBuf;
   if (NS_WARN_IF(!clientDataBuf.Assign(mClientData.ref()))) {
     mTransactionPromise.Reject(ErrorCode::OTHER_ERROR, __func__);
@@ -423,49 +400,60 @@ U2FManager::FinishSign(nsTArray<uint8_t>
     return;
   }
 
   mTransactionPromise.Resolve(responseStr, __func__);
   MaybeClearTransaction();
 }
 
 void
+U2FManager::RequestAborted(const nsresult& aError)
+{
+  MOZ_ASSERT(NS_IsMainThread());
+
+  Cancel(aError);
+}
+
+void
 U2FManager::Cancel(const nsresult& aError)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   ErrorCode code = ConvertNSResultToErrorCode(aError);
 
   if (!mTransactionPromise.IsEmpty()) {
     mTransactionPromise.RejectIfExists(code, __func__);
   }
 
   MaybeClearTransaction();
 }
 
 NS_IMETHODIMP
 U2FManager::HandleEvent(nsIDOMEvent* aEvent)
 {
+  MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(aEvent);
+  MOZ_ASSERT(mChild);
 
   nsAutoString type;
   aEvent->GetType(type);
   if (!type.Equals(kVisibilityChange)) {
     return NS_ERROR_FAILURE;
   }
 
   nsCOMPtr<nsIDocument> doc =
     do_QueryInterface(aEvent->InternalDOMEvent()->GetTarget());
   MOZ_ASSERT(doc);
 
   if (doc && doc->Hidden()) {
     MOZ_LOG(gU2FManagerLog, LogLevel::Debug,
             ("Visibility change: U2F window is hidden, cancelling job."));
 
-    StartCancel();
+    mChild->SendRequestCancel();
+
     Cancel(NS_ERROR_DOM_TIMEOUT_ERR);
   }
 
   return NS_OK;
 }
 
 void
 U2FManager::ActorCreated(PBackgroundChild* aActor)
--- a/dom/u2f/U2FManager.h
+++ b/dom/u2f/U2FManager.h
@@ -54,43 +54,41 @@ class U2FTransactionChild;
 class U2FTransactionInfo;
 
 class U2FManager final : public nsIIPCBackgroundChildCreateCallback
                        , public nsIDOMEventListener
 {
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSIDOMEVENTLISTENER
+  NS_DECL_NSIIPCBACKGROUNDCHILDCREATECALLBACK
+
   static U2FManager* GetOrCreate();
   static U2FManager* Get();
 
-  void FinishRegister(nsTArray<uint8_t>& aRegBuffer);
-  void FinishSign(nsTArray<uint8_t>& aCredentialId,
-                  nsTArray<uint8_t>& aSigBuffer);
-  void Cancel(const nsresult& aError);
-
   already_AddRefed<U2FPromise> Register(nsPIDOMWindowInner* aParent,
               const nsCString& aRpId,
               const nsCString& aClientDataJSON,
               const uint32_t& aTimeoutMillis,
               const nsTArray<WebAuthnScopedCredentialDescriptor>& aExcludeList);
   already_AddRefed<U2FPromise> Sign(nsPIDOMWindowInner* aParent,
               const nsCString& aRpId,
               const nsCString& aClientDataJSON,
               const uint32_t& aTimeoutMillis,
               const nsTArray<WebAuthnScopedCredentialDescriptor>& aKeyList);
 
-  void StartRegister();
-  void StartSign();
-  void StartCancel();
+  void FinishRegister(nsTArray<uint8_t>& aRegBuffer);
+  void FinishSign(nsTArray<uint8_t>& aCredentialId,
+                  nsTArray<uint8_t>& aSigBuffer);
+  void RequestAborted(const nsresult& aError);
 
-  // nsIIPCbackgroundChildCreateCallback methods
-  void ActorCreated(PBackgroundChild* aActor) override;
-  void ActorFailed() override;
+  void Cancel(const nsresult& aError);
+
   void ActorDestroyed();
+
 private:
   U2FManager();
   virtual ~U2FManager();
 
   void MaybeClearTransaction();
   nsresult PopulateTransactionInfo(const nsCString& aRpId,
                     const nsCString& aClientDataJSON,
                     const uint32_t& aTimeoutMillis,
--- a/dom/u2f/U2FTransactionChild.cpp
+++ b/dom/u2f/U2FTransactionChild.cpp
@@ -32,21 +32,21 @@ U2FTransactionChild::RecvConfirmSign(nsT
 {
   RefPtr<U2FManager> mgr = U2FManager::Get();
   MOZ_ASSERT(mgr);
   mgr->FinishSign(aCredentialId, aBuffer);
   return IPC_OK();
 }
 
 mozilla::ipc::IPCResult
-U2FTransactionChild::RecvCancel(const nsresult& aError)
+U2FTransactionChild::RecvAbort(const nsresult& aError)
 {
   RefPtr<U2FManager> mgr = U2FManager::Get();
   MOZ_ASSERT(mgr);
-  mgr->Cancel(aError);
+  mgr->RequestAborted(aError);
   return IPC_OK();
 }
 
 void
 U2FTransactionChild::ActorDestroy(ActorDestroyReason why)
 {
   RefPtr<U2FManager> mgr = U2FManager::Get();
   // This could happen after the U2FManager has been shut down.
--- a/dom/u2f/U2FTransactionChild.h
+++ b/dom/u2f/U2FTransactionChild.h
@@ -21,17 +21,17 @@ namespace dom {
 class U2FTransactionChild final : public PWebAuthnTransactionChild
 {
 public:
   NS_INLINE_DECL_REFCOUNTING(U2FTransactionChild);
   U2FTransactionChild();
   mozilla::ipc::IPCResult RecvConfirmRegister(nsTArray<uint8_t>&& aRegBuffer) override;
   mozilla::ipc::IPCResult RecvConfirmSign(nsTArray<uint8_t>&& aCredentialId,
                                           nsTArray<uint8_t>&& aBuffer) override;
-  mozilla::ipc::IPCResult RecvCancel(const nsresult& aError) override;
+  mozilla::ipc::IPCResult RecvAbort(const nsresult& aError) override;
   void ActorDestroy(ActorDestroyReason why) override;
 private:
   ~U2FTransactionChild() = default;
 };
 
 }
 }
 
--- a/dom/webauthn/PWebAuthnTransaction.ipdl
+++ b/dom/webauthn/PWebAuthnTransaction.ipdl
@@ -40,13 +40,13 @@ async protocol PWebAuthnTransaction {
   parent:
     async __delete__();
     async RequestRegister(WebAuthnTransactionInfo aTransactionInfo);
     async RequestSign(WebAuthnTransactionInfo aTransactionInfo);
     async RequestCancel();
   child:
     async ConfirmRegister(uint8_t[] RegBuffer);
     async ConfirmSign(uint8_t[] CredentialID, uint8_t[] ReplyBuffer);
-    async Cancel(nsresult Error);
+    async Abort(nsresult Error);
 };
 
 }
 }
--- a/dom/webauthn/U2FTokenManager.cpp
+++ b/dom/webauthn/U2FTokenManager.cpp
@@ -155,17 +155,17 @@ U2FTokenManager::Get()
   // We should only be accessing this on the background thread
   MOZ_ASSERT(!NS_IsMainThread());
   return gU2FTokenManager;
 }
 
 void
 U2FTokenManager::AbortTransaction(const nsresult& aError)
 {
-  Unused << mTransactionParent->SendCancel(aError);
+  Unused << mTransactionParent->SendAbort(aError);
   ClearTransaction();
 }
 
 void
 U2FTokenManager::MaybeClearTransaction(PWebAuthnTransactionParent* aParent)
 {
   // Only clear if we've been requested to do so by our current transaction
   // parent.
--- a/dom/webauthn/WebAuthnManager.cpp
+++ b/dom/webauthn/WebAuthnManager.cpp
@@ -494,61 +494,33 @@ WebAuthnManager::MakeCredential(nsPIDOMW
                                clientDataHash,
                                adjustedTimeout,
                                excludeList,
                                extensions);
   RefPtr<MozPromise<nsresult, nsresult, false>> p = GetOrCreateBackgroundActor();
   p->Then(GetMainThreadSerialEventTarget(), __func__,
           []() {
             WebAuthnManager* mgr = WebAuthnManager::Get();
-            if (!mgr) {
-              return;
+            if (mgr && mgr->mChild) {
+              mgr->mChild->SendRequestRegister(mgr->mInfo.ref());
             }
-            mgr->StartRegister();
           },
           []() {
             // This case can't actually happen, we'll have crashed if the child
             // failed to create.
           });
   mTransactionPromise = promise;
   mClientData = Some(clientDataJSON);
   mCurrentParent = aParent;
   mInfo = Some(info);
   ListenForVisibilityEvents(aParent, this);
 
   return promise.forget();
 }
 
-void
-WebAuthnManager::StartRegister() {
-  MOZ_ASSERT(NS_IsMainThread());
-
-  if (mChild) {
-    mChild->SendRequestRegister(mInfo.ref());
-  }
-}
-
-void
-WebAuthnManager::StartSign() {
-  MOZ_ASSERT(NS_IsMainThread());
-
-  if (mChild) {
-    mChild->SendRequestSign(mInfo.ref());
-  }
-}
-
-void
-WebAuthnManager::StartCancel() {
-  MOZ_ASSERT(NS_IsMainThread());
-
-  if (mChild) {
-    mChild->SendRequestCancel();
-  }
-}
-
 already_AddRefed<Promise>
 WebAuthnManager::GetAssertion(nsPIDOMWindowInner* aParent,
                               const PublicKeyCredentialRequestOptions& aOptions)
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(aParent);
 
   MaybeClearTransaction();
@@ -672,20 +644,19 @@ WebAuthnManager::GetAssertion(nsPIDOMWin
                                clientDataHash,
                                adjustedTimeout,
                                allowList,
                                extensions);
   RefPtr<MozPromise<nsresult, nsresult, false>> p = GetOrCreateBackgroundActor();
   p->Then(GetMainThreadSerialEventTarget(), __func__,
           []() {
             WebAuthnManager* mgr = WebAuthnManager::Get();
-            if (!mgr) {
-              return;
+            if (mgr && mgr->mChild) {
+              mgr->mChild->SendRequestSign(mgr->mInfo.ref());
             }
-            mgr->StartSign();
           },
           []() {
             // This case can't actually happen, we'll have crashed if the child
             // failed to create.
           });
 
   // Only store off the promise if we've succeeded in sending the IPC event.
   mTransactionPromise = promise;
@@ -919,48 +890,58 @@ WebAuthnManager::FinishGetAssertion(nsTA
   credential->SetRawId(credentialBuf);
   credential->SetResponse(assertion);
 
   mTransactionPromise->MaybeResolve(credential);
   MaybeClearTransaction();
 }
 
 void
+WebAuthnManager::RequestAborted(const nsresult& aError)
+{
+  MOZ_ASSERT(NS_IsMainThread());
+
+  Cancel(aError);
+}
+
+void
 WebAuthnManager::Cancel(const nsresult& aError)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   if (mTransactionPromise) {
     mTransactionPromise->MaybeReject(aError);
   }
 
   MaybeClearTransaction();
 }
 
 NS_IMETHODIMP
 WebAuthnManager::HandleEvent(nsIDOMEvent* aEvent)
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(aEvent);
+  MOZ_ASSERT(mChild);
 
   nsAutoString type;
   aEvent->GetType(type);
   if (!type.Equals(kVisibilityChange)) {
     return NS_ERROR_FAILURE;
   }
 
   nsCOMPtr<nsIDocument> doc =
     do_QueryInterface(aEvent->InternalDOMEvent()->GetTarget());
   MOZ_ASSERT(doc);
 
   if (doc && doc->Hidden()) {
     MOZ_LOG(gWebAuthnManagerLog, LogLevel::Debug,
             ("Visibility change: WebAuthn window is hidden, cancelling job."));
 
-    StartCancel();
+    mChild->SendRequestCancel();
+
     Cancel(NS_ERROR_ABORT);
   }
 
   return NS_OK;
 }
 
 void
 WebAuthnManager::ActorCreated(PBackgroundChild* aActor)
--- a/dom/webauthn/WebAuthnManager.h
+++ b/dom/webauthn/WebAuthnManager.h
@@ -63,52 +63,49 @@ class WebAuthnTransactionChild;
 class WebAuthnTransactionInfo;
 
 class WebAuthnManager final : public nsIIPCBackgroundChildCreateCallback,
                               public nsIDOMEventListener
 {
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSIDOMEVENTLISTENER
+  NS_DECL_NSIIPCBACKGROUNDCHILDCREATECALLBACK
+
   static WebAuthnManager* GetOrCreate();
   static WebAuthnManager* Get();
 
-  void
-  FinishMakeCredential(nsTArray<uint8_t>& aRegBuffer);
-
-  void
-  FinishGetAssertion(nsTArray<uint8_t>& aCredentialId,
-                     nsTArray<uint8_t>& aSigBuffer);
-
-  void
-  Cancel(const nsresult& aError);
-
   already_AddRefed<Promise>
   MakeCredential(nsPIDOMWindowInner* aParent,
                  const MakePublicKeyCredentialOptions& aOptions);
 
   already_AddRefed<Promise>
   GetAssertion(nsPIDOMWindowInner* aParent,
                const PublicKeyCredentialRequestOptions& aOptions);
 
   already_AddRefed<Promise>
   Store(nsPIDOMWindowInner* aParent, const Credential& aCredential);
 
-  void StartRegister();
-  void StartSign();
-  void StartCancel();
+  void
+  FinishMakeCredential(nsTArray<uint8_t>& aRegBuffer);
 
-  // nsIIPCbackgroundChildCreateCallback methods
-  void ActorCreated(PBackgroundChild* aActor) override;
-  void ActorFailed() override;
+  void
+  FinishGetAssertion(nsTArray<uint8_t>& aCredentialId,
+                     nsTArray<uint8_t>& aSigBuffer);
+
+  void
+  RequestAborted(const nsresult& aError);
+
   void ActorDestroyed();
+
 private:
   WebAuthnManager();
   virtual ~WebAuthnManager();
 
+  void Cancel(const nsresult& aError);
   void MaybeClearTransaction();
 
   typedef MozPromise<nsresult, nsresult, false> BackgroundActorPromise;
 
   RefPtr<BackgroundActorPromise> GetOrCreateBackgroundActor();
 
   // JS Promise representing transaction status.
   RefPtr<Promise> mTransactionPromise;
--- a/dom/webauthn/WebAuthnTransactionChild.cpp
+++ b/dom/webauthn/WebAuthnTransactionChild.cpp
@@ -33,21 +33,21 @@ WebAuthnTransactionChild::RecvConfirmSig
 {
   RefPtr<WebAuthnManager> mgr = WebAuthnManager::Get();
   MOZ_ASSERT(mgr);
   mgr->FinishGetAssertion(aCredentialId, aBuffer);
   return IPC_OK();
 }
 
 mozilla::ipc::IPCResult
-WebAuthnTransactionChild::RecvCancel(const nsresult& aError)
+WebAuthnTransactionChild::RecvAbort(const nsresult& aError)
 {
   RefPtr<WebAuthnManager> mgr = WebAuthnManager::Get();
   MOZ_ASSERT(mgr);
-  mgr->Cancel(aError);
+  mgr->RequestAborted(aError);
   return IPC_OK();
 }
 
 void
 WebAuthnTransactionChild::ActorDestroy(ActorDestroyReason why)
 {
   RefPtr<WebAuthnManager> mgr = WebAuthnManager::Get();
   // This could happen after the WebAuthnManager has been shut down.
--- a/dom/webauthn/WebAuthnTransactionChild.h
+++ b/dom/webauthn/WebAuthnTransactionChild.h
@@ -22,17 +22,17 @@ namespace dom {
 class WebAuthnTransactionChild final : public PWebAuthnTransactionChild
 {
 public:
   NS_INLINE_DECL_REFCOUNTING(WebAuthnTransactionChild);
   WebAuthnTransactionChild();
   mozilla::ipc::IPCResult RecvConfirmRegister(nsTArray<uint8_t>&& aRegBuffer) override;
   mozilla::ipc::IPCResult RecvConfirmSign(nsTArray<uint8_t>&& aCredentialId,
                                           nsTArray<uint8_t>&& aBuffer) override;
-  mozilla::ipc::IPCResult RecvCancel(const nsresult& aError) override;
+  mozilla::ipc::IPCResult RecvAbort(const nsresult& aError) override;
   void ActorDestroy(ActorDestroyReason why) override;
 private:
   ~WebAuthnTransactionChild() = default;
 };
 
 }
 }
 
--- a/dom/webidl/Blob.webidl
+++ b/dom/webidl/Blob.webidl
@@ -22,17 +22,17 @@ interface Blob {
 
   readonly attribute DOMString type;
 
   //slice Blob into byte-ranged chunks
 
   [Throws]
   Blob slice([Clamp] optional long long start,
              [Clamp] optional long long end,
-             optional DOMString contentType = "");
+             optional DOMString contentType);
 };
 
 enum EndingTypes { "transparent", "native" };
 
 dictionary BlobPropertyBag {
   DOMString type = "";
   EndingTypes endings = "transparent";
 };
--- a/dom/webidl/FileReader.webidl
+++ b/dom/webidl/FileReader.webidl
@@ -1,28 +1,30 @@
 /* -*- Mode: IDL; tab-width: 2; 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/.
  *
  * The origin of this IDL file is
- * http://dev.w3.org/2006/webapi/FileAPI/#dfn-filereader
+ * https://w3c.github.io/FileAPI/#APIASynch
  *
  * Copyright © 2013 W3C® (MIT, ERCIM, Keio, Beihang), All Rights Reserved. W3C
  * liability, trademark and document use rules apply.
  */
 
 [Constructor,
  Exposed=(Window,Worker,System)]
 interface FileReader : EventTarget {
   // async read methods
   [Throws]
   void readAsArrayBuffer(Blob blob);
   [Throws]
-  void readAsText(Blob blob, optional DOMString label = "");
+  void readAsBinaryString(Blob filedata);
+  [Throws]
+  void readAsText(Blob blob, optional DOMString label);
   [Throws]
   void readAsDataURL(Blob blob);
 
   void abort();
 
   // states
   const unsigned short EMPTY = 0;
   const unsigned short LOADING = 1;
@@ -41,14 +43,8 @@ interface FileReader : EventTarget {
   // event handler attributes
   attribute EventHandler onloadstart;
   attribute EventHandler onprogress;
   attribute EventHandler onload;
   attribute EventHandler onabort;
   attribute EventHandler onerror;
   attribute EventHandler onloadend;
 };
-
-// Mozilla extensions.
-partial interface FileReader {
-  [Throws]
-  void readAsBinaryString(Blob filedata);
-};
--- a/extensions/spellcheck/locales/en-US/hunspell/en-US.dic
+++ b/extensions/spellcheck/locales/en-US/hunspell/en-US.dic
@@ -1,9 +1,9 @@
-52366
+52368
 0/nm
 0th/pt
 1/n1
 1st/p
 1th/tc
 2/nm
 2nd/p
 2th/tc
@@ -39901,16 +39901,17 @@ posit/DSGV
 position/CKEMS
 positional/K
 positioned/K
 positioning/K
 positive/MYPS
 positiveness/M
 positivism
 positivist/S
+positivity/MS
 positron/MS
 poss
 posse/MS
 possess/AEVGSD
 possession/ASM
 possessive/SMYP
 possessiveness/M
 possessor/SM
@@ -40190,16 +40191,17 @@ pregnancy/SM
 pregnant
 preheat/GSD
 prehensile
 prehistorian/S
 prehistoric
 prehistorical/Y
 prehistory/M
 prehuman
+preinstall/D
 prejudge/LGDS
 prejudgement/MS
 prejudgment/SM
 prejudice/MGDS
 prejudiced/U
 prejudicial
 prekindergarten/SM
 prelacy/M
--- a/gfx/harfbuzz/Makefile.am
+++ b/gfx/harfbuzz/Makefile.am
@@ -1,21 +1,22 @@
 # Process this file with automake to produce Makefile.in
 
 NULL =
 
 ACLOCAL_AMFLAGS = -I m4
 
-SUBDIRS = src util test docs win32
+SUBDIRS = src util test docs
 
 EXTRA_DIST = \
 	autogen.sh \
 	harfbuzz.doap \
 	README.python \
 	BUILD.md \
+	RELEASING.md \
 	CMakeLists.txt \
 	$(NULL)
 
 MAINTAINERCLEANFILES = \
 	$(GITIGNORE_MAINTAINERCLEANFILES_TOPLEVEL) \
 	$(GITIGNORE_MAINTAINERCLEANFILES_M4_LIBTOOL) \
 	$(GITIGNORE_MAINTAINERCLEANFILES_MAKEFILE_IN) \
 	$(srcdir)/INSTALL \
--- a/gfx/harfbuzz/NEWS
+++ b/gfx/harfbuzz/NEWS
@@ -1,8 +1,43 @@
+Overview of changes leading to 1.6.0
+Friday, October the 13th, 2017
+====================================
+
+- Update to Unicode 10.
+
+- Various Indic and Universal Shaping Engine fixes as a result of
+  HarfBuzz Hackfest with Jonathan Kew at Web Engines Hackfest at
+  the Igalia offices in A Coruña, Spain.  Thanks Igalia for having
+  us!
+
+- Implement Unicode Arabic Mark Ordering Algorithm UTR#53.
+
+- Implement optical sizing / tracking in CoreText backend, using
+  new API hb_font_set_ptem().
+
+- Allow notifying hb_font_t that underlying FT_Face changed sizing,
+  using new API hb_ft_font_changed().
+
+- More Graphite backend RTL fixes.
+
+- Fix caching of variable font shaping plans.
+
+- hb-view / hb-shape now accept following new arguments:
+
+  o --unicodes: takes a list of hex numbers that represent Unicode
+    codepoints.
+
+New API:
++hb_face_get_table_tags()
++hb_font_set_ptem()
++hb_font_get_ptem()
++hb_ft_font_changed()
+
+
 Overview of changes leading to 1.5.1
 Tuesday, September 5, 2017
 ====================================
 
 - Fix "unsafe-to-break" in fallback shaping and other corner cases.
   All our tests pass with --verify now, meaning unsafe-to-break API
   works as expected.
 - Add --unicodes to hb-view / hb-shape.
--- a/gfx/harfbuzz/README-mozilla
+++ b/gfx/harfbuzz/README-mozilla
@@ -1,14 +1,14 @@
-gfx/harfbuzz status as of 2017-09-05:
+gfx/harfbuzz status as of 2017-10-13:
 
 This directory contains the harfbuzz source from the 'master' branch of
 https://github.com/behdad/harfbuzz.
 
-Current version: 1.5.1
+Current version: 1.6.0
 
 UPDATING:
 
 Note that gfx/harfbuzz/src/hb-version.h is not present in the upstream Git
 repository. It is created at build time by the harfbuzz build system;
 but as we don't use that build system in mozilla, it is necessary to refresh
 this file when updating harfbuzz, and check it into the mozilla tree.
 
--- a/gfx/harfbuzz/configure.ac
+++ b/gfx/harfbuzz/configure.ac
@@ -1,11 +1,11 @@
 AC_PREREQ([2.64])
 AC_INIT([HarfBuzz],
-        [1.5.1],
+        [1.6.0],
         [https://github.com/behdad/harfbuzz/issues/new],
         [harfbuzz],
         [http://harfbuzz.org/])
 
 AC_CONFIG_MACRO_DIR([m4])
 AC_CONFIG_SRCDIR([src/harfbuzz.pc.in])
 AC_CONFIG_HEADERS([config.h])
 
@@ -64,18 +64,18 @@ GTK_DOC_CHECK([1.15],[--flavour no-tmpl]
 	if test "x$enable_gtk_doc" = xyes; then
 		have_gtk_doc=true
 	fi
 ], [
 	AM_CONDITIONAL([ENABLE_GTK_DOC], false)
 ])
 
 # Functions and headers
-AC_CHECK_FUNCS(atexit mprotect sysconf getpagesize mmap isatty)
-AC_CHECK_HEADERS(unistd.h sys/mman.h)
+AC_CHECK_FUNCS(atexit mprotect sysconf getpagesize mmap isatty newlocale strtod_l)
+AC_CHECK_HEADERS(unistd.h sys/mman.h xlocale.h)
 
 # Compiler flags
 AC_CANONICAL_HOST
 AC_CHECK_ALIGNOF([struct{char;}])
 if test "x$GCC" = "xyes"; then
 
 	# Make symbols link locally
 	LDFLAGS="$LDFLAGS -Bsymbolic-functions"
@@ -489,18 +489,16 @@ src/hb-version.h
 src/hb-ucdn/Makefile
 util/Makefile
 test/Makefile
 test/api/Makefile
 test/fuzzing/Makefile
 test/shaping/Makefile
 docs/Makefile
 docs/version.xml
-win32/Makefile
-win32/config.h.win32
 ])
 
 AC_OUTPUT
 
 AC_MSG_NOTICE([
 
 Build configuration:
 
--- a/gfx/harfbuzz/src/Makefile.am
+++ b/gfx/harfbuzz/src/Makefile.am
@@ -117,17 +117,17 @@ if HAVE_GCC
 libharfbuzz_la_LINK = $(LINK) $(libharfbuzz_la_LDFLAGS)
 else
 libharfbuzz_la_LINK = $(CXXLINK) $(libharfbuzz_la_LDFLAGS)
 endif
 endif
 
 libharfbuzz_la_SOURCES = $(HBSOURCES) $(HBHEADERS) $(HBNODISTHEADERS)
 libharfbuzz_la_CPPFLAGS = $(HBCFLAGS)
-libharfbuzz_la_LDFLAGS = $(AM_LDFLAGS) -version-info $(HB_LIBTOOL_VERSION_INFO) $(export_symbols) -no-undefined
+libharfbuzz_la_LDFLAGS = $(AM_LDFLAGS) -lm -version-info $(HB_LIBTOOL_VERSION_INFO) $(export_symbols) -no-undefined
 libharfbuzz_la_LIBADD = $(HBLIBS)
 EXTRA_libharfbuzz_la_DEPENDENCIES = $(harfbuzz_def_dependency)
 pkginclude_HEADERS = $(HBHEADERS)
 nodist_pkginclude_HEADERS = $(HBNODISTHEADERS)
 pkgconfigdir = $(libdir)/pkgconfig
 pkgconfig_DATA = harfbuzz.pc
 EXTRA_DIST += harfbuzz.pc.in
 
@@ -295,16 +295,17 @@ test_buffer_serialize_SOURCES = test-buf
 test_buffer_serialize_CPPFLAGS = $(HBCFLAGS)
 test_buffer_serialize_LDADD = libharfbuzz.la $(HBLIBS)
 
 check: harfbuzz.def # For check-defs.sh
 
 dist_check_SCRIPTS = \
 	check-c-linkage-decls.sh \
 	check-defs.sh \
+	check-externs.sh \
 	check-header-guards.sh \
 	check-includes.sh \
 	check-libstdc++.sh \
 	check-static-inits.sh \
 	check-symbols.sh \
 	$(NULL)
 
 check_PROGRAMS = \
new file mode 100755
--- /dev/null
+++ b/gfx/harfbuzz/src/check-externs.sh
@@ -0,0 +1,21 @@
+#!/bin/sh
+
+LC_ALL=C
+export LC_ALL
+
+test -z "$srcdir" && srcdir=.
+stat=0
+
+test "x$HBHEADERS" = x && HBHEADERS=`cd "$srcdir"; find . -maxdepth 1 -name 'hb*.h'`
+test "x$EGREP" = x && EGREP='grep -E'
+
+
+echo 'Checking that all public symbols are exported with HB_EXTERN'
+
+for x in $HBHEADERS; do
+	test -f "$srcdir/$x" && x="$srcdir/$x"
+	$EGREP -B1 '^hb_' "$x" | $EGREP -E -v '^(--|hb_|HB_EXTERN )' -A1
+done |
+grep . >&2 && stat=1
+
+exit $stat
--- a/gfx/harfbuzz/src/gen-use-table.py
+++ b/gfx/harfbuzz/src/gen-use-table.py
@@ -112,16 +112,17 @@ property_names = [
 	'Visual_Order_Left',
 	'Left_And_Right',
 	'Top',
 	'Bottom',
 	'Top_And_Bottom',
 	'Top_And_Right',
 	'Top_And_Left',
 	'Top_And_Left_And_Right',
+	'Bottom_And_Left',
 	'Bottom_And_Right',
 	'Top_And_Bottom_And_Right',
 	'Overstruck',
 ]
 
 class PropertyValue(object):
 	def __init__(self, name_):
 		self.name = name_
@@ -148,17 +149,17 @@ def is_BASE(U, UISC, UGC):
 			Tone_Letter,
 			Vowel_Independent #SPEC-DRAFT
 			] or
 		(UGC == Lo and UISC in [Avagraha, Bindu, Consonant_Final, Consonant_Medial,
 					Consonant_Subjoined, Vowel, Vowel_Dependent]))
 def is_BASE_IND(U, UISC, UGC):
 	#SPEC-DRAFT return (UISC in [Consonant_Dead, Modifying_Letter] or UGC == Po)
 	return (UISC in [Consonant_Dead, Modifying_Letter] or
-		(UGC == Po and not U in [0x104E, 0x2022]) or
+		(UGC == Po and not U in [0x104E, 0x2022, 0x11A3F, 0x11A45]) or
 		False # SPEC-DRAFT-OUTDATED! U == 0x002D
 		)
 def is_BASE_NUM(U, UISC, UGC):
 	return UISC == Brahmi_Joining_Number
 def is_BASE_OTHER(U, UISC, UGC):
 	if UISC == Consonant_Placeholder: return True #SPEC-DRAFT
 	#SPEC-DRAFT return U in [0x00A0, 0x00D7, 0x2015, 0x2022, 0x25CC, 0x25FB, 0x25FC, 0x25FD, 0x25FE]
 	return U in [0x2015, 0x2022, 0x25FB, 0x25FC, 0x25FD, 0x25FE]
@@ -172,16 +173,18 @@ def is_CONS_FINAL_MOD(U, UISC, UGC):
 	return  UISC == Syllable_Modifier
 def is_CONS_MED(U, UISC, UGC):
 	return UISC == Consonant_Medial and UGC != Lo
 def is_CONS_MOD(U, UISC, UGC):
 	return UISC in [Nukta, Gemination_Mark, Consonant_Killer]
 def is_CONS_SUB(U, UISC, UGC):
 	#SPEC-DRAFT return UISC == Consonant_Subjoined
 	return UISC == Consonant_Subjoined and UGC != Lo
+def is_CONS_WITH_STACKER(U, UISC, UGC):
+	return UISC == Consonant_With_Stacker
 def is_HALANT(U, UISC, UGC):
 	return UISC in [Virama, Invisible_Stacker]
 def is_HALANT_NUM(U, UISC, UGC):
 	return UISC == Number_Joiner
 def is_ZWNJ(U, UISC, UGC):
 	return UISC == Non_Joiner
 def is_ZWJ(U, UISC, UGC):
 	return UISC == Joiner
@@ -193,19 +196,17 @@ def is_OTHER(U, UISC, UGC):
 		and not is_SYM_MOD(U, UISC, UGC)
 		and not is_CGJ(U, UISC, UGC)
 		and not is_Word_Joiner(U, UISC, UGC)
 		and not is_VARIATION_SELECTOR(U, UISC, UGC)
 	)
 def is_Reserved(U, UISC, UGC):
 	return UGC == 'Cn'
 def is_REPHA(U, UISC, UGC):
-	#return UISC == Consonant_Preceding_Repha
-	#SPEC-OUTDATED hack to categorize Consonant_With_Stacker and Consonant_Prefixed
-	return UISC in [Consonant_Preceding_Repha, Consonant_With_Stacker, Consonant_Prefixed]
+	return UISC in [Consonant_Preceding_Repha, Consonant_Prefixed]
 def is_SYM(U, UISC, UGC):
 	if U == 0x25CC: return False #SPEC-DRAFT
 	#SPEC-DRAFT return UGC in [So, Sc] or UISC == Symbol_Letter
 	return UGC in [So, Sc]
 def is_SYM_MOD(U, UISC, UGC):
 	return U in [0x1B6B, 0x1B6C, 0x1B6D, 0x1B6E, 0x1B6F, 0x1B70, 0x1B71, 0x1B72, 0x1B73]
 def is_VARIATION_SELECTOR(U, UISC, UGC):
 	return 0xFE00 <= U <= 0xFE0F
@@ -224,16 +225,17 @@ use_mapping = {
 	'N':	is_BASE_NUM,
 	'GB':	is_BASE_OTHER,
 	'CGJ':	is_CGJ,
 	'F':	is_CONS_FINAL,
 	'FM':	is_CONS_FINAL_MOD,
 	'M':	is_CONS_MED,
 	'CM':	is_CONS_MOD,
 	'SUB':	is_CONS_SUB,
+	'CS':	is_CONS_WITH_STACKER,
 	'H':	is_HALANT,
 	'HN':	is_HALANT_NUM,
 	'ZWNJ':	is_ZWNJ,
 	'ZWJ':	is_ZWJ,
 	'WJ':	is_Word_Joiner,
 	'O':	is_OTHER,
 	'Rsv':	is_Reserved,
 	'R':	is_REPHA,
@@ -247,17 +249,17 @@ use_mapping = {
 use_positions = {
 	'F': {
 		'Abv': [Top],
 		'Blw': [Bottom],
 		'Pst': [Right],
 	},
 	'M': {
 		'Abv': [Top],
-		'Blw': [Bottom],
+		'Blw': [Bottom, Bottom_And_Left],
 		'Pst': [Right],
 		'Pre': [Left],
 	},
 	'CM': {
 		'Abv': [Top],
 		'Blw': [Bottom],
 	},
 	'V': {
@@ -293,18 +295,20 @@ def map_to_use(data):
 		# have UIPC
 		if U == 0x17DD: UISC = Vowel_Dependent
 		if 0x1CE2 <= U <= 0x1CE8: UISC = Cantillation_Mark
 
 		# TODO: U+1CED should only be allowed after some of
 		# the nasalization marks, maybe only for U+1CE9..U+1CF1.
 		if U == 0x1CED: UISC = Tone_Mark
 
-		evals = [(k, v(U,UISC,UGC)) for k,v in items]
-		values = [k for k,v in evals if v]
+		# TODO: https://github.com/behdad/harfbuzz/issues/525
+		if U == 0x1A7F: UISC = Consonant_Final; UIPC = Bottom
+
+		values = [k for k,v in items if v(U,UISC,UGC)]
 		assert len(values) == 1, "%s %s %s %s" % (hex(U), UISC, UGC, values)
 		USE = values[0]
 
 		# Resolve Indic_Positional_Category
 
 		# TODO: Not in Unicode 8.0 yet, but in spec.
 		if U == 0x1B6C: UIPC = Bottom
 
--- a/gfx/harfbuzz/src/harfbuzz-icu.pc
+++ b/gfx/harfbuzz/src/harfbuzz-icu.pc
@@ -1,13 +1,13 @@
 prefix=/usr/local
 exec_prefix=/usr/local
 libdir=/usr/local/lib
 includedir=/usr/local/include
 
 Name: harfbuzz
 Description: HarfBuzz text shaping library ICU integration
-Version: 1.5.1
+Version: 1.6.0
 
 Requires: harfbuzz
 Requires.private: icu-uc
 Libs: -L${libdir} -lharfbuzz-icu
 Cflags: -I${includedir}/harfbuzz
--- a/gfx/harfbuzz/src/harfbuzz.pc
+++ b/gfx/harfbuzz/src/harfbuzz.pc
@@ -1,13 +1,13 @@
 prefix=/usr/local
 exec_prefix=/usr/local
 libdir=/usr/local/lib
 includedir=/usr/local/include
 
 Name: harfbuzz
 Description: HarfBuzz text shaping library
-Version: 1.5.1
+Version: 1.6.0
 
 Libs: -L${libdir} -lharfbuzz
-Libs.private:    
+Libs.private: -lm    
 Requires.private: glib-2.0 >= 2.19.1 
 Cflags: -I${includedir}/harfbuzz
--- a/gfx/harfbuzz/src/harfbuzz.pc.in
+++ b/gfx/harfbuzz/src/harfbuzz.pc.in
@@ -3,11 +3,11 @@ exec_prefix=%exec_prefix%
 libdir=%libdir%
 includedir=%includedir%
 
 Name: harfbuzz
 Description: HarfBuzz text shaping library
 Version: %VERSION%
 
 Libs: -L${libdir} -lharfbuzz
-Libs.private: %libs_private%
+Libs.private: -lm %libs_private%
 Requires.private: %requires_private%
 Cflags: -I${includedir}/harfbuzz
--- a/gfx/harfbuzz/src/hb-blob.cc
+++ b/gfx/harfbuzz/src/hb-blob.cc
@@ -123,16 +123,22 @@ hb_blob_create (const char        *data,
       hb_blob_destroy (blob);
       return hb_blob_get_empty ();
     }
   }
 
   return blob;
 }
 
+static void
+_hb_blob_destroy (void *data)
+{
+  hb_blob_destroy ((hb_blob_t *) data);
+}
+
 /**
  * hb_blob_create_sub_blob:
  * @parent: Parent blob.
  * @offset: Start offset of sub-blob within @parent, in bytes.
  * @length: Length of sub-blob.
  *
  * Returns a blob that represents a range of bytes in @parent.  The new
  * blob is always created with %HB_MEMORY_MODE_READONLY, meaning that it
@@ -159,17 +165,17 @@ hb_blob_create_sub_blob (hb_blob_t    *p
     return hb_blob_get_empty ();
 
   hb_blob_make_immutable (parent);
 
   blob = hb_blob_create (parent->data + offset,
 			 MIN (length, parent->length - offset),
 			 HB_MEMORY_MODE_READONLY,
 			 hb_blob_reference (parent),
-			 (hb_destroy_func_t) hb_blob_destroy);
+			 _hb_blob_destroy);
 
   return blob;
 }
 
 /**
  * hb_blob_get_empty:
  *
  * Returns the singleton empty blob.
--- a/gfx/harfbuzz/src/hb-buffer.h
+++ b/gfx/harfbuzz/src/hb-buffer.h
@@ -499,17 +499,17 @@ typedef enum { /*< flags >*/
   HB_BUFFER_DIFF_FLAG_CODEPOINT_MISMATCH	= 0x0010,
   HB_BUFFER_DIFF_FLAG_CLUSTER_MISMATCH		= 0x0020,
   HB_BUFFER_DIFF_FLAG_GLYPH_FLAGS_MISMATCH	= 0x0040,
   HB_BUFFER_DIFF_FLAG_POSITION_MISMATCH		= 0x0080
 
 } hb_buffer_diff_flags_t;
 
 /* Compare the contents of two buffers, report types of differences. */
-hb_buffer_diff_flags_t
+HB_EXTERN hb_buffer_diff_flags_t
 hb_buffer_diff (hb_buffer_t *buffer,
 		hb_buffer_t *reference,
 		hb_codepoint_t dottedcircle_glyph,
 		unsigned int position_fuzz);
 
 
 /*
  * Debugging.
--- a/gfx/harfbuzz/src/hb-common.cc
+++ b/gfx/harfbuzz/src/hb-common.cc
@@ -27,16 +27,19 @@
  */
 
 #include "hb-private.hh"
 
 #include "hb-mutex-private.hh"
 #include "hb-object-private.hh"
 
 #include <locale.h>
+#ifdef HAVE_XLOCALE_H
+#include <xlocale.h>
+#endif
 
 
 /* hb_options_t */
 
 hb_options_union_t _hb_options;
 
 void
 _hb_options_init (void)
@@ -241,18 +244,18 @@ struct hb_language_item_t {
 };
 
 
 /* Thread-safe lock-free language list */
 
 static hb_language_item_t *langs;
 
 #ifdef HB_USE_ATEXIT
-static
-void free_langs (void)
+static void
+free_langs (void)
 {
   while (langs) {
     hb_language_item_t *next = langs->next;
     langs->finish ();
     free (langs);
     langs = next;
   }
 }
@@ -689,30 +692,76 @@ parse_uint32 (const char **pp, const cha
   if (errno || p == pend)
     return false;
 
   *pv = v;
   *pp += pend - p;
   return true;
 }
 
+#if defined (HAVE_NEWLOCALE) && defined (HAVE_STRTOD_L)
+#define USE_XLOCALE 1
+#endif
+
+#ifdef USE_XLOCALE
+
+static locale_t C_locale;
+
+#ifdef HB_USE_ATEXIT
+static void
+free_C_locale (void)
+{
+  if (C_locale)
+    freelocale (C_locale);
+}
+#endif
+
+static locale_t
+get_C_locale (void)
+{
+retry:
+  locale_t C = (locale_t) hb_atomic_ptr_get (&C_locale);
+
+  if (unlikely (!C))
+  {
+    C = newlocale (LC_ALL_MASK, "C", NULL);
+
+    if (!hb_atomic_ptr_cmpexch (&C_locale, NULL, C))
+    {
+      freelocale (C_locale);
+      goto retry;
+    }
+
+#ifdef HB_USE_ATEXIT
+    atexit (free_C_locale); /* First person registers atexit() callback. */
+#endif
+  }
+
+  return C;
+}
+#endif
+
 static bool
 parse_float (const char **pp, const char *end, float *pv)
 {
   char buf[32];
   unsigned int len = MIN (ARRAY_LENGTH (buf) - 1, (unsigned int) (end - *pp));
   strncpy (buf, *pp, len);
   buf[len] = '\0';
 
   char *p = buf;
   char *pend = p;
   float v;
 
   errno = 0;
+#ifdef USE_XLOCALE
+  v = strtod_l (p, &pend, get_C_locale ());
+#else
   v = strtod (p, &pend);
+#endif
   if (errno || p == pend)
     return false;
 
   *pv = v;
   *pp += pend - p;
   return true;
 }
 
--- a/gfx/harfbuzz/src/hb-common.h
+++ b/gfx/harfbuzz/src/hb-common.h
@@ -38,40 +38,26 @@
 #  define HB_BEGIN_DECLS	extern "C" {
 #  define HB_END_DECLS		}
 # else /* !__cplusplus */
 #  define HB_BEGIN_DECLS
 #  define HB_END_DECLS
 # endif /* !__cplusplus */
 #endif
 
-#if !defined (HB_DONT_DEFINE_STDINT)
-
 #if defined (_SVR4) || defined (SVR4) || defined (__OpenBSD__) || \
     defined (_sgi) || defined (__sun) || defined (sun) || \
     defined (__digital__) || defined (__HP_cc)
 #  include <inttypes.h>
 #elif defined (_AIX)
 #  include <sys/inttypes.h>
-/* VS 2010 (_MSC_VER 1600) has stdint.h */
-#elif defined (_MSC_VER) && _MSC_VER < 1600
-typedef __int8 int8_t;
-typedef unsigned __int8 uint8_t;
-typedef __int16 int16_t;
-typedef unsigned __int16 uint16_t;
-typedef __int32 int32_t;
-typedef unsigned __int32 uint32_t;
-typedef __int64 int64_t;
-typedef unsigned __int64 uint64_t;
 #else
 #  include <stdint.h>
 #endif
 
-#endif
-
 HB_BEGIN_DECLS
 
 
 typedef int hb_bool_t;
 
 typedef uint32_t hb_codepoint_t;
 typedef int32_t hb_position_t;
 typedef uint32_t hb_mask_t;
@@ -316,16 +302,24 @@ typedef enum
    */
   /*9.0*/ HB_SCRIPT_ADLAM			= HB_TAG ('A','d','l','m'),
   /*9.0*/ HB_SCRIPT_BHAIKSUKI			= HB_TAG ('B','h','k','s'),
   /*9.0*/ HB_SCRIPT_MARCHEN			= HB_TAG ('M','a','r','c'),
   /*9.0*/ HB_SCRIPT_OSAGE			= HB_TAG ('O','s','g','e'),
   /*9.0*/ HB_SCRIPT_TANGUT			= HB_TAG ('T','a','n','g'),
   /*9.0*/ HB_SCRIPT_NEWA			= HB_TAG ('N','e','w','a'),
 
+  /*
+   * Since 1.6.0
+   */
+  /*10.0*/HB_SCRIPT_MASARAM_GONDI		= HB_TAG ('G','o','n','m'),
+  /*10.0*/HB_SCRIPT_NUSHU			= HB_TAG ('N','s','h','u'),
+  /*10.0*/HB_SCRIPT_SOYOMBO			= HB_TAG ('S','o','y','o'),
+  /*10.0*/HB_SCRIPT_ZANABAZAR_SQUARE		= HB_TAG ('Z','a','n','b'),
+
   /* No script set. */
   HB_SCRIPT_INVALID				= HB_TAG_NONE,
 
   /* Dummy values to ensure any hb_tag_t value can be passed/stored as hb_script_t
    * without risking undefined behavior.  Include both a signed and unsigned max,
    * since technically enums are int, and indeed, hb_script_t ends up being signed.
    * See this thread for technicalities:
    *
--- a/gfx/harfbuzz/src/hb-coretext.cc
+++ b/gfx/harfbuzz/src/hb-coretext.cc
@@ -25,22 +25,37 @@
  * Mozilla Author(s): Jonathan Kew
  * Google Author(s): Behdad Esfahbod
  */
 
 #define HB_SHAPER coretext
 #include "hb-shaper-impl-private.hh"
 
 #include "hb-coretext.h"
+#include <math.h>
 
 
 #ifndef HB_DEBUG_CORETEXT
 #define HB_DEBUG_CORETEXT (HB_DEBUG+0)
 #endif
 
+/* https://developer.apple.com/documentation/coretext/1508745-ctfontcreatewithgraphicsfont */
+#define HB_CORETEXT_DEFAULT_FONT_SIZE 12.f
+
+static CGFloat
+coretext_font_size (float ptem)
+{
+  /* CoreText points are CSS pixels (96 per inch),
+   * NOT typographic points (72 per inch).
+   *
+   * https://developer.apple.com/library/content/documentation/GraphicsAnimation/Conceptual/HighResolutionOSX/Explained/Explained.html
+   */
+  ptem *= 96.f / 72.f;
+  return ptem <= 0.f ? HB_CORETEXT_DEFAULT_FONT_SIZE : ptem;
+}
 
 static void
 release_table_data (void *user_data)
 {
   CFDataRef cf_data = reinterpret_cast<CFDataRef> (user_data);
   CFRelease(cf_data);
 }
 
@@ -57,26 +72,32 @@ reference_table  (hb_face_t *face HB_UNU
   if (!data || !length)
     return NULL;
 
   return hb_blob_create (data, length, HB_MEMORY_MODE_READONLY,
 			 reinterpret_cast<void *> (const_cast<__CFData *> (cf_data)),
 			 release_table_data);
 }
 
+static void
+_hb_cg_font_release (void *data)
+{
+  CGFontRelease ((CGFontRef) data);
+}
+
 hb_face_t *
 hb_coretext_face_create (CGFontRef cg_font)
 {
-  return hb_face_create_for_tables (reference_table, CGFontRetain (cg_font), (hb_destroy_func_t) CGFontRelease);
+  return hb_face_create_for_tables (reference_table, CGFontRetain (cg_font), _hb_cg_font_release);
 }
 
-
 HB_SHAPER_DATA_ENSURE_DEFINE(coretext, face)
-HB_SHAPER_DATA_ENSURE_DEFINE(coretext, font)
-
+HB_SHAPER_DATA_ENSURE_DEFINE_WITH_CONDITION(coretext, font,
+	fabs (CTFontGetSize((CTFontRef) data) - coretext_font_size (font->ptem)) <= .5
+)
 
 /*
  * shaper face data
  */
 
 static CTFontDescriptorRef
 get_last_resort_font_desc (void)
 {
@@ -108,17 +129,17 @@ release_data (void *info, const void *da
 
   hb_blob_destroy ((hb_blob_t *) info);
 }
 
 static CGFontRef
 create_cg_font (hb_face_t *face)
 {
   CGFontRef cg_font = NULL;
-  if (face->destroy == (hb_destroy_func_t) CGFontRelease)
+  if (face->destroy == _hb_cg_font_release)
   {
     cg_font = CGFontRetain ((CGFontRef) face->user_data);
   }
   else
   {
     hb_blob_t *blob = hb_face_reference_blob (face);
     unsigned int blob_length;
     const char *blob_data = hb_blob_get_data (blob, &blob_length);
@@ -135,17 +156,43 @@ create_cg_font (hb_face_t *face)
     }
   }
   return cg_font;
 }
 
 static CTFontRef
 create_ct_font (CGFontRef cg_font, CGFloat font_size)
 {
-  CTFontRef ct_font = CTFontCreateWithGraphicsFont (cg_font, font_size, NULL, NULL);
+  CTFontRef ct_font = NULL;
+
+  /* CoreText does not enable trak table usage / tracking when creating a CTFont
+   * using CTFontCreateWithGraphicsFont. The only way of enabling tracking seems
+   * to be through the CTFontCreateUIFontForLanguage call. */
+  CFStringRef cg_postscript_name = CGFontCopyPostScriptName (cg_font);
+  if (CFStringHasPrefix (cg_postscript_name, CFSTR (".SFNSText")) ||
+      CFStringHasPrefix (cg_postscript_name, CFSTR (".SFNSDisplay")))
+  {
+    CTFontUIFontType font_type = kCTFontUIFontSystem;
+    if (CFStringHasSuffix (cg_postscript_name, CFSTR ("-Bold")))
+      font_type = kCTFontUIFontEmphasizedSystem;
+
+    ct_font = CTFontCreateUIFontForLanguage (font_type, font_size, NULL);
+    CFStringRef ct_result_name = CTFontCopyPostScriptName(ct_font);
+    if (CFStringCompare (ct_result_name, cg_postscript_name, 0) != kCFCompareEqualTo)
+    {
+      CFRelease(ct_font);
+      ct_font = NULL;
+    }
+    CFRelease (ct_result_name);
+  }
+  CFRelease (cg_postscript_name);
+
+  if (!ct_font)
+    ct_font = CTFontCreateWithGraphicsFont (cg_font, font_size, NULL, NULL);
+
   if (unlikely (!ct_font)) {
     DEBUG_MSG (CORETEXT, cg_font, "Font CTFontCreateWithGraphicsFont() failed");
     return NULL;
   }
 
   /* crbug.com/576941 and crbug.com/625902 and the investigation in the latter
    * bug indicate that the cascade list reconfiguration occasionally causes
    * crashes in CoreText on OS X 10.9, thus let's skip this step on older
@@ -197,90 +244,73 @@ create_ct_font (CGFontRef cg_font, CGFlo
       DEBUG_MSG (CORETEXT, ct_font, "Font copy with empty cascade list failed");
   }
 
   if (original_url)
     CFRelease (original_url);
   return ct_font;
 }
 
-struct hb_coretext_shaper_face_data_t {
-  CGFontRef cg_font;
-  CTFontRef ct_font;
-};
-
 hb_coretext_shaper_face_data_t *
 _hb_coretext_shaper_face_data_create (hb_face_t *face)
 {
-  hb_coretext_shaper_face_data_t *data = (hb_coretext_shaper_face_data_t *) calloc (1, sizeof (hb_coretext_shaper_face_data_t));
-  if (unlikely (!data))
-    return NULL;
+  CGFontRef cg_font = create_cg_font (face);
 
-  data->cg_font = create_cg_font (face);
-  if (unlikely (!data->cg_font))
+  if (unlikely (!cg_font))
   {
     DEBUG_MSG (CORETEXT, face, "CGFont creation failed..");
-    free (data);
     return NULL;
   }
 
-  /* We use 36pt size instead of UPEM, because CoreText implements the 'trak' table,
-   * which can make the font too tight at large sizes.  36pt should be a good semi-neutral
-   * size.
-   *
-   * Since we always create CTFont at a fixed size, our CTFont lives in face_data
-   * instead of font_data.  Which is good, because when people change scale on
-   * hb_font_t, we won't need to update our CTFont. */
-  data->ct_font = create_ct_font (data->cg_font, 36.);
-  if (unlikely (!data->ct_font))
-  {
-    DEBUG_MSG (CORETEXT, face, "CTFont creation failed.");
-    CFRelease (data->cg_font);
-    free (data);
-    return NULL;
-  }
-
-  return data;
+  return (hb_coretext_shaper_face_data_t *) cg_font;
 }
 
 void
 _hb_coretext_shaper_face_data_destroy (hb_coretext_shaper_face_data_t *data)
 {
-  CFRelease (data->ct_font);
-  CFRelease (data->cg_font);
-  free (data);
+  CFRelease ((CGFontRef) data);
 }
 
 /*
  * Since: 0.9.10
  */
 CGFontRef
 hb_coretext_face_get_cg_font (hb_face_t *face)
 {
   if (unlikely (!hb_coretext_shaper_face_data_ensure (face))) return NULL;
-  hb_coretext_shaper_face_data_t *face_data = HB_SHAPER_DATA_GET (face);
-  return face_data->cg_font;
+  return (CGFontRef) HB_SHAPER_DATA_GET (face);
 }
 
 
 /*
  * shaper font data
  */
 
-struct hb_coretext_shaper_font_data_t {};
+hb_coretext_shaper_font_data_t *
+_hb_coretext_shaper_font_data_create (hb_font_t *font)
+{
+  hb_face_t *face = font->face;
+  if (unlikely (!hb_coretext_shaper_face_data_ensure (face))) return NULL;
+  CGFontRef cg_font = (CGFontRef) HB_SHAPER_DATA_GET (face);
 
-hb_coretext_shaper_font_data_t *
-_hb_coretext_shaper_font_data_create (hb_font_t *font HB_UNUSED)
-{
-  return (hb_coretext_shaper_font_data_t *) HB_SHAPER_DATA_SUCCEEDED;
+  CTFontRef ct_font = create_ct_font (cg_font, coretext_font_size (font->ptem));
+
+  if (unlikely (!ct_font))
+  {
+    DEBUG_MSG (CORETEXT, font, "CGFont creation failed..");
+    return NULL;
+  }
+
+  return (hb_coretext_shaper_font_data_t *) ct_font;
 }
 
 void
 _hb_coretext_shaper_font_data_destroy (hb_coretext_shaper_font_data_t *data)
 {
+  CFRelease ((CTFontRef) data);
 }
 
 
 /*
  * shaper shape_plan data
  */
 
 struct hb_coretext_shaper_shape_plan_data_t {};
@@ -298,20 +328,18 @@ hb_coretext_shaper_shape_plan_data_t *
 void
 _hb_coretext_shaper_shape_plan_data_destroy (hb_coretext_shaper_shape_plan_data_t *data HB_UNUSED)
 {
 }
 
 CTFontRef
 hb_coretext_font_get_ct_font (hb_font_t *font)
 {
-  hb_face_t *face = font->face;
-  if (unlikely (!hb_coretext_shaper_face_data_ensure (face))) return NULL;
-  hb_coretext_shaper_face_data_t *face_data = HB_SHAPER_DATA_GET (face);
-  return face_data->ct_font;
+  if (unlikely (!hb_coretext_shaper_font_data_ensure (font))) return NULL;
+  return (CTFontRef)HB_SHAPER_DATA_GET (font);
 }
 
 
 /*
  * shaper
  */
 
 struct feature_record_t {
@@ -533,19 +561,20 @@ static int
 hb_bool_t
 _hb_coretext_shape (hb_shape_plan_t    *shape_plan,
 		    hb_font_t          *font,
                     hb_buffer_t        *buffer,
                     const hb_feature_t *features,
                     unsigned int        num_features)
 {
   hb_face_t *face = font->face;
-  hb_coretext_shaper_face_data_t *face_data = HB_SHAPER_DATA_GET (face);
+  CGFontRef cg_font = (CGFontRef) HB_SHAPER_DATA_GET (face);
+  CTFontRef ct_font = (CTFontRef) HB_SHAPER_DATA_GET (font);
 
-  CGFloat ct_font_size = CTFontGetSize (face_data->ct_font);
+  CGFloat ct_font_size = CTFontGetSize (ct_font);
   CGFloat x_mult = (CGFloat) font->x_scale / ct_font_size;
   CGFloat y_mult = (CGFloat) font->y_scale / ct_font_size;
 
   /* Attach marks to their bases, to match the 'ot' shaper.
    * Adapted from hb-ot-shape:hb_form_clusters().
    * Note that this only makes us be closer to the 'ot' shaper,
    * but by no means the same.  For example, if there's
    * B1 M1 B2 M2, and B1-B2 form a ligature, M2's cluster will
@@ -670,17 +699,17 @@ hb_bool_t
 							   1,
 							   &kCFTypeDictionaryKeyCallBacks,
 							   &kCFTypeDictionaryValueCallBacks);
 	  CFRelease (features_array);
 
 	  CTFontDescriptorRef font_desc = CTFontDescriptorCreateWithAttributes (attributes);
 	  CFRelease (attributes);
 
-	  range->font = CTFontCreateCopyWithAttributes (face_data->ct_font, 0.0, NULL, font_desc);
+	  range->font = CTFontCreateCopyWithAttributes (ct_font, 0.0, NULL, font_desc);
 	  CFRelease (font_desc);
 	}
 	else
 	{
 	  range->font = NULL;
 	}
 
 	range->index_first = last_index;
@@ -824,17 +853,17 @@ resize_and_retry:
 							    kCFAllocatorNull);
 	if (unlikely (!lang))
 	  FAIL ("CFStringCreateWithCStringNoCopy failed");
 	CFAttributedStringSetAttribute (attr_string, CFRangeMake (0, chars_len),
 					kCTLanguageAttributeName, lang);
 	CFRelease (lang);
       }
       CFAttributedStringSetAttribute (attr_string, CFRangeMake (0, chars_len),
-				      kCTFontAttributeName, face_data->ct_font);
+				      kCTFontAttributeName, ct_font);
 
       if (num_features && range_records.len)
       {
 	unsigned int start = 0;
 	range_record_t *last_range = &range_records[0];
 	for (unsigned int k = 0; k < chars_len; k++)
 	{
 	  range_record_t *range = last_range;
@@ -942,17 +971,17 @@ resize_and_retry:
       /* CoreText does automatic font fallback (AKA "cascading") for  characters
        * not supported by the requested font, and provides no way to turn it off,
        * so we must detect if the returned run uses a font other than the requested
        * one and fill in the buffer with .notdef glyphs instead of random glyph
        * indices from a different font.
        */
       CFDictionaryRef attributes = CTRunGetAttributes (run);
       CTFontRef run_ct_font = static_cast<CTFontRef>(CFDictionaryGetValue (attributes, kCTFontAttributeName));
-      if (!CFEqual (run_ct_font, face_data->ct_font))
+      if (!CFEqual (run_ct_font, ct_font))
       {
 	/* The run doesn't use our main font instance.  We have to figure out
 	 * whether font fallback happened, or this is just CoreText giving us
 	 * another CTFont using the same underlying CGFont.  CoreText seems
 	 * to do that in a variety of situations, one of which being vertical
 	 * text, but also perhaps for caching reasons.
 	 *
 	 * First, see if it uses any of our subfonts created to set font features...
@@ -980,23 +1009,23 @@ resize_and_retry:
 	    matched = true;
 	    break;
 	  }
 	if (!matched)
 	{
 	  CGFontRef run_cg_font = CTFontCopyGraphicsFont (run_ct_font, 0);
 	  if (run_cg_font)
 	  {
-	    matched = CFEqual (run_cg_font, face_data->cg_font);
+	    matched = CFEqual (run_cg_font, cg_font);
 	    CFRelease (run_cg_font);
 	  }
 	}
 	if (!matched)
 	{
-	  CFStringRef font_ps_name = CTFontCopyName (face_data->ct_font, kCTFontPostScriptNameKey);
+	  CFStringRef font_ps_name = CTFontCopyName (ct_font, kCTFontPostScriptNameKey);
 	  CFStringRef run_ps_name = CTFontCopyName (run_ct_font, kCTFontPostScriptNameKey);
 	  CFComparisonResult result = CFStringCompare (run_ps_name, font_ps_name, 0);
 	  CFRelease (run_ps_name);
 	  CFRelease (font_ps_name);
 	  if (result == kCFCompareEqualTo)
 	    matched = true;
 	}
 	if (!matched)
@@ -1258,32 +1287,30 @@ HB_SHAPER_DATA_ENSURE_DEFINE(coretext_aa
  * shaper face data
  */
 
 struct hb_coretext_aat_shaper_face_data_t {};
 
 hb_coretext_aat_shaper_face_data_t *
 _hb_coretext_aat_shaper_face_data_create (hb_face_t *face)
 {
-  hb_blob_t *mort_blob = face->reference_table (HB_CORETEXT_TAG_MORT);
-  /* Umm, we just reference the table to check whether it exists.
-   * Maybe add better API for this? */
-  if (!hb_blob_get_length (mort_blob))
+  static const hb_tag_t tags[] = {HB_CORETEXT_TAG_MORX, HB_CORETEXT_TAG_MORT, HB_CORETEXT_TAG_KERX};
+
+  for (unsigned int i = 0; i < ARRAY_LENGTH (tags); i++)
   {
-    hb_blob_destroy (mort_blob);
-    mort_blob = face->reference_table (HB_CORETEXT_TAG_MORX);
-    if (!hb_blob_get_length (mort_blob))
+    hb_blob_t *blob = face->reference_table (tags[i]);
+    if (hb_blob_get_length (blob))
     {
-      hb_blob_destroy (mort_blob);
-      return NULL;
+      hb_blob_destroy (blob);
+      return hb_coretext_shaper_face_data_ensure (face) ? (hb_coretext_aat_shaper_face_data_t *) HB_SHAPER_DATA_SUCCEEDED : NULL;
     }
+    hb_blob_destroy (blob);
   }
-  hb_blob_destroy (mort_blob);
 
-  return hb_coretext_shaper_face_data_ensure (face) ? (hb_coretext_aat_shaper_face_data_t *) HB_SHAPER_DATA_SUCCEEDED : NULL;
+  return NULL;
 }
 
 void
 _hb_coretext_aat_shaper_face_data_destroy (hb_coretext_aat_shaper_face_data_t *data HB_UNUSED)
 {
 }
 
 
--- a/gfx/harfbuzz/src/hb-coretext.h
+++ b/gfx/harfbuzz/src/hb-coretext.h
@@ -37,16 +37,17 @@
 #  include <ApplicationServices/ApplicationServices.h>
 #endif
 
 HB_BEGIN_DECLS
 
 
 #define HB_CORETEXT_TAG_MORT HB_TAG('m','o','r','t')
 #define HB_CORETEXT_TAG_MORX HB_TAG('m','o','r','x')
+#define HB_CORETEXT_TAG_KERX HB_TAG('k','e','r','x')
 
 
 HB_EXTERN hb_face_t *
 hb_coretext_face_create (CGFontRef cg_font);
 
 
 HB_EXTERN CGFontRef
 hb_coretext_face_get_cg_font (hb_face_t *face);
--- a/gfx/harfbuzz/src/hb-face-private.hh
+++ b/gfx/harfbuzz/src/hb-face-private.hh
@@ -49,23 +49,16 @@ struct hb_face_t {
   hb_reference_table_func_t  reference_table_func;
   void                      *user_data;
   hb_destroy_func_t          destroy;
 
   unsigned int index;			/* Face index in a collection, zero-based. */
   mutable unsigned int upem;		/* Units-per-EM. */
   mutable unsigned int num_glyphs;	/* Number of glyphs. */
 
-  enum dirty_t {
-    DIRTY_NOTHING	= 0x0000,
-    DIRTY_INDEX		= 0x0001,
-    DIRTY_UPEM		= 0x0002,
-    DIRTY_NUM_GLYPHS	= 0x0004,
-  } dirty;
-
   struct hb_shaper_data_t shaper_data;	/* Various shaper data. */
 
   /* Various non-shaping data. */
   /* ... */
 
   /* Cache */
   struct plan_node_t {
     hb_shape_plan_t *shape_plan;
@@ -101,18 +94,16 @@ struct hb_face_t {
     return num_glyphs;
   }
 
   private:
   HB_INTERNAL void load_upem (void) const;
   HB_INTERNAL void load_num_glyphs (void) const;
 };
 
-HB_MARK_AS_FLAG_T (hb_face_t::dirty_t);
-
 extern HB_INTERNAL const hb_face_t _hb_face_nil;
 
 #define HB_SHAPER_DATA_CREATE_FUNC_EXTRA_ARGS
 #define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_PROTOTYPE(shaper, face);
 #include "hb-shaper-list.hh"
 #undef HB_SHAPER_IMPLEMENT
 #undef HB_SHAPER_DATA_CREATE_FUNC_EXTRA_ARGS
 
--- a/gfx/harfbuzz/src/hb-face.cc
+++ b/gfx/harfbuzz/src/hb-face.cc
@@ -46,18 +46,16 @@ const hb_face_t _hb_face_nil = {
   NULL, /* reference_table_func */
   NULL, /* user_data */
   NULL, /* destroy */
 
   0,    /* index */
   1000, /* upem */
   0,    /* num_glyphs */
 
-  hb_face_t::DIRTY_NOTHING, /* dirty */
-
   {
 #define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_INVALID,
 #include "hb-shaper-list.hh"
 #undef HB_SHAPER_IMPLEMENT
   },
 
   NULL, /* shape_plans */
 };
@@ -115,18 +113,20 @@ static hb_face_for_data_closure_t *
 
   closure->blob = blob;
   closure->index = index;
 
   return closure;
 }
 
 static void
-_hb_face_for_data_closure_destroy (hb_face_for_data_closure_t *closure)
+_hb_face_for_data_closure_destroy (void *data)
 {
+  hb_face_for_data_closure_t *closure = (hb_face_for_data_closure_t *) data;
+
   hb_blob_destroy (closure->blob);
   free (closure);
 }
 
 static hb_blob_t *
 _hb_face_for_data_reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void *user_data)
 {
   hb_face_for_data_closure_t *data = (hb_face_for_data_closure_t *) user_data;
@@ -166,17 +166,17 @@ hb_face_create (hb_blob_t    *blob,
 
   hb_face_for_data_closure_t *closure = _hb_face_for_data_closure_create (OT::Sanitizer<OT::OpenTypeFontFile>::sanitize (hb_blob_reference (blob)), index);
 
   if (unlikely (!closure))
     return hb_face_get_empty ();
 
   face = hb_face_create_for_tables (_hb_face_for_data_reference_table,
 				    closure,
-				    (hb_destroy_func_t) _hb_face_for_data_closure_destroy);
+				    _hb_face_for_data_closure_destroy);
 
   face->index = index;
 
   return face;
 }
 
 /**
  * hb_face_get_empty:
@@ -362,21 +362,16 @@ hb_face_reference_blob (hb_face_t *face)
  **/
 void
 hb_face_set_index (hb_face_t    *face,
 		   unsigned int  index)
 {
   if (face->immutable)
     return;
 
-  if (face->index == index)
-    return;
-
-  face->dirty |= face->DIRTY_INDEX;
-
   face->index = index;
 }
 
 /**
  * hb_face_get_index:
  * @face: a face.
  *
  * 
@@ -402,21 +397,16 @@ hb_face_get_index (hb_face_t    *face)
  **/
 void
 hb_face_set_upem (hb_face_t    *face,
 		  unsigned int  upem)
 {
   if (face->immutable)
     return;
 
-  if (face->upem == upem)
-    return;
-
-  face->dirty |= face->DIRTY_UPEM;
-
   face->upem = upem;
 }
 
 /**
  * hb_face_get_upem:
  * @face: a face.
  *
  * 
@@ -451,21 +441,16 @@ hb_face_t::load_upem (void) const
  **/
 void
 hb_face_set_glyph_count (hb_face_t    *face,
 			 unsigned int  glyph_count)
 {
   if (face->immutable)
     return;
 
-  if (face->num_glyphs == glyph_count)
-    return;
-
-  face->dirty |= face->DIRTY_NUM_GLYPHS;
-
   face->num_glyphs = glyph_count;
 }
 
 /**
  * hb_face_get_glyph_count:
  * @face: a face.
  *
  * 
@@ -484,9 +469,38 @@ void
 hb_face_t::load_num_glyphs (void) const
 {
   hb_blob_t *maxp_blob = OT::Sanitizer<OT::maxp>::sanitize (reference_table (HB_OT_TAG_maxp));
   const OT::maxp *maxp_table = OT::Sanitizer<OT::maxp>::lock_instance (maxp_blob);
   num_glyphs = maxp_table->get_num_glyphs ();
   hb_blob_destroy (maxp_blob);
 }
 
+/**
+ * hb_face_get_table_tags:
+ * @face: a face.
+ *
+ * Retrieves table tags for a face, if possible.
+ *
+ * Return value: total number of tables, or 0 if not possible to list.
+ *
+ * Since: 1.6.0
+ **/
+unsigned int
+hb_face_get_table_tags (hb_face_t    *face,
+			unsigned int  start_offset,
+			unsigned int *table_count, /* IN/OUT */
+			hb_tag_t     *table_tags /* OUT */)
+{
+  if (face->destroy != _hb_face_for_data_closure_destroy)
+  {
+    if (table_count)
+      *table_count = 0;
+    return 0;
+  }
 
+  hb_face_for_data_closure_t *data = (hb_face_for_data_closure_t *) face->user_data;
+
+  const OT::OpenTypeFontFile &ot_file = *OT::Sanitizer<OT::OpenTypeFontFile>::lock_instance (data->blob);
+  const OT::OpenTypeFontFace &ot_face = ot_file.get_face (data->index);
+
+  return ot_face.get_table_tags (start_offset, table_count, table_tags);
+}
--- a/gfx/harfbuzz/src/hb-face.h
+++ b/gfx/harfbuzz/src/hb-face.h
@@ -106,12 +106,17 @@ hb_face_get_upem (hb_face_t *face);
 
 HB_EXTERN void
 hb_face_set_glyph_count (hb_face_t    *face,
 			 unsigned int  glyph_count);
 
 HB_EXTERN unsigned int
 hb_face_get_glyph_count (hb_face_t *face);
 
+HB_EXTERN unsigned int
+hb_face_get_table_tags (hb_face_t    *face,
+			unsigned int  start_offset,
+			unsigned int *table_count, /* IN/OUT */
+			hb_tag_t     *table_tags /* OUT */);
 
 HB_END_DECLS
 
 #endif /* HB_FACE_H */
--- a/gfx/harfbuzz/src/hb-font-private.hh
+++ b/gfx/harfbuzz/src/hb-font-private.hh
@@ -103,34 +103,26 @@ struct hb_font_t {
   hb_face_t *face;
 
   int x_scale;
   int y_scale;
 
   unsigned int x_ppem;
   unsigned int y_ppem;
 
+  float ptem;
+
   /* Font variation coordinates. */
   unsigned int num_coords;
   int *coords;
 
   hb_font_funcs_t   *klass;
   void              *user_data;
   hb_destroy_func_t  destroy;
 
-  enum dirty_t {
-    DIRTY_NOTHING	= 0x0000,
-    DIRTY_FACE		= 0x0001,
-    DIRTY_PARENT	= 0x0002,
-    DIRTY_FUNCS		= 0x0004,
-    DIRTY_SCALE		= 0x0008,
-    DIRTY_PPEM		= 0x0010,
-    DIRTY_VARIATIONS	= 0x0020,
-  } dirty;
-
   struct hb_shaper_data_t shaper_data;
 
 
   /* Convert from font-space to user-space */
   inline int dir_scale (hb_direction_t direction)
   { return HB_DIRECTION_IS_VERTICAL(direction) ? y_scale : x_scale; }
   inline hb_position_t em_scale_x (int16_t v) { return em_scale (v, x_scale); }
   inline hb_position_t em_scale_y (int16_t v) { return em_scale (v, y_scale); }
@@ -548,18 +540,16 @@ struct hb_font_t {
     return (hb_position_t) (scaled / upem);
   }
   inline hb_position_t em_scalef (float v, int scale)
   {
     return (hb_position_t) (v * scale / face->get_upem ());
   }
 };
 
-HB_MARK_AS_FLAG_T (hb_font_t::dirty_t);
-
 #define HB_SHAPER_DATA_CREATE_FUNC_EXTRA_ARGS
 #define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_PROTOTYPE(shaper, font);
 #include "hb-shaper-list.hh"
 #undef HB_SHAPER_IMPLEMENT
 #undef HB_SHAPER_DATA_CREATE_FUNC_EXTRA_ARGS
 
 
 #endif /* HB_FONT_PRIVATE_HH */
--- a/gfx/harfbuzz/src/hb-font.cc
+++ b/gfx/harfbuzz/src/hb-font.cc
@@ -1152,18 +1152,30 @@ hb_font_create_sub_font (hb_font_t *pare
     return font;
 
   font->parent = hb_font_reference (parent);
 
   font->x_scale = parent->x_scale;
   font->y_scale = parent->y_scale;
   font->x_ppem = parent->x_ppem;
   font->y_ppem = parent->y_ppem;
+  font->ptem = parent->ptem;
 
-  /* TODO: copy variation coordinates. */
+  font->num_coords = parent->num_coords;
+  if (!font->num_coords)
+    font->coords = NULL;
+  else
+  {
+    unsigned int size = parent->num_coords * sizeof (parent->coords[0]);
+    font->coords = (int *) malloc (size);
+    if (unlikely (!font->coords))
+      font->num_coords = 0;
+    else
+      memcpy (font->coords, parent->coords, size);
+  }
 
   return font;
 }
 
 /**
  * hb_font_get_empty:
  *
  * 
@@ -1183,26 +1195,25 @@ hb_font_get_empty (void)
     NULL, /* parent */
     const_cast<hb_face_t *> (&_hb_face_nil),
 
     1000, /* x_scale */
     1000, /* y_scale */
 
     0, /* x_ppem */
     0, /* y_ppem */
+    0, /* ptem */
 
     0, /* num_coords */
     NULL, /* coords */
 
     const_cast<hb_font_funcs_t *> (&_hb_font_funcs_nil), /* klass */
     NULL, /* user_data */
     NULL, /* destroy */
 
-    hb_font_t::DIRTY_NOTHING, /* dirty */
-
     {
 #define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_INVALID,
 #include "hb-shaper-list.hh"
 #undef HB_SHAPER_IMPLEMENT
     }
   };
 
   return const_cast<hb_font_t *> (&_hb_font_nil);
@@ -1345,21 +1356,16 @@ hb_font_set_parent (hb_font_t *font,
 		    hb_font_t *parent)
 {
   if (font->immutable)
     return;
 
   if (!parent)
     parent = hb_font_get_empty ();
 
-  if (parent == font->parent)
-    return;
-
-  font->dirty |= font->DIRTY_PARENT;
-
   hb_font_t *old = font->parent;
 
   font->parent = hb_font_reference (parent);
 
   hb_font_destroy (old);
 }
 
 /**
@@ -1392,21 +1398,16 @@ hb_font_set_face (hb_font_t *font,
 		  hb_face_t *face)
 {
   if (font->immutable)
     return;
 
   if (unlikely (!face))
     face = hb_face_get_empty ();
 
-  if (font->face == face)
-    return;
-
-  font->dirty |= font->DIRTY_FACE;
-
   hb_face_t *old = font->face;
 
   font->face = hb_face_reference (face);
 
   hb_face_destroy (old);
 }
 
 /**
@@ -1450,18 +1451,16 @@ hb_font_set_funcs (hb_font_t         *fo
   }
 
   if (font->destroy)
     font->destroy (font->user_data);
 
   if (!klass)
     klass = hb_font_funcs_get_empty ();
 
-  font->dirty |= font->DIRTY_FUNCS;
-
   hb_font_funcs_reference (klass);
   hb_font_funcs_destroy (font->klass);
   font->klass = klass;
   font->user_data = font_data;
   font->destroy = destroy;
 }
 
 /**
@@ -1507,21 +1506,16 @@ hb_font_set_funcs_data (hb_font_t       
 void
 hb_font_set_scale (hb_font_t *font,
 		   int x_scale,
 		   int y_scale)
 {
   if (font->immutable)
     return;
 
-  if (font->x_scale == x_scale && font->y_scale == y_scale)
-    return;
-
-  font->dirty |= font->DIRTY_SCALE;
-
   font->x_scale = x_scale;
   font->y_scale = y_scale;
 }
 
 /**
  * hb_font_get_scale:
  * @font: a font.
  * @x_scale: (out): 
@@ -1553,21 +1547,16 @@ hb_font_get_scale (hb_font_t *font,
 void
 hb_font_set_ppem (hb_font_t *font,
 		  unsigned int x_ppem,
 		  unsigned int y_ppem)
 {
   if (font->immutable)
     return;
 
-  if (font->x_ppem == x_ppem && font->y_ppem == y_ppem)
-    return;
-
-  font->dirty |= font->DIRTY_PPEM;
-
   font->x_ppem = x_ppem;
   font->y_ppem = y_ppem;
 }
 
 /**
  * hb_font_get_ppem:
  * @font: a font.
  * @x_ppem: (out): 
@@ -1581,35 +1570,59 @@ void
 hb_font_get_ppem (hb_font_t *font,
 		  unsigned int *x_ppem,
 		  unsigned int *y_ppem)
 {
   if (x_ppem) *x_ppem = font->x_ppem;
   if (y_ppem) *y_ppem = font->y_ppem;
 }
 
+/**
+ * hb_font_set_ptem:
+ * @font: a font.
+ * @ptem: 
+ *
+ * Sets "point size" of the font.
+ *
+ * Since: 1.6.0
+ **/
+void
+hb_font_set_ptem (hb_font_t *font, float ptem)
+{
+  if (font->immutable)
+    return;
+
+  font->ptem = ptem;
+}
+
+/**
+ * hb_font_get_ptem:
+ * @font: a font.
+ *
+ * Gets the "point size" of the font.  A value of 0 means unset.
+ *
+ * Return value: Point size.
+ *
+ * Since: 0.9.2
+ **/
+float
+hb_font_get_ptem (hb_font_t *font)
+{
+  return font->ptem;
+}
+
 /*
  * Variations
  */
 
 static void
 _hb_font_adopt_var_coords_normalized (hb_font_t *font,
 				      int *coords, /* 2.14 normalized */
 				      unsigned int coords_length)
 {
-  if (font->num_coords == coords_length &&
-      (coords_length == 0 ||
-       0 == memcmp (font->coords, coords, coords_length * sizeof (coords[0]))))
-  {
-    free (coords);
-    return;
-  }
-
-  font->dirty |= font->DIRTY_VARIATIONS;
-
   free (font->coords);
 
   font->coords = coords;
   font->num_coords = coords_length;
 }
 
 /**
  * hb_font_set_variations:
--- a/gfx/harfbuzz/src/hb-font.h
+++ b/gfx/harfbuzz/src/hb-font.h
@@ -602,16 +602,26 @@ hb_font_set_ppem (hb_font_t *font,
 		  unsigned int x_ppem,
 		  unsigned int y_ppem);
 
 HB_EXTERN void
 hb_font_get_ppem (hb_font_t *font,
 		  unsigned int *x_ppem,
 		  unsigned int *y_ppem);
 
+/*
+ * Point size per EM.  Used for optical-sizing in CoreText.
+ * A value of zero means "not set".
+ */
+HB_EXTERN void
+hb_font_set_ptem (hb_font_t *font, float ptem);
+
+HB_EXTERN float
+hb_font_get_ptem (hb_font_t *font);
+
 HB_EXTERN void
 hb_font_set_variations (hb_font_t *font,
 			const hb_variation_t *variations,
 			unsigned int variations_length);
 
 HB_EXTERN void
 hb_font_set_var_coords_design (hb_font_t *font,
 			       const float *coords,
--- a/gfx/harfbuzz/src/hb-ft.cc
+++ b/gfx/harfbuzz/src/hb-ft.cc
@@ -90,24 +90,26 @@ static hb_ft_font_t *
   ft_font->unref = unref;
 
   ft_font->load_flags = FT_LOAD_DEFAULT | FT_LOAD_NO_HINTING;
 
   return ft_font;
 }
 
 static void
-_hb_ft_face_destroy (FT_Face ft_face)
+_hb_ft_face_destroy (void *data)
 {
-  FT_Done_Face (ft_face);
+  FT_Done_Face ((FT_Face) data);
 }
 
 static void
-_hb_ft_font_destroy (hb_ft_font_t *ft_font)
+_hb_ft_font_destroy (void *data)
 {
+  hb_ft_font_t *ft_font = (hb_ft_font_t *) data;
+
   if (ft_font->unref)
     _hb_ft_face_destroy (ft_font->ft_face);
 
   free (ft_font);
 }
 
 /**
  * hb_ft_font_set_load_flags:
@@ -119,17 +121,17 @@ static void
  * Since: 1.0.5
  **/
 void
 hb_ft_font_set_load_flags (hb_font_t *font, int load_flags)
 {
   if (font->immutable)
     return;
 
-  if (font->destroy != (hb_destroy_func_t) _hb_ft_font_destroy)
+  if (font->destroy != _hb_ft_font_destroy)
     return;
 
   hb_ft_font_t *ft_font = (hb_ft_font_t *) font->user_data;
 
   ft_font->load_flags = load_flags;
 }
 
 /**
@@ -139,28 +141,28 @@ hb_ft_font_set_load_flags (hb_font_t *fo
  * 
  *
  * Return value:
  * Since: 1.0.5
  **/
 int
 hb_ft_font_get_load_flags (hb_font_t *font)
 {
-  if (font->destroy != (hb_destroy_func_t) _hb_ft_font_destroy)
+  if (font->destroy != _hb_ft_font_destroy)
     return 0;
 
   const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font->user_data;
 
   return ft_font->load_flags;
 }
 
 FT_Face
 hb_ft_font_get_face (hb_font_t *font)
 {
-  if (font->destroy != (hb_destroy_func_t) _hb_ft_font_destroy)
+  if (font->destroy != _hb_ft_font_destroy)
     return NULL;
 
   const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font->user_data;
 
   return ft_font->ft_face;
 }
 
 
@@ -469,17 +471,17 @@ retry:
 #endif
   };
 
   bool symbol = ft_face->charmap && ft_face->charmap->encoding == FT_ENCODING_MS_SYMBOL;
 
   hb_font_set_funcs (font,
 		     funcs,
 		     _hb_ft_font_create (ft_face, symbol, unref),
-		     (hb_destroy_func_t) _hb_ft_font_destroy);
+		     _hb_ft_font_destroy);
 }
 
 
 static hb_blob_t *
 reference_table  (hb_face_t *face HB_UNUSED, hb_tag_t tag, void *user_data)
 {
   FT_Face ft_face = (FT_Face) user_data;
   FT_Byte *buffer;
@@ -548,17 +550,17 @@ hb_ft_face_create (FT_Face           ft_
  *
  * Return value: (transfer full): 
  * Since: 0.9.38
  **/
 hb_face_t *
 hb_ft_face_create_referenced (FT_Face ft_face)
 {
   FT_Reference_Face (ft_face);
-  return hb_ft_face_create (ft_face, (hb_destroy_func_t) _hb_ft_face_destroy);
+  return hb_ft_face_create (ft_face, _hb_ft_face_destroy);
 }
 
 static void
 hb_ft_face_finalize (FT_Face ft_face)
 {
   hb_face_destroy ((hb_face_t *) ft_face->generic.data);
 }
 
@@ -603,16 +605,29 @@ hb_ft_font_create (FT_Face           ft_
 {
   hb_font_t *font;
   hb_face_t *face;
 
   face = hb_ft_face_create (ft_face, destroy);
   font = hb_font_create (face);
   hb_face_destroy (face);
   _hb_ft_font_set_funcs (font, ft_face, false);
+  hb_ft_font_changed (font);
+  return font;
+}
+
+void
+hb_ft_font_changed (hb_font_t *font)
+{
+  if (font->destroy != _hb_ft_font_destroy)
+    return;
+
+  hb_ft_font_t *ft_font = (hb_ft_font_t *) font->user_data;
+  FT_Face ft_face = ft_font->ft_face;
+
   hb_font_set_scale (font,
 		     (int) (((uint64_t) ft_face->size->metrics.x_scale * (uint64_t) ft_face->units_per_EM + (1u<<15)) >> 16),
 		     (int) (((uint64_t) ft_face->size->metrics.y_scale * (uint64_t) ft_face->units_per_EM + (1u<<15)) >> 16));
 #if 0 /* hb-ft works in no-hinting model */
   hb_font_set_ppem (font,
 		    ft_face->size->metrics.x_ppem,
 		    ft_face->size->metrics.y_ppem);
 #endif
@@ -633,34 +648,32 @@ hb_ft_font_create (FT_Face           ft_
 	hb_font_set_var_coords_normalized (font, coords, mm_var->num_axis);
       }
     }
     free (coords);
     free (ft_coords);
     free (mm_var);
   }
 #endif
-
-  return font;
 }
 
 /**
  * hb_ft_font_create_referenced:
  * @ft_face:
  *
  * 
  *
  * Return value: (transfer full): 
  * Since: 0.9.38
  **/
 hb_font_t *
 hb_ft_font_create_referenced (FT_Face ft_face)
 {
   FT_Reference_Face (ft_face);
-  return hb_ft_font_create (ft_face, (hb_destroy_func_t) _hb_ft_face_destroy);
+  return hb_ft_font_create (ft_face, _hb_ft_face_destroy);
 }
 
 
 /* Thread-safe, lock-free, FT_Library */
 
 static FT_Library ft_library;
 
 #ifdef HB_USE_ATEXIT
--- a/gfx/harfbuzz/src/hb-ft.h
+++ b/gfx/harfbuzz/src/hb-ft.h
@@ -111,16 +111,22 @@ HB_EXTERN FT_Face
 hb_ft_font_get_face (hb_font_t *font);
 
 HB_EXTERN void
 hb_ft_font_set_load_flags (hb_font_t *font, int load_flags);
 
 HB_EXTERN int
 hb_ft_font_get_load_flags (hb_font_t *font);
 
-/* Makes an hb_font_t use FreeType internally to implement font functions. */
+/* Call when size or variations settings on underlying FT_Face change. */
+HB_EXTERN void
+hb_ft_font_changed (hb_font_t *font);
+
+/* Makes an hb_font_t use FreeType internally to implement font functions.
+ * Note: this internally creates an FT_Face.  Use it when you create your
+ * hb_face_t using hb_face_create(). */
 HB_EXTERN void
 hb_ft_font_set_funcs (hb_font_t *font);
 
 
 HB_END_DECLS
 
 #endif /* HB_FT_H */
--- a/gfx/harfbuzz/src/hb-glib.cc
+++ b/gfx/harfbuzz/src/hb-glib.cc
@@ -378,25 +378,32 @@ hb_glib_get_unicode_funcs (void)
 #undef HB_UNICODE_FUNC_IMPLEMENT
     }
   };
 
   return const_cast<hb_unicode_funcs_t *> (&_hb_glib_unicode_funcs);
 }
 
 #if GLIB_CHECK_VERSION(2,31,10)
+
+static void
+_hb_g_bytes_unref (void *data)
+{
+  g_bytes_unref ((GBytes *) data);
+}
+
 /**
  * hb_glib_blob_create:
  *
  * Since: 0.9.38
  **/
 hb_blob_t *
 hb_glib_blob_create (GBytes *gbytes)
 {
   gsize size = 0;
   gconstpointer data = g_bytes_get_data (gbytes, &size);
   return hb_blob_create ((const char *) data,
 			 size,
 			 HB_MEMORY_MODE_READONLY,
 			 g_bytes_ref (gbytes),
-			 (hb_destroy_func_t) g_bytes_unref);
+			 _hb_g_bytes_unref);
 }
 #endif
--- a/gfx/harfbuzz/src/hb-graphite2.cc
+++ b/gfx/harfbuzz/src/hb-graphite2.cc
@@ -384,17 +384,17 @@ hb_bool_t
         pPos->x_advance = 0.;
 
       pPos->y_advance = gr_slot_advance_Y (is, grface, NULL) * yscale;
       curradvy += pPos->y_advance;
     }
   }
   else
   {
-    curradvx = gr_seg_advance_X(seg);
+    curradvx = gr_seg_advance_X(seg) * xscale;
     for (is = gr_seg_first_slot (seg); is; pPos++, info++, is = gr_slot_next_in_segment (is))
     {
       if (info->cluster != currclus)
       {
         pPos->x_advance = info->var1.i32 * xscale;
         curradvx -= pPos->x_advance;
         currclus = info->cluster;
       } else
--- a/gfx/harfbuzz/src/hb-open-file-private.hh
+++ b/gfx/harfbuzz/src/hb-open-file-private.hh
@@ -74,16 +74,34 @@ typedef struct OffsetTable
 
   inline unsigned int get_table_count (void) const
   { return numTables; }
   inline const TableRecord& get_table (unsigned int i) const
   {
     if (unlikely (i >= numTables)) return Null(TableRecord);
     return tables[i];
   }
+  inline unsigned int get_table_tags (unsigned int start_offset,
+				      unsigned int *table_count, /* IN/OUT */
+				      hb_tag_t     *table_tags /* OUT */) const
+  {
+    if (table_count)
+    {
+      if (start_offset >= numTables)
+        *table_count = 0;
+      else
+        *table_count = MIN (*table_count, numTables - start_offset);
+
+      const TableRecord *sub_tables = tables + start_offset;
+      unsigned int count = *table_count;
+      for (unsigned int i = 0; i < count; i++)
+	table_tags[i] = sub_tables[i].tag;
+    }
+    return numTables;
+  }
   inline bool find_table_index (hb_tag_t tag, unsigned int *table_index) const
   {
     Tag t;
     t.set (tag);
     unsigned int count = numTables;
     for (unsigned int i = 0; i < count; i++)
     {
       if (t == tables[i].tag)
--- a/gfx/harfbuzz/src/hb-ot-font.cc
+++ b/gfx/harfbuzz/src/hb-ot-font.cc
@@ -453,18 +453,20 @@ static hb_ot_font_t *
 			   ot_font->h_metrics.ascender - ot_font->h_metrics.descender); /* TODO Can we do this lazily? */
   ot_font->glyf.init (face);
   ot_font->cbdt.init (face);
 
   return ot_font;
 }
 
 static void
-_hb_ot_font_destroy (hb_ot_font_t *ot_font)
+_hb_ot_font_destroy (void *data)
 {
+  hb_ot_font_t *ot_font = (hb_ot_font_t *) data;
+
   ot_font->cmap.fini ();
   ot_font->h_metrics.fini ();
   ot_font->v_metrics.fini ();
   ot_font->glyf.fini ();
   ot_font->cbdt.fini ();
 
   free (ot_font);
 }
@@ -622,10 +624,10 @@ hb_ot_font_set_funcs (hb_font_t *font)
 {
   hb_ot_font_t *ot_font = _hb_ot_font_create (font->face);
   if (unlikely (!ot_font))
     return;
 
   hb_font_set_funcs (font,
 		     _hb_ot_get_font_funcs (),
 		     ot_font,
-		     (hb_destroy_func_t) _hb_ot_font_destroy);
+		     _hb_ot_font_destroy);
 }
--- a/gfx/harfbuzz/src/hb-ot-layout-gpos-table.hh
+++ b/gfx/harfbuzz/src/hb-ot-layout-gpos-table.hh
@@ -1082,17 +1082,19 @@ struct MarkBasePosFormat1
 
     /* Now we search backwards for a non-mark glyph */
     hb_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
     skippy_iter.reset (buffer->idx, 1);
     skippy_iter.set_lookup_props (LookupFlag::IgnoreMarks);
     do {
       if (!skippy_iter.prev ()) return_trace (false);
       /* We only want to attach to the first of a MultipleSubst sequence.  Reject others. */
-      if (0 == _hb_glyph_info_get_lig_comp (&buffer->info[skippy_iter.idx])) break;
+      if (!_hb_glyph_info_multiplied (&buffer->info[skippy_iter.idx]) ||
+	  0 == _hb_glyph_info_get_lig_comp (&buffer->info[skippy_iter.idx]))
+	break;
       skippy_iter.reject ();
     } while (1);
 
     /* Checking that matched glyph is actually a base glyph by GDEF is too strong; disabled */
     //if (!_hb_glyph_info_is_base_glyph (&buffer->info[skippy_iter.idx])) { return_trace (false); }
 
     unsigned int base_index = (this+baseCoverage).get_coverage  (buffer->info[skippy_iter.idx].codepoint);
     if (base_index == NOT_COVERED) return_trace (false);
--- a/gfx/harfbuzz/src/hb-ot-layout-gsubgpos-private.hh
+++ b/gfx/harfbuzz/src/hb-ot-layout-gsubgpos-private.hh
@@ -369,16 +369,23 @@ struct hb_apply_context_t :
       idx = start_index_;
       num_items = num_items_;
       end = c->buffer->len;
       matcher.set_syllable (start_index_ == c->buffer->idx ? c->buffer->cur().syllable () : 0);
     }
 
     inline void reject (void) { num_items++; match_glyph_data--; }
 
+    inline matcher_t::may_skip_t
+    may_skip (const hb_apply_context_t *c,
+	      const hb_glyph_info_t    &info) const
+    {
+      return matcher.may_skip (c, info);
+    }
+
     inline bool next (void)
     {
       assert (num_items > 0);
       while (idx + num_items < end)
       {
 	idx++;
 	const hb_glyph_info_t &info = c->buffer->info[idx];
 
@@ -731,48 +738,90 @@ static inline bool match_input (hb_apply
    * - If all components of the ligature were marks, we call this a mark ligature.
    *
    * - If there is no GDEF, and the ligature is NOT a mark ligature, we categorize
    *   it as a ligature glyph.
    *
    * - Ligatures cannot be formed across glyphs attached to different components
    *   of previous ligatures.  Eg. the sequence is LAM,SHADDA,LAM,FATHA,HEH, and
    *   LAM,LAM,HEH form a ligature, leaving SHADDA,FATHA next to eachother.
-   *   However, it would be wrong to ligate that SHADDA,FATHA sequence.o
-   *   There is an exception to this: If a ligature tries ligating with marks that
-   *   belong to it itself, go ahead, assuming that the font designer knows what
-   *   they are doing (otherwise it can break Indic stuff when a matra wants to
-   *   ligate with a conjunct...)
+   *   However, it would be wrong to ligate that SHADDA,FATHA sequence.
+   *   There are a couple of exceptions to this:
+   *
+   *   o If a ligature tries ligating with marks that belong to it itself, go ahead,
+   *     assuming that the font designer knows what they are doing (otherwise it can
+   *     break Indic stuff when a matra wants to ligate with a conjunct,
+   *
+   *   o If two marks want to ligate and they belong to different components of the
+   *     same ligature glyph, and said ligature glyph is to be ignored according to
+   *     mark-filtering rules, then allow.
+   *     https://github.com/behdad/harfbuzz/issues/545
    */
 
   bool is_mark_ligature = _hb_glyph_info_is_mark (&buffer->cur());
 
   unsigned int total_component_count = 0;
   total_component_count += _hb_glyph_info_get_lig_num_comps (&buffer->cur());
 
   unsigned int first_lig_id = _hb_glyph_info_get_lig_id (&buffer->cur());
   unsigned int first_lig_comp = _hb_glyph_info_get_lig_comp (&buffer->cur());
 
+  enum {
+    LIGBASE_NOT_CHECKED,
+    LIGBASE_MAY_NOT_SKIP,
+    LIGBASE_MAY_SKIP
+  } ligbase = LIGBASE_NOT_CHECKED;
+
   match_positions[0] = buffer->idx;
   for (unsigned int i = 1; i < count; i++)
   {
     if (!skippy_iter.next ()) return_trace (false);
 
     match_positions[i] = skippy_iter.idx;
 
     unsigned int this_lig_id = _hb_glyph_info_get_lig_id (&buffer->info[skippy_iter.idx]);
     unsigned int this_lig_comp = _hb_glyph_info_get_lig_comp (&buffer->info[skippy_iter.idx]);
 
-    if (first_lig_id && first_lig_comp) {
+    if (first_lig_id && first_lig_comp)
+    {
       /* If first component was attached to a previous ligature component,
        * all subsequent components should be attached to the same ligature
-       * component, otherwise we shouldn't ligate them. */
+       * component, otherwise we shouldn't ligate them... */
       if (first_lig_id != this_lig_id || first_lig_comp != this_lig_comp)
-	return_trace (false);
-    } else {
+      {
+        /* ...unless, we are attached to a base ligature and that base
+	 * ligature is ignorable. */
+        if (ligbase == LIGBASE_NOT_CHECKED)
+	{
+	  bool found = false;
+	  const hb_glyph_info_t *out = buffer->out_info;
+	  unsigned int j = buffer->out_len;
+	  while (j && _hb_glyph_info_get_lig_id (&out[j - 1]) == first_lig_id)
+	  {
+	    if (_hb_glyph_info_get_lig_comp (&out[j - 1]) == 0)
+	    {
+	      j--;
+	      found = true;
+	      break;
+	    }
+	    j--;
+	  }
+
+	  if (found && skippy_iter.may_skip (c, out[j]) == hb_apply_context_t::matcher_t::SKIP_YES)
+	    ligbase = LIGBASE_MAY_SKIP;
+	  else
+	    ligbase = LIGBASE_MAY_NOT_SKIP;
+	}
+
+        if (ligbase == LIGBASE_MAY_NOT_SKIP)
+	  return_trace (false);
+      }
+    }
+    else
+    {
       /* If first component was NOT attached to a previous ligature component,
        * all subsequent components should also NOT be attached to any ligature
        * component, unless they are attached to the first component itself! */
       if (this_lig_id && this_lig_comp && (this_lig_id != first_lig_id))
 	return_trace (false);
     }
 
     is_mark_ligature = is_mark_ligature && _hb_glyph_info_is_mark (&buffer->info[skippy_iter.idx]);
--- a/gfx/harfbuzz/src/hb-ot-layout-private.hh
+++ b/gfx/harfbuzz/src/hb-ot-layout-private.hh
@@ -342,16 +342,18 @@ static inline void
   info->unicode_props() = (modified_class<<8) | (info->unicode_props() & 0xFF);
 }
 static inline unsigned int
 _hb_glyph_info_get_modified_combining_class (const hb_glyph_info_t *info)
 {
   return _hb_glyph_info_is_unicode_mark (info) ? info->unicode_props()>>8 : 0;
 }
 
+#define info_cc(info) (_hb_glyph_info_get_modified_combining_class (&(info)))
+
 static inline bool
 _hb_glyph_info_is_unicode_space (const hb_glyph_info_t *info)
 {
   return _hb_glyph_info_get_general_category (info) ==
 	 HB_UNICODE_GENERAL_CATEGORY_SPACE_SEPARATOR;
 }
 static inline void
 _hb_glyph_info_set_unicode_space_fallback_type (hb_glyph_info_t *info, hb_unicode_funcs_t::space_t s)
--- a/gfx/harfbuzz/src/hb-ot-shape-complex-arabic-table.hh
+++ b/gfx/harfbuzz/src/hb-ot-shape-complex-arabic-table.hh
@@ -1,20 +1,20 @@
 /* == Start of generated table == */
 /*
  * The following table is generated by running:
  *
  *   ./gen-arabic-table.py ArabicShaping.txt UnicodeData.txt Blocks.txt
  *
  * on files with these headers:
  *
- * # ArabicShaping-9.0.0.txt
- * # Date: 2016-02-24, 22:25:00 GMT [RP]
- * # Blocks-9.0.0.txt
- * # Date: 2016-02-05, 23:48:00 GMT [KW]
+ * # ArabicShaping-10.0.0.txt
+ * # Date: 2017-02-16, 00:00:00 GMT [RP, KW]
+ * # Blocks-10.0.0.txt
+ * # Date: 2017-04-12, 17:30:00 GMT [KW]
  * UnicodeData.txt does not have a header.
  */
 
 #ifndef HB_OT_SHAPE_COMPLEX_ARABIC_TABLE_HH
 #define HB_OT_SHAPE_COMPLEX_ARABIC_TABLE_HH
 
 
 #define X	JOINING_TYPE_X
@@ -67,17 +67,20 @@ static const uint8_t joining_table[] =
   /* FILLER */
 
   /* 0800 */ X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,
   /* 0820 */ X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,
 
   /* Mandaic */
 
   /* 0840 */ R,D,D,D,D,D,R,R,D,R,D,D,D,D,D,D,D,D,D,D,R,D,U,U,U,X,X,X,X,X,X,X,
-  /* 0860 */ X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,
+
+  /* Syriac Supplement */
+
+  /* 0860 */ D,U,D,D,D,D,U,R,D,R,R,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,
   /* 0880 */ X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,
 
   /* Arabic Extended-A */
 
   /* 08A0 */ D,D,D,D,D,D,D,D,D,D,R,R,R,U,R,D,D,R,R,D,D,X,D,D,D,R,D,D,D,D,X,X,
   /* 08C0 */ X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,
   /* 08E0 */ X,X,U,
 
@@ -125,17 +128,17 @@ static const uint8_t joining_table[] =
 #define joining_offset_0x1e900u 1146
 
   /* Adlam */
 
   /* 1E900 */ D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,
   /* 1E920 */ D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,
   /* 1E940 */ D,D,D,D,
 
-}; /* Table items: 1214; occupancy: 54% */
+}; /* Table items: 1214; occupancy: 55% */
 
 
 static unsigned int
 joining_type (hb_codepoint_t u)
 {
   switch (u >> 12)
   {
     case 0x0u:
--- a/gfx/harfbuzz/src/hb-ot-shape-complex-arabic.cc
+++ b/gfx/harfbuzz/src/hb-ot-shape-complex-arabic.cc
@@ -608,25 +608,100 @@ postprocess_glyphs_arabic (const hb_ot_s
 			   hb_buffer_t              *buffer,
 			   hb_font_t                *font)
 {
   apply_stch (plan, buffer, font);
 
   HB_BUFFER_DEALLOCATE_VAR (buffer, arabic_shaping_action);
 }
 
+/* http://www.unicode.org/reports/tr53/tr53-1.pdf */
+
+static hb_codepoint_t
+modifier_combining_marks[] =
+{
+  0x0654u, /* ARABIC HAMZA ABOVE */
+  0x0655u, /* ARABIC HAMZA BELOW */
+  0x0658u, /* ARABIC MARK NOON GHUNNA */
+  0x06DCu, /* ARABIC SMALL HIGH SEEN */
+  0x06E3u, /* ARABIC SMALL LOW SEEN */
+  0x06E7u, /* ARABIC SMALL HIGH YEH */
+  0x06E8u, /* ARABIC SMALL HIGH NOON */
+  0x08F3u, /* ARABIC SMALL HIGH WAW */
+};
+
+static inline bool
+info_is_mcm (const hb_glyph_info_t &info)
+{
+  hb_codepoint_t u = info.codepoint;
+  for (unsigned int i = 0; i < ARRAY_LENGTH (modifier_combining_marks); i++)
+    if (u == modifier_combining_marks[i])
+      return true;
+  return false;
+}
+
+static void
+reorder_marks_arabic (const hb_ot_shape_plan_t *plan,
+		      hb_buffer_t              *buffer,
+		      unsigned int              start,
+		      unsigned int              end)
+{
+  hb_glyph_info_t *info = buffer->info;
+
+  unsigned int i = start;
+  for (unsigned int cc = 220; cc <= 230; cc += 10)
+  {
+    DEBUG_MSG (ARABIC, buffer, "Looking for %d's starting at %d\n", cc, i);
+    while (i < end && info_cc(info[i]) < cc)
+      i++;
+    DEBUG_MSG (ARABIC, buffer, "Looking for %d's stopped at %d\n", cc, i);
+
+    if (i == end)
+      break;
+
+    if (info_cc(info[i]) > cc)
+      continue;
+
+    /* Technically we should also check "info_cc(info[j]) == cc"
+     * in the following loop.  But not doing it is safe; we might
+     * end up moving all the 220 MCMs and 230 MCMs together in one
+     * move and be done. */
+    unsigned int j = i;
+    while (j < end && info_is_mcm (info[j]))
+      j++;
+    DEBUG_MSG (ARABIC, buffer, "Found %d's from %d to %d\n", cc, i, j);
+
+    if (i == j)
+      continue;
+
+    /* Shift it! */
+    DEBUG_MSG (ARABIC, buffer, "Shifting %d's: %d %d\n", cc, i, j);
+    hb_glyph_info_t temp[HB_OT_SHAPE_COMPLEX_MAX_COMBINING_MARKS];
+    assert (j - i <= ARRAY_LENGTH (temp));
+    buffer->merge_clusters (start, j);
+    memmove (temp, &info[i], (j - i) * sizeof (hb_glyph_info_t));
+    memmove (&info[start + j - i], &info[start], (i - start) * sizeof (hb_glyph_info_t));
+    memmove (&info[start], temp, (j - i) * sizeof (hb_glyph_info_t));
+
+    start += j - i;
+
+    i = j;
+  }
+}
+
 const hb_ot_complex_shaper_t _hb_ot_complex_shaper_arabic =
 {
   "arabic",
   collect_features_arabic,
   NULL, /* override_features */
   data_create_arabic,
   data_destroy_arabic,
   NULL, /* preprocess_text */
   postprocess_glyphs_arabic,
   HB_OT_SHAPE_NORMALIZATION_MODE_DEFAULT,
   NULL, /* decompose */
   NULL, /* compose */
   setup_masks_arabic,
   NULL, /* disable_otl */
+  reorder_marks_arabic,
   HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE,
   true, /* fallback_position */
 };
--- a/gfx/harfbuzz/src/hb-ot-shape-complex-default.cc
+++ b/gfx/harfbuzz/src/hb-ot-shape-complex-default.cc
@@ -36,11 +36,12 @@ const hb_ot_complex_shaper_t _hb_ot_comp
   NULL, /* data_destroy */
   NULL, /* preprocess_text */
   NULL, /* postprocess_glyphs */
   HB_OT_SHAPE_NORMALIZATION_MODE_DEFAULT,
   NULL, /* decompose */
   NULL, /* compose */
   NULL, /* setup_masks */
   NULL, /* disable_otl */
+  NULL, /* reorder_marks */
   HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE,
   true, /* fallback_position */
 };
--- a/gfx/harfbuzz/src/hb-ot-shape-complex-hangul.cc
+++ b/gfx/harfbuzz/src/hb-ot-shape-complex-hangul.cc
@@ -421,11 +421,12 @@ const hb_ot_complex_shaper_t _hb_ot_comp
   data_destroy_hangul,
   preprocess_text_hangul,
   NULL, /* postprocess_glyphs */
   HB_OT_SHAPE_NORMALIZATION_MODE_NONE,
   NULL, /* decompose */
   NULL, /* compose */
   setup_masks_hangul,
   NULL, /* disable_otl */
+  NULL, /* reorder_marks */
   HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE,
   false, /* fallback_position */
 };
--- a/gfx/harfbuzz/src/hb-ot-shape-complex-hebrew.cc
+++ b/gfx/harfbuzz/src/hb-ot-shape-complex-hebrew.cc
@@ -176,11 +176,12 @@ const hb_ot_complex_shaper_t _hb_ot_comp
   NULL, /* data_destroy */
   NULL, /* preprocess_text */
   NULL, /* postprocess_glyphs */
   HB_OT_SHAPE_NORMALIZATION_MODE_DEFAULT,
   NULL, /* decompose */
   compose_hebrew,
   NULL, /* setup_masks */
   disable_otl_hebrew,
+  NULL, /* reorder_marks */
   HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE,
   true, /* fallback_position */
 };
--- a/gfx/harfbuzz/src/hb-ot-shape-complex-indic-machine.hh
+++ b/gfx/harfbuzz/src/hb-ot-shape-complex-indic-machine.hh
@@ -51,17 +51,17 @@ static const unsigned char _indic_syllab
 	8u, 13u, 5u, 8u, 5u, 7u, 7u, 7u, 5u, 8u, 5u, 7u, 7u, 7u, 5u, 8u, 
 	5u, 7u, 7u, 7u, 5u, 8u, 5u, 7u, 7u, 7u, 4u, 8u, 6u, 6u, 16u, 16u, 
 	4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, 6u, 6u, 
 	16u, 16u, 4u, 14u, 4u, 14u, 4u, 14u, 4u, 14u, 4u, 14u, 4u, 14u, 4u, 14u, 
 	4u, 14u, 4u, 14u, 4u, 14u, 4u, 14u, 5u, 8u, 4u, 14u, 4u, 14u, 5u, 8u, 
 	5u, 7u, 5u, 8u, 5u, 7u, 7u, 7u, 5u, 8u, 5u, 7u, 7u, 7u, 5u, 8u, 
 	5u, 7u, 7u, 7u, 8u, 8u, 1u, 16u, 8u, 13u, 4u, 8u, 6u, 6u, 16u, 16u, 
 	4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, 6u, 6u, 
-	16u, 16u, 8u, 8u, 1u, 18u, 3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u, 3u, 17u, 
+	16u, 16u, 8u, 8u, 1u, 19u, 3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u, 3u, 17u, 
 	3u, 17u, 4u, 17u, 1u, 16u, 3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u, 3u, 17u, 
 	3u, 17u, 4u, 17u, 1u, 16u, 3u, 17u, 3u, 17u, 4u, 17u, 5u, 14u, 5u, 14u, 
 	5u, 10u, 9u, 10u, 9u, 9u, 9u, 10u, 9u, 10u, 9u, 9u, 5u, 10u, 3u, 13u, 
 	3u, 10u, 5u, 10u, 3u, 10u, 3u, 13u, 3u, 14u, 3u, 14u, 4u, 14u, 5u, 14u, 
 	3u, 14u, 4u, 14u, 5u, 14u, 3u, 14u, 4u, 14u, 5u, 14u, 3u, 14u, 4u, 14u, 
 	5u, 14u, 3u, 14u, 1u, 16u, 4u, 14u, 3u, 17u, 3u, 17u, 1u, 16u, 1u, 16u, 
 	1u, 16u, 1u, 16u, 1u, 16u, 3u, 17u, 3u, 17u, 1u, 16u, 1u, 16u, 1u, 16u, 
 	1u, 16u, 1u, 16u, 3u, 17u, 3u, 17u, 1u, 16u, 1u, 16u, 1u, 16u, 1u, 16u, 
@@ -96,17 +96,17 @@ static const unsigned char _indic_syllab
 	3u, 17u, 3u, 17u, 1u, 16u, 1u, 16u, 1u, 16u, 1u, 16u, 1u, 16u, 3u, 17u, 
 	3u, 17u, 1u, 16u, 1u, 16u, 1u, 16u, 1u, 16u, 1u, 16u, 3u, 17u, 3u, 17u, 
 	1u, 16u, 1u, 16u, 1u, 16u, 1u, 16u, 1u, 16u, 3u, 17u, 1u, 17u, 3u, 17u, 
 	1u, 17u, 4u, 14u, 5u, 10u, 9u, 10u, 9u, 9u, 9u, 10u, 9u, 10u, 9u, 9u, 
 	5u, 10u, 1u, 16u, 3u, 17u, 3u, 17u, 4u, 17u, 3u, 17u, 3u, 17u, 1u, 16u, 
 	3u, 14u, 4u, 14u, 5u, 14u, 3u, 14u, 4u, 14u, 5u, 14u, 3u, 14u, 4u, 14u, 
 	5u, 14u, 3u, 14u, 4u, 14u, 5u, 14u, 3u, 13u, 3u, 10u, 5u, 10u, 3u, 10u, 
 	3u, 13u, 1u, 16u, 3u, 10u, 5u, 10u, 5u, 10u, 9u, 10u, 9u, 9u, 9u, 10u, 
-	9u, 10u, 9u, 9u, 5u, 10u, 0
+	9u, 10u, 9u, 9u, 5u, 10u, 1u, 16u, 0
 };
 
 static const char _indic_syllable_machine_key_spans[] = {
 	1, 16, 6, 4, 3, 1, 4, 3, 
 	1, 4, 3, 1, 4, 3, 1, 5, 
 	1, 1, 5, 1, 1, 5, 1, 1, 
 	5, 1, 1, 11, 11, 11, 11, 11, 
 	11, 11, 11, 11, 11, 1, 16, 6, 
@@ -122,17 +122,17 @@ static const char _indic_syllable_machin
 	6, 4, 3, 1, 4, 3, 1, 4, 
 	3, 1, 4, 3, 1, 5, 1, 1, 
 	5, 1, 1, 5, 1, 1, 5, 1, 
 	1, 11, 11, 11, 11, 11, 11, 11, 
 	11, 11, 11, 11, 4, 11, 11, 4, 
 	3, 4, 3, 1, 4, 3, 1, 4, 
 	3, 1, 1, 16, 6, 5, 1, 1, 
 	5, 1, 1, 5, 1, 1, 5, 1, 
-	1, 1, 18, 15, 15, 14, 16, 15, 
+	1, 1, 19, 15, 15, 14, 16, 15, 
 	15, 14, 16, 15, 15, 14, 16, 15, 
 	15, 14, 16, 15, 15, 14, 10, 10, 
 	6, 2, 1, 2, 2, 1, 6, 11, 
 	8, 6, 8, 11, 12, 12, 11, 10, 
 	12, 11, 10, 12, 11, 10, 12, 11, 
 	10, 12, 16, 11, 15, 15, 16, 16, 
 	16, 16, 16, 15, 15, 16, 16, 16, 
 	16, 16, 15, 15, 16, 16, 16, 16, 
@@ -167,17 +167,17 @@ static const char _indic_syllable_machin
 	15, 15, 16, 16, 16, 16, 16, 15, 
 	15, 16, 16, 16, 16, 16, 15, 15, 
 	16, 16, 16, 16, 16, 15, 17, 15, 
 	17, 11, 6, 2, 1, 2, 2, 1, 
 	6, 16, 15, 15, 14, 15, 15, 16, 
 	12, 11, 10, 12, 11, 10, 12, 11, 
 	10, 12, 11, 10, 11, 8, 6, 8, 
 	11, 16, 8, 6, 6, 2, 1, 2, 
-	2, 1, 6
+	2, 1, 6, 16
 };
 
 static const short _indic_syllable_machine_index_offsets[] = {
 	0, 2, 19, 26, 31, 35, 37, 42, 
 	46, 48, 53, 57, 59, 64, 68, 70, 
 	76, 78, 80, 86, 88, 90, 96, 98, 
 	100, 106, 108, 110, 122, 134, 146, 158, 
 	170, 182, 194, 206, 218, 230, 232, 249, 
@@ -193,62 +193,62 @@ static const short _indic_syllable_machi
 	697, 704, 709, 713, 715, 720, 724, 726, 
 	731, 735, 737, 742, 746, 748, 754, 756, 
 	758, 764, 766, 768, 774, 776, 778, 784, 
 	786, 788, 800, 812, 824, 836, 848, 860, 
 	872, 884, 896, 908, 920, 925, 937, 949, 
 	954, 958, 963, 967, 969, 974, 978, 980, 
 	985, 989, 991, 993, 1010, 1017, 1023, 1025, 
 	1027, 1033, 1035, 1037, 1043, 1045, 1047, 1053, 
-	1055, 1057, 1059, 1078, 1094, 1110, 1125, 1142, 
-	1158, 1174, 1189, 1206, 1222, 1238, 1253, 1270, 
-	1286, 1302, 1317, 1334, 1350, 1366, 1381, 1392, 
-	1403, 1410, 1413, 1415, 1418, 1421, 1423, 1430, 
-	1442, 1451, 1458, 1467, 1479, 1492, 1505, 1517, 
-	1528, 1541, 1553, 1564, 1577, 1589, 1600, 1613, 
-	1625, 1636, 1649, 1666, 1678, 1694, 1710, 1727, 
-	1744, 1761, 1778, 1795, 1811, 1827, 1844, 1861, 
-	1878, 1895, 1912, 1928, 1944, 1961, 1978, 1995, 
-	2012, 2029, 2045, 2061, 2078, 2095, 2112, 2129, 
-	2146, 2162, 2178, 2194, 2210, 2225, 2242, 2258, 
-	2274, 2289, 2306, 2322, 2338, 2353, 2370, 2386, 
-	2402, 2417, 2434, 2450, 2466, 2481, 2492, 2503, 
-	2510, 2513, 2515, 2518, 2521, 2523, 2530, 2542, 
-	2551, 2558, 2567, 2579, 2592, 2605, 2617, 2628, 
-	2641, 2653, 2664, 2677, 2689, 2700, 2713, 2725, 
-	2736, 2749, 2766, 2778, 2794, 2810, 2827, 2844, 
-	2861, 2878, 2895, 2911, 2927, 2944, 2961, 2978, 
-	2995, 3012, 3028, 3044, 3061, 3078, 3095, 3112, 
-	3129, 3145, 3161, 3178, 3195, 3212, 3229, 3241, 
-	3258, 3274, 3290, 3305, 3322, 3338, 3354, 3369, 
-	3386, 3402, 3418, 3433, 3450, 3466, 3482, 3497, 
-	3514, 3530, 3546, 3561, 3572, 3583, 3590, 3593, 
-	3595, 3598, 3601, 3603, 3610, 3622, 3631, 3638, 
-	3647, 3659, 3672, 3685, 3697, 3708, 3721, 3733, 
-	3744, 3757, 3769, 3780, 3793, 3805, 3816, 3829, 
-	3846, 3858, 3874, 3890, 3907, 3924, 3941, 3958, 
-	3975, 3991, 4007, 4024, 4041, 4058, 4075, 4092, 
-	4108, 4124, 4141, 4158, 4175, 4192, 4209, 4225, 
-	4241, 4258, 4275, 4292, 4309, 4326, 4338, 4354, 
-	4366, 4382, 4398, 4413, 4430, 4446, 4462, 4477, 
-	4494, 4510, 4526, 4541, 4558, 4574, 4590, 4605, 
-	4622, 4638, 4654, 4669, 4680, 4691, 4698, 4701, 
-	4703, 4706, 4709, 4711, 4718, 4730, 4739, 4746, 
-	4755, 4767, 4780, 4793, 4805, 4816, 4829, 4841, 
-	4852, 4865, 4877, 4888, 4901, 4913, 4924, 4937, 
-	4954, 4966, 4982, 4998, 5015, 5032, 5049, 5066, 
-	5083, 5099, 5115, 5132, 5149, 5166, 5183, 5200, 
-	5216, 5232, 5249, 5266, 5283, 5300, 5317, 5333, 
-	5349, 5366, 5383, 5400, 5417, 5434, 5450, 5468, 
-	5484, 5502, 5514, 5521, 5524, 5526, 5529, 5532, 
-	5534, 5541, 5558, 5574, 5590, 5605, 5621, 5637, 
-	5654, 5667, 5679, 5690, 5703, 5715, 5726, 5739, 
-	5751, 5762, 5775, 5787, 5798, 5810, 5819, 5826, 
-	5835, 5847, 5864, 5873, 5880, 5887, 5890, 5892, 
-	5895, 5898, 5900
+	1055, 1057, 1059, 1079, 1095, 1111, 1126, 1143, 
+	1159, 1175, 1190, 1207, 1223, 1239, 1254, 1271, 
+	1287, 1303, 1318, 1335, 1351, 1367, 1382, 1393, 
+	1404, 1411, 1414, 1416, 1419, 1422, 1424, 1431, 
+	1443, 1452, 1459, 1468, 1480, 1493, 1506, 1518, 
+	1529, 1542, 1554, 1565, 1578, 1590, 1601, 1614, 
+	1626, 1637, 1650, 1667, 1679, 1695, 1711, 1728, 
+	1745, 1762, 1779, 1796, 1812, 1828, 1845, 1862, 
+	1879, 1896, 1913, 1929, 1945, 1962, 1979, 1996, 
+	2013, 2030, 2046, 2062, 2079, 2096, 2113, 2130, 
+	2147, 2163, 2179, 2195, 2211, 2226, 2243, 2259, 
+	2275, 2290, 2307, 2323, 2339, 2354, 2371, 2387, 
+	2403, 2418, 2435, 2451, 2467, 2482, 2493, 2504, 
+	2511, 2514, 2516, 2519, 2522, 2524, 2531, 2543, 
+	2552, 2559, 2568, 2580, 2593, 2606, 2618, 2629, 
+	2642, 2654, 2665, 2678, 2690, 2701, 2714, 2726, 
+	2737, 2750, 2767, 2779, 2795, 2811, 2828, 2845, 
+	2862, 2879, 2896, 2912, 2928, 2945, 2962, 2979, 
+	2996, 3013, 3029, 3045, 3062, 3079, 3096, 3113, 
+	3130, 3146, 3162, 3179, 3196, 3213, 3230, 3242, 
+	3259, 3275, 3291, 3306, 3323, 3339, 3355, 3370, 
+	3387, 3403, 3419, 3434, 3451, 3467, 3483, 3498, 
+	3515, 3531, 3547, 3562, 3573, 3584, 3591, 3594, 
+	3596, 3599, 3602, 3604, 3611, 3623, 3632, 3639, 
+	3648, 3660, 3673, 3686, 3698, 3709, 3722, 3734, 
+	3745, 3758, 3770, 3781, 3794, 3806, 3817, 3830, 
+	3847, 3859, 3875, 3891, 3908, 3925, 3942, 3959, 
+	3976, 3992, 4008, 4025, 4042, 4059, 4076, 4093, 
+	4109, 4125, 4142, 4159, 4176, 4193, 4210, 4226, 
+	4242, 4259, 4276, 4293, 4310, 4327, 4339, 4355, 
+	4367, 4383, 4399, 4414, 4431, 4447, 4463, 4478, 
+	4495, 4511, 4527, 4542, 4559, 4575, 4591, 4606, 
+	4623, 4639, 4655, 4670, 4681, 4692, 4699, 4702, 
+	4704, 4707, 4710, 4712, 4719, 4731, 4740, 4747, 
+	4756, 4768, 4781, 4794, 4806, 4817, 4830, 4842, 
+	4853, 4866, 4878, 4889, 4902, 4914, 4925, 4938, 
+	4955, 4967, 4983, 4999, 5016, 5033, 5050, 5067, 
+	5084, 5100, 5116, 5133, 5150, 5167, 5184, 5201, 
+	5217, 5233, 5250, 5267, 5284, 5301, 5318, 5334, 
+	5350, 5367, 5384, 5401, 5418, 5435, 5451, 5469, 
+	5485, 5503, 5515, 5522, 5525, 5527, 5530, 5533, 
+	5535, 5542, 5559, 5575, 5591, 5606, 5622, 5638, 
+	5655, 5668, 5680, 5691, 5704, 5716, 5727, 5740, 
+	5752, 5763, 5776, 5788, 5799, 5811, 5820, 5827, 
+	5836, 5848, 5865, 5874, 5881, 5888, 5891, 5893, 
+	5896, 5899, 5901, 5908
 };
 
 static const short _indic_syllable_machine_indicies[] = {
 	1, 0, 2, 3, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
 	0, 2, 0, 1, 0, 0, 0, 0, 
 	4, 0, 5, 5, 6, 1, 0, 7, 
 	7, 6, 0, 6, 0, 8, 8, 9, 
@@ -376,621 +376,623 @@ static const short _indic_syllable_machi
 	170, 0, 157, 0, 0, 0, 0, 172, 
 	0, 173, 0, 0, 0, 157, 0, 174, 
 	0, 175, 0, 176, 167, 167, 168, 157, 
 	0, 177, 0, 178, 0, 179, 164, 164, 
 	165, 157, 0, 180, 0, 181, 0, 182, 
 	161, 161, 162, 157, 0, 183, 0, 184, 
 	0, 186, 185, 188, 189, 190, 191, 192, 
 	193, 84, 79, 194, 195, 196, 196, 156, 
-	197, 198, 199, 200, 201, 187, 203, 204, 
-	205, 206, 6, 1, 207, 208, 202, 202, 
-	38, 209, 202, 202, 210, 202, 211, 204, 
-	212, 212, 6, 1, 207, 208, 202, 202, 
-	202, 209, 202, 202, 210, 202, 204, 212, 
-	212, 6, 1, 207, 208, 202, 202, 202, 
-	209, 202, 202, 210, 202, 213, 202, 202, 
-	202, 19, 214, 202, 1, 207, 208, 202, 
-	202, 202, 215, 202, 213, 202, 216, 217, 
-	218, 219, 6, 1, 207, 208, 202, 202, 
-	36, 220, 202, 202, 210, 202, 221, 217, 
-	222, 222, 6, 1, 207, 208, 202, 202, 
-	202, 220, 202, 202, 210, 202, 217, 222, 
-	222, 6, 1, 207, 208, 202, 202, 202, 
-	220, 202, 202, 210, 202, 223, 202, 202, 
-	202, 19, 224, 202, 1, 207, 208, 202, 
-	202, 202, 215, 202, 223, 202, 225, 226, 
-	227, 228, 6, 1, 207, 208, 202, 202, 
-	34, 229, 202, 202, 210, 202, 230, 226, 
-	231, 231, 6, 1, 207, 208, 202, 202, 
-	202, 229, 202, 202, 210, 202, 226, 231, 
-	231, 6, 1, 207, 208, 202, 202, 202, 
-	229, 202, 202, 210, 202, 232, 202, 202, 
-	202, 19, 233, 202, 1, 207, 208, 202, 
-	202, 202, 215, 202, 232, 202, 234, 235, 
-	236, 237, 6, 1, 207, 208, 202, 202, 
-	32, 238, 202, 202, 210, 202, 239, 235, 
-	240, 240, 6, 1, 207, 208, 202, 202, 
-	202, 238, 202, 202, 210, 202, 235, 240, 
-	240, 6, 1, 207, 208, 202, 202, 202, 
-	238, 202, 202, 210, 202, 241, 202, 202, 
-	202, 19, 242, 202, 1, 207, 208, 202, 
-	202, 202, 215, 202, 241, 202, 243, 244, 
-	245, 246, 6, 1, 207, 208, 202, 202, 
-	30, 247, 202, 202, 210, 202, 248, 244, 
-	249, 249, 6, 1, 207, 208, 202, 202, 
-	202, 247, 202, 202, 210, 202, 244, 249, 
-	249, 6, 1, 207, 208, 202, 202, 202, 
-	247, 202, 202, 210, 202, 19, 250, 202, 
-	1, 207, 208, 202, 202, 202, 215, 202, 
-	251, 251, 202, 1, 207, 208, 202, 202, 
-	202, 215, 202, 252, 202, 202, 253, 207, 
-	208, 202, 207, 208, 202, 254, 202, 207, 
-	255, 202, 207, 256, 202, 207, 202, 252, 
-	202, 202, 202, 207, 208, 202, 257, 202, 
-	258, 259, 202, 1, 207, 208, 202, 202, 
-	4, 202, 3, 202, 251, 251, 202, 1, 
-	207, 208, 202, 251, 251, 202, 1, 207, 
-	208, 202, 257, 202, 251, 251, 202, 1, 
-	207, 208, 202, 257, 202, 258, 251, 202, 
-	1, 207, 208, 202, 202, 4, 202, 19, 
-	202, 260, 260, 6, 1, 207, 208, 202, 
-	202, 202, 215, 202, 261, 28, 262, 263, 
-	9, 1, 207, 208, 202, 202, 202, 215, 
-	202, 28, 262, 263, 9, 1, 207, 208, 
-	202, 202, 202, 215, 202, 262, 262, 9, 
-	1, 207, 208, 202, 202, 202, 215, 202, 
-	264, 25, 265, 266, 12, 1, 207, 208, 
-	202, 202, 202, 215, 202, 25, 265, 266, 
-	12, 1, 207, 208, 202, 202, 202, 215, 
-	202, 265, 265, 12, 1, 207, 208, 202, 
-	202, 202, 215, 202, 267, 22, 268, 269, 
-	15, 1, 207, 208, 202, 202, 202, 215, 
-	202, 22, 268, 269, 15, 1, 207, 208, 
-	202, 202, 202, 215, 202, 268, 268, 15, 
-	1, 207, 208, 202, 202, 202, 215, 202, 
-	270, 19, 251, 271, 202, 1, 207, 208, 
-	202, 202, 202, 215, 202, 19, 251, 271, 
-	202, 1, 207, 208, 202, 202, 202, 215, 
-	202, 251, 272, 202, 1, 207, 208, 202, 
-	202, 202, 215, 202, 19, 202, 251, 251, 
-	202, 1, 207, 208, 202, 202, 202, 215, 
-	202, 2, 3, 202, 202, 19, 250, 202, 
-	1, 207, 208, 202, 202, 202, 215, 202, 
-	2, 202, 244, 249, 249, 6, 1, 207, 
-	208, 202, 202, 202, 247, 202, 243, 244, 
-	249, 249, 6, 1, 207, 208, 202, 202, 
-	202, 247, 202, 202, 210, 202, 243, 244, 
-	245, 249, 6, 1, 207, 208, 202, 202, 
-	30, 247, 202, 202, 210, 202, 241, 202, 
-	273, 202, 260, 260, 6, 1, 207, 208, 
-	202, 202, 202, 215, 202, 241, 202, 241, 
-	202, 202, 202, 251, 251, 202, 1, 207, 
-	208, 202, 202, 202, 215, 202, 241, 202, 
-	241, 202, 202, 202, 251, 274, 202, 1, 
-	207, 208, 202, 202, 202, 215, 202, 241, 
-	202, 241, 202, 273, 202, 251, 251, 202, 
-	1, 207, 208, 202, 202, 202, 215, 202, 
-	241, 202, 241, 3, 202, 202, 19, 242, 
-	202, 1, 207, 208, 202, 202, 202, 215, 
-	202, 241, 202, 234, 235, 240, 240, 6, 
-	1, 207, 208, 202, 202, 202, 238, 202, 
-	202, 210, 202, 234, 235, 236, 240, 6, 
-	1, 207, 208, 202, 202, 32, 238, 202, 
-	202, 210, 202, 232, 202, 275, 202, 260, 
-	260, 6, 1, 207, 208, 202, 202, 202, 
-	215, 202, 232, 202, 232, 202, 202, 202, 
-	251, 251, 202, 1, 207, 208, 202, 202, 
-	202, 215, 202, 232, 202, 232, 202, 202, 
-	202, 251, 276, 202, 1, 207, 208, 202, 
-	202, 202, 215, 202, 232, 202, 232, 202, 
-	275, 202, 251, 251, 202, 1, 207, 208, 
-	202, 202, 202, 215, 202, 232, 202, 232, 
-	3, 202, 202, 19, 233, 202, 1, 207, 
-	208, 202, 202, 202, 215, 202, 232, 202, 
-	225, 226, 231, 231, 6, 1, 207, 208, 
-	202, 202, 202, 229, 202, 202, 210, 202, 
-	225, 226, 227, 231, 6, 1, 207, 208, 
-	202, 202, 34, 229, 202, 202, 210, 202, 
-	223, 202, 277, 202, 260, 260, 6, 1, 
-	207, 208, 202, 202, 202, 215, 202, 223, 
-	202, 223, 202, 202, 202, 251, 251, 202, 
-	1, 207, 208, 202, 202, 202, 215, 202, 
-	223, 202, 223, 202, 202, 202, 251, 278, 
-	202, 1, 207, 208, 202, 202, 202, 215, 
-	202, 223, 202, 223, 202, 277, 202, 251, 
-	251, 202, 1, 207, 208, 202, 202, 202, 
-	215, 202, 223, 202, 223, 3, 202, 202, 
-	19, 224, 202, 1, 207, 208, 202, 202, 
-	202, 215, 202, 223, 202, 216, 217, 222, 
-	222, 6, 1, 207, 208, 202, 202, 202, 
-	220, 202, 202, 210, 202, 216, 217, 218, 
-	222, 6, 1, 207, 208, 202, 202, 36, 
-	220, 202, 202, 210, 202, 213, 202, 279, 
-	202, 260, 260, 6, 1, 207, 208, 202, 
-	202, 202, 215, 202, 213, 202, 213, 202, 
-	202, 202, 251, 251, 202, 1, 207, 208, 
-	202, 202, 202, 215, 202, 213, 202, 213, 
-	202, 202, 202, 251, 280, 202, 1, 207, 
-	208, 202, 202, 202, 215, 202, 213, 202, 
-	213, 202, 279, 202, 251, 251, 202, 1, 
-	207, 208, 202, 202, 202, 215, 202, 213, 
-	202, 213, 3, 202, 202, 19, 214, 202, 
-	1, 207, 208, 202, 202, 202, 215, 202, 
-	213, 202, 203, 204, 212, 212, 6, 1, 
-	207, 208, 202, 202, 202, 209, 202, 202, 
-	210, 202, 203, 204, 205, 212, 6, 1, 
-	207, 208, 202, 202, 38, 209, 202, 202, 
-	210, 202, 282, 283, 284, 285, 45, 40, 
-	286, 287, 281, 281, 77, 288, 281, 281, 
-	289, 281, 290, 283, 291, 285, 45, 40, 
-	286, 287, 281, 281, 281, 288, 281, 281, 
-	289, 281, 283, 291, 285, 45, 40, 286, 
-	287, 281, 281, 281, 288, 281, 281, 289, 
-	281, 292, 281, 281, 281, 58, 293, 281, 
-	40, 286, 287, 281, 281, 281, 294, 281, 
-	292, 281, 295, 296, 297, 298, 45, 40, 
-	286, 287, 281, 281, 75, 299, 281, 281, 
-	289, 281, 300, 296, 301, 301, 45, 40, 
-	286, 287, 281, 281, 281, 299, 281, 281, 
-	289, 281, 296, 301, 301, 45, 40, 286, 
-	287, 281, 281, 281, 299, 281, 281, 289, 
-	281, 302, 281, 281, 281, 58, 303, 281, 
-	40, 286, 287, 281, 281, 281, 294, 281, 
-	302, 281, 304, 305, 306, 307, 45, 40, 
-	286, 287, 281, 281, 73, 308, 281, 281, 
-	289, 281, 309, 305, 310, 310, 45, 40, 
-	286, 287, 281, 281, 281, 308, 281, 281, 
-	289, 281, 305, 310, 310, 45, 40, 286, 
-	287, 281, 281, 281, 308, 281, 281, 289, 
-	281, 311, 281, 281, 281, 58, 312, 281, 
-	40, 286, 287, 281, 281, 281, 294, 281, 
-	311, 281, 313, 314, 315, 316, 45, 40, 
-	286, 287, 281, 281, 71, 317, 281, 281, 
-	289, 281, 318, 314, 319, 319, 45, 40, 
-	286, 287, 281, 281, 281, 317, 281, 281, 
-	289, 281, 314, 319, 319, 45, 40, 286, 
-	287, 281, 281, 281, 317, 281, 281, 289, 
-	281, 320, 281, 281, 281, 58, 321, 281, 
-	40, 286, 287, 281, 281, 281, 294, 281, 
-	320, 281, 322, 323, 324, 325, 45, 40, 
-	286, 287, 281, 281, 69, 326, 281, 281, 
-	289, 281, 327, 323, 328, 328, 45, 40, 
-	286, 287, 281, 281, 281, 326, 281, 281, 
-	289, 281, 323, 328, 328, 45, 40, 286, 
-	287, 281, 281, 281, 326, 281, 281, 289, 
-	281, 58, 329, 281, 40, 286, 287, 281, 
-	281, 281, 294, 281, 330, 330, 281, 40, 
-	286, 287, 281, 281, 281, 294, 281, 331, 
-	281, 281, 332, 286, 287, 281, 286, 287, 
-	281, 333, 281, 286, 334, 281, 286, 335, 
-	281, 286, 281, 331, 281, 281, 281, 286, 
-	287, 281, 336, 281, 337, 338, 281, 40, 
-	286, 287, 281, 281, 43, 281, 42, 281, 
-	330, 330, 281, 40, 286, 287, 281, 330, 
-	330, 281, 40, 286, 287, 281, 336, 281, 
-	330, 330, 281, 40, 286, 287, 281, 336, 
-	281, 337, 330, 281, 40, 286, 287, 281, 
-	281, 43, 281, 58, 281, 339, 339, 45, 
-	40, 286, 287, 281, 281, 281, 294, 281, 
-	340, 67, 341, 342, 48, 40, 286, 287, 
-	281, 281, 281, 294, 281, 67, 341, 342, 
-	48, 40, 286, 287, 281, 281, 281, 294, 
-	281, 341, 341, 48, 40, 286, 287, 281, 
-	281, 281, 294, 281, 343, 64, 344, 345, 
-	51, 40, 286, 287, 281, 281, 281, 294, 
-	281, 64, 344, 345, 51, 40, 286, 287, 
-	281, 281, 281, 294, 281, 344, 344, 51, 
-	40, 286, 287, 281, 281, 281, 294, 281, 
-	346, 61, 347, 348, 54, 40, 286, 287, 
-	281, 281, 281, 294, 281, 61, 347, 348, 
-	54, 40, 286, 287, 281, 281, 281, 294, 
-	281, 347, 347, 54, 40, 286, 287, 281, 
-	281, 281, 294, 281, 349, 58, 330, 350, 
-	281, 40, 286, 287, 281, 281, 281, 294, 
-	281, 58, 330, 350, 281, 40, 286, 287, 
-	281, 281, 281, 294, 281, 330, 351, 281, 
-	40, 286, 287, 281, 281, 281, 294, 281, 
-	58, 281, 330, 330, 281, 40, 286, 287, 
-	281, 281, 281, 294, 281, 41, 42, 281, 
-	281, 58, 329, 281, 40, 286, 287, 281, 
-	281, 281, 294, 281, 41, 281, 323, 328, 
-	328, 45, 40, 286, 287, 281, 281, 281, 
-	326, 281, 322, 323, 328, 328, 45, 40, 
-	286, 287, 281, 281, 281, 326, 281, 281, 
-	289, 281, 322, 323, 324, 328, 45, 40, 
-	286, 287, 281, 281, 69, 326, 281, 281, 
-	289, 281, 320, 281, 352, 281, 339, 339, 
-	45, 40, 286, 287, 281, 281, 281, 294, 
-	281, 320, 281, 320, 281, 281, 281, 330, 
-	330, 281, 40, 286, 287, 281, 281, 281, 
-	294, 281, 320, 281, 320, 281, 281, 281, 
-	330, 353, 281, 40, 286, 287, 281, 281, 
-	281, 294, 281, 320, 281, 320, 281, 352, 
-	281, 330, 330, 281, 40, 286, 287, 281, 
-	281, 281, 294, 281, 320, 281, 320, 42, 
-	281, 281, 58, 321, 281, 40, 286, 287, 
-	281, 281, 281, 294, 281, 320, 281, 313, 
-	314, 319, 319, 45, 40, 286, 287, 281, 
-	281, 281, 317, 281, 281, 289, 281, 313, 
-	314, 315, 319, 45, 40, 286, 287, 281, 
-	281, 71, 317, 281, 281, 289, 281, 311, 
-	281, 354, 281, 339, 339, 45, 40, 286, 
-	287, 281, 281, 281, 294, 281, 311, 281, 
-	311, 281, 281, 281, 330, 330, 281, 40, 
-	286, 287, 281, 281, 281, 294, 281, 311, 
-	281, 311, 281, 281, 281, 330, 355, 281, 
-	40, 286, 287, 281, 281, 281, 294, 281, 
-	311, 281, 311, 281, 354, 281, 330, 330, 
-	281, 40, 286, 287, 281, 281, 281, 294, 
-	281, 311, 281, 311, 42, 281, 281, 58, 
-	312, 281, 40, 286, 287, 281, 281, 281, 
-	294, 281, 311, 281, 304, 305, 310, 310, 
-	45, 40, 286, 287, 281, 281, 281, 308, 
-	281, 281, 289, 281, 304, 305, 306, 310, 
-	45, 40, 286, 287, 281, 281, 73, 308, 
-	281, 281, 289, 281, 302, 281, 356, 281, 
-	339, 339, 45, 40, 286, 287, 281, 281, 
-	281, 294, 281, 302, 281, 302, 281, 281, 
-	281, 330, 330, 281, 40, 286, 287, 281, 
-	281, 281, 294, 281, 302, 281, 302, 281, 
-	281, 281, 330, 357, 281, 40, 286, 287, 
-	281, 281, 281, 294, 281, 302, 281, 302, 
-	281, 356, 281, 330, 330, 281, 40, 286, 
-	287, 281, 281, 281, 294, 281, 302, 281, 
-	302, 42, 281, 281, 58, 303, 281, 40, 
-	286, 287, 281, 281, 281, 294, 281, 302, 
-	281, 295, 296, 301, 301, 45, 40, 286, 
-	287, 281, 281, 281, 299, 281, 281, 289, 
-	281, 295, 296, 297, 301, 45, 40, 286, 
-	287, 281, 281, 75, 299, 281, 281, 289, 
-	281, 292, 281, 358, 281, 339, 339, 45, 
-	40, 286, 287, 281, 281, 281, 294, 281, 
-	292, 281, 292, 281, 281, 281, 330, 330, 
-	281, 40, 286, 287, 281, 281, 281, 294, 
-	281, 292, 281, 292, 281, 281, 281, 330, 
-	359, 281, 40, 286, 287, 281, 281, 281, 
-	294, 281, 292, 281, 292, 281, 358, 281, 
-	330, 330, 281, 40, 286, 287, 281, 281, 
-	281, 294, 281, 292, 281, 76, 44, 44, 
-	45, 40, 281, 281, 281, 281, 281, 76, 
-	281, 292, 42, 281, 281, 58, 293, 281, 
-	40, 286, 287, 281, 281, 281, 294, 281, 
-	292, 281, 282, 283, 291, 285, 45, 40, 
-	286, 287, 281, 281, 281, 288, 281, 281, 
-	289, 281, 361, 191, 362, 362, 84, 79, 
-	194, 195, 360, 360, 360, 197, 360, 360, 
-	200, 360, 191, 362, 362, 84, 79, 194, 
-	195, 360, 360, 360, 197, 360, 360, 200, 
-	360, 363, 360, 360, 360, 98, 364, 360, 
-	79, 194, 195, 360, 360, 360, 365, 360, 
-	363, 360, 366, 367, 368, 369, 84, 79, 
-	194, 195, 360, 360, 115, 370, 360, 360, 
-	200, 360, 371, 367, 372, 372, 84, 79, 
-	194, 195, 360, 360, 360, 370, 360, 360, 
-	200, 360, 367, 372, 372, 84, 79, 194, 
-	195, 360, 360, 360, 370, 360, 360, 200, 
-	360, 373, 360, 360, 360, 98, 374, 360, 
-	79, 194, 195, 360, 360, 360, 365, 360, 
-	373, 360, 375, 376, 377, 378, 84, 79, 
-	194, 195, 360, 360, 113, 379, 360, 360, 
-	200, 360, 380, 376, 381, 381, 84, 79, 
-	194, 195, 360, 360, 360, 379, 360, 360, 
-	200, 360, 376, 381, 381, 84, 79, 194, 
-	195, 360, 360, 360, 379, 360, 360, 200, 
-	360, 382, 360, 360, 360, 98, 383, 360, 
-	79, 194, 195, 360, 360, 360, 365, 360, 
-	382, 360, 384, 385, 386, 387, 84, 79, 
-	194, 195, 360, 360, 111, 388, 360, 360, 
-	200, 360, 389, 385, 390, 390, 84, 79, 
-	194, 195, 360, 360, 360, 388, 360, 360, 
-	200, 360, 385, 390, 390, 84, 79, 194, 
-	195, 360, 360, 360, 388, 360, 360, 200, 
-	360, 391, 360, 360, 360, 98, 392, 360, 
-	79, 194, 195, 360, 360, 360, 365, 360, 
-	391, 360, 393, 394, 395, 396, 84, 79, 
-	194, 195, 360, 360, 109, 397, 360, 360, 
-	200, 360, 398, 394, 399, 399, 84, 79, 
-	194, 195, 360, 360, 360, 397, 360, 360, 
-	200, 360, 394, 399, 399, 84, 79, 194, 
-	195, 360, 360, 360, 397, 360, 360, 200, 
-	360, 98, 400, 360, 79, 194, 195, 360, 
-	360, 360, 365, 360, 401, 401, 360, 79, 
-	194, 195, 360, 360, 360, 365, 360, 402, 
-	360, 360, 403, 194, 195, 360, 194, 195, 
-	360, 404, 360, 194, 405, 360, 194, 406, 
-	360, 194, 360, 402, 360, 360, 360, 194, 
-	195, 360, 407, 360, 408, 409, 360, 79, 
-	194, 195, 360, 360, 82, 360, 81, 360, 
-	401, 401, 360, 79, 194, 195, 360, 401, 
-	401, 360, 79, 194, 195, 360, 407, 360, 
-	401, 401, 360, 79, 194, 195, 360, 407, 
-	360, 408, 401, 360, 79, 194, 195, 360, 
-	360, 82, 360, 98, 360, 410, 410, 84, 
-	79, 194, 195, 360, 360, 360, 365, 360, 
-	411, 107, 412, 413, 88, 79, 194, 195, 
-	360, 360, 360, 365, 360, 107, 412, 413, 
-	88, 79, 194, 195, 360, 360, 360, 365, 
-	360, 412, 412, 88, 79, 194, 195, 360, 
-	360, 360, 365, 360, 414, 104, 415, 416, 
-	91, 79, 194, 195, 360, 360, 360, 365, 
-	360, 104, 415, 416, 91, 79, 194, 195, 
-	360, 360, 360, 365, 360, 415, 415, 91, 
-	79, 194, 195, 360, 360, 360, 365, 360, 
-	417, 101, 418, 419, 94, 79, 194, 195, 
-	360, 360, 360, 365, 360, 101, 418, 419, 
-	94, 79, 194, 195, 360, 360, 360, 365, 
-	360, 418, 418, 94, 79, 194, 195, 360, 
-	360, 360, 365, 360, 420, 98, 401, 421, 
-	360, 79, 194, 195, 360, 360, 360, 365, 
-	360, 98, 401, 421, 360, 79, 194, 195, 
-	360, 360, 360, 365, 360, 401, 422, 360, 
-	79, 194, 195, 360, 360, 360, 365, 360, 
-	98, 360, 401, 401, 360, 79, 194, 195, 
-	360, 360, 360, 365, 360, 80, 81, 360, 
-	360, 98, 400, 360, 79, 194, 195, 360, 
-	360, 360, 365, 360, 80, 360, 394, 399, 
-	399, 84, 79, 194, 195, 360, 360, 360, 
-	397, 360, 393, 394, 399, 399, 84, 79, 
-	194, 195, 360, 360, 360, 397, 360, 360, 
-	200, 360, 393, 394, 395, 399, 84, 79, 
-	194, 195, 360, 360, 109, 397, 360, 360, 
-	200, 360, 391, 360, 423, 360, 410, 410, 
-	84, 79, 194, 195, 360, 360, 360, 365, 
-	360, 391, 360, 391, 360, 360, 360, 401, 
-	401, 360, 79, 194, 195, 360, 360, 360, 
-	365, 360, 391, 360, 391, 360, 360, 360, 
-	401, 424, 360, 79, 194, 195, 360, 360, 
-	360, 365, 360, 391, 360, 391, 360, 423, 
-	360, 401, 401, 360, 79, 194, 195, 360, 
-	360, 360, 365, 360, 391, 360, 391, 81, 
-	360, 360, 98, 392, 360, 79, 194, 195, 
-	360, 360, 360, 365, 360, 391, 360, 384, 
-	385, 390, 390, 84, 79, 194, 195, 360, 
-	360, 360, 388, 360, 360, 200, 360, 384, 
-	385, 386, 390, 84, 79, 194, 195, 360, 
-	360, 111, 388, 360, 360, 200, 360, 382, 
-	360, 425, 360, 410, 410, 84, 79, 194, 
-	195, 360, 360, 360, 365, 360, 382, 360, 
-	382, 360, 360, 360, 401, 401, 360, 79, 
-	194, 195, 360, 360, 360, 365, 360, 382, 
-	360, 382, 360, 360, 360, 401, 426, 360, 
-	79, 194, 195, 360, 360, 360, 365, 360, 
-	382, 360, 382, 360, 425, 360, 401, 401, 
-	360, 79, 194, 195, 360, 360, 360, 365, 
-	360, 382, 360, 382, 81, 360, 360, 98, 
-	383, 360, 79, 194, 195, 360, 360, 360, 
-	365, 360, 382, 360, 375, 376, 381, 381, 
-	84, 79, 194, 195, 360, 360, 360, 379, 
-	360, 360, 200, 360, 375, 376, 377, 381, 
-	84, 79, 194, 195, 360, 360, 113, 379, 
-	360, 360, 200, 360, 373, 360, 427, 360, 
-	410, 410, 84, 79, 194, 195, 360, 360, 
-	360, 365, 360, 373, 360, 373, 360, 360, 
-	360, 401, 401, 360, 79, 194, 195, 360, 
-	360, 360, 365, 360, 373, 360, 373, 360, 
-	360, 360, 401, 428, 360, 79, 194, 195, 
-	360, 360, 360, 365, 360, 373, 360, 373, 
-	360, 427, 360, 401, 401, 360, 79, 194, 
-	195, 360, 360, 360, 365, 360, 373, 360, 
-	373, 81, 360, 360, 98, 374, 360, 79, 
-	194, 195, 360, 360, 360, 365, 360, 373, 
-	360, 366, 367, 372, 372, 84, 79, 194, 
-	195, 360, 360, 360, 370, 360, 360, 200, 
-	360, 366, 367, 368, 372, 84, 79, 194, 
-	195, 360, 360, 115, 370, 360, 360, 200, 
-	360, 363, 360, 429, 360, 410, 410, 84, 
-	79, 194, 195, 360, 360, 360, 365, 360, 
-	363, 360, 363, 360, 360, 360, 401, 401, 
-	360, 79, 194, 195, 360, 360, 360, 365, 
-	360, 363, 360, 363, 360, 360, 360, 401, 
-	430, 360, 79, 194, 195, 360, 360, 360, 
-	365, 360, 363, 360, 363, 360, 429, 360, 
-	401, 401, 360, 79, 194, 195, 360, 360, 
-	360, 365, 360, 363, 360, 363, 81, 360, 
-	360, 98, 364, 360, 79, 194, 195, 360, 
-	360, 360, 365, 360, 363, 360, 116, 83, 
-	83, 84, 79, 431, 431, 431, 431, 156, 
-	116, 431, 190, 191, 362, 362, 84, 79, 
-	194, 195, 360, 360, 360, 197, 360, 360, 
-	200, 360, 116, 83, 83, 84, 79, 431, 
-	431, 431, 431, 431, 116, 431, 433, 434, 
-	435, 436, 123, 118, 437, 438, 432, 432, 
-	155, 439, 432, 432, 440, 432, 441, 434, 
-	436, 436, 123, 118, 437, 438, 432, 432, 
-	432, 439, 432, 432, 440, 432, 434, 436, 
-	436, 123, 118, 437, 438, 432, 432, 432, 
-	439, 432, 432, 440, 432, 442, 432, 432, 
-	432, 136, 443, 432, 118, 437, 438, 432, 
-	432, 432, 444, 432, 442, 432, 445, 446, 
-	447, 448, 123, 118, 437, 438, 432, 432, 
-	153, 449, 432, 432, 440, 432, 450, 446, 
-	451, 451, 123, 118, 437, 438, 432, 432, 
-	432, 449, 432, 432, 440, 432, 446, 451, 
-	451, 123, 118, 437, 438, 432, 432, 432, 
-	449, 432, 432, 440, 432, 452, 432, 432, 
-	432, 136, 453, 432, 118, 437, 438, 432, 
-	432, 432, 444, 432, 452, 432, 454, 455, 
-	456, 457, 123, 118, 437, 438, 432, 432, 
-	151, 458, 432, 432, 440, 432, 459, 455, 
-	460, 460, 123, 118, 437, 438, 432, 432, 
-	432, 458, 432, 432, 440, 432, 455, 460, 
-	460, 123, 118, 437, 438, 432, 432, 432, 
-	458, 432, 432, 440, 432, 461, 432, 432, 
-	432, 136, 462, 432, 118, 437, 438, 432, 
-	432, 432, 444, 432, 461, 432, 463, 464, 
-	465, 466, 123, 118, 437, 438, 432, 432, 
-	149, 467, 432, 432, 440, 432, 468, 464, 
-	469, 469, 123, 118, 437, 438, 432, 432, 
-	432, 467, 432, 432, 440, 432, 464, 469, 
-	469, 123, 118, 437, 438, 432, 432, 432, 
-	467, 432, 432, 440, 432, 470, 432, 432, 
-	432, 136, 471, 432, 118, 437, 438, 432, 
-	432, 432, 444, 432, 470, 432, 472, 473, 
-	474, 475, 123, 118, 437, 438, 432, 432, 
-	147, 476, 432, 432, 440, 432, 477, 473, 
-	478, 478, 123, 118, 437, 438, 432, 432, 
-	432, 476, 432, 432, 440, 432, 473, 478, 
-	478, 123, 118, 437, 438, 432, 432, 432, 
-	476, 432, 432, 440, 432, 136, 479, 432, 
-	118, 437, 438, 432, 432, 432, 444, 432, 
-	480, 480, 432, 118, 437, 438, 432, 432, 
-	432, 444, 432, 481, 432, 432, 482, 437, 
-	438, 432, 437, 438, 432, 483, 432, 437, 
-	484, 432, 437, 485, 432, 437, 432, 481, 
-	432, 432, 432, 437, 438, 432, 486, 432, 
-	487, 488, 432, 118, 437, 438, 432, 432, 
-	121, 432, 120, 432, 480, 480, 432, 118, 
-	437, 438, 432, 480, 480, 432, 118, 437, 
-	438, 432, 486, 432, 480, 480, 432, 118, 
-	437, 438, 432, 486, 432, 487, 480, 432, 
-	118, 437, 438, 432, 432, 121, 432, 136, 
-	432, 489, 489, 123, 118, 437, 438, 432, 
-	432, 432, 444, 432, 490, 145, 491, 492, 
-	126, 118, 437, 438, 432, 432, 432, 444, 
-	432, 145, 491, 492, 126, 118, 437, 438, 
-	432, 432, 432, 444, 432, 491, 491, 126, 
-	118, 437, 438, 432, 432, 432, 444, 432, 
-	493, 142, 494, 495, 129, 118, 437, 438, 
-	432, 432, 432, 444, 432, 142, 494, 495, 
-	129, 118, 437, 438, 432, 432, 432, 444, 
-	432, 494, 494, 129, 118, 437, 438, 432, 
-	432, 432, 444, 432, 496, 139, 497, 498, 
-	132, 118, 437, 438, 432, 432, 432, 444, 
-	432, 139, 497, 498, 132, 118, 437, 438, 
-	432, 432, 432, 444, 432, 497, 497, 132, 
-	118, 437, 438, 432, 432, 432, 444, 432, 
-	499, 136, 480, 500, 432, 118, 437, 438, 
-	432, 432, 432, 444, 432, 136, 480, 500, 
-	432, 118, 437, 438, 432, 432, 432, 444, 
-	432, 480, 501, 432, 118, 437, 438, 432, 
-	432, 432, 444, 432, 136, 432, 480, 480, 
-	432, 118, 437, 438, 432, 432, 432, 444, 
-	432, 119, 120, 432, 432, 136, 479, 432, 
-	118, 437, 438, 432, 432, 432, 444, 432, 
-	119, 432, 473, 478, 478, 123, 118, 437, 
-	438, 432, 432, 432, 476, 432, 472, 473, 
-	478, 478, 123, 118, 437, 438, 432, 432, 
-	432, 476, 432, 432, 440, 432, 472, 473, 
-	474, 478, 123, 118, 437, 438, 432, 432, 
-	147, 476, 432, 432, 440, 432, 470, 432, 
-	502, 432, 489, 489, 123, 118, 437, 438, 
-	432, 432, 432, 444, 432, 470, 432, 470, 
-	432, 432, 432, 480, 480, 432, 118, 437, 
-	438, 432, 432, 432, 444, 432, 470, 432, 
-	470, 432, 432, 432, 480, 503, 432, 118, 
-	437, 438, 432, 432, 432, 444, 432, 470, 
-	432, 470, 432, 502, 432, 480, 480, 432, 
-	118, 437, 438, 432, 432, 432, 444, 432, 
-	470, 432, 470, 120, 432, 432, 136, 471, 
-	432, 118, 437, 438, 432, 432, 432, 444, 
-	432, 470, 432, 463, 464, 469, 469, 123, 
-	118, 437, 438, 432, 432, 432, 467, 432, 
-	432, 440, 432, 463, 464, 465, 469, 123, 
-	118, 437, 438, 432, 432, 149, 467, 432, 
-	432, 440, 432, 461, 432, 504, 432, 489, 
-	489, 123, 118, 437, 438, 432, 432, 432, 
-	444, 432, 461, 432, 461, 432, 432, 432, 
-	480, 480, 432, 118, 437, 438, 432, 432, 
-	432, 444, 432, 461, 432, 461, 432, 432, 
-	432, 480, 505, 432, 118, 437, 438, 432, 
-	432, 432, 444, 432, 461, 432, 461, 432, 
-	504, 432, 480, 480, 432, 118, 437, 438, 
-	432, 432, 432, 444, 432, 461, 432, 461, 
-	120, 432, 432, 136, 462, 432, 118, 437, 
-	438, 432, 432, 432, 444, 432, 461, 432, 
-	454, 455, 460, 460, 123, 118, 437, 438, 
-	432, 432, 432, 458, 432, 432, 440, 432, 
-	454, 455, 456, 460, 123, 118, 437, 438, 
-	432, 432, 151, 458, 432, 432, 440, 432, 
-	452, 432, 506, 432, 489, 489, 123, 118, 
-	437, 438, 432, 432, 432, 444, 432, 452, 
-	432, 452, 432, 432, 432, 480, 480, 432, 
-	118, 437, 438, 432, 432, 432, 444, 432, 
-	452, 432, 452, 432, 432, 432, 480, 507, 
-	432, 118, 437, 438, 432, 432, 432, 444, 
-	432, 452, 432, 452, 432, 506, 432, 480, 
-	480, 432, 118, 437, 438, 432, 432, 432, 
-	444, 432, 452, 432, 452, 120, 432, 432, 
-	136, 453, 432, 118, 437, 438, 432, 432, 
-	432, 444, 432, 452, 432, 445, 446, 451, 
-	451, 123, 118, 437, 438, 432, 432, 432, 
-	449, 432, 432, 440, 432, 445, 446, 447, 
-	451, 123, 118, 437, 438, 432, 432, 153, 
-	449, 432, 432, 440, 432, 442, 432, 508, 
-	432, 489, 489, 123, 118, 437, 438, 432, 
-	432, 432, 444, 432, 442, 432, 442, 432, 
-	432, 432, 480, 480, 432, 118, 437, 438, 
-	432, 432, 432, 444, 432, 442, 432, 442, 
-	432, 432, 432, 480, 509, 432, 118, 437, 
-	438, 432, 432, 432, 444, 432, 442, 432, 
-	442, 432, 508, 432, 480, 480, 432, 118, 
-	437, 438, 432, 432, 432, 444, 432, 442, 
-	432, 442, 120, 432, 432, 136, 443, 432, 
-	118, 437, 438, 432, 432, 432, 444, 432, 
-	442, 432, 433, 434, 436, 436, 123, 118, 
-	437, 438, 432, 432, 432, 439, 432, 432, 
-	440, 432, 188, 189, 190, 191, 510, 362, 
-	84, 79, 194, 195, 196, 196, 156, 197, 
-	360, 188, 200, 360, 203, 511, 205, 206, 
-	6, 1, 207, 208, 202, 202, 38, 209, 
-	202, 202, 210, 202, 213, 189, 190, 191, 
-	512, 513, 84, 157, 514, 515, 202, 196, 
-	156, 516, 202, 213, 200, 202, 116, 517, 
-	517, 84, 157, 207, 208, 202, 202, 156, 
-	518, 202, 519, 202, 202, 520, 514, 515, 
-	202, 514, 515, 202, 254, 202, 514, 521, 
-	202, 514, 522, 202, 514, 202, 519, 202, 
-	202, 202, 514, 515, 202, 523, 3, 360, 
-	360, 401, 430, 360, 79, 194, 195, 360, 
-	360, 360, 365, 360, 523, 360, 524, 367, 
-	525, 526, 84, 157, 514, 515, 202, 202, 
-	158, 370, 202, 202, 200, 202, 527, 367, 
-	528, 528, 84, 157, 514, 515, 202, 202, 
-	202, 370, 202, 202, 200, 202, 367, 528, 
-	528, 84, 157, 514, 515, 202, 202, 202, 
-	370, 202, 202, 200, 202, 524, 367, 528, 
-	528, 84, 157, 514, 515, 202, 202, 202, 
-	370, 202, 202, 200, 202, 524, 367, 525, 
-	528, 84, 157, 514, 515, 202, 202, 158, 
-	370, 202, 202, 200, 202, 213, 202, 279, 
-	116, 529, 529, 160, 157, 207, 208, 202, 
-	202, 202, 518, 202, 213, 202, 530, 184, 
-	531, 532, 162, 157, 514, 515, 202, 202, 
-	202, 533, 202, 184, 531, 532, 162, 157, 
-	514, 515, 202, 202, 202, 533, 202, 531, 
-	531, 162, 157, 514, 515, 202, 202, 202, 
-	533, 202, 534, 181, 535, 536, 165, 157, 
-	514, 515, 202, 202, 202, 533, 202, 181, 
-	535, 536, 165, 157, 514, 515, 202, 202, 
-	202, 533, 202, 535, 535, 165, 157, 514, 
-	515, 202, 202, 202, 533, 202, 537, 178, 
-	538, 539, 168, 157, 514, 515, 202, 202, 
-	202, 533, 202, 178, 538, 539, 168, 157, 
-	514, 515, 202, 202, 202, 533, 202, 538, 
-	538, 168, 157, 514, 515, 202, 202, 202, 
-	533, 202, 540, 175, 541, 542, 202, 157, 
-	514, 515, 202, 202, 202, 533, 202, 175, 
-	541, 542, 202, 157, 514, 515, 202, 202, 
-	202, 533, 202, 541, 541, 202, 157, 514, 
-	515, 202, 202, 202, 533, 202, 543, 202, 
-	544, 545, 202, 157, 514, 515, 202, 202, 
-	172, 202, 171, 202, 541, 541, 202, 157, 
-	514, 515, 202, 541, 541, 202, 157, 514, 
-	515, 202, 543, 202, 541, 541, 202, 157, 
-	514, 515, 202, 543, 202, 544, 541, 202, 
-	157, 514, 515, 202, 202, 172, 202, 523, 
-	171, 360, 360, 98, 364, 360, 79, 194, 
-	195, 360, 360, 360, 365, 360, 523, 360, 
-	547, 546, 548, 548, 546, 186, 549, 550, 
-	546, 548, 548, 546, 186, 549, 550, 546, 
-	551, 546, 546, 552, 549, 550, 546, 549, 
-	550, 546, 553, 546, 549, 554, 546, 549, 
-	555, 546, 549, 546, 551, 546, 546, 546, 
-	549, 550, 546, 0
+	197, 198, 199, 200, 201, 202, 187, 204, 
+	205, 206, 207, 6, 1, 208, 209, 203, 
+	203, 38, 210, 203, 203, 211, 203, 212, 
+	205, 213, 213, 6, 1, 208, 209, 203, 
+	203, 203, 210, 203, 203, 211, 203, 205, 
+	213, 213, 6, 1, 208, 209, 203, 203, 
+	203, 210, 203, 203, 211, 203, 214, 203, 
+	203, 203, 19, 215, 203, 1, 208, 209, 
+	203, 203, 203, 216, 203, 214, 203, 217, 
+	218, 219, 220, 6, 1, 208, 209, 203, 
+	203, 36, 221, 203, 203, 211, 203, 222, 
+	218, 223, 223, 6, 1, 208, 209, 203, 
+	203, 203, 221, 203, 203, 211, 203, 218, 
+	223, 223, 6, 1, 208, 209, 203, 203, 
+	203, 221, 203, 203, 211, 203, 224, 203, 
+	203, 203, 19, 225, 203, 1, 208, 209, 
+	203, 203, 203, 216, 203, 224, 203, 226, 
+	227, 228, 229, 6, 1, 208, 209, 203, 
+	203, 34, 230, 203, 203, 211, 203, 231, 
+	227, 232, 232, 6, 1, 208, 209, 203, 
+	203, 203, 230, 203, 203, 211, 203, 227, 
+	232, 232, 6, 1, 208, 209, 203, 203, 
+	203, 230, 203, 203, 211, 203, 233, 203, 
+	203, 203, 19, 234, 203, 1, 208, 209, 
+	203, 203, 203, 216, 203, 233, 203, 235, 
+	236, 237, 238, 6, 1, 208, 209, 203, 
+	203, 32, 239, 203, 203, 211, 203, 240, 
+	236, 241, 241, 6, 1, 208, 209, 203, 
+	203, 203, 239, 203, 203, 211, 203, 236, 
+	241, 241, 6, 1, 208, 209, 203, 203, 
+	203, 239, 203, 203, 211, 203, 242, 203, 
+	203, 203, 19, 243, 203, 1, 208, 209, 
+	203, 203, 203, 216, 203, 242, 203, 244, 
+	245, 246, 247, 6, 1, 208, 209, 203, 
+	203, 30, 248, 203, 203, 211, 203, 249, 
+	245, 250, 250, 6, 1, 208, 209, 203, 
+	203, 203, 248, 203, 203, 211, 203, 245, 
+	250, 250, 6, 1, 208, 209, 203, 203, 
+	203, 248, 203, 203, 211, 203, 19, 251, 
+	203, 1, 208, 209, 203, 203, 203, 216, 
+	203, 252, 252, 203, 1, 208, 209, 203, 
+	203, 203, 216, 203, 253, 203, 203, 254, 
+	208, 209, 203, 208, 209, 203, 255, 203, 
+	208, 256, 203, 208, 257, 203, 208, 203, 
+	253, 203, 203, 203, 208, 209, 203, 258, 
+	203, 259, 260, 203, 1, 208, 209, 203, 
+	203, 4, 203, 3, 203, 252, 252, 203, 
+	1, 208, 209, 203, 252, 252, 203, 1, 
+	208, 209, 203, 258, 203, 252, 252, 203, 
+	1, 208, 209, 203, 258, 203, 259, 252, 
+	203, 1, 208, 209, 203, 203, 4, 203, 
+	19, 203, 261, 261, 6, 1, 208, 209, 
+	203, 203, 203, 216, 203, 262, 28, 263, 
+	264, 9, 1, 208, 209, 203, 203, 203, 
+	216, 203, 28, 263, 264, 9, 1, 208, 
+	209, 203, 203, 203, 216, 203, 263, 263, 
+	9, 1, 208, 209, 203, 203, 203, 216, 
+	203, 265, 25, 266, 267, 12, 1, 208, 
+	209, 203, 203, 203, 216, 203, 25, 266, 
+	267, 12, 1, 208, 209, 203, 203, 203, 
+	216, 203, 266, 266, 12, 1, 208, 209, 
+	203, 203, 203, 216, 203, 268, 22, 269, 
+	270, 15, 1, 208, 209, 203, 203, 203, 
+	216, 203, 22, 269, 270, 15, 1, 208, 
+	209, 203, 203, 203, 216, 203, 269, 269, 
+	15, 1, 208, 209, 203, 203, 203, 216, 
+	203, 271, 19, 252, 272, 203, 1, 208, 
+	209, 203, 203, 203, 216, 203, 19, 252, 
+	272, 203, 1, 208, 209, 203, 203, 203, 
+	216, 203, 252, 273, 203, 1, 208, 209, 
+	203, 203, 203, 216, 203, 19, 203, 252, 
+	252, 203, 1, 208, 209, 203, 203, 203, 
+	216, 203, 2, 3, 203, 203, 19, 251, 
+	203, 1, 208, 209, 203, 203, 203, 216, 
+	203, 2, 203, 245, 250, 250, 6, 1, 
+	208, 209, 203, 203, 203, 248, 203, 244, 
+	245, 250, 250, 6, 1, 208, 209, 203, 
+	203, 203, 248, 203, 203, 211, 203, 244, 
+	245, 246, 250, 6, 1, 208, 209, 203, 
+	203, 30, 248, 203, 203, 211, 203, 242, 
+	203, 274, 203, 261, 261, 6, 1, 208, 
+	209, 203, 203, 203, 216, 203, 242, 203, 
+	242, 203, 203, 203, 252, 252, 203, 1, 
+	208, 209, 203, 203, 203, 216, 203, 242, 
+	203, 242, 203, 203, 203, 252, 275, 203, 
+	1, 208, 209, 203, 203, 203, 216, 203, 
+	242, 203, 242, 203, 274, 203, 252, 252, 
+	203, 1, 208, 209, 203, 203, 203, 216, 
+	203, 242, 203, 242, 3, 203, 203, 19, 
+	243, 203, 1, 208, 209, 203, 203, 203, 
+	216, 203, 242, 203, 235, 236, 241, 241, 
+	6, 1, 208, 209, 203, 203, 203, 239, 
+	203, 203, 211, 203, 235, 236, 237, 241, 
+	6, 1, 208, 209, 203, 203, 32, 239, 
+	203, 203, 211, 203, 233, 203, 276, 203, 
+	261, 261, 6, 1, 208, 209, 203, 203, 
+	203, 216, 203, 233, 203, 233, 203, 203, 
+	203, 252, 252, 203, 1, 208, 209, 203, 
+	203, 203, 216, 203, 233, 203, 233, 203, 
+	203, 203, 252, 277, 203, 1, 208, 209, 
+	203, 203, 203, 216, 203, 233, 203, 233, 
+	203, 276, 203, 252, 252, 203, 1, 208, 
+	209, 203, 203, 203, 216, 203, 233, 203, 
+	233, 3, 203, 203, 19, 234, 203, 1, 
+	208, 209, 203, 203, 203, 216, 203, 233, 
+	203, 226, 227, 232, 232, 6, 1, 208, 
+	209, 203, 203, 203, 230, 203, 203, 211, 
+	203, 226, 227, 228, 232, 6, 1, 208, 
+	209, 203, 203, 34, 230, 203, 203, 211, 
+	203, 224, 203, 278, 203, 261, 261, 6, 
+	1, 208, 209, 203, 203, 203, 216, 203, 
+	224, 203, 224, 203, 203, 203, 252, 252, 
+	203, 1, 208, 209, 203, 203, 203, 216, 
+	203, 224, 203, 224, 203, 203, 203, 252, 
+	279, 203, 1, 208, 209, 203, 203, 203, 
+	216, 203, 224, 203, 224, 203, 278, 203, 
+	252, 252, 203, 1, 208, 209, 203, 203, 
+	203, 216, 203, 224, 203, 224, 3, 203, 
+	203, 19, 225, 203, 1, 208, 209, 203, 
+	203, 203, 216, 203, 224, 203, 217, 218, 
+	223, 223, 6, 1, 208, 209, 203, 203, 
+	203, 221, 203, 203, 211, 203, 217, 218, 
+	219, 223, 6, 1, 208, 209, 203, 203, 
+	36, 221, 203, 203, 211, 203, 214, 203, 
+	280, 203, 261, 261, 6, 1, 208, 209, 
+	203, 203, 203, 216, 203, 214, 203, 214, 
+	203, 203, 203, 252, 252, 203, 1, 208, 
+	209, 203, 203, 203, 216, 203, 214, 203, 
+	214, 203, 203, 203, 252, 281, 203, 1, 
+	208, 209, 203, 203, 203, 216, 203, 214, 
+	203, 214, 203, 280, 203, 252, 252, 203, 
+	1, 208, 209, 203, 203, 203, 216, 203, 
+	214, 203, 214, 3, 203, 203, 19, 215, 
+	203, 1, 208, 209, 203, 203, 203, 216, 
+	203, 214, 203, 204, 205, 213, 213, 6, 
+	1, 208, 209, 203, 203, 203, 210, 203, 
+	203, 211, 203, 204, 205, 206, 213, 6, 
+	1, 208, 209, 203, 203, 38, 210, 203, 
+	203, 211, 203, 283, 284, 285, 286, 45, 
+	40, 287, 288, 282, 282, 77, 289, 282, 
+	282, 290, 282, 291, 284, 292, 286, 45, 
+	40, 287, 288, 282, 282, 282, 289, 282, 
+	282, 290, 282, 284, 292, 286, 45, 40, 
+	287, 288, 282, 282, 282, 289, 282, 282, 
+	290, 282, 293, 282, 282, 282, 58, 294, 
+	282, 40, 287, 288, 282, 282, 282, 295, 
+	282, 293, 282, 296, 297, 298, 299, 45, 
+	40, 287, 288, 282, 282, 75, 300, 282, 
+	282, 290, 282, 301, 297, 302, 302, 45, 
+	40, 287, 288, 282, 282, 282, 300, 282, 
+	282, 290, 282, 297, 302, 302, 45, 40, 
+	287, 288, 282, 282, 282, 300, 282, 282, 
+	290, 282, 303, 282, 282, 282, 58, 304, 
+	282, 40, 287, 288, 282, 282, 282, 295, 
+	282, 303, 282, 305, 306, 307, 308, 45, 
+	40, 287, 288, 282, 282, 73, 309, 282, 
+	282, 290, 282, 310, 306, 311, 311, 45, 
+	40, 287, 288, 282, 282, 282, 309, 282, 
+	282, 290, 282, 306, 311, 311, 45, 40, 
+	287, 288, 282, 282, 282, 309, 282, 282, 
+	290, 282, 312, 282, 282, 282, 58, 313, 
+	282, 40, 287, 288, 282, 282, 282, 295, 
+	282, 312, 282, 314, 315, 316, 317, 45, 
+	40, 287, 288, 282, 282, 71, 318, 282, 
+	282, 290, 282, 319, 315, 320, 320, 45, 
+	40, 287, 288, 282, 282, 282, 318, 282, 
+	282, 290, 282, 315, 320, 320, 45, 40, 
+	287, 288, 282, 282, 282, 318, 282, 282, 
+	290, 282, 321, 282, 282, 282, 58, 322, 
+	282, 40, 287, 288, 282, 282, 282, 295, 
+	282, 321, 282, 323, 324, 325, 326, 45, 
+	40, 287, 288, 282, 282, 69, 327, 282, 
+	282, 290, 282, 328, 324, 329, 329, 45, 
+	40, 287, 288, 282, 282, 282, 327, 282, 
+	282, 290, 282, 324, 329, 329, 45, 40, 
+	287, 288, 282, 282, 282, 327, 282, 282, 
+	290, 282, 58, 330, 282, 40, 287, 288, 
+	282, 282, 282, 295, 282, 331, 331, 282, 
+	40, 287, 288, 282, 282, 282, 295, 282, 
+	332, 282, 282, 333, 287, 288, 282, 287, 
+	288, 282, 334, 282, 287, 335, 282, 287, 
+	336, 282, 287, 282, 332, 282, 282, 282, 
+	287, 288, 282, 337, 282, 338, 339, 282, 
+	40, 287, 288, 282, 282, 43, 282, 42, 
+	282, 331, 331, 282, 40, 287, 288, 282, 
+	331, 331, 282, 40, 287, 288, 282, 337, 
+	282, 331, 331, 282, 40, 287, 288, 282, 
+	337, 282, 338, 331, 282, 40, 287, 288, 
+	282, 282, 43, 282, 58, 282, 340, 340, 
+	45, 40, 287, 288, 282, 282, 282, 295, 
+	282, 341, 67, 342, 343, 48, 40, 287, 
+	288, 282, 282, 282, 295, 282, 67, 342, 
+	343, 48, 40, 287, 288, 282, 282, 282, 
+	295, 282, 342, 342, 48, 40, 287, 288, 
+	282, 282, 282, 295, 282, 344, 64, 345, 
+	346, 51, 40, 287, 288, 282, 282, 282, 
+	295, 282, 64, 345, 346, 51, 40, 287, 
+	288, 282, 282, 282, 295, 282, 345, 345, 
+	51, 40, 287, 288, 282, 282, 282, 295, 
+	282, 347, 61, 348, 349, 54, 40, 287, 
+	288, 282, 282, 282, 295, 282, 61, 348, 
+	349, 54, 40, 287, 288, 282, 282, 282, 
+	295, 282, 348, 348, 54, 40, 287, 288, 
+	282, 282, 282, 295, 282, 350, 58, 331, 
+	351, 282, 40, 287, 288, 282, 282, 282, 
+	295, 282, 58, 331, 351, 282, 40, 287, 
+	288, 282, 282, 282, 295, 282, 331, 352, 
+	282, 40, 287, 288, 282, 282, 282, 295, 
+	282, 58, 282, 331, 331, 282, 40, 287, 
+	288, 282, 282, 282, 295, 282, 41, 42, 
+	282, 282, 58, 330, 282, 40, 287, 288, 
+	282, 282, 282, 295, 282, 41, 282, 324, 
+	329, 329, 45, 40, 287, 288, 282, 282, 
+	282, 327, 282, 323, 324, 329, 329, 45, 
+	40, 287, 288, 282, 282, 282, 327, 282, 
+	282, 290, 282, 323, 324, 325, 329, 45, 
+	40, 287, 288, 282, 282, 69, 327, 282, 
+	282, 290, 282, 321, 282, 353, 282, 340, 
+	340, 45, 40, 287, 288, 282, 282, 282, 
+	295, 282, 321, 282, 321, 282, 282, 282, 
+	331, 331, 282, 40, 287, 288, 282, 282, 
+	282, 295, 282, 321, 282, 321, 282, 282, 
+	282, 331, 354, 282, 40, 287, 288, 282, 
+	282, 282, 295, 282, 321, 282, 321, 282, 
+	353, 282, 331, 331, 282, 40, 287, 288, 
+	282, 282, 282, 295, 282, 321, 282, 321, 
+	42, 282, 282, 58, 322, 282, 40, 287, 
+	288, 282, 282, 282, 295, 282, 321, 282, 
+	314, 315, 320, 320, 45, 40, 287, 288, 
+	282, 282, 282, 318, 282, 282, 290, 282, 
+	314, 315, 316, 320, 45, 40, 287, 288, 
+	282, 282, 71, 318, 282, 282, 290, 282, 
+	312, 282, 355, 282, 340, 340, 45, 40, 
+	287, 288, 282, 282, 282, 295, 282, 312, 
+	282, 312, 282, 282, 282, 331, 331, 282, 
+	40, 287, 288, 282, 282, 282, 295, 282, 
+	312, 282, 312, 282, 282, 282, 331, 356, 
+	282, 40, 287, 288, 282, 282, 282, 295, 
+	282, 312, 282, 312, 282, 355, 282, 331, 
+	331, 282, 40, 287, 288, 282, 282, 282, 
+	295, 282, 312, 282, 312, 42, 282, 282, 
+	58, 313, 282, 40, 287, 288, 282, 282, 
+	282, 295, 282, 312, 282, 305, 306, 311, 
+	311, 45, 40, 287, 288, 282, 282, 282, 
+	309, 282, 282, 290, 282, 305, 306, 307, 
+	311, 45, 40, 287, 288, 282, 282, 73, 
+	309, 282, 282, 290, 282, 303, 282, 357, 
+	282, 340, 340, 45, 40, 287, 288, 282, 
+	282, 282, 295, 282, 303, 282, 303, 282, 
+	282, 282, 331, 331, 282, 40, 287, 288, 
+	282, 282, 282, 295, 282, 303, 282, 303, 
+	282, 282, 282, 331, 358, 282, 40, 287, 
+	288, 282, 282, 282, 295, 282, 303, 282, 
+	303, 282, 357, 282, 331, 331, 282, 40, 
+	287, 288, 282, 282, 282, 295, 282, 303, 
+	282, 303, 42, 282, 282, 58, 304, 282, 
+	40, 287, 288, 282, 282, 282, 295, 282, 
+	303, 282, 296, 297, 302, 302, 45, 40, 
+	287, 288, 282, 282, 282, 300, 282, 282, 
+	290, 282, 296, 297, 298, 302, 45, 40, 
+	287, 288, 282, 282, 75, 300, 282, 282, 
+	290, 282, 293, 282, 359, 282, 340, 340, 
+	45, 40, 287, 288, 282, 282, 282, 295, 
+	282, 293, 282, 293, 282, 282, 282, 331, 
+	331, 282, 40, 287, 288, 282, 282, 282, 
+	295, 282, 293, 282, 293, 282, 282, 282, 
+	331, 360, 282, 40, 287, 288, 282, 282, 
+	282, 295, 282, 293, 282, 293, 282, 359, 
+	282, 331, 331, 282, 40, 287, 288, 282, 
+	282, 282, 295, 282, 293, 282, 76, 44, 
+	44, 45, 40, 282, 282, 282, 282, 282, 
+	76, 282, 293, 42, 282, 282, 58, 294, 
+	282, 40, 287, 288, 282, 282, 282, 295, 
+	282, 293, 282, 283, 284, 292, 286, 45, 
+	40, 287, 288, 282, 282, 282, 289, 282, 
+	282, 290, 282, 362, 191, 363, 363, 84, 
+	79, 194, 195, 361, 361, 361, 197, 361, 
+	361, 200, 361, 191, 363, 363, 84, 79, 
+	194, 195, 361, 361, 361, 197, 361, 361, 
+	200, 361, 364, 361, 361, 361, 98, 365, 
+	361, 79, 194, 195, 361, 361, 361, 366, 
+	361, 364, 361, 367, 368, 369, 370, 84, 
+	79, 194, 195, 361, 361, 115, 371, 361, 
+	361, 200, 361, 372, 368, 373, 373, 84, 
+	79, 194, 195, 361, 361, 361, 371, 361, 
+	361, 200, 361, 368, 373, 373, 84, 79, 
+	194, 195, 361, 361, 361, 371, 361, 361, 
+	200, 361, 374, 361, 361, 361, 98, 375, 
+	361, 79, 194, 195, 361, 361, 361, 366, 
+	361, 374, 361, 376, 377, 378, 379, 84, 
+	79, 194, 195, 361, 361, 113, 380, 361, 
+	361, 200, 361, 381, 377, 382, 382, 84, 
+	79, 194, 195, 361, 361, 361, 380, 361, 
+	361, 200, 361, 377, 382, 382, 84, 79, 
+	194, 195, 361, 361, 361, 380, 361, 361, 
+	200, 361, 383, 361, 361, 361, 98, 384, 
+	361, 79, 194, 195, 361, 361, 361, 366, 
+	361, 383, 361, 385, 386, 387, 388, 84, 
+	79, 194, 195, 361, 361, 111, 389, 361, 
+	361, 200, 361, 390, 386, 391, 391, 84, 
+	79, 194, 195, 361, 361, 361, 389, 361, 
+	361, 200, 361, 386, 391, 391, 84, 79, 
+	194, 195, 361, 361, 361, 389, 361, 361, 
+	200, 361, 392, 361, 361, 361, 98, 393, 
+	361, 79, 194, 195, 361, 361, 361, 366, 
+	361, 392, 361, 394, 395, 396, 397, 84, 
+	79, 194, 195, 361, 361, 109, 398, 361, 
+	361, 200, 361, 399, 395, 400, 400, 84, 
+	79, 194, 195, 361, 361, 361, 398, 361, 
+	361, 200, 361, 395, 400, 400, 84, 79, 
+	194, 195, 361, 361, 361, 398, 361, 361, 
+	200, 361, 98, 401, 361, 79, 194, 195, 
+	361, 361, 361, 366, 361, 402, 402, 361, 
+	79, 194, 195, 361, 361, 361, 366, 361, 
+	403, 361, 361, 404, 194, 195, 361, 194, 
+	195, 361, 405, 361, 194, 406, 361, 194, 
+	407, 361, 194, 361, 403, 361, 361, 361, 
+	194, 195, 361, 408, 361, 409, 410, 361, 
+	79, 194, 195, 361, 361, 82, 361, 81, 
+	361, 402, 402, 361, 79, 194, 195, 361, 
+	402, 402, 361, 79, 194, 195, 361, 408, 
+	361, 402, 402, 361, 79, 194, 195, 361, 
+	408, 361, 409, 402, 361, 79, 194, 195, 
+	361, 361, 82, 361, 98, 361, 411, 411, 
+	84, 79, 194, 195, 361, 361, 361, 366, 
+	361, 412, 107, 413, 414, 88, 79, 194, 
+	195, 361, 361, 361, 366, 361, 107, 413, 
+	414, 88, 79, 194, 195, 361, 361, 361, 
+	366, 361, 413, 413, 88, 79, 194, 195, 
+	361, 361, 361, 366, 361, 415, 104, 416, 
+	417, 91, 79, 194, 195, 361, 361, 361, 
+	366, 361, 104, 416, 417, 91, 79, 194, 
+	195, 361, 361, 361, 366, 361, 416, 416, 
+	91, 79, 194, 195, 361, 361, 361, 366, 
+	361, 418, 101, 419, 420, 94, 79, 194, 
+	195, 361, 361, 361, 366, 361, 101, 419, 
+	420, 94, 79, 194, 195, 361, 361, 361, 
+	366, 361, 419, 419, 94, 79, 194, 195, 
+	361, 361, 361, 366, 361, 421, 98, 402, 
+	422, 361, 79, 194, 195, 361, 361, 361, 
+	366, 361, 98, 402, 422, 361, 79, 194, 
+	195, 361, 361, 361, 366, 361, 402, 423, 
+	361, 79, 194, 195, 361, 361, 361, 366, 
+	361, 98, 361, 402, 402, 361, 79, 194, 
+	195, 361, 361, 361, 366, 361, 80, 81, 
+	361, 361, 98, 401, 361, 79, 194, 195, 
+	361, 361, 361, 366, 361, 80, 361, 395, 
+	400, 400, 84, 79, 194, 195, 361, 361, 
+	361, 398, 361, 394, 395, 400, 400, 84, 
+	79, 194, 195, 361, 361, 361, 398, 361, 
+	361, 200, 361, 394, 395, 396, 400, 84, 
+	79, 194, 195, 361, 361, 109, 398, 361, 
+	361, 200, 361, 392, 361, 424, 361, 411, 
+	411, 84, 79, 194, 195, 361, 361, 361, 
+	366, 361, 392, 361, 392, 361, 361, 361, 
+	402, 402, 361, 79, 194, 195, 361, 361, 
+	361, 366, 361, 392, 361, 392, 361, 361, 
+	361, 402, 425, 361, 79, 194, 195, 361, 
+	361, 361, 366, 361, 392, 361, 392, 361, 
+	424, 361, 402, 402, 361, 79, 194, 195, 
+	361, 361, 361, 366, 361, 392, 361, 392, 
+	81, 361, 361, 98, 393, 361, 79, 194, 
+	195, 361, 361, 361, 366, 361, 392, 361, 
+	385, 386, 391, 391, 84, 79, 194, 195, 
+	361, 361, 361, 389, 361, 361, 200, 361, 
+	385, 386, 387, 391, 84, 79, 194, 195, 
+	361, 361, 111, 389, 361, 361, 200, 361, 
+	383, 361, 426, 361, 411, 411, 84, 79, 
+	194, 195, 361, 361, 361, 366, 361, 383, 
+	361, 383, 361, 361, 361, 402, 402, 361, 
+	79, 194, 195, 361, 361, 361, 366, 361, 
+	383, 361, 383, 361, 361, 361, 402, 427, 
+	361, 79, 194, 195, 361, 361, 361, 366, 
+	361, 383, 361, 383, 361, 426, 361, 402, 
+	402, 361, 79, 194, 195, 361, 361, 361, 
+	366, 361, 383, 361, 383, 81, 361, 361, 
+	98, 384, 361, 79, 194, 195, 361, 361, 
+	361, 366, 361, 383, 361, 376, 377, 382, 
+	382, 84, 79, 194, 195, 361, 361, 361, 
+	380, 361, 361, 200, 361, 376, 377, 378, 
+	382, 84, 79, 194, 195, 361, 361, 113, 
+	380, 361, 361, 200, 361, 374, 361, 428, 
+	361, 411, 411, 84, 79, 194, 195, 361, 
+	361, 361, 366, 361, 374, 361, 374, 361, 
+	361, 361, 402, 402, 361, 79, 194, 195, 
+	361, 361, 361, 366, 361, 374, 361, 374, 
+	361, 361, 361, 402, 429, 361, 79, 194, 
+	195, 361, 361, 361, 366, 361, 374, 361, 
+	374, 361, 428, 361, 402, 402, 361, 79, 
+	194, 195, 361, 361, 361, 366, 361, 374, 
+	361, 374, 81, 361, 361, 98, 375, 361, 
+	79, 194, 195, 361, 361, 361, 366, 361, 
+	374, 361, 367, 368, 373, 373, 84, 79, 
+	194, 195, 361, 361, 361, 371, 361, 361, 
+	200, 361, 367, 368, 369, 373, 84, 79, 
+	194, 195, 361, 361, 115, 371, 361, 361, 
+	200, 361, 364, 361, 430, 361, 411, 411, 
+	84, 79, 194, 195, 361, 361, 361, 366, 
+	361, 364, 361, 364, 361, 361, 361, 402, 
+	402, 361, 79, 194, 195, 361, 361, 361, 
+	366, 361, 364, 361, 364, 361, 361, 361, 
+	402, 431, 361, 79, 194, 195, 361, 361, 
+	361, 366, 361, 364, 361, 364, 361, 430, 
+	361, 402, 402, 361, 79, 194, 195, 361, 
+	361, 361, 366, 361, 364, 361, 364, 81, 
+	361, 361, 98, 365, 361, 79, 194, 195, 
+	361, 361, 361, 366, 361, 364, 361, 116, 
+	83, 83, 84, 79, 432, 432, 432, 432, 
+	156, 116, 432, 190, 191, 363, 363, 84, 
+	79, 194, 195, 361, 361, 361, 197, 361, 
+	361, 200, 361, 116, 83, 83, 84, 79, 
+	432, 432, 432, 432, 432, 116, 432, 434, 
+	435, 436, 437, 123, 118, 438, 439, 433, 
+	433, 155, 440, 433, 433, 441, 433, 442, 
+	435, 437, 437, 123, 118, 438, 439, 433, 
+	433, 433, 440, 433, 433, 441, 433, 435, 
+	437, 437, 123, 118, 438, 439, 433, 433, 
+	433, 440, 433, 433, 441, 433, 443, 433, 
+	433, 433, 136, 444, 433, 118, 438, 439, 
+	433, 433, 433, 445, 433, 443, 433, 446, 
+	447, 448, 449, 123, 118, 438, 439, 433, 
+	433, 153, 450, 433, 433, 441, 433, 451, 
+	447, 452, 452, 123, 118, 438, 439, 433, 
+	433, 433, 450, 433, 433, 441, 433, 447, 
+	452, 452, 123, 118, 438, 439, 433, 433, 
+	433, 450, 433, 433, 441, 433, 453, 433, 
+	433, 433, 136, 454, 433, 118, 438, 439, 
+	433, 433, 433, 445, 433, 453, 433, 455, 
+	456, 457, 458, 123, 118, 438, 439, 433, 
+	433, 151, 459, 433, 433, 441, 433, 460, 
+	456, 461, 461, 123, 118, 438, 439, 433, 
+	433, 433, 459, 433, 433, 441, 433, 456, 
+	461, 461, 123, 118, 438, 439, 433, 433, 
+	433, 459, 433, 433, 441, 433, 462, 433, 
+	433, 433, 136, 463, 433, 118, 438, 439, 
+	433, 433, 433, 445, 433, 462, 433, 464, 
+	465, 466, 467, 123, 118, 438, 439, 433, 
+	433, 149, 468, 433, 433, 441, 433, 469, 
+	465, 470, 470, 123, 118, 438, 439, 433, 
+	433, 433, 468, 433, 433, 441, 433, 465, 
+	470, 470, 123, 118, 438, 439, 433, 433, 
+	433, 468, 433, 433, 441, 433, 471, 433, 
+	433, 433, 136, 472, 433, 118, 438, 439, 
+	433, 433, 433, 445, 433, 471, 433, 473, 
+	474, 475, 476, 123, 118, 438, 439, 433, 
+	433, 147, 477, 433, 433, 441, 433, 478, 
+	474, 479, 479, 123, 118, 438, 439, 433, 
+	433, 433, 477, 433, 433, 441, 433, 474, 
+	479, 479, 123, 118, 438, 439, 433, 433, 
+	433, 477, 433, 433, 441, 433, 136, 480, 
+	433, 118, 438, 439, 433, 433, 433, 445, 
+	433, 481, 481, 433, 118, 438, 439, 433, 
+	433, 433, 445, 433, 482, 433, 433, 483, 
+	438, 439, 433, 438, 439, 433, 484, 433, 
+	438, 485, 433, 438, 486, 433, 438, 433, 
+	482, 433, 433, 433, 438, 439, 433, 487, 
+	433, 488, 489, 433, 118, 438, 439, 433, 
+	433, 121, 433, 120, 433, 481, 481, 433, 
+	118, 438, 439, 433, 481, 481, 433, 118, 
+	438, 439, 433, 487, 433, 481, 481, 433, 
+	118, 438, 439, 433, 487, 433, 488, 481, 
+	433, 118, 438, 439, 433, 433, 121, 433, 
+	136, 433, 490, 490, 123, 118, 438, 439, 
+	433, 433, 433, 445, 433, 491, 145, 492, 
+	493, 126, 118, 438, 439, 433, 433, 433, 
+	445, 433, 145, 492, 493, 126, 118, 438, 
+	439, 433, 433, 433, 445, 433, 492, 492, 
+	126, 118, 438, 439, 433, 433, 433, 445, 
+	433, 494, 142, 495, 496, 129, 118, 438, 
+	439, 433, 433, 433, 445, 433, 142, 495, 
+	496, 129, 118, 438, 439, 433, 433, 433, 
+	445, 433, 495, 495, 129, 118, 438, 439, 
+	433, 433, 433, 445, 433, 497, 139, 498, 
+	499, 132, 118, 438, 439, 433, 433, 433, 
+	445, 433, 139, 498, 499, 132, 118, 438, 
+	439, 433, 433, 433, 445, 433, 498, 498, 
+	132, 118, 438, 439, 433, 433, 433, 445, 
+	433, 500, 136, 481, 501, 433, 118, 438, 
+	439, 433, 433, 433, 445, 433, 136, 481, 
+	501, 433, 118, 438, 439, 433, 433, 433, 
+	445, 433, 481, 502, 433, 118, 438, 439, 
+	433, 433, 433, 445, 433, 136, 433, 481, 
+	481, 433, 118, 438, 439, 433, 433, 433, 
+	445, 433, 119, 120, 433, 433, 136, 480, 
+	433, 118, 438, 439, 433, 433, 433, 445, 
+	433, 119, 433, 474, 479, 479, 123, 118, 
+	438, 439, 433, 433, 433, 477, 433, 473, 
+	474, 479, 479, 123, 118, 438, 439, 433, 
+	433, 433, 477, 433, 433, 441, 433, 473, 
+	474, 475, 479, 123, 118, 438, 439, 433, 
+	433, 147, 477, 433, 433, 441, 433, 471, 
+	433, 503, 433, 490, 490, 123, 118, 438, 
+	439, 433, 433, 433, 445, 433, 471, 433, 
+	471, 433, 433, 433, 481, 481, 433, 118, 
+	438, 439, 433, 433, 433, 445, 433, 471, 
+	433, 471, 433, 433, 433, 481, 504, 433, 
+	118, 438, 439, 433, 433, 433, 445, 433, 
+	471, 433, 471, 433, 503, 433, 481, 481, 
+	433, 118, 438, 439, 433, 433, 433, 445, 
+	433, 471, 433, 471, 120, 433, 433, 136, 
+	472, 433, 118, 438, 439, 433, 433, 433, 
+	445, 433, 471, 433, 464, 465, 470, 470, 
+	123, 118, 438, 439, 433, 433, 433, 468, 
+	433, 433, 441, 433, 464, 465, 466, 470, 
+	123, 118, 438, 439, 433, 433, 149, 468, 
+	433, 433, 441, 433, 462, 433, 505, 433, 
+	490, 490, 123, 118, 438, 439, 433, 433, 
+	433, 445, 433, 462, 433, 462, 433, 433, 
+	433, 481, 481, 433, 118, 438, 439, 433, 
+	433, 433, 445, 433, 462, 433, 462, 433, 
+	433, 433, 481, 506, 433, 118, 438, 439, 
+	433, 433, 433, 445, 433, 462, 433, 462, 
+	433, 505, 433, 481, 481, 433, 118, 438, 
+	439, 433, 433, 433, 445, 433, 462, 433, 
+	462, 120, 433, 433, 136, 463, 433, 118, 
+	438, 439, 433, 433, 433, 445, 433, 462, 
+	433, 455, 456, 461, 461, 123, 118, 438, 
+	439, 433, 433, 433, 459, 433, 433, 441, 
+	433, 455, 456, 457, 461, 123, 118, 438, 
+	439, 433, 433, 151, 459, 433, 433, 441, 
+	433, 453, 433, 507, 433, 490, 490, 123, 
+	118, 438, 439, 433, 433, 433, 445, 433, 
+	453, 433, 453, 433, 433, 433, 481, 481, 
+	433, 118, 438, 439, 433, 433, 433, 445, 
+	433, 453, 433, 453, 433, 433, 433, 481, 
+	508, 433, 118, 438, 439, 433, 433, 433, 
+	445, 433, 453, 433, 453, 433, 507, 433, 
+	481, 481, 433, 118, 438, 439, 433, 433, 
+	433, 445, 433, 453, 433, 453, 120, 433, 
+	433, 136, 454, 433, 118, 438, 439, 433, 
+	433, 433, 445, 433, 453, 433, 446, 447, 
+	452, 452, 123, 118, 438, 439, 433, 433, 
+	433, 450, 433, 433, 441, 433, 446, 447, 
+	448, 452, 123, 118, 438, 439, 433, 433, 
+	153, 450, 433, 433, 441, 433, 443, 433, 
+	509, 433, 490, 490, 123, 118, 438, 439, 
+	433, 433, 433, 445, 433, 443, 433, 443, 
+	433, 433, 433, 481, 481, 433, 118, 438, 
+	439, 433, 433, 433, 445, 433, 443, 433, 
+	443, 433, 433, 433, 481, 510, 433, 118, 
+	438, 439, 433, 433, 433, 445, 433, 443, 
+	433, 443, 433, 509, 433, 481, 481, 433, 
+	118, 438, 439, 433, 433, 433, 445, 433, 
+	443, 433, 443, 120, 433, 433, 136, 444, 
+	433, 118, 438, 439, 433, 433, 433, 445, 
+	433, 443, 433, 434, 435, 437, 437, 123, 
+	118, 438, 439, 433, 433, 433, 440, 433, 
+	433, 441, 433, 188, 189, 190, 191, 511, 
+	363, 84, 79, 194, 195, 196, 196, 156, 
+	197, 361, 188, 200, 361, 204, 512, 206, 
+	207, 6, 1, 208, 209, 203, 203, 38, 
+	210, 203, 203, 211, 203, 214, 189, 190, 
+	191, 513, 514, 84, 157, 515, 516, 203, 
+	196, 156, 517, 203, 214, 200, 203, 116, 
+	518, 518, 84, 157, 208, 209, 203, 203, 
+	156, 519, 203, 520, 203, 203, 521, 515, 
+	516, 203, 515, 516, 203, 255, 203, 515, 
+	522, 203, 515, 523, 203, 515, 203, 520, 
+	203, 203, 203, 515, 516, 203, 524, 3, 
+	361, 361, 402, 431, 361, 79, 194, 195, 
+	361, 361, 361, 366, 361, 524, 361, 525, 
+	368, 526, 527, 84, 157, 515, 516, 203, 
+	203, 158, 371, 203, 203, 200, 203, 528, 
+	368, 529, 529, 84, 157, 515, 516, 203, 
+	203, 203, 371, 203, 203, 200, 203, 368, 
+	529, 529, 84, 157, 515, 516, 203, 203, 
+	203, 371, 203, 203, 200, 203, 525, 368, 
+	529, 529, 84, 157, 515, 516, 203, 203, 
+	203, 371, 203, 203, 200, 203, 525, 368, 
+	526, 529, 84, 157, 515, 516, 203, 203, 
+	158, 371, 203, 203, 200, 203, 214, 203, 
+	280, 116, 530, 530, 160, 157, 208, 209, 
+	203, 203, 203, 519, 203, 214, 203, 531, 
+	184, 532, 533, 162, 157, 515, 516, 203, 
+	203, 203, 534, 203, 184, 532, 533, 162, 
+	157, 515, 516, 203, 203, 203, 534, 203, 
+	532, 532, 162, 157, 515, 516, 203, 203, 
+	203, 534, 203, 535, 181, 536, 537, 165, 
+	157, 515, 516, 203, 203, 203, 534, 203, 
+	181, 536, 537, 165, 157, 515, 516, 203, 
+	203, 203, 534, 203, 536, 536, 165, 157, 
+	515, 516, 203, 203, 203, 534, 203, 538, 
+	178, 539, 540, 168, 157, 515, 516, 203, 
+	203, 203, 534, 203, 178, 539, 540, 168, 
+	157, 515, 516, 203, 203, 203, 534, 203, 
+	539, 539, 168, 157, 515, 516, 203, 203, 
+	203, 534, 203, 541, 175, 542, 543, 203, 
+	157, 515, 516, 203, 203, 203, 534, 203, 
+	175, 542, 543, 203, 157, 515, 516, 203, 
+	203, 203, 534, 203, 542, 542, 203, 157, 
+	515, 516, 203, 203, 203, 534, 203, 544, 
+	203, 545, 546, 203, 157, 515, 516, 203, 
+	203, 172, 203, 171, 203, 542, 542, 203, 
+	157, 515, 516, 203, 542, 542, 203, 157, 
+	515, 516, 203, 544, 203, 542, 542, 203, 
+	157, 515, 516, 203, 544, 203, 545, 542, 
+	203, 157, 515, 516, 203, 203, 172, 203, 
+	524, 171, 361, 361, 98, 365, 361, 79, 
+	194, 195, 361, 361, 361, 366, 361, 524, 
+	361, 548, 547, 549, 549, 547, 186, 550, 
+	551, 547, 549, 549, 547, 186, 550, 551, 
+	547, 552, 547, 547, 553, 550, 551, 547, 
+	550, 551, 547, 554, 547, 550, 555, 547, 
+	550, 556, 547, 550, 547, 552, 547, 547, 
+	547, 550, 551, 547, 188, 432, 432, 432, 
+	432, 432, 432, 432, 432, 432, 196, 432, 
+	432, 432, 432, 188, 432, 0
 };
 
 static const short _indic_syllable_machine_trans_targs[] = {
 	178, 200, 207, 209, 210, 4, 213, 5, 
 	7, 216, 8, 10, 219, 11, 13, 222, 
 	14, 16, 17, 199, 19, 20, 221, 22, 
 	23, 218, 25, 26, 215, 224, 228, 232, 
 	235, 239, 242, 246, 249, 253, 256, 178, 
@@ -1009,61 +1011,61 @@ static const short _indic_syllable_machi
 	436, 129, 130, 458, 132, 133, 455, 135, 
 	136, 452, 461, 465, 469, 472, 476, 479, 
 	483, 486, 490, 493, 414, 498, 509, 152, 
 	512, 154, 515, 155, 157, 518, 158, 160, 
 	521, 161, 524, 526, 527, 166, 167, 523, 
 	169, 170, 520, 172, 173, 517, 175, 176, 
 	514, 178, 532, 178, 179, 258, 337, 339, 
 	413, 415, 359, 360, 416, 412, 494, 495, 
-	384, 530, 178, 180, 182, 36, 257, 202, 
-	203, 255, 227, 181, 35, 183, 251, 1, 
-	184, 186, 34, 250, 248, 185, 33, 187, 
-	244, 188, 190, 32, 243, 241, 189, 31, 
-	191, 237, 192, 194, 30, 236, 234, 193, 
-	29, 195, 230, 196, 198, 28, 229, 226, 
-	197, 27, 212, 0, 201, 206, 178, 204, 
-	205, 208, 2, 211, 3, 214, 6, 24, 
-	217, 9, 21, 220, 12, 18, 223, 15, 
-	225, 231, 233, 238, 240, 245, 247, 252, 
-	254, 178, 259, 261, 73, 334, 281, 282, 
-	335, 306, 260, 72, 262, 330, 38, 263, 
-	265, 71, 329, 327, 264, 70, 266, 323, 
-	267, 269, 69, 322, 320, 268, 68, 270, 
-	316, 271, 273, 67, 315, 313, 272, 66, 
-	274, 309, 275, 277, 65, 308, 305, 276, 
-	64, 291, 37, 280, 285, 178, 283, 284, 
-	287, 39, 290, 40, 293, 43, 61, 296, 
-	46, 58, 299, 49, 55, 302, 52, 304, 
-	310, 312, 317, 319, 324, 326, 331, 333, 
-	178, 338, 109, 340, 408, 75, 341, 343, 
-	108, 407, 405, 342, 107, 344, 401, 345, 
-	347, 106, 400, 398, 346, 105, 348, 394, 
-	349, 351, 104, 393, 391, 350, 103, 352, 
-	387, 353, 355, 102, 386, 383, 354, 101, 
-	369, 74, 358, 363, 178, 361, 362, 365, 
-	76, 368, 77, 371, 80, 98, 374, 83, 
-	95, 377, 86, 92, 380, 89, 382, 388, 
-	390, 395, 397, 402, 404, 409, 411, 178, 
-	178, 417, 419, 146, 145, 439, 440, 492, 
-	464, 418, 420, 488, 111, 421, 423, 144, 
-	487, 485, 422, 143, 424, 481, 425, 427, 
-	142, 480, 478, 426, 141, 428, 474, 429, 
-	431, 140, 473, 471, 430, 139, 432, 467, 
-	433, 435, 138, 466, 463, 434, 137, 449, 
-	110, 438, 443, 178, 441, 442, 445, 112, 
-	448, 113, 451, 116, 134, 454, 119, 131, 
-	457, 122, 128, 460, 125, 462, 468, 470, 
-	475, 477, 482, 484, 489, 491, 147, 496, 
-	497, 511, 500, 501, 529, 148, 505, 499, 
-	504, 502, 503, 506, 507, 150, 510, 508, 
-	149, 151, 513, 153, 174, 163, 516, 156, 
-	171, 519, 159, 168, 522, 162, 165, 525, 
-	164, 528, 178, 531, 177, 534, 535, 533, 
-	538, 178, 536, 537
+	384, 530, 539, 178, 180, 182, 36, 257, 
+	202, 203, 255, 227, 181, 35, 183, 251, 
+	1, 184, 186, 34, 250, 248, 185, 33, 
+	187, 244, 188, 190, 32, 243, 241, 189, 
+	31, 191, 237, 192, 194, 30, 236, 234, 
+	193, 29, 195, 230, 196, 198, 28, 229, 
+	226, 197, 27, 212, 0, 201, 206, 178, 
+	204, 205, 208, 2, 211, 3, 214, 6, 
+	24, 217, 9, 21, 220, 12, 18, 223, 
+	15, 225, 231, 233, 238, 240, 245, 247, 
+	252, 254, 178, 259, 261, 73, 334, 281, 
+	282, 335, 306, 260, 72, 262, 330, 38, 
+	263, 265, 71, 329, 327, 264, 70, 266, 
+	323, 267, 269, 69, 322, 320, 268, 68, 
+	270, 316, 271, 273, 67, 315, 313, 272, 
+	66, 274, 309, 275, 277, 65, 308, 305, 
+	276, 64, 291, 37, 280, 285, 178, 283, 
+	284, 287, 39, 290, 40, 293, 43, 61, 
+	296, 46, 58, 299, 49, 55, 302, 52, 
+	304, 310, 312, 317, 319, 324, 326, 331, 
+	333, 178, 338, 109, 340, 408, 75, 341, 
+	343, 108, 407, 405, 342, 107, 344, 401, 
+	345, 347, 106, 400, 398, 346, 105, 348, 
+	394, 349, 351, 104, 393, 391, 350, 103, 
+	352, 387, 353, 355, 102, 386, 383, 354, 
+	101, 369, 74, 358, 363, 178, 361, 362, 
+	365, 76, 368, 77, 371, 80, 98, 374, 
+	83, 95, 377, 86, 92, 380, 89, 382, 
+	388, 390, 395, 397, 402, 404, 409, 411, 
+	178, 178, 417, 419, 146, 145, 439, 440, 
+	492, 464, 418, 420, 488, 111, 421, 423, 
+	144, 487, 485, 422, 143, 424, 481, 425, 
+	427, 142, 480, 478, 426, 141, 428, 474, 
+	429, 431, 140, 473, 471, 430, 139, 432, 
+	467, 433, 435, 138, 466, 463, 434, 137, 
+	449, 110, 438, 443, 178, 441, 442, 445, 
+	112, 448, 113, 451, 116, 134, 454, 119, 
+	131, 457, 122, 128, 460, 125, 462, 468, 
+	470, 475, 477, 482, 484, 489, 491, 147, 
+	496, 497, 511, 500, 501, 529, 148, 505, 
+	499, 504, 502, 503, 506, 507, 150, 510, 
+	508, 149, 151, 513, 153, 174, 163, 516, 
+	156, 171, 519, 159, 168, 522, 162, 165, 
+	525, 164, 528, 178, 531, 177, 534, 535, 
+	533, 538, 178, 536, 537
 };
 
 static const char _indic_syllable_machine_trans_actions[] = {
 	1, 0, 2, 2, 2, 0, 2, 0, 
 	0, 2, 0, 0, 2, 0, 0, 2, 
 	0, 0, 0, 2, 0, 0, 2, 0, 
 	0, 2, 0, 0, 2, 2, 2, 2, 
 	2, 2, 2, 2, 2, 2, 2, 3, 
@@ -1082,61 +1084,61 @@ static const char _indic_syllable_machin
 	2, 0, 0, 2, 0, 0, 2, 0, 
 	0, 2, 2, 2, 2, 2, 2, 2, 
 	2, 2, 2, 2, 6, 0, 8, 0, 
 	2, 0, 2, 0, 0, 2, 0, 0, 
 	2, 0, 2, 2, 2, 0, 0, 2, 
 	0, 0, 2, 0, 0, 2, 0, 0, 
 	2, 9, 0, 12, 2, 2, 6, 2, 
 	13, 13, 0, 0, 2, 2, 6, 2, 
-	6, 2, 14, 2, 2, 0, 2, 0, 
+	6, 2, 0, 14, 2, 2, 0, 2, 
+	0, 0, 2, 2, 2, 0, 2, 2, 
+	0, 2, 2, 0, 2, 2, 2, 0, 
+	2, 2, 2, 2, 0, 2, 2, 2, 
+	0, 2, 2, 2, 2, 0, 2, 2, 
+	2, 0, 2, 2, 2, 2, 0, 2, 
+	2, 2, 0, 2, 0, 0, 0, 15, 
+	0, 0, 2, 0, 2, 0, 2, 0, 
+	0, 2, 0, 0, 2, 0, 0, 2, 
+	0, 2, 2, 2, 2, 2, 2, 2, 
+	2, 2, 16, 2, 2, 0, 2, 0, 
 	0, 2, 2, 2, 0, 2, 2, 0, 
 	2, 2, 0, 2, 2, 2, 0, 2, 
 	2, 2, 2, 0, 2, 2, 2, 0, 
 	2, 2, 2, 2, 0, 2, 2, 2, 
 	0, 2, 2, 2, 2, 0, 2, 2, 
-	2, 0, 2, 0, 0, 0, 15, 0, 
+	2, 0, 2, 0, 0, 0, 17, 0, 
 	0, 2, 0, 2, 0, 2, 0, 0, 
 	2, 0, 0, 2, 0, 0, 2, 0, 
 	2, 2, 2, 2, 2, 2, 2, 2, 
-	2, 16, 2, 2, 0, 2, 0, 0, 
-	2, 2, 2, 0, 2, 2, 0, 2, 
-	2, 0, 2, 2, 2, 0, 2, 2, 
-	2, 2, 0, 2, 2, 2, 0, 2, 
-	2, 2, 2, 0, 2, 2, 2, 0, 
-	2, 2, 2, 2, 0, 2, 2, 2, 
-	0, 2, 0, 0, 0, 17, 0, 0, 
-	2, 0, 2, 0, 2, 0, 0, 2, 
-	0, 0, 2, 0, 0, 2, 0, 2, 
-	2, 2, 2, 2, 2, 2, 2, 2, 
-	18, 6, 0, 6, 6, 0, 6, 2, 
-	0, 6, 2, 6, 0, 6, 6, 6, 
+	2, 18, 6, 0, 6, 6, 0, 6, 
 	2, 0, 6, 2, 6, 0, 6, 6, 
 	6, 2, 0, 6, 2, 6, 0, 6, 
 	6, 6, 2, 0, 6, 2, 6, 0, 
-	6, 0, 0, 0, 19, 0, 0, 2, 
-	0, 2, 0, 2, 0, 0, 2, 0, 
-	0, 2, 0, 0, 2, 0, 2, 2, 
-	2, 2, 2, 2, 2, 2, 2, 20, 
-	21, 2, 2, 0, 0, 0, 0, 2, 
-	2, 2, 2, 2, 0, 2, 2, 0, 
-	2, 2, 2, 0, 2, 2, 2, 2, 
+	6, 6, 6, 2, 0, 6, 2, 6, 
+	0, 6, 0, 0, 0, 19, 0, 0, 
+	2, 0, 2, 0, 2, 0, 0, 2, 
+	0, 0, 2, 0, 0, 2, 0, 2, 
+	2, 2, 2, 2, 2, 2, 2, 2, 
+	20, 21, 2, 2, 0, 0, 0, 0, 
+	2, 2, 2, 2, 2, 0, 2, 2, 
 	0, 2, 2, 2, 0, 2, 2, 2, 
 	2, 0, 2, 2, 2, 0, 2, 2, 
 	2, 2, 0, 2, 2, 2, 0, 2, 
-	0, 0, 0, 22, 0, 0, 2, 0, 
-	2, 0, 2, 0, 0, 2, 0, 0, 
-	2, 0, 0, 2, 0, 2, 2, 2, 
-	2, 2, 2, 2, 2, 2, 0, 0, 
-	8, 2, 0, 0, 2, 0, 2, 0, 
-	0, 0, 0, 8, 8, 0, 8, 8, 
-	0, 0, 2, 0, 0, 0, 2, 0, 
-	0, 2, 0, 0, 2, 0, 0, 2, 
-	0, 2, 23, 2, 0, 0, 0, 0, 
-	0, 24, 0, 0
+	2, 2, 2, 0, 2, 2, 2, 0, 
+	2, 0, 0, 0, 22, 0, 0, 2, 
+	0, 2, 0, 2, 0, 0, 2, 0, 
+	0, 2, 0, 0, 2, 0, 2, 2, 
+	2, 2, 2, 2, 2, 2, 2, 0, 
+	0, 8, 2, 0, 0, 2, 0, 2, 
+	0, 0, 0, 0, 8, 8, 0, 8, 
+	8, 0, 0, 2, 0, 0, 0, 2, 
+	0, 0, 2, 0, 0, 2, 0, 0, 
+	2, 0, 2, 23, 2, 0, 0, 0, 
+	0, 0, 24, 0, 0
 };
 
 static const char _indic_syllable_machine_to_state_actions[] = {
 	0, 0, 0, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
@@ -1197,17 +1199,17 @@ static const char _indic_syllable_machin
 	0, 0, 0, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0
+	0, 0, 0, 0
 };
 
 static const char _indic_syllable_machine_from_state_actions[] = {
 	0, 0, 0, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
@@ -1268,17 +1270,17 @@ static const char _indic_syllable_machin
 	0, 0, 0, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0
+	0, 0, 0, 0
 };
 
 static const short _indic_syllable_machine_eof_trans[] = {
 	1, 1, 1, 1, 1, 1, 1, 1, 
 	1, 1, 1, 1, 1, 1, 1, 1, 
 	1, 1, 1, 1, 1, 1, 1, 1, 
 	1, 1, 1, 1, 1, 1, 1, 1, 
 	1, 1, 1, 1, 1, 40, 40, 40, 
@@ -1294,76 +1296,76 @@ static const short _indic_syllable_machi
 	118, 118, 118, 118, 118, 118, 118, 118, 
 	118, 118, 118, 118, 118, 118, 118, 118, 
 	118, 118, 118, 118, 118, 118, 118, 118, 
 	118, 118, 118, 118, 118, 118, 118, 118, 
 	118, 118, 118, 79, 1, 1, 1, 1, 
 	1, 1, 1, 1, 1, 1, 1, 1, 
 	1, 1, 1, 1, 1, 1, 1, 1, 
 	1, 1, 1, 1, 1, 1, 1, 1, 
-	1, 186, 0, 203, 203, 203, 203, 203, 
-	203, 203, 203, 203, 203, 203, 203, 203, 
-	203, 203, 203, 203, 203, 203, 203, 203, 
-	203, 203, 203, 203, 203, 203, 203, 203, 
-	203, 203, 203, 203, 203, 203, 203, 203, 
-	203, 203, 203, 203, 203, 203, 203, 203, 
-	203, 203, 203, 203, 203, 203, 203, 203, 
-	203, 203, 203, 203, 203, 203, 203, 203, 
-	203, 203, 203, 203, 203, 203, 203, 203, 
-	203, 203, 203, 203, 203, 203, 203, 203, 
-	203, 203, 282, 282, 282, 282, 282, 282, 
-	282, 282, 282, 282, 282, 282, 282, 282, 
-	282, 282, 282, 282, 282, 282, 282, 282, 
-	282, 282, 282, 282, 282, 282, 282, 282, 
-	282, 282, 282, 282, 282, 282, 282, 282, 
-	282, 282, 282, 282, 282, 282, 282, 282, 
-	282, 282, 282, 282, 282, 282, 282, 282, 
-	282, 282, 282, 282, 282, 282, 282, 282, 
-	282, 282, 282, 282, 282, 282, 282, 282, 
-	282, 282, 282, 282, 282, 282, 282, 282, 
-	282, 361, 361, 361, 361, 361, 361, 361, 
-	361, 361, 361, 361, 361, 361, 361, 361, 
-	361, 361, 361, 361, 361, 361, 361, 361, 
-	361, 361, 361, 361, 361, 361, 361, 361, 
-	361, 361, 361, 361, 361, 361, 361, 361, 
-	361, 361, 361, 361, 361, 361, 361, 361, 
-	361, 361, 361, 361, 361, 361, 361, 361, 
-	361, 361, 361, 361, 361, 361, 361, 361, 
-	361, 361, 361, 361, 361, 361, 361, 361, 
-	361, 361, 361, 361, 361, 432, 361, 432, 
-	433, 433, 433, 433, 433, 433, 433, 433, 
-	433, 433, 433, 433, 433, 433, 433, 433, 
-	433, 433, 433, 433, 433, 433, 433, 433, 
-	433, 433, 433, 433, 433, 433, 433, 433, 
-	433, 433, 433, 433, 433, 433, 433, 433, 
-	433, 433, 433, 433, 433, 433, 433, 433, 
-	433, 433, 433, 433, 433, 433, 433, 433, 
-	433, 433, 433, 433, 433, 433, 433, 433, 
-	433, 433, 433, 433, 433, 433, 433, 433, 
-	433, 433, 433, 433, 433, 433, 361, 203, 
-	203, 203, 203, 203, 203, 203, 203, 203, 
-	203, 361, 203, 203, 203, 203, 203, 203, 
-	203, 203, 203, 203, 203, 203, 203, 203, 
-	203, 203, 203, 203, 203, 203, 203, 203, 
-	203, 361, 547, 547, 547, 547, 547, 547, 
-	547, 547, 547
+	1, 186, 0, 204, 204, 204, 204, 204, 
+	204, 204, 204, 204, 204, 204, 204, 204, 
+	204, 204, 204, 204, 204, 204, 204, 204, 
+	204, 204, 204, 204, 204, 204, 204, 204, 
+	204, 204, 204, 204, 204, 204, 204, 204, 
+	204, 204, 204, 204, 204, 204, 204, 204, 
+	204, 204, 204, 204, 204, 204, 204, 204, 
+	204, 204, 204, 204, 204, 204, 204, 204, 
+	204, 204, 204, 204, 204, 204, 204, 204, 
+	204, 204, 204, 204, 204, 204, 204, 204, 
+	204, 204, 283, 283, 283, 283, 283, 283, 
+	283, 283, 283, 283, 283, 283, 283, 283, 
+	283, 283, 283, 283, 283, 283, 283, 283, 
+	283, 283, 283, 283, 283, 283, 283, 283, 
+	283, 283, 283, 283, 283, 283, 283, 283, 
+	283, 283, 283, 283, 283, 283, 283, 283, 
+	283, 283, 283, 283, 283, 283, 283, 283, 
+	283, 283, 283, 283, 283, 283, 283, 283, 
+	283, 283, 283, 283, 283, 283, 283, 283, 
+	283, 283, 283, 283, 283, 283, 283, 283, 
+	283, 362, 362, 362, 362, 362, 362, 362, 
+	362, 362, 362, 362, 362, 362, 362, 362, 
+	362, 362, 362, 362, 362, 362, 362, 362, 
+	362, 362, 362, 362, 362, 362, 362, 362, 
+	362, 362, 362, 362, 362, 362, 362, 362, 
+	362, 362, 362, 362, 362, 362, 362, 362, 
+	362, 362, 362, 362, 362, 362, 362, 362, 
+	362, 362, 362, 362, 362, 362, 362, 362, 
+	362, 362, 362, 362, 362, 362, 362, 362, 
+	362, 362, 362, 362, 362, 433, 362, 433, 
+	434, 434, 434, 434, 434, 434, 434, 434, 
+	434, 434, 434, 434, 434, 434, 434, 434, 
+	434, 434, 434, 434, 434, 434, 434, 434, 
+	434, 434, 434, 434, 434, 434, 434, 434, 
+	434, 434, 434, 434, 434, 434, 434, 434, 
+	434, 434, 434, 434, 434, 434, 434, 434, 
+	434, 434, 434, 434, 434, 434, 434, 434, 
+	434, 434, 434, 434, 434, 434, 434, 434, 
+	434, 434, 434, 434, 434, 434, 434, 434, 
+	434, 434, 434, 434, 434, 434, 362, 204, 
+	204, 204, 204, 204, 204, 204, 204, 204, 
+	204, 362, 204, 204, 204, 204, 204, 204, 
+	204, 204, 204, 204, 204, 204, 204, 204, 
+	204, 204, 204, 204, 204, 204, 204, 204, 
+	204, 362, 548, 548, 548, 548, 548, 548, 
+	548, 548, 548, 433
 };
 
 static const int indic_syllable_machine_start = 178;
 static const int indic_syllable_machine_first_final = 178;
 static const int indic_syllable_machine_error = -1;
 
 static const int indic_syllable_machine_en_main = 178;
 
 
 #line 36 "hb-ot-shape-complex-indic-machine.rl"
 
 
 
-#line 96 "hb-ot-shape-complex-indic-machine.rl"
+#line 97 "hb-ot-shape-complex-indic-machine.rl"
 
 
 #define found_syllable(syllable_type) \
   HB_STMT_START { \
     if (0) fprintf (stderr, "syllable %d..%d %s\n", last, p+1, #syllable_type); \
     for (unsigned int i = last; i < p+1; i++) \
       info[i].syllable() = (syllable_serial << 4) | syllable_type; \
     last = p+1; \
@@ -1373,48 +1375,48 @@ static const int indic_syllable_machine_
 
 static void
 find_syllables (hb_buffer_t *buffer)
 {
   unsigned int p, pe, eof, ts HB_UNUSED, te HB_UNUSED, act HB_UNUSED;
   int cs;
   hb_glyph_info_t *info = buffer->info;
   
-#line 1382 "hb-ot-shape-complex-indic-machine.hh"
+#line 1384 "hb-ot-shape-complex-indic-machine.hh"
 	{
 	cs = indic_syllable_machine_start;
 	ts = 0;
 	te = 0;
 	act = 0;
 	}
 
-#line 117 "hb-ot-shape-complex-indic-machine.rl"
+#line 118 "hb-ot-shape-complex-indic-machine.rl"
 
 
   p = 0;
   pe = eof = buffer->len;
 
   unsigned int last = 0;
   unsigned int syllable_serial = 1;
   
-#line 1399 "hb-ot-shape-complex-indic-machine.hh"
+#line 1401 "hb-ot-shape-complex-indic-machine.hh"
 	{
 	int _slen;
 	int _trans;
 	const unsigned char *_keys;
 	const short *_inds;
 	if ( p == pe )
 		goto _test_eof;
 _resume:
 	switch ( _indic_syllable_machine_from_state_actions[cs] ) {
 	case 11:
 #line 1 "NONE"
 	{ts = p;}
 	break;
-#line 1413 "hb-ot-shape-complex-indic-machine.hh"
+#line 1415 "hb-ot-shape-complex-indic-machine.hh"
 	}
 
 	_keys = _indic_syllable_machine_trans_keys + (cs<<1);
 	_inds = _indic_syllable_machine_indicies + _indic_syllable_machine_index_offsets[cs];
 
 	_slen = _indic_syllable_machine_key_spans[cs];
 	_trans = _inds[ _slen > 0 && _keys[0] <=( info[p].indic_category()) &&
 		( info[p].indic_category()) <= _keys[1] ?
@@ -1427,81 +1429,81 @@ find_syllables (hb_buffer_t *buffer)
 		goto _again;
 
 	switch ( _indic_syllable_machine_trans_actions[_trans] ) {
 	case 2:
 #line 1 "NONE"
 	{te = p+1;}
 	break;
 	case 15:
-#line 87 "hb-ot-shape-complex-indic-machine.rl"
+#line 88 "hb-ot-shape-complex-indic-machine.rl"
 	{te = p+1;{ found_syllable (consonant_syllable); }}
 	break;
 	case 17:
-#line 88 "hb-ot-shape-complex-indic-machine.rl"
+#line 89 "hb-ot-shape-complex-indic-machine.rl"
 	{te = p+1;{ found_syllable (vowel_syllable); }}
 	break;
 	case 22:
-#line 89 "hb-ot-shape-complex-indic-machine.rl"
+#line 90 "hb-ot-shape-complex-indic-machine.rl"
 	{te = p+1;{ found_syllable (standalone_cluster); }}
 	break;
 	case 24:
-#line 90 "hb-ot-shape-complex-indic-machine.rl"
+#line 91 "hb-ot-shape-complex-indic-machine.rl"
 	{te = p+1;{ found_syllable (symbol_cluster); }}
 	break;
 	case 19:
-#line 91 "hb-ot-shape-complex-indic-machine.rl"
+#line 92 "hb-ot-shape-complex-indic-machine.rl"
 	{te = p+1;{ found_syllable (broken_cluster); }}
 	break;
 	case 12:
-#line 92 "hb-ot-shape-complex-indic-machine.rl"
+#line 93 "hb-ot-shape-complex-indic-machine.rl"
 	{te = p+1;{ found_syllable (non_indic_cluster); }}
 	break;
 	case 14:
-#line 87 "hb-ot-shape-complex-indic-machine.rl"
+#line 88 "hb-ot-shape-complex-indic-machine.rl"
 	{te = p;p--;{ found_syllable (consonant_syllable); }}
 	break;
 	case 16:
-#line 88 "hb-ot-shape-complex-indic-machine.rl"
+#line 89 "hb-ot-shape-complex-indic-machine.rl"
 	{te = p;p--;{ found_syllable (vowel_syllable); }}
 	break;
 	case 21:
-#line 89 "hb-ot-shape-complex-indic-machine.rl"
+#line 90 "hb-ot-shape-complex-indic-machine.rl"
 	{te = p;p--;{ found_syllable (standalone_cluster); }}
 	break;
 	case 23:
-#line 90 "hb-ot-shape-complex-indic-machine.rl"
+#line 91 "hb-ot-shape-complex-indic-machine.rl"
 	{te = p;p--;{ found_syllable (symbol_cluster); }}
 	break;
 	case 18:
-#line 91 "hb-ot-shape-complex-indic-machine.rl"
+#line 92 "hb-ot-shape-complex-indic-machine.rl"
 	{te = p;p--;{ found_syllable (broken_cluster); }}
 	break;
 	case 20:
-#line 92 "hb-ot-shape-complex-indic-machine.rl"
+#line 93 "hb-ot-shape-complex-indic-machine.rl"
 	{te = p;p--;{ found_syllable (non_indic_cluster); }}
 	break;
 	case 1:
-#line 87 "hb-ot-shape-complex-indic-machine.rl"
+#line 88 "hb-ot-shape-complex-indic-machine.rl"
 	{{p = ((te))-1;}{ found_syllable (consonant_syllable); }}
 	break;
 	case 3:
-#line 88 "hb-ot-shape-complex-indic-machine.rl"
+#line 89 "hb-ot-shape-complex-indic-machine.rl"
 	{{p = ((te))-1;}{ found_syllable (vowel_syllable); }}
 	break;
 	case 7:
-#line 89 "hb-ot-shape-complex-indic-machine.rl"
+#line 90 "hb-ot-shape-complex-indic-machine.rl"
 	{{p = ((te))-1;}{ found_syllable (standalone_cluster); }}
 	break;
 	case 9:
-#line 90 "hb-ot-shape-complex-indic-machine.rl"
+#line 91 "hb-ot-shape-complex-indic-machine.rl"
 	{{p = ((te))-1;}{ found_syllable (symbol_cluster); }}
 	break;
 	case 4:
-#line 91 "hb-ot-shape-complex-indic-machine.rl"
+#line 92 "hb-ot-shape-complex-indic-machine.rl"
 	{{p = ((te))-1;}{ found_syllable (broken_cluster); }}
 	break;
 	case 5:
 #line 1 "NONE"
 	{	switch( act ) {
 	case 1:
 	{{p = ((te))-1;} found_syllable (consonant_syllable); }
 	break;
@@ -1512,53 +1514,53 @@ find_syllables (hb_buffer_t *buffer)
 	{{p = ((te))-1;} found_syllable (non_indic_cluster); }
 	break;
 	}
 	}
 	break;
 	case 8:
 #line 1 "NONE"
 	{te = p+1;}
-#line 87 "hb-ot-shape-complex-indic-machine.rl"
+#line 88 "hb-ot-shape-complex-indic-machine.rl"
 	{act = 1;}
 	break;
 	case 6:
 #line 1 "NONE"
 	{te = p+1;}
-#line 91 "hb-ot-shape-complex-indic-machine.rl"
+#line 92 "hb-ot-shape-complex-indic-machine.rl"
 	{act = 5;}
 	break;
 	case 13:
 #line 1 "NONE"
 	{te = p+1;}
-#line 92 "hb-ot-shape-complex-indic-machine.rl"
+#line 93 "hb-ot-shape-complex-indic-machine.rl"
 	{act = 6;}
 	break;
-#line 1536 "hb-ot-shape-complex-indic-machine.hh"
+#line 1538 "hb-ot-shape-complex-indic-machine.hh"
 	}
 
 _again:
 	switch ( _indic_syllable_machine_to_state_actions[cs] ) {
 	case 10:
 #line 1 "NONE"
 	{ts = 0;}
 	break;
-#line 1545 "hb-ot-shape-complex-indic-machine.hh"
+#line 1547 "hb-ot-shape-complex-indic-machine.hh"
 	}
 
 	if ( ++p != pe )
 		goto _resume;
 	_test_eof: {}
 	if ( p == eof )
 	{
 	if ( _indic_syllable_machine_eof_trans[cs] > 0 ) {
 		_trans = _indic_syllable_machine_eof_trans[cs] - 1;
 		goto _eof_trans;
 	}
 	}
 
 	}
 
-#line 126 "hb-ot-shape-complex-indic-machine.rl"
+#line 127 "hb-ot-shape-complex-indic-machine.rl"
 
 }
 
 #endif /* HB_OT_SHAPE_COMPLEX_INDIC_MACHINE_HH */
--- a/gfx/harfbuzz/src/hb-ot-shape-complex-indic-machine.rl
+++ b/gfx/harfbuzz/src/hb-ot-shape-complex-indic-machine.rl
@@ -52,16 +52,17 @@ A    = 10;
 PLACEHOLDER = 11;
 DOTTEDCIRCLE = 12;
 RS    = 13;
 Coeng = 14;
 Repha = 15;
 Ra    = 16;
 CM    = 17;
 Symbol= 18;
+CS    = 19;
 
 c = (C | Ra);			# is_consonant
 n = ((ZWNJ?.RS)? (N.N?)?);	# is_consonant_modifier
 z = ZWJ|ZWNJ;			# is_joiner
 h = H | Coeng;			# is_halant_or_coeng
 reph = (Ra H | Repha);		# possible reph
 
 cn = c.ZWJ?.n?;
@@ -71,19 +72,19 @@ matra_group = z{0,3}.M.N?.(H | forced_ra
 syllable_tail = (z?.SM.SM?.ZWNJ?)? A{0,3}? VD{0,2};
 place_holder = PLACEHOLDER | DOTTEDCIRCLE;
 halant_group = (z?.h.(ZWJ.N?)?);
 final_halant_group = halant_group | h.ZWNJ;
 medial_group = CM?;
 halant_or_matra_group = (final_halant_group | (h.ZWJ)? matra_group{0,4}) (Coeng (cn|V))?;
 
 
-consonant_syllable =	Repha? (cn.halant_group){0,4} cn medial_group halant_or_matra_group syllable_tail;
+consonant_syllable =	(Repha|CS)? (cn.halant_group){0,4} cn medial_group halant_or_matra_group syllable_tail;
 vowel_syllable =	reph? V.n? (ZWJ | (halant_group.cn){0,4} medial_group halant_or_matra_group syllable_tail);
-standalone_cluster =	(Repha? PLACEHOLDER | reph? DOTTEDCIRCLE).n? (halant_group.cn){0,4} medial_group halant_or_matra_group syllable_tail;
+standalone_cluster =	((Repha|CS)? PLACEHOLDER | reph? DOTTEDCIRCLE).n? (halant_group.cn){0,4} medial_group halant_or_matra_group syllable_tail;
 symbol_cluster = 	symbol syllable_tail;
 broken_cluster =	reph? n? (halant_group.cn){0,4} medial_group halant_or_matra_group syllable_tail;
 other =			any;
 
 main := |*
 	consonant_syllable	=> { found_syllable (consonant_syllable); };
 	vowel_syllable		=> { found_syllable (vowel_syllable); };
 	standalone_cluster	=> { found_syllable (standalone_cluster); };
--- a/gfx/harfbuzz/src/hb-ot-shape-complex-indic-private.hh
+++ b/gfx/harfbuzz/src/hb-ot-shape-complex-indic-private.hh
@@ -55,27 +55,28 @@ enum indic_category_t {
   OT_A = 10,
   OT_PLACEHOLDER = 11,
   OT_DOTTEDCIRCLE = 12,
   OT_RS = 13, /* Register Shifter, used in Khmer OT spec. */
   OT_Coeng = 14, /* Khmer-style Virama. */
   OT_Repha = 15, /* Atomically-encoded logical or visual repha. */
   OT_Ra = 16,
   OT_CM = 17,  /* Consonant-Medial. */
-  OT_Symbol = 18 /* Avagraha, etc that take marks (SM,A,VD). */
+  OT_Symbol = 18, /* Avagraha, etc that take marks (SM,A,VD). */
+  OT_CS = 19
 };
 
 #define MEDIAL_FLAGS (FLAG (OT_CM))
 
 /* Note:
  *
  * We treat Vowels and placeholders as if they were consonants.  This is safe because Vowels
  * cannot happen in a consonant syllable.  The plus side however is, we can call the
  * consonant syllable logic from the vowel syllable function and get it all right! */
-#define CONSONANT_FLAGS (FLAG (OT_C) | FLAG (OT_Ra) | MEDIAL_FLAGS | FLAG (OT_V) | FLAG (OT_PLACEHOLDER) | FLAG (OT_DOTTEDCIRCLE))
+#define CONSONANT_FLAGS (FLAG (OT_C) | FLAG (OT_CS) | FLAG (OT_Ra) | MEDIAL_FLAGS | FLAG (OT_V) | FLAG (OT_PLACEHOLDER) | FLAG (OT_DOTTEDCIRCLE))
 #define JOINER_FLAGS (FLAG (OT_ZWJ) | FLAG (OT_ZWNJ))
 #define HALANT_OR_COENG_FLAGS (FLAG (OT_H) | FLAG (OT_Coeng))
 
 
 /* Visual positions in a syllable from left to right. */
 enum indic_position_t {
   POS_START,
 
@@ -116,18 +117,18 @@ enum indic_syllabic_category_t {
   INDIC_SYLLABIC_CATEGORY_CONSONANT_HEAD_LETTER		= OT_C,
   INDIC_SYLLABIC_CATEGORY_CONSONANT_KILLER		= OT_M, /* U+17CD only. */
   INDIC_SYLLABIC_CATEGORY_CONSONANT_MEDIAL		= OT_CM,
   INDIC_SYLLABIC_CATEGORY_CONSONANT_PLACEHOLDER		= OT_PLACEHOLDER,
   INDIC_SYLLABIC_CATEGORY_CONSONANT_PRECEDING_REPHA	= OT_Repha,
   INDIC_SYLLABIC_CATEGORY_CONSONANT_PREFIXED		= OT_X, /* Don't care. */
   INDIC_SYLLABIC_CATEGORY_CONSONANT_SUBJOINED		= OT_CM,
   INDIC_SYLLABIC_CATEGORY_CONSONANT_SUCCEEDING_REPHA	= OT_N,
-  INDIC_SYLLABIC_CATEGORY_CONSONANT_WITH_STACKER	= OT_C,
-  INDIC_SYLLABIC_CATEGORY_GEMINATION_MARK		= OT_SM,
+  INDIC_SYLLABIC_CATEGORY_CONSONANT_WITH_STACKER	= OT_CS,
+  INDIC_SYLLABIC_CATEGORY_GEMINATION_MARK		= OT_SM, /* https://github.com/behdad/harfbuzz/issues/552 */
   INDIC_SYLLABIC_CATEGORY_INVISIBLE_STACKER		= OT_Coeng,
   INDIC_SYLLABIC_CATEGORY_JOINER			= OT_ZWJ,
   INDIC_SYLLABIC_CATEGORY_MODIFYING_LETTER		= OT_X,
   INDIC_SYLLABIC_CATEGORY_NON_JOINER			= OT_ZWNJ,
   INDIC_SYLLABIC_CATEGORY_NUKTA				= OT_N,
   INDIC_SYLLABIC_CATEGORY_NUMBER			= OT_PLACEHOLDER,
   INDIC_SYLLABIC_CATEGORY_NUMBER_JOINER			= OT_PLACEHOLDER, /* Don't care. */
   INDIC_SYLLABIC_CATEGORY_PURE_KILLER			= OT_M, /* Is like a vowel matra. */
--- a/gfx/harfbuzz/src/hb-ot-shape-complex-indic-table.cc
+++ b/gfx/harfbuzz/src/hb-ot-shape-complex-indic-table.cc
@@ -1,71 +1,72 @@
 /* == Start of generated table == */
 /*
  * The following table is generated by running:
  *
  *   ./gen-indic-table.py IndicSyllabicCategory.txt IndicPositionalCategory.txt Blocks.txt
  *
  * on files with these headers:
  *
- * # IndicSyllabicCategory-9.0.0.txt
- * # Date: 2016-05-21, 02:46:00 GMT [RP]
- * # IndicPositionalCategory-9.0.0.txt
- * # Date: 2016-02-25, 00:48:00 GMT [RP]
- * # Blocks-9.0.0.txt
- * # Date: 2016-02-05, 23:48:00 GMT [KW]
+ * # IndicSyllabicCategory-10.0.0.txt
+ * # Date: 2017-05-31, 01:07:00 GMT [KW, RP]
+ * # IndicPositionalCategory-10.0.0.txt
+ * # Date: 2017-05-31, 01:07:00 GMT [RP]
+ * # Blocks-10.0.0.txt
+ * # Date: 2017-04-12, 17:30:00 GMT [KW]
  */
 
 #include "hb-ot-shape-complex-indic-private.hh"
 
 
 #define ISC_A	INDIC_SYLLABIC_CATEGORY_AVAGRAHA		/*  15 chars; Avagraha */
-#define ISC_Bi	INDIC_SYLLABIC_CATEGORY_BINDU			/*  67 chars; Bindu */
+#define ISC_Bi	INDIC_SYLLABIC_CATEGORY_BINDU			/*  80 chars; Bindu */
 #define ISC_BJN	INDIC_SYLLABIC_CATEGORY_BRAHMI_JOINING_NUMBER	/*  20 chars; Brahmi_Joining_Number */
-#define ISC_Ca	INDIC_SYLLABIC_CATEGORY_CANTILLATION_MARK	/*  53 chars; Cantillation_Mark */
-#define ISC_C	INDIC_SYLLABIC_CATEGORY_CONSONANT		/* 1907 chars; Consonant */
+#define ISC_Ca	INDIC_SYLLABIC_CATEGORY_CANTILLATION_MARK	/*  57 chars; Cantillation_Mark */
+#define ISC_C	INDIC_SYLLABIC_CATEGORY_CONSONANT		/* 2024 chars; Consonant */
 #define ISC_CD	INDIC_SYLLABIC_CATEGORY_CONSONANT_DEAD		/*  10 chars; Consonant_Dead */
-#define ISC_CF	INDIC_SYLLABIC_CATEGORY_CONSONANT_FINAL		/*  62 chars; Consonant_Final */
+#define ISC_CF	INDIC_SYLLABIC_CATEGORY_CONSONANT_FINAL		/*  68 chars; Consonant_Final */
 #define ISC_CHL	INDIC_SYLLABIC_CATEGORY_CONSONANT_HEAD_LETTER	/*   5 chars; Consonant_Head_Letter */
 #define ISC_CK	INDIC_SYLLABIC_CATEGORY_CONSONANT_KILLER	/*   2 chars; Consonant_Killer */
-#define ISC_CM	INDIC_SYLLABIC_CATEGORY_CONSONANT_MEDIAL	/*  22 chars; Consonant_Medial */
-#define ISC_CP	INDIC_SYLLABIC_CATEGORY_CONSONANT_PLACEHOLDER	/*  16 chars; Consonant_Placeholder */
-#define ISC_CPR	INDIC_SYLLABIC_CATEGORY_CONSONANT_PRECEDING_REPHA	/*   1 chars; Consonant_Preceding_Repha */
-#define ISC_CPrf	INDIC_SYLLABIC_CATEGORY_CONSONANT_PREFIXED	/*   2 chars; Consonant_Prefixed */
-#define ISC_CS	INDIC_SYLLABIC_CATEGORY_CONSONANT_SUBJOINED	/*  90 chars; Consonant_Subjoined */
-#define ISC_CSR	INDIC_SYLLABIC_CATEGORY_CONSONANT_SUCCEEDING_REPHA	/*   4 chars; Consonant_Succeeding_Repha */
+#define ISC_CM	INDIC_SYLLABIC_CATEGORY_CONSONANT_MEDIAL	/*  27 chars; Consonant_Medial */
+#define ISC_CP	INDIC_SYLLABIC_CATEGORY_CONSONANT_PLACEHOLDER	/*  18 chars; Consonant_Placeholder */
+#define ISC_CPR	INDIC_SYLLABIC_CATEGORY_CONSONANT_PRECEDING_REPHA	/*   2 chars; Consonant_Preceding_Repha */
+#define ISC_CPrf	INDIC_SYLLABIC_CATEGORY_CONSONANT_PREFIXED	/*   7 chars; Consonant_Prefixed */
+#define ISC_CS	INDIC_SYLLABIC_CATEGORY_CONSONANT_SUBJOINED	/*  95 chars; Consonant_Subjoined */
+#define ISC_CSR	INDIC_SYLLABIC_CATEGORY_CONSONANT_SUCCEEDING_REPHA	/*   5 chars; Consonant_Succeeding_Repha */
 #define ISC_CWS	INDIC_SYLLABIC_CATEGORY_CONSONANT_WITH_STACKER	/*   4 chars; Consonant_With_Stacker */
-#define ISC_GM	INDIC_SYLLABIC_CATEGORY_GEMINATION_MARK		/*   2 chars; Gemination_Mark */
-#define ISC_IS	INDIC_SYLLABIC_CATEGORY_INVISIBLE_STACKER	/*   7 chars; Invisible_Stacker */
+#define ISC_GM	INDIC_SYLLABIC_CATEGORY_GEMINATION_MARK		/*   3 chars; Gemination_Mark */
+#define ISC_IS	INDIC_SYLLABIC_CATEGORY_INVISIBLE_STACKER	/*  10 chars; Invisible_Stacker */
 #define ISC_ZWJ	INDIC_SYLLABIC_CATEGORY_JOINER			/*   1 chars; Joiner */
 #define ISC_ML	INDIC_SYLLABIC_CATEGORY_MODIFYING_LETTER	/*   1 chars; Modifying_Letter */
 #define ISC_ZWNJ	INDIC_SYLLABIC_CATEGORY_NON_JOINER		/*   1 chars; Non_Joiner */
-#define ISC_N	INDIC_SYLLABIC_CATEGORY_NUKTA			/*  24 chars; Nukta */
-#define ISC_Nd	INDIC_SYLLABIC_CATEGORY_NUMBER			/* 459 chars; Number */
+#define ISC_N	INDIC_SYLLABIC_CATEGORY_NUKTA			/*  28 chars; Nukta */
+#define ISC_Nd	INDIC_SYLLABIC_CATEGORY_NUMBER			/* 469 chars; Number */
 #define ISC_NJ	INDIC_SYLLABIC_CATEGORY_NUMBER_JOINER		/*   1 chars; Number_Joiner */
 #define ISC_x	INDIC_SYLLABIC_CATEGORY_OTHER			/*   1 chars; Other */
-#define ISC_PK	INDIC_SYLLABIC_CATEGORY_PURE_KILLER		/*  16 chars; Pure_Killer */
+#define ISC_PK	INDIC_SYLLABIC_CATEGORY_PURE_KILLER		/*  21 chars; Pure_Killer */
 #define ISC_RS	INDIC_SYLLABIC_CATEGORY_REGISTER_SHIFTER	/*   2 chars; Register_Shifter */
 #define ISC_SM	INDIC_SYLLABIC_CATEGORY_SYLLABLE_MODIFIER	/*  22 chars; Syllable_Modifier */
 #define ISC_TL	INDIC_SYLLABIC_CATEGORY_TONE_LETTER		/*   7 chars; Tone_Letter */
 #define ISC_TM	INDIC_SYLLABIC_CATEGORY_TONE_MARK		/*  42 chars; Tone_Mark */
 #define ISC_V	INDIC_SYLLABIC_CATEGORY_VIRAMA			/*  24 chars; Virama */
-#define ISC_Vs	INDIC_SYLLABIC_CATEGORY_VISARGA			/*  31 chars; Visarga */
+#define ISC_Vs	INDIC_SYLLABIC_CATEGORY_VISARGA			/*  34 chars; Visarga */
 #define ISC_Vo	INDIC_SYLLABIC_CATEGORY_VOWEL			/*  30 chars; Vowel */
-#define ISC_M	INDIC_SYLLABIC_CATEGORY_VOWEL_DEPENDENT		/* 602 chars; Vowel_Dependent */
-#define ISC_VI	INDIC_SYLLABIC_CATEGORY_VOWEL_INDEPENDENT	/* 431 chars; Vowel_Independent */
+#define ISC_M	INDIC_SYLLABIC_CATEGORY_VOWEL_DEPENDENT		/* 633 chars; Vowel_Dependent */
+#define ISC_VI	INDIC_SYLLABIC_CATEGORY_VOWEL_INDEPENDENT	/* 443 chars; Vowel_Independent */
 
-#define IMC_B	INDIC_MATRA_CATEGORY_BOTTOM			/* 300 chars; Bottom */
+#define IMC_B	INDIC_MATRA_CATEGORY_BOTTOM			/* 330 chars; Bottom */
+#define IMC_BL	INDIC_MATRA_CATEGORY_BOTTOM_AND_LEFT		/*   1 chars; Bottom_And_Left */
 #define IMC_BR	INDIC_MATRA_CATEGORY_BOTTOM_AND_RIGHT		/*   2 chars; Bottom_And_Right */
 #define IMC_L	INDIC_MATRA_CATEGORY_LEFT			/*  57 chars; Left */
 #define IMC_LR	INDIC_MATRA_CATEGORY_LEFT_AND_RIGHT		/*  21 chars; Left_And_Right */
 #define IMC_x	INDIC_MATRA_CATEGORY_NOT_APPLICABLE		/*   1 chars; Not_Applicable */
 #define IMC_O	INDIC_MATRA_CATEGORY_OVERSTRUCK			/*  10 chars; Overstruck */
-#define IMC_R	INDIC_MATRA_CATEGORY_RIGHT			/* 258 chars; Right */
-#define IMC_T	INDIC_MATRA_CATEGORY_TOP			/* 342 chars; Top */
+#define IMC_R	INDIC_MATRA_CATEGORY_RIGHT			/* 262 chars; Right */
+#define IMC_T	INDIC_MATRA_CATEGORY_TOP			/* 380 chars; Top */
 #define IMC_TB	INDIC_MATRA_CATEGORY_TOP_AND_BOTTOM		/*  10 chars; Top_And_Bottom */
 #define IMC_TBR	INDIC_MATRA_CATEGORY_TOP_AND_BOTTOM_AND_RIGHT	/*   1 chars; Top_And_Bottom_And_Right */
 #define IMC_TL	INDIC_MATRA_CATEGORY_TOP_AND_LEFT		/*   6 chars; Top_And_Left */
 #define IMC_TLR	INDIC_MATRA_CATEGORY_TOP_AND_LEFT_AND_RIGHT	/*   4 chars; Top_And_Left_And_Right */
 #define IMC_TR	INDIC_MATRA_CATEGORY_TOP_AND_RIGHT		/*  13 chars; Top_And_Right */
 #define IMC_VOL	INDIC_MATRA_CATEGORY_VISUAL_ORDER_LEFT		/*  19 chars; Visual_Order_Left */
 
 #define _(S,M) INDIC_COMBINE_CATEGORIES (ISC_##S, IMC_##M)
@@ -128,17 +129,17 @@ static const INDIC_TABLE_ELEMENT_TYPE in
   /* 09B8 */  _(C,x),  _(C,x),  _(x,x),  _(x,x),  _(N,B),  _(A,x),  _(M,R),  _(M,L),
   /* 09C0 */  _(M,R),  _(M,B),  _(M,B),  _(M,B),  _(M,B),  _(x,x),  _(x,x),  _(M,L),
   /* 09C8 */  _(M,L),  _(x,x),  _(x,x), _(M,LR), _(M,LR),  _(V,B), _(CD,x),  _(x,x),
   /* 09D0 */  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(M,R),
   /* 09D8 */  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(C,x),  _(C,x),  _(x,x),  _(C,x),
   /* 09E0 */ _(VI,x), _(VI,x),  _(M,B),  _(M,B),  _(x,x),  _(x,x), _(Nd,x), _(Nd,x),
   /* 09E8 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
   /* 09F0 */  _(C,x),  _(C,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
-  /* 09F8 */  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
+  /* 09F8 */  _(x,x),  _(x,x),  _(x,x),  _(x,x), _(Bi,x),  _(x,x),  _(x,x),  _(x,x),
 
   /* Gurmukhi */
 
   /* 0A00 */  _(x,x), _(Bi,T), _(Bi,T), _(Vs,R),  _(x,x), _(VI,x), _(VI,x), _(VI,x),
   /* 0A08 */ _(VI,x), _(VI,x), _(VI,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x), _(VI,x),
   /* 0A10 */ _(VI,x),  _(x,x),  _(x,x), _(VI,x), _(VI,x),  _(C,x),  _(C,x),  _(C,x),
   /* 0A18 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
   /* 0A20 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
@@ -166,17 +167,17 @@ static const INDIC_TABLE_ELEMENT_TYPE in
   /* 0AB8 */  _(C,x),  _(C,x),  _(x,x),  _(x,x),  _(N,B),  _(A,x),  _(M,R),  _(M,L),
   /* 0AC0 */  _(M,R),  _(M,B),  _(M,B),  _(M,B),  _(M,B),  _(M,T),  _(x,x),  _(M,T),
   /* 0AC8 */  _(M,T), _(M,TR),  _(x,x),  _(M,R),  _(M,R),  _(V,B),  _(x,x),  _(x,x),
   /* 0AD0 */  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
   /* 0AD8 */  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
   /* 0AE0 */ _(VI,x), _(VI,x),  _(M,B),  _(M,B),  _(x,x),  _(x,x), _(Nd,x), _(Nd,x),
   /* 0AE8 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
   /* 0AF0 */  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
-  /* 0AF8 */  _(x,x),  _(C,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
+  /* 0AF8 */  _(x,x),  _(C,x), _(Ca,T), _(Ca,T), _(Ca,T),  _(N,T),  _(N,T),  _(N,T),
 
   /* Oriya */
 
   /* 0B00 */  _(x,x), _(Bi,T), _(Bi,R), _(Vs,R),  _(x,x), _(VI,x), _(VI,x), _(VI,x),
   /* 0B08 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x),  _(x,x),  _(x,x), _(VI,x),
   /* 0B10 */ _(VI,x),  _(x,x),  _(x,x), _(VI,x), _(VI,x),  _(C,x),  _(C,x),  _(C,x),
   /* 0B18 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
   /* 0B20 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
@@ -246,24 +247,24 @@ static const INDIC_TABLE_ELEMENT_TYPE in
   /* 0CD8 */  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(C,x),  _(x,x),
   /* 0CE0 */ _(VI,x), _(VI,x),  _(M,B),  _(M,B),  _(x,x),  _(x,x), _(Nd,x), _(Nd,x),
   /* 0CE8 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
   /* 0CF0 */  _(x,x),_(CWS,x),_(CWS,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
   /* 0CF8 */  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
 
   /* Malayalam */
 
-  /* 0D00 */  _(x,x), _(Bi,T), _(Bi,R), _(Vs,R),  _(x,x), _(VI,x), _(VI,x), _(VI,x),
+  /* 0D00 */ _(Bi,T), _(Bi,T), _(Bi,R), _(Vs,R),  _(x,x), _(VI,x), _(VI,x), _(VI,x),
   /* 0D08 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x),  _(x,x), _(VI,x), _(VI,x),
   /* 0D10 */ _(VI,x),  _(x,x), _(VI,x), _(VI,x), _(VI,x),  _(C,x),  _(C,x),  _(C,x),
   /* 0D18 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
   /* 0D20 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
   /* 0D28 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
   /* 0D30 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
-  /* 0D38 */  _(C,x),  _(C,x),  _(C,x),  _(x,x),  _(x,x),  _(A,x),  _(M,R),  _(M,R),
+  /* 0D38 */  _(C,x),  _(C,x),  _(C,x), _(PK,T), _(PK,T),  _(A,x),  _(M,R),  _(M,R),
   /* 0D40 */  _(M,R),  _(M,R),  _(M,R),  _(M,B),  _(M,B),  _(x,x),  _(M,L),  _(M,L),
   /* 0D48 */  _(M,L),  _(x,x), _(M,LR), _(M,LR), _(M,LR),  _(V,T),_(CPR,x),  _(x,x),
   /* 0D50 */  _(x,x),  _(x,x),  _(x,x),  _(x,x), _(CD,x), _(CD,x), _(CD,x),  _(M,R),
   /* 0D58 */  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x), _(VI,x),
   /* 0D60 */ _(VI,x), _(VI,x),  _(M,B),  _(M,B),  _(x,x),  _(x,x), _(Nd,x), _(Nd,x),
   /* 0D68 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
   /* 0D70 */  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
   /* 0D78 */  _(x,x),  _(x,x), _(CD,x), _(CD,x), _(CD,x), _(CD,x), _(CD,x), _(CD,x),
@@ -336,17 +337,17 @@ static const INDIC_TABLE_ELEMENT_TYPE in
 
 
   /* Vedic Extensions */
 
   /* 1CD0 */ _(Ca,T), _(Ca,T), _(Ca,T),  _(x,x), _(Ca,O), _(Ca,B), _(Ca,B), _(Ca,B),
   /* 1CD8 */ _(Ca,B), _(Ca,B), _(Ca,T), _(Ca,T), _(Ca,B), _(Ca,B), _(Ca,B), _(Ca,B),
   /* 1CE0 */ _(Ca,T), _(Ca,R),  _(x,O),  _(x,O),  _(x,O),  _(x,O),  _(x,O),  _(x,O),
   /* 1CE8 */  _(x,O),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,B),  _(x,x),  _(x,x),
-  /* 1CF0 */  _(x,x),  _(x,x), _(Vs,x), _(Vs,x), _(Ca,T),  _(x,x),  _(x,x),  _(x,x),
+  /* 1CF0 */  _(x,x),  _(x,x), _(Vs,x), _(Vs,x), _(Ca,T),  _(x,x),  _(x,x), _(Ca,R),
   /* 1CF8 */ _(Ca,x), _(Ca,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
 
 #define indic_offset_0x2008u 1656
 
 
   /* General Punctuation */
 
   /* 2008 */  _(x,x),  _(x,x),  _(x,x),  _(x,x),_(ZWNJ,x),_(ZWJ,x),  _(x,x),  _(x,x),
@@ -363,17 +364,17 @@ static const INDIC_TABLE_ELEMENT_TYPE in
 
 #define indic_offset_0xa8e0u 1696
 
 
   /* Devanagari Extended */
 
   /* A8E0 */ _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T),
   /* A8E8 */ _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T),
-  /* A8F0 */ _(Ca,T), _(Ca,T),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
+  /* A8F0 */ _(Ca,T), _(Ca,T), _(Bi,x), _(Bi,x),  _(x,x),  _(x,x),  _(x,x),  _(x,x),
 
 #define indic_offset_0xa9e0u 1720
 
 
   /* Myanmar Extended-B */
 
   /* A9E0 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(M,T),  _(x,x),  _(C,x),
   /* A9E8 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
@@ -385,17 +386,17 @@ static const INDIC_TABLE_ELEMENT_TYPE in
 
   /* Myanmar Extended-A */
 
   /* AA60 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
   /* AA68 */  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),  _(C,x),
   /* AA70 */  _(x,x),  _(C,x),  _(C,x),  _(C,x), _(CP,x), _(CP,x), _(CP,x),  _(x,x),
   /* AA78 */  _(x,x),  _(x,x),  _(C,x), _(TM,R), _(TM,T), _(TM,R),  _(C,x),  _(C,x),
 
-}; /* Table items: 1784; occupancy: 69% */
+}; /* Table items: 1784; occupancy: 70% */
 
 INDIC_TABLE_ELEMENT_TYPE
 hb_indic_get_categories (hb_codepoint_t u)
 {
   switch (u >> 12)
   {
     case 0x0u:
       if (hb_in_range<hb_codepoint_t> (u, 0x0028u, 0x003Fu)) return indic_table[u - 0x0028u + indic_offset_0x0028u];
@@ -417,23 +418,16 @@ hb_indic_get_categories (hb_codepoint_t 
       break;
 
     case 0xAu:
       if (hb_in_range<hb_codepoint_t> (u, 0xA8E0u, 0xA8F7u)) return indic_table[u - 0xA8E0u + indic_offset_0xa8e0u];
       if (hb_in_range<hb_codepoint_t> (u, 0xA9E0u, 0xA9FFu)) return indic_table[u - 0xA9E0u + indic_offset_0xa9e0u];
       if (hb_in_range<hb_codepoint_t> (u, 0xAA60u, 0xAA7Fu)) return indic_table[u - 0xAA60u + indic_offset_0xaa60u];
       break;
 
-    case 0x11u:
-      // According to ScriptExtensions.txt, these Grantha marks may also be used in Tamil,
-      // so the Indic shaper needs to know their categories.
-      if (unlikely (u == 0x11303)) return _(Vs,R);
-      if (unlikely (u == 0x1133c)) return _(N,B);
-      break;
-
     default:
       break;
   }
   return _(x,x);
 }
 
 #undef _
 
@@ -469,16 +463,17 @@ hb_indic_get_categories (hb_codepoint_t 
 #undef ISC_TM
 #undef ISC_V
 #undef ISC_Vs
 #undef ISC_Vo
 #undef ISC_M
 #undef ISC_VI
 
 #undef IMC_B
+#undef IMC_BL
 #undef IMC_BR
 #undef IMC_L
 #undef IMC_LR
 #undef IMC_x
 #undef IMC_O
 #undef IMC_R
 #undef IMC_T
 #undef IMC_TB
--- a/gfx/harfbuzz/src/hb-ot-shape-complex-indic.cc
+++ b/gfx/harfbuzz/src/hb-ot-shape-complex-indic.cc
@@ -203,17 +203,31 @@ set_indic_properties (hb_glyph_info_t &i
   else if (unlikely (hb_in_range<hb_codepoint_t> (u, 0x17CDu, 0x17D1u) ||
 		     u == 0x17CBu || u == 0x17D3u || u == 0x17DDu)) /* Khmer Various signs */
   {
     /* These can occur mid-syllable (eg. before matras), even though Unicode marks them as Syllable_Modifier.
      * https://github.com/roozbehp/unicode-data/issues/5 */
     cat = OT_M;
     pos = POS_ABOVE_C;
   }
+  else if (unlikely (u == 0x0A51u))
+  {
+    /* https://github.com/behdad/harfbuzz/issues/524 */
+    cat = OT_M;
+    pos = POS_BELOW_C;
+  }
 
+  /* According to ScriptExtensions.txt, these Grantha marks may also be used in Tamil,
+   * so the Indic shaper needs to know their categories. */
+  else if (unlikely (u == 0x11303u)) cat = OT_SM;
+  else if (unlikely (u == 0x1133cu)) cat = OT_N;
+
+  else if (unlikely (u == 0x0AFBu)) cat = OT_N; /* https://github.com/behdad/harfbuzz/issues/552 */
+
+  else if (unlikely (u == 0x0980u)) cat = OT_PLACEHOLDER; /* https://github.com/behdad/harfbuzz/issues/538 */
   else if (unlikely (u == 0x17C6u)) cat = OT_N; /* Khmer Bindu doesn't like to be repositioned. */
   else if (unlikely (hb_in_range<hb_codepoint_t> (u, 0x2010u, 0x2011u)))
 				    cat = OT_PLACEHOLDER;
   else if (unlikely (u == 0x25CCu)) cat = OT_DOTTEDCIRCLE;
 
 
   /*
    * Re-assign position.
@@ -672,16 +686,31 @@ static void
 initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan,
 				       hb_face_t *face,
 				       hb_buffer_t *buffer,
 				       unsigned int start, unsigned int end)
 {
   const indic_shape_plan_t *indic_plan = (const indic_shape_plan_t *) plan->data;
   hb_glyph_info_t *info = buffer->info;
 
+  /* https://github.com/behdad/harfbuzz/issues/435#issuecomment-335560167
+   * // For compatibility with legacy useage in Kannada,
+   * // Ra+h+ZWJ must behave like Ra+ZWJ+h...
+   */
+  if (buffer->props.script == HB_SCRIPT_KANNADA &&
+      start + 3 <= end &&
+      is_one_of (info[start  ], FLAG (OT_Ra)) &&
+      is_one_of (info[start+1], FLAG (OT_H)) &&
+      is_one_of (info[start+2], FLAG (OT_ZWJ)))
+  {
+    buffer->merge_clusters (start+1, start+3);
+    hb_glyph_info_t tmp = info[start+1];
+    info[start+1] = info[start+2];
+    info[start+2] = tmp;
+  }
 
   /* 1. Find base consonant:
    *
    * The shaping engine finds the base consonant of the syllable, using the
    * following algorithm: starting from the end of the syllable, move backwards
    * until a consonant is found that does not have a below-base or post-base
    * form (post-base forms have to follow below-base forms), or that is not a
    * pre-base reordering Ra, or arrive at the first consonant. The consonant
@@ -837,18 +866,18 @@ initial_reordering_consonant_syllable (c
       /* Have no other consonant, so Reph is not formed and Ra becomes base. */
       has_reph = false;
     }
   }
 
 
   /* 2. Decompose and reorder Matras:
    *
-   * Each matra and any syllable modifier sign in the cluster are moved to the
-   * appropriate position relative to the consonant(s) in the cluster. The
+   * Each matra and any syllable modifier sign in the syllable are moved to the
+   * appropriate position relative to the consonant(s) in the syllable. The
    * shaping engine decomposes two- or three-part matras into their constituent
    * parts before any repositioning. Matra characters are classified by which
    * consonant in a conjunct they have affinity for and are reordered to the
    * following positions:
    *
    *   o Before first half form in the syllable
    *   o After subjoined consonants
    *   o After post-form consonant
@@ -1264,17 +1293,17 @@ final_reordering_syllable (const hb_ot_s
 			   hb_buffer_t *buffer,
 			   unsigned int start, unsigned int end)
 {
   const indic_shape_plan_t *indic_plan = (const indic_shape_plan_t *) plan->data;
   hb_glyph_info_t *info = buffer->info;
 
 
   /* This function relies heavily on halant glyphs.  Lots of ligation
-   * and possibly multiplication substitutions happened prior to this
+   * and possibly multiple substitutions happened prior to this
    * phase, and that might have messed up our properties.  Recover
    * from a particular case of that where we're fairly sure that a
    * class of OT_H is desired but has been lost. */
   if (indic_plan->virama_glyph)
   {
     unsigned int virama_glyph = indic_plan->virama_glyph;
     for (unsigned int i = start; i < end; i++)
       if (info[i].codepoint == virama_glyph &&
@@ -1288,17 +1317,17 @@ final_reordering_syllable (const hb_ot_s
   }
 
 
   /* 4. Final reordering:
    *
    * After the localized forms and basic shaping forms GSUB features have been
    * applied (see below), the shaping engine performs some final glyph
    * reordering before applying all the remaining font features to the entire
-   * cluster.
+   * syllable.
    */
 
   bool try_pref = !!indic_plan->mask_array[PREF];
 
   /* Find base again */
   unsigned int base;
   for (base = start; base < end; base++)
     if (info[base].indic_position() >= POS_BASE_C)
@@ -1671,18 +1700,18 @@ final_reordering_syllable (const hb_ot_s
   {
     switch ((hb_tag_t) plan->props.script)
     {
       case HB_SCRIPT_TAMIL:
       case HB_SCRIPT_SINHALA:
         break;
 
       default:
-	/* Uniscribe merges the entire cluster... Except for Tamil & Sinhala.
-	 * This means, half forms are submerged into the main consonants cluster.
+	/* Uniscribe merges the entire syllable into a single cluster... Except for Tamil & Sinhala.
+	 * This means, half forms are submerged into the main consonant's cluster.
 	 * This is unnecessary, and makes cursor positioning harder, but that's what
 	 * Uniscribe does. */
 	buffer->merge_clusters (start, end);
 	break;
     }
   }
 }
 
@@ -1821,11 +1850,12 @@ const hb_ot_complex_shaper_t _hb_ot_comp
   data_destroy_indic,
   NULL, /* preprocess_text */
   NULL, /* postprocess_glyphs */
   HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT,
   decompose_indic,
   compose_indic,
   setup_masks_indic,
   NULL, /* disable_otl */
+  NULL, /* reorder_marks */
   HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE,
   false, /* fallback_position */
 };
--- a/gfx/harfbuzz/src/hb-ot-shape-complex-myanmar-machine.hh
+++ b/gfx/harfbuzz/src/hb-ot-shape-complex-myanmar-machine.hh
@@ -29,248 +29,252 @@
 #ifndef HB_OT_SHAPE_COMPLEX_MYANMAR_MACHINE_HH
 #define HB_OT_SHAPE_COMPLEX_MYANMAR_MACHINE_HH
 
 #include "hb-private.hh"
 
 
 #line 36 "hb-ot-shape-complex-myanmar-machine.hh"
 static const unsigned char _myanmar_syllable_machine_trans_keys[] = {
-	1u, 31u, 3u, 30u, 5u, 29u, 5u, 8u, 5u, 29u, 3u, 25u, 5u, 25u, 5u, 25u, 
+	1u, 32u, 3u, 30u, 5u, 29u, 5u, 8u, 5u, 29u, 3u, 25u, 5u, 25u, 5u, 25u, 
 	3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, 1u, 16u, 3u, 29u, 3u, 29u, 3u, 29u, 
 	3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, 5u, 29u, 5u, 8u, 
 	5u, 29u, 3u, 25u, 5u, 25u, 5u, 25u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, 
-	3u, 30u, 3u, 29u, 1u, 30u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, 
-	3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, 8u, 8u, 0
+	3u, 30u, 3u, 29u, 1u, 32u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, 
+	3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, 1u, 32u, 8u, 8u, 0
 };
 
 static const char _myanmar_syllable_machine_key_spans[] = {
-	31, 28, 25, 4, 25, 23, 21, 21, 
+	32, 28, 25, 4, 25, 23, 21, 21, 
 	27, 27, 27, 27, 16, 27, 27, 27, 
 	27, 27, 27, 27, 27, 27, 25, 4, 
 	25, 23, 21, 21, 27, 27, 27, 27, 
-	28, 27, 30, 27, 27, 27, 27, 27, 
-	27, 27, 27, 27, 1
+	28, 27, 32, 27, 27, 27, 27, 27, 
+	27, 27, 27, 27, 32, 1
 };
 
 static const short _myanmar_syllable_machine_index_offsets[] = {
-	0, 32, 61, 87, 92, 118, 142, 164, 
-	186, 214, 242, 270, 298, 315, 343, 371, 
-	399, 427, 455, 483, 511, 539, 567, 593, 
-	598, 624, 648, 670, 692, 720, 748, 776, 
-	804, 833, 861, 892, 920, 948, 976, 1004, 
-	1032, 1060, 1088, 1116, 1144
+	0, 33, 62, 88, 93, 119, 143, 165, 
+	187, 215, 243, 271, 299, 316, 344, 372, 
+	400, 428, 456, 484, 512, 540, 568, 594, 
+	599, 625, 649, 671, 693, 721, 749, 777, 
+	805, 834, 862, 895, 923, 951, 979, 1007, 
+	1035, 1063, 1091, 1119, 1147, 1180
 };
 
 static const char _myanmar_syllable_machine_indicies[] = {
 	1, 1, 2, 3, 4, 4, 0, 5, 
 	0, 6, 1, 0, 0, 0, 0, 7, 
-	0, 8, 1, 0, 9, 10, 11, 12, 
-	13, 14, 15, 16, 17, 18, 19, 0, 
-	21, 22, 23, 23, 20, 24, 20, 25, 
-	20, 20, 20, 20, 20, 20, 20, 26, 
-	20, 20, 27, 28, 29, 30, 31, 32, 
-	33, 34, 35, 36, 20, 23, 23, 20, 
-	24, 20, 20, 20, 20, 20, 20, 20, 
-	20, 20, 37, 20, 20, 20, 20, 20, 
-	20, 31, 20, 20, 20, 35, 20, 23, 
-	23, 20, 24, 20, 23, 23, 20, 24, 
-	20, 20, 20, 20, 20, 20, 20, 20, 
-	20, 20, 20, 20, 20, 20, 20, 20, 
-	31, 20, 20, 20, 35, 20, 38, 20, 
-	23, 23, 20, 24, 20, 31, 20, 20, 
-	20, 20, 20, 20, 20, 39, 20, 20, 
-	20, 20, 20, 20, 31, 20, 23, 23, 
-	20, 24, 20, 20, 20, 20, 20, 20, 
-	20, 20, 20, 39, 20, 20, 20, 20, 
-	20, 20, 31, 20, 23, 23, 20, 24, 
-	20, 20, 20, 20, 20, 20, 20, 20, 
-	20, 20, 20, 20, 20, 20, 20, 20, 
-	31, 20, 21, 20, 23, 23, 20, 24, 
-	20, 25, 20, 20, 20, 20, 20, 20, 
-	20, 40, 20, 20, 40, 20, 20, 20, 
-	31, 41, 20, 20, 35, 20, 21, 20, 
-	23, 23, 20, 24, 20, 25, 20, 20, 
-	20, 20, 20, 20, 20, 20, 20, 20, 
-	20, 20, 20, 20, 31, 20, 20, 20, 
-	35, 20, 21, 20, 23, 23, 20, 24, 
-	20, 25, 20, 20, 20, 20, 20, 20, 
-	20, 40, 20, 20, 20, 20, 20, 20, 
-	31, 41, 20, 20, 35, 20, 21, 20, 
-	23, 23, 20, 24, 20, 25, 20, 20, 
-	20, 20, 20, 20, 20, 20, 20, 20, 
-	20, 20, 20, 20, 31, 41, 20, 20, 
-	35, 20, 1, 1, 20, 20, 20, 20, 
-	20, 20, 20, 20, 20, 20, 20, 20, 
-	20, 1, 20, 21, 20, 23, 23, 20, 
-	24, 20, 25, 20, 20, 20, 20, 20, 
-	20, 20, 26, 20, 20, 27, 28, 29, 
-	30, 31, 32, 33, 34, 35, 20, 21, 
-	20, 23, 23, 20, 24, 20, 25, 20, 
-	20, 20, 20, 20, 20, 20, 34, 20, 
-	20, 20, 20, 20, 20, 31, 32, 33, 
-	34, 35, 20, 21, 20, 23, 23, 20, 
-	24, 20, 25, 20, 20, 20, 20, 20, 
-	20, 20, 20, 20, 20, 20, 20, 20, 
-	20, 31, 32, 33, 34, 35, 20, 21, 
-	20, 23, 23, 20, 24, 20, 25, 20, 
-	20, 20, 20, 20, 20, 20, 20, 20, 
-	20, 20, 20, 20, 20, 31, 32, 33, 
-	20, 35, 20, 21, 20, 23, 23, 20, 
-	24, 20, 25, 20, 20, 20, 20, 20, 
-	20, 20, 20, 20, 20, 20, 20, 20, 
-	20, 31, 20, 33, 20, 35, 20, 21, 
-	20, 23, 23, 20, 24, 20, 25, 20, 
-	20, 20, 20, 20, 20, 20, 34, 20, 
-	20, 27, 20, 29, 20, 31, 32, 33, 
-	34, 35, 20, 21, 20, 23, 23, 20, 
-	24, 20, 25, 20, 20, 20, 20, 20, 
-	20, 20, 34, 20, 20, 27, 20, 20, 
-	20, 31, 32, 33, 34, 35, 20, 21, 
-	20, 23, 23, 20, 24, 20, 25, 20, 
-	20, 20, 20, 20, 20, 20, 34, 20, 
-	20, 27, 28, 29, 20, 31, 32, 33, 
-	34, 35, 20, 21, 22, 23, 23, 20, 
-	24, 20, 25, 20, 20, 20, 20, 20, 
-	20, 20, 26, 20, 20, 27, 28, 29, 
-	30, 31, 32, 33, 34, 35, 20, 3, 
-	3, 42, 5, 42, 42, 42, 42, 42, 
-	42, 42, 42, 42, 43, 42, 42, 42, 
-	42, 42, 42, 13, 42, 42, 42, 17, 
-	42, 3, 3, 42, 5, 42, 3, 3, 
-	42, 5, 42, 42, 42, 42, 42, 42, 
-	42, 42, 42, 42, 42, 42, 42, 42, 
-	42, 42, 13, 42, 42, 42, 17, 42, 
-	44, 42, 3, 3, 42, 5, 42, 13, 
-	42, 42, 42, 42, 42, 42, 42, 45, 
-	42, 42, 42, 42, 42, 42, 13, 42, 
-	3, 3, 42, 5, 42, 42, 42, 42, 
-	42, 42, 42, 42, 42, 45, 42, 42, 
-	42, 42, 42, 42, 13, 42, 3, 3, 
-	42, 5, 42, 42, 42, 42, 42, 42, 
-	42, 42, 42, 42, 42, 42, 42, 42, 
-	42, 42, 13, 42, 2, 42, 3, 3, 
-	42, 5, 42, 6, 42, 42, 42, 42, 
-	42, 42, 42, 46, 42, 42, 46, 42, 
-	42, 42, 13, 47, 42, 42, 17, 42, 
-	2, 42, 3, 3, 42, 5, 42, 6, 
-	42, 42, 42, 42, 42, 42, 42, 42, 
-	42, 42, 42, 42, 42, 42, 13, 42, 
-	42, 42, 17, 42, 2, 42, 3, 3, 
-	42, 5, 42, 6, 42, 42, 42, 42, 
-	42, 42, 42, 46, 42, 42, 42, 42, 
-	42, 42, 13, 47, 42, 42, 17, 42, 
-	2, 42, 3, 3, 42, 5, 42, 6, 
-	42, 42, 42, 42, 42, 42, 42, 42, 
-	42, 42, 42, 42, 42, 42, 13, 47, 
-	42, 42, 17, 42, 21, 22, 23, 23, 
-	20, 24, 20, 25, 20, 20, 20, 20, 
-	20, 20, 20, 48, 20, 20, 27, 28, 
+	0, 8, 9, 0, 10, 11, 12, 13, 
+	14, 15, 16, 17, 18, 19, 20, 1, 
+	0, 22, 23, 24, 24, 21, 25, 21, 
+	26, 21, 21, 21, 21, 21, 21, 21, 
+	27, 21, 21, 28, 29, 30, 31, 32, 
+	33, 34, 35, 36, 37, 21, 24, 24, 
+	21, 25, 21, 21, 21, 21, 21, 21, 
+	21, 21, 21, 38, 21, 21, 21, 21, 
+	21, 21, 32, 21, 21, 21, 36, 21, 
+	24, 24, 21, 25, 21, 24, 24, 21, 
+	25, 21, 21, 21, 21, 21, 21, 21, 
+	21, 21, 21, 21, 21, 21, 21, 21, 
+	21, 32, 21, 21, 21, 36, 21, 39, 
+	21, 24, 24, 21, 25, 21, 32, 21, 
+	21, 21, 21, 21, 21, 21, 40, 21, 
+	21, 21, 21, 21, 21, 32, 21, 24, 
+	24, 21, 25, 21, 21, 21, 21, 21, 
+	21, 21, 21, 21, 40, 21, 21, 21, 
+	21, 21, 21, 32, 21, 24, 24, 21, 
+	25, 21, 21, 21, 21, 21, 21, 21, 
+	21, 21, 21, 21, 21, 21, 21, 21, 
+	21, 32, 21, 22, 21, 24, 24, 21, 
+	25, 21, 26, 21, 21, 21, 21, 21, 
+	21, 21, 41, 21, 21, 41, 21, 21, 
+	21, 32, 42, 21, 21, 36, 21, 22, 
+	21, 24, 24, 21, 25, 21, 26, 21, 
+	21, 21, 21, 21, 21, 21, 21, 21, 
+	21, 21, 21, 21, 21, 32, 21, 21, 
+	21, 36, 21, 22, 21, 24, 24, 21, 
+	25, 21, 26, 21, 21, 21, 21, 21, 
+	21, 21, 41, 21, 21, 21, 21, 21, 
+	21, 32, 42, 21, 21, 36, 21, 22, 
+	21, 24, 24, 21, 25, 21, 26, 21, 
+	21, 21, 21, 21, 21, 21, 21, 21, 
+	21, 21, 21, 21, 21, 32, 42, 21, 
+	21, 36, 21, 1, 1, 21, 21, 21, 
+	21, 21, 21, 21, 21, 21, 21, 21, 
+	21, 21, 1, 21, 22, 21, 24, 24, 
+	21, 25, 21, 26, 21, 21, 21, 21, 
+	21, 21, 21, 27, 21, 21, 28, 29, 
+	30, 31, 32, 33, 34, 35, 36, 21, 
+	22, 21, 24, 24, 21, 25, 21, 26, 
+	21, 21, 21, 21, 21, 21, 21, 35, 
+	21, 21, 21, 21, 21, 21, 32, 33, 
+	34, 35, 36, 21, 22, 21, 24, 24, 
+	21, 25, 21, 26, 21, 21, 21, 21, 
+	21, 21, 21, 21, 21, 21, 21, 21, 
+	21, 21, 32, 33, 34, 35, 36, 21, 
+	22, 21, 24, 24, 21, 25, 21, 26, 
+	21, 21, 21, 21, 21, 21, 21, 21, 
+	21, 21, 21, 21, 21, 21, 32, 33, 
+	34, 21, 36, 21, 22, 21, 24, 24, 
+	21, 25, 21, 26, 21, 21, 21, 21, 
+	21, 21, 21, 21, 21, 21, 21, 21, 
+	21, 21, 32, 21, 34, 21, 36, 21, 
+	22, 21, 24, 24, 21, 25, 21, 26, 
+	21, 21, 21, 21, 21, 21, 21, 35, 
+	21, 21, 28, 21, 30, 21, 32, 33, 
+	34, 35, 36, 21, 22, 21, 24, 24, 
+	21, 25, 21, 26, 21, 21, 21, 21, 
+	21, 21, 21, 35, 21, 21, 28, 21, 
+	21, 21, 32, 33, 34, 35, 36, 21, 
+	22, 21, 24, 24, 21, 25, 21, 26, 
+	21, 21, 21, 21, 21, 21, 21, 35, 
+	21, 21, 28, 29, 30, 21, 32, 33, 
+	34, 35, 36, 21, 22, 23, 24, 24, 
+	21, 25, 21, 26, 21, 21, 21, 21, 
+	21, 21, 21, 27, 21, 21, 28, 29, 
+	30, 31, 32, 33, 34, 35, 36, 21, 
+	3, 3, 43, 5, 43, 43, 43, 43, 
+	43, 43, 43, 43, 43, 44, 43, 43, 
+	43, 43, 43, 43, 14, 43, 43, 43, 
+	18, 43, 3, 3, 43, 5, 43, 3, 
+	3, 43, 5, 43, 43, 43, 43, 43, 
+	43, 43, 43, 43, 43, 43, 43, 43, 
+	43, 43, 43, 14, 43, 43, 43, 18, 
+	43, 45, 43, 3, 3, 43, 5, 43, 
+	14, 43, 43, 43, 43, 43, 43, 43, 
+	46, 43, 43, 43, 43, 43, 43, 14, 
+	43, 3, 3, 43, 5, 43, 43, 43, 
+	43, 43, 43, 43, 43, 43, 46, 43, 
+	43, 43, 43, 43, 43, 14, 43, 3, 
+	3, 43, 5, 43, 43, 43, 43, 43, 
+	43, 43, 43, 43, 43, 43, 43, 43, 
+	43, 43, 43, 14, 43, 2, 43, 3, 
+	3, 43, 5, 43, 6, 43, 43, 43, 
+	43, 43, 43, 43, 47, 43, 43, 47, 
+	43, 43, 43, 14, 48, 43, 43, 18, 
+	43, 2, 43, 3, 3, 43, 5, 43, 
+	6, 43, 43, 43, 43, 43, 43, 43, 
+	43, 43, 43, 43, 43, 43, 43, 14, 
+	43, 43, 43, 18, 43, 2, 43, 3, 
+	3, 43, 5, 43, 6, 43, 43, 43, 
+	43, 43, 43, 43, 47, 43, 43, 43, 
+	43, 43, 43, 14, 48, 43, 43, 18, 
+	43, 2, 43, 3, 3, 43, 5, 43, 
+	6, 43, 43, 43, 43, 43, 43, 43, 
+	43, 43, 43, 43, 43, 43, 43, 14, 
+	48, 43, 43, 18, 43, 22, 23, 24, 
+	24, 21, 25, 21, 26, 21, 21, 21, 
+	21, 21, 21, 21, 49, 21, 21, 28, 
 	29, 30, 31, 32, 33, 34, 35, 36, 
-	20, 21, 49, 23, 23, 20, 24, 20, 
-	25, 20, 20, 20, 20, 20, 20, 20, 
-	26, 20, 20, 27, 28, 29, 30, 31, 
-	32, 33, 34, 35, 20, 1, 1, 2, 
-	3, 3, 3, 42, 5, 42, 6, 1, 
-	42, 42, 42, 42, 1, 42, 8, 1, 
-	42, 9, 10, 11, 12, 13, 14, 15, 
-	16, 17, 18, 42, 2, 42, 3, 3, 
-	42, 5, 42, 6, 42, 42, 42, 42, 
-	42, 42, 42, 8, 42, 42, 9, 10, 
-	11, 12, 13, 14, 15, 16, 17, 42, 
-	2, 42, 3, 3, 42, 5, 42, 6, 
-	42, 42, 42, 42, 42, 42, 42, 16, 
-	42, 42, 42, 42, 42, 42, 13, 14, 
-	15, 16, 17, 42, 2, 42, 3, 3, 
-	42, 5, 42, 6, 42, 42, 42, 42, 
-	42, 42, 42, 42, 42, 42, 42, 42, 
-	42, 42, 13, 14, 15, 16, 17, 42, 
-	2, 42, 3, 3, 42, 5, 42, 6, 
-	42, 42, 42, 42, 42, 42, 42, 42, 
-	42, 42, 42, 42, 42, 42, 13, 14, 
-	15, 42, 17, 42, 2, 42, 3, 3, 
-	42, 5, 42, 6, 42, 42, 42, 42, 
-	42, 42, 42, 42, 42, 42, 42, 42, 
-	42, 42, 13, 42, 15, 42, 17, 42, 
-	2, 42, 3, 3, 42, 5, 42, 6, 
-	42, 42, 42, 42, 42, 42, 42, 16, 
-	42, 42, 9, 42, 11, 42, 13, 14, 
-	15, 16, 17, 42, 2, 42, 3, 3, 
-	42, 5, 42, 6, 42, 42, 42, 42, 
-	42, 42, 42, 16, 42, 42, 9, 42, 
-	42, 42, 13, 14, 15, 16, 17, 42, 
-	2, 42, 3, 3, 42, 5, 42, 6, 
-	42, 42, 42, 42, 42, 42, 42, 16, 
-	42, 42, 9, 10, 11, 42, 13, 14, 
-	15, 16, 17, 42, 2, 3, 3, 3, 
-	42, 5, 42, 6, 42, 42, 42, 42, 
-	42, 42, 42, 8, 42, 42, 9, 10, 
-	11, 12, 13, 14, 15, 16, 17, 42, 
-	51, 50, 0
+	37, 21, 22, 50, 24, 24, 21, 25, 
+	21, 26, 21, 21, 21, 21, 21, 21, 
+	21, 27, 21, 21, 28, 29, 30, 31, 
+	32, 33, 34, 35, 36, 21, 1, 1, 
+	2, 3, 3, 3, 43, 5, 43, 6, 
+	1, 43, 43, 43, 43, 1, 43, 8, 
+	43, 43, 10, 11, 12, 13, 14, 15, 
+	16, 17, 18, 19, 43, 1, 43, 2, 
+	43, 3, 3, 43, 5, 43, 6, 43, 
+	43, 43, 43, 43, 43, 43, 8, 43, 
+	43, 10, 11, 12, 13, 14, 15, 16, 
+	17, 18, 43, 2, 43, 3, 3, 43, 
+	5, 43, 6, 43, 43, 43, 43, 43, 
+	43, 43, 17, 43, 43, 43, 43, 43, 
+	43, 14, 15, 16, 17, 18, 43, 2, 
+	43, 3, 3, 43, 5, 43, 6, 43, 
+	43, 43, 43, 43, 43, 43, 43, 43, 
+	43, 43, 43, 43, 43, 14, 15, 16, 
+	17, 18, 43, 2, 43, 3, 3, 43, 
+	5, 43, 6, 43, 43, 43, 43, 43, 
+	43, 43, 43, 43, 43, 43, 43, 43, 
+	43, 14, 15, 16, 43, 18, 43, 2, 
+	43, 3, 3, 43, 5, 43, 6, 43, 
+	43, 43, 43, 43, 43, 43, 43, 43, 
+	43, 43, 43, 43, 43, 14, 43, 16, 
+	43, 18, 43, 2, 43, 3, 3, 43, 
+	5, 43, 6, 43, 43, 43, 43, 43, 
+	43, 43, 17, 43, 43, 10, 43, 12, 
+	43, 14, 15, 16, 17, 18, 43, 2, 
+	43, 3, 3, 43, 5, 43, 6, 43, 
+	43, 43, 43, 43, 43, 43, 17, 43, 
+	43, 10, 43, 43, 43, 14, 15, 16, 
+	17, 18, 43, 2, 43, 3, 3, 43, 
+	5, 43, 6, 43, 43, 43, 43, 43, 
+	43, 43, 17, 43, 43, 10, 11, 12, 
+	43, 14, 15, 16, 17, 18, 43, 2, 
+	3, 3, 3, 43, 5, 43, 6, 43, 
+	43, 43, 43, 43, 43, 43, 8, 43, 
+	43, 10, 11, 12, 13, 14, 15, 16, 
+	17, 18, 43, 1, 1, 51, 51, 51, 
+	51, 51, 51, 51, 51, 1, 51, 51, 
+	51, 51, 1, 51, 51, 51, 51, 51, 
+	51, 51, 51, 51, 51, 51, 51, 51, 
+	51, 51, 1, 51, 52, 51, 0
 };
 
 static const char _myanmar_syllable_machine_trans_targs[] = {
 	0, 1, 22, 0, 0, 23, 29, 32, 
-	35, 36, 40, 41, 42, 25, 38, 39, 
-	37, 28, 43, 44, 0, 2, 12, 0, 
-	3, 9, 13, 14, 18, 19, 20, 5, 
-	16, 17, 15, 8, 21, 4, 6, 7, 
-	10, 11, 0, 24, 26, 27, 30, 31, 
-	33, 34, 0, 0
+	35, 44, 36, 40, 41, 42, 25, 38, 
+	39, 37, 28, 43, 45, 0, 2, 12, 
+	0, 3, 9, 13, 14, 18, 19, 20, 
+	5, 16, 17, 15, 8, 21, 4, 6, 
+	7, 10, 11, 0, 24, 26, 27, 30, 
+	31, 33, 34, 0, 0
 };
 
 static const char _myanmar_syllable_machine_trans_actions[] = {
 	3, 0, 0, 4, 5, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 6, 0, 0, 7, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
+	0, 0, 0, 0, 0, 6, 0, 0, 
+	7, 0, 0, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 8, 0, 0, 0, 0, 0, 
-	0, 0, 9, 10
+	0, 0, 0, 8, 0, 0, 0, 0, 
+	0, 0, 0, 9, 10
 };
 
 static const char _myanmar_syllable_machine_to_state_actions[] = {
 	1, 0, 0, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0
+	0, 0, 0, 0, 0, 0
 };
 
 static const char _myanmar_syllable_machine_from_state_actions[] = {
 	2, 0, 0, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0
+	0, 0, 0, 0, 0, 0
 };
 
 static const short _myanmar_syllable_machine_eof_trans[] = {
-	0, 21, 21, 21, 21, 21, 21, 21, 
-	21, 21, 21, 21, 21, 21, 21, 21, 
-	21, 21, 21, 21, 21, 21, 43, 43, 
-	43, 43, 43, 43, 43, 43, 43, 43, 
-	21, 21, 43, 43, 43, 43, 43, 43, 
-	43, 43, 43, 43, 51
+	0, 22, 22, 22, 22, 22, 22, 22, 
+	22, 22, 22, 22, 22, 22, 22, 22, 
+	22, 22, 22, 22, 22, 22, 44, 44, 
+	44, 44, 44, 44, 44, 44, 44, 44, 
+	22, 22, 44, 44, 44, 44, 44, 44, 
+	44, 44, 44, 44, 52, 52
 };
 
 static const int myanmar_syllable_machine_start = 0;
 static const int myanmar_syllable_machine_first_final = 0;
 static const int myanmar_syllable_machine_error = -1;
 
 static const int myanmar_syllable_machine_en_main = 0;
 
 
 #line 36 "hb-ot-shape-complex-myanmar-machine.rl"
 
 
 
-#line 93 "hb-ot-shape-complex-myanmar-machine.rl"
+#line 94 "hb-ot-shape-complex-myanmar-machine.rl"
 
 
 #define found_syllable(syllable_type) \
   HB_STMT_START { \
     if (0) fprintf (stderr, "syllable %d..%d %s\n", last, p+1, #syllable_type); \
     for (unsigned int i = last; i < p+1; i++) \
       info[i].syllable() = (syllable_serial << 4) | syllable_type; \
     last = p+1; \
@@ -280,48 +284,48 @@ static const int myanmar_syllable_machin
 
 static void
 find_syllables (hb_buffer_t *buffer)
 {
   unsigned int p, pe, eof, ts HB_UNUSED, te HB_UNUSED, act HB_UNUSED;
   int cs;
   hb_glyph_info_t *info = buffer->info;
   
-#line 289 "hb-ot-shape-complex-myanmar-machine.hh"
+#line 293 "hb-ot-shape-complex-myanmar-machine.hh"
 	{
 	cs = myanmar_syllable_machine_start;
 	ts = 0;
 	te = 0;
 	act = 0;
 	}
 
-#line 114 "hb-ot-shape-complex-myanmar-machine.rl"
+#line 115 "hb-ot-shape-complex-myanmar-machine.rl"
 
 
   p = 0;
   pe = eof = buffer->len;
 
   unsigned int last = 0;
   unsigned int syllable_serial = 1;
   
-#line 306 "hb-ot-shape-complex-myanmar-machine.hh"
+#line 310 "hb-ot-shape-complex-myanmar-machine.hh"
 	{
 	int _slen;
 	int _trans;
 	const unsigned char *_keys;
 	const char *_inds;
 	if ( p == pe )
 		goto _test_eof;
 _resume:
 	switch ( _myanmar_syllable_machine_from_state_actions[cs] ) {
 	case 2:
 #line 1 "NONE"
 	{ts = p;}
 	break;
-#line 320 "hb-ot-shape-complex-myanmar-machine.hh"
+#line 324 "hb-ot-shape-complex-myanmar-machine.hh"
 	}
 
 	_keys = _myanmar_syllable_machine_trans_keys + (cs<<1);
 	_inds = _myanmar_syllable_machine_indicies + _myanmar_syllable_machine_index_offsets[cs];
 
 	_slen = _myanmar_syllable_machine_key_spans[cs];
 	_trans = _inds[ _slen > 0 && _keys[0] <=( info[p].myanmar_category()) &&
 		( info[p].myanmar_category()) <= _keys[1] ?
@@ -330,71 +334,71 @@ find_syllables (hb_buffer_t *buffer)
 _eof_trans:
 	cs = _myanmar_syllable_machine_trans_targs[_trans];
 
 	if ( _myanmar_syllable_machine_trans_actions[_trans] == 0 )
 		goto _again;
 
 	switch ( _myanmar_syllable_machine_trans_actions[_trans] ) {
 	case 7:
-#line 85 "hb-ot-shape-complex-myanmar-machine.rl"
+#line 86 "hb-ot-shape-complex-myanmar-machine.rl"
 	{te = p+1;{ found_syllable (consonant_syllable); }}
 	break;
 	case 5:
-#line 86 "hb-ot-shape-complex-myanmar-machine.rl"
+#line 87 "hb-ot-shape-complex-myanmar-machine.rl"
 	{te = p+1;{ found_syllable (non_myanmar_cluster); }}
 	break;
 	case 10:
-#line 87 "hb-ot-shape-complex-myanmar-machine.rl"
+#line 88 "hb-ot-shape-complex-myanmar-machine.rl"
 	{te = p+1;{ found_syllable (punctuation_cluster); }}
 	break;
 	case 4:
-#line 88 "hb-ot-shape-complex-myanmar-machine.rl"
+#line 89 "hb-ot-shape-complex-myanmar-machine.rl"
 	{te = p+1;{ found_syllable (broken_cluster); }}
 	break;
 	case 3:
-#line 89 "hb-ot-shape-complex-myanmar-machine.rl"
+#line 90 "hb-ot-shape-complex-myanmar-machine.rl"
 	{te = p+1;{ found_syllable (non_myanmar_cluster); }}
 	break;
 	case 6:
-#line 85 "hb-ot-shape-complex-myanmar-machine.rl"
+#line 86 "hb-ot-shape-complex-myanmar-machine.rl"
 	{te = p;p--;{ found_syllable (consonant_syllable); }}
 	break;
 	case 8:
-#line 88 "hb-ot-shape-complex-myanmar-machine.rl"
+#line 89 "hb-ot-shape-complex-myanmar-machine.rl"
 	{te = p;p--;{ found_syllable (broken_cluster); }}
 	break;
 	case 9:
-#line 89 "hb-ot-shape-complex-myanmar-machine.rl"
+#line 90 "hb-ot-shape-complex-myanmar-machine.rl"
 	{te = p;p--;{ found_syllable (non_myanmar_cluster); }}
 	break;
-#line 370 "hb-ot-shape-complex-myanmar-machine.hh"
+#line 374 "hb-ot-shape-complex-myanmar-machine.hh"
 	}
 
 _again:
 	switch ( _myanmar_syllable_machine_to_state_actions[cs] ) {
 	case 1:
 #line 1 "NONE"
 	{ts = 0;}
 	break;
-#line 379 "hb-ot-shape-complex-myanmar-machine.hh"
+#line 383 "hb-ot-shape-complex-myanmar-machine.hh"
 	}
 
 	if ( ++p != pe )
 		goto _resume;
 	_test_eof: {}
 	if ( p == eof )
 	{
 	if ( _myanmar_syllable_machine_eof_trans[cs] > 0 ) {
 		_trans = _myanmar_syllable_machine_eof_trans[cs] - 1;
 		goto _eof_trans;
 	}
 	}
 
 	}
 
-#line 123 "hb-ot-shape-complex-myanmar-machine.rl"
+#line 124 "hb-ot-shape-complex-myanmar-machine.rl"
 
 }
 
 #undef found_syllable
 
 #endif /* HB_OT_SHAPE_COMPLEX_MYANMAR_MACHINE_HH */
--- a/gfx/harfbuzz/src/hb-ot-shape-complex-myanmar-machine.rl
+++ b/gfx/harfbuzz/src/hb-ot-shape-complex-myanmar-machine.rl
@@ -36,17 +36,17 @@
 }%%
 
 %%{
 
 # Same order as enum myanmar_category_t.  Not sure how to avoid duplication.
 A    = 10;
 As   = 18;
 C    = 1;
-D    = 19;
+D    = 32;
 D0   = 20;
 DB   = 3;
 GB   = 11;
 H    = 4;
 IV   = 2;
 MH   = 21;
 MR   = 22;
 MW   = 23;
@@ -57,31 +57,32 @@ VAbv = 26;
 VBlw = 27;
 VPre = 28;
 VPst = 29;
 VS   = 30;
 ZWJ  = 6;
 ZWNJ = 5;
 Ra   = 16;
 P    = 31;
+CS   = 19;
 
 j = ZWJ|ZWNJ;			# Joiners
 k = (Ra As H);			# Kinzi
 
 c = C|Ra;			# is_consonant
 
 medial_group = MY? MR? MW? MH? As?;
 main_vowel_group = VPre* VAbv* VBlw* A* (DB As?)?;
 post_vowel_group = VPst MH? As* VAbv* A* (DB As?)?;
 pwo_tone_group = PT A* DB? As?;
 
 complex_syllable_tail = As* medial_group main_vowel_group post_vowel_group* pwo_tone_group* V* j?;
 syllable_tail = (H | complex_syllable_tail);
 
-consonant_syllable =	k? (c|IV|D|GB).VS? (H (c|IV).VS?)* syllable_tail;
+consonant_syllable =	(k|CS)? (c|IV|D|GB).VS? (H (c|IV).VS?)* syllable_tail;
 punctuation_cluster = 	P V;
 broken_cluster =	k? VS? syllable_tail;
 other =			any;
 
 main := |*
 	consonant_syllable	=> { found_syllable (consonant_syllable); };
 	j			=> { found_syllable (non_myanmar_cluster); };
 	punctuation_cluster	=> { found_syllable (punctuation_cluster); };
--- a/gfx/harfbuzz/src/hb-ot-shape-complex-myanmar.cc
+++ b/gfx/harfbuzz/src/hb-ot-shape-complex-myanmar.cc
@@ -125,32 +125,32 @@ enum syllable_type_t {
 };
 
 #include "hb-ot-shape-complex-myanmar-machine.hh"
 
 
 /* Note: This enum is duplicated in the -machine.rl source file.
  * Not sure how to avoid duplication. */
 enum myanmar_category_t {
-  OT_As  = 18, /* Asat */
-  OT_D   = 19, /* Digits except zero */
+  OT_As  = 18,  /* Asat */
   OT_D0  = 20, /* Digit zero */
   OT_DB  = OT_N, /* Dot below */
   OT_GB  = OT_PLACEHOLDER,
   OT_MH  = 21, /* Various consonant medial types */
   OT_MR  = 22, /* Various consonant medial types */
   OT_MW  = 23, /* Various consonant medial types */
   OT_MY  = 24, /* Various consonant medial types */
   OT_PT  = 25, /* Pwo and other tones */
   OT_VAbv = 26,
   OT_VBlw = 27,
   OT_VPre = 28,
   OT_VPst = 29,
   OT_VS   = 30, /* Variation selectors */
-  OT_P    = 31  /* Punctuation */
+  OT_P    = 31, /* Punctuation */
+  OT_D    = 32, /* Digits except zero */
 };
 
 
 static inline bool
 is_one_of (const hb_glyph_info_t &info, unsigned int flags)
 {
   /* If it ligated, all bets are off. */
   if (_hb_glyph_info_ligated (&info)) return false;
@@ -519,16 +519,17 @@ const hb_ot_complex_shaper_t _hb_ot_comp
   NULL, /* data_destroy */
   NULL, /* preprocess_text */
   NULL, /* postprocess_glyphs */
   HB_OT_SHAPE_NORMALIZATION_MODE_DEFAULT,
   NULL, /* decompose */
   NULL, /* compose */
   NULL, /* setup_masks */
   NULL, /* disable_otl */
+  NULL, /* reorder_marks */
   HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE,
   true, /* fallback_position */
 };
 
 const hb_ot_complex_shaper_t _hb_ot_complex_shaper_myanmar =
 {
   "myanmar",
   collect_features_myanmar,
@@ -537,11 +538,12 @@ const hb_ot_complex_shaper_t _hb_ot_comp
   NULL, /* data_destroy */
   NULL, /* preprocess_text */
   NULL, /* postprocess_glyphs */
   HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT,
   NULL, /* decompose */
   NULL, /* compose */
   setup_masks_myanmar,
   NULL, /* disable_otl */
+  NULL, /* reorder_marks */
   HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_EARLY,
   false, /* fallback_position */
 };
--- a/gfx/harfbuzz/src/hb-ot-shape-complex-private.hh
+++ b/gfx/harfbuzz/src/hb-ot-shape-complex-private.hh
@@ -34,16 +34,18 @@
 
 
 
 /* buffer var allocations, used by complex shapers */
 #define complex_var_u8_0()	var2.u8[2]
 #define complex_var_u8_1()	var2.u8[3]
 
 
+#define HB_OT_SHAPE_COMPLEX_MAX_COMBINING_MARKS 32
+
 enum hb_ot_shape_zero_width_marks_type_t {
   HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE,
   HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_EARLY,
   HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE
 };
 
 
 /* Master OT shaper list */
@@ -149,16 +151,26 @@ struct hb_ot_complex_shaper_t
   /* disable_otl()
    * Called during shape().
    * If set and returns true, GDEF/GSUB/GPOS of the font are ignored
    * and fallback operations used.
    * May be NULL.
    */
   bool (*disable_otl) (const hb_ot_shape_plan_t *plan);
 
+  /* reorder_marks()
+   * Called during shape().
+   * Shapers can use to modify ordering of combining marks.
+   * May be NULL.
+   */
+  void (*reorder_marks) (const hb_ot_shape_plan_t *plan,
+			 hb_buffer_t              *buffer,
+			 unsigned int              start,
+			 unsigned int              end);
+
   hb_ot_shape_zero_width_marks_type_t zero_width_marks;
 
   bool fallback_position;
 };
 
 #define HB_COMPLEX_SHAPER_IMPLEMENT(name) extern HB_INTERNAL const hb_ot_complex_shaper_t _hb_ot_complex_shaper_##name;
 HB_COMPLEX_SHAPERS_IMPLEMENT_SHAPERS
 #undef HB_COMPLEX_SHAPER_IMPLEMENT
@@ -248,20 +260,22 @@ hb_ot_shape_complex_categorize (const hb
     case HB_SCRIPT_ORIYA:
     case HB_SCRIPT_TAMIL:
     case HB_SCRIPT_TELUGU:
 
     /* Unicode-3.0 additions */
     case HB_SCRIPT_SINHALA:
 
       /* If the designer designed the font for the 'DFLT' script,
-       * use the default shaper.  Otherwise, use the specific shaper.
+       * (or we ended up arbitrarily pick 'latn'), use the default shaper.
+       * Otherwise, use the specific shaper.
        * Note that for some simple scripts, there may not be *any*
        * GSUB/GPOS needed, so there may be no scripts found! */
-      if (planner->map.chosen_script[0] == HB_TAG ('D','F','L','T'))
+      if (planner->map.chosen_script[0] == HB_TAG ('D','F','L','T') ||
+	  planner->map.chosen_script[0] == HB_TAG ('l','a','t','n'))
 	return &_hb_ot_complex_shaper_default;
       else
 	return &_hb_ot_complex_shaper_indic;
 
     case HB_SCRIPT_KHMER:
       /* A number of Khmer fonts in the wild don't have a 'pref' feature,
        * and as such won't shape properly via the Indic shaper;
        * however, they typically have 'liga' / 'clig' features that implement
@@ -357,21 +371,28 @@ hb_ot_shape_complex_categorize (const hb
     case HB_SCRIPT_AHOM:
     //case HB_SCRIPT_MULTANI:
 
     /* Unicode-9.0 additions */
     case HB_SCRIPT_BHAIKSUKI:
     case HB_SCRIPT_MARCHEN:
     case HB_SCRIPT_NEWA:
 
+    /* Unicode-10.0 additions */
+    case HB_SCRIPT_MASARAM_GONDI:
+    case HB_SCRIPT_SOYOMBO:
+    case HB_SCRIPT_ZANABAZAR_SQUARE:
+
       /* If the designer designed the font for the 'DFLT' script,
-       * use the default shaper.  Otherwise, use the specific shaper.
+       * (or we ended up arbitrarily pick 'latn'), use the default shaper.
+       * Otherwise, use the specific shaper.
        * Note that for some simple scripts, there may not be *any*
        * GSUB/GPOS needed, so there may be no scripts found! */
-      if (planner->map.chosen_script[0] == HB_TAG ('D','F','L','T'))
+      if (planner->map.chosen_script[0] == HB_TAG ('D','F','L','T') ||
+	  planner->map.chosen_script[0] == HB_TAG ('l','a','t','n'))
 	return &_hb_ot_complex_shaper_default;
       else
 	return &_hb_ot_complex_shaper_use;
   }
 }
 
 
 #endif /* HB_OT_SHAPE_COMPLEX_PRIVATE_HH */
--- a/gfx/harfbuzz/src/hb-ot-shape-complex-thai.cc
+++ b/gfx/harfbuzz/src/hb-ot-shape-complex-thai.cc
@@ -373,11 +373,12 @@ const hb_ot_complex_shaper_t _hb_ot_comp
   NULL, /* data_destroy */
   preprocess_text_thai,
   NULL, /* postprocess_glyphs */
   HB_OT_SHAPE_NORMALIZATION_MODE_DEFAULT,
   NULL, /* decompose */
   NULL, /* compose */
   NULL, /* setup_masks */
   NULL, /* disable_otl */
+  NULL, /* reorder_marks */
   HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE,
   false,/* fallback_position */
 };
--- a/gfx/harfbuzz/src/hb-ot-shape-complex-tibetan.cc
+++ b/gfx/harfbuzz/src/hb-ot-shape-complex-tibetan.cc
@@ -53,11 +53,12 @@ const hb_ot_complex_shaper_t _hb_ot_comp
   NULL, /* data_destroy */
   NULL, /* preprocess_text */
   NULL, /* postprocess_glyphs */
   HB_OT_SHAPE_NORMALIZATION_MODE_DEFAULT,
   NULL, /* decompose */
   NULL, /* compose */
   NULL, /* setup_masks */
   NULL, /* disable_otl */
+  NULL, /* reorder_marks */
   HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE,
   true, /* fallback_position */
 };
--- a/gfx/harfbuzz/src/hb-ot-shape-complex-use-machine.hh
+++ b/gfx/harfbuzz/src/hb-ot-shape-complex-use-machine.hh
@@ -31,280 +31,281 @@
 #ifndef HB_OT_SHAPE_COMPLEX_USE_MACHINE_HH
 #define HB_OT_SHAPE_COMPLEX_USE_MACHINE_HH
 
 #include "hb-private.hh"
 
 
 #line 38 "hb-ot-shape-complex-use-machine.hh"
 static const unsigned char _use_syllable_machine_trans_keys[] = {
-	1u, 1u, 0u, 39u, 21u, 21u, 8u, 39u, 8u, 39u, 1u, 1u, 8u, 39u, 8u, 39u, 
+	1u, 1u, 0u, 43u, 21u, 21u, 8u, 39u, 8u, 39u, 1u, 1u, 8u, 39u, 8u, 39u, 
 	8u, 39u, 8u, 26u, 8u, 26u, 8u, 26u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 
 	8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 
 	13u, 21u, 4u, 4u, 13u, 13u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 26u, 
 	8u, 26u, 8u, 26u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 
 	8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 1u, 1u, 1u, 39u, 8u, 39u, 
-	21u, 42u, 41u, 42u, 42u, 42u, 0
+	21u, 42u, 41u, 42u, 42u, 42u, 1u, 5u, 0
 };
 
 static const char _use_syllable_machine_key_spans[] = {
-	1, 40, 1, 32, 32, 1, 32, 32, 
+	1, 44, 1, 32, 32, 1, 32, 32, 
 	32, 19, 19, 19, 32, 32, 32, 32, 
 	32, 32, 32, 32, 32, 32, 32, 32, 
 	9, 1, 1, 32, 32, 32, 32, 19, 
 	19, 19, 32, 32, 32, 32, 32, 32, 
 	32, 32, 32, 32, 32, 1, 39, 32, 
-	22, 2, 1
+	22, 2, 1, 5
 };
 
 static const short _use_syllable_machine_index_offsets[] = {
-	0, 2, 43, 45, 78, 111, 113, 146, 
-	179, 212, 232, 252, 272, 305, 338, 371, 
-	404, 437, 470, 503, 536, 569, 602, 635, 
-	668, 678, 680, 682, 715, 748, 781, 814, 
-	834, 854, 874, 907, 940, 973, 1006, 1039, 
-	1072, 1105, 1138, 1171, 1204, 1237, 1239, 1279, 
-	1312, 1335, 1338
+	0, 2, 47, 49, 82, 115, 117, 150, 
+	183, 216, 236, 256, 276, 309, 342, 375, 
+	408, 441, 474, 507, 540, 573, 606, 639, 
+	672, 682, 684, 686, 719, 752, 785, 818, 
+	838, 858, 878, 911, 944, 977, 1010, 1043, 
+	1076, 1109, 1142, 1175, 1208, 1241, 1243, 1283, 
+	1316, 1339, 1342, 1344
 };
 
 static const char _use_syllable_machine_indicies[] = {
 	1, 0, 2, 3, 4, 2, 5, 3, 
 	4, 4, 6, 4, 4, 1, 7, 4, 
 	4, 4, 2, 2, 8, 9, 4, 4, 
 	10, 11, 12, 13, 14, 15, 16, 10, 
 	17, 18, 19, 20, 21, 22, 4, 23, 
-	24, 25, 4, 27, 26, 29, 28, 28, 
-	30, 31, 28, 28, 28, 28, 28, 28, 
-	28, 28, 32, 33, 34, 35, 36, 37, 
-	38, 39, 33, 40, 32, 41, 42, 43, 
-	44, 28, 45, 46, 47, 28, 29, 28, 
-	28, 30, 31, 28, 28, 28, 28, 28, 
-	28, 28, 28, 48, 33, 34, 35, 36, 
-	37, 38, 39, 33, 40, 41, 41, 42, 
-	43, 44, 28, 45, 46, 47, 28, 30, 
-	49, 29, 28, 28, 30, 31, 28, 28, 
-	28, 28, 28, 28, 28, 28, 28, 33, 
-	34, 35, 36, 37, 38, 39, 33, 40, 
-	41, 41, 42, 43, 44, 28, 45, 46, 
-	47, 28, 29, 28, 28, 28, 28, 28, 
-	28, 28, 28, 28, 28, 28, 28, 28, 
-	33, 34, 35, 36, 37, 28, 28, 28, 
-	28, 28, 28, 42, 43, 44, 28, 45, 
-	46, 47, 28, 29, 28, 28, 28, 28, 
-	28, 28, 28, 28, 28, 28, 28, 28, 
-	28, 28, 34, 35, 36, 37, 28, 28, 
-	28, 28, 28, 28, 28, 28, 28, 28, 
-	45, 46, 47, 28, 29, 28, 28, 28, 
-	28, 28, 28, 28, 28, 28, 28, 28, 
-	28, 28, 28, 28, 35, 36, 37, 28, 
-	29, 28, 28, 28, 28, 28, 28, 28, 
-	28, 28, 28, 28, 28, 28, 28, 28, 
-	28, 36, 37, 28, 29, 28, 28, 28, 
-	28, 28, 28, 28, 28, 28, 28, 28, 
-	28, 28, 28, 28, 28, 28, 37, 28, 
-	29, 28, 28, 28, 28, 28, 28, 28, 
-	28, 28, 28, 28, 28, 28, 28, 28, 
-	35, 36, 37, 28, 28, 28, 28, 28, 
-	28, 28, 28, 28, 28, 45, 46, 47, 
-	28, 29, 28, 28, 28, 28, 28, 28, 
-	28, 28, 28, 28, 28, 28, 28, 28, 
-	28, 35, 36, 37, 28, 28, 28, 28, 
-	28, 28, 28, 28, 28, 28, 28, 46, 
-	47, 28, 29, 28, 28, 28, 28, 28, 
-	28, 28, 28, 28, 28, 28, 28, 28, 
-	28, 28, 35, 36, 37, 28, 28, 28, 
-	28, 28, 28, 28, 28, 28, 28, 28, 
-	28, 47, 28, 29, 28, 28, 28, 28, 
-	28, 28, 28, 28, 28, 28, 28, 28, 
-	28, 28, 34, 35, 36, 37, 28, 28, 
-	28, 28, 28, 28, 42, 43, 44, 28, 
-	45, 46, 47, 28, 29, 28, 28, 28, 
-	28, 28, 28, 28, 28, 28, 28, 28, 
-	28, 28, 28, 34, 35, 36, 37, 28, 
-	28, 28, 28, 28, 28, 28, 43, 44, 
-	28, 45, 46, 47, 28, 29, 28, 28, 
-	28, 28, 28, 28, 28, 28, 28, 28, 
-	28, 28, 28, 28, 34, 35, 36, 37, 
-	28, 28, 28, 28, 28, 28, 28, 28, 
-	44, 28, 45, 46, 47, 28, 29, 28, 
-	28, 28, 28, 28, 28, 28, 28, 28, 
-	28, 28, 28, 28, 33, 34, 35, 36, 
-	37, 28, 39, 33, 28, 28, 28, 42, 
-	43, 44, 28, 45, 46, 47, 28, 29, 
-	28, 28, 28, 28, 28, 28, 28, 28, 
-	28, 28, 28, 28, 28, 33, 34, 35, 
-	36, 37, 28, 50, 33, 28, 28, 28, 
-	42, 43, 44, 28, 45, 46, 47, 28, 
-	29, 28, 28, 28, 28, 28, 28, 28, 
-	28, 28, 28, 28, 28, 28, 33, 34, 
-	35, 36, 37, 28, 28, 33, 28, 28, 
-	28, 42, 43, 44, 28, 45, 46, 47, 
-	28, 29, 28, 28, 28, 28, 28, 28, 
-	28, 28, 28, 28, 28, 28, 28, 33, 
-	34, 35, 36, 37, 38, 39, 33, 28, 
-	28, 28, 42, 43, 44, 28, 45, 46, 
-	47, 28, 29, 28, 28, 30, 31, 28, 
-	28, 28, 28, 28, 28, 28, 28, 28, 
-	33, 34, 35, 36, 37, 38, 39, 33, 
-	40, 28, 41, 42, 43, 44, 28, 45, 
-	46, 47, 28, 29, 28, 28, 30, 31, 
-	28, 28, 28, 28, 28, 28, 28, 28, 
-	28, 33, 34, 35, 36, 37, 38, 39, 
-	33, 40, 32, 41, 42, 43, 44, 28, 
-	45, 46, 47, 28, 52, 51, 51, 51, 
-	51, 51, 51, 51, 53, 51, 5, 54, 
-	52, 51, 6, 55, 55, 1, 56, 55, 
-	55, 55, 55, 55, 55, 55, 55, 57, 
+	24, 25, 4, 4, 4, 26, 4, 28, 
+	27, 30, 29, 29, 31, 32, 29, 29, 
+	29, 29, 29, 29, 29, 29, 33, 34, 
+	35, 36, 37, 38, 39, 40, 34, 41, 
+	33, 42, 43, 44, 45, 29, 46, 47, 
+	48, 29, 30, 29, 29, 31, 32, 29, 
+	29, 29, 29, 29, 29, 29, 29, 49, 
+	34, 35, 36, 37, 38, 39, 40, 34, 
+	41, 42, 42, 43, 44, 45, 29, 46, 
+	47, 48, 29, 31, 50, 30, 29, 29, 
+	31, 32, 29, 29, 29, 29, 29, 29, 
+	29, 29, 29, 34, 35, 36, 37, 38, 
+	39, 40, 34, 41, 42, 42, 43, 44, 
+	45, 29, 46, 47, 48, 29, 30, 29, 
+	29, 29, 29, 29, 29, 29, 29, 29, 
+	29, 29, 29, 29, 34, 35, 36, 37, 
+	38, 29, 29, 29, 29, 29, 29, 43, 
+	44, 45, 29, 46, 47, 48, 29, 30, 
+	29, 29, 29, 29, 29, 29, 29, 29, 
+	29, 29, 29, 29, 29, 29, 35, 36, 
+	37, 38, 29, 29, 29, 29, 29, 29, 
+	29, 29, 29, 29, 46, 47, 48, 29, 
+	30, 29, 29, 29, 29, 29, 29, 29, 
+	29, 29, 29, 29, 29, 29, 29, 29, 
+	36, 37, 38, 29, 30, 29, 29, 29, 
+	29, 29, 29, 29, 29, 29, 29, 29, 
+	29, 29, 29, 29, 29, 37, 38, 29, 
+	30, 29, 29, 29, 29, 29, 29, 29, 
+	29, 29, 29, 29, 29, 29, 29, 29, 
+	29, 29, 38, 29, 30, 29, 29, 29, 
+	29, 29, 29, 29, 29, 29, 29, 29, 
+	29, 29, 29, 29, 36, 37, 38, 29, 
+	29, 29, 29, 29, 29, 29, 29, 29, 
+	29, 46, 47, 48, 29, 30, 29, 29, 
+	29, 29, 29, 29, 29, 29, 29, 29, 
+	29, 29, 29, 29, 29, 36, 37, 38, 
+	29, 29, 29, 29, 29, 29, 29, 29, 
+	29, 29, 29, 47, 48, 29, 30, 29, 
+	29, 29, 29, 29, 29, 29, 29, 29, 
+	29, 29, 29, 29, 29, 29, 36, 37, 
+	38, 29, 29, 29, 29, 29, 29, 29, 
+	29, 29, 29, 29, 29, 48, 29, 30, 
+	29, 29, 29, 29, 29, 29, 29, 29, 
+	29, 29, 29, 29, 29, 29, 35, 36, 
+	37, 38, 29, 29, 29, 29, 29, 29, 
+	43, 44, 45, 29, 46, 47, 48, 29, 
+	30, 29, 29, 29, 29, 29, 29, 29, 
+	29, 29, 29, 29, 29, 29, 29, 35, 
+	36, 37, 38, 29, 29, 29, 29, 29, 
+	29, 29, 44, 45, 29, 46, 47, 48, 
+	29, 30, 29, 29, 29, 29, 29, 29, 
+	29, 29, 29, 29, 29, 29, 29, 29, 
+	35, 36, 37, 38, 29, 29, 29, 29, 
+	29, 29, 29, 29, 45, 29, 46, 47, 
+	48, 29, 30, 29, 29, 29, 29, 29, 
+	29, 29, 29, 29, 29, 29, 29, 29, 
+	34, 35, 36, 37, 38, 29, 40, 34, 
+	29, 29, 29, 43, 44, 45, 29, 46, 
+	47, 48, 29, 30, 29, 29, 29, 29, 
+	29, 29, 29, 29, 29, 29, 29, 29, 
+	29, 34, 35, 36, 37, 38, 29, 51, 
+	34, 29, 29, 29, 43, 44, 45, 29, 
+	46, 47, 48, 29, 30, 29, 29, 29, 
+	29, 29, 29, 29, 29, 29, 29, 29, 
+	29, 29, 34, 35, 36, 37, 38, 29, 
+	29, 34, 29, 29, 29, 43, 44, 45, 
+	29, 46, 47, 48, 29, 30, 29, 29, 
+	29, 29, 29, 29, 29, 29, 29, 29, 
+	29, 29, 29, 34, 35, 36, 37, 38, 
+	39, 40, 34, 29, 29, 29, 43, 44, 
+	45, 29, 46, 47, 48, 29, 30, 29, 
+	29, 31, 32, 29, 29, 29, 29, 29, 
+	29, 29, 29, 29, 34, 35, 36, 37, 
+	38, 39, 40, 34, 41, 29, 42, 43, 
+	44, 45, 29, 46, 47, 48, 29, 30, 
+	29, 29, 31, 32, 29, 29, 29, 29, 
+	29, 29, 29, 29, 29, 34, 35, 36, 
+	37, 38, 39, 40, 34, 41, 33, 42, 
+	43, 44, 45, 29, 46, 47, 48, 29, 
+	53, 52, 52, 52, 52, 52, 52, 52, 
+	54, 52, 5, 55, 53, 52, 6, 56, 
+	56, 1, 57, 56, 56, 56, 56, 56, 
+	56, 56, 56, 58, 10, 11, 12, 13, 
+	14, 15, 16, 10, 17, 19, 19, 20, 
+	21, 22, 56, 23, 24, 25, 56, 6, 
+	56, 56, 1, 57, 56, 56, 56, 56, 
+	56, 56, 56, 56, 56, 10, 11, 12, 
+	13, 14, 15, 16, 10, 17, 19, 19, 
+	20, 21, 22, 56, 23, 24, 25, 56, 
+	6, 56, 56, 56, 56, 56, 56, 56, 
+	56, 56, 56, 56, 56, 56, 10, 11, 
+	12, 13, 14, 56, 56, 56, 56, 56, 
+	56, 20, 21, 22, 56, 23, 24, 25, 
+	56, 6, 56, 56, 56, 56, 56, 56, 
+	56, 56, 56, 56, 56, 56, 56, 56, 
+	11, 12, 13, 14, 56, 56, 56, 56, 
+	56, 56, 56, 56, 56, 56, 23, 24, 
+	25, 56, 6, 56, 56, 56, 56, 56, 
+	56, 56, 56, 56, 56, 56, 56, 56, 
+	56, 56, 12, 13, 14, 56, 6, 56, 
+	56, 56, 56, 56, 56, 56, 56, 56, 
+	56, 56, 56, 56, 56, 56, 56, 13, 
+	14, 56, 6, 56, 56, 56, 56, 56, 
+	56, 56, 56, 56, 56, 56, 56, 56, 
+	56, 56, 56, 56, 14, 56, 6, 56, 
+	56, 56, 56, 56, 56, 56, 56, 56, 
+	56, 56, 56, 56, 56, 56, 12, 13, 
+	14, 56, 56, 56, 56, 56, 56, 56, 
+	56, 56, 56, 23, 24, 25, 56, 6, 
+	56, 56, 56, 56, 56, 56, 56, 56, 
+	56, 56, 56, 56, 56, 56, 56, 12, 
+	13, 14, 56, 56, 56, 56, 56, 56, 
+	56, 56, 56, 56, 56, 24, 25, 56, 
+	6, 56, 56, 56, 56, 56, 56, 56, 
+	56, 56, 56, 56, 56, 56, 56, 56, 
+	12, 13, 14, 56, 56, 56, 56, 56, 
+	56, 56, 56, 56, 56, 56, 56, 25, 
+	56, 6, 56, 56, 56, 56, 56, 56, 
+	56, 56, 56, 56, 56, 56, 56, 56, 
+	11, 12, 13, 14, 56, 56, 56, 56, 
+	56, 56, 20, 21, 22, 56, 23, 24, 
+	25, 56, 6, 56, 56, 56, 56, 56, 
+	56, 56, 56, 56, 56, 56, 56, 56, 
+	56, 11, 12, 13, 14, 56, 56, 56, 
+	56, 56, 56, 56, 21, 22, 56, 23, 
+	24, 25, 56, 6, 56, 56, 56, 56, 
+	56, 56, 56, 56, 56, 56, 56, 56, 
+	56, 56, 11, 12, 13, 14, 56, 56, 
+	56, 56, 56, 56, 56, 56, 22, 56, 
+	23, 24, 25, 56, 6, 56, 56, 56, 
+	56, 56, 56, 56, 56, 56, 56, 56, 
+	56, 56, 10, 11, 12, 13, 14, 56, 
+	16, 10, 56, 56, 56, 20, 21, 22, 
+	56, 23, 24, 25, 56, 6, 56, 56, 
+	56, 56, 56, 56, 56, 56, 56, 56, 
+	56, 56, 56, 10, 11, 12, 13, 14, 
+	56, 59, 10, 56, 56, 56, 20, 21, 
+	22, 56, 23, 24, 25, 56, 6, 56, 
+	56, 56, 56, 56, 56, 56, 56, 56, 
+	56, 56, 56, 56, 10, 11, 12, 13, 
+	14, 56, 56, 10, 56, 56, 56, 20, 
+	21, 22, 56, 23, 24, 25, 56, 6, 
+	56, 56, 56, 56, 56, 56, 56, 56, 
+	56, 56, 56, 56, 56, 10, 11, 12, 
+	13, 14, 15, 16, 10, 56, 56, 56, 
+	20, 21, 22, 56, 23, 24, 25, 56, 
+	6, 56, 56, 1, 57, 56, 56, 56, 
+	56, 56, 56, 56, 56, 56, 10, 11, 
+	12, 13, 14, 15, 16, 10, 17, 56, 
+	19, 20, 21, 22, 56, 23, 24, 25, 
+	56, 1, 60, 3, 56, 56, 56, 3, 
+	56, 56, 6, 56, 56, 1, 57, 56, 
+	56, 56, 56, 56, 56, 56, 56, 56, 
 	10, 11, 12, 13, 14, 15, 16, 10, 
-	17, 19, 19, 20, 21, 22, 55, 23, 
-	24, 25, 55, 6, 55, 55, 1, 56, 
-	55, 55, 55, 55, 55, 55, 55, 55, 
-	55, 10, 11, 12, 13, 14, 15, 16, 
-	10, 17, 19, 19, 20, 21, 22, 55, 
-	23, 24, 25, 55, 6, 55, 55, 55, 
-	55, 55, 55, 55, 55, 55, 55, 55, 
-	55, 55, 10, 11, 12, 13, 14, 55, 
-	55, 55, 55, 55, 55, 20, 21, 22, 
-	55, 23, 24, 25, 55, 6, 55, 55, 
-	55, 55, 55, 55, 55, 55, 55, 55, 
-	55, 55, 55, 55, 11, 12, 13, 14, 
-	55, 55, 55, 55, 55, 55, 55, 55, 
-	55, 55, 23, 24, 25, 55, 6, 55, 
-	55, 55, 55, 55, 55, 55, 55, 55, 
-	55, 55, 55, 55, 55, 55, 12, 13, 
-	14, 55, 6, 55, 55, 55, 55, 55, 
-	55, 55, 55, 55, 55, 55, 55, 55, 
-	55, 55, 55, 13, 14, 55, 6, 55, 
-	55, 55, 55, 55, 55, 55, 55, 55, 
-	55, 55, 55, 55, 55, 55, 55, 55, 
-	14, 55, 6, 55, 55, 55, 55, 55, 
-	55, 55, 55, 55, 55, 55, 55, 55, 
-	55, 55, 12, 13, 14, 55, 55, 55, 
-	55, 55, 55, 55, 55, 55, 55, 23, 
-	24, 25, 55, 6, 55, 55, 55, 55, 
-	55, 55, 55, 55, 55, 55, 55, 55, 
-	55, 55, 55, 12, 13, 14, 55, 55, 
-	55, 55, 55, 55, 55, 55, 55, 55, 
-	55, 24, 25, 55, 6, 55, 55, 55, 
-	55, 55, 55, 55, 55, 55, 55, 55, 
-	55, 55, 55, 55, 12, 13, 14, 55, 
-	55, 55, 55, 55, 55, 55, 55, 55, 
-	55, 55, 55, 25, 55, 6, 55, 55, 
-	55, 55, 55, 55, 55, 55, 55, 55, 
-	55, 55, 55, 55, 11, 12, 13, 14, 
-	55, 55, 55, 55, 55, 55, 20, 21, 
-	22, 55, 23, 24, 25, 55, 6, 55, 
-	55, 55, 55, 55, 55, 55, 55, 55, 
-	55, 55, 55, 55, 55, 11, 12, 13, 
-	14, 55, 55, 55, 55, 55, 55, 55, 
-	21, 22, 55, 23, 24, 25, 55, 6, 
-	55, 55, 55, 55, 55, 55, 55, 55, 
-	55, 55, 55, 55, 55, 55, 11, 12, 
-	13, 14, 55, 55, 55, 55, 55, 55, 
-	55, 55, 22, 55, 23, 24, 25, 55, 
-	6, 55, 55, 55, 55, 55, 55, 55, 
-	55, 55, 55, 55, 55, 55, 10, 11, 
-	12, 13, 14, 55, 16, 10, 55, 55, 
-	55, 20, 21, 22, 55, 23, 24, 25, 
-	55, 6, 55, 55, 55, 55, 55, 55, 
-	55, 55, 55, 55, 55, 55, 55, 10, 
-	11, 12, 13, 14, 55, 58, 10, 55, 
-	55, 55, 20, 21, 22, 55, 23, 24, 
-	25, 55, 6, 55, 55, 55, 55, 55, 
-	55, 55, 55, 55, 55, 55, 55, 55, 
-	10, 11, 12, 13, 14, 55, 55, 10, 
-	55, 55, 55, 20, 21, 22, 55, 23, 
-	24, 25, 55, 6, 55, 55, 55, 55, 
-	55, 55, 55, 55, 55, 55, 55, 55, 
-	55, 10, 11, 12, 13, 14, 15, 16, 
-	10, 55, 55, 55, 20, 21, 22, 55, 
-	23, 24, 25, 55, 6, 55, 55, 1, 
-	56, 55, 55, 55, 55, 55, 55, 55, 
-	55, 55, 10, 11, 12, 13, 14, 15, 
-	16, 10, 17, 55, 19, 20, 21, 22, 
-	55, 23, 24, 25, 55, 1, 59, 3, 
-	55, 55, 55, 3, 55, 55, 6, 55, 
-	55, 1, 56, 55, 55, 55, 55, 55, 
-	55, 55, 55, 55, 10, 11, 12, 13, 
-	14, 15, 16, 10, 17, 18, 19, 20, 
-	21, 22, 55, 23, 24, 25, 55, 6, 
-	55, 55, 1, 56, 55, 55, 55, 55, 
-	55, 55, 55, 55, 55, 10, 11, 12, 
-	13, 14, 15, 16, 10, 17, 18, 19, 
-	20, 21, 22, 55, 23, 24, 25, 55, 
-	61, 60, 60, 60, 60, 60, 60, 60, 
-	60, 60, 60, 60, 60, 60, 60, 60, 
-	60, 60, 60, 60, 61, 62, 60, 61, 
-	62, 60, 62, 60, 0
+	17, 18, 19, 20, 21, 22, 56, 23, 
+	24, 25, 56, 6, 56, 56, 1, 57, 
+	56, 56, 56, 56, 56, 56, 56, 56, 
+	56, 10, 11, 12, 13, 14, 15, 16, 
+	10, 17, 18, 19, 20, 21, 22, 56, 
+	23, 24, 25, 56, 62, 61, 61, 61, 
+	61, 61, 61, 61, 61, 61, 61, 61, 
+	61, 61, 61, 61, 61, 61, 61, 61, 
+	62, 63, 61, 62, 63, 61, 63, 61, 
+	3, 60, 60, 60, 3, 60, 0
 };
 
 static const char _use_syllable_machine_trans_targs[] = {
 	1, 27, 2, 3, 1, 24, 1, 45, 
 	46, 48, 29, 30, 31, 32, 33, 40, 
 	41, 43, 47, 44, 37, 38, 39, 34, 
-	35, 36, 1, 1, 1, 1, 4, 5, 
-	23, 7, 8, 9, 10, 11, 18, 19, 
-	21, 22, 15, 16, 17, 12, 13, 14, 
-	6, 1, 20, 1, 25, 26, 1, 1, 
-	0, 28, 42, 1, 1, 49, 50
+	35, 36, 51, 1, 1, 1, 1, 4, 
+	5, 23, 7, 8, 9, 10, 11, 18, 
+	19, 21, 22, 15, 16, 17, 12, 13, 
+	14, 6, 1, 20, 1, 25, 26, 1, 
+	1, 0, 28, 42, 1, 1, 49, 50
 };
 
 static const char _use_syllable_machine_trans_actions[] = {
 	1, 2, 0, 0, 5, 0, 6, 0, 
 	2, 0, 0, 0, 0, 0, 0, 0, 
 	0, 0, 2, 2, 0, 0, 0, 0, 
-	0, 0, 7, 8, 9, 10, 0, 0, 
+	0, 0, 0, 7, 8, 9, 10, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 11, 0, 12, 0, 0, 13, 14, 
-	0, 2, 0, 15, 16, 0, 0
+	0, 0, 11, 0, 12, 0, 0, 13, 
+	14, 0, 2, 0, 15, 16, 0, 0
 };
 
 static const char _use_syllable_machine_to_state_actions[] = {
 	0, 3, 0, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0
+	0, 0, 0, 0
 };
 
 static const char _use_syllable_machine_from_state_actions[] = {
 	0, 4, 0, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
 	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0
+	0, 0, 0, 0
 };
 
 static const short _use_syllable_machine_eof_trans[] = {
-	1, 0, 27, 29, 29, 50, 29, 29, 
-	29, 29, 29, 29, 29, 29, 29, 29, 
-	29, 29, 29, 29, 29, 29, 29, 29, 
-	52, 55, 52, 56, 56, 56, 56, 56, 
-	56, 56, 56, 56, 56, 56, 56, 56, 
-	56, 56, 56, 56, 56, 60, 56, 56, 
-	61, 61, 61
+	1, 0, 28, 30, 30, 51, 30, 30, 
+	30, 30, 30, 30, 30, 30, 30, 30, 
+	30, 30, 30, 30, 30, 30, 30, 30, 
+	53, 56, 53, 57, 57, 57, 57, 57, 
+	57, 57, 57, 57, 57, 57, 57, 57, 
+	57, 57, 57, 57, 57, 61, 57, 57, 
+	62, 62, 62, 61
 };
 
 static const int use_syllable_machine_start = 1;
 static const int use_syllable_machine_first_final = 1;
 static const int use_syllable_machine_error = -1;
 
 static const int use_syllable_machine_en_main = 1;
 
 
 #line 38 "hb-ot-shape-complex-use-machine.rl"
 
 
 
-#line 139 "hb-ot-shape-complex-use-machine.rl"
+#line 140 "hb-ot-shape-complex-use-machine.rl"
 
 
 #define found_syllable(syllable_type) \
   HB_STMT_START { \
     if (0) fprintf (stderr, "syllable %d..%d %s\n", last, p+1, #syllable_type); \
     for (unsigned int i = last; i < p+1; i++) \
       info[i].syllable() = (syllable_serial << 4) | syllable_type; \
     last = p+1; \
@@ -314,48 +315,48 @@ static const int use_syllable_machine_en
 
 static void
 find_syllables (hb_buffer_t *buffer)
 {
   unsigned int p, pe, eof, ts HB_UNUSED, te HB_UNUSED, act HB_UNUSED;
   int cs;
   hb_glyph_info_t *info = buffer->info;
   
-#line 323 "hb-ot-shape-complex-use-machine.hh"
+#line 324 "hb-ot-shape-complex-use-machine.hh"
 	{
 	cs = use_syllable_machine_start;
 	ts = 0;
 	te = 0;
 	act = 0;
 	}
 
-#line 160 "hb-ot-shape-complex-use-machine.rl"
+#line 161 "hb-ot-shape-complex-use-machine.rl"
 
 
   p = 0;
   pe = eof = buffer->len;
 
   unsigned int last = 0;
   unsigned int syllable_serial = 1;
   
-#line 340 "hb-ot-shape-complex-use-machine.hh"
+#line 341 "hb-ot-shape-complex-use-machine.hh"
 	{
 	int _slen;
 	int _trans;
 	const unsigned char *_keys;
 	const char *_inds;
 	if ( p == pe )
 		goto _test_eof;
 _resume:
 	switch ( _use_syllable_machine_from_state_actions[cs] ) {
 	case 4:
 #line 1 "NONE"
 	{ts = p;}
 	break;
-#line 354 "hb-ot-shape-complex-use-machine.hh"
+#line 355 "hb-ot-shape-complex-use-machine.hh"
 	}
 
 	_keys = _use_syllable_machine_trans_keys + (cs<<1);
 	_inds = _use_syllable_machine_indicies + _use_syllable_machine_index_offsets[cs];
 
 	_slen = _use_syllable_machine_key_spans[cs];
 	_trans = _inds[ _slen > 0 && _keys[0] <=( info[p].use_category()) &&
 		( info[p].use_category()) <= _keys[1] ?
@@ -368,91 +369,91 @@ find_syllables (hb_buffer_t *buffer)
 		goto _again;
 
 	switch ( _use_syllable_machine_trans_actions[_trans] ) {
 	case 2:
 #line 1 "NONE"
 	{te = p+1;}
 	break;
 	case 8:
-#line 128 "hb-ot-shape-complex-use-machine.rl"
+#line 129 "hb-ot-shape-complex-use-machine.rl"
 	{te = p+1;{ found_syllable (independent_cluster); }}
 	break;
 	case 10:
-#line 130 "hb-ot-shape-complex-use-machine.rl"
+#line 131 "hb-ot-shape-complex-use-machine.rl"
 	{te = p+1;{ found_syllable (standard_cluster); }}
 	break;
 	case 6:
-#line 134 "hb-ot-shape-complex-use-machine.rl"
+#line 135 "hb-ot-shape-complex-use-machine.rl"
 	{te = p+1;{ found_syllable (broken_cluster); }}
 	break;
 	case 5:
-#line 135 "hb-ot-shape-complex-use-machine.rl"
+#line 136 "hb-ot-shape-complex-use-machine.rl"
 	{te = p+1;{ found_syllable (non_cluster); }}
 	break;
 	case 7:
-#line 128 "hb-ot-shape-complex-use-machine.rl"
+#line 129 "hb-ot-shape-complex-use-machine.rl"
 	{te = p;p--;{ found_syllable (independent_cluster); }}
 	break;
 	case 11:
-#line 129 "hb-ot-shape-complex-use-machine.rl"
+#line 130 "hb-ot-shape-complex-use-machine.rl"
 	{te = p;p--;{ found_syllable (virama_terminated_cluster); }}
 	break;
 	case 9:
-#line 130 "hb-ot-shape-complex-use-machine.rl"
+#line 131 "hb-ot-shape-complex-use-machine.rl"
 	{te = p;p--;{ found_syllable (standard_cluster); }}
 	break;
 	case 13:
-#line 131 "hb-ot-shape-complex-use-machine.rl"
+#line 132 "hb-ot-shape-complex-use-machine.rl"
 	{te = p;p--;{ found_syllable (number_joiner_terminated_cluster); }}
 	break;
 	case 12:
-#line 132 "hb-ot-shape-complex-use-machine.rl"
+#line 133 "hb-ot-shape-complex-use-machine.rl"
 	{te = p;p--;{ found_syllable (numeral_cluster); }}
 	break;
 	case 16:
-#line 133 "hb-ot-shape-complex-use-machine.rl"
+#line 134 "hb-ot-shape-complex-use-machine.rl"
 	{te = p;p--;{ found_syllable (symbol_cluster); }}
 	break;
 	case 14:
-#line 134 "hb-ot-shape-complex-use-machine.rl"
+#line 135 "hb-ot-shape-complex-use-machine.rl"
 	{te = p;p--;{ found_syllable (broken_cluster); }}
 	break;
 	case 15:
-#line 135 "hb-ot-shape-complex-use-machine.rl"
+#line 136 "hb-ot-shape-complex-use-machine.rl"
 	{te = p;p--;{ found_syllable (non_cluster); }}
 	break;
 	case 1:
-#line 134 "hb-ot-shape-complex-use-machine.rl"
+#line 135 "hb-ot-shape-complex-use-machine.rl"
 	{{p = ((te))-1;}{ found_syllable (broken_cluster); }}
 	break;
-#line 428 "hb-ot-shape-complex-use-machine.hh"
+#line 429 "hb-ot-shape-complex-use-machine.hh"
 	}
 
 _again:
 	switch ( _use_syllable_machine_to_state_actions[cs] ) {
 	case 3:
 #line 1 "NONE"
 	{ts = 0;}
 	break;
-#line 437 "hb-ot-shape-complex-use-machine.hh"
+#line 438 "hb-ot-shape-complex-use-machine.hh"
 	}
 
 	if ( ++p != pe )
 		goto _resume;
 	_test_eof: {}
 	if ( p == eof )
 	{
 	if ( _use_syllable_machine_eof_trans[cs] > 0 ) {
 		_trans = _use_syllable_machine_eof_trans[cs] - 1;
 		goto _eof_trans;
 	}
 	}
 
 	}
 
-#line 169 "hb-ot-shape-complex-use-machine.rl"
+#line 170 "hb-ot-shape-complex-use-machine.rl"
 
 }
 
 #undef found_syllable
 
 #endif /* HB_OT_SHAPE_COMPLEX_USE_MACHINE_HH */
--- a/gfx/harfbuzz/src/hb-ot-shape-complex-use-machine.rl
+++ b/gfx/harfbuzz/src/hb-ot-shape-complex-use-machine.rl
@@ -81,32 +81,33 @@ VBlw	= 34; # VOWEL_BELOW / VOWEL_BELOW_P
 VPst	= 35; # VOWEL_POST	UIPC = Right
 VPre	= 22; # VOWEL_PRE / VOWEL_PRE_ABOVE / VOWEL_PRE_ABOVE_POST / VOWEL_PRE_POST
 VMAbv	= 37; # VOWEL_MOD_ABOVE
 VMBlw	= 38; # VOWEL_MOD_BELOW
 VMPst	= 39; # VOWEL_MOD_POST
 VMPre	= 23; # VOWEL_MOD_PRE
 SMAbv	= 41; # SYM_MOD_ABOVE
 SMBlw	= 42; # SYM_MOD_BELOW
+CS	= 43; # CONS_WITH_STACKER
 
 
 consonant_modifiers = CMAbv* CMBlw* ((H B | SUB) VS? CMAbv? CMBlw*)*;
 # Override: Allow two MBlw. https://github.com/behdad/harfbuzz/issues/376
 medial_consonants = MPre? MAbv? MBlw?.MBlw? MPst?;
 dependent_vowels = VPre* VAbv* VBlw* VPst*;
 vowel_modifiers = VMPre* VMAbv* VMBlw* VMPst*;
 final_consonants = FAbv* FBlw* FPst* FM?;
 
 virama_terminated_cluster =
-	R? (B | GB) VS?
+	(R|CS)? (B | GB) VS?
 	consonant_modifiers
 	H
 ;
 standard_cluster =
-	R? (B | GB) VS?
+	(R|CS)? (B | GB) VS?
 	consonant_modifiers
 	medial_consonants
 	dependent_vowels
 	vowel_modifiers
 	final_consonants
 ;
 
 broken_cluster =
--- a/gfx/harfbuzz/src/hb-ot-shape-complex-use-private.hh
+++ b/gfx/harfbuzz/src/hb-ot-shape-complex-use-private.hh
@@ -82,15 +82,16 @@ enum use_category_t {
   USE_VBlw	= 34,	/* VOWEL_BELOW / VOWEL_BELOW_POST */
   USE_VPst	= 35,	/* VOWEL_POST	UIPC = Right */
   USE_VPre	= 22,	/* VOWEL_PRE / VOWEL_PRE_ABOVE / VOWEL_PRE_ABOVE_POST / VOWEL_PRE_POST */
   USE_VMAbv	= 37,	/* VOWEL_MOD_ABOVE */
   USE_VMBlw	= 38,	/* VOWEL_MOD_BELOW */
   USE_VMPst	= 39,	/* VOWEL_MOD_POST */
   USE_VMPre	= 23,	/* VOWEL_MOD_PRE */
   USE_SMAbv	= 41,	/* SYM_MOD_ABOVE */
-  USE_SMBlw	= 42	/* SYM_MOD_BELOW */
+  USE_SMBlw	= 42,	/* SYM_MOD_BELOW */
+  USE_CS	= 43	/* CONS_WITH_STACKER */
 };
 
 HB_INTERNAL USE_TABLE_ELEMENT_TYPE
 hb_use_get_categories (hb_codepoint_t u);
 
 #endif /* HB_OT_SHAPE_COMPLEX_USE_PRIVATE_HH */
--- a/gfx/harfbuzz/src/hb-ot-shape-complex-use-table.cc
+++ b/gfx/harfbuzz/src/hb-ot-shape-complex-use-table.cc
@@ -1,29 +1,30 @@
 /* == Start of generated table == */
 /*
  * The following table is generated by running:
  *
  *   ./gen-use-table.py IndicSyllabicCategory.txt IndicPositionalCategory.txt UnicodeData.txt Blocks.txt
  *
  * on files with these headers:
  *
- * # IndicSyllabicCategory-9.0.0.txt
- * # Date: 2016-05-21, 02:46:00 GMT [RP]
- * # IndicPositionalCategory-9.0.0.txt
- * # Date: 2016-06-09, 19:33:00 GMT [RP]
- * # Blocks-9.0.0.txt
- * # Date: 2016-02-05, 23:48:00 GMT [KW]
+ * # IndicSyllabicCategory-10.0.0.txt
+ * # Date: 2017-05-31, 01:07:00 GMT [KW, RP]
+ * # IndicPositionalCategory-10.0.0.txt
+ * # Date: 2017-05-31, 01:07:00 GMT [RP]
+ * # Blocks-10.0.0.txt
+ * # Date: 2017-04-12, 17:30:00 GMT [KW]
  * UnicodeData.txt does not have a header.
  */
 
 #include "hb-ot-shape-complex-use-private.hh"
 
 #define B	USE_B	/* BASE */
 #define CGJ	USE_CGJ	/* CGJ */
+#define CS	USE_CS	/* CONS_WITH_STACKER */
 #define FM	USE_FM	/* CONS_FINAL_MOD */
 #define GB	USE_GB	/* BASE_OTHER */
 #define H	USE_H	/* HALANT */
 #define HN	USE_HN	/* HALANT_NUM */
 #define IND	USE_IND	/* BASE_IND */
 #define N	USE_N	/* BASE_NUM */
 #define O	USE_O	/* OTHER */
 #define R	USE_R	/* REPHA */
@@ -92,17 +93,17 @@ static const USE_TABLE_ELEMENT_TYPE use_
 
   /* 0980 */     O, VMAbv, VMPst, VMPst,     O,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     B,
   /* 0990 */     B,     O,     O,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 09A0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     B,     B,     B,     B,     B,     B,
   /* 09B0 */     B,     O,     B,     O,     O,     O,     B,     B,     B,     B,     O,     O, CMBlw,     B,  VPst,  VPre,
   /* 09C0 */  VPst,  VBlw,  VBlw,  VBlw,  VBlw,     O,     O,  VPre,  VPre,     O,     O,  VPre,  VPre,     H,   IND,     O,
   /* 09D0 */     O,     O,     O,     O,     O,     O,     O,  VPst,     O,     O,     O,     O,     B,     B,     O,     B,
   /* 09E0 */     B,     B,  VBlw,  VBlw,     O,     O,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* 09F0 */     B,     B,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
+  /* 09F0 */     B,     B,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     B,     O,     O,     O,
 
   /* Gurmukhi */
 
   /* 0A00 */     O, VMAbv, VMAbv, VMPst,     O,     B,     B,     B,     B,     B,     B,     O,     O,     O,     O,     B,
   /* 0A10 */     B,     O,     O,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 0A20 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     B,     B,     B,     B,     B,     B,
   /* 0A30 */     B,     O,     B,     B,     O,     B,     B,     O,     B,     B,     O,     O, CMBlw,     O,  VPst,  VPre,
   /* 0A40 */  VPst,  VBlw,  VBlw,     O,     O,     O,     O,  VAbv,  VAbv,     O,     O,  VAbv,  VAbv,     H,     O,     O,
@@ -114,17 +115,17 @@ static const USE_TABLE_ELEMENT_TYPE use_
 
   /* 0A80 */     O, VMAbv, VMAbv, VMPst,     O,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     B,
   /* 0A90 */     B,     B,     O,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 0AA0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     B,     B,     B,     B,     B,     B,
   /* 0AB0 */     B,     O,     B,     B,     O,     B,     B,     B,     B,     B,     O,     O, CMBlw,     B,  VPst,  VPre,
   /* 0AC0 */  VPst,  VBlw,  VBlw,  VBlw,  VBlw,  VAbv,     O,  VAbv,  VAbv,  VAbv,     O,  VPst,  VPst,     H,     O,     O,
   /* 0AD0 */     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
   /* 0AE0 */     B,     B,  VBlw,  VBlw,     O,     O,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* 0AF0 */     O,     O,     O,     O,     O,     O,     O,     O,     O,     B,     O,     O,     O,     O,     O,     O,
+  /* 0AF0 */     O,     O,     O,     O,     O,     O,     O,     O,     O,     B, VMAbv, VMAbv, VMAbv, CMAbv, CMAbv, CMAbv,
 
   /* Oriya */
 
   /* 0B00 */     O, VMAbv, VMPst, VMPst,     O,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     B,
   /* 0B10 */     B,     O,     O,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 0B20 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     B,     B,     B,     B,     B,     B,
   /* 0B30 */     B,     O,     B,     B,     O,     B,     B,     B,     B,     B,     O,     O, CMBlw,     B,  VPst,  VAbv,
   /* 0B40 */  VPst,  VBlw,  VBlw,  VBlw,  VBlw,     O,     O,  VPre,  VPre,     O,     O,  VPre,  VPre,     H,     O,     O,
@@ -158,24 +159,24 @@ static const USE_TABLE_ELEMENT_TYPE use_
 
   /* 0C80 */     O, VMAbv, VMPst, VMPst,     O,     B,     B,     B,     B,     B,     B,     B,     B,     O,     B,     B,
   /* 0C90 */     B,     O,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 0CA0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     B,     B,     B,     B,     B,     B,
   /* 0CB0 */     B,     B,     B,     B,     O,     B,     B,     B,     B,     B,     O,     O, CMBlw,     B,  VPst,  VAbv,
   /* 0CC0 */  VAbv,  VPst,  VPst,  VPst,  VPst,     O,  VAbv,  VAbv,  VAbv,     O,  VAbv,  VAbv,  VAbv,     H,     O,     O,
   /* 0CD0 */     O,     O,     O,     O,     O,  VPst,  VPst,     O,     O,     O,     O,     O,     O,     O,     B,     O,
   /* 0CE0 */     B,     B,  VBlw,  VBlw,     O,     O,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* 0CF0 */     O,     R,     R,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
+  /* 0CF0 */     O,    CS,    CS,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
 
   /* Malayalam */
 
-  /* 0D00 */     O, VMAbv, VMPst, VMPst,     O,     B,     B,     B,     B,     B,     B,     B,     B,     O,     B,     B,
+  /* 0D00 */ VMAbv, VMAbv, VMPst, VMPst,     O,     B,     B,     B,     B,     B,     B,     B,     B,     O,     B,     B,
   /* 0D10 */     B,     O,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 0D20 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* 0D30 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     B,  VPst,  VPst,
+  /* 0D30 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,  VAbv,  VAbv,     B,  VPst,  VPst,
   /* 0D40 */  VPst,  VPst,  VPst,  VBlw,  VBlw,     O,  VPre,  VPre,  VPre,     O,  VPre,  VPre,  VPre,     H,     R,     O,
   /* 0D50 */     O,     O,     O,     O,   IND,   IND,   IND,  VPst,     O,     O,     O,     O,     O,     O,     O,     B,
   /* 0D60 */     B,     B,  VBlw,  VBlw,     O,     O,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 0D70 */     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,   IND,   IND,   IND,   IND,   IND,   IND,
 
   /* Sinhala */
 
   /* 0D80 */     O,     O, VMPst, VMPst,     O,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
@@ -269,19 +270,19 @@ static const USE_TABLE_ELEMENT_TYPE use_
   /* 1A00 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 1A10 */     B,     B,     B,     B,     B,     B,     B,  VAbv,  VBlw,  VPre,  VPst,  VAbv,     O,     O,     O,     O,
 
   /* Tai Tham */
 
   /* 1A20 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 1A30 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 1A40 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* 1A50 */     B,     B,     B,     B,     B,  MPre,  MBlw,  FPst,  FAbv,  FAbv,  FAbv,  FBlw,  FBlw,  FBlw,  FBlw,     O,
+  /* 1A50 */     B,     B,     B,     B,     B,  MPre,  MBlw,   SUB,  FAbv,  FAbv,  FAbv,   SUB,   SUB,   SUB,   SUB,     O,
   /* 1A60 */     H,  VPst,  VAbv,  VPst,  VPst,  VAbv,  VAbv,  VAbv,  VAbv,  VBlw,  VBlw,  VAbv,  VBlw,  VPst,  VPre,  VPre,
-  /* 1A70 */  VPre,  VPre,  VPre,  VAbv,  VAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv,    FM,    FM,    FM,     O,     O,    FM,
+  /* 1A70 */  VPre,  VPre,  VPre,  VAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv,  VAbv,    FM,    FM,     O,     O,  FBlw,
   /* 1A80 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,     O,     O,     O,
   /* 1A90 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,     O,     O,     O,
 
 #define use_offset_0x1b00u 2168
 
 
   /* Balinese */
 
@@ -318,17 +319,17 @@ static const USE_TABLE_ELEMENT_TYPE use_
 
 #define use_offset_0x1cd0u 2504
 
 
   /* Vedic Extensions */
 
   /* 1CD0 */ VMAbv, VMAbv, VMAbv,     O, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, VMAbv, VMAbv, VMBlw, VMBlw, VMBlw, VMBlw,
   /* 1CE0 */ VMAbv, VMPst, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw,     O,     O,     O,     O, VMBlw,     O,     O,
-  /* 1CF0 */     O,     O, VMPst, VMPst, VMAbv,     O,     O,     O, VMAbv, VMAbv,     O,     O,     O,     O,     O,     O,
+  /* 1CF0 */     O,     O, VMPst, VMPst, VMAbv,     O,     O, VMPst, VMAbv, VMAbv,     O,     O,     O,     O,     O,     O,
 
 #define use_offset_0x1df8u 2552
 
 
   /* Combining Diacritical Marks Supplement */
                                                                          O,     O,     O,    FM,     O,     O,     O,     O,
 
 #define use_offset_0x2008u 2560
@@ -371,17 +372,17 @@ static const USE_TABLE_ELEMENT_TYPE use_
   /* A8A0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* A8B0 */     B,     B,     B,     B,  FPst,  VPst,  VPst,  VPst,  VPst,  VPst,  VPst,  VPst,  VPst,  VPst,  VPst,  VPst,
   /* A8C0 */  VPst,  VPst,  VPst,  VPst,     H, VMAbv,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
   /* A8D0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,     O,     O,     O,
 
   /* Devanagari Extended */
 
   /* A8E0 */ VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv,
-  /* A8F0 */ VMAbv, VMAbv,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
+  /* A8F0 */ VMAbv, VMAbv,     B,     B,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
 
   /* Kayah Li */
 
   /* A900 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* A910 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* A920 */     B,     B,     B,     B,     B,     B,  VAbv,  VAbv,  VAbv,  VAbv,  VAbv, VMBlw, VMBlw, VMBlw,     O,     O,
 
   /* Rejang */
@@ -392,17 +393,17 @@ static const USE_TABLE_ELEMENT_TYPE use_
   /* A960 */     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
   /* A970 */     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
 
   /* Javanese */
 
   /* A980 */ VMAbv, VMAbv,  FAbv, VMPst,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* A990 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* A9A0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* A9B0 */     B,     B,     B, CMAbv,  VPst,  VPst,  VAbv,  VAbv,  VBlw,  VBlw,  VPre,  VPre,  VAbv,   SUB,  MPst,  MPst,
+  /* A9B0 */     B,     B,     B, CMAbv,  VPst,  VPst,  VAbv,  VAbv,  VBlw,  VBlw,  VPre,  VPre,  VAbv,   SUB,  MPst,  MBlw,
   /* A9C0 */     H,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
   /* A9D0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,     O,     O,     O,
 
   /* Myanmar Extended-B */
 
   /* A9E0 */     B,     B,     B,     B,     B,  VAbv,     O,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* A9F0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,
 
@@ -462,17 +463,17 @@ static const USE_TABLE_ELEMENT_TYPE use_
   /* 10A30 */     B,     B,     B,     B,     O,     O,     O,     O, CMAbv, CMBlw, CMBlw,     O,     O,     O,     O,     H,
   /* 10A40 */     B,     B,     B,     B,     B,     B,     B,     B,
 
 #define use_offset_0x11000u 3528
 
 
   /* Brahmi */
 
-  /* 11000 */ VMPst, VMAbv, VMPst,     R,     R,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
+  /* 11000 */ VMPst, VMAbv, VMPst,    CS,    CS,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 11010 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 11020 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 11030 */     B,     B,     B,     B,     B,     B,     B,     B,  VAbv,  VAbv,  VAbv,  VAbv,  VBlw,  VBlw,  VBlw,  VBlw,
   /* 11040 */  VBlw,  VBlw,  VAbv,  VAbv,  VAbv,  VAbv,     H,     O,     O,     O,     O,     O,     O,     O,     O,     O,
   /* 11050 */     O,     O,     N,     N,     N,     N,     N,     N,     N,     N,     N,     N,     N,     N,     N,     N,
   /* 11060 */     N,     N,     N,     N,     N,     N,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 11070 */     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
 
@@ -540,17 +541,17 @@ static const USE_TABLE_ELEMENT_TYPE use_
 
   /* Grantha */
 
   /* 11300 */ VMAbv, VMAbv, VMPst, VMPst,     O,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     B,
   /* 11310 */     B,     O,     O,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 11320 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     B,     B,     B,     B,     B,     B,
   /* 11330 */     B,     O,     B,     B,     O,     B,     B,     B,     B,     B,     O,     O, CMBlw,     B,  VPst,  VPst,
   /* 11340 */  VAbv,  VPst,  VPst,  VPst,  VPst,     O,     O,  VPre,  VPre,     O,     O,  VPre,  VPre,     H,     O,     O,
-  /* 11350 */     O,     O,     O,     O,     O,     O,     O,  VPst,     O,     O,     O,     O,     O,     O,     O,     O,
+  /* 11350 */     O,     O,     O,     O,     O,     O,     O,  VPst,     O,     O,     O,     O,     O,     O,     B,     B,
   /* 11360 */     B,     B,  VPst,  VPst,     O,     O, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv,     O,     O,     O,
   /* 11370 */ VMAbv, VMAbv, VMAbv, VMAbv, VMAbv,     O,     O,     O,
 
 #define use_offset_0x11400u 4288
 
 
   /* Newa */
 
@@ -610,17 +611,36 @@ static const USE_TABLE_ELEMENT_TYPE use_
 
   /* Ahom */
 
   /* 11700 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 11710 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,  MBlw,  MPre,  MAbv,
   /* 11720 */  VPst,  VPst,  VAbv,  VAbv,  VBlw,  VBlw,  VPre,  VAbv,  VBlw,  VAbv,  VAbv,  VAbv,     O,     O,     O,     O,
   /* 11730 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,     O,
 
-#define use_offset_0x11c00u 4960
+#define use_offset_0x11a00u 4960
+
+
+  /* Zanabazar Square */
+
+  /* 11A00 */     B,  VAbv,  VBlw,  VBlw,  VAbv,  VAbv,  VAbv,  VAbv,  VAbv,  VAbv,  VBlw,     B,     B,     B,     B,     B,
+  /* 11A10 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
+  /* 11A20 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
+  /* 11A30 */     B,     B,     B,    FM,  VBlw, VMAbv, VMAbv, VMAbv, VMAbv, VMPst,     R,  MBlw,  MBlw,  MBlw,  MBlw,    GB,
+  /* 11A40 */     O,     O,     O,     O,     O,    GB,     O,     H,     O,     O,     O,     O,     O,     O,     O,     O,
+
+  /* Soyombo */
+
+  /* 11A50 */     B,  VAbv,  VBlw,  VBlw,  VAbv,  VAbv,  VAbv,  VPst,  VPst,  VBlw,  VBlw,  VBlw,     B,     B,     B,     B,
+  /* 11A60 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
+  /* 11A70 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
+  /* 11A80 */     B,     B,     B,     B,     O,     O,     R,     R,     R,     R,  FBlw,  FBlw,  FBlw,  FBlw,  FBlw,  FBlw,
+  /* 11A90 */  FBlw,  FBlw,  FBlw,  FBlw,  FBlw,  FBlw, VMAbv, VMPst, CMAbv,     H,     O,     O,     O,     O,     O,     O,
+
+#define use_offset_0x11c00u 5120
 
 
   /* Bhaiksuki */
 
   /* 11C00 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     B,     B,     B,     B,     B,     B,
   /* 11C10 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 11C20 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,  VPst,
   /* 11C30 */  VAbv,  VAbv,  VBlw,  VBlw,  VBlw,  VBlw,  VBlw,     O,  VAbv,  VAbv,  VAbv,  VAbv, VMAbv, VMAbv, VMPst,     H,
@@ -631,17 +651,29 @@ static const USE_TABLE_ELEMENT_TYPE use_
   /* Marchen */
 
   /* 11C70 */     O,     O,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 11C80 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 11C90 */     O,     O,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,
   /* 11CA0 */   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,     O,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,
   /* 11CB0 */  VBlw,  VPre,  VBlw,  VAbv,  VPst, VMAbv, VMAbv,     O,
 
-}; /* Table items: 5144; occupancy: 72% */
+#define use_offset_0x11d00u 5304
+
+
+  /* Masaram Gondi */
+
+  /* 11D00 */     B,     B,     B,     B,     B,     B,     B,     O,     B,     B,     O,     B,     B,     B,     B,     B,
+  /* 11D10 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
+  /* 11D20 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
+  /* 11D30 */     B,  VAbv,  VAbv,  VAbv,  VAbv,  VAbv,  VBlw,     O,     O,     O,  VAbv,     O,  VAbv,  VAbv,     O,  VAbv,
+  /* 11D40 */ VMAbv, VMAbv, CMBlw,  VAbv,  VBlw,     H,     R,  MBlw,     O,     O,     O,     O,     O,     O,     O,     O,
+  /* 11D50 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,     O,     O,     O,
+
+}; /* Table items: 5400; occupancy: 73% */
 
 USE_TABLE_ELEMENT_TYPE
 hb_use_get_categories (hb_codepoint_t u)
 {
   switch (u >> 12)
   {
     case 0x0u:
       if (hb_in_range<hb_codepoint_t> (u, 0x0028u, 0x003Fu)) return use_table[u - 0x0028u + use_offset_0x0028u];
@@ -679,28 +711,31 @@ hb_use_get_categories (hb_codepoint_t u)
       break;
 
     case 0x11u:
       if (hb_in_range<hb_codepoint_t> (u, 0x11000u, 0x110BFu)) return use_table[u - 0x11000u + use_offset_0x11000u];
       if (hb_in_range<hb_codepoint_t> (u, 0x11100u, 0x1123Fu)) return use_table[u - 0x11100u + use_offset_0x11100u];
       if (hb_in_range<hb_codepoint_t> (u, 0x11280u, 0x11377u)) return use_table[u - 0x11280u + use_offset_0x11280u];
       if (hb_in_range<hb_codepoint_t> (u, 0x11400u, 0x114DFu)) return use_table[u - 0x11400u + use_offset_0x11400u];
       if (hb_in_range<hb_codepoint_t> (u, 0x11580u, 0x1173Fu)) return use_table[u - 0x11580u + use_offset_0x11580u];
+      if (hb_in_range<hb_codepoint_t> (u, 0x11A00u, 0x11A9Fu)) return use_table[u - 0x11A00u + use_offset_0x11a00u];
       if (hb_in_range<hb_codepoint_t> (u, 0x11C00u, 0x11CB7u)) return use_table[u - 0x11C00u + use_offset_0x11c00u];
+      if (hb_in_range<hb_codepoint_t> (u, 0x11D00u, 0x11D5Fu)) return use_table[u - 0x11D00u + use_offset_0x11d00u];
       if (unlikely (u == 0x1107Fu)) return HN;
       break;
 
     default:
       break;
   }
   return USE_O;
 }
 
 #undef B
 #undef CGJ
+#undef CS
 #undef FM
 #undef GB
 #undef H
 #undef HN
 #undef IND
 #undef N
 #undef O
 #undef R
--- a/gfx/harfbuzz/src/hb-ot-shape-complex-use.cc
+++ b/gfx/harfbuzz/src/hb-ot-shape-complex-use.cc
@@ -602,11 +602,12 @@ const hb_ot_complex_shaper_t _hb_ot_comp
   data_destroy_use,
   NULL, /* preprocess_text */
   NULL, /* postprocess_glyphs */
   HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT,
   decompose_use,
   compose_use,
   setup_masks_use,
   NULL, /* disable_otl */
+  NULL, /* reorder_marks */
   HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_EARLY,
   false, /* fallback_position */
 };
--- a/gfx/harfbuzz/src/hb-ot-shape-normalize.cc
+++ b/gfx/harfbuzz/src/hb-ot-shape-normalize.cc
@@ -340,76 +340,92 @@ void
     if (_hb_glyph_info_get_modified_combining_class (&buffer->info[i]) == 0)
       continue;
 
     unsigned int end;
     for (end = i + 1; end < count; end++)
       if (_hb_glyph_info_get_modified_combining_class (&buffer->info[end]) == 0)
         break;
 
-    /* We are going to do a O(n^2).  Only do this if the sequence is short. */
-    if (end - i > 10) {
+    /* We are going to do a O(n^2).  Only do this if the sequence is short,
+     * but not too short ;). */
+    if (end - i < 2 || end - i > HB_OT_SHAPE_COMPLEX_MAX_COMBINING_MARKS) {
       i = end;
       continue;
     }
 
     buffer->sort (i, end, compare_combining_class);
 
+    if (plan->shaper->reorder_marks)
+      plan->shaper->reorder_marks (plan, buffer, i, end);
+
     i = end;
   }
 
 
   if (mode == HB_OT_SHAPE_NORMALIZATION_MODE_NONE ||
       mode == HB_OT_SHAPE_NORMALIZATION_MODE_DECOMPOSED)
     return;
 
   /* Third round, recompose */
 
   /* As noted in the comment earlier, we don't try to combine
    * ccc=0 chars with their previous Starter. */
 
   buffer->clear_output ();
   count = buffer->len;
   unsigned int starter = 0;
+  bool combine = true;
   buffer->next_glyph ();
   while (buffer->idx < count && !buffer->in_error)
   {
     hb_codepoint_t composed, glyph;
-    if (/* We don't try to compose a non-mark character with it's preceding starter.
+    if (combine &&
+	/* We don't try to compose a non-mark character with it's preceding starter.
 	 * This is both an optimization to avoid trying to compose every two neighboring
 	 * glyphs in most scripts AND a desired feature for Hangul.  Apparently Hangul
 	 * fonts are not designed to mix-and-match pre-composed syllables and Jamo. */
-	HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&buffer->cur())) &&
-	/* If there's anything between the starter and this char, they should have CCC
-	 * smaller than this character's. */
-	(starter == buffer->out_len - 1 ||
-	 _hb_glyph_info_get_modified_combining_class (&buffer->prev()) < _hb_glyph_info_get_modified_combining_class (&buffer->cur())) &&
-	/* And compose. */
-	c.compose (&c,
-		   buffer->out_info[starter].codepoint,
-		   buffer->cur().codepoint,
-		   &composed) &&
-	/* And the font has glyph for the composite. */
-	font->get_nominal_glyph (composed, &glyph))
+	HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&buffer->cur())))
     {
-      /* Composes. */
-      buffer->next_glyph (); /* Copy to out-buffer. */
-      if (unlikely (buffer->in_error))
-        return;
-      buffer->merge_out_clusters (starter, buffer->out_len);
-      buffer->out_len--; /* Remove the second composable. */
-      /* Modify starter and carry on. */
-      buffer->out_info[starter].codepoint = composed;
-      buffer->out_info[starter].glyph_index() = glyph;
-      _hb_glyph_info_set_unicode_props (&buffer->out_info[starter], buffer);
+      if (/* If there's anything between the starter and this char, they should have CCC
+	   * smaller than this character's. */
+	  (starter == buffer->out_len - 1 ||
+	   info_cc (buffer->prev()) < info_cc (buffer->cur())) &&
+	  /* And compose. */
+	  c.compose (&c,
+		     buffer->out_info[starter].codepoint,
+		     buffer->cur().codepoint,
+		     &composed) &&
+	  /* And the font has glyph for the composite. */
+	  font->get_nominal_glyph (composed, &glyph))
+      {
+	/* Composes. */
+	buffer->next_glyph (); /* Copy to out-buffer. */
+	if (unlikely (buffer->in_error))
+	  return;
+	buffer->merge_out_clusters (starter, buffer->out_len);
+	buffer->out_len--; /* Remove the second composable. */
+	/* Modify starter and carry on. */
+	buffer->out_info[starter].codepoint = composed;
+	buffer->out_info[starter].glyph_index() = glyph;
+	_hb_glyph_info_set_unicode_props (&buffer->out_info[starter], buffer);
 
-      continue;
+	continue;
+      }
+      else if (/* We sometimes custom-tailor the sorted order of marks. In that case, stop
+		* trying to combine as soon as combining-class drops. */
+	       starter < buffer->out_len - 1 &&
+	       info_cc (buffer->prev()) > info_cc (buffer->cur()))
+        combine = false;
     }
 
     /* Blocked, or doesn't compose. */
     buffer->next_glyph ();
 
-    if (_hb_glyph_info_get_modified_combining_class (&buffer->prev()) == 0)
+    if (info_cc (buffer->prev()) == 0)
+    {
       starter = buffer->out_len - 1;
+      combine = true;
+    }
   }
   buffer->swap_buffers ();
 
 }
--- a/gfx/harfbuzz/src/hb-ot-shape.cc
+++ b/gfx/harfbuzz/src/hb-ot-shape.cc
@@ -688,86 +688,82 @@ hb_ot_position_default (hb_ot_shape_cont
   }
   if (c->buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_SPACE_FALLBACK)
     _hb_ot_shape_fallback_spaces (c->plan, c->font, c->buffer);
 }
 
 static inline void
 hb_ot_position_complex (hb_ot_shape_context_t *c)
 {
-  hb_ot_layout_position_start (c->font, c->buffer);
-
   unsigned int count = c->buffer->len;
+  hb_glyph_info_t *info = c->buffer->info;
+  hb_glyph_position_t *pos = c->buffer->pos;
 
   /* If the font has no GPOS, AND, no fallback positioning will
    * happen, AND, direction is forward, then when zeroing mark
    * widths, we shift the mark with it, such that the mark
    * is positioned hanging over the previous glyph.  When
    * direction is backward we don't shift and it will end up
    * hanging over the next glyph after the final reordering.
    * If fallback positinoing happens or GPOS is present, we don't
    * care.
    */
   bool adjust_offsets_when_zeroing = c->fallback_positioning &&
 				     !c->plan->shaper->fallback_position &&
 				     HB_DIRECTION_IS_FORWARD (c->buffer->props.direction);
 
+  /* We change glyph origin to what GPOS expects (horizontal), apply GPOS, change it back. */
+
+  /* The nil glyph_h_origin() func returns 0, so no need to apply it. */
+  if (c->font->has_glyph_h_origin_func ())
+    for (unsigned int i = 0; i < count; i++)
+      c->font->add_glyph_h_origin (info[i].codepoint,
+				   &pos[i].x_offset,
+				   &pos[i].y_offset);
+
+  hb_ot_layout_position_start (c->font, c->buffer);
+
   switch (c->plan->shaper->zero_width_marks)
   {
     case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_EARLY:
       zero_mark_widths_by_gdef (c->buffer, adjust_offsets_when_zeroing);
       break;
 
     default:
     case HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE:
     case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE:
       break;
   }
 
   if (likely (!c->fallback_positioning))
-  {
-    hb_glyph_info_t *info = c->buffer->info;
-    hb_glyph_position_t *pos = c->buffer->pos;
-
-    /* Change glyph origin to what GPOS expects (horizontal), apply GPOS, change it back. */
-
-    /* The nil glyph_h_origin() func returns 0, so no need to apply it. */
-    if (c->font->has_glyph_h_origin_func ())
-      for (unsigned int i = 0; i < count; i++)
-	c->font->add_glyph_h_origin (info[i].codepoint,
-				     &pos[i].x_offset,
-				     &pos[i].y_offset);
-
     c->plan->position (c->font, c->buffer);
 
-    /* The nil glyph_h_origin() func returns 0, so no need to apply it. */
-    if (c->font->has_glyph_h_origin_func ())
-      for (unsigned int i = 0; i < count; i++)
-	c->font->subtract_glyph_h_origin (info[i].codepoint,
-					  &pos[i].x_offset,
-					  &pos[i].y_offset);
-
-  }
-
   switch (c->plan->shaper->zero_width_marks)
   {
     case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE:
       zero_mark_widths_by_gdef (c->buffer, adjust_offsets_when_zeroing);
       break;
 
     default:
     case HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE:
     case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_EARLY:
       break;
   }
 
   /* Finishing off GPOS has to follow a certain order. */
   hb_ot_layout_position_finish_advances (c->font, c->buffer);
   hb_ot_zero_width_default_ignorables (c);
   hb_ot_layout_position_finish_offsets (c->font, c->buffer);
+
+  /* The nil glyph_h_origin() func returns 0, so no need to apply it. */
+  if (c->font->has_glyph_h_origin_func ())
+    for (unsigned int i = 0; i < count; i++)
+      c->font->subtract_glyph_h_origin (info[i].codepoint,
+					&pos[i].x_offset,
+					&pos[i].y_offset);
 }
 
 static inline void
 hb_ot_position (hb_ot_shape_context_t *c)
 {
   c->buffer->clear_positions ();
 
   hb_ot_position_default (c);
--- a/gfx/harfbuzz/src/hb-ot-tag.cc
+++ b/gfx/harfbuzz/src/hb-ot-tag.cc
@@ -265,57 +265,71 @@ static const LangTag ot_languages[] = {
   {"bts",	HB_TAG('B','T','S',' ')},	/* Batak Simalungun */
   {"bug",	HB_TAG('B','U','G',' ')},	/* Buginese */
   {"bxr",	HB_TAG('R','B','U',' ')},	/* Russian Buriat */
   {"byn",	HB_TAG('B','I','L',' ')},	/* Bilen */
   {"ca",	HB_TAG('C','A','T',' ')},	/* Catalan */
   {"cak",	HB_TAG('C','A','K',' ')},	/* Kaqchikel */
   {"cbk",	HB_TAG('C','B','K',' ')},	/* Chavacano */
   {"cbl",	HB_TAG('Q','I','N',' ')},	/* Bualkhaw Chin */
+  {"cco",	HB_TAG('C','C','H','N')},	/* Chinantec */
   {"ce",	HB_TAG('C','H','E',' ')},	/* Chechen */
   {"ceb",	HB_TAG('C','E','B',' ')},	/* Cebuano */
   {"cfm",	HB_TAG('H','A','L',' ')},	/* Halam/Falam Chin */
   {"cgg",	HB_TAG('C','G','G',' ')},	/* Chiga */
   {"ch",	HB_TAG('C','H','A',' ')},	/* Chamorro */
+  {"chj",	HB_TAG('C','C','H','N')},	/* Chinantec */
   {"chk",	HB_TAG('C','H','K','0')},	/* Chuukese */
   {"cho",	HB_TAG('C','H','O',' ')},	/* Choctaw */
   {"chp",	HB_TAG('C','H','P',' ')},	/* Chipewyan */
+  {"chq",	HB_TAG('C','C','H','N')},	/* Chinantec */
   {"chr",	HB_TAG('C','H','R',' ')},	/* Cherokee */
   {"chy",	HB_TAG('C','H','Y',' ')},	/* Cheyenne */
+  {"chz",	HB_TAG('C','C','H','N')},	/* Chinantec */
   {"cja",	HB_TAG('C','J','A',' ')},	/* Western Cham */
   {"cjm",	HB_TAG('C','J','M',' ')},	/* Eastern Cham */
   {"cka",	HB_TAG('Q','I','N',' ')},	/* Khumi Awa Chin */
   {"ckb",	HB_TAG('K','U','R',' ')},	/* Central Kurdish (Sorani) */
   {"ckt",	HB_TAG('C','H','K',' ')},	/* Chukchi */
   {"cld",	HB_TAG('S','Y','R',' ')},	/* Chaldean Neo-Aramaic */
+  {"cle",	HB_TAG('C','C','H','N')},	/* Chinantec */
   {"cmr",	HB_TAG('Q','I','N',' ')},	/* Mro-Khimi Chin */
   {"cnb",	HB_TAG('Q','I','N',' ')},	/* Chinbon Chin */
   {"cnh",	HB_TAG('Q','I','N',' ')},	/* Hakha Chin */
   {"cnk",	HB_TAG('Q','I','N',' ')},	/* Khumi Chin */
+  {"cnl",	HB_TAG('C','C','H','N')},	/* Chinantec */
+  {"cnt",	HB_TAG('C','C','H','N')},	/* Chinantec */
   {"cnw",	HB_TAG('Q','I','N',' ')},	/* Ngawn Chin */
   {"cop",	HB_TAG('C','O','P',' ')},	/* Coptic */
+  {"cpa",	HB_TAG('C','C','H','N')},	/* Chinantec */
   {"cpp",	HB_TAG('C','P','P',' ')},	/* Creoles */
   {"cr",	HB_TAG('C','R','E',' ')},	/* Cree */
   {"cre",	HB_TAG('Y','C','R',' ')},	/* Y-Cree */
   {"crh",	HB_TAG('C','R','T',' ')},	/* Crimean Tatar */
   {"crj",	HB_TAG('E','C','R',' ')},	/* [Southern] East Cree */
   {"crk",	HB_TAG('W','C','R',' ')},	/* West-Cree */
   {"crl",	HB_TAG('E','C','R',' ')},	/* [Northern] East Cree */
   {"crm",	HB_TAG('M','C','R',' ')},	/* Moose Cree */
   {"crx",	HB_TAG('C','R','R',' ')},	/* Carrier */
   {"cs",	HB_TAG('C','S','Y',' ')},	/* Czech */
+  {"csa",	HB_TAG('C','C','H','N')},	/* Chinantec */
   {"csb",	HB_TAG('C','S','B',' ')},	/* Kashubian */
   {"csh",	HB_TAG('Q','I','N',' ')},	/* Asho Chin */
+  {"cso",	HB_TAG('C','C','H','N')},	/* Chinantec */
   {"csy",	HB_TAG('Q','I','N',' ')},	/* Siyin Chin */
   {"ctd",	HB_TAG('Q','I','N',' ')},	/* Tedim Chin */
+  {"cte",	HB_TAG('C','C','H','N')},	/* Chinantec */
   {"ctg",	HB_TAG('C','T','G',' ')},	/* Chittagonian */
+  {"ctl",	HB_TAG('C','C','H','N')},	/* Chinantec */
   {"cts",	HB_TAG('B','I','K',' ')},	/* Northern Catanduanes Bikol */
   {"cu",	HB_TAG('C','S','L',' ')},	/* Church Slavic */
+  {"cuc",	HB_TAG('C','C','H','N')},	/* Chinantec */
   {"cuk",	HB_TAG('C','U','K',' ')},	/* San Blas Kuna */
   {"cv",	HB_TAG('C','H','U',' ')},	/* Chuvash */
+  {"cvn",	HB_TAG('C','C','H','N')},	/* Chinantec */
   {"cwd",	HB_TAG('D','C','R',' ')},	/* Woods Cree */
   {"cy",	HB_TAG('W','E','L',' ')},	/* Welsh */
   {"czt",	HB_TAG('Q','I','N',' ')},	/* Zotung Chin */
   {"da",	HB_TAG('D','A','N',' ')},	/* Danish */
   {"dao",	HB_TAG('Q','I','N',' ')},	/* Daai Chin */
   {"dap",	HB_TAG('N','I','S',' ')},	/* Nisi (India) */
   {"dar",	HB_TAG('D','A','R',' ')},	/* Dargwa */
   {"dax",	HB_TAG('D','A','X',' ')},	/* Dayi */
@@ -375,17 +389,16 @@ static const LangTag ot_languages[] = {
   {"gd",	HB_TAG('G','A','E',' ')},	/* Scottish Gaelic */
   {"gez",	HB_TAG('G','E','Z',' ')},	/* Ge'ez */
   {"ggo",	HB_TAG('G','O','N',' ')},	/* Southern Gondi */
   {"gih",	HB_TAG('G','I','H',' ')},	/* Githabul */
   {"gil",	HB_TAG('G','I','L','0')},	/* Kiribati (Gilbertese) */
   {"gkp",	HB_TAG('G','K','P',' ')},	/* Kpelle (Guinea) */
   {"gl",	HB_TAG('G','A','L',' ')},	/* Galician */
   {"gld",	HB_TAG('N','A','N',' ')},	/* Nanai */
-  {"gle",	HB_TAG('I','R','T',' ')},	/* Irish Traditional */
   {"glk",	HB_TAG('G','L','K',' ')},	/* Gilaki */
   {"gn",	HB_TAG('G','U','A',' ')},	/* Guarani [macrolanguage] */
   {"gnn",	HB_TAG('G','N','N',' ')},	/* Gumatj */
   {"gno",	HB_TAG('G','O','N',' ')},	/* Northern Gondi */
   {"gog",	HB_TAG('G','O','G',' ')},	/* Gogo */
   {"gon",	HB_TAG('G','O','N',' ')},	/* Gondi [macrolanguage] */
   {"grt",	HB_TAG('G','R','O',' ')},	/* Garo */
   {"gru",	HB_TAG('S','O','G',' ')},	/* Sodo Gurage */
@@ -533,17 +546,16 @@ static const LangTag ot_languages[] = {
   {"luy",	HB_TAG('L','U','H',' ')},	/* Luyia/Oluluyia [macrolanguage] */
   {"luz",	HB_TAG('L','R','C',' ')},	/* Southern Luri */
   {"lv",	HB_TAG('L','V','I',' ')},	/* Latvian */
   {"lzz",	HB_TAG('L','A','Z',' ')},	/* Laz */
   {"mad",	HB_TAG('M','A','D',' ')},	/* Madurese */
   {"mag",	HB_TAG('M','A','G',' ')},	/* Magahi */
   {"mai",	HB_TAG('M','T','H',' ')},	/* Maithili */
   {"mak",	HB_TAG('M','K','R',' ')},	/* Makasar */
-  {"mal",	HB_TAG('M','A','L',' ')},	/* Malayalam */
   {"mam",	HB_TAG('M','A','M',' ')},	/* Mam */
   {"man",	HB_TAG('M','N','K',' ')},	/* Manding/Mandingo [macrolanguage] */
   {"mdc",	HB_TAG('M','L','E',' ')},	/* Male (Papua New Guinea) */
   {"mdf",	HB_TAG('M','O','K',' ')},	/* Moksha */
   {"mdr",	HB_TAG('M','D','R',' ')},	/* Mandar */
   {"mdy",	HB_TAG('M','L','E',' ')},	/* Male (Ethiopia) */
   {"men",	HB_TAG('M','D','E',' ')},	/* Mende (Sierra Leone) */
   {"mer",	HB_TAG('M','E','R',' ')},	/* Meru */
--- a/gfx/harfbuzz/src/hb-shaper-private.hh
+++ b/gfx/harfbuzz/src/hb-shaper-private.hh
@@ -83,21 +83,33 @@ struct hb_shaper_data_t {
 	HB_SHAPER_DATA_ENSURE_FUNC (shaper, object) (hb_##object##_t *object)
 
 #define HB_SHAPER_DATA_DESTROY(shaper, object) \
     if (HB_SHAPER_DATA_TYPE (shaper, object) *data = HB_SHAPER_DATA (shaper, object)) \
       if (data != HB_SHAPER_DATA_INVALID && data != HB_SHAPER_DATA_SUCCEEDED) \
         HB_SHAPER_DATA_DESTROY_FUNC (shaper, object) (data);
 
 #define HB_SHAPER_DATA_ENSURE_DEFINE(shaper, object) \
+	HB_SHAPER_DATA_ENSURE_DEFINE_WITH_CONDITION(shaper, object, true)
+
+#define HB_SHAPER_DATA_ENSURE_DEFINE_WITH_CONDITION(shaper, object, condition) \
 bool \
 HB_SHAPER_DATA_ENSURE_FUNC(shaper, object) (hb_##object##_t *object) \
 {\
   retry: \
   HB_SHAPER_DATA_TYPE (shaper, object) *data = (HB_SHAPER_DATA_TYPE (shaper, object) *) hb_atomic_ptr_get (&HB_SHAPER_DATA (shaper, object)); \
+  if (likely (data) && !(condition)) { \
+    /* Drop and recreate. */ \
+    /* If someone dropped it in the mean time, throw it away and don't touch it. \
+     * Otherwise, destruct it. */ \
+    if (hb_atomic_ptr_cmpexch (&HB_SHAPER_DATA (shaper, object), data, NULL)) { \
+      HB_SHAPER_DATA_DESTROY_FUNC (shaper, object) (data); \
+    } \
+    goto retry; \
+  } \
   if (unlikely (!data)) { \
     data = HB_SHAPER_DATA_CREATE_FUNC (shaper, object) (object); \
     if (unlikely (!data)) \
       data = (HB_SHAPER_DATA_TYPE (shaper, object) *) HB_SHAPER_DATA_INVALID; \
     if (!hb_atomic_ptr_cmpexch (&HB_SHAPER_DATA (shaper, object), NULL, data)) { \
       if (data && \
 	  data != HB_SHAPER_DATA_INVALID && \
 	  data != HB_SHAPER_DATA_SUCCEEDED) \
--- a/gfx/harfbuzz/src/hb-ucdn.cc
+++ b/gfx/harfbuzz/src/hb-ucdn.cc
@@ -155,72 +155,81 @@ static const hb_script_t ucdn_script_tra
     HB_SCRIPT_OLD_HUNGARIAN,
     HB_SCRIPT_SIGNWRITING,
     HB_SCRIPT_ADLAM,
     HB_SCRIPT_BHAIKSUKI,
     HB_SCRIPT_MARCHEN,
     HB_SCRIPT_NEWA,
     HB_SCRIPT_OSAGE,
     HB_SCRIPT_TANGUT,
+    HB_SCRIPT_MASARAM_GONDI,
+    HB_SCRIPT_NUSHU,
+    HB_SCRIPT_SOYOMBO,
+    HB_SCRIPT_ZANABAZAR_SQUARE,
 };
 
 static hb_unicode_combining_class_t
-hb_ucdn_combining_class(hb_unicode_funcs_t *ufuncs, hb_codepoint_t unicode,
+hb_ucdn_combining_class(hb_unicode_funcs_t *ufuncs HB_UNUSED,
+			hb_codepoint_t unicode,
 			void *user_data HB_UNUSED)
 {
     return (hb_unicode_combining_class_t) ucdn_get_combining_class(unicode);
 }
 
 static unsigned int
-hb_ucdn_eastasian_width(hb_unicode_funcs_t *ufuncs, hb_codepoint_t unicode,
+hb_ucdn_eastasian_width(hb_unicode_funcs_t *ufuncs HB_UNUSED,
+			hb_codepoint_t unicode,
 			void *user_data HB_UNUSED)
 {
     int w = ucdn_get_east_asian_width(unicode);
     return (w == UCDN_EAST_ASIAN_F || w == UCDN_EAST_ASIAN_W) ? 2 : 1;
 }
 
 static hb_unicode_general_category_t
-hb_ucdn_general_category(hb_unicode_funcs_t *ufuncs, hb_codepoint_t unicode,
+hb_ucdn_general_category(hb_unicode_funcs_t *ufuncs HB_UNUSED,
+			 hb_codepoint_t unicode,
 			 void *user_data HB_UNUSED)
 {
     return (hb_unicode_general_category_t)ucdn_get_general_category(unicode);
 }
 
 static hb_codepoint_t
-hb_ucdn_mirroring(hb_unicode_funcs_t *ufuncs, hb_codepoint_t unicode,
+hb_ucdn_mirroring(hb_unicode_funcs_t *ufuncs HB_UNUSED,
+		  hb_codepoint_t unicode,
 		  void *user_data HB_UNUSED)
 {
     return ucdn_mirror(unicode);
 }
 
 static hb_script_t
-hb_ucdn_script(hb_unicode_funcs_t *ufuncs, hb_codepoint_t unicode,
+hb_ucdn_script(hb_unicode_funcs_t *ufuncs HB_UNUSED,
+	       hb_codepoint_t unicode,
 	       void *user_data HB_UNUSED)
 {
     return ucdn_script_translate[ucdn_get_script(unicode)];
 }
 
 static hb_bool_t
-hb_ucdn_compose(hb_unicode_funcs_t *ufuncs,
+hb_ucdn_compose(hb_unicode_funcs_t *ufuncs HB_UNUSED,
 		hb_codepoint_t a, hb_codepoint_t b, hb_codepoint_t *ab,
 		void *user_data HB_UNUSED)
 {
     return ucdn_compose(ab, a, b);
 }
 
 static hb_bool_t
-hb_ucdn_decompose(hb_unicode_funcs_t *ufuncs,
+hb_ucdn_decompose(hb_unicode_funcs_t *ufuncs HB_UNUSED,
 		  hb_codepoint_t ab, hb_codepoint_t *a, hb_codepoint_t *b,
 		  void *user_data HB_UNUSED)
 {
     return ucdn_decompose(ab, a, b);
 }
 
 static unsigned int
-hb_ucdn_decompose_compatibility(hb_unicode_funcs_t *ufuncs,
+hb_ucdn_decompose_compatibility(hb_unicode_funcs_t *ufuncs HB_UNUSED,
 				hb_codepoint_t u, hb_codepoint_t *decomposed,
 				void *user_data HB_UNUSED)
 {
     return ucdn_compat_decompose(u, decomposed);
 }
 
 extern "C" HB_INTERNAL
 hb_unicode_funcs_t *
--- a/gfx/harfbuzz/src/hb-unicode-private.hh
+++ b/gfx/harfbuzz/src/hb-unicode-private.hh
@@ -100,24 +100,20 @@ HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS_SIM
     decomposed[ret] = 0;
     return ret;
   }
 
 
   inline unsigned int
   modified_combining_class (hb_codepoint_t unicode)
   {
-    /* XXX This hack belongs to the Arabic shaper:
-     * Put HAMZA ABOVE in the same class as SHADDA. */
-    if (unlikely (unicode == 0x0654u)) unicode = 0x0651u;
-
     /* XXX This hack belongs to the Myanmar shaper. */
     if (unlikely (unicode == 0x1037u)) unicode = 0x103Au;
 
-    /* XXX This hack belongs to the SEA shaper (for Tai Tham):
+    /* XXX This hack belongs to the USE shaper (for Tai Tham):
      * Reorder SAKOT to ensure it comes after any tone marks. */
     if (unlikely (unicode == 0x1A60u)) return 254;
 
     /* XXX This hack belongs to the Tibetan shaper:
      * Reorder PADMA to ensure it comes after any vowel marks. */
     if (unlikely (unicode == 0x0FC6u)) return 254;
     /* Reorder TSA -PHRU to reorder before U+0F74 */
     if (unlikely (unicode == 0x0F39u)) return 127;
@@ -136,16 +132,17 @@ HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS_SIM
   }
 
   /* Default_Ignorable codepoints:
    *
    * Note: While U+115F, U+1160, U+3164 and U+FFA0 are Default_Ignorable,
    * we do NOT want to hide them, as the way Uniscribe has implemented them
    * is with regular spacing glyphs, and that's the way fonts are made to work.
    * As such, we make exceptions for those four.
+   * Also ignoring U+1BCA0..1BCA3. https://github.com/behdad/harfbuzz/issues/503
    *
    * Unicode 7.0:
    * $ grep '; Default_Ignorable_Code_Point ' DerivedCoreProperties.txt | sed 's/;.*#/#/'
    * 00AD          # Cf       SOFT HYPHEN
    * 034F          # Mn       COMBINING GRAPHEME JOINER
    * 061C          # Cf       ARABIC LETTER MARK
    * 115F..1160    # Lo   [2] HANGUL CHOSEONG FILLER..HANGUL JUNGSEONG FILLER
    * 17B4..17B5    # Mn   [2] KHMER VOWEL INHERENT AQ..KHMER VOWEL INHERENT AA
@@ -192,18 +189,17 @@ HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS_SIM
 	case 0xFF: return hb_in_range<hb_codepoint_t> (ch, 0xFFF0u, 0xFFF8u);
 	default: return false;
       }
     }
     else
     {
       /* Other planes */
       switch (plane) {
-	case 0x01: return hb_in_ranges<hb_codepoint_t> (ch, 0x1BCA0u, 0x1BCA3u,
-					    0x1D173u, 0x1D17Au);
+	case 0x01: return hb_in_range<hb_codepoint_t> (ch, 0x1D173u, 0x1D17Au);
 	case 0x0E: return hb_in_range<hb_codepoint_t> (ch, 0xE0000u, 0xE0FFFu);
 	default: return false;
       }
     }
   }
 
   /* Space estimates based on:
    * http://www.unicode.org/charts/PDF/U2000.pdf
--- a/gfx/harfbuzz/src/hb-version.h
+++ b/gfx/harfbuzz/src/hb-version.h
@@ -32,20 +32,20 @@
 #define HB_VERSION_H
 
 #include "hb-common.h"
 
 HB_BEGIN_DECLS
 
 
 #define HB_VERSION_MAJOR 1
-#define HB_VERSION_MINOR 5
-#define HB_VERSION_MICRO 1
+#define HB_VERSION_MINOR 6
+#define HB_VERSION_MICRO 0
 
-#define HB_VERSION_STRING "1.5.1"
+#define HB_VERSION_STRING "1.6.0"
 
 #define HB_VERSION_ATLEAST(major,minor,micro) \
 	((major)*10000+(minor)*100+(micro) <= \
 	 HB_VERSION_MAJOR*10000+HB_VERSION_MINOR*100+HB_VERSION_MICRO)
 
 
 HB_EXTERN void
 hb_version (unsigned int *major,
--- a/gfx/thebes/gfxFont.cpp
+++ b/gfx/thebes/gfxFont.cpp
@@ -1612,19 +1612,25 @@ public:
     }
 
     const TextRunDrawParams& mRunParams;
     const FontDrawParams& mFontParams;
 
 private:
 #define GLYPH_BUFFER_SIZE (2048/sizeof(Glyph))
 
+    Glyph* GlyphBuffer()
+    {
+        return *mGlyphBuffer.addr();
+    }
+
+
     Glyph *AppendGlyph()
     {
-        return &mGlyphBuffer[mNumGlyphs++];
+        return &GlyphBuffer()[mNumGlyphs++];
     }
 
     static DrawMode
     GetStrokeMode(DrawMode aMode)
     {
         return aMode & (DrawMode::GLYPH_STROKE |
                         DrawMode::GLYPH_STROKE_UNDERNEATH);
     }
@@ -1635,23 +1641,23 @@ private:
     void Flush(bool aFinish)
     {
         // Ensure there's enough room for a glyph to be added to the buffer
         if ((!aFinish && mNumGlyphs < GLYPH_BUFFER_SIZE) || !mNumGlyphs) {
             return;
         }
 
         if (mRunParams.isRTL) {
-            Glyph *begin = &mGlyphBuffer[0];
-            Glyph *end = &mGlyphBuffer[mNumGlyphs];
+            Glyph *begin = &GlyphBuffer()[0];
+            Glyph *end = &GlyphBuffer()[mNumGlyphs];
             std::reverse(begin, end);
         }
 
         gfx::GlyphBuffer buf;
-        buf.mGlyphs = mGlyphBuffer;
+        buf.mGlyphs = GlyphBuffer();
         buf.mNumGlyphs = mNumGlyphs;
 
         const gfxContext::AzureState &state = mRunParams.context->CurrentState();
         if (mRunParams.drawMode & DrawMode::GLYPH_FILL) {
             if (state.pattern || mFontParams.contextPaint) {
                 Pattern *pat;
 
                 RefPtr<gfxPattern> fillPattern;
@@ -1783,17 +1789,19 @@ private:
     {
         mRunParams.dt->StrokeGlyphs(mFontParams.scaledFont, aBuf,
                                     aPattern,
                                     *mRunParams.strokeOpts,
                                     mFontParams.drawOptions,
                                     mFontParams.renderingOptions);
     }
 
-    Glyph        mGlyphBuffer[GLYPH_BUFFER_SIZE];
+    // Allocate space for a buffer of Glyph records, without initializing them.
+    AlignedStorage2<Glyph[GLYPH_BUFFER_SIZE]> mGlyphBuffer;
+
     unsigned int mNumGlyphs;
 
 #undef GLYPH_BUFFER_SIZE
 };
 
 // Bug 674909. When synthetic bolding text by drawing twice, need to
 // render using a pixel offset in device pixels, otherwise text
 // doesn't appear bolded, it appears as if a bad text shadow exists
deleted file mode 100644
--- a/intl/locales/Makefile.in
+++ /dev/null
@@ -1,14 +0,0 @@
-# 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 $(topsrcdir)/config/rules.mk
-
-ifndef MOZ_EXCLUDE_HYPHENATION_DICTIONARIES
-PATTERN_FILES = $(strip $(wildcard $(srcdir)/*/hyphenation/*.dic))
-
-ifneq (,$(PATTERN_FILES))
-libs::
-	$(INSTALL)  $(PATTERN_FILES) $(FINAL_TARGET)/hyphenation
-endif
-endif # MOZ_EXCLUDE_HYPHENATION_DICTIONARIES
--- a/intl/locales/moz.build
+++ b/intl/locales/moz.build
@@ -1,6 +1,48 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
+locales = [
+    'af',
+    'bg',
+    'ca',
+    'cy',
+    'da',
+    'de-1901',
+    'de-1996',
+    'de-CH',
+    # 'en-US',  # en-US is renamed -- see below.
+    'eo',
+    'es',
+    'et',
+    'fi',
+    'fr',
+    'gl',
+    'hr',
+    'hsb',
+    'hu',
+    'ia',
+    'is',
+    'it',
+    'kmr',
+    'la',
+    'lt',
+    'mn',
+    'nb',
+    'nl',
+    'nn',
+    'pl',
+    'pt',
+    'ru',
+    'sh',
+    'sl',
+    'sv',
+    'tr',
+    'uk',
+]
+filename = '{locale}/hyphenation/hyph_{locale}.dic'
+FINAL_TARGET_FILES.hyphenation += [filename.format(locale=locale) for locale in locales]
+# en-US is a special case: the dic file is named like en_US.
+FINAL_TARGET_FILES.hyphenation += ['en-US/hyphenation/hyph_en_US.dic']
--- a/js/moz.configure
+++ b/js/moz.configure
@@ -249,8 +249,20 @@ with only_when('--enable-compile-environ
         if fuzzing and not afl:
             return True
 
     set_config('FUZZING', enable_fuzzing)
     set_define('FUZZING', enable_fuzzing)
 
     set_config('LIBFUZZER', enable_libfuzzer)
     set_define('LIBFUZZER', enable_libfuzzer)
+
+# Enable pipeline operator
+# ===================================================
+js_option('--enable-pipeline-operator', default=False, help='Enable pipeline operator')
+
+@depends('--enable-pipeline-operator')
+def enable_pipeline_operator(value):
+    if value:
+        return True
+
+set_config('ENABLE_PIPELINE_OPERATOR', enable_pipeline_operator)
+set_define('ENABLE_PIPELINE_OPERATOR', enable_pipeline_operator)
--- a/js/src/builtin/ReflectParse.cpp
+++ b/js/src/builtin/ReflectParse.cpp
@@ -73,17 +73,17 @@ enum BinaryOperator {
     BINOP_LT, BINOP_LE, BINOP_GT, BINOP_GE,
     /* shift */
     BINOP_LSH, BINOP_RSH, BINOP_URSH,
     /* arithmetic */
     BINOP_ADD, BINOP_SUB, BINOP_STAR, BINOP_DIV, BINOP_MOD, BINOP_POW,
     /* binary */
     BINOP_BITOR, BINOP_BITXOR, BINOP_BITAND,
     /* misc */
-    BINOP_IN, BINOP_INSTANCEOF,
+    BINOP_IN, BINOP_INSTANCEOF, BINOP_PIPELINE,
 
     BINOP_LIMIT
 };
 
 enum UnaryOperator {
     UNOP_ERR = -1,
 
     UNOP_DELETE = 0,
@@ -149,16 +149,17 @@ static const char* const binopNames[] = 
     "/",          /* BINOP_DIV */
     "%",          /* BINOP_MOD */
     "**",         /* BINOP_POW */
     "|",          /* BINOP_BITOR */
     "^",          /* BINOP_BITXOR */
     "&",          /* BINOP_BITAND */
     "in",         /* BINOP_IN */
     "instanceof", /* BINOP_INSTANCEOF */
+    "|>",         /* BINOP_PIPELINE */
 };
 
 static const char* const unopNames[] = {
     "delete",  /* UNOP_DELETE */
     "-",       /* UNOP_NEG */
     "+",       /* UNOP_POS */
     "!",       /* UNOP_NOT */
     "~",       /* UNOP_BITNOT */
@@ -1947,16 +1948,18 @@ ASTSerializer::binop(ParseNodeKind kind)
       case PNK_BITXOR:
         return BINOP_BITXOR;
       case PNK_BITAND:
         return BINOP_BITAND;
       case PNK_IN:
         return BINOP_IN;
       case PNK_INSTANCEOF:
         return BINOP_INSTANCEOF;
+      case PNK_PIPELINE:
+        return BINOP_PIPELINE;
       default:
         return BINOP_ERR;
     }
 }
 
 bool
 ASTSerializer::statements(ParseNode* pn, NodeVector& elts)
 {
@@ -2890,16 +2893,17 @@ ASTSerializer::expression(ParseNode* pn,
         LOCAL_ASSERT(op > AOP_ERR && op < AOP_LIMIT);
 
         RootedValue lhs(cx), rhs(cx);
         return pattern(pn->pn_left, &lhs) &&
                expression(pn->pn_right, &rhs) &&
                builder.assignmentExpression(op, lhs, rhs, &pn->pn_pos, dst);
       }
 
+      case PNK_PIPELINE:
       case PNK_ADD:
       case PNK_SUB:
       case PNK_STRICTEQ:
       case PNK_EQ:
       case PNK_STRICTNE:
       case PNK_NE:
       case PNK_LT:
       case PNK_LE:
--- a/js/src/builtin/TestingFunctions.cpp
+++ b/js/src/builtin/TestingFunctions.cpp
@@ -562,16 +562,39 @@ WasmThreadsSupported(JSContext* cx, unsi
 
     isSupported = isSupported && jit::AtomicOperations::isLockfree8();
 
     args.rval().setBoolean(isSupported);
     return true;
 }
 
 static bool
+WasmCompileMode(JSContext* cx, unsigned argc, Value* vp)
+{
+    CallArgs args = CallArgsFromVp(argc, vp);
+
+    // We default to ion if nothing is enabled, as does the Wasm compiler.
+    JSString* result;
+    if (!wasm::HasSupport(cx))
+        result = JS_NewStringCopyZ(cx, "disabled");
+    else if (cx->options().wasmBaseline() && cx->options().wasmIon())
+        result = JS_NewStringCopyZ(cx, "baseline-or-ion");
+    else if (cx->options().wasmBaseline())
+        result = JS_NewStringCopyZ(cx, "baseline");
+    else
+        result = JS_NewStringCopyZ(cx, "ion");
+
+    if (!result)
+        return false;
+
+    args.rval().setString(result);
+    return true;
+}
+
+static bool
 WasmTextToBinary(JSContext* cx, unsigned argc, Value* vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     RootedObject callee(cx, &args.callee());
 
     if (!args.requireAtLeast(cx, "wasmTextToBinary", 1))
         return false;
 
@@ -5242,16 +5265,21 @@ gc::ZealModeHelpText),
 "  Returns a boolean indicating whether WebAssembly debugging is supported on the current device;\n"
 "  returns false also if WebAssembly is not supported"),
 
     JS_FN_HELP("wasmThreadsSupported", WasmThreadsSupported, 0, 0,
 "wasmThreadsSupported()",
 "  Returns a boolean indicating whether the WebAssembly threads proposal is\n"
 "  supported on the current device."),
 
+    JS_FN_HELP("wasmCompileMode", WasmCompileMode, 0, 0,
+"wasmCompileMode()",
+"  Returns a string indicating the available compile policy: 'baseline', 'ion',\n"
+"  'baseline-or-ion', or 'disabled' (if wasm is not available at all)."),
+
     JS_FN_HELP("wasmTextToBinary", WasmTextToBinary, 1, 0,
 "wasmTextToBinary(str)",
 "  Translates the given text wasm module into its binary encoding."),
 
     JS_FN_HELP("wasmBinaryToText", WasmBinaryToText, 1, 0,
 "wasmBinaryToText(bin)",
 "  Translates binary encoding to text format"),
 
--- a/js/src/builtin/TypedObject.cpp
+++ b/js/src/builtin/TypedObject.cpp
@@ -19,16 +19,17 @@
 #include "vm/GlobalObject.h"
 #include "vm/String.h"
 #include "vm/StringBuffer.h"
 #include "vm/TypedArrayObject.h"
 
 #include "jsatominlines.h"
 #include "jsobjinlines.h"
 
+#include "gc/Nursery-inl.h"
 #include "gc/StoreBuffer-inl.h"
 #include "vm/NativeObject-inl.h"
 #include "vm/Shape-inl.h"
 
 using mozilla::AssertedCast;
 using mozilla::CheckedInt32;
 using mozilla::DebugOnly;
 using mozilla::IsPowerOfTwo;
@@ -1239,17 +1240,17 @@ DefineMetaTypeDescr(JSContext* cx,
 /* static */ bool
 GlobalObject::initTypedObjectModule(JSContext* cx, Handle<GlobalObject*> global)
 {
     RootedObject objProto(cx, GlobalObject::getOrCreateObjectPrototype(cx, global));
     if (!objProto)
         return false;
 
     Rooted<TypedObjectModuleObject*> module(cx);
-    module = NewObjectWithGivenProto<TypedObjectModuleObject>(cx, objProto);
+    module = NewObjectWithGivenProto<TypedObjectModuleObject>(cx, objProto, SingletonObject);
     if (!module)
         return false;
 
     if (!JS_DefineFunctions(cx, module, TypedObjectMethods))
         return false;
 
     // uint8, uint16, any, etc
 
--- a/js/src/devtools/rootAnalysis/annotations.js
+++ b/js/src/devtools/rootAnalysis/annotations.js
@@ -214,18 +214,19 @@ var ignoreFunctions = {
     // currently smart enough to determine that. In either case, this is (a)
     // only in GTests, and (b) only when the Gtest has already failed. We have
     // static and dynamic checks for no GC in the non-test code, and in the test
     // code we fall back to only the dynamic checks.
     "void test::RingbufferDumper::OnTestPartResult(testing::TestPartResult*)" : true,
 
     "float64 JS_GetCurrentEmbedderTime()" : true,
 
-    "uint64 js::TenuringTracer::moveObjectToTenured(JSObject*, JSObject*, int32)" : true,
-    "uint32 js::TenuringTracer::moveObjectToTenured(JSObject*, JSObject*, int32)" : true,
+    // This calls any JSObjectMovedOp for the tenured object via an indirect call.
+    "JSObject* js::TenuringTracer::moveToTenuredSlow(JSObject*)" : true,
+
     "void js::Nursery::freeMallocedBuffers()" : true,
 
     "void js::AutoEnterOOMUnsafeRegion::crash(uint64, int8*)" : true,
 
     "void mozilla::dom::workers::WorkerPrivate::AssertIsOnWorkerThread() const" : true,
 
     // It would be cool to somehow annotate that nsTHashtable<T> will use
     // nsTHashtable<T>::s_MatchEntry for its matchEntry function pointer, but
--- a/js/src/frontend/BytecodeEmitter.cpp
+++ b/js/src/frontend/BytecodeEmitter.cpp
@@ -3382,16 +3382,22 @@ BytecodeEmitter::checkSideEffects(ParseN
       case PNK_NEW:
       case PNK_CALL:
       case PNK_TAGGED_TEMPLATE:
       case PNK_SUPERCALL:
         MOZ_ASSERT(pn->isArity(PN_LIST));
         *answer = true;
         return true;
 
+      case PNK_PIPELINE:
+        MOZ_ASSERT(pn->isArity(PN_LIST));
+        MOZ_ASSERT(pn->pn_count >= 2);
+        *answer = true;
+        return true;
+
       // Classes typically introduce names.  Even if no name is introduced,
       // the heritage and/or class body (through computed property names)
       // usually have effects.
       case PNK_CLASS:
         MOZ_ASSERT(pn->isArity(PN_TERNARY));
         *answer = true;
         return true;
 
@@ -9462,16 +9468,123 @@ BytecodeEmitter::isRestParameter(ParseNo
             return paramName && name == paramName;
         }
     }
 
     return false;
 }
 
 bool
+BytecodeEmitter::emitCallee(ParseNode* callee, ParseNode* call, bool spread, bool* callop)
+{
+    switch (callee->getKind()) {
+      case PNK_NAME:
+        if (!emitGetName(callee, *callop))
+            return false;
+        break;
+      case PNK_DOT:
+        MOZ_ASSERT(emitterMode != BytecodeEmitter::SelfHosting);
+        if (callee->as<PropertyAccess>().isSuper()) {
+            if (!emitSuperPropOp(callee, JSOP_GETPROP_SUPER, /* isCall = */ *callop))
+                return false;
+        } else {
+            if (!emitPropOp(callee, *callop ? JSOP_CALLPROP : JSOP_GETPROP))
+                return false;
+        }
+
+        break;
+      case PNK_ELEM:
+        MOZ_ASSERT(emitterMode != BytecodeEmitter::SelfHosting);
+        if (callee->as<PropertyByValue>().isSuper()) {
+            if (!emitSuperElemOp(callee, JSOP_GETELEM_SUPER, /* isCall = */ *callop))
+                return false;
+        } else {
+            if (!emitElemOp(callee, *callop ? JSOP_CALLELEM : JSOP_GETELEM))
+                return false;
+            if (*callop) {
+                if (!emit1(JSOP_SWAP))
+                    return false;
+            }
+        }
+
+        break;
+      case PNK_FUNCTION:
+        /*
+         * Top level lambdas which are immediately invoked should be
+         * treated as only running once. Every time they execute we will
+         * create new types and scripts for their contents, to increase
+         * the quality of type information within them and enable more
+         * backend optimizations. Note that this does not depend on the
+         * lambda being invoked at most once (it may be named or be
+         * accessed via foo.caller indirection), as multiple executions
+         * will just cause the inner scripts to be repeatedly cloned.
+         */
+        MOZ_ASSERT(!emittingRunOnceLambda);
+        if (checkRunOnceContext()) {
+            emittingRunOnceLambda = true;
+            if (!emitTree(callee))
+                return false;
+            emittingRunOnceLambda = false;
+        } else {
+            if (!emitTree(callee))
+                return false;
+        }
+        *callop = false;
+        break;
+      case PNK_SUPERBASE:
+        MOZ_ASSERT(call->isKind(PNK_SUPERCALL));
+        MOZ_ASSERT(parser.isSuperBase(callee));
+        if (!emit1(JSOP_SUPERFUN))
+            return false;
+        break;
+      default:
+        if (!emitTree(callee))
+            return false;
+        *callop = false;             /* trigger JSOP_UNDEFINED after */
+        break;
+    }
+
+    return true;
+}
+
+bool
+BytecodeEmitter::emitPipeline(ParseNode* pn)
+{
+    MOZ_ASSERT(pn->isArity(PN_LIST));
+    MOZ_ASSERT(pn->pn_count >= 2);
+
+    if (!emitTree(pn->pn_head))
+        return false;
+
+    ParseNode* callee = pn->pn_head->pn_next;
+
+    do {
+        bool callop = true;
+        if (!emitCallee(callee, pn, false, &callop))
+            return false;
+
+        // Emit room for |this|
+        if (!callop) {
+            if (!emit1(JSOP_UNDEFINED))
+                return false;
+        }
+
+        if (!emit2(JSOP_PICK, 2))
+            return false;
+
+        if (!emitCall(JSOP_CALL, 1, pn))
+            return false;
+
+        checkTypeSet(JSOP_CALL);
+    } while ((callee = callee->pn_next));
+
+    return true;
+}
+
+bool
 BytecodeEmitter::emitCallOrNew(ParseNode* pn, ValueUsage valueUsage /* = ValueUsage::WantValue */)
 {
     bool callop = pn->isKind(PNK_CALL) || pn->isKind(PNK_TAGGED_TEMPLATE);
     /*
      * Emit callable invocation or operator new (constructor call) code.
      * First, emit code for the left operand to evaluate the callable or
      * constructable object expression.
      *
@@ -9489,104 +9602,42 @@ BytecodeEmitter::emitCallOrNew(ParseNode
 
     if (argc >= ARGC_LIMIT) {
         parser.reportError(callop ? JSMSG_TOO_MANY_FUN_ARGS : JSMSG_TOO_MANY_CON_ARGS);
         return false;
     }
 
     ParseNode* pn2 = pn->pn_head;
     bool spread = JOF_OPTYPE(pn->getOp()) == JOF_BYTE;
-    switch (pn2->getKind()) {
-      case PNK_NAME:
-        if (emitterMode == BytecodeEmitter::SelfHosting && !spread) {
-            // Calls to "forceInterpreter", "callFunction",
-            // "callContentFunction", or "resumeGenerator" in self-hosted
-            // code generate inline bytecode.
-            if (pn2->name() == cx->names().callFunction ||
-                pn2->name() == cx->names().callContentFunction ||
-                pn2->name() == cx->names().constructContentFunction)
-            {
-                return emitSelfHostedCallFunction(pn);
-            }
-            if (pn2->name() == cx->names().resumeGenerator)
-                return emitSelfHostedResumeGenerator(pn);
-            if (pn2->name() == cx->names().forceInterpreter)
-                return emitSelfHostedForceInterpreter(pn);
-            if (pn2->name() == cx->names().allowContentIter)
-                return emitSelfHostedAllowContentIter(pn);
-            if (pn2->name() == cx->names().defineDataPropertyIntrinsic && pn->pn_count == 4)
-                return emitSelfHostedDefineDataProperty(pn);
-            if (pn2->name() == cx->names().hasOwn)
-                return emitSelfHostedHasOwn(pn);
-            // Fall through.
-        }
-        if (!emitGetName(pn2, callop))
-            return false;
-        break;
-      case PNK_DOT:
-        MOZ_ASSERT(emitterMode != BytecodeEmitter::SelfHosting);
-        if (pn2->as<PropertyAccess>().isSuper()) {
-            if (!emitSuperPropOp(pn2, JSOP_GETPROP_SUPER, /* isCall = */ callop))
-                return false;
-        } else {
-            if (!emitPropOp(pn2, callop ? JSOP_CALLPROP : JSOP_GETPROP))
-                return false;
-        }
-
-        break;
-      case PNK_ELEM:
-        MOZ_ASSERT(emitterMode != BytecodeEmitter::SelfHosting);
-        if (pn2->as<PropertyByValue>().isSuper()) {
-            if (!emitSuperElemOp(pn2, JSOP_GETELEM_SUPER, /* isCall = */ callop))
-                return false;
-        } else {
-            if (!emitElemOp(pn2, callop ? JSOP_CALLELEM : JSOP_GETELEM))
-                return false;
-            if (callop) {
-                if (!emit1(JSOP_SWAP))
-                    return false;
-            }
-        }
-
-        break;
-      case PNK_FUNCTION:
-        /*
-         * Top level lambdas which are immediately invoked should be
-         * treated as only running once. Every time they execute we will
-         * create new types and scripts for their contents, to increase
-         * the quality of type information within them and enable more
-         * backend optimizations. Note that this does not depend on the
-         * lambda being invoked at most once (it may be named or be
-         * accessed via foo.caller indirection), as multiple executions
-         * will just cause the inner scripts to be repeatedly cloned.
-         */
-        MOZ_ASSERT(!emittingRunOnceLambda);
-        if (checkRunOnceContext()) {
-            emittingRunOnceLambda = true;
-            if (!emitTree(pn2))
-                return false;
-            emittingRunOnceLambda = false;
-        } else {
-            if (!emitTree(pn2))
-                return false;
-        }
-        callop = false;
-        break;
-      case PNK_SUPERBASE:
-        MOZ_ASSERT(pn->isKind(PNK_SUPERCALL));
-        MOZ_ASSERT(parser.isSuperBase(pn2));
-        if (!emit1(JSOP_SUPERFUN))
-            return false;
-        break;
-      default:
-        if (!emitTree(pn2))
-            return false;
-        callop = false;             /* trigger JSOP_UNDEFINED after */
-        break;
-    }
+
+    if (pn2->isKind(PNK_NAME) && emitterMode == BytecodeEmitter::SelfHosting && !spread) {
+        // Calls to "forceInterpreter", "callFunction",
+        // "callContentFunction", or "resumeGenerator" in self-hosted
+        // code generate inline bytecode.
+        if (pn2->name() == cx->names().callFunction ||
+            pn2->name() == cx->names().callContentFunction ||
+            pn2->name() == cx->names().constructContentFunction)
+        {
+            return emitSelfHostedCallFunction(pn);
+        }
+        if (pn2->name() == cx->names().resumeGenerator)
+            return emitSelfHostedResumeGenerator(pn);
+        if (pn2->name() == cx->names().forceInterpreter)
+            return emitSelfHostedForceInterpreter(pn);
+        if (pn2->name() == cx->names().allowContentIter)
+            return emitSelfHostedAllowContentIter(pn);
+        if (pn2->name() == cx->names().defineDataPropertyIntrinsic && pn->pn_count == 4)
+            return emitSelfHostedDefineDataProperty(pn);
+        if (pn2->name() == cx->names().hasOwn)
+            return emitSelfHostedHasOwn(pn);
+        // Fall through
+    }
+
+    if (!emitCallee(pn2, pn, spread, &callop))
+        return false;
 
     bool isNewOp = pn->getOp() == JSOP_NEW || pn->getOp() == JSOP_SPREADNEW ||
                    pn->getOp() == JSOP_SUPERCALL || pn->getOp() == JSOP_SPREADSUPERCALL;
 
 
     // Emit room for |this|.
     if (!callop) {
         if (isNewOp) {
@@ -9696,16 +9747,19 @@ BytecodeEmitter::emitCallOrNew(ParseNode
         if (!emitUint32Operand(JSOP_LINENO, lineNum))
             return false;
     }
 
     return true;
 }
 
 static const JSOp ParseNodeKindToJSOp[] = {
+    // JSOP_NOP is for pipeline operator which does not emit its own JSOp
+    // but has highest precedence in binary operators
+    JSOP_NOP,
     JSOP_OR,
     JSOP_AND,
     JSOP_BITOR,
     JSOP_BITXOR,
     JSOP_BITAND,
     JSOP_STRICTEQ,
     JSOP_EQ,
     JSOP_STRICTNE,
@@ -11082,16 +11136,21 @@ BytecodeEmitter::emitTree(ParseNode* pn,
             return false;
         break;
 
       case PNK_POW:
         if (!emitRightAssociative(pn))
             return false;
         break;
 
+      case PNK_PIPELINE:
+        if (!emitPipeline(pn))
+            return false;
+        break;
+
       case PNK_TYPEOFNAME:
         if (!emitTypeof(pn, JSOP_TYPEOF))
             return false;
         break;
 
       case PNK_TYPEOFEXPR:
         if (!emitTypeof(pn, JSOP_TYPEOFEXPR))
             return false;
--- a/js/src/frontend/BytecodeEmitter.h
+++ b/js/src/frontend/BytecodeEmitter.h
@@ -830,14 +830,18 @@ struct MOZ_STACK_CLASS BytecodeEmitter
     MOZ_MUST_USE bool emitSpread(bool allowSelfHosted = false);
 
     MOZ_MUST_USE bool emitClass(ParseNode* pn);
     MOZ_MUST_USE bool emitSuperPropLHS(ParseNode* superBase, bool isCall = false);
     MOZ_MUST_USE bool emitSuperPropOp(ParseNode* pn, JSOp op, bool isCall = false);
     MOZ_MUST_USE bool emitSuperElemOperands(ParseNode* pn,
                                             EmitElemOption opts = EmitElemOption::Get);
     MOZ_MUST_USE bool emitSuperElemOp(ParseNode* pn, JSOp op, bool isCall = false);
+
+    MOZ_MUST_USE bool emitCallee(ParseNode* callee, ParseNode* call, bool spread, bool* callop);
+
+    MOZ_MUST_USE bool emitPipeline(ParseNode* pn);
 };
 
 } /* namespace frontend */
 } /* namespace js */
 
 #endif /* frontend_BytecodeEmitter_h */
--- a/js/src/frontend/FoldConstants.cpp
+++ b/js/src/frontend/FoldConstants.cpp
@@ -400,16 +400,21 @@ ContainsHoistedDeclaration(JSContext* cx
       case PNK_NEWTARGET:
       case PNK_POSHOLDER:
       case PNK_SUPERCALL:
       case PNK_SUPERBASE:
       case PNK_SETTHIS:
         MOZ_CRASH("ContainsHoistedDeclaration should have indicated false on "
                   "some parent node without recurring to test this node");
 
+      case PNK_PIPELINE:
+        MOZ_ASSERT(node->isArity(PN_LIST));
+        *result = false;
+        return true;
+
       case PNK_LIMIT: // invalid sentinel value
         MOZ_CRASH("unexpected PNK_LIMIT in node");
     }
 
     MOZ_CRASH("invalid node kind");
 }
 
 /*
@@ -1719,16 +1724,19 @@ Fold(JSContext* cx, ParseNode** pnp, Par
 
       case PNK_SEMI:
       case PNK_THIS:
         MOZ_ASSERT(pn->isArity(PN_UNARY));
         if (ParseNode*& expr = pn->pn_kid)
             return Fold(cx, &expr, parser, inGenexpLambda);
         return true;
 
+      case PNK_PIPELINE:
+        return true;
+
       case PNK_AND:
       case PNK_OR:
         return FoldAndOr(cx, pnp, parser, inGenexpLambda);
 
       case PNK_FUNCTION:
         return FoldFunction(cx, pn, parser, inGenexpLambda);
 
       case PNK_MODULE:
--- a/js/src/frontend/NameFunctions.cpp
+++ b/js/src/frontend/NameFunctions.cpp
@@ -682,16 +682,17 @@ class NameResolver
           case PNK_RSH:
           case PNK_URSH:
           case PNK_ADD:
           case PNK_SUB:
           case PNK_STAR:
           case PNK_DIV:
           case PNK_MOD:
           case PNK_POW:
+          case PNK_PIPELINE:
           case PNK_COMMA:
           case PNK_NEW:
           case PNK_CALL:
           case PNK_SUPERCALL:
           case PNK_GENEXP:
           case PNK_ARRAY:
           case PNK_STATEMENTLIST:
           case PNK_PARAMSBODY:
--- a/js/src/frontend/ParseNode.cpp
+++ b/js/src/frontend/ParseNode.cpp
@@ -442,16 +442,17 @@ PushNodeChildren(ParseNode* pn, NodeStac
       case PNK_RSH:
       case PNK_URSH:
       case PNK_ADD:
       case PNK_SUB:
       case PNK_STAR:
       case PNK_DIV:
       case PNK_MOD:
       case PNK_POW:
+      case PNK_PIPELINE:
       case PNK_COMMA:
       case PNK_NEW:
       case PNK_CALL:
       case PNK_SUPERCALL:
       case PNK_GENEXP:
       case PNK_ARRAY:
       case PNK_OBJECT:
       case PNK_TEMPLATE_STRING_LIST:
--- a/js/src/frontend/ParseNode.h
+++ b/js/src/frontend/ParseNode.h
@@ -124,16 +124,17 @@ class ObjectBox;
     F(NOT) \
     F(BITNOT) \
     F(AWAIT) \
     \
     /* \
      * Binary operators. \
      * These must be in the same order as TOK_OR and friends in TokenStream.h. \
      */ \
+    F(PIPELINE) \
     F(OR) \
     F(AND) \
     F(BITOR) \
     F(BITXOR) \
     F(BITAND) \
     F(STRICTEQ) \
     F(EQ) \
     F(STRICTNE) \
@@ -181,17 +182,17 @@ class ObjectBox;
  * The long comment after this enum block describes the kinds in detail.
  */
 enum ParseNodeKind : uint16_t
 {
 #define EMIT_ENUM(name) PNK_##name,
     FOR_EACH_PARSE_NODE_KIND(EMIT_ENUM)
 #undef EMIT_ENUM
     PNK_LIMIT, /* domain size */
-    PNK_BINOP_FIRST = PNK_OR,
+    PNK_BINOP_FIRST = PNK_PIPELINE,
     PNK_BINOP_LAST = PNK_POW,
     PNK_ASSIGNMENT_START = PNK_ASSIGN,
     PNK_ASSIGNMENT_LAST = PNK_POWASSIGN
 };
 
 inline bool
 IsDeleteKind(ParseNodeKind kind)
 {
--- a/js/src/frontend/Parser.cpp
+++ b/js/src/frontend/Parser.cpp
@@ -7992,43 +7992,44 @@ Parser<ParseHandler, CharT>::expr(InHand
 static ParseNodeKind
 BinaryOpTokenKindToParseNodeKind(TokenKind tok)
 {
     MOZ_ASSERT(TokenKindIsBinaryOp(tok));
     return ParseNodeKind(PNK_BINOP_FIRST + (tok - TOK_BINOP_FIRST));
 }
 
 static const int PrecedenceTable[] = {
-    1, /* PNK_OR */
-    2, /* PNK_AND */
-    3, /* PNK_BITOR */
-    4, /* PNK_BITXOR */
-    5, /* PNK_BITAND */
-    6, /* PNK_STRICTEQ */
-    6, /* PNK_EQ */
-    6, /* PNK_STRICTNE */
-    6, /* PNK_NE */
-    7, /* PNK_LT */
-    7, /* PNK_LE */
-    7, /* PNK_GT */
-    7, /* PNK_GE */
-    7, /* PNK_INSTANCEOF */
-    7, /* PNK_IN */
-    8, /* PNK_LSH */
-    8, /* PNK_RSH */
-    8, /* PNK_URSH */
-    9, /* PNK_ADD */
-    9, /* PNK_SUB */
-    10, /* PNK_STAR */
-    10, /* PNK_DIV */
-    10, /* PNK_MOD */
-    11  /* PNK_POW */
+    1, /* PNK_PIPELINE */
+    2, /* PNK_OR */
+    3, /* PNK_AND */
+    4, /* PNK_BITOR */
+    5, /* PNK_BITXOR */
+    6, /* PNK_BITAND */
+    7, /* PNK_STRICTEQ */
+    7, /* PNK_EQ */
+    7, /* PNK_STRICTNE */
+    7, /* PNK_NE */
+    8, /* PNK_LT */
+    8, /* PNK_LE */
+    8, /* PNK_GT */
+    8, /* PNK_GE */
+    8, /* PNK_INSTANCEOF */
+    8, /* PNK_IN */
+    9, /* PNK_LSH */
+    9, /* PNK_RSH */
+    9, /* PNK_URSH */
+    10, /* PNK_ADD */
+    10, /* PNK_SUB */
+    11, /* PNK_STAR */
+    11, /* PNK_DIV */
+    11, /* PNK_MOD */
+    12  /* PNK_POW */
 };
 
-static const int PRECEDENCE_CLASSES = 11;
+static const int PRECEDENCE_CLASSES = 12;
 
 static int
 Precedence(ParseNodeKind pnk) {
     // Everything binds tighter than PNK_LIMIT, because we want to reduce all
     // nodes to a single node when we reach a token that is not another binary
     // operator.
     if (pnk == PNK_LIMIT)
         return 0;
--- a/js/src/frontend/TokenKind.h
+++ b/js/src/frontend/TokenKind.h
@@ -150,18 +150,19 @@
     /* \
      * The following token types occupy contiguous ranges to enable easy \
      * range-testing. \
      */ \
     /* \
      * Binary operators tokens, TOK_OR thru TOK_POW. These must be in the same \
      * order as F(OR) and friends in FOR_EACH_PARSE_NODE_KIND in ParseNode.h. \
      */ \
+    macro(PIPELINE,     "'|>'") \
+    range(BINOP_FIRST,  PIPELINE) \
     macro(OR,           "'||'")   /* logical or */ \
-    range(BINOP_FIRST, OR) \
     macro(AND,          "'&&'")   /* logical and */ \
     macro(BITOR,        "'|'")    /* bitwise-or */ \
     macro(BITXOR,       "'^'")    /* bitwise-xor */ \
     macro(BITAND,       "'&'")    /* bitwise-and */ \
     \
     /* Equality operation tokens, per TokenKindIsEquality. */ \
     macro(STRICTEQ,     "'==='") \
     range(EQUALITY_START, STRICTEQ) \
@@ -191,17 +192,17 @@
     range(SHIFTOP_LAST, URSH) \
     \
     macro(ADD,          "'+'") \
     macro(SUB,          "'-'") \
     macro(MUL,          "'*'") \
     macro(DIV,          "'/'") \
     macro(MOD,          "'%'") \
     macro(POW,          "'**'") \
-    range(BINOP_LAST, POW) \
+    range(BINOP_LAST,   POW) \
     \
     /* Unary operation tokens. */ \
     macro(TYPEOF,       "keyword 'typeof'") \
     range(KEYWORD_UNOP_FIRST, TYPEOF) \
     macro(VOID,         "keyword 'void'") \
     range(KEYWORD_UNOP_LAST, VOID) \
     macro(NOT,          "'!'") \
     macro(BITNOT,       "'~'") \
--- a/js/src/frontend/TokenStream.cpp
+++ b/js/src/frontend/TokenStream.cpp
@@ -1725,16 +1725,20 @@ TokenStream::getTokenInternal(TokenKind*
             goto identifier;
         }
         goto badchar;
       }
 
       case '|':
         if (matchChar('|'))
             tp->type = TOK_OR;
+#ifdef ENABLE_PIPELINE_OPERATOR
+        else if (matchChar('>'))
+            tp->type = TOK_PIPELINE;
+#endif
         else
             tp->type = matchChar('=') ? TOK_BITORASSIGN : TOK_BITOR;
         goto out;
 
       case '^':
         tp->type = matchChar('=') ? TOK_BITXORASSIGN : TOK_BITXOR;
         goto out;
 
--- a/js/src/gc/Allocator.cpp
+++ b/js/src/gc/Allocator.cpp
@@ -292,57 +292,52 @@ GCRuntime::refillFreeListFromAnyThread(J
 /* static */ TenuredCell*
 GCRuntime::refillFreeListFromActiveCooperatingThread(JSContext* cx, AllocKind thingKind, size_t thingSize)
 {
     // It should not be possible to allocate on the active thread while we are
     // inside a GC.
     Zone *zone = cx->zone();
     MOZ_ASSERT(!JS::CurrentThreadIsHeapBusy(), "allocating while under GC");
 
-    AutoMaybeStartBackgroundAllocation maybeStartBGAlloc;
-    return cx->arenas()->allocateFromArena(zone, thingKind, CheckThresholds, maybeStartBGAlloc);
+    return cx->arenas()->allocateFromArena(zone, thingKind, CheckThresholds);
 }
 
 /* static */ TenuredCell*
 GCRuntime::refillFreeListFromHelperThread(JSContext* cx, AllocKind thingKind)
 {
     // A GC may be happening on the active thread, but zones used by off thread
     // tasks are never collected.
     Zone* zone = cx->zone();
     MOZ_ASSERT(!zone->wasGCStarted());
 
-    AutoMaybeStartBackgroundAllocation maybeStartBGAlloc;
-    return cx->arenas()->allocateFromArena(zone, thingKind, CheckThresholds, maybeStartBGAlloc);
+    return cx->arenas()->allocateFromArena(zone, thingKind, CheckThresholds);
 }
 
 /* static */ TenuredCell*
 GCRuntime::refillFreeListInGC(Zone* zone, AllocKind thingKind)
 {
     /*
      * Called by compacting GC to refill a free list while we are in a GC.
      */
 
     zone->arenas.checkEmptyFreeList(thingKind);
     mozilla::DebugOnly<JSRuntime*> rt = zone->runtimeFromActiveCooperatingThread();
     MOZ_ASSERT(JS::CurrentThreadIsHeapCollecting());
     MOZ_ASSERT_IF(!JS::CurrentThreadIsHeapMinorCollecting(), !rt->gc.isBackgroundSweeping());
 
-    AutoMaybeStartBackgroundAllocation maybeStartBackgroundAllocation;
-    return zone->arenas.allocateFromArena(zone, thingKind, DontCheckThresholds,
-                                          maybeStartBackgroundAllocation);
+    return zone->arenas.allocateFromArena(zone, thingKind, DontCheckThresholds);
 }
 
 TenuredCell*
 ArenaLists::allocateFromArena(JS::Zone* zone, AllocKind thingKind,
-                              ShouldCheckThresholds checkThresholds,
-                              AutoMaybeStartBackgroundAllocation& maybeStartBGAlloc)
+                              ShouldCheckThresholds checkThresholds)
 {
     JSRuntime* rt = zone->runtimeFromAnyThread();
 
-    mozilla::Maybe<AutoLockGC> maybeLock;
+    mozilla::Maybe<AutoLockGCBgAlloc> maybeLock;
 
     // See if we can proceed without taking the GC lock.
     if (backgroundFinalizeState(thingKind) != BFS_DONE)
         maybeLock.emplace(rt);
 
     ArenaList& al = arenaLists(thingKind);
     Arena* arena = al.takeNextArena();
     if (arena) {
@@ -352,17 +347,17 @@ ArenaLists::allocateFromArena(JS::Zone* 
         return allocateFromArenaInner(zone, arena, thingKind);
     }
 
     // Parallel threads have their own ArenaLists, but chunks are shared;
     // if we haven't already, take the GC lock now to avoid racing.
     if (maybeLock.isNothing())
         maybeLock.emplace(rt);
 
-    Chunk* chunk = rt->gc.pickChunk(maybeLock.ref(), maybeStartBGAlloc);
+    Chunk* chunk = rt->gc.pickChunk(maybeLock.ref());
     if (!chunk)
         return nullptr;
 
     // Although our chunk should definitely have enough space for another arena,
     // there are other valid reasons why Chunk::allocateArena() may fail.
     arena = rt->gc.allocateArena(chunk, zone, thingKind, checkThresholds, maybeLock.ref());
     if (!arena)
         return nullptr;
@@ -504,47 +499,45 @@ Chunk::findDecommittedArenaOffset()
     }
     MOZ_CRASH("No decommitted arenas found.");
 }
 
 
 // ///////////  System -> Chunk Allocator  /////////////////////////////////////
 
 Chunk*
-GCRuntime::getOrAllocChunk(const AutoLockGC& lock,
-                           AutoMaybeStartBackgroundAllocation& maybeStartBackgroundAllocation)
+GCRuntime::getOrAllocChunk(AutoLockGCBgAlloc& lock)
 {
     Chunk* chunk = emptyChunks(lock).pop();
     if (!chunk) {
         chunk = Chunk::allocate(rt);
         if (!chunk)
             return nullptr;
         MOZ_ASSERT(chunk->info.numArenasFreeCommitted == 0);
     }
 
     if (wantBackgroundAllocation(lock))
-        maybeStartBackgroundAllocation.tryToStartBackgroundAllocation(rt->gc);
+        lock.tryToStartBackgroundAllocation();
 
     return chunk;
 }
 
 void
 GCRuntime::recycleChunk(Chunk* chunk, const AutoLockGC& lock)
 {
     emptyChunks(lock).push(chunk);
 }
 
 Chunk*
-GCRuntime::pickChunk(const AutoLockGC& lock,
-                     AutoMaybeStartBackgroundAllocation& maybeStartBackgroundAllocation)
+GCRuntime::pickChunk(AutoLockGCBgAlloc& lock)
 {
     if (availableChunks(lock).count())
         return availableChunks(lock).head();
 
-    Chunk* chunk = getOrAllocChunk(lock, maybeStartBackgroundAllocation);
+    Chunk* chunk = getOrAllocChunk(lock);
     if (!chunk)
         return nullptr;
 
     chunk->init(rt);
     MOZ_ASSERT(chunk->info.numArenasFreeCommitted == 0);
     MOZ_ASSERT(chunk->unused());
     MOZ_ASSERT(!fullChunks(lock).contains(chunk));
     MOZ_ASSERT(!availableChunks(lock).contains(chunk));
--- a/js/src/gc/GCRuntime.h
+++ b/js/src/gc/GCRuntime.h
@@ -21,26 +21,26 @@
 #include "gc/StoreBuffer.h"
 #include "gc/Tracer.h"
 #include "js/GCAnnotations.h"
 #include "js/UniquePtr.h"
 
 namespace js {
 
 class AutoLockGC;
+class AutoLockGCBgAlloc;
 class AutoLockHelperThreadState;
 class VerifyPreTracer;
 
 namespace gc {
 
 typedef Vector<ZoneGroup*, 4, SystemAllocPolicy> ZoneGroupVector;
 using BlackGrayEdgeVector = Vector<TenuredCell*, 0, SystemAllocPolicy>;
 
 class AutoCallGCCallbacks;
-class AutoMaybeStartBackgroundAllocation;
 class AutoRunParallelTask;
 class AutoTraceSession;
 class MarkingValidator;
 struct MovingTracer;
 class WeakCacheSweepIterator;
 
 enum IncrementalProgress
 {
@@ -934,18 +934,17 @@ class GCRuntime
     const ChunkPool& availableChunks(const AutoLockGC& lock) const { return availableChunks_.ref(); }
     const ChunkPool& emptyChunks(const AutoLockGC& lock) const { return emptyChunks_.ref(); }
     typedef ChainedIter<Chunk*, ChunkPool::Iter, ChunkPool::Iter> NonEmptyChunksIter;
     NonEmptyChunksIter allNonEmptyChunks(const AutoLockGC& lock) {
         return NonEmptyChunksIter(ChunkPool::Iter(availableChunks(lock)),
                                   ChunkPool::Iter(fullChunks(lock)));
     }
 
-    Chunk* getOrAllocChunk(const AutoLockGC& lock,
-                           AutoMaybeStartBackgroundAllocation& maybeStartBGAlloc);
+    Chunk* getOrAllocChunk(AutoLockGCBgAlloc& lock);
     void recycleChunk(Chunk* chunk, const AutoLockGC& lock);
 
 #ifdef JS_GC_ZEAL
     void startVerifyPreBarriers();
     void endVerifyPreBarriers();
     void finishVerifier();
     bool isVerifyPreBarriersEnabled() const { return !!verifyPreData; }
 #else
@@ -992,18 +991,17 @@ class GCRuntime
         Ok
     };
 
     // Delete an empty zone group after its contents have been merged.
     void deleteEmptyZoneGroup(ZoneGroup* group);
 
     // For ArenaLists::allocateFromArena()
     friend class ArenaLists;
-    Chunk* pickChunk(const AutoLockGC& lock,
-                     AutoMaybeStartBackgroundAllocation& maybeStartBGAlloc);
+    Chunk* pickChunk(AutoLockGCBgAlloc& lock);
     Arena* allocateArena(Chunk* chunk, Zone* zone, AllocKind kind,
                          ShouldCheckThresholds checkThresholds, const AutoLockGC& lock);
 
 
     void arenaAllocatedDuringGC(JS::Zone* zone, Arena* arena);
 
     // Allocator internals
     MOZ_MUST_USE bool gcIfNeededAtAllocation(JSContext* cx);
@@ -1020,17 +1018,16 @@ class GCRuntime
      * Must be called either during the GC or with the GC lock taken.
      */
     friend class BackgroundDecommitTask;
     ChunkPool expireEmptyChunkPool(const AutoLockGC& lock);
     void freeEmptyChunks(JSRuntime* rt, const AutoLockGC& lock);
     void prepareToFreeChunk(ChunkInfo& info);
 
     friend class BackgroundAllocTask;
-    friend class AutoMaybeStartBackgroundAllocation;
     bool wantBackgroundAllocation(const AutoLockGC& lock) const;
     void startBackgroundAllocTaskIfIdle();
 
     void requestMajorGC(JS::gcreason::Reason reason);
     SliceBudget defaultBudget(JS::gcreason::Reason reason, int64_t millis);
     IncrementalResult budgetIncrementalGC(bool nonincrementalByAPI, JS::gcreason::Reason reason,
                                           SliceBudget& budget, AutoLockForExclusiveAccess& lock);
     IncrementalResult resetIncrementalGC(AbortReason reason, AutoLockForExclusiveAccess& lock);
@@ -1437,16 +1434,17 @@ class GCRuntime
     ActiveThreadData<bool> alwaysPreserveCode;
 
 #ifdef DEBUG
     ActiveThreadData<bool> arenasEmptyAtShutdown;
 #endif
 
     /* Synchronize GC heap access among GC helper threads and active threads. */
     friend class js::AutoLockGC;
+    friend class js::AutoLockGCBgAlloc;
     js::Mutex lock;
 
     BackgroundAllocTask allocTask;
     BackgroundDecommitTask decommitTask;
 
     GCHelperState helperState;
 
     /*
@@ -1496,40 +1494,16 @@ class MOZ_RAII AutoEnterIteration {
     }
 
     ~AutoEnterIteration() {
         MOZ_ASSERT(gc->numActiveZoneIters);
         --gc->numActiveZoneIters;
     }
 };
 
-// After pulling a Chunk out of the empty chunks pool, we want to run the
-// background allocator to refill it. The code that takes Chunks does so under
-// the GC lock. We need to start the background allocation under the helper
-// threads lock. To avoid lock inversion we have to delay the start until after
-// we are outside the GC lock. This class handles that delay automatically.
-class MOZ_RAII AutoMaybeStartBackgroundAllocation
-{
-    GCRuntime* gc;
-
-  public:
-    AutoMaybeStartBackgroundAllocation()
-      : gc(nullptr)
-    {}
-
-    void tryToStartBackgroundAllocation(GCRuntime& gc) {
-        this->gc = &gc;
-    }
-
-    ~AutoMaybeStartBackgroundAllocation() {
-        if (gc)
-            gc->startBackgroundAllocTaskIfIdle();
-    }
-};
-
 #ifdef JS_GC_ZEAL
 
 inline bool
 GCRuntime::hasZealMode(ZealMode mode)
 {
     static_assert(size_t(ZealMode::Limit) < sizeof(zealModeBits) * 8,
                   "Zeal modes must fit in zealModeBits");
     return zealModeBits & (1 << uint32_t(mode));
--- a/js/src/gc/Heap.h
+++ b/js/src/gc/Heap.h
@@ -32,16 +32,17 @@
 
 #include "vm/Printer.h"
 
 struct JSRuntime;
 
 namespace js {
 
 class AutoLockGC;
+class AutoLockGCBgAlloc;
 class FreeOp;
 
 extern bool
 RuntimeFromActiveCooperatingThreadIsHeapMajorCollecting(JS::shadow::Zone* shadowZone);
 
 #ifdef DEBUG
 
 // Barriers can't be triggered during backend Ion compilation, which may run on
--- a/js/src/gc/Marking.cpp
+++ b/js/src/gc/Marking.cpp
@@ -33,16 +33,17 @@
 #include "vm/UnboxedObject.h"
 #include "wasm/WasmJS.h"
 
 #include "jscompartmentinlines.h"
 #include "jsgcinlines.h"
 #include "jsobjinlines.h"
 
 #include "gc/Nursery-inl.h"
+#include "vm/NativeObject-inl.h"
 #include "vm/String-inl.h"
 #include "vm/UnboxedObject-inl.h"
 
 using namespace js;
 using namespace js::gc;
 
 using JS::MapTypeToTraceKind;
 
@@ -2663,18 +2664,28 @@ TenuringTracer::traverse(T** tp)
 
 template <>
 void
 TenuringTracer::traverse(JSObject** objp)
 {
     // We only ever visit the internals of objects after moving them to tenured.
     MOZ_ASSERT(!nursery().isInside(objp));
 
-    if (IsInsideNursery(*objp) && !nursery().getForwardedPointer(objp))
-        *objp = moveToTenured(*objp);
+    JSObject* obj = *objp;
+    if (!IsInsideNursery(obj) || nursery().getForwardedPointer(objp))
+        return;
+
+    // Take a fast path for tenuring a plain object which is by far the most
+    // common case.
+    if (obj->is<PlainObject>()) {
+        *objp = movePlainObjectToTenured(&obj->as<PlainObject>());
+        return;
+    }
+
+    *objp = moveToTenuredSlow(obj);
 }
 
 template <typename S>
 struct TenuringTraversalFunctor : public IdentityDefaultAdaptor<S> {
     template <typename T> S operator()(T* t, TenuringTracer* trc) {
         trc->traverse(&t);
         return js::gc::RewrapTaggedPointer<S, T>::wrap(t);
     }
@@ -2826,68 +2837,16 @@ js::gc::StoreBuffer::CellPtrEdge::trace(
 
 void
 js::gc::StoreBuffer::ValueEdge::trace(TenuringTracer& mover) const
 {
     if (deref())
         mover.traverse(edge);
 }
 
-/* Insert the given relocation entry into the list of things to visit. */
-void
-js::TenuringTracer::insertIntoFixupList(RelocationOverlay* entry) {
-    *tail = entry;
-    tail = &entry->nextRef();
-    *tail = nullptr;
-}
-
-JSObject*
-js::TenuringTracer::moveToTenured(JSObject* src)
-{
-    MOZ_ASSERT(IsInsideNursery(src));
-    MOZ_ASSERT(!src->zone()->usedByHelperThread());
-
-    AllocKind dstKind = src->allocKindForTenure(nursery());
-    Zone* zone = src->zone();
-
-    TenuredCell* t = zone->arenas.allocateFromFreeList(dstKind, Arena::thingSize(dstKind));
-    if (!t) {
-        AutoEnterOOMUnsafeRegion oomUnsafe;
-        t = runtime()->gc.refillFreeListInGC(zone, dstKind);
-        if (!t)
-            oomUnsafe.crash(ChunkSize, "Failed to allocate object while tenuring.");
-    }
-    JSObject* dst = reinterpret_cast<JSObject*>(t);
-    tenuredSize += moveObjectToTenured(dst, src, dstKind);
-
-    RelocationOverlay* overlay = RelocationOverlay::fromCell(src);
-    overlay->forwardTo(dst);
-    insertIntoFixupList(overlay);
-