merge mozilla-inbound to mozilla-central a=merge
authorCarsten "Tomcat" Book <cbook@mozilla.com>
Fri, 28 Jul 2017 15:24:39 +0200
changeset 420320 16ffc1d05422a81099ce8b9b59de66dde4c8b2f0
parent 420264 09a412e3cc3b1a1fd9a1325e161d36b91018ef24 (current diff)
parent 420319 91c459dd13e5d05cd5b707ae717801a6b04d6031 (diff)
child 420321 e91b2c85aacd9aa32fbb3a71a7fae14fc21127b2
child 420351 3e94306b5b97dce94423a3d3be2b574b53f7ecf3
child 420424 6e3ba727a94a487b0df71986d7456101a3486dbf
push id7566
push usermtabara@mozilla.com
push dateWed, 02 Aug 2017 08:25:16 +0000
treeherdermozilla-beta@86913f512c3c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone56.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
merge mozilla-inbound to mozilla-central a=merge
browser/base/content/browser.js
dom/base/nsContentUtils.cpp
layout/generic/crashtests/crashtests.list
layout/style/crashtests/crashtests.list
modules/libpref/init/all.js
taskcluster/ci/test/tests.yml
testing/marionette/harness/marionette_harness/marionette_test/testcases.py
widget/windows/nsWindow.cpp
--- a/browser/extensions/pdfjs/README.mozilla
+++ b/browser/extensions/pdfjs/README.mozilla
@@ -1,5 +1,5 @@
 This is the PDF.js project output, https://github.com/mozilla/pdf.js
 
-Current extension version is: 1.8.564
+Current extension version is: 1.8.581
 
-Taken from upstream commit: e7cddcce
+Taken from upstream commit: 343b4dc2
--- a/browser/extensions/pdfjs/content/PdfJs.jsm
+++ b/browser/extensions/pdfjs/content/PdfJs.jsm
@@ -90,16 +90,17 @@ function initializeDefaultPreferences() 
   "disableFontFace": false,
   "disableTextLayer": false,
   "useOnlyCssZoom": false,
   "externalLinkTarget": 0,
   "enhanceTextSelection": false,
   "renderer": "canvas",
   "renderInteractiveForms": false,
   "enablePrintAutoRotate": false,
+  "disablePageMode": false,
   "disablePageLabels": false
 }
 
 
   var defaultBranch = Services.prefs.getDefaultBranch(PREF_PREFIX + ".");
   var defaultValue;
   for (var key in DEFAULT_PREFERENCES) {
     defaultValue = DEFAULT_PREFERENCES[key];
--- a/browser/extensions/pdfjs/content/PdfjsChromeUtils.jsm
+++ b/browser/extensions/pdfjs/content/PdfjsChromeUtils.jsm
@@ -48,16 +48,17 @@ var DEFAULT_PREFERENCES =
   "disableFontFace": false,
   "disableTextLayer": false,
   "useOnlyCssZoom": false,
   "externalLinkTarget": 0,
   "enhanceTextSelection": false,
   "renderer": "canvas",
   "renderInteractiveForms": false,
   "enablePrintAutoRotate": false,
+  "disablePageMode": false,
   "disablePageLabels": false
 }
 
 
 var PdfjsChromeUtils = {
   // For security purposes when running remote, we restrict preferences
   // content can access.
   _allowedPrefNames: Object.keys(DEFAULT_PREFERENCES),
--- a/browser/extensions/pdfjs/content/build/pdf.js
+++ b/browser/extensions/pdfjs/content/build/pdf.js
@@ -83,32 +83,32 @@ return /******/ (function(modules) { // 
 /******/
 /******/ 	// Object.prototype.hasOwnProperty.call
 /******/ 	__w_pdfjs_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
 /******/
 /******/ 	// __webpack_public_path__
 /******/ 	__w_pdfjs_require__.p = "";
 /******/
 /******/ 	// Load entry module and return exports
-/******/ 	return __w_pdfjs_require__(__w_pdfjs_require__.s = 13);
+/******/ 	return __w_pdfjs_require__(__w_pdfjs_require__.s = 14);
 /******/ })
 /************************************************************************/
 /******/ ([
 /* 0 */
 /***/ (function(module, exports, __w_pdfjs_require__) {
 
 "use strict";
 
 
 Object.defineProperty(exports, "__esModule", {
   value: true
 });
 exports.unreachable = exports.warn = exports.utf8StringToString = exports.stringToUTF8String = exports.stringToPDFString = exports.stringToBytes = exports.string32 = exports.shadow = exports.setVerbosityLevel = exports.ReadableStream = exports.removeNullCharacters = exports.readUint32 = exports.readUint16 = exports.readInt8 = exports.log2 = exports.loadJpegStream = exports.isEvalSupported = exports.isLittleEndian = exports.createValidAbsoluteUrl = exports.isSameOrigin = exports.isNodeJS = exports.isSpace = exports.isString = exports.isNum = exports.isInt = exports.isEmptyObj = exports.isBool = exports.isArrayBuffer = exports.isArray = exports.info = exports.globalScope = exports.getVerbosityLevel = exports.getLookupTableFactory = exports.deprecated = exports.createObjectURL = exports.createPromiseCapability = exports.createBlob = exports.bytesToString = exports.assert = exports.arraysToBytes = exports.arrayByteLength = exports.FormatError = exports.XRefParseException = exports.Util = exports.UnknownErrorException = exports.UnexpectedResponseException = exports.TextRenderingMode = exports.StreamType = exports.StatTimer = exports.PasswordResponses = exports.PasswordException = exports.PageViewport = exports.NotImplementedException = exports.NativeImageDecoding = exports.MissingPDFException = exports.MissingDataException = exports.MessageHandler = exports.InvalidPDFException = exports.CMapCompressionType = exports.ImageKind = exports.FontType = exports.AnnotationType = exports.AnnotationFlag = exports.AnnotationFieldFlag = exports.AnnotationBorderStyleType = exports.UNSUPPORTED_FEATURES = exports.VERBOSITY_LEVELS = exports.OPS = exports.IDENTITY_MATRIX = exports.FONT_IDENTITY_MATRIX = undefined;
 
-__w_pdfjs_require__(14);
+__w_pdfjs_require__(15);
 
 var _streamsLib = __w_pdfjs_require__(9);
 
 var globalScope = typeof window !== 'undefined' && window.Math === Math ? window : typeof global !== 'undefined' && global.Math === Math ? global : typeof self !== 'undefined' && self.Math === Math ? self : undefined;
 var FONT_IDENTITY_MATRIX = [0.001, 0, 0, 0.001, 0, 0];
 const NativeImageDecoding = {
   NONE: 'none',
   DECODE: 'decode',
@@ -995,16 +995,29 @@ var createObjectURL = function createObj
 function resolveCall(fn, args, thisArg = null) {
   if (!fn) {
     return Promise.resolve(undefined);
   }
   return new Promise((resolve, reject) => {
     resolve(fn.apply(thisArg, args));
   });
 }
+function wrapReason(reason) {
+  if (typeof reason !== 'object') {
+    return reason;
+  }
+  switch (reason.name) {
+    case 'MissingPDFException':
+      return new MissingPDFException(reason.message);
+    case 'UnexpectedResponseException':
+      return new UnexpectedResponseException(reason.message, reason.status);
+    default:
+      return new UnknownErrorException(reason.message, reason.details);
+  }
+}
 function resolveOrReject(capability, success, reason) {
   if (success) {
     capability.resolve();
   } else {
     capability.reject(reason);
   }
 }
 function finalize(promise) {
@@ -1166,53 +1179,65 @@ MessageHandler.prototype = {
   _createStreamSink(data) {
     let self = this;
     let action = this.actionHandler[data.action];
     let streamId = data.streamId;
     let desiredSize = data.desiredSize;
     let sourceName = this.sourceName;
     let targetName = data.sourceName;
     let capability = createPromiseCapability();
-    let sendStreamRequest = ({ stream, chunk, success, reason }) => {
-      this.comObj.postMessage({
+    let sendStreamRequest = ({ stream, chunk, transfers, success, reason }) => {
+      this.postMessage({
         sourceName,
         targetName,
         stream,
         streamId,
         chunk,
         success,
         reason
-      });
+      }, transfers);
     };
     let streamSink = {
-      enqueue(chunk, size = 1) {
+      enqueue(chunk, size = 1, transfers) {
+        if (this.isCancelled) {
+          return;
+        }
         let lastDesiredSize = this.desiredSize;
         this.desiredSize -= size;
         if (lastDesiredSize > 0 && this.desiredSize <= 0) {
           this.sinkCapability = createPromiseCapability();
           this.ready = this.sinkCapability.promise;
         }
         sendStreamRequest({
           stream: 'enqueue',
-          chunk
+          chunk,
+          transfers
         });
       },
       close() {
+        if (this.isCancelled) {
+          return;
+        }
         sendStreamRequest({ stream: 'close' });
         delete self.streamSinks[streamId];
       },
       error(reason) {
+        if (this.isCancelled) {
+          return;
+        }
+        this.isCancelled = true;
         sendStreamRequest({
           stream: 'error',
           reason
         });
       },
       sinkCapability: capability,
       onPull: null,
       onCancel: null,
+      isCancelled: false,
       desiredSize,
       ready: null
     };
     streamSink.sinkCapability.resolve();
     streamSink.ready = streamSink.sinkCapability.promise;
     this.streamSinks[streamId] = streamSink;
     resolveCall(action[0], [data.data, streamSink], action[1]).then(() => {
       sendStreamRequest({
@@ -1245,20 +1270,20 @@ MessageHandler.prototype = {
       Promise.all([this.streamControllers[data.streamId].startCall, this.streamControllers[data.streamId].pullCall, this.streamControllers[data.streamId].cancelCall].map(function (capability) {
         return capability && finalize(capability.promise);
       })).then(() => {
         delete this.streamControllers[data.streamId];
       });
     };
     switch (data.stream) {
       case 'start_complete':
-        resolveOrReject(this.streamControllers[data.streamId].startCall, data.success, data.reason);
+        resolveOrReject(this.streamControllers[data.streamId].startCall, data.success, wrapReason(data.reason));
         break;
       case 'pull_complete':
-        resolveOrReject(this.streamControllers[data.streamId].pullCall, data.success, data.reason);
+        resolveOrReject(this.streamControllers[data.streamId].pullCall, data.success, wrapReason(data.reason));
         break;
       case 'pull':
         if (!this.streamSinks[data.streamId]) {
           sendStreamResponse({
             stream: 'pull_complete',
             success: true
           });
           break;
@@ -1276,52 +1301,57 @@ MessageHandler.prototype = {
           sendStreamResponse({
             stream: 'pull_complete',
             success: false,
             reason
           });
         });
         break;
       case 'enqueue':
+        assert(this.streamControllers[data.streamId], 'enqueue should have stream controller');
         if (!this.streamControllers[data.streamId].isClosed) {
           this.streamControllers[data.streamId].controller.enqueue(data.chunk);
         }
         break;
       case 'close':
+        assert(this.streamControllers[data.streamId], 'close should have stream controller');
         if (this.streamControllers[data.streamId].isClosed) {
           break;
         }
         this.streamControllers[data.streamId].isClosed = true;
         this.streamControllers[data.streamId].controller.close();
         deleteStreamController();
         break;
       case 'error':
-        this.streamControllers[data.streamId].controller.error(data.reason);
+        assert(this.streamControllers[data.streamId], 'error should have stream controller');
+        this.streamControllers[data.streamId].controller.error(wrapReason(data.reason));
         deleteStreamController();
         break;
       case 'cancel_complete':
-        resolveOrReject(this.streamControllers[data.streamId].cancelCall, data.success, data.reason);
+        resolveOrReject(this.streamControllers[data.streamId].cancelCall, data.success, wrapReason(data.reason));
         deleteStreamController();
         break;
       case 'cancel':
         if (!this.streamSinks[data.streamId]) {
           break;
         }
-        resolveCall(this.streamSinks[data.streamId].onCancel, [data.reason]).then(() => {
+        resolveCall(this.streamSinks[data.streamId].onCancel, [wrapReason(data.reason)]).then(() => {
           sendStreamResponse({
             stream: 'cancel_complete',
             success: true
           });
         }, reason => {
           sendStreamResponse({
             stream: 'cancel_complete',
             success: false,
             reason
           });
         });
+        this.streamSinks[data.streamId].sinkCapability.reject(wrapReason(data.reason));
+        this.streamSinks[data.streamId].isCancelled = true;
         delete this.streamSinks[data.streamId];
         break;
       default:
         throw new Error('Unexpected stream case');
     }
   },
   postMessage(message, transfers) {
     if (transfers && this.postMessageTransfers) {
@@ -2322,36 +2352,42 @@ exports.AnnotationLayer = AnnotationLaye
 /***/ (function(module, exports, __w_pdfjs_require__) {
 
 "use strict";
 
 
 Object.defineProperty(exports, "__esModule", {
   value: true
 });
-exports.build = exports.version = exports._UnsupportedManager = exports.PDFPageProxy = exports.PDFDocumentProxy = exports.PDFWorker = exports.PDFDataRangeTransport = exports.LoopbackPort = exports.getDocument = undefined;
+exports.build = exports.version = exports._UnsupportedManager = exports.setPDFNetworkStreamClass = exports.PDFPageProxy = exports.PDFDocumentProxy = exports.PDFWorker = exports.PDFDataRangeTransport = exports.LoopbackPort = exports.getDocument = undefined;
 
 var _util = __w_pdfjs_require__(0);
 
 var _dom_utils = __w_pdfjs_require__(1);
 
 var _font_loader = __w_pdfjs_require__(11);
 
 var _canvas = __w_pdfjs_require__(10);
 
 var _metadata = __w_pdfjs_require__(6);
 
+var _transport_stream = __w_pdfjs_require__(13);
+
 var DEFAULT_RANGE_CHUNK_SIZE = 65536;
 var isWorkerDisabled = false;
 var workerSrc;
 var isPostMessageTransfersDisabled = false;
 var pdfjsFilePath = null;
 var fakeWorkerFilesLoader = null;
 var useRequireEnsure = false;
 ;
+var PDFNetworkStream;
+function setPDFNetworkStreamClass(cls) {
+  PDFNetworkStream = cls;
+}
 function getDocument(src, pdfDataRangeTransport, passwordCallback, progressCallback) {
   var task = new PDFDocumentLoadingTask();
   if (arguments.length > 1) {
     (0, _util.deprecated)('getDocument is called with pdfDataRangeTransport, ' + 'passwordCallback or progressCallback argument');
   }
   if (pdfDataRangeTransport) {
     if (!(pdfDataRangeTransport instanceof PDFDataRangeTransport)) {
       pdfDataRangeTransport = Object.create(pdfDataRangeTransport);
@@ -2433,18 +2469,28 @@ function getDocument(src, pdfDataRangeTr
   worker.promise.then(function () {
     if (task.destroyed) {
       throw new Error('Loading aborted');
     }
     return _fetchDocument(worker, params, rangeTransport, docId).then(function (workerId) {
       if (task.destroyed) {
         throw new Error('Loading aborted');
       }
+      let networkStream;
+      if (rangeTransport) {
+        networkStream = new _transport_stream.PDFDataTransportStream(params, rangeTransport);
+      } else if (!params.data) {
+        networkStream = new PDFNetworkStream({
+          source: params,
+          disableRange: (0, _dom_utils.getDefaultSetting)('disableRange')
+        });
+      }
       var messageHandler = new _util.MessageHandler(docId, workerId, worker.port);
-      var transport = new WorkerTransport(messageHandler, task, rangeTransport, CMapReaderFactory);
+      messageHandler.postMessageTransfers = worker.postMessageTransfers;
+      var transport = new WorkerTransport(messageHandler, task, networkStream, CMapReaderFactory);
       task._transport = transport;
       messageHandler.send('Ready', null);
     });
   }).catch(task._capability.reject);
   return task;
 }
 function _fetchDocument(worker, source, pdfDataRangeTransport, docId) {
   if (worker.destroyed) {
@@ -2455,17 +2501,16 @@ function _fetchDocument(worker, source, 
   source.chunkedViewerLoading = !!pdfDataRangeTransport;
   if (pdfDataRangeTransport) {
     source.length = pdfDataRangeTransport.length;
     source.initialData = pdfDataRangeTransport.initialData;
   }
   return worker.messageHandler.sendWithPromise('GetDocRequest', {
     docId,
     source,
-    disableRange: (0, _dom_utils.getDefaultSetting)('disableRange'),
     maxImageSize: (0, _dom_utils.getDefaultSetting)('maxImageSize'),
     disableFontFace: (0, _dom_utils.getDefaultSetting)('disableFontFace'),
     disableCreateObjectURL: (0, _dom_utils.getDefaultSetting)('disableCreateObjectURL'),
     postMessageTransfers: (0, _dom_utils.getDefaultSetting)('postMessageTransfers') && !isPostMessageTransfersDisabled,
     docBaseUrl: source.docBaseUrl,
     nativeImageDecoderSupport: source.nativeImageDecoderSupport,
     ignoreErrors: source.ignoreErrors
   }).then(function (workerId) {
@@ -2582,16 +2627,19 @@ var PDFDocumentProxy = function PDFDocum
       return this.transport.getDestinations();
     },
     getDestination: function PDFDocumentProxy_getDestination(id) {
       return this.transport.getDestination(id);
     },
     getPageLabels: function PDFDocumentProxy_getPageLabels() {
       return this.transport.getPageLabels();
     },
+    getPageMode() {
+      return this.transport.getPageMode();
+    },
     getAttachments: function PDFDocumentProxy_getAttachments() {
       return this.transport.getAttachments();
     },
     getJavaScript: function PDFDocumentProxy_getJavaScript() {
       return this.transport.getJavaScript();
     },
     getOutline: function PDFDocumentProxy_getOutline() {
       return this.transport.getOutline();
@@ -2963,16 +3011,17 @@ var PDFWorker = function PDFWorkerClosur
   }
   let pdfWorkerPorts = new WeakMap();
   function PDFWorker(name, port) {
     if (port && pdfWorkerPorts.has(port)) {
       throw new Error('Cannot use more than one PDFWorker per port');
     }
     this.name = name;
     this.destroyed = false;
+    this.postMessageTransfers = true;
     this._readyCapability = (0, _util.createPromiseCapability)();
     this._port = null;
     this._webWorker = null;
     this._messageHandler = null;
     if (port) {
       pdfWorkerPorts.set(port, this);
       this._initializeFromPort(port);
       return;
@@ -3024,16 +3073,17 @@ var PDFWorker = function PDFWorkerClosur
               return;
             }
             var supportTypedArray = data && data.supportTypedArray;
             if (supportTypedArray) {
               this._messageHandler = messageHandler;
               this._port = worker;
               this._webWorker = worker;
               if (!data.supportTransfers) {
+                this.postMessageTransfers = false;
                 isPostMessageTransfersDisabled = true;
               }
               this._readyCapability.resolve();
               messageHandler.send('configure', { verbosity: (0, _util.getVerbosityLevel)() });
             } else {
               this._setupFakeWorker();
               messageHandler.destroy();
               worker.terminate();
@@ -3114,29 +3164,31 @@ var PDFWorker = function PDFWorkerClosur
     if (pdfWorkerPorts.has(port)) {
       return pdfWorkerPorts.get(port);
     }
     return new PDFWorker(null, port);
   };
   return PDFWorker;
 }();
 var WorkerTransport = function WorkerTransportClosure() {
-  function WorkerTransport(messageHandler, loadingTask, pdfDataRangeTransport, CMapReaderFactory) {
+  function WorkerTransport(messageHandler, loadingTask, networkStream, CMapReaderFactory) {
     this.messageHandler = messageHandler;
     this.loadingTask = loadingTask;
-    this.pdfDataRangeTransport = pdfDataRangeTransport;
     this.commonObjs = new PDFObjects();
     this.fontLoader = new _font_loader.FontLoader(loadingTask.docId);
     this.CMapReaderFactory = new CMapReaderFactory({
       baseUrl: (0, _dom_utils.getDefaultSetting)('cMapUrl'),
       isCompressed: (0, _dom_utils.getDefaultSetting)('cMapPacked')
     });
     this.destroyed = false;
     this.destroyCapability = null;
     this._passwordCapability = null;
+    this._networkStream = networkStream;
+    this._fullReader = null;
+    this._lastProgress = null;
     this.pageCache = [];
     this.pagePromises = [];
     this.downloadInfoCapability = (0, _util.createPromiseCapability)();
     this.setupMessageHandler();
   }
   WorkerTransport.prototype = {
     destroy: function WorkerTransport_destroy() {
       if (this.destroyCapability) {
@@ -3154,49 +3206,103 @@ var WorkerTransport = function WorkerTra
         }
       });
       this.pageCache = [];
       this.pagePromises = [];
       var terminated = this.messageHandler.sendWithPromise('Terminate', null);
       waitOn.push(terminated);
       Promise.all(waitOn).then(() => {
         this.fontLoader.clear();
-        if (this.pdfDataRangeTransport) {
-          this.pdfDataRangeTransport.abort();
-          this.pdfDataRangeTransport = null;
+        if (this._networkStream) {
+          this._networkStream.cancelAllRequests();
         }
         if (this.messageHandler) {
           this.messageHandler.destroy();
           this.messageHandler = null;
         }
         this.destroyCapability.resolve();
       }, this.destroyCapability.reject);
       return this.destroyCapability.promise;
     },
     setupMessageHandler: function WorkerTransport_setupMessageHandler() {
       var messageHandler = this.messageHandler;
       var loadingTask = this.loadingTask;
-      var pdfDataRangeTransport = this.pdfDataRangeTransport;
-      if (pdfDataRangeTransport) {
-        pdfDataRangeTransport.addRangeListener(function (begin, chunk) {
-          messageHandler.send('OnDataRange', {
-            begin,
-            chunk
+      messageHandler.on('GetReader', function (data, sink) {
+        (0, _util.assert)(this._networkStream);
+        this._fullReader = this._networkStream.getFullReader();
+        this._fullReader.onProgress = evt => {
+          this._lastProgress = {
+            loaded: evt.loaded,
+            total: evt.total
+          };
+        };
+        sink.onPull = () => {
+          this._fullReader.read().then(function ({ value, done }) {
+            if (done) {
+              sink.close();
+              return;
+            }
+            (0, _util.assert)((0, _util.isArrayBuffer)(value));
+            sink.enqueue(new Uint8Array(value), 1, [value]);
+          }).catch(reason => {
+            sink.error(reason);
           });
-        });
-        pdfDataRangeTransport.addProgressListener(function (loaded) {
-          messageHandler.send('OnDataProgress', { loaded });
-        });
-        pdfDataRangeTransport.addProgressiveReadListener(function (chunk) {
-          messageHandler.send('OnDataRange', { chunk });
-        });
-        messageHandler.on('RequestDataRange', function transportDataRange(data) {
-          pdfDataRangeTransport.requestDataRange(data.begin, data.end);
-        }, this);
-      }
+        };
+        sink.onCancel = reason => {
+          this._fullReader.cancel(reason);
+        };
+      }, this);
+      messageHandler.on('ReaderHeadersReady', function (data) {
+        let headersCapability = (0, _util.createPromiseCapability)();
+        let fullReader = this._fullReader;
+        fullReader.headersReady.then(() => {
+          if (!fullReader.isStreamingSupported || !fullReader.isRangeSupported) {
+            if (this._lastProgress) {
+              let loadingTask = this.loadingTask;
+              if (loadingTask.onProgress) {
+                loadingTask.onProgress(this._lastProgress);
+              }
+            }
+            fullReader.onProgress = evt => {
+              let loadingTask = this.loadingTask;
+              if (loadingTask.onProgress) {
+                loadingTask.onProgress({
+                  loaded: evt.loaded,
+                  total: evt.total
+                });
+              }
+            };
+          }
+          headersCapability.resolve({
+            isStreamingSupported: fullReader.isStreamingSupported,
+            isRangeSupported: fullReader.isRangeSupported,
+            contentLength: fullReader.contentLength
+          });
+        }, headersCapability.reject);
+        return headersCapability.promise;
+      }, this);
+      messageHandler.on('GetRangeReader', function (data, sink) {
+        (0, _util.assert)(this._networkStream);
+        let _rangeReader = this._networkStream.getRangeReader(data.begin, data.end);
+        sink.onPull = () => {
+          _rangeReader.read().then(function ({ value, done }) {
+            if (done) {
+              sink.close();
+              return;
+            }
+            (0, _util.assert)((0, _util.isArrayBuffer)(value));
+            sink.enqueue(new Uint8Array(value), 1, [value]);
+          }).catch(reason => {
+            sink.error(reason);
+          });
+        };
+        sink.onCancel = reason => {
+          _rangeReader.cancel(reason);
+        };
+      }, this);
       messageHandler.on('GetDoc', function transportDoc(data) {
         var pdfInfo = data.pdfInfo;
         this.numPages = data.pdfInfo.numPages;
         var loadingTask = this.loadingTask;
         var pdfDocument = new PDFDocumentProxy(pdfInfo, this, loadingTask);
         this.pdfDocument = pdfDocument;
         loadingTask._capability.resolve(pdfDocument);
       }, this);
@@ -3225,21 +3331,17 @@ var WorkerTransport = function WorkerTra
         this.loadingTask._capability.reject(new _util.UnexpectedResponseException(exception.message, exception.status));
       }, this);
       messageHandler.on('UnknownError', function transportUnknownError(exception) {
         this.loadingTask._capability.reject(new _util.UnknownErrorException(exception.message, exception.details));
       }, this);
       messageHandler.on('DataLoaded', function transportPage(data) {
         this.downloadInfoCapability.resolve(data);
       }, this);
-      messageHandler.on('PDFManagerReady', function transportPage(data) {
-        if (this.pdfDataRangeTransport) {
-          this.pdfDataRangeTransport.transportReady();
-        }
-      }, this);
+      messageHandler.on('PDFManagerReady', function transportPage(data) {}, this);
       messageHandler.on('StartRenderPage', function transportRender(data) {
         if (this.destroyed) {
           return;
         }
         var page = this.pageCache[data.pageIndex];
         page.stats.timeEnd('Page Request');
         page._startRenderPage(data.transparency, data.intent);
       }, this);
@@ -3457,16 +3559,19 @@ var WorkerTransport = function WorkerTra
       return this.messageHandler.sendWithPromise('GetDestinations', null);
     },
     getDestination: function WorkerTransport_getDestination(id) {
       return this.messageHandler.sendWithPromise('GetDestination', { id });
     },
     getPageLabels: function WorkerTransport_getPageLabels() {
       return this.messageHandler.sendWithPromise('GetPageLabels', null);
     },
+    getPageMode() {
+      return this.messageHandler.sendWithPromise('GetPageMode', null);
+    },
     getAttachments: function WorkerTransport_getAttachments() {
       return this.messageHandler.sendWithPromise('GetAttachments', null);
     },
     getJavaScript: function WorkerTransport_getJavaScript() {
       return this.messageHandler.sendWithPromise('GetJavaScript', null);
     },
     getOutline: function WorkerTransport_getOutline() {
       return this.messageHandler.sendWithPromise('GetOutline', null);
@@ -3696,25 +3801,26 @@ var _UnsupportedManager = function Unsup
       for (var i = 0, ii = listeners.length; i < ii; i++) {
         listeners[i](featureId);
       }
     }
   };
 }();
 var version, build;
 {
-  exports.version = version = '1.8.564';
-  exports.build = build = 'e7cddcce';
+  exports.version = version = '1.8.581';
+  exports.build = build = '343b4dc2';
 }
 exports.getDocument = getDocument;
 exports.LoopbackPort = LoopbackPort;
 exports.PDFDataRangeTransport = PDFDataRangeTransport;
 exports.PDFWorker = PDFWorker;
 exports.PDFDocumentProxy = PDFDocumentProxy;
 exports.PDFPageProxy = PDFPageProxy;
+exports.setPDFNetworkStreamClass = setPDFNetworkStreamClass;
 exports._UnsupportedManager = _UnsupportedManager;
 exports.version = version;
 exports.build = build;
 
 /***/ }),
 /* 4 */
 /***/ (function(module, exports, __w_pdfjs_require__) {
 
@@ -4746,18 +4852,18 @@ var _text_layer = __w_pdfjs_require__(5)
 var _svg = __w_pdfjs_require__(4);
 
 var isWorker = typeof window === 'undefined';
 if (!_util.globalScope.PDFJS) {
   _util.globalScope.PDFJS = {};
 }
 var PDFJS = _util.globalScope.PDFJS;
 {
-  PDFJS.version = '1.8.564';
-  PDFJS.build = 'e7cddcce';
+  PDFJS.version = '1.8.581';
+  PDFJS.build = '343b4dc2';
 }
 PDFJS.pdfBug = false;
 if (PDFJS.verbosity !== undefined) {
   (0, _util.setVerbosityLevel)(PDFJS.verbosity);
 }
 delete PDFJS.verbosity;
 Object.defineProperty(PDFJS, 'verbosity', {
   get() {
@@ -10077,25 +10183,262 @@ exports.TilingPattern = TilingPattern;
 
 /***/ }),
 /* 13 */
 /***/ (function(module, exports, __w_pdfjs_require__) {
 
 "use strict";
 
 
-var pdfjsVersion = '1.8.564';
-var pdfjsBuild = 'e7cddcce';
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.PDFDataTransportStream = undefined;
+
+var _util = __w_pdfjs_require__(0);
+
+var PDFDataTransportStream = function PDFDataTransportStreamClosure() {
+  function PDFDataTransportStream(params, pdfDataRangeTransport) {
+    (0, _util.assert)(pdfDataRangeTransport);
+    this._queuedChunks = [];
+    var initialData = params.initialData;
+    if (initialData && initialData.length > 0) {
+      let buffer = new Uint8Array(initialData).buffer;
+      this._queuedChunks.push(buffer);
+    }
+    this._pdfDataRangeTransport = pdfDataRangeTransport;
+    this._isRangeSupported = !params.disableRange;
+    this._isStreamingSupported = !params.disableStream;
+    this._contentLength = params.length;
+    this._fullRequestReader = null;
+    this._rangeReaders = [];
+    this._pdfDataRangeTransport.addRangeListener((begin, chunk) => {
+      this._onReceiveData({
+        begin,
+        chunk
+      });
+    });
+    this._pdfDataRangeTransport.addProgressListener(loaded => {
+      this._onProgress({ loaded });
+    });
+    this._pdfDataRangeTransport.addProgressiveReadListener(chunk => {
+      this._onReceiveData({ chunk });
+    });
+    this._pdfDataRangeTransport.transportReady();
+  }
+  PDFDataTransportStream.prototype = {
+    _onReceiveData: function PDFDataTransportStream_onReceiveData(args) {
+      let buffer = new Uint8Array(args.chunk).buffer;
+      if (args.begin === undefined) {
+        if (this._fullRequestReader) {
+          this._fullRequestReader._enqueue(buffer);
+        } else {
+          this._queuedChunks.push(buffer);
+        }
+      } else {
+        var found = this._rangeReaders.some(function (rangeReader) {
+          if (rangeReader._begin !== args.begin) {
+            return false;
+          }
+          rangeReader._enqueue(buffer);
+          return true;
+        });
+        (0, _util.assert)(found);
+      }
+    },
+    _onProgress: function PDFDataTransportStream_onDataProgress(evt) {
+      if (this._rangeReaders.length > 0) {
+        var firstReader = this._rangeReaders[0];
+        if (firstReader.onProgress) {
+          firstReader.onProgress({ loaded: evt.loaded });
+        }
+      }
+    },
+    _removeRangeReader: function PDFDataTransportStream_removeRangeReader(reader) {
+      var i = this._rangeReaders.indexOf(reader);
+      if (i >= 0) {
+        this._rangeReaders.splice(i, 1);
+      }
+    },
+    getFullReader: function PDFDataTransportStream_getFullReader() {
+      (0, _util.assert)(!this._fullRequestReader);
+      var queuedChunks = this._queuedChunks;
+      this._queuedChunks = null;
+      return new PDFDataTransportStreamReader(this, queuedChunks);
+    },
+    getRangeReader: function PDFDataTransportStream_getRangeReader(begin, end) {
+      var reader = new PDFDataTransportStreamRangeReader(this, begin, end);
+      this._pdfDataRangeTransport.requestDataRange(begin, end);
+      this._rangeReaders.push(reader);
+      return reader;
+    },
+    cancelAllRequests: function PDFDataTransportStream_cancelAllRequests(reason) {
+      if (this._fullRequestReader) {
+        this._fullRequestReader.cancel(reason);
+      }
+      var readers = this._rangeReaders.slice(0);
+      readers.forEach(function (rangeReader) {
+        rangeReader.cancel(reason);
+      });
+      this._pdfDataRangeTransport.abort();
+    }
+  };
+  function PDFDataTransportStreamReader(stream, queuedChunks) {
+    this._stream = stream;
+    this._done = false;
+    this._queuedChunks = queuedChunks || [];
+    this._requests = [];
+    this._headersReady = Promise.resolve();
+    stream._fullRequestReader = this;
+    this.onProgress = null;
+  }
+  PDFDataTransportStreamReader.prototype = {
+    _enqueue: function PDFDataTransportStreamReader_enqueue(chunk) {
+      if (this._done) {
+        return;
+      }
+      if (this._requests.length > 0) {
+        var requestCapability = this._requests.shift();
+        requestCapability.resolve({
+          value: chunk,
+          done: false
+        });
+        return;
+      }
+      this._queuedChunks.push(chunk);
+    },
+    get headersReady() {
+      return this._headersReady;
+    },
+    get isRangeSupported() {
+      return this._stream._isRangeSupported;
+    },
+    get isStreamingSupported() {
+      return this._stream._isStreamingSupported;
+    },
+    get contentLength() {
+      return this._stream._contentLength;
+    },
+    read: function PDFDataTransportStreamReader_read() {
+      if (this._queuedChunks.length > 0) {
+        var chunk = this._queuedChunks.shift();
+        return Promise.resolve({
+          value: chunk,
+          done: false
+        });
+      }
+      if (this._done) {
+        return Promise.resolve({
+          value: undefined,
+          done: true
+        });
+      }
+      var requestCapability = (0, _util.createPromiseCapability)();
+      this._requests.push(requestCapability);
+      return requestCapability.promise;
+    },
+    cancel: function PDFDataTransportStreamReader_cancel(reason) {
+      this._done = true;
+      this._requests.forEach(function (requestCapability) {
+        requestCapability.resolve({
+          value: undefined,
+          done: true
+        });
+      });
+      this._requests = [];
+    }
+  };
+  function PDFDataTransportStreamRangeReader(stream, begin, end) {
+    this._stream = stream;
+    this._begin = begin;
+    this._end = end;
+    this._queuedChunk = null;
+    this._requests = [];
+    this._done = false;
+    this.onProgress = null;
+  }
+  PDFDataTransportStreamRangeReader.prototype = {
+    _enqueue: function PDFDataTransportStreamRangeReader_enqueue(chunk) {
+      if (this._done) {
+        return;
+      }
+      if (this._requests.length === 0) {
+        this._queuedChunk = chunk;
+      } else {
+        var requestsCapability = this._requests.shift();
+        requestsCapability.resolve({
+          value: chunk,
+          done: false
+        });
+        this._requests.forEach(function (requestCapability) {
+          requestCapability.resolve({
+            value: undefined,
+            done: true
+          });
+        });
+        this._requests = [];
+      }
+      this._done = true;
+      this._stream._removeRangeReader(this);
+    },
+    get isStreamingSupported() {
+      return false;
+    },
+    read: function PDFDataTransportStreamRangeReader_read() {
+      if (this._queuedChunk) {
+        let chunk = this._queuedChunk;
+        this._queuedChunk = null;
+        return Promise.resolve({
+          value: chunk,
+          done: false
+        });
+      }
+      if (this._done) {
+        return Promise.resolve({
+          value: undefined,
+          done: true
+        });
+      }
+      var requestCapability = (0, _util.createPromiseCapability)();
+      this._requests.push(requestCapability);
+      return requestCapability.promise;
+    },
+    cancel: function PDFDataTransportStreamRangeReader_cancel(reason) {
+      this._done = true;
+      this._requests.forEach(function (requestCapability) {
+        requestCapability.resolve({
+          value: undefined,
+          done: true
+        });
+      });
+      this._requests = [];
+      this._stream._removeRangeReader(this);
+    }
+  };
+  return PDFDataTransportStream;
+}();
+exports.PDFDataTransportStream = PDFDataTransportStream;
+
+/***/ }),
+/* 14 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var pdfjsVersion = '1.8.581';
+var pdfjsBuild = '343b4dc2';
 var pdfjsSharedUtil = __w_pdfjs_require__(0);
 var pdfjsDisplayGlobal = __w_pdfjs_require__(8);
 var pdfjsDisplayAPI = __w_pdfjs_require__(3);
 var pdfjsDisplayTextLayer = __w_pdfjs_require__(5);
 var pdfjsDisplayAnnotationLayer = __w_pdfjs_require__(2);
 var pdfjsDisplayDOMUtils = __w_pdfjs_require__(1);
 var pdfjsDisplaySVG = __w_pdfjs_require__(4);
+;
 exports.PDFJS = pdfjsDisplayGlobal.PDFJS;
 exports.build = pdfjsDisplayAPI.build;
 exports.version = pdfjsDisplayAPI.version;
 exports.getDocument = pdfjsDisplayAPI.getDocument;
 exports.LoopbackPort = pdfjsDisplayAPI.LoopbackPort;
 exports.PDFDataRangeTransport = pdfjsDisplayAPI.PDFDataRangeTransport;
 exports.PDFWorker = pdfjsDisplayAPI.PDFWorker;
 exports.renderTextLayer = pdfjsDisplayTextLayer.renderTextLayer;
@@ -10117,17 +10460,17 @@ exports.removeNullCharacters = pdfjsShar
 exports.shadow = pdfjsSharedUtil.shadow;
 exports.createBlob = pdfjsSharedUtil.createBlob;
 exports.RenderingCancelledException = pdfjsDisplayDOMUtils.RenderingCancelledException;
 exports.getFilenameFromUrl = pdfjsDisplayDOMUtils.getFilenameFromUrl;
 exports.addLinkAttributes = pdfjsDisplayDOMUtils.addLinkAttributes;
 exports.StatTimer = pdfjsSharedUtil.StatTimer;
 
 /***/ }),
-/* 14 */
+/* 15 */
 /***/ (function(module, exports, __w_pdfjs_require__) {
 
 "use strict";
 
 
 ;
 
 /***/ })
--- a/browser/extensions/pdfjs/content/build/pdf.worker.js
+++ b/browser/extensions/pdfjs/content/build/pdf.worker.js
@@ -995,16 +995,29 @@ var createObjectURL = function createObj
 function resolveCall(fn, args, thisArg = null) {
   if (!fn) {
     return Promise.resolve(undefined);
   }
   return new Promise((resolve, reject) => {
     resolve(fn.apply(thisArg, args));
   });
 }
+function wrapReason(reason) {
+  if (typeof reason !== 'object') {
+    return reason;
+  }
+  switch (reason.name) {
+    case 'MissingPDFException':
+      return new MissingPDFException(reason.message);
+    case 'UnexpectedResponseException':
+      return new UnexpectedResponseException(reason.message, reason.status);
+    default:
+      return new UnknownErrorException(reason.message, reason.details);
+  }
+}
 function resolveOrReject(capability, success, reason) {
   if (success) {
     capability.resolve();
   } else {
     capability.reject(reason);
   }
 }
 function finalize(promise) {
@@ -1166,53 +1179,65 @@ MessageHandler.prototype = {
   _createStreamSink(data) {
     let self = this;
     let action = this.actionHandler[data.action];
     let streamId = data.streamId;
     let desiredSize = data.desiredSize;
     let sourceName = this.sourceName;
     let targetName = data.sourceName;
     let capability = createPromiseCapability();
-    let sendStreamRequest = ({ stream, chunk, success, reason }) => {
-      this.comObj.postMessage({
+    let sendStreamRequest = ({ stream, chunk, transfers, success, reason }) => {
+      this.postMessage({
         sourceName,
         targetName,
         stream,
         streamId,
         chunk,
         success,
         reason
-      });
+      }, transfers);
     };
     let streamSink = {
-      enqueue(chunk, size = 1) {
+      enqueue(chunk, size = 1, transfers) {
+        if (this.isCancelled) {
+          return;
+        }
         let lastDesiredSize = this.desiredSize;
         this.desiredSize -= size;
         if (lastDesiredSize > 0 && this.desiredSize <= 0) {
           this.sinkCapability = createPromiseCapability();
           this.ready = this.sinkCapability.promise;
         }
         sendStreamRequest({
           stream: 'enqueue',
-          chunk
+          chunk,
+          transfers
         });
       },
       close() {
+        if (this.isCancelled) {
+          return;
+        }
         sendStreamRequest({ stream: 'close' });
         delete self.streamSinks[streamId];
       },
       error(reason) {
+        if (this.isCancelled) {
+          return;
+        }
+        this.isCancelled = true;
         sendStreamRequest({
           stream: 'error',
           reason
         });
       },
       sinkCapability: capability,
       onPull: null,
       onCancel: null,
+      isCancelled: false,
       desiredSize,
       ready: null
     };
     streamSink.sinkCapability.resolve();
     streamSink.ready = streamSink.sinkCapability.promise;
     this.streamSinks[streamId] = streamSink;
     resolveCall(action[0], [data.data, streamSink], action[1]).then(() => {
       sendStreamRequest({
@@ -1245,20 +1270,20 @@ MessageHandler.prototype = {
       Promise.all([this.streamControllers[data.streamId].startCall, this.streamControllers[data.streamId].pullCall, this.streamControllers[data.streamId].cancelCall].map(function (capability) {
         return capability && finalize(capability.promise);
       })).then(() => {
         delete this.streamControllers[data.streamId];
       });
     };
     switch (data.stream) {
       case 'start_complete':
-        resolveOrReject(this.streamControllers[data.streamId].startCall, data.success, data.reason);
+        resolveOrReject(this.streamControllers[data.streamId].startCall, data.success, wrapReason(data.reason));
         break;
       case 'pull_complete':
-        resolveOrReject(this.streamControllers[data.streamId].pullCall, data.success, data.reason);
+        resolveOrReject(this.streamControllers[data.streamId].pullCall, data.success, wrapReason(data.reason));
         break;
       case 'pull':
         if (!this.streamSinks[data.streamId]) {
           sendStreamResponse({
             stream: 'pull_complete',
             success: true
           });
           break;
@@ -1276,52 +1301,57 @@ MessageHandler.prototype = {
           sendStreamResponse({
             stream: 'pull_complete',
             success: false,
             reason
           });
         });
         break;
       case 'enqueue':
+        assert(this.streamControllers[data.streamId], 'enqueue should have stream controller');
         if (!this.streamControllers[data.streamId].isClosed) {
           this.streamControllers[data.streamId].controller.enqueue(data.chunk);
         }
         break;
       case 'close':
+        assert(this.streamControllers[data.streamId], 'close should have stream controller');
         if (this.streamControllers[data.streamId].isClosed) {
           break;
         }
         this.streamControllers[data.streamId].isClosed = true;
         this.streamControllers[data.streamId].controller.close();
         deleteStreamController();
         break;
       case 'error':
-        this.streamControllers[data.streamId].controller.error(data.reason);
+        assert(this.streamControllers[data.streamId], 'error should have stream controller');
+        this.streamControllers[data.streamId].controller.error(wrapReason(data.reason));
         deleteStreamController();
         break;
       case 'cancel_complete':
-        resolveOrReject(this.streamControllers[data.streamId].cancelCall, data.success, data.reason);
+        resolveOrReject(this.streamControllers[data.streamId].cancelCall, data.success, wrapReason(data.reason));
         deleteStreamController();
         break;
       case 'cancel':
         if (!this.streamSinks[data.streamId]) {
           break;
         }
-        resolveCall(this.streamSinks[data.streamId].onCancel, [data.reason]).then(() => {
+        resolveCall(this.streamSinks[data.streamId].onCancel, [wrapReason(data.reason)]).then(() => {
           sendStreamResponse({
             stream: 'cancel_complete',
             success: true
           });
         }, reason => {
           sendStreamResponse({
             stream: 'cancel_complete',
             success: false,
             reason
           });
         });
+        this.streamSinks[data.streamId].sinkCapability.reject(wrapReason(data.reason));
+        this.streamSinks[data.streamId].isCancelled = true;
         delete this.streamSinks[data.streamId];
         break;
       default:
         throw new Error('Unexpected stream case');
     }
   },
   postMessage(message, transfers) {
     if (transfers && this.postMessageTransfers) {
@@ -3758,17 +3788,17 @@ var IndexedCS = function IndexedCSClosur
       throw new _util.FormatError(`Unrecognized lookup table: ${lookup}`);
     }
   }
   IndexedCS.prototype = {
     getRgb: ColorSpace.prototype.getRgb,
     getRgbItem: function IndexedCS_getRgbItem(src, srcOffset, dest, destOffset) {
       var numComps = this.base.numComps;
       var start = src[srcOffset] * numComps;
-      this.base.getRgbItem(this.lookup, start, dest, destOffset);
+      this.base.getRgbBuffer(this.lookup, start, 1, dest, destOffset, 8, 0);
     },
     getRgbBuffer: function IndexedCS_getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) {
       var base = this.base;
       var numComps = base.numComps;
       var outputDelta = base.getOutputLength(numComps, alpha01);
       var lookup = this.lookup;
       for (var i = 0; i < count; ++i) {
         var lookupPos = src[srcOffset++] * numComps;
@@ -21812,16 +21842,32 @@ var Catalog = function CatalogClosure() 
             }
         }
         pageLabels[i] = prefix + currentLabel;
         currentLabel = '';
         currentIndex++;
       }
       return pageLabels;
     },
+    get pageMode() {
+      let obj = this.catDict.get('PageMode');
+      let pageMode = 'UseNone';
+      if ((0, _primitives.isName)(obj)) {
+        switch (obj.name) {
+          case 'UseNone':
+          case 'UseOutlines':
+          case 'UseThumbs':
+          case 'FullScreen':
+          case 'UseOC':
+          case 'UseAttachments':
+            pageMode = obj.name;
+        }
+      }
+      return (0, _util.shadow)(this, 'pageMode', pageMode);
+    },
     get attachments() {
       var xref = this.xref;
       var attachments = null,
           nameTreeRef;
       var obj = this.catDict.get('Names');
       if (obj) {
         nameTreeRef = obj.getRaw('EmbeddedFiles');
       }
@@ -23025,16 +23071,17 @@ var getStdFontMap = (0, _util.getLookupT
   t['CourierNewPS-ItalicMT'] = 'Courier-Oblique';
   t['CourierNewPSMT'] = 'Courier';
   t['Helvetica'] = 'Helvetica';
   t['Helvetica-Bold'] = 'Helvetica-Bold';
   t['Helvetica-BoldItalic'] = 'Helvetica-BoldOblique';
   t['Helvetica-BoldOblique'] = 'Helvetica-BoldOblique';
   t['Helvetica-Italic'] = 'Helvetica-Oblique';
   t['Helvetica-Oblique'] = 'Helvetica-Oblique';
+  t['SegoeUISymbol'] = 'Helvetica';
   t['Symbol-Bold'] = 'Symbol';
   t['Symbol-BoldItalic'] = 'Symbol';
   t['Symbol-Italic'] = 'Symbol';
   t['TimesNewRoman'] = 'Times-Roman';
   t['TimesNewRoman-Bold'] = 'Times-Bold';
   t['TimesNewRoman-BoldItalic'] = 'Times-BoldItalic';
   t['TimesNewRoman-Italic'] = 'Times-Italic';
   t['TimesNewRomanPS'] = 'Times-Roman';
@@ -23633,17 +23680,17 @@ exports.getSupplementalGlyphMapForArialB
 /***/ (function(module, exports, __w_pdfjs_require__) {
 
 "use strict";
 
 
 Object.defineProperty(exports, "__esModule", {
   value: true
 });
-exports.WorkerMessageHandler = exports.WorkerTask = exports.setPDFNetworkStreamClass = undefined;
+exports.WorkerMessageHandler = exports.WorkerTask = undefined;
 
 var _util = __w_pdfjs_require__(0);
 
 var _pdf_manager = __w_pdfjs_require__(32);
 
 var _primitives = __w_pdfjs_require__(1);
 
 var WorkerTask = function WorkerTaskClosure() {
@@ -23667,225 +23714,120 @@ var WorkerTask = function WorkerTaskClos
         throw new Error('Worker task was terminated');
       }
     }
   };
   return WorkerTask;
 }();
 ;
 var PDFWorkerStream = function PDFWorkerStreamClosure() {
-  function PDFWorkerStream(params, msgHandler) {
-    this._queuedChunks = [];
-    var initialData = params.initialData;
-    if (initialData && initialData.length > 0) {
-      this._queuedChunks.push(initialData);
-    }
+  function PDFWorkerStream(msgHandler) {
     this._msgHandler = msgHandler;
-    this._isRangeSupported = !params.disableRange;
-    this._isStreamingSupported = !params.disableStream;
-    this._contentLength = params.length;
+    this._contentLength = null;
     this._fullRequestReader = null;
-    this._rangeReaders = [];
-    msgHandler.on('OnDataRange', this._onReceiveData.bind(this));
-    msgHandler.on('OnDataProgress', this._onProgress.bind(this));
+    this._rangeRequestReaders = [];
   }
   PDFWorkerStream.prototype = {
-    _onReceiveData: function PDFWorkerStream_onReceiveData(args) {
-      if (args.begin === undefined) {
-        if (this._fullRequestReader) {
-          this._fullRequestReader._enqueue(args.chunk);
-        } else {
-          this._queuedChunks.push(args.chunk);
-        }
-      } else {
-        var found = this._rangeReaders.some(function (rangeReader) {
-          if (rangeReader._begin !== args.begin) {
-            return false;
-          }
-          rangeReader._enqueue(args.chunk);
-          return true;
-        });
-        (0, _util.assert)(found);
-      }
-    },
-    _onProgress: function PDFWorkerStream_onProgress(evt) {
-      if (this._rangeReaders.length > 0) {
-        var firstReader = this._rangeReaders[0];
-        if (firstReader.onProgress) {
-          firstReader.onProgress({ loaded: evt.loaded });
-        }
-      }
-    },
-    _removeRangeReader: function PDFWorkerStream_removeRangeReader(reader) {
-      var i = this._rangeReaders.indexOf(reader);
-      if (i >= 0) {
-        this._rangeReaders.splice(i, 1);
-      }
-    },
-    getFullReader: function PDFWorkerStream_getFullReader() {
+    getFullReader() {
       (0, _util.assert)(!this._fullRequestReader);
-      var queuedChunks = this._queuedChunks;
-      this._queuedChunks = null;
-      return new PDFWorkerStreamReader(this, queuedChunks);
-    },
-    getRangeReader: function PDFWorkerStream_getRangeReader(begin, end) {
-      var reader = new PDFWorkerStreamRangeReader(this, begin, end);
-      this._msgHandler.send('RequestDataRange', {
-        begin,
-        end
-      });
-      this._rangeReaders.push(reader);
+      this._fullRequestReader = new PDFWorkerStreamReader(this._msgHandler);
+      return this._fullRequestReader;
+    },
+    getRangeReader(begin, end) {
+      let reader = new PDFWorkerStreamRangeReader(begin, end, this._msgHandler);
+      this._rangeRequestReaders.push(reader);
       return reader;
     },
-    cancelAllRequests: function PDFWorkerStream_cancelAllRequests(reason) {
+    cancelAllRequests(reason) {
       if (this._fullRequestReader) {
         this._fullRequestReader.cancel(reason);
       }
-      var readers = this._rangeReaders.slice(0);
-      readers.forEach(function (rangeReader) {
-        rangeReader.cancel(reason);
-      });
-    }
-  };
-  function PDFWorkerStreamReader(stream, queuedChunks) {
-    this._stream = stream;
-    this._done = false;
-    this._queuedChunks = queuedChunks || [];
-    this._requests = [];
-    this._headersReady = Promise.resolve();
-    stream._fullRequestReader = this;
-    this.onProgress = null;
+      let readers = this._rangeRequestReaders.slice(0);
+      readers.forEach(function (reader) {
+        reader.cancel(reason);
+      });
+    }
+  };
+  function PDFWorkerStreamReader(msgHandler) {
+    this._msgHandler = msgHandler;
+    this._contentLength = null;
+    this._isRangeSupported = false;
+    this._isStreamingSupported = false;
+    let readableStream = this._msgHandler.sendWithStream('GetReader');
+    this._reader = readableStream.getReader();
+    this._headersReady = this._msgHandler.sendWithPromise('ReaderHeadersReady').then(data => {
+      this._isStreamingSupported = data.isStreamingSupported;
+      this._isRangeSupported = data.isRangeSupported;
+      this._contentLength = data.contentLength;
+    });
   }
   PDFWorkerStreamReader.prototype = {
-    _enqueue: function PDFWorkerStreamReader_enqueue(chunk) {
-      if (this._done) {
-        return;
-      }
-      if (this._requests.length > 0) {
-        var requestCapability = this._requests.shift();
-        requestCapability.resolve({
-          value: chunk,
-          done: false
-        });
-        return;
-      }
-      this._queuedChunks.push(chunk);
-    },
     get headersReady() {
       return this._headersReady;
     },
+    get contentLength() {
+      return this._contentLength;
+    },
+    get isStreamingSupported() {
+      return this._isStreamingSupported;
+    },
     get isRangeSupported() {
-      return this._stream._isRangeSupported;
-    },
-    get isStreamingSupported() {
-      return this._stream._isStreamingSupported;
-    },
-    get contentLength() {
-      return this._stream._contentLength;
-    },
-    read: function PDFWorkerStreamReader_read() {
-      if (this._queuedChunks.length > 0) {
-        var chunk = this._queuedChunks.shift();
-        return Promise.resolve({
-          value: chunk,
+      return this._isRangeSupported;
+    },
+    read() {
+      return this._reader.read().then(function ({ value, done }) {
+        if (done) {
+          return {
+            value: undefined,
+            done: true
+          };
+        }
+        return {
+          value: value.buffer,
           done: false
-        });
-      }
-      if (this._done) {
-        return Promise.resolve({
-          value: undefined,
-          done: true
-        });
-      }
-      var requestCapability = (0, _util.createPromiseCapability)();
-      this._requests.push(requestCapability);
-      return requestCapability.promise;
-    },
-    cancel: function PDFWorkerStreamReader_cancel(reason) {
-      this._done = true;
-      this._requests.forEach(function (requestCapability) {
-        requestCapability.resolve({
-          value: undefined,
-          done: true
-        });
-      });
-      this._requests = [];
-    }
-  };
-  function PDFWorkerStreamRangeReader(stream, begin, end) {
-    this._stream = stream;
-    this._begin = begin;
-    this._end = end;
-    this._queuedChunk = null;
-    this._requests = [];
-    this._done = false;
+        };
+      });
+    },
+    cancel(reason) {
+      this._reader.cancel(reason);
+    }
+  };
+  function PDFWorkerStreamRangeReader(begin, end, msgHandler) {
+    this._msgHandler = msgHandler;
     this.onProgress = null;
+    let readableStream = this._msgHandler.sendWithStream('GetRangeReader', {
+      begin,
+      end
+    });
+    this._reader = readableStream.getReader();
   }
   PDFWorkerStreamRangeReader.prototype = {
-    _enqueue: function PDFWorkerStreamRangeReader_enqueue(chunk) {
-      if (this._done) {
-        return;
-      }
-      if (this._requests.length === 0) {
-        this._queuedChunk = chunk;
-      } else {
-        var requestsCapability = this._requests.shift();
-        requestsCapability.resolve({
-          value: chunk,
-          done: false
-        });
-        this._requests.forEach(function (requestCapability) {
-          requestCapability.resolve({
+    get isStreamingSupported() {
+      return false;
+    },
+    read() {
+      return this._reader.read().then(function ({ value, done }) {
+        if (done) {
+          return {
             value: undefined,
             done: true
-          });
-        });
-        this._requests = [];
-      }
-      this._done = true;
-      this._stream._removeRangeReader(this);
-    },
-    get isStreamingSupported() {
-      return false;
-    },
-    read: function PDFWorkerStreamRangeReader_read() {
-      if (this._queuedChunk) {
-        return Promise.resolve({
-          value: this._queuedChunk,
+          };
+        }
+        return {
+          value: value.buffer,
           done: false
-        });
-      }
-      if (this._done) {
-        return Promise.resolve({
-          value: undefined,
-          done: true
-        });
-      }
-      var requestCapability = (0, _util.createPromiseCapability)();
-      this._requests.push(requestCapability);
-      return requestCapability.promise;
-    },
-    cancel: function PDFWorkerStreamRangeReader_cancel(reason) {
-      this._done = true;
-      this._requests.forEach(function (requestCapability) {
-        requestCapability.resolve({
-          value: undefined,
-          done: true
-        });
-      });
-      this._requests = [];
-      this._stream._removeRangeReader(this);
+        };
+      });
+    },
+    cancel(reason) {
+      this._reader.cancel(reason);
     }
   };
   return PDFWorkerStream;
 }();
-var PDFNetworkStream;
-function setPDFNetworkStreamClass(cls) {
-  PDFNetworkStream = cls;
-}
 var WorkerMessageHandler = {
   setup(handler, port) {
     var testMessageProcessed = false;
     handler.on('test', function wphSetupTest(data) {
       if (testMessageProcessed) {
         return;
       }
       testMessageProcessed = true;
@@ -23974,60 +23916,49 @@ var WorkerMessageHandler = {
         try {
           pdfManager = new _pdf_manager.LocalPdfManager(docId, source.data, source.password, evaluatorOptions, docBaseUrl);
           pdfManagerCapability.resolve(pdfManager);
         } catch (ex) {
           pdfManagerCapability.reject(ex);
         }
         return pdfManagerCapability.promise;
       }
-      var pdfStream;
+      var pdfStream,
+          cachedChunks = [];
       try {
-        if (source.chunkedViewerLoading) {
-          pdfStream = new PDFWorkerStream(source, handler);
-        } else {
-          if (!PDFNetworkStream) {
-            throw new Error('./network module is not loaded');
-          }
-          pdfStream = new PDFNetworkStream(data);
-        }
+        pdfStream = new PDFWorkerStream(handler);
       } catch (ex) {
         pdfManagerCapability.reject(ex);
         return pdfManagerCapability.promise;
       }
       var fullRequest = pdfStream.getFullReader();
       fullRequest.headersReady.then(function () {
-        if (!fullRequest.isStreamingSupported || !fullRequest.isRangeSupported) {
-          fullRequest.onProgress = function (evt) {
-            handler.send('DocProgress', {
-              loaded: evt.loaded,
-              total: evt.total
-            });
-          };
-        }
         if (!fullRequest.isRangeSupported) {
           return;
         }
         var disableAutoFetch = source.disableAutoFetch || fullRequest.isStreamingSupported;
         pdfManager = new _pdf_manager.NetworkPdfManager(docId, pdfStream, {
           msgHandler: handler,
           url: source.url,
           password: source.password,
           length: fullRequest.contentLength,
           disableAutoFetch,
           rangeChunkSize: source.rangeChunkSize
         }, evaluatorOptions, docBaseUrl);
+        for (let i = 0; i < cachedChunks.length; i++) {
+          pdfManager.sendProgressiveData(cachedChunks[i]);
+        }
+        cachedChunks = [];
         pdfManagerCapability.resolve(pdfManager);
         cancelXHRs = null;
       }).catch(function (reason) {
         pdfManagerCapability.reject(reason);
         cancelXHRs = null;
       });
-      var cachedChunks = [],
-          loaded = 0;
+      var loaded = 0;
       var flushChunks = function () {
         var pdfFile = (0, _util.arraysToBytes)(cachedChunks);
         if (source.length && pdfFile.length !== source.length) {
           (0, _util.warn)('reported HTTP length is different from actual');
         }
         try {
           pdfManager = new _pdf_manager.LocalPdfManager(docId, pdfFile, source.password, evaluatorOptions, docBaseUrl);
           pdfManagerCapability.resolve(pdfManager);
@@ -24164,16 +24095,19 @@ var WorkerMessageHandler = {
       return pdfManager.ensureCatalog('destinations');
     });
     handler.on('GetDestination', function wphSetupGetDestination(data) {
       return pdfManager.ensureCatalog('getDestination', [data.id]);
     });
     handler.on('GetPageLabels', function wphSetupGetPageLabels(data) {
       return pdfManager.ensureCatalog('pageLabels');
     });
+    handler.on('GetPageMode', function wphSetupGetPageMode(data) {
+      return pdfManager.ensureCatalog('pageMode');
+    });
     handler.on('GetAttachments', function wphSetupGetAttachments(data) {
       return pdfManager.ensureCatalog('attachments');
     });
     handler.on('GetJavaScript', function wphSetupGetJavaScript(data) {
       return pdfManager.ensureCatalog('javaScript');
     });
     handler.on('GetOutline', function wphSetupGetOutline(data) {
       return pdfManager.ensureCatalog('documentOutline');
@@ -24306,17 +24240,16 @@ var WorkerMessageHandler = {
   }
 };
 function isMessagePort(maybePort) {
   return typeof maybePort.postMessage === 'function' && 'onmessage' in maybePort;
 }
 if (typeof window === 'undefined' && !(0, _util.isNodeJS)() && typeof self !== 'undefined' && isMessagePort(self)) {
   WorkerMessageHandler.initializeFromPort(self);
 }
-exports.setPDFNetworkStreamClass = setPDFNetworkStreamClass;
 exports.WorkerTask = WorkerTask;
 exports.WorkerMessageHandler = WorkerMessageHandler;
 
 /***/ }),
 /* 18 */
 /***/ (function(module, exports, __w_pdfjs_require__) {
 
 "use strict";
@@ -39900,20 +39833,19 @@ exports.Type1Parser = Type1Parser;
 
 /***/ }),
 /* 35 */
 /***/ (function(module, exports, __w_pdfjs_require__) {
 
 "use strict";
 
 
-var pdfjsVersion = '1.8.564';
-var pdfjsBuild = 'e7cddcce';
+var pdfjsVersion = '1.8.581';
+var pdfjsBuild = '343b4dc2';
 var pdfjsCoreWorker = __w_pdfjs_require__(17);
-;
 exports.WorkerMessageHandler = pdfjsCoreWorker.WorkerMessageHandler;
 
 /***/ }),
 /* 36 */
 /***/ (function(module, exports, __w_pdfjs_require__) {
 
 "use strict";
 
--- a/browser/extensions/pdfjs/content/web/viewer.js
+++ b/browser/extensions/pdfjs/content/web/viewer.js
@@ -866,16 +866,17 @@ let PDFViewerApplication = {
   l10n: null,
   isInitialViewSet: false,
   downloadComplete: false,
   viewerPrefs: {
     sidebarViewOnLoad: _pdf_sidebar.SidebarView.NONE,
     pdfBugEnabled: false,
     showPreviousViewOnLoad: true,
     defaultZoomValue: '',
+    disablePageMode: false,
     disablePageLabels: false,
     renderer: 'canvas',
     enhanceTextSelection: false,
     renderInteractiveForms: false,
     enablePrintAutoRotate: false
   },
   isViewerEmbedded: window.parent !== window,
   url: '',
@@ -945,16 +946,18 @@ let PDFViewerApplication = {
       if (_pdfjsLib.PDFJS.isExternalLinkTargetSet()) {
         return;
       }
       _pdfjsLib.PDFJS.externalLinkTarget = value;
     }), preferences.get('renderer').then(function resolved(value) {
       viewerPrefs['renderer'] = value;
     }), preferences.get('renderInteractiveForms').then(function resolved(value) {
       viewerPrefs['renderInteractiveForms'] = value;
+    }), preferences.get('disablePageMode').then(function resolved(value) {
+      viewerPrefs['disablePageMode'] = value;
     }), preferences.get('disablePageLabels').then(function resolved(value) {
       viewerPrefs['disablePageLabels'] = value;
     }), preferences.get('enablePrintAutoRotate').then(function resolved(value) {
       viewerPrefs['enablePrintAutoRotate'] = value;
     })]).catch(function (reason) {});
   },
   _initializeL10n() {
     this.l10n = this.externalServices.createL10n();
@@ -1349,16 +1352,17 @@ let PDFViewerApplication = {
     this.pdfDocument = pdfDocument;
     pdfDocument.getDownloadInfo().then(() => {
       this.downloadComplete = true;
       this.loadingBar.hide();
       firstPagePromise.then(() => {
         this.eventBus.dispatch('documentload', { source: this });
       });
     });
+    let pageModePromise = pdfDocument.getPageMode().catch(function () {});
     this.toolbar.setPagesCount(pdfDocument.numPages, false);
     this.secondaryToolbar.setPagesCount(pdfDocument.numPages);
     let id = this.documentFingerprint = pdfDocument.fingerprint;
     let store = this.store = new _view_history.ViewHistory(id);
     let baseDocumentUrl;
     baseDocumentUrl = this.baseUrl;
     this.pdfLinkService.setDocument(pdfDocument, baseDocumentUrl);
     this.pdfDocumentProperties.setDocument(pdfDocument, this.url);
@@ -1382,45 +1386,44 @@ let PDFViewerApplication = {
           this.initialBookmark = this.pdfHistory.initialBookmark;
         }
       }
       let initialParams = {
         destination: this.initialDestination,
         bookmark: this.initialBookmark,
         hash: null
       };
-      let storedHash = this.viewerPrefs['defaultZoomValue'] ? 'zoom=' + this.viewerPrefs['defaultZoomValue'] : null;
-      let sidebarView = this.viewerPrefs['sidebarViewOnLoad'];
-      new Promise((resolve, reject) => {
-        if (!this.viewerPrefs['showPreviousViewOnLoad']) {
-          resolve();
-          return;
+      let storePromise = store.getMultiple({
+        exists: false,
+        page: '1',
+        zoom: _ui_utils.DEFAULT_SCALE_VALUE,
+        scrollLeft: '0',
+        scrollTop: '0',
+        sidebarView: _pdf_sidebar.SidebarView.NONE
+      }).catch(() => {});
+      Promise.all([storePromise, pageModePromise]).then(([values = {}, pageMode]) => {
+        let hash = this.viewerPrefs['defaultZoomValue'] ? 'zoom=' + this.viewerPrefs['defaultZoomValue'] : null;
+        let sidebarView = this.viewerPrefs['sidebarViewOnLoad'];
+        if (values.exists && this.viewerPrefs['showPreviousViewOnLoad']) {
+          hash = 'page=' + values.page + '&zoom=' + (this.viewerPrefs['defaultZoomValue'] || values.zoom) + ',' + values.scrollLeft + ',' + values.scrollTop;
+          sidebarView = sidebarView || values.sidebarView | 0;
         }
-        store.getMultiple({
-          exists: false,
-          page: '1',
-          zoom: _ui_utils.DEFAULT_SCALE_VALUE,
-          scrollLeft: '0',
-          scrollTop: '0',
-          sidebarView: _pdf_sidebar.SidebarView.NONE
-        }).then(values => {
-          if (!values.exists) {
-            resolve();
-            return;
-          }
-          storedHash = 'page=' + values.page + '&zoom=' + (this.viewerPrefs['defaultZoomValue'] || values.zoom) + ',' + values.scrollLeft + ',' + values.scrollTop;
-          sidebarView = this.viewerPrefs['sidebarViewOnLoad'] || values.sidebarView | 0;
-          resolve();
-        }).catch(resolve);
-      }).then(() => {
-        this.setInitialView(storedHash, {
+        if (pageMode && !this.viewerPrefs['disablePageMode']) {
+          sidebarView = sidebarView || apiPageModeToSidebarView(pageMode);
+        }
+        return {
+          hash,
+          sidebarView
+        };
+      }).then(({ hash, sidebarView }) => {
+        this.setInitialView(hash, {
           sidebarView,
           scale
         });
-        initialParams.hash = storedHash;
+        initialParams.hash = hash;
         if (!this.isViewerEmbedded) {
           pdfViewer.focus();
         }
         return pagesPromise;
       }).then(() => {
         if (!initialParams.destination && !initialParams.bookmark && !initialParams.hash) {
           return;
         }
@@ -2324,16 +2327,30 @@ function webViewerKeyDown(evt) {
   }
   if (ensureViewerFocused && !pdfViewer.containsElement(curElement)) {
     pdfViewer.focus();
   }
   if (handled) {
     evt.preventDefault();
   }
 }
+function apiPageModeToSidebarView(mode) {
+  switch (mode) {
+    case 'UseNone':
+      return _pdf_sidebar.SidebarView.NONE;
+    case 'UseThumbs':
+      return _pdf_sidebar.SidebarView.THUMBS;
+    case 'UseOutlines':
+      return _pdf_sidebar.SidebarView.OUTLINE;
+    case 'UseAttachments':
+      return _pdf_sidebar.SidebarView.ATTACHMENTS;
+    case 'UseOC':
+  }
+  return _pdf_sidebar.SidebarView.NONE;
+}
 let PDFPrintServiceFactory = {
   instance: {
     supportsPrinting: false,
     createPrintService() {
       throw new Error('Not implemented: createPrintService');
     }
   }
 };
@@ -7071,16 +7088,17 @@ function getDefaultPreferences() {
       "disableFontFace": false,
       "disableTextLayer": false,
       "useOnlyCssZoom": false,
       "externalLinkTarget": 0,
       "enhanceTextSelection": false,
       "renderer": "canvas",
       "renderInteractiveForms": false,
       "enablePrintAutoRotate": false,
+      "disablePageMode": false,
       "disablePageLabels": false
     });
   }
   return defaultPreferences;
 }
 class BasePreferences {
   constructor() {
     if (this.constructor === BasePreferences) {
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -12384,17 +12384,22 @@ nsGlobalWindow::Observe(nsISupports* aSu
 
 void
 nsGlobalWindow::ObserveStorageNotification(StorageEvent* aEvent,
                                            const char16_t* aStorageType,
                                            bool aPrivateBrowsing)
 {
   MOZ_ASSERT(aEvent);
 
-  MOZ_DIAGNOSTIC_ASSERT(IsPrivateBrowsing() == aPrivateBrowsing);
+  // The private browsing check must be done here again because this window
+  // could have changed its state before the notification check and now. This
+  // happens in case this window did have a docShell at that time.
+  if (aPrivateBrowsing != IsPrivateBrowsing()) {
+    return;
+  }
 
   // LocalStorage can only exist on an inner window, and we don't want to
   // generate events on frozen or otherwise-navigated-away from windows.
   // (Actually, this code used to try and buffer events for frozen windows,
   // but it never worked, so we've removed it.  See bug 1285898.)
   if (!IsInnerWindow() || !AsInner()->IsCurrentInnerWindow() || IsFrozen()) {
     return;
   }
--- a/dom/base/nsJSEnvironment.cpp
+++ b/dom/base/nsJSEnvironment.cpp
@@ -2446,17 +2446,17 @@ DOMGCSliceCallback(JSContext* aCx, JS::G
         }
       }
 
       if (!sShuttingDown) {
         if (sPostGCEventsToObserver || Telemetry::CanRecordExtended()) {
           nsString json;
           json.Adopt(aDesc.formatJSON(aCx, PR_Now()));
           RefPtr<NotifyGCEndRunnable> notify = new NotifyGCEndRunnable(json);
-          NS_DispatchToMainThread(notify);
+          SystemGroup::Dispatch(TaskCategory::GarbageCollection, notify.forget());
         }
       }
 
       sCCLockedOut = false;
       sIsCompactingOnUserInactive = false;
 
       // May need to kill the inter-slice GC runner
       nsJSContext::KillInterSliceGCRunner();
--- a/dom/base/nsWindowMemoryReporter.cpp
+++ b/dom/base/nsWindowMemoryReporter.cpp
@@ -832,19 +832,19 @@ nsWindowMemoryReporter::CheckForGhostWin
       // This window does not share a domain with a non-detached window, so it
       // meets ghost criterion (2).
       if (timeStamp.IsNull()) {
         // This may become a ghost window later; start its clock.
         timeStamp = now;
       } else if ((now - timeStamp).ToSeconds() > ghostTimeout) {
         // This definitely is a ghost window, so add it to aOutGhostIDs, if
         // that is not null.
+        mGhostWindowCount++;
         if (aOutGhostIDs && window) {
           aOutGhostIDs->PutEntry(window->WindowID());
-          mGhostWindowCount++;
         }
       }
     }
   }
 }
 
 /* static */ int64_t
 nsWindowMemoryReporter::GhostWindowsDistinguishedAmount()
--- a/dom/console/Console.cpp
+++ b/dom/console/Console.cpp
@@ -578,17 +578,17 @@ private:
       nsString id = frame.mFilename;
       nsString innerID;
       if (mWorkerPrivate->IsSharedWorker()) {
         innerID = NS_LITERAL_STRING("SharedWorker");
       } else if (mWorkerPrivate->IsServiceWorker()) {
         innerID = NS_LITERAL_STRING("ServiceWorker");
         // Use scope as ID so the webconsole can decide if the message should
         // show up per tab
-        id.AssignWithConversion(mWorkerPrivate->ServiceWorkerScope());
+        CopyASCIItoUTF16(mWorkerPrivate->ServiceWorkerScope(), id);
       } else {
         innerID = NS_LITERAL_STRING("Worker");
       }
 
       mCallData->SetIDs(id, innerID);
     }
 
     // Now we could have the correct window (if we are not window-less).
--- a/dom/indexedDB/ActorsParent.cpp
+++ b/dom/indexedDB/ActorsParent.cpp
@@ -4415,17 +4415,17 @@ struct StorageOpenTraits<nsIFile*>
 
 #ifdef DEBUG
   static void
   GetPath(nsIFile* aFile, nsCString& aPath)
   {
     nsString path;
     MOZ_ALWAYS_SUCCEEDS(aFile->GetPath(path));
 
-    aPath.AssignWithConversion(path);
+    LossyCopyUTF16toASCII(path, aPath);
   }
 #endif
 };
 
 template <template <class> class SmartPtr, class FileOrURLType>
 struct StorageOpenTraits<SmartPtr<FileOrURLType>>
   : public StorageOpenTraits<FileOrURLType*>
 { };
@@ -22196,17 +22196,17 @@ OpenDatabaseOp::UpdateLocaleAwareIndex(m
                                            "locale = :locale WHERE id = :id");
   nsCOMPtr<mozIStorageStatement> metaStmt;
   rv = aConnection->CreateStatement(metaQuery, getter_AddRefs(metaStmt));
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   nsString locale;
-  locale.AssignWithConversion(aLocale);
+  CopyASCIItoUTF16(aLocale, locale);
   rv = metaStmt->BindStringByName(NS_LITERAL_CSTRING("locale"), locale);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   rv = metaStmt->BindInt64ByName(NS_LITERAL_CSTRING("id"), aIndexMetadata.id());
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
--- a/dom/indexedDB/IDBIndex.cpp
+++ b/dom/indexedDB/IDBIndex.cpp
@@ -248,17 +248,17 @@ void
 IDBIndex::GetLocale(nsString& aLocale) const
 {
   AssertIsOnOwningThread();
   MOZ_ASSERT(mMetadata);
 
   if (mMetadata->locale().IsEmpty()) {
     SetDOMStringToNull(aLocale);
   } else {
-    aLocale.AssignWithConversion(mMetadata->locale());
+    CopyASCIItoUTF16(mMetadata->locale(), aLocale);
   }
 }
 
 const nsCString&
 IDBIndex::Locale() const
 {
   AssertIsOnOwningThread();
   MOZ_ASSERT(mMetadata);
--- a/dom/webbrowserpersist/nsWebBrowserPersist.cpp
+++ b/dom/webbrowserpersist/nsWebBrowserPersist.cpp
@@ -1536,17 +1536,17 @@ nsWebBrowserPersist::GetExtensionForCont
     nsresult rv;
     if (!mMIMEService)
     {
         mMIMEService = do_GetService(NS_MIMESERVICE_CONTRACTID, &rv);
         NS_ENSURE_TRUE(mMIMEService, NS_ERROR_FAILURE);
     }
 
     nsAutoCString contentType;
-    contentType.AssignWithConversion(aContentType);
+    LossyCopyUTF16toASCII(aContentType, contentType);
     nsAutoCString ext;
     rv = mMIMEService->GetPrimaryExtension(contentType, EmptyCString(), ext);
     if (NS_SUCCEEDED(rv))
     {
         *aExt = UTF8ToNewUnicode(ext);
         NS_ENSURE_TRUE(*aExt, NS_ERROR_OUT_OF_MEMORY);
         return NS_OK;
     }
@@ -2086,17 +2086,17 @@ nsWebBrowserPersist::CalculateUniqueFile
         }
 
         nsCOMPtr<nsIFile> localFile;
         GetLocalFileFromURI(aURI, getter_AddRefs(localFile));
 
         if (localFile)
         {
             nsAutoString filenameAsUnichar;
-            filenameAsUnichar.AssignWithConversion(filename.get());
+            CopyASCIItoUTF16(filename, filenameAsUnichar);
             localFile->SetLeafName(filenameAsUnichar);
 
             // Resync the URI with the file after the extension has been appended
             nsresult rv;
             nsCOMPtr<nsIFileURL> fileURL = do_QueryInterface(aURI, &rv);
             NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
             fileURL->SetFile(localFile);  // this should recalculate uri
         }
@@ -2121,17 +2121,17 @@ nsWebBrowserPersist::MakeFilenameFromURI
 
     nsCOMPtr<nsIURL> url(do_QueryInterface(aURI));
     if (url)
     {
         nsAutoCString nameFromURL;
         url->GetFileName(nameFromURL);
         if (mPersistFlags & PERSIST_FLAGS_DONT_CHANGE_FILENAMES)
         {
-            fileName.AssignWithConversion(NS_UnescapeURL(nameFromURL).BeginReading());
+            CopyASCIItoUTF16(NS_UnescapeURL(nameFromURL), fileName);
             aFilename = fileName;
             return NS_OK;
         }
         if (!nameFromURL.IsEmpty())
         {
             // Unescape the file name (GetFileName escapes it)
             NS_UnescapeURL(nameFromURL);
             uint32_t nameLength = 0;
--- a/dom/xbl/nsXBLPrototypeBinding.cpp
+++ b/dom/xbl/nsXBLPrototypeBinding.cpp
@@ -630,17 +630,17 @@ nsXBLPrototypeBinding::ConstructAttribut
       while( token != nullptr ) {
         // Build an atom out of this attribute.
         nsCOMPtr<nsIAtom> atom;
         int32_t atomNsID = kNameSpaceID_None;
         nsCOMPtr<nsIAtom> attribute;
         int32_t attributeNsID = kNameSpaceID_None;
 
         // Figure out if this token contains a :.
-        nsAutoString attrTok; attrTok.AssignWithConversion(token);
+        NS_ConvertASCIItoUTF16 attrTok(token);
         int32_t index = attrTok.Find("=", true);
         nsresult rv;
         if (index != -1) {
           // This attribute maps to something different.
           nsAutoString left, right;
           attrTok.Left(left, index);
           attrTok.Right(right, attrTok.Length()-index-1);
 
@@ -650,18 +650,17 @@ nsXBLPrototypeBinding::ConstructAttribut
             return;
 
           rv = nsContentUtils::SplitQName(aElement, right, &atomNsID,
                                           getter_AddRefs(atom));
           if (NS_FAILED(rv))
             return;
         }
         else {
-          nsAutoString tok;
-          tok.AssignWithConversion(token);
+          NS_ConvertASCIItoUTF16 tok(token);
           rv = nsContentUtils::SplitQName(aElement, tok, &atomNsID,
                                           getter_AddRefs(atom));
           if (NS_FAILED(rv))
             return;
           attribute = atom;
           attributeNsID = atomNsID;
         }
 
--- a/dom/xbl/nsXBLPrototypeHandler.cpp
+++ b/dom/xbl/nsXBLPrototypeHandler.cpp
@@ -767,17 +767,17 @@ static const keyCodeData gKeyCodes[] = {
 #undef NS_DEFINE_VK
 
   { nullptr, 0, 0 }
 };
 
 int32_t nsXBLPrototypeHandler::GetMatchingKeyCode(const nsAString& aKeyName)
 {
   nsAutoCString keyName;
-  keyName.AssignWithConversion(aKeyName);
+  LossyCopyUTF16toASCII(aKeyName, keyName);
   ToUpperCase(keyName); // We want case-insensitive comparison with data
                         // stored as uppercase.
 
   uint32_t keyNameLength = keyName.Length();
   const char* keyNameStr = keyName.get();
   for (uint16_t i = 0; i < ArrayLength(gKeyCodes) - 1; ++i) {
     if (keyNameLength == gKeyCodes[i].strlength &&
         !nsCRT::strcmp(gKeyCodes[i].str, keyNameStr)) {
--- a/dom/xhr/XMLHttpRequestWorker.cpp
+++ b/dom/xhr/XMLHttpRequestWorker.cpp
@@ -443,17 +443,17 @@ public:
     , mWorkerPrivate(aProxy->mWorkerPrivate)
     , mProxy(aProxy)
     , mXHR(aProxy->mXHR)
     , mXMLHttpRequestPrivate(aXHRPrivate)
     , mChannelId(mProxy->mInnerChannelId)
     , mReceivedLoadStart(false)
   {
     AssertIsOnMainThread();
-    mEventType.AssignWithConversion(sEventStrings[STRING_loadstart]);
+    CopyASCIItoUTF16(sEventStrings[STRING_loadstart], mEventType);
   }
 
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_NSIRUNNABLE
   NS_DECL_NSIDOMEVENTLISTENER
 
   bool
   RegisterAndDispatch()
--- a/dom/xul/XULDocument.cpp
+++ b/dom/xul/XULDocument.cpp
@@ -3809,17 +3809,17 @@ XULDocument::OverlayForwardReference::Re
         // XXX this is bogus, the content in 'target' might already be
         // in the document
         rv = mDocument->AddSubtreeToDocument(target);
         if (NS_FAILED(rv)) return eResolve_Error;
     }
 
     if (MOZ_LOG_TEST(gXULLog, LogLevel::Debug)) {
         nsAutoCString idC;
-        idC.AssignWithConversion(id);
+        LossyCopyUTF16toASCII(id, idC);
         MOZ_LOG(gXULLog, LogLevel::Debug,
                ("xul: overlay resolved '%s'",
                 idC.get()));
     }
 
     mResolved = true;
     return eResolve_Succeeded;
 }
@@ -3981,17 +3981,17 @@ XULDocument::OverlayForwardReference::Me
 
 XULDocument::OverlayForwardReference::~OverlayForwardReference()
 {
     if (MOZ_LOG_TEST(gXULLog, LogLevel::Warning) && !mResolved) {
         nsAutoString id;
         mOverlay->GetAttr(kNameSpaceID_None, nsGkAtoms::id, id);
 
         nsAutoCString idC;
-        idC.AssignWithConversion(id);
+        LossyCopyUTF16toASCII(id, idC);
 
         nsIURI *protoURI = mDocument->mCurrentPrototype->GetURI();
 
         nsCOMPtr<nsIURI> docURI;
         mDocument->mChannel->GetOriginalURI(getter_AddRefs(docURI));
 
         MOZ_LOG(gXULLog, LogLevel::Warning,
                ("xul: %s overlay failed to resolve '%s' in %s",
@@ -4032,18 +4032,18 @@ XULDocument::BroadcasterHookup::~Broadca
             mObservesElement->GetAttr(kNameSpaceID_None, nsGkAtoms::attribute, attribute);
         }
         else {
             mObservesElement->GetAttr(kNameSpaceID_None, nsGkAtoms::observes, broadcasterID);
             attribute.Assign('*');
         }
 
         nsAutoCString attributeC,broadcasteridC;
-        attributeC.AssignWithConversion(attribute);
-        broadcasteridC.AssignWithConversion(broadcasterID);
+        LossyCopyUTF16toASCII(attribute, attributeC);
+        LossyCopyUTF16toASCII(broadcasterID, broadcasteridC);
         MOZ_LOG(gXULLog, LogLevel::Warning,
                ("xul: broadcaster hookup failed <%s attribute='%s'> to %s",
                 nsAtomCString(mObservesElement->NodeInfo()->NameAtom()).get(),
                 attributeC.get(),
                 broadcasteridC.get()));
     }
 }
 
@@ -4244,18 +4244,18 @@ XULDocument::CheckBroadcasterHookup(Elem
         nsCOMPtr<nsIContent> content =
             do_QueryInterface(listener);
 
         NS_ASSERTION(content != nullptr, "not an nsIContent");
         if (! content)
             return rv;
 
         nsAutoCString attributeC,broadcasteridC;
-        attributeC.AssignWithConversion(attribute);
-        broadcasteridC.AssignWithConversion(broadcasterID);
+        LossyCopyUTF16toASCII(attribute, attributeC);
+        LossyCopyUTF16toASCII(broadcasterID, broadcasteridC);
         MOZ_LOG(gXULLog, LogLevel::Debug,
                ("xul: broadcaster hookup <%s attribute='%s'> to %s",
                 nsAtomCString(content->NodeInfo()->NameAtom()).get(),
                 attributeC.get(),
                 broadcasteridC.get()));
     }
 
     *aNeedsHookup = false;
--- a/dom/xul/nsXULCommandDispatcher.cpp
+++ b/dom/xul/nsXULCommandDispatcher.cpp
@@ -258,18 +258,18 @@ nsXULCommandDispatcher::AddCommandUpdate
   Updater** link = &mUpdaters;
 
   while (updater) {
     if (updater->mElement == aElement) {
 
 #ifdef DEBUG
       if (MOZ_LOG_TEST(gCommandLog, LogLevel::Debug)) {
         nsAutoCString eventsC, targetsC, aeventsC, atargetsC;
-        eventsC.AssignWithConversion(updater->mEvents);
-        targetsC.AssignWithConversion(updater->mTargets);
+        LossyCopyUTF16toASCII(updater->mEvents, eventsC);
+        LossyCopyUTF16toASCII(updater->mTargets, targetsC);
         CopyUTF16toUTF8(aEvents, aeventsC);
         CopyUTF16toUTF8(aTargets, atargetsC);
         MOZ_LOG(gCommandLog, LogLevel::Debug,
                ("xulcmd[%p] replace %p(events=%s targets=%s) with (events=%s targets=%s)",
                 this, aElement,
                 eventsC.get(),
                 targetsC.get(),
                 aeventsC.get(),
@@ -317,18 +317,18 @@ nsXULCommandDispatcher::RemoveCommandUpd
   Updater* updater = mUpdaters;
   Updater** link = &mUpdaters;
 
   while (updater) {
     if (updater->mElement == aElement) {
 #ifdef DEBUG
       if (MOZ_LOG_TEST(gCommandLog, LogLevel::Debug)) {
         nsAutoCString eventsC, targetsC;
-        eventsC.AssignWithConversion(updater->mEvents);
-        targetsC.AssignWithConversion(updater->mTargets);
+        LossyCopyUTF16toASCII(updater->mEvents, eventsC);
+        LossyCopyUTF16toASCII(updater->mTargets, targetsC);
         MOZ_LOG(gCommandLog, LogLevel::Debug,
                ("xulcmd[%p] remove  %p(events=%s targets=%s)",
                 this, aElement,
                 eventsC.get(),
                 targetsC.get()));
       }
 #endif
 
--- a/dom/xul/templates/nsXULTemplateQueryProcessorRDF.cpp
+++ b/dom/xul/templates/nsXULTemplateQueryProcessorRDF.cpp
@@ -1008,17 +1008,17 @@ nsXULTemplateQueryProcessorRDF::Log(cons
             return rv;
 
         nsAutoString targetStr;
         rv = nsXULContentUtils::GetTextForNode(aTarget, targetStr);
         if (NS_FAILED(rv))
             return rv;
 
         nsAutoCString targetstrC;
-        targetstrC.AssignWithConversion(targetStr);
+        LossyCopyUTF16toASCII(targetStr, targetstrC);
         MOZ_LOG(gXULTemplateLog, LogLevel::Debug,
                ("                        --[%s]-->[%s]",
                 propertyStr,
                 targetstrC.get()));
     }
     return NS_OK;
 }
 
@@ -1234,17 +1234,17 @@ nsXULTemplateQueryProcessorRDF::CompileQ
     else if (aTag == nsGkAtoms::member) {
         rv = CompileMemberCondition(aQuery, aCondition, aParentNode, aResult);
     }
     else if (MOZ_LOG_TEST(gXULTemplateLog, LogLevel::Info)) {
         nsAutoString tagstr;
         aTag->ToString(tagstr);
 
         nsAutoCString tagstrC;
-        tagstrC.AssignWithConversion(tagstr);
+        LossyCopyUTF16toASCII(tagstr, tagstrC);
         MOZ_LOG(gXULTemplateLog, LogLevel::Info,
                ("xultemplate[%p] unrecognized condition test <%s>",
                 this, tagstrC.get()));
     }
 
     return rv;
 }
 
--- a/editor/composer/nsComposerCommands.cpp
+++ b/editor/composer/nsComposerCommands.cpp
@@ -582,17 +582,17 @@ nsMultiStateCommand::DoCommandParams(con
   nsresult rv = NS_OK;
   if (editor) {
       nsAutoString tString;
 
       if (aParams) {
         nsXPIDLCString s;
         rv = aParams->GetCStringValue(STATE_ATTRIBUTE, getter_Copies(s));
         if (NS_SUCCEEDED(rv))
-          tString.AssignWithConversion(s);
+          CopyASCIItoUTF16(s, tString);
         else
           rv = aParams->GetStringValue(STATE_ATTRIBUTE, tString);
       }
 
       rv = SetState(editor, tString);
   }
 
   return rv;
@@ -625,17 +625,17 @@ nsParagraphStateCommand::GetCurrentState
   nsCOMPtr<nsIHTMLEditor> htmlEditor = do_QueryInterface(aEditor);
   NS_ENSURE_TRUE(htmlEditor, NS_ERROR_FAILURE);
 
   bool outMixed;
   nsAutoString outStateString;
   nsresult rv = htmlEditor->GetParagraphState(&outMixed, outStateString);
   if (NS_SUCCEEDED(rv)) {
     nsAutoCString tOutStateString;
-    tOutStateString.AssignWithConversion(outStateString);
+    LossyCopyUTF16toASCII(outStateString, tOutStateString);
     aParams->SetBooleanValue(STATE_MIXED,outMixed);
     aParams->SetCStringValue(STATE_ATTRIBUTE, tOutStateString.get());
   }
   return rv;
 }
 
 
 nsresult
@@ -702,18 +702,16 @@ nsFontFaceStateCommand::SetState(nsIEdit
                                        NS_LITERAL_STRING("face"), newState);
 }
 
 nsFontSizeStateCommand::nsFontSizeStateCommand()
   : nsMultiStateCommand()
 {
 }
 
-//  nsAutoCString tOutStateString;
-//  tOutStateString.AssignWithConversion(outStateString);
 nsresult
 nsFontSizeStateCommand::GetCurrentState(nsIEditor *aEditor,
                                         nsICommandParams *aParams)
 {
   NS_ASSERTION(aEditor, "Need an editor here");
   nsCOMPtr<nsIHTMLEditor> htmlEditor = do_QueryInterface(aEditor);
   NS_ENSURE_TRUE(htmlEditor, NS_ERROR_INVALID_ARG);
 
@@ -723,17 +721,17 @@ nsFontSizeStateCommand::GetCurrentState(
   nsresult rv = htmlEditor->GetInlinePropertyWithAttrValue(fontAtom,
                                          NS_LITERAL_STRING("size"),
                                          EmptyString(),
                                          &firstHas, &anyHas, &allHas,
                                          outStateString);
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsAutoCString tOutStateString;
-  tOutStateString.AssignWithConversion(outStateString);
+  LossyCopyUTF16toASCII(outStateString, tOutStateString);
   aParams->SetBooleanValue(STATE_MIXED, anyHas && !allHas);
   aParams->SetCStringValue(STATE_ATTRIBUTE, tOutStateString.get());
   aParams->SetBooleanValue(STATE_ENABLED, true);
 
   return rv;
 }
 
 
@@ -786,17 +784,17 @@ nsFontColorStateCommand::GetCurrentState
   NS_ENSURE_TRUE(htmlEditor, NS_ERROR_FAILURE);
 
   bool outMixed;
   nsAutoString outStateString;
   nsresult rv = htmlEditor->GetFontColorState(&outMixed, outStateString);
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsAutoCString tOutStateString;
-  tOutStateString.AssignWithConversion(outStateString);
+  LossyCopyUTF16toASCII(outStateString, tOutStateString);
   aParams->SetBooleanValue(STATE_MIXED, outMixed);
   aParams->SetCStringValue(STATE_ATTRIBUTE, tOutStateString.get());
   return NS_OK;
 }
 
 nsresult
 nsFontColorStateCommand::SetState(nsIEditor *aEditor, nsString& newState)
 {
@@ -827,17 +825,17 @@ nsHighlightColorStateCommand::GetCurrent
   NS_ENSURE_TRUE(htmlEditor, NS_ERROR_FAILURE);
 
   bool outMixed;
   nsAutoString outStateString;
   nsresult rv = htmlEditor->GetHighlightColorState(&outMixed, outStateString);
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsAutoCString tOutStateString;
-  tOutStateString.AssignWithConversion(outStateString);
+  LossyCopyUTF16toASCII(outStateString, tOutStateString);
   aParams->SetBooleanValue(STATE_MIXED, outMixed);
   aParams->SetCStringValue(STATE_ATTRIBUTE, tOutStateString.get());
   return NS_OK;
 }
 
 nsresult
 nsHighlightColorStateCommand::SetState(nsIEditor *aEditor, nsString& newState)
 {
@@ -884,17 +882,17 @@ nsBackgroundColorStateCommand::GetCurren
   NS_ENSURE_TRUE(htmlEditor, NS_ERROR_FAILURE);
 
   bool outMixed;
   nsAutoString outStateString;
   nsresult rv =  htmlEditor->GetBackgroundColorState(&outMixed, outStateString);
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsAutoCString tOutStateString;
-  tOutStateString.AssignWithConversion(outStateString);
+  LossyCopyUTF16toASCII(outStateString, tOutStateString);
   aParams->SetBooleanValue(STATE_MIXED, outMixed);
   aParams->SetCStringValue(STATE_ATTRIBUTE, tOutStateString.get());
   return NS_OK;
 }
 
 nsresult
 nsBackgroundColorStateCommand::SetState(nsIEditor *aEditor, nsString& newState)
 {
@@ -940,17 +938,17 @@ nsAlignCommand::GetCurrentState(nsIEdito
       outStateString.AssignLiteral("right");
       break;
 
     case nsIHTMLEditor::eJustify:
       outStateString.AssignLiteral("justify");
       break;
   }
   nsAutoCString tOutStateString;
-  tOutStateString.AssignWithConversion(outStateString);
+  LossyCopyUTF16toASCII(outStateString, tOutStateString);
   aParams->SetBooleanValue(STATE_MIXED,outMixed);
   aParams->SetCStringValue(STATE_ATTRIBUTE, tOutStateString.get());
   return NS_OK;
 }
 
 nsresult
 nsAlignCommand::SetState(nsIEditor *aEditor, nsString& newState)
 {
@@ -1403,17 +1401,18 @@ nsInsertTagCommand::DoCommandParams(cons
 
   nsCOMPtr<nsIHTMLEditor> editor = do_QueryInterface(refCon);
   NS_ENSURE_TRUE(editor, NS_ERROR_NOT_IMPLEMENTED);
 
   // do we have an href to use for creating link?
   nsXPIDLCString s;
   nsresult rv = aParams->GetCStringValue(STATE_ATTRIBUTE, getter_Copies(s));
   NS_ENSURE_SUCCESS(rv, rv);
-  nsAutoString attrib; attrib.AssignWithConversion(s);
+  nsAutoString attrib;
+  CopyASCIItoUTF16(s, attrib);
 
   if (attrib.IsEmpty())
     return NS_ERROR_INVALID_ARG;
 
   // filter out tags we don't know how to insert
   nsAutoString attributeType;
   if (mTagName == nsGkAtoms::a) {
     attributeType.AssignLiteral("href");
--- a/editor/libeditor/HTMLEditor.cpp
+++ b/editor/libeditor/HTMLEditor.cpp
@@ -3483,17 +3483,17 @@ HTMLEditor::StyleSheetLoaded(StyleSheet*
   nsresult rv = DoTransaction(transaction);
   if (NS_SUCCEEDED(rv)) {
     // Get the URI, then url spec from the sheet
     nsAutoCString spec;
     rv = aSheet->GetSheetURI()->GetSpec(spec);
 
     if (NS_SUCCEEDED(rv)) {
       // Save it so we can remove before applying the next one
-      mLastStyleSheetURL.AssignWithConversion(spec.get());
+      CopyASCIItoUTF16(spec, mLastStyleSheetURL);
 
       // Also save in our arrays of urls and sheets
       AddNewStyleSheetToList(mLastStyleSheetURL, aSheet);
     }
   }
 
   return NS_OK;
 }
--- a/editor/libeditor/HTMLEditorDataTransfer.cpp
+++ b/editor/libeditor/HTMLEditorDataTransfer.cpp
@@ -1148,17 +1148,17 @@ HTMLEditor::InsertFromTransferable(nsITr
   nsCOMPtr<nsISupports> genericDataObj;
   uint32_t len = 0;
   if (NS_SUCCEEDED(
         transferable->GetAnyTransferData(bestFlavor,
                                          getter_AddRefs(genericDataObj),
                                          &len))) {
     AutoTransactionsConserveSelection dontSpazMySelection(this);
     nsAutoString flavor;
-    flavor.AssignWithConversion(bestFlavor);
+    CopyASCIItoUTF16(bestFlavor, flavor);
     nsAutoString stuffToPaste;
     bool isSafe = IsSafeToInsertData(aSourceDoc);
 
     if (bestFlavor.EqualsLiteral(kFileMime) ||
         bestFlavor.EqualsLiteral(kJPEGImageMime) ||
         bestFlavor.EqualsLiteral(kJPGImageMime) ||
         bestFlavor.EqualsLiteral(kPNGImageMime) ||
         bestFlavor.EqualsLiteral(kGIFImageMime)) {
--- a/gfx/2d/2D.h
+++ b/gfx/2d/2D.h
@@ -1227,24 +1227,16 @@ public:
 
   /**
    * Create a DrawTarget whose snapshot is optimized for use with this DrawTarget.
    */
   virtual already_AddRefed<DrawTarget>
     CreateSimilarDrawTarget(const IntSize &aSize, SurfaceFormat aFormat) const = 0;
 
   /**
-   * Create a DrawTarget that captures the drawing commands and can be replayed
-   * onto a compatible DrawTarget afterwards.
-   *
-   * @param aSize Size of the area this DT will capture.
-   */
-  virtual already_AddRefed<DrawTargetCapture> CreateCaptureDT(const IntSize& aSize);
-
-  /**
    * Create a draw target optimized for drawing a shadow.
    *
    * Note that aSigma is the blur radius that must be used when we draw the
    * shadow. Also note that this doesn't affect the size of the allocated
    * surface, the caller is still responsible for including the shadow area in
    * its size.
    */
   virtual already_AddRefed<DrawTarget>
@@ -1492,16 +1484,26 @@ public:
 
   static already_AddRefed<DrawTarget> CreateDrawTargetForCairoSurface(cairo_surface_t* aSurface, const IntSize& aSize, SurfaceFormat* aFormat = nullptr);
 
   static already_AddRefed<SourceSurface> CreateSourceSurfaceForCairoSurface(cairo_surface_t* aSurface, const IntSize& aSize, SurfaceFormat aFormat);
 
   static already_AddRefed<DrawTarget>
     CreateDrawTarget(BackendType aBackend, const IntSize &aSize, SurfaceFormat aFormat);
 
+  /**
+   * Create a DrawTarget that captures the drawing commands and can be replayed
+   * onto a compatible DrawTarget afterwards.
+   *
+   * @param aSize Size of the area this DT will capture.
+   */
+  static already_AddRefed<DrawTargetCapture>
+    CreateCaptureDrawTarget(BackendType aBackend, const IntSize &aSize, SurfaceFormat aFormat);
+
+
   static already_AddRefed<DrawTarget>
     CreateWrapAndRecordDrawTarget(DrawEventRecorder *aRecorder, DrawTarget *aDT);
 
   static already_AddRefed<DrawTarget>
     CreateRecordingDrawTarget(DrawEventRecorder *aRecorder, DrawTarget *aDT, IntSize aSize);
 
   static already_AddRefed<DrawTarget>
     CreateDrawTargetForData(BackendType aBackend, unsigned char* aData, const IntSize &aSize, int32_t aStride, SurfaceFormat aFormat, bool aUninitialized = false);
--- a/gfx/2d/DrawTarget.cpp
+++ b/gfx/2d/DrawTarget.cpp
@@ -170,29 +170,16 @@ ComputeLinearRGBLuminanceMask(const uint
       sourcePixel += 4;
       destPixel++;
     }
     sourcePixel += sourceOffset;
     destPixel += destOffset;
   }
 }
 
-already_AddRefed<DrawTargetCapture>
-DrawTarget::CreateCaptureDT(const IntSize& aSize)
-{
-  RefPtr<DrawTargetCaptureImpl> dt = new DrawTargetCaptureImpl();
-
-  if (!dt->Init(aSize, this)) {
-    gfxWarning() << "Failed to initialize Capture DrawTarget!";
-    return nullptr;
-  }
-
-  return dt.forget();
-}
-
 void
 DrawTarget::DrawCapturedDT(DrawTargetCapture *aCaptureDT,
                            const Matrix& aTransform)
 {
   if (aTransform.HasNonIntegerTranslation()) {
     gfxWarning() << "Non integer translations are not supported for DrawCaptureDT at this time!";
     return;
   }
--- a/gfx/2d/DrawTargetCapture.cpp
+++ b/gfx/2d/DrawTargetCapture.cpp
@@ -1,15 +1,16 @@
 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "DrawTargetCapture.h"
 #include "DrawCommand.h"
+#include "gfxPlatform.h"
 
 namespace mozilla {
 namespace gfx {
 
 
 DrawTargetCaptureImpl::~DrawTargetCaptureImpl()
 {
   uint8_t* start = &mDrawCommandStorage.front();
@@ -17,16 +18,41 @@ DrawTargetCaptureImpl::~DrawTargetCaptur
   uint8_t* current = start;
 
   while (current < start + mDrawCommandStorage.size()) {
     reinterpret_cast<DrawingCommand*>(current + sizeof(uint32_t))->~DrawingCommand();
     current += *(uint32_t*)current;
   }
 }
 
+DrawTargetCaptureImpl::DrawTargetCaptureImpl(BackendType aBackend,
+                                             const IntSize& aSize,
+                                             SurfaceFormat aFormat)
+  : mSize(aSize)
+{
+  RefPtr<DrawTarget> screenRefDT =
+      gfxPlatform::GetPlatform()->ScreenReferenceDrawTarget();
+
+  if (aBackend == screenRefDT->GetBackendType()) {
+    mRefDT = screenRefDT;
+  } else {
+    // If you got here, we have to create a new ref DT to create
+    // backend specific assets like paths / gradients. Try to
+    // create the same backend type as the screen ref dt.
+    gfxWarning() << "Creating a RefDT in DrawTargetCapture.";
+
+    // Create a 1x1 size ref dt to create assets
+    // If we have to snapshot, we'll just create the real DT
+    IntSize size(1, 1);
+    mRefDT = Factory::CreateDrawTarget(aBackend, size, mFormat);
+  }
+
+  mFormat = aFormat;
+}
+
 bool
 DrawTargetCaptureImpl::Init(const IntSize& aSize, DrawTarget* aRefDT)
 {
   if (!aRefDT) {
     return false;
   }
 
   mRefDT = aRefDT;
@@ -34,17 +60,17 @@ DrawTargetCaptureImpl::Init(const IntSiz
   mSize = aSize;
   mFormat = aRefDT->GetFormat();
   return true;
 }
 
 already_AddRefed<SourceSurface>
 DrawTargetCaptureImpl::Snapshot()
 {
-  RefPtr<DrawTarget> dt = mRefDT->CreateSimilarDrawTarget(mSize, mRefDT->GetFormat());
+  RefPtr<DrawTarget> dt = mRefDT->CreateSimilarDrawTarget(mSize, mFormat);
 
   ReplayToDrawTarget(dt, Matrix());
 
   return dt->Snapshot();
 }
 
 void
 DrawTargetCaptureImpl::DetachAllSnapshots()
--- a/gfx/2d/DrawTargetCapture.h
+++ b/gfx/2d/DrawTargetCapture.h
@@ -14,18 +14,17 @@
 namespace mozilla {
 namespace gfx {
 
 class DrawingCommand;
 
 class DrawTargetCaptureImpl : public DrawTargetCapture
 {
 public:
-  DrawTargetCaptureImpl()
-  {}
+  DrawTargetCaptureImpl(BackendType aBackend, const IntSize& aSize, SurfaceFormat aFormat);
 
   bool Init(const IntSize& aSize, DrawTarget* aRefDT);
 
   virtual BackendType GetBackendType() const override { return mRefDT->GetBackendType(); }
   virtual DrawTargetType GetType() const override { return mRefDT->GetType(); }
   virtual bool IsCaptureDT() const override { return true; }
   virtual already_AddRefed<SourceSurface> Snapshot() override;
   virtual void DetachAllSnapshots() override;
@@ -144,34 +143,33 @@ public:
     return mRefDT->CreateFilter(aType);
   }
 
   void ReplayToDrawTarget(DrawTarget* aDT, const Matrix& aTransform);
 
   bool ContainsOnlyColoredGlyphs(RefPtr<ScaledFont>& aScaledFont, Color& aColor, std::vector<Glyph>& aGlyphs) override;
 
 protected:
-  ~DrawTargetCaptureImpl();
+  virtual ~DrawTargetCaptureImpl();
 
 private:
 
   // This storage system was used to minimize the amount of heap allocations
   // that are required while recording. It should be noted there's no
   // guarantees on the alignments of DrawingCommands allocated in this array.
   template<typename T>
   T* AppendToCommandList()
   {
     size_t oldSize = mDrawCommandStorage.size();
     mDrawCommandStorage.resize(mDrawCommandStorage.size() + sizeof(T) + sizeof(uint32_t));
     uint8_t* nextDrawLocation = &mDrawCommandStorage.front() + oldSize;
     *(uint32_t*)(nextDrawLocation) = sizeof(T) + sizeof(uint32_t);
     return reinterpret_cast<T*>(nextDrawLocation + sizeof(uint32_t));
   }
   RefPtr<DrawTarget> mRefDT;
-
   IntSize mSize;
 
   std::vector<uint8_t> mDrawCommandStorage;
 };
 
 } // namespace gfx
 
 } // namespace mozilla
--- a/gfx/2d/Factory.cpp
+++ b/gfx/2d/Factory.cpp
@@ -1,10 +1,10 @@
-/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
- * This Source Code Form is subject to the terms of the Mozilla Public
+
+/* 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 "2D.h"
 #include "Swizzle.h"
 
 #ifdef USE_CAIRO
 #include "DrawTargetCairo.h"
@@ -43,16 +43,17 @@
 #include "ScaledFontDWrite.h"
 #include "NativeFontResourceDWrite.h"
 #include <d3d10_1.h>
 #include "HelpersD2D.h"
 #include "HelpersWinFonts.h"
 #include "mozilla/Mutex.h"
 #endif
 
+#include "DrawTargetCapture.h"
 #include "DrawTargetDual.h"
 #include "DrawTargetTiled.h"
 #include "DrawTargetWrapAndRecord.h"
 #include "DrawTargetRecording.h"
 
 #include "SourceSurfaceRawData.h"
 
 #include "DrawEventRecorder.h"
@@ -413,16 +414,22 @@ Factory::CreateWrapAndRecordDrawTarget(D
 }
 
 already_AddRefed<DrawTarget>
 Factory::CreateRecordingDrawTarget(DrawEventRecorder *aRecorder, DrawTarget *aDT, IntSize aSize)
 {
   return MakeAndAddRef<DrawTargetRecording>(aRecorder, aDT, aSize);
 }
 
+already_AddRefed<DrawTargetCapture>
+Factory::CreateCaptureDrawTarget(BackendType aBackend, const IntSize& aSize, SurfaceFormat aFormat)
+{
+  return MakeAndAddRef<DrawTargetCaptureImpl>(aBackend, aSize, aFormat);
+}
+
 already_AddRefed<DrawTarget>
 Factory::CreateDrawTargetForData(BackendType aBackend,
                                  unsigned char *aData,
                                  const IntSize &aSize,
                                  int32_t aStride,
                                  SurfaceFormat aFormat,
                                  bool aUninitialized)
 {
--- a/gfx/layers/apz/src/APZCTreeManager.cpp
+++ b/gfx/layers/apz/src/APZCTreeManager.cpp
@@ -847,16 +847,18 @@ APZCTreeManager::PrepareNodeForLayer(con
       }
       if (aMetrics.IsRootContent()) {
         aState.mPaintLogger.LogTestData(aMetrics.GetScrollId(),
             "isRootContent", true);
       }
       // Note that the async scroll offset is in ParentLayer pixels
       aState.mPaintLogger.LogTestData(aMetrics.GetScrollId(), "asyncScrollOffset",
           apzc->GetCurrentAsyncScrollOffset(AsyncPanZoomController::eForHitTesting));
+      aState.mPaintLogger.LogTestData(aMetrics.GetScrollId(), "hasAsyncKeyScrolled",
+          apzc->TestHasAsyncKeyScrolled());
     }
 
     if (newApzc) {
       auto it = mZoomConstraints.find(guid);
       if (it != mZoomConstraints.end()) {
         // We have a zoomconstraints for this guid, apply it.
         apzc->UpdateZoomConstraints(it->second);
       } else if (!apzc->HasNoParentWithSameLayersId()) {
--- a/gfx/layers/apz/src/AsyncPanZoomController.cpp
+++ b/gfx/layers/apz/src/AsyncPanZoomController.cpp
@@ -732,16 +732,17 @@ AsyncPanZoomController::AsyncPanZoomCont
      mOverscrollEffect(MakeUnique<OverscrollEffect>(*this)),
      mState(NOTHING),
      mNotificationBlockers(0),
      mInputQueue(aInputQueue),
      mPinchPaintTimerSet(false),
      mAPZCId(sAsyncPanZoomControllerCount++),
      mSharedLock(nullptr),
      mAsyncTransformAppliedToContent(false),
+     mTestHasAsyncKeyScrolled(false),
      mCheckerboardEventLock("APZCBELock")
 {
   if (aGestures == USE_GESTURE_DETECTOR) {
     mGestureEventListener = new GestureEventListener(this);
   }
 }
 
 AsyncPanZoomController::~AsyncPanZoomController()
@@ -1698,16 +1699,19 @@ void ReportKeyboardScrollAction(const Ke
 }
 
 nsEventStatus
 AsyncPanZoomController::OnKeyboard(const KeyboardInput& aEvent)
 {
   // Report the type of scroll action to telemetry
   ReportKeyboardScrollAction(aEvent.mAction);
 
+  // Mark that this APZC has async key scrolled
+  mTestHasAsyncKeyScrolled = true;
+
   // Calculate the destination for this keyboard scroll action
   CSSPoint destination = GetKeyboardDestination(aEvent.mAction);
   nsIScrollableFrame::ScrollUnit scrollUnit = KeyboardScrollAction::GetScrollUnit(aEvent.mAction.mType);
 
   // The lock must be held across the entire update operation, so the
   // compositor doesn't end the animation before we get a chance to
   // update it.
   ReentrantMonitorAutoEnter lock(mMonitor);
--- a/gfx/layers/apz/src/AsyncPanZoomController.h
+++ b/gfx/layers/apz/src/AsyncPanZoomController.h
@@ -1211,16 +1211,24 @@ private:
 
 
   /* ===================================================================
    * The functions and members in this section are used for testing
    * and assertion purposes only.
    */
 public:
   /**
+   * Gets whether this APZC has performed async key scrolling.
+   */
+  bool TestHasAsyncKeyScrolled() const
+  {
+    return mTestHasAsyncKeyScrolled;
+  }
+
+  /**
    * Set an extra offset for testing async scrolling.
    */
   void SetTestAsyncScrollOffset(const CSSPoint& aPoint)
   {
     mTestAsyncScrollOffset = aPoint;
   }
   /**
    * Set an extra offset for testing async scrolling.
@@ -1247,18 +1255,19 @@ public:
 
 private:
   // Extra offset to add to the async scroll position for testing
   CSSPoint mTestAsyncScrollOffset;
   // Extra zoom to include in the aync zoom for testing
   LayerToParentLayerScale mTestAsyncZoom;
   // Flag to track whether or not the APZ transform is not used. This
   // flag is recomputed for every composition frame.
-  bool mAsyncTransformAppliedToContent;
-
+  bool mAsyncTransformAppliedToContent : 1;
+  // Flag to track whether or not this APZC has ever async key scrolled.
+  bool mTestHasAsyncKeyScrolled : 1;
 
   /* ===================================================================
    * The functions and members in this section are used for checkerboard
    * recording.
    */
 private:
   // Helper function to update the in-progress checkerboard event, if any.
   void UpdateCheckerboardEvent(const MutexAutoLock& aProofOfLock,
--- a/gfx/layers/apz/src/FocusTarget.cpp
+++ b/gfx/layers/apz/src/FocusTarget.cpp
@@ -161,18 +161,18 @@ FocusTarget::FocusTarget(nsIPresShell* a
 
   // The content to scroll is either the focused element or the focus node of
   // the selection. It's difficult to determine if an element is an interactive
   // element requiring async keyboard scrolling to be disabled. So we only
   // allow async key scrolling based on the selection, which doesn't have
   // this problem and is more common.
   if (focusedContent) {
     FT_LOG("Creating nil target with seq=%" PRIu64 ", kl=%d (disabling for focusing an element)\n",
-           mFocusHasKeyEventListeners,
-           aFocusSequenceNumber);
+           aFocusSequenceNumber,
+           mFocusHasKeyEventListeners);
 
     mType = FocusTarget::eNone;
     return;
   }
 
   nsCOMPtr<nsIContent> selectedContent = presShell->GetSelectedContentForScrolling();
 
   // Gather the scrollable frames that would be scrolled in each direction
--- a/gfx/layers/apz/src/InputQueue.cpp
+++ b/gfx/layers/apz/src/InputQueue.cpp
@@ -573,25 +573,27 @@ InputQueue::FindBlockForId(uint64_t aInp
     if (queuedInput->Block()->GetBlockId() == aInputBlockId) {
       if (aOutFirstInput) {
         *aOutFirstInput = queuedInput->Input();
       }
       return queuedInput->Block();
     }
   }
 
-  CancelableBlockState* block = nullptr;
+  InputBlockState* block = nullptr;
   if (mActiveTouchBlock && mActiveTouchBlock->GetBlockId() == aInputBlockId) {
     block = mActiveTouchBlock.get();
   } else if (mActiveWheelBlock && mActiveWheelBlock->GetBlockId() == aInputBlockId) {
     block = mActiveWheelBlock.get();
   } else if (mActiveDragBlock && mActiveDragBlock->GetBlockId() == aInputBlockId) {
     block = mActiveDragBlock.get();
   } else if (mActivePanGestureBlock && mActivePanGestureBlock->GetBlockId() == aInputBlockId) {
     block = mActivePanGestureBlock.get();
+  } else if (mActiveKeyboardBlock && mActiveKeyboardBlock->GetBlockId() == aInputBlockId) {
+    block = mActiveKeyboardBlock.get();
   }
   // Since we didn't encounter this block while iterating through mQueuedInputs,
   // it must have no events associated with it at the moment.
   if (aOutFirstInput) {
     *aOutFirstInput = nullptr;
   }
   return block;
 }
@@ -744,16 +746,19 @@ InputQueue::ProcessQueue() {
     mActiveWheelBlock = nullptr;
   }
   if (CanDiscardBlock(mActiveDragBlock)) {
     mActiveDragBlock = nullptr;
   }
   if (CanDiscardBlock(mActivePanGestureBlock)) {
     mActivePanGestureBlock = nullptr;
   }
+  if (CanDiscardBlock(mActiveKeyboardBlock)) {
+    mActiveKeyboardBlock = nullptr;
+  }
 }
 
 bool
 InputQueue::CanDiscardBlock(InputBlockState* aBlock)
 {
   if (!aBlock ||
       (aBlock->AsCancelableBlock() && !aBlock->AsCancelableBlock()->IsReadyForHandling()) ||
       aBlock->MustStayActive()) {
@@ -783,13 +788,14 @@ InputQueue::Clear()
 {
   APZThreadUtils::AssertOnControllerThread();
 
   mQueuedInputs.Clear();
   mActiveTouchBlock = nullptr;
   mActiveWheelBlock = nullptr;
   mActiveDragBlock = nullptr;
   mActivePanGestureBlock = nullptr;
+  mActiveKeyboardBlock = nullptr;
   mLastActiveApzc = nullptr;
 }
 
 } // namespace layers
 } // namespace mozilla
--- a/gfx/layers/apz/test/mochitest/apz_test_utils.js
+++ b/gfx/layers/apz/test/mochitest/apz_test_utils.js
@@ -270,16 +270,20 @@ function isApzEnabled() {
     // All tests are required to have at least one assertion. Since APZ is
     // disabled, and the main test is presumably not going to run, we stick in
     // a dummy assertion here to keep the test passing.
     SimpleTest.ok(true, "APZ is not enabled; this test will be skipped");
   }
   return enabled;
 }
 
+function isKeyApzEnabled() {
+  return isApzEnabled() && SpecialPowers.getBoolPref("apz.keyboard.enabled");
+}
+
 // Despite what this function name says, this does not *directly* run the
 // provided continuation testFunction. Instead, it returns a function that
 // can be used to run the continuation. The extra level of indirection allows
 // it to be more easily added to a promise chain, like so:
 //   waitUntilApzStable().then(runContinuation(myTest));
 //
 // If you want to run the continuation directly, outside of a promise chain,
 // you can invoke the return value of this function, like so:
new file mode 100644
--- /dev/null
+++ b/gfx/layers/apz/test/mochitest/helper_key_scroll.html
@@ -0,0 +1,107 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1383365
+-->
+<head>
+  <meta charset="utf-8">
+  <title>Async key scrolling test, helper page</title>
+  <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+  <script type="application/javascript" src="/tests/SimpleTest/paint_listener.js"></script>
+  <script type="application/javascript" src="apz_test_utils.js"></script>
+  <script type="application/javascript">
+    var SimpleTest = window.opener.SimpleTest;
+
+    SimpleTest.waitForFocus(runTests, window);
+
+    // --------------------------------------------------------------------
+    // Async key scrolling test
+    //
+    // This test checks that a key scroll occurs asynchronously.
+    //
+    // The page contains a <div> that is large enough to make the page
+    // scrollable. We first synthesize a page down to scroll to the bottom
+    // of the page. Once we have reached the bottom of the page, we synthesize
+    // a page up to get us back to the top of the page.
+    //
+    // Once at the top, we request test data from APZ, rebuild the APZC tree
+    // structure, and use it to check that async key scrolling happened.
+    // --------------------------------------------------------------------
+
+    function runTests() {
+      // Sanity check
+      SimpleTest.is(checkHasAsyncKeyScrolled(false), false, "expected no async key scrolling before test");
+
+      // Send a key to initiate a page scroll to take us to the bottom of the
+      // page. This scroll is done synchronously because APZ doesn't have
+      // current focus state at page load.
+      window.addEventListener("scroll", waitForScrollBottom);
+      window.synthesizeKey("VK_END", {});
+    };
+
+    function waitForScrollBottom() {
+      if (window.scrollY < window.scrollYMax) {
+        return;
+      }
+      window.removeEventListener("scroll", waitForScrollBottom);
+
+      // Wait for scrolling to finish before dispatching the next key input or
+      // the default action won't occur.
+      waitForApzFlushedRepaints(function () {
+        // This scroll should be asynchronous now that the focus state is up to date.
+        window.addEventListener("scroll", waitForScrollTop);
+        window.synthesizeKey("VK_HOME", {});
+      });
+    };
+
+    function waitForScrollTop() {
+      if (window.scrollY > 0) {
+        return;
+      }
+      window.removeEventListener("scroll", waitForScrollTop);
+
+      // Wait for APZ to settle and then check that async scrolling happened.
+      waitForApzFlushedRepaints(function () {
+        SimpleTest.is(checkHasAsyncKeyScrolled(true), true, "expected async key scrolling after test");
+        window.opener.finishTest();
+      });
+    };
+
+    function checkHasAsyncKeyScrolled(requirePaints) {
+      // Get the compositor-side test data from nsIDOMWindowUtils.
+      var utils = SpecialPowers.getDOMWindowUtils(window);
+      var compositorTestData = utils.getCompositorAPZTestData();
+
+      if (requirePaints) {
+        SimpleTest.ok(compositorTestData.paints.length > 0,
+                      "expected at least one paint in compositor test data");
+      }
+
+      // Get the sequence number of the last paint on the compositor side.
+      // We do this before converting the APZ test data because the conversion
+      // loses the order of the paints.
+      var lastPaint = compositorTestData.paints[compositorTestData.paints.length - 1];
+      var lastPaintSeqNo = lastPaint.sequenceNumber;
+
+      // Convert the test data into a representation that's easier to navigate.
+      compositorTestData = convertTestData(compositorTestData);
+
+      // Reconstruct the APZC tree structure in the last paint.
+      var apzcTree = buildApzcTree(compositorTestData.paints[lastPaintSeqNo]);
+      var rcd = findRcdNode(apzcTree);
+
+      if (rcd) {
+        return rcd.hasAsyncKeyScrolled === "1";
+      } else {
+        SimpleTest.info("Last paint rcd is null");
+        return false;
+      }
+    }
+  </script>
+</head>
+<body style="height: 500px; overflow: scroll">
+  <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1383365">Async key scrolling test</a>
+  <!-- Put enough content into the page to make it have a nonzero scroll range -->
+  <div style="height: 5000px"></div>
+</body>
+</html>
--- a/gfx/layers/apz/test/mochitest/mochitest.ini
+++ b/gfx/layers/apz/test/mochitest/mochitest.ini
@@ -13,16 +13,17 @@
     helper_bug1346632.html
     helper_click.html
     helper_div_pan.html
     helper_drag_click.html
     helper_drag_scroll.html
     helper_iframe_pan.html
     helper_iframe1.html
     helper_iframe2.html
+    helper_key_scroll.html
     helper_long_tap.html
     helper_scroll_inactive_perspective.html
     helper_scroll_inactive_zindex.html
     helper_scroll_on_position_fixed.html
     helper_scroll_over_scrollbar.html
     helper_scrollto_tap.html
     helper_subframe_style.css
     helper_tall.html
@@ -48,16 +49,17 @@
   skip-if = (toolkit == 'android') # mouse events not supported on mobile
 [test_group_pointerevents.html]
 [test_group_touchevents.html]
 [test_group_wheelevents.html]
   skip-if = (toolkit == 'android') # wheel events not supported on mobile
 [test_group_zoom.html]
   skip-if = (toolkit != 'android') # only android supports zoom
 [test_interrupted_reflow.html]
+[test_key_scroll.html]
 [test_layerization.html]
   skip-if = (os == 'android') # wheel events not supported on mobile
 [test_scroll_inactive_bug1190112.html]
   skip-if = (os == 'android') # wheel events not supported on mobile
 [test_scroll_inactive_flattened_frame.html]
   skip-if = (os == 'android') # wheel events not supported on mobile
 [test_scroll_subframe_scrollbar.html]
   skip-if = (os == 'android') # wheel events not supported on mobile
new file mode 100644
--- /dev/null
+++ b/gfx/layers/apz/test/mochitest/test_key_scroll.html
@@ -0,0 +1,41 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1383365
+-->
+<head>
+  <meta charset="utf-8">
+  <title>Async key scrolling test</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <script type="application/javascript" src="apz_test_utils.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+  <script type="application/javascript">
+
+    if (isKeyApzEnabled()) {
+      SimpleTest.waitForExplicitFinish();
+
+      // Run the actual test in its own window, because it requires that the
+      // root APZC be scrollable. Mochitest pages themselves often run
+      // inside an iframe which means we have no control over the root APZC.
+      var w = null;
+      window.onload = function() {
+        pushPrefs([["apz.test.logging_enabled", true],
+                   ["test.events.async.enabled", true]]).then(function() {
+          w = window.open("helper_key_scroll.html", "_blank");
+        });
+      };
+    } else {
+      SimpleTest.ok(true, "Keyboard APZ is disabled");
+    }
+
+    function finishTest() {
+      w.close();
+      SimpleTest.finish();
+    };
+
+  </script>
+</head>
+<body>
+  <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1383365">Async key scrolling test</a>
+</body>
+</html>
--- a/gfx/layers/client/ClientPaintedLayer.cpp
+++ b/gfx/layers/client/ClientPaintedLayer.cpp
@@ -199,26 +199,24 @@ ClientPaintedLayer::PaintOffMainThread()
   while (DrawTarget* target = mContentClient->BorrowDrawTargetForPainting(state, &iter)) {
     if (!target || !target->IsValid()) {
       if (target) {
         mContentClient->ReturnDrawTargetToBuffer(target);
       }
       continue;
     }
 
-    RefPtr<DrawTarget> refDT =
-      Factory::CreateDrawTarget(gfxPlatform::GetPlatform()->GetDefaultContentBackend(),
-                                target->GetSize(), target->GetFormat());
-
     // We don't clear the rect here like WRPaintedBlobLayers do
     // because ContentClient already clears the surface for us during BeginPaint.
-    RefPtr<DrawTargetCapture> captureDT = refDT->CreateCaptureDT(target->GetSize());
+    RefPtr<DrawTargetCapture> captureDT =
+      Factory::CreateCaptureDrawTarget(target->GetBackendType(),
+                                       target->GetSize(),
+                                       target->GetFormat());
     captureDT->SetTransform(target->GetTransform());
 
-    SetAntialiasingFlags(this, refDT);
     SetAntialiasingFlags(this, captureDT);
     SetAntialiasingFlags(this, target);
 
     RefPtr<gfxContext> ctx = gfxContext::CreatePreservingTransformOrNull(captureDT);
     MOZ_ASSERT(ctx); // already checked the target above
 
     ClientManager()->GetPaintedLayerCallback()(this,
                                               ctx,
--- a/gfx/layers/ipc/CompositorBridgeParent.cpp
+++ b/gfx/layers/ipc/CompositorBridgeParent.cpp
@@ -1952,34 +1952,34 @@ CompositorBridgeParent::NotifyDidComposi
   }
   mWrBridge->CompositableHolder()->Update(aPipelineId, aEpoch);
 
   if (mPaused) {
     return;
   }
 
   if (mWrBridge->PipelineId() == aPipelineId) {
-    uint64_t transactionId = mWrBridge->FlushTransactionIdsForEpoch(aEpoch);
+    uint64_t transactionId = mWrBridge->FlushTransactionIdsForEpoch(aEpoch, aCompositeEnd);
     Unused << SendDidComposite(0, transactionId, aCompositeStart, aCompositeEnd);
 
     nsTArray<ImageCompositeNotificationInfo> notifications;
     mWrBridge->ExtractImageCompositeNotifications(&notifications);
     if (!notifications.IsEmpty()) {
       Unused << ImageBridgeParent::NotifyImageComposites(notifications);
     }
     return;
   }
 
   MonitorAutoLock lock(*sIndirectLayerTreesLock);
   ForEachIndirectLayerTree([&] (LayerTreeState* lts, const uint64_t& aLayersId) -> void {
     if (lts->mCrossProcessParent &&
         lts->mWrBridge &&
         lts->mWrBridge->PipelineId() == aPipelineId) {
       CrossProcessCompositorBridgeParent* cpcp = lts->mCrossProcessParent;
-      uint64_t transactionId = lts->mWrBridge->FlushTransactionIdsForEpoch(aEpoch);
+      uint64_t transactionId = lts->mWrBridge->FlushTransactionIdsForEpoch(aEpoch, aCompositeEnd);
       Unused << cpcp->SendDidComposite(aLayersId, transactionId, aCompositeStart, aCompositeEnd);
     }
   });
 }
 
 void
 CompositorBridgeParent::NotifyDidComposite(uint64_t aTransactionId, TimeStamp& aCompositeStart, TimeStamp& aCompositeEnd)
 {
--- a/gfx/layers/ipc/PWebRenderBridge.ipdl
+++ b/gfx/layers/ipc/PWebRenderBridge.ipdl
@@ -51,20 +51,20 @@ parent:
                    SurfaceFormat aFormat, ByteBuffer aBytes);
   async DeleteImage(ImageKey aImageKey);
   async DeleteCompositorAnimations(uint64_t[] aIds);
   async AddRawFont(FontKey aFontKey, ByteBuffer aBytes, uint32_t aFontIndex);
   async DeleteFont(FontKey aFontKey);
   async DPBegin(IntSize aSize);
   async DPEnd(IntSize aSize, WebRenderParentCommand[] commands, OpDestroy[] toDestroy, uint64_t fwdTransactionId, uint64_t transactionId,
               LayoutSize aContentSize, ByteBuffer aDL, BuiltDisplayListDescriptor aDLDesc,
-              WebRenderScrollData aScrollData, uint32_t idNameSpace);
+              WebRenderScrollData aScrollData, uint32_t idNameSpace, TimeStamp fwdTime);
   sync DPSyncEnd(IntSize aSize, WebRenderParentCommand[] commands, OpDestroy[] toDestroy, uint64_t fwdTransactionId, uint64_t transactionId,
                  LayoutSize aContentSize, ByteBuffer aDL, BuiltDisplayListDescriptor aDLDesc,
-                 WebRenderScrollData aScrollData, uint32_t idNameSpace);
+                 WebRenderScrollData aScrollData, uint32_t idNameSpace, TimeStamp fwdTime);
   async ParentCommands(WebRenderParentCommand[] commands);
   sync DPGetSnapshot(PTexture texture);
   async AddPipelineIdForAsyncCompositable(PipelineId aImageId, CompositableHandle aHandle);
   async RemovePipelineIdForAsyncCompositable(PipelineId aPipelineId);
   async AddExternalImageIdForCompositable(ExternalImageId aImageId, CompositableHandle aHandle);
   async RemoveExternalImageId(ExternalImageId aImageId);
   async SetLayerObserverEpoch(uint64_t layerObserverEpoch);
   async ClearCachedResources();
--- a/gfx/layers/wr/WebRenderBridgeChild.cpp
+++ b/gfx/layers/wr/WebRenderBridgeChild.cpp
@@ -107,22 +107,27 @@ WebRenderBridgeChild::DPEnd(wr::DisplayL
   MOZ_ASSERT(!mDestroyed);
   MOZ_ASSERT(mIsInTransaction);
 
   wr::BuiltDisplayList dl;
   wr::LayoutSize contentSize;
   aBuilder.Finalize(contentSize, dl);
   ByteBuffer dlData(Move(dl.dl));
 
+  TimeStamp fwdTime;
+#if defined(ENABLE_FRAME_LATENCY_LOG)
+  fwdTime = TimeStamp::Now();
+#endif
+
   if (aIsSync) {
     this->SendDPSyncEnd(aSize, mParentCommands, mDestroyedActors, GetFwdTransactionId(), aTransactionId,
-                        contentSize, dlData, dl.dl_desc, aScrollData, mIdNamespace);
+                        contentSize, dlData, dl.dl_desc, aScrollData, mIdNamespace,fwdTime);
   } else {
     this->SendDPEnd(aSize, mParentCommands, mDestroyedActors, GetFwdTransactionId(), aTransactionId,
-                    contentSize, dlData, dl.dl_desc, aScrollData, mIdNamespace);
+                    contentSize, dlData, dl.dl_desc, aScrollData, mIdNamespace, fwdTime);
   }
 
   mParentCommands.Clear();
   mDestroyedActors.Clear();
   mIsInTransaction = false;
 }
 
 void
--- a/gfx/layers/wr/WebRenderBridgeParent.cpp
+++ b/gfx/layers/wr/WebRenderBridgeParent.cpp
@@ -399,17 +399,18 @@ WebRenderBridgeParent::HandleDPEnd(const
                                  InfallibleTArray<WebRenderParentCommand>&& aCommands,
                                  InfallibleTArray<OpDestroy>&& aToDestroy,
                                  const uint64_t& aFwdTransactionId,
                                  const uint64_t& aTransactionId,
                                  const wr::LayoutSize& aContentSize,
                                  const wr::ByteBuffer& dl,
                                  const wr::BuiltDisplayListDescriptor& dlDesc,
                                  const WebRenderScrollData& aScrollData,
-                                 const uint32_t& aIdNameSpace)
+                                 const uint32_t& aIdNameSpace,
+                                 const TimeStamp& aFwdTime)
 {
   AutoProfilerTracing tracing("Paint", "DPTransaction");
   UpdateFwdTransactionId(aFwdTransactionId);
   AutoClearReadLocks clearLocks(mReadLocks);
 
   if (mDestroyed) {
     for (const auto& op : aToDestroy) {
       DestroyActor(op);
@@ -418,17 +419,17 @@ WebRenderBridgeParent::HandleDPEnd(const
   }
   // This ensures that destroy operations are always processed. It is not safe
   // to early-return from RecvDPEnd without doing so.
   AutoWebRenderBridgeParentAsyncMessageSender autoAsyncMessageSender(this, &aToDestroy);
 
   uint32_t wrEpoch = GetNextWrEpoch();
   ProcessWebRenderCommands(aSize, aCommands, wr::NewEpoch(wrEpoch),
                            aContentSize, dl, dlDesc, aIdNameSpace);
-  HoldPendingTransactionId(wrEpoch, aTransactionId);
+  HoldPendingTransactionId(wrEpoch, aTransactionId, aFwdTime);
 
   mScrollData = aScrollData;
   UpdateAPZ();
 
   if (mIdNameSpace != aIdNameSpace) {
     // Pretend we composited since someone is wating for this event,
     // though DisplayList was not pushed to webrender.
     TimeStamp now = TimeStamp::Now();
@@ -512,43 +513,45 @@ WebRenderBridgeParent::RecvDPEnd(const g
                                  InfallibleTArray<WebRenderParentCommand>&& aCommands,
                                  InfallibleTArray<OpDestroy>&& aToDestroy,
                                  const uint64_t& aFwdTransactionId,
                                  const uint64_t& aTransactionId,
                                  const wr::LayoutSize& aContentSize,
                                  const wr::ByteBuffer& dl,
                                  const wr::BuiltDisplayListDescriptor& dlDesc,
                                  const WebRenderScrollData& aScrollData,
-                                 const uint32_t& aIdNameSpace)
+                                 const uint32_t& aIdNameSpace,
+                                 const TimeStamp& aFwdTime)
 {
   if (mDestroyed) {
     return IPC_OK();
   }
   HandleDPEnd(aSize, Move(aCommands), Move(aToDestroy), aFwdTransactionId, aTransactionId,
-              aContentSize, dl, dlDesc, aScrollData, aIdNameSpace);
+              aContentSize, dl, dlDesc, aScrollData, aIdNameSpace, aFwdTime);
   return IPC_OK();
 }
 
 mozilla::ipc::IPCResult
 WebRenderBridgeParent::RecvDPSyncEnd(const gfx::IntSize &aSize,
                                      InfallibleTArray<WebRenderParentCommand>&& aCommands,
                                      InfallibleTArray<OpDestroy>&& aToDestroy,
                                      const uint64_t& aFwdTransactionId,
                                      const uint64_t& aTransactionId,
                                      const wr::LayoutSize& aContentSize,
                                      const wr::ByteBuffer& dl,
                                      const wr::BuiltDisplayListDescriptor& dlDesc,
                                      const WebRenderScrollData& aScrollData,
-                                     const uint32_t& aIdNameSpace)
+                                     const uint32_t& aIdNameSpace,
+                                     const TimeStamp& aFwdTime)
 {
   if (mDestroyed) {
     return IPC_OK();
   }
   HandleDPEnd(aSize, Move(aCommands), Move(aToDestroy), aFwdTransactionId, aTransactionId,
-              aContentSize, dl, dlDesc, aScrollData, aIdNameSpace);
+              aContentSize, dl, dlDesc, aScrollData, aIdNameSpace, aFwdTime);
   return IPC_OK();
 }
 
 mozilla::ipc::IPCResult
 WebRenderBridgeParent::RecvParentCommands(nsTArray<WebRenderParentCommand>&& aCommands)
 {
   if (mDestroyed) {
     return IPC_OK();
@@ -1119,43 +1122,48 @@ WebRenderBridgeParent::CompositeToTarget
   }
 
   if (PushAPZStateToWR(transformArray)) {
     scheduleComposite = true;
   }
 
   wr::RenderThread::Get()->IncPendingFrameCount(mApi->GetId());
 
+#if defined(ENABLE_FRAME_LATENCY_LOG)
+  auto startTime = TimeStamp::Now();
+  mApi->SetFrameStartTime(startTime);
+#endif
+
   if (!transformArray.IsEmpty() || !opacityArray.IsEmpty()) {
     mApi->GenerateFrame(opacityArray, transformArray);
   } else {
     mApi->GenerateFrame();
   }
 
   if (!mCompositableHolder->GetCompositeUntilTime().IsNull()) {
     scheduleComposite = true;
   }
 
   if (scheduleComposite) {
     ScheduleComposition();
   }
 }
 
 void
-WebRenderBridgeParent::HoldPendingTransactionId(uint32_t aWrEpoch, uint64_t aTransactionId)
+WebRenderBridgeParent::HoldPendingTransactionId(uint32_t aWrEpoch, uint64_t aTransactionId, const TimeStamp& aFwdTime)
 {
   // The transaction ID might get reset to 1 if the page gets reloaded, see
   // https://bugzilla.mozilla.org/show_bug.cgi?id=1145295#c41
   // Otherwise, it should be continually increasing.
   MOZ_ASSERT(aTransactionId == 1 || aTransactionId > LastPendingTransactionId());
   // Handle TransactionIdAllocator(RefreshDriver) change.
   if (aTransactionId == 1) {
     FlushPendingTransactionIds();
   }
-  mPendingTransactionIds.push(PendingTransactionId(wr::NewEpoch(aWrEpoch), aTransactionId));
+  mPendingTransactionIds.push(PendingTransactionId(wr::NewEpoch(aWrEpoch), aTransactionId, aFwdTime));
 }
 
 uint64_t
 WebRenderBridgeParent::LastPendingTransactionId()
 {
   uint64_t id = 0;
   if (!mPendingTransactionIds.empty()) {
     id = mPendingTransactionIds.back().mId;
@@ -1170,25 +1178,32 @@ WebRenderBridgeParent::FlushPendingTrans
   while (!mPendingTransactionIds.empty()) {
     id = mPendingTransactionIds.front().mId;
     mPendingTransactionIds.pop();
   }
   return id;
 }
 
 uint64_t
-WebRenderBridgeParent::FlushTransactionIdsForEpoch(const wr::Epoch& aEpoch)
+WebRenderBridgeParent::FlushTransactionIdsForEpoch(const wr::Epoch& aEpoch, const TimeStamp& aEndTime)
 {
   uint64_t id = 0;
   while (!mPendingTransactionIds.empty()) {
     int64_t diff =
       static_cast<int64_t>(aEpoch.mHandle) - static_cast<int64_t>(mPendingTransactionIds.front().mEpoch.mHandle);
     if (diff < 0) {
       break;
     }
+#if defined(ENABLE_FRAME_LATENCY_LOG)
+    if (mPendingTransactionIds.front().mFwdTime) {
+      uint32_t latencyMs = round((aEndTime - mPendingTransactionIds.front().mFwdTime).ToMilliseconds());
+      printf_stderr("From EndTransaction to end of generate frame latencyMs %d this %p\n", latencyMs, this);
+    }
+#endif
+
     id = mPendingTransactionIds.front().mId;
     mPendingTransactionIds.pop();
     if (diff == 0) {
       break;
     }
   }
   return id;
 }
--- a/gfx/layers/wr/WebRenderBridgeParent.h
+++ b/gfx/layers/wr/WebRenderBridgeParent.h
@@ -97,27 +97,29 @@ public:
                                     InfallibleTArray<WebRenderParentCommand>&& aCommands,
                                     InfallibleTArray<OpDestroy>&& aToDestroy,
                                     const uint64_t& aFwdTransactionId,
                                     const uint64_t& aTransactionId,
                                     const wr::LayoutSize& aContentSize,
                                     const wr::ByteBuffer& dl,
                                     const wr::BuiltDisplayListDescriptor& dlDesc,
                                     const WebRenderScrollData& aScrollData,
-                                    const uint32_t& aIdNameSpace) override;
+                                    const uint32_t& aIdNameSpace,
+                                    const TimeStamp& aFwdTime) override;
   mozilla::ipc::IPCResult RecvDPSyncEnd(const gfx::IntSize& aSize,
                                         InfallibleTArray<WebRenderParentCommand>&& aCommands,
                                         InfallibleTArray<OpDestroy>&& aToDestroy,
                                         const uint64_t& aFwdTransactionId,
                                         const uint64_t& aTransactionId,
                                         const wr::LayoutSize& aContentSize,
                                         const wr::ByteBuffer& dl,
                                         const wr::BuiltDisplayListDescriptor& dlDesc,
                                         const WebRenderScrollData& aScrollData,
-                                        const uint32_t& aIdNameSpace) override;
+                                        const uint32_t& aIdNameSpace,
+                                        const TimeStamp& aFwdTime) override;
   mozilla::ipc::IPCResult RecvParentCommands(nsTArray<WebRenderParentCommand>&& commands) override;
   mozilla::ipc::IPCResult RecvDPGetSnapshot(PTextureParent* aTexture) override;
 
   mozilla::ipc::IPCResult RecvAddPipelineIdForAsyncCompositable(const wr::PipelineId& aPipelineIds,
                                                                 const CompositableHandle& aHandle) override;
   mozilla::ipc::IPCResult RecvRemovePipelineIdForAsyncCompositable(const wr::PipelineId& aPipelineId) override;
 
   mozilla::ipc::IPCResult RecvAddExternalImageIdForCompositable(const ExternalImageId& aImageId,
@@ -162,20 +164,20 @@ public:
   // CompositableParentManager
   bool IsSameProcess() const override;
   base::ProcessId GetChildProcessId() override;
   void NotifyNotUsed(PTextureParent* aTexture, uint64_t aTransactionId) override;
   void SendAsyncMessage(const InfallibleTArray<AsyncParentMessageData>& aMessage) override;
   void SendPendingAsyncMessages() override;
   void SetAboutToSendAsyncMessages() override;
 
-  void HoldPendingTransactionId(uint32_t aWrEpoch, uint64_t aTransactionId);
+  void HoldPendingTransactionId(uint32_t aWrEpoch, uint64_t aTransactionId, const TimeStamp& aFwdTime);
   uint64_t LastPendingTransactionId();
   uint64_t FlushPendingTransactionIds();
-  uint64_t FlushTransactionIdsForEpoch(const wr::Epoch& aEpoch);
+  uint64_t FlushTransactionIdsForEpoch(const wr::Epoch& aEpoch, const TimeStamp& aEndTime);
 
   TextureFactoryIdentifier GetTextureFactoryIdentifier();
 
   void AppendImageCompositeNotification(const ImageCompositeNotificationInfo& aNotification)
   {
     MOZ_ASSERT(mWidget);
     mImageCompositeNotifications.AppendElement(aNotification);
   }
@@ -228,17 +230,18 @@ private:
                    InfallibleTArray<WebRenderParentCommand>&& aCommands,
                    InfallibleTArray<OpDestroy>&& aToDestroy,
                    const uint64_t& aFwdTransactionId,
                    const uint64_t& aTransactionId,
                    const wr::LayoutSize& aContentSize,
                    const wr::ByteBuffer& dl,
                    const wr::BuiltDisplayListDescriptor& dlDesc,
                    const WebRenderScrollData& aScrollData,
-                   const uint32_t& aIdNameSpace);
+                   const uint32_t& aIdNameSpace,
+                   const TimeStamp& aFwdTime);
   mozilla::ipc::IPCResult HandleShutdown();
 
   void AdvanceAnimations();
   void SampleAnimations(nsTArray<wr::WrOpacityProperty>& aOpacityArray,
                         nsTArray<wr::WrTransformProperty>& aTransformArray);
 
   CompositorBridgeParent* GetRootCompositorBridgeParent() const;
 
@@ -251,22 +254,24 @@ private:
   // Helper method to get an APZC reference from a scroll id. Uses the layers
   // id of this bridge, and may return null if the APZC wasn't found.
   already_AddRefed<AsyncPanZoomController> GetTargetAPZC(const FrameMetrics::ViewID& aId);
 
   uint32_t GetNextWrEpoch();
 
 private:
   struct PendingTransactionId {
-    PendingTransactionId(wr::Epoch aEpoch, uint64_t aId)
+    PendingTransactionId(wr::Epoch aEpoch, uint64_t aId, const TimeStamp& aFwdTime)
       : mEpoch(aEpoch)
       , mId(aId)
+      , mFwdTime(aFwdTime)
     {}
     wr::Epoch mEpoch;
     uint64_t mId;
+    TimeStamp mFwdTime;
   };
 
   CompositorBridgeParentBase* MOZ_NON_OWNING_REF mCompositorBridge;
   wr::PipelineId mPipelineId;
   RefPtr<widget::CompositorWidget> mWidget;
   RefPtr<wr::WebRenderAPI> mApi;
   RefPtr<WebRenderCompositableHolder> mCompositableHolder;
   RefPtr<CompositorVsyncScheduler> mCompositorScheduler;
--- a/gfx/thebes/gfxFT2Utils.h
+++ b/gfx/thebes/gfxFT2Utils.h
@@ -15,16 +15,23 @@
 // part and low 6 bits for the fractional part. 
 #define FLOAT_FROM_26_6(x) ((x) / 64.0)
 #define FLOAT_FROM_16_16(x) ((x) / 65536.0)
 #define ROUND_26_6_TO_INT(x) ((x) >= 0 ?  ((32 + (x)) >> 6) \
                                        : -((32 - (x)) >> 6))
 
 typedef struct FT_FaceRec_* FT_Face;
 
+/**
+ * BEWARE: Recursively locking with gfxFT2LockedFace is not supported.
+ * Do not instantiate gfxFT2LockedFace within the scope of another instance.
+ * Do not attempt to call into Cairo within the scope of gfxFT2LockedFace,
+ * as that may accidentally try to re-lock the face within Cairo itself
+ * and thus deadlock.
+ */
 class gfxFT2LockedFace {
 public:
     explicit gfxFT2LockedFace(gfxFT2FontBase *aFont) :
         mGfxFont(aFont),
         mFace(cairo_ft_scaled_font_lock_face(aFont->CairoScaledFont()))
     { }
     ~gfxFT2LockedFace()
     {
--- a/gfx/webrender_bindings/RendererOGL.cpp
+++ b/gfx/webrender_bindings/RendererOGL.cpp
@@ -127,16 +127,25 @@ RendererOGL::Render()
   // XXX set clear color if MOZ_WIDGET_ANDROID is defined.
 
   auto size = mWidget->GetClientSize();
   wr_renderer_render(mRenderer, size.width, size.height);
 
   mGL->SwapBuffers();
   mWidget->PostRender(&widgetContext);
 
+#if defined(ENABLE_FRAME_LATENCY_LOG)
+  if (mFrameStartTime) {
+    uint32_t latencyMs = round((TimeStamp::Now() - mFrameStartTime).ToMilliseconds());
+    printf_stderr("generate frame latencyMs latencyMs %d\n", latencyMs);
+  }
+  // Clear frame start time
+  mFrameStartTime = TimeStamp();
+#endif
+
   // TODO: Flush pending actions such as texture deletions/unlocks and
   //       textureHosts recycling.
 
   return true;
 }
 
 void
 RendererOGL::Pause()
@@ -165,16 +174,27 @@ RendererOGL::Resume()
 }
 
 void
 RendererOGL::SetProfilerEnabled(bool aEnabled)
 {
   wr_renderer_set_profiler_enabled(mRenderer, aEnabled);
 }
 
+void
+RendererOGL::SetFrameStartTime(const TimeStamp& aTime)
+{
+  if (mFrameStartTime) {
+    // frame start time is already set. This could happen when multiple
+    // generate frame requests are merged by webrender.
+    return;
+  }
+  mFrameStartTime = aTime;
+}
+
 wr::WrRenderedEpochs*
 RendererOGL::FlushRenderedEpochs()
 {
   return wr_renderer_flush_rendered_epochs(mRenderer);
 }
 
 RenderTextureHost*
 RendererOGL::GetRenderTexture(wr::WrExternalImageId aExternalImageId)
--- a/gfx/webrender_bindings/RendererOGL.h
+++ b/gfx/webrender_bindings/RendererOGL.h
@@ -54,16 +54,19 @@ public:
 
   /// This can be called on the render thread only.
   bool RenderToTarget(gfx::DrawTarget& aTarget);
 
   /// This can be called on the render thread only.
   void SetProfilerEnabled(bool aEnabled);
 
   /// This can be called on the render thread only.
+  void SetFrameStartTime(const TimeStamp& aTime);
+
+  /// This can be called on the render thread only.
   ~RendererOGL();
 
   /// This can be called on the render thread only.
   RendererOGL(RefPtr<RenderThread>&& aThread,
               RefPtr<gl::GLContext>&& aGL,
               RefPtr<widget::CompositorWidget>&&,
               wr::WindowId aWindowId,
               wr::Renderer* aRenderer,
@@ -86,14 +89,15 @@ public:
 protected:
 
   RefPtr<RenderThread> mThread;
   RefPtr<gl::GLContext> mGL;
   RefPtr<widget::CompositorWidget> mWidget;
   wr::Renderer* mRenderer;
   layers::CompositorBridgeParentBase* mBridge;
   wr::WindowId mWindowId;
+  TimeStamp mFrameStartTime;
 };
 
 } // namespace wr
 } // namespace mozilla
 
 #endif
--- a/gfx/webrender_bindings/WebRenderAPI.cpp
+++ b/gfx/webrender_bindings/WebRenderAPI.cpp
@@ -505,16 +505,49 @@ private:
 
 void
 WebRenderAPI::SetProfilerEnabled(bool aEnabled)
 {
   auto event = MakeUnique<EnableProfiler>(aEnabled);
   RunOnRenderThread(Move(event));
 }
 
+class FrameStartTime : public RendererEvent
+{
+public:
+  explicit FrameStartTime(const TimeStamp& aTime)
+    : mTime(aTime)
+  {
+    MOZ_COUNT_CTOR(FrameStartTime);
+  }
+
+  ~FrameStartTime()
+  {
+    MOZ_COUNT_DTOR(FrameStartTime);
+  }
+
+  virtual void Run(RenderThread& aRenderThread, WindowId aWindowId) override
+  {
+    auto renderer = aRenderThread.GetRenderer(aWindowId);
+    if (renderer) {
+      renderer->SetFrameStartTime(mTime);
+    }
+  }
+
+private:
+  TimeStamp mTime;
+};
+
+void
+WebRenderAPI::SetFrameStartTime(const TimeStamp& aTime)
+{
+  auto event = MakeUnique<FrameStartTime>(aTime);
+  RunOnRenderThread(Move(event));
+}
+
 void
 WebRenderAPI::RunOnRenderThread(UniquePtr<RendererEvent> aEvent)
 {
   auto event = reinterpret_cast<uintptr_t>(aEvent.release());
   wr_api_send_external_event(mRenderApi, event);
 }
 
 DisplayListBuilder::DisplayListBuilder(PipelineId aId,
--- a/gfx/webrender_bindings/WebRenderAPI.h
+++ b/gfx/webrender_bindings/WebRenderAPI.h
@@ -96,16 +96,18 @@ public:
   void DeleteImage(wr::ImageKey aKey);
 
   void AddRawFont(wr::FontKey aKey, Range<uint8_t> aBytes, uint32_t aIndex);
 
   void DeleteFont(wr::FontKey aKey);
 
   void SetProfilerEnabled(bool aEnabled);
 
+  void SetFrameStartTime(const TimeStamp& aTime);
+
   void RunOnRenderThread(UniquePtr<RendererEvent> aEvent);
   void Readback(gfx::IntSize aSize, uint8_t *aBuffer, uint32_t aBufferSize);
 
   void Pause();
   bool Resume();
 
   wr::WrIdNamespace GetNamespace();
   GLint GetMaxTextureSize() const { return mMaxTextureSize; }
--- a/gfx/webrender_bindings/WebRenderTypes.h
+++ b/gfx/webrender_bindings/WebRenderTypes.h
@@ -12,16 +12,18 @@
 #include "mozilla/gfx/Types.h"
 #include "mozilla/gfx/Tools.h"
 #include "mozilla/layers/LayersTypes.h"
 #include "mozilla/Range.h"
 #include "Units.h"
 #include "RoundedRect.h"
 #include "nsStyleConsts.h"
 
+//#define ENABLE_FRAME_LATENCY_LOG
+
 namespace mozilla {
 namespace wr {
 
 typedef wr::WrWindowId WindowId;
 typedef wr::WrPipelineId PipelineId;
 typedef wr::WrImageKey ImageKey;
 typedef wr::WrFontKey FontKey;
 typedef wr::WrEpoch Epoch;
--- a/image/SourceBuffer.cpp
+++ b/image/SourceBuffer.cpp
@@ -616,17 +616,17 @@ SourceBuffer::AdvanceIteratorOrScheduleR
   if (MOZ_UNLIKELY(mStatus && NS_FAILED(*mStatus))) {
     // This SourceBuffer is complete due to an error; all reads fail.
     return aIterator.SetComplete(*mStatus);
   }
 
   if (MOZ_UNLIKELY(mChunks.Length() == 0)) {
     // We haven't gotten an initial chunk yet.
     AddWaitingConsumer(aConsumer);
-    return aIterator.SetWaiting();
+    return aIterator.SetWaiting(!!aConsumer);
   }
 
   uint32_t iteratorChunkIdx = aIterator.mData.mIterating.mChunk;
   MOZ_ASSERT(iteratorChunkIdx < mChunks.Length());
 
   const Chunk& currentChunk = mChunks[iteratorChunkIdx];
   size_t iteratorEnd = aIterator.mData.mIterating.mOffset +
                        aIterator.mData.mIterating.mAvailableLength;
@@ -654,17 +654,17 @@ SourceBuffer::AdvanceIteratorOrScheduleR
     // There's no more data and this SourceBuffer completed successfully.
     MOZ_ASSERT(NS_SUCCEEDED(*mStatus), "Handled failures earlier");
     return aIterator.SetComplete(*mStatus);
   }
 
   // We're not complete, but there's no more data right now. Arrange to wake up
   // the consumer when we get more data.
   AddWaitingConsumer(aConsumer);
-  return aIterator.SetWaiting();
+  return aIterator.SetWaiting(!!aConsumer);
 }
 
 nsresult
 SourceBuffer::HandleError(nsresult aError)
 {
   MOZ_ASSERT(NS_FAILED(aError), "Should have an error here");
   MOZ_ASSERT(aError == NS_ERROR_OUT_OF_MEMORY,
              "Unexpected error; may want to notify waiting readers, which "
--- a/image/SourceBuffer.h
+++ b/image/SourceBuffer.h
@@ -237,20 +237,24 @@ private:
     // Update metrics.
     mChunkCount++;
     mByteCount += aAvailableLength;
 
     // Attempt to advance by the requested number of bytes.
     return AdvanceFromLocalBuffer(aRequestedBytes);
   }
 
-  State SetWaiting()
+  State SetWaiting(bool aHasConsumer)
   {
     MOZ_ASSERT(mState != COMPLETE);
-    MOZ_ASSERT(mState != WAITING, "Did we get a spurious wakeup somehow?");
+    // Without a consumer, we won't know when to wake up precisely. Caller
+    // convention should mean that we don't try to advance unless we have
+    // written new data, but that doesn't mean we got enough.
+    MOZ_ASSERT(mState != WAITING || !aHasConsumer,
+               "Did we get a spurious wakeup somehow?");
     return mState = WAITING;
   }
 
   State SetComplete(nsresult aStatus)
   {
     mData.mAtEnd.mStatus = aStatus;
     return mState = COMPLETE;
   }
--- a/ipc/glue/ProtocolUtils.h
+++ b/ipc/glue/ProtocolUtils.h
@@ -592,45 +592,41 @@ public:
     Endpoint()
       : mValid(false)
     {}
 
     Endpoint(const PrivateIPDLInterface&,
              mozilla::ipc::Transport::Mode aMode,
              TransportDescriptor aTransport,
              ProcessId aMyPid,
-             ProcessId aOtherPid,
-             ProtocolId aProtocolId)
+             ProcessId aOtherPid)
       : mValid(true)
       , mMode(aMode)
       , mTransport(aTransport)
       , mMyPid(aMyPid)
       , mOtherPid(aOtherPid)
-      , mProtocolId(aProtocolId)
     {}
 
     Endpoint(Endpoint&& aOther)
       : mValid(aOther.mValid)
       , mMode(aOther.mMode)
       , mTransport(aOther.mTransport)
       , mMyPid(aOther.mMyPid)
       , mOtherPid(aOther.mOtherPid)
-      , mProtocolId(aOther.mProtocolId)
     {
         aOther.mValid = false;
     }
 
     Endpoint& operator=(Endpoint&& aOther)
     {
         mValid = aOther.mValid;
         mMode = aOther.mMode;
         mTransport = aOther.mTransport;
         mMyPid = aOther.mMyPid;
         mOtherPid = aOther.mOtherPid;
-        mProtocolId = aOther.mProtocolId;
 
         aOther.mValid = false;
         return *this;
     }
 
     ~Endpoint() {
         if (mValid) {
             CloseDescriptor(mTransport);
@@ -670,53 +666,50 @@ private:
 
     Endpoint(const Endpoint&) = delete;
     Endpoint& operator=(const Endpoint&) = delete;
 
     bool mValid;
     mozilla::ipc::Transport::Mode mMode;
     TransportDescriptor mTransport;
     ProcessId mMyPid, mOtherPid;
-    ProtocolId mProtocolId;
 };
 
 #if defined(MOZ_CRASHREPORTER) && defined(XP_MACOSX)
 void AnnotateCrashReportWithErrno(const char* tag, int error);
 #else
 static inline void AnnotateCrashReportWithErrno(const char* tag, int error)
 {}
 #endif
 
 // This function is used internally to create a pair of Endpoints. See the
 // comment above Endpoint for a description of how it might be used.
 template<class PFooParent, class PFooChild>
 nsresult
 CreateEndpoints(const PrivateIPDLInterface& aPrivate,
                 base::ProcessId aParentDestPid,
                 base::ProcessId aChildDestPid,
-                ProtocolId aProtocol,
-                ProtocolId aChildProtocol,
                 Endpoint<PFooParent>* aParentEndpoint,
                 Endpoint<PFooChild>* aChildEndpoint)
 {
   MOZ_RELEASE_ASSERT(aParentDestPid);
   MOZ_RELEASE_ASSERT(aChildDestPid);
 
   TransportDescriptor parentTransport, childTransport;
   nsresult rv;
   if (NS_FAILED(rv = CreateTransport(aParentDestPid, &parentTransport, &childTransport))) {
     AnnotateCrashReportWithErrno("IpcCreateEndpointsNsresult", int(rv));
     return rv;
   }
 
   *aParentEndpoint = Endpoint<PFooParent>(aPrivate, mozilla::ipc::Transport::MODE_SERVER,
-                                          parentTransport, aParentDestPid, aChildDestPid, aProtocol);
+                                          parentTransport, aParentDestPid, aChildDestPid);
 
   *aChildEndpoint = Endpoint<PFooChild>(aPrivate, mozilla::ipc::Transport::MODE_CLIENT,
-                                        childTransport, aChildDestPid, aParentDestPid, aChildProtocol);
+                                        childTransport, aChildDestPid, aParentDestPid);
 
   return NS_OK;
 }
 
 void
 TableToArray(const nsTHashtable<nsPtrHashKey<void>>& aTable,
              nsTArray<void*>& aArray);
 
@@ -817,41 +810,38 @@ struct ParamTraits<mozilla::ipc::Endpoin
         // valid after the write. An alternative would be to set
         // aParam.mTransport.mValid to false, but that won't work because aParam
         // is const.
         mozilla::ipc::TransportDescriptor desc = mozilla::ipc::DuplicateDescriptor(aParam.mTransport);
         IPC::WriteParam(aMsg, desc);
 
         IPC::WriteParam(aMsg, aParam.mMyPid);
         IPC::WriteParam(aMsg, aParam.mOtherPid);
-        IPC::WriteParam(aMsg, static_cast<uint32_t>(aParam.mProtocolId));
     }
 
     static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
     {
         MOZ_RELEASE_ASSERT(!aResult->mValid);
 
         if (!IPC::ReadParam(aMsg, aIter, &aResult->mValid)) {
             return false;
         }
         if (!aResult->mValid) {
             // Object is empty, but read succeeded.
             return true;
         }
 
-        uint32_t mode, protocolId;
+        uint32_t mode;
         if (!IPC::ReadParam(aMsg, aIter, &mode) ||
             !IPC::ReadParam(aMsg, aIter, &aResult->mTransport) ||
             !IPC::ReadParam(aMsg, aIter, &aResult->mMyPid) ||
-            !IPC::ReadParam(aMsg, aIter, &aResult->mOtherPid) ||
-            !IPC::ReadParam(aMsg, aIter, &protocolId)) {
+            !IPC::ReadParam(aMsg, aIter, &aResult->mOtherPid)) {
             return false;
         }
         aResult->mMode = Channel::Mode(mode);
-        aResult->mProtocolId = mozilla::ipc::ProtocolId(protocolId);
         return true;
     }
 
     static void Log(const paramType& aParam, std::wstring* aLog)
     {
         aLog->append(StringPrintf(L"Endpoint"));
     }
 };
--- a/ipc/ipdl/ipdl.py
+++ b/ipc/ipdl/ipdl.py
@@ -203,17 +203,16 @@ print >>ipcmsgstart, """
 #ifndef IPCMessageStart_h
 #define IPCMessageStart_h
 
 enum IPCMessageStart {
 """
 
 for name in allprotocols:
     print >>ipcmsgstart, "  %s," % name
-    print >>ipcmsgstart, "  %sChild," % name
 
 print >>ipcmsgstart, """
   LastMsgIndex
 };
 
 static_assert(LastMsgIndex <= 65536, "need to update IPC_MESSAGE_MACRO");
 
 #endif // ifndef IPCMessageStart_h
--- a/ipc/ipdl/ipdl/lower.py
+++ b/ipc/ipdl/ipdl/lower.py
@@ -1630,18 +1630,16 @@ class _GenerateProtocolCode(ipdl.ast.Vis
                      Decl(Type('base::ProcessId'), childpidvar.name),
                      Decl(Type('mozilla::ipc::Endpoint<' + tparent.name + '>', ptr=1), parentvar.name),
                      Decl(Type('mozilla::ipc::Endpoint<' + tchild.name + '>', ptr=1), childvar.name) ],
             ret=rettype))
         openfunc.addstmt(StmtReturn(ExprCall(
             ExprVar('mozilla::ipc::CreateEndpoints'),
             args=[ _backstagePass(),
                    parentpidvar, childpidvar,
-                   _protocolId(p),
-                   ExprVar(_messageStartName(p) + 'Child'),
                    parentvar, childvar
                    ])))
         return openfunc
 
 
     def genTransitionFunc(self):
         ptype = self.protocol.decl.type
 
--- a/js/public/TrackedOptimizationInfo.h
+++ b/js/public/TrackedOptimizationInfo.h
@@ -206,17 +206,16 @@ namespace JS {
     _(CantInlineNotHot)                                                 \
     _(CantInlineNotInDispatch)                                          \
     _(CantInlineUnreachable)                                            \
     _(CantInlineNativeBadForm)                                          \
     _(CantInlineNativeBadType)                                          \
     _(CantInlineNativeNoTemplateObj)                                    \
     _(CantInlineBound)                                                  \
     _(CantInlineNativeNoSpecialization)                                 \
-    _(CantInlineNoObservedTypes)                                        \
     _(HasCommonInliningPath)                                            \
                                                                         \
     _(GenericSuccess)                                                   \
     _(Inlined)                                                          \
     _(DOM)                                                              \
     _(Monomorphic)                                                      \
     _(Polymorphic)
 
--- a/js/src/doc/Debugger/Debugger.Object.md
+++ b/js/src/doc/Debugger/Debugger.Object.md
@@ -170,16 +170,32 @@ from its prototype:
     bound function; `false` otherwise. If the referent is not a debuggee
     function, or not a function at all, returns `undefined` instead.
 
 `isArrowFunction`
 :   If the referent is a debuggee function, returns `true` if the referent is an
     arrow function; `false` otherwise. If the referent is not a debuggee
     function, or not a function at all, returns `undefined` instead.
 
+`isGeneratorFunction`
+:   If the referent is a debuggee function, returns `true` if the referent was
+    created with a `function*` expression or statement, or false if it is some
+    other sort of function. If the referent is not a debuggee function, or not a
+    function at all, this is `undefined`. (This is always equal to
+    `obj.script.isGeneratorFunction`, assuming `obj.script` is a
+    `Debugger.Script`.)
+
+`isAsyncFunction`
+:   If the referent is a debuggee function, returns `true` if the referent is an
+    async function, defined with an `async function` expression or statement, or
+    false if it is some other sort of function. If the referent is not a
+    debuggee function, or not a function at all, this is `undefined`. (This is
+    always equal to `obj.script.isAsyncFunction`, assuming `obj.script` is a
+    `Debugger.Script`.)
+
 `isPromise`
 :   `true` if the referent is a Promise; `false` otherwise.
 
 `boundTargetFunction`
 :   If the referent is a bound debuggee function, this is its target function—
     the function that was bound to a particular `this` object. If the referent
     is either not a bound function, not a debuggee function, or not a function
     at all, this is `undefined`.
--- a/js/src/doc/Debugger/Debugger.Script.md
+++ b/js/src/doc/Debugger/Debugger.Script.md
@@ -80,16 +80,24 @@ headed by "**if the instance refers to a
 refers to WebAssembly code**", respectively. If the behavior does not differ,
 no such emphasized headings will appear.
 
 ## Accessor Properties of the Debugger.Script Prototype Object
 
 A `Debugger.Script` instance inherits the following accessor properties
 from its prototype:
 
+`isGeneratorFunction`
+:   True if this instance refers to a `JSScript` for a function defined with a
+    `function*` expression or statement. False otherwise.
+
+`isAsyncFunction`
+:   True if this instance refers to a `JSScript` for an async function, defined
+    with an `async function` expression or statement. False otherwise.
+
 `displayName`
 :   **If the instance refers to a `JSScript`**, this is the script's display
     name, if it has one. If the script has no display name &mdash; for example,
     if it is a top-level `eval` script &mdash; this is `undefined`.
 
     If the script's function has a given name, its display name is the same as
     its function's given name.
 
--- a/js/src/frontend/Parser.cpp
+++ b/js/src/frontend/Parser.cpp
@@ -2924,16 +2924,20 @@ Parser<ParseHandler, CharT>::matchOrInse
          *
          * Detect this situation and throw an understandable error.  Otherwise
          * we'd throw a confusing "missing ; before statement" error.
          */
         if (!pc->isAsync() && tokenStream.currentToken().type == TOK_AWAIT) {
             error(JSMSG_AWAIT_OUTSIDE_ASYNC);
             return false;
         }
+        if (!yieldExpressionsSupported() && tokenStream.currentToken().type == TOK_YIELD) {
+            error(JSMSG_YIELD_OUTSIDE_GENERATOR);
+            return false;
+        }
 
         /* Advance the scanner for proper error location reporting. */
         tokenStream.consumeKnownToken(tt, modifier);
         error(JSMSG_SEMI_BEFORE_STMNT);
         return false;
     }
     bool matched;
     if (!tokenStream.matchToken(&matched, TOK_SEMI, modifier))
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/debug/isAsyncFunction-isGeneratorFunction.js
@@ -0,0 +1,54 @@
+// Debugger.Script.prototype.isAsyncFunction, Debugger.Object.prototype.isAsyncFunction,
+// Debugger.Script.prototype.isGeneratorFunction, Debugger.Object.prototype.isGeneratorFunction
+
+var g = newGlobal();
+var dbg = new Debugger();
+var gDO = dbg.addDebuggee(g);
+g.non_debuggee = function non_debuggee () {}
+
+function checkExpr(expr, { isAsync, isGenerator })
+{
+  print("Evaluating: " + uneval(expr));
+  let fn = gDO.executeInGlobal(expr).return;
+
+  assertEq(fn.isAsyncFunction, isAsync);
+  assertEq(fn.isGeneratorFunction, isGenerator);
+
+  // The Debugger.Object and its Debugger.Script should always agree.
+  if (fn.script) {
+    assertEq(fn.isAsyncFunction, fn.script.isAsyncFunction);
+    assertEq(fn.isGeneratorFunction, fn.script.isGeneratorFunction);
+  }
+}
+
+checkExpr('({})', { isAsync: undefined, isGenerator: undefined });
+checkExpr('non_debuggee', { isAsync: undefined, isGenerator: undefined });
+checkExpr('(function(){})', { isAsync: false, isGenerator: false });
+checkExpr('(function*(){})', { isAsync: false, isGenerator: true });
+checkExpr('(async function snerf(){})', { isAsync: true, isGenerator: false });
+checkExpr('(async function* omlu(){})', { isAsync: true, isGenerator: true });
+
+checkExpr('new Function("1+2")', { isAsync: false, isGenerator: false });
+checkExpr('Object.getPrototypeOf(function*(){}).constructor("1+2")',
+          { isAsync: false, isGenerator: true });
+checkExpr('Object.getPrototypeOf(async function(){}).constructor("1+2")',
+          { isAsync: true, isGenerator: false });
+checkExpr('Object.getPrototypeOf(async function*(){}).constructor("1+2")',
+          { isAsync: true, isGenerator: true });
+
+// Check eval scripts.
+function checkFrame(expr, type)
+{
+  var log = '';
+  dbg.onDebuggerStatement = function(frame) {
+    log += 'd';
+    assertEq(frame.type, type);
+    assertEq(frame.script.isAsyncFunction, false);
+    assertEq(frame.script.isGeneratorFunction, false);
+  }
+  gDO.executeInGlobal(expr);
+  assertEq(log, 'd');
+}
+
+checkFrame('debugger;', 'global');
+checkFrame('eval("debugger;")', 'eval');
--- a/js/src/jit/IonBuilder.cpp
+++ b/js/src/jit/IonBuilder.cpp
@@ -414,32 +414,21 @@ IonBuilder::canInlineTarget(JSFunction* 
         }
 
         for (size_t i = 0; i < callInfo.argc(); i++) {
             if (callInfo.getArg(i)->emptyResultTypeSet()) {
                 trackOptimizationOutcome(TrackedOutcome::CantInlineUnreachable);
                 return DontInline(nullptr, "Empty TypeSet for argument");
             }
         }
-
-        // If we're going to add a TypeBarrier that always fails, it's not
-        // worth inlining this call as the script will be invalidated
-        // immediately.
-        if ((CodeSpec[*pc].format & JOF_TYPESET) &&
-            !BytecodeIsPopped(pc) &&
-            bytecodeTypes(pc)->empty())
-        {
-            trackOptimizationOutcome(TrackedOutcome::CantInlineNoObservedTypes);
-            return DontInline(nullptr, "Empty type barrier");
-        }
     }
 
     // Allow constructing lazy scripts when performing the definite properties
     // analysis, as baseline has not been used to warm the caller up yet.
-    if (info().analysisMode() == Analysis_DefiniteProperties) {
+    if (target->isInterpreted() && info().analysisMode() == Analysis_DefiniteProperties) {
         RootedFunction fun(analysisContext, target);
         RootedScript script(analysisContext, JSFunction::getOrCreateScript(analysisContext, fun));
         if (!script)
             return InliningDecision_Error;
 
         if (!script->hasBaselineScript() && script->canBaselineCompile()) {
             MethodStatus status = BaselineCompile(analysisContext, script);
             if (status == Method_Error)
--- a/js/src/js.msg
+++ b/js/src/js.msg
@@ -348,16 +348,17 @@ MSG_DEF(JSMSG_UNTERMINATED_REGEXP,     0
 MSG_DEF(JSMSG_UNTERMINATED_STRING,     0, JSEXN_SYNTAXERR, "unterminated string literal")
 MSG_DEF(JSMSG_USELESS_EXPR,            0, JSEXN_TYPEERR, "useless expression")
 MSG_DEF(JSMSG_USE_ASM_DIRECTIVE_FAIL,  0, JSEXN_SYNTAXERR, "\"use asm\" is only meaningful in the Directive Prologue of a function body")
 MSG_DEF(JSMSG_VAR_HIDES_ARG,           1, JSEXN_TYPEERR, "variable {0} redeclares argument")
 MSG_DEF(JSMSG_WHILE_AFTER_DO,          0, JSEXN_SYNTAXERR, "missing while after do-loop body")
 MSG_DEF(JSMSG_YIELD_IN_ARROW,          0, JSEXN_SYNTAXERR, "arrow function may not contain yield")
 MSG_DEF(JSMSG_YIELD_IN_DEFAULT,        0, JSEXN_SYNTAXERR, "yield in default expression")
 MSG_DEF(JSMSG_YIELD_IN_METHOD,         0, JSEXN_SYNTAXERR, "non-generator method definitions may not contain yield")
+MSG_DEF(JSMSG_YIELD_OUTSIDE_GENERATOR, 0, JSEXN_SYNTAXERR, "yield expression is only valid in generators")
 MSG_DEF(JSMSG_BAD_COLUMN_NUMBER,       0, JSEXN_RANGEERR, "column number out of range")
 MSG_DEF(JSMSG_COMPUTED_NAME_IN_PATTERN,0, JSEXN_SYNTAXERR, "computed property names aren't supported in this destructuring declaration")
 MSG_DEF(JSMSG_DEFAULT_IN_PATTERN,      0, JSEXN_SYNTAXERR, "destructuring defaults aren't supported in this destructuring declaration")
 MSG_DEF(JSMSG_BAD_NEWTARGET,           0, JSEXN_SYNTAXERR, "new.target only allowed within functions")
 MSG_DEF(JSMSG_ESCAPED_KEYWORD,         0, JSEXN_SYNTAXERR, "keywords must be written literally, without embedded escapes")
 
 // asm.js
 MSG_DEF(JSMSG_USE_ASM_TYPE_FAIL,       1, JSEXN_TYPEERR, "asm.js type error: {0}")
--- a/js/src/jsgc.cpp
+++ b/js/src/jsgc.cpp
@@ -3082,18 +3082,17 @@ GCRuntime::maybeGC(Zone* zone)
 }
 
 void
 GCRuntime::triggerFullGCForAtoms(JSContext* cx)
 {
     MOZ_ASSERT(fullGCForAtomsRequested_);
     MOZ_ASSERT(CurrentThreadCanAccessRuntime(rt));
     MOZ_ASSERT(!JS::CurrentThreadIsHeapCollecting());
-    MOZ_ASSERT(!cx->keepAtoms);
-    MOZ_ASSERT(!rt->hasHelperThreadZones());
+    MOZ_ASSERT(cx->canCollectAtoms());
     fullGCForAtomsRequested_ = false;
     MOZ_RELEASE_ASSERT(triggerGC(JS::gcreason::DELAYED_ATOMS_GC));
 }
 
 // Do all possible decommit immediately from the current thread without
 // releasing the GC lock or allocating any memory.
 void
 GCRuntime::decommitAllWithoutUnlocking(const AutoLockGC& lock)
@@ -7381,16 +7380,25 @@ bool
 GCRuntime::gcIfRequested()
 {
     // This method returns whether a major GC was performed.
 
     if (nursery().minorGCRequested())
         minorGC(nursery().minorGCTriggerReason());
 
     if (majorGCRequested()) {
+        if (majorGCTriggerReason == JS::gcreason::DELAYED_ATOMS_GC &&
+            !TlsContext.get()->canCollectAtoms())
+        {
+            // A GC was requested to collect the atoms zone, but it's no longer
+            // possible. Skip this collection.
+            majorGCTriggerReason = JS::gcreason::NO_REASON;
+            return false;
+        }
+
         if (!isIncrementalGCInProgress())
             startGC(GC_NORMAL, majorGCTriggerReason);
         else
             gcSlice(majorGCTriggerReason);
         return true;
     }
 
     return false;
new file mode 100644
--- /dev/null
+++ b/js/src/tests/ecma_6/Generators/yield-error.js
@@ -0,0 +1,32 @@
+var BUGNUMBER = 1384299;
+var summary = "yield outside of generators should provide better error";
+
+print(BUGNUMBER + ": " + summary);
+
+let caught = false;
+try {
+    eval("yield 10");
+} catch(e) {
+    assertEq(e.message, "yield expression is only valid in generators");
+    caught = true;
+}
+assertEq(caught, true);
+
+try {
+    eval("function f() { yield 10; }");
+} catch(e) {
+    assertEq(e.message, "yield expression is only valid in generators");
+    caught = true;
+}
+assertEq(caught, true);
+
+try {
+    eval("async function f() { yield 10; }");
+} catch(e) {
+    assertEq(e.message, "yield expression is only valid in generators");
+    caught = true;
+}
+assertEq(caught, true);
+
+if (typeof reportCompare === "function")
+    reportCompare(true, true);
--- a/js/src/vm/Debugger.cpp
+++ b/js/src/vm/Debugger.cpp
@@ -5648,16 +5648,32 @@ DebuggerScript_checkThis(JSContext* cx, 
     CallArgs args = CallArgsFromVp(argc, vp);                                       \
     RootedObject obj(cx, DebuggerScript_checkThis<JSScript*>(cx, args, fnname,      \
                                                              "a JS script"));       \
     if (!obj)                                                                       \
         return false;                                                               \
     RootedScript script(cx, GetScriptReferent(obj).as<JSScript*>())
 
 static bool
+DebuggerScript_getIsGeneratorFunction(JSContext* cx, unsigned argc, Value* vp)
+{
+    THIS_DEBUGSCRIPT_SCRIPT(cx, argc, vp, "(get isGeneratorFunction)", args, obj, script);
+    args.rval().setBoolean(script->isLegacyGenerator() || script->isStarGenerator());
+    return true;
+}
+
+static bool
+DebuggerScript_getIsAsyncFunction(JSContext* cx, unsigned argc, Value* vp)
+{
+    THIS_DEBUGSCRIPT_SCRIPT(cx, argc, vp, "(get isAsyncFunction)", args, obj, script);
+    args.rval().setBoolean(script->isAsync());
+    return true;
+}
+
+static bool
 DebuggerScript_getDisplayName(JSContext* cx, unsigned argc, Value* vp)
 {
     THIS_DEBUGSCRIPT_SCRIPT(cx, argc, vp, "(get displayName)", args, obj, script);
     Debugger* dbg = Debugger::fromChildJSObject(obj);
 
     JSFunction* func = script->functionNonDelazifying();
     JSString* name = func ? func->displayAtom() : nullptr;
     if (!name) {
@@ -7115,16 +7131,18 @@ static bool
 DebuggerScript_construct(JSContext* cx, unsigned argc, Value* vp)
 {
     JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_NO_CONSTRUCTOR,
                               "Debugger.Script");
     return false;
 }
 
 static const JSPropertySpec DebuggerScript_properties[] = {
+    JS_PSG("isGeneratorFunction", DebuggerScript_getIsGeneratorFunction, 0),
+    JS_PSG("isAsyncFunction", DebuggerScript_getIsAsyncFunction, 0),
     JS_PSG("displayName", DebuggerScript_getDisplayName, 0),
     JS_PSG("url", DebuggerScript_getUrl, 0),
     JS_PSG("startLine", DebuggerScript_getStartLine, 0),
     JS_PSG("lineCount", DebuggerScript_getLineCount, 0),
     JS_PSG("source", DebuggerScript_getSource, 0),
     JS_PSG("sourceStart", DebuggerScript_getSourceStart, 0),
     JS_PSG("sourceLength", DebuggerScript_getSourceLength, 0),
     JS_PSG("global", DebuggerScript_getGlobal, 0),
@@ -9169,16 +9187,44 @@ DebuggerObject::isArrowFunctionGetter(JS
         return true;
     }
 
     args.rval().setBoolean(object->isArrowFunction());
     return true;
 }
 
 /* static */ bool
+DebuggerObject::isAsyncFunctionGetter(JSContext* cx, unsigned argc, Value* vp)
+{
+    THIS_DEBUGOBJECT(cx, argc, vp, "get isAsyncFunction", args, object)
+
+    if (!object->isDebuggeeFunction()) {
+        args.rval().setUndefined();
+        return true;
+    }
+
+    args.rval().setBoolean(object->isAsyncFunction());
+    return true;
+}
+
+/* static */ bool
+DebuggerObject::isGeneratorFunctionGetter(JSContext* cx, unsigned argc, Value* vp)
+{
+    THIS_DEBUGOBJECT(cx, argc, vp, "get isGeneratorFunction", args, object)
+
+    if (!object->isDebuggeeFunction()) {
+        args.rval().setUndefined();
+        return true;
+    }
+
+    args.rval().setBoolean(object->isGeneratorFunction());
+    return true;
+}
+
+/* static */ bool
 DebuggerObject::protoGetter(JSContext* cx, unsigned argc, Value* vp)
 {
     THIS_DEBUGOBJECT(cx, argc, vp, "get proto", args, object)
 
     RootedDebuggerObject result(cx);
     if (!DebuggerObject::getPrototypeOf(cx, object, &result))
         return false;
 
@@ -10080,16 +10126,18 @@ DebuggerObject::unwrapMethod(JSContext* 
     args.rval().setObjectOrNull(result);
     return true;
 }
 
 const JSPropertySpec DebuggerObject::properties_[] = {
     JS_PSG("callable", DebuggerObject::callableGetter, 0),
     JS_PSG("isBoundFunction", DebuggerObject::isBoundFunctionGetter, 0),
     JS_PSG("isArrowFunction", DebuggerObject::isArrowFunctionGetter, 0),
+    JS_PSG("isGeneratorFunction", DebuggerObject::isGeneratorFunctionGetter, 0),
+    JS_PSG("isAsyncFunction", DebuggerObject::isAsyncFunctionGetter, 0),
     JS_PSG("proto", DebuggerObject::protoGetter, 0),
     JS_PSG("class", DebuggerObject::classGetter, 0),
     JS_PSG("name", DebuggerObject::nameGetter, 0),
     JS_PSG("displayName", DebuggerObject::displayNameGetter, 0),
     JS_PSG("parameterNames", DebuggerObject::parameterNamesGetter, 0),
     JS_PSG("script", DebuggerObject::scriptGetter, 0),
     JS_PSG("environment", DebuggerObject::environmentGetter, 0),
     JS_PSG("boundTargetFunction", DebuggerObject::boundTargetFunctionGetter, 0),
@@ -10212,16 +10260,33 @@ bool
 DebuggerObject::isArrowFunction() const
 {
     MOZ_ASSERT(isDebuggeeFunction());
 
     return RemoveAsyncWrapper(&referent()->as<JSFunction>())->isArrow();
 }
 
 bool
+DebuggerObject::isAsyncFunction() const
+{
+    MOZ_ASSERT(isDebuggeeFunction());
+
+    return RemoveAsyncWrapper(&referent()->as<JSFunction>())->isAsync();
+}
+
+bool
+DebuggerObject::isGeneratorFunction() const
+{
+    MOZ_ASSERT(isDebuggeeFunction());
+
+    JSFunction* fun = RemoveAsyncWrapper(&referent()->as<JSFunction>());
+    return fun->isLegacyGenerator() || fun->isStarGenerator();
+}
+
+bool
 DebuggerObject::isGlobal() const
 {
     return referent()->is<GlobalObject>();
 }
 
 bool
 DebuggerObject::isScriptedProxy() const
 {
--- a/js/src/vm/Debugger.h
+++ b/js/src/vm/Debugger.h
@@ -1475,16 +1475,18 @@ class DebuggerObject : public NativeObje
                                     MutableHandleDebuggerObject result);
 
     // Infallible properties
     bool isCallable() const;
     bool isFunction() const;
     bool isDebuggeeFunction() const;
     bool isBoundFunction() const;
     bool isArrowFunction() const;
+    bool isAsyncFunction() const;
+    bool isGeneratorFunction() const;
     bool isGlobal() const;
     bool isScriptedProxy() const;
     bool isPromise() const;
     JSAtom* name(JSContext* cx) const;
     JSAtom* displayName(JSContext* cx) const;
     JS::PromiseState promiseState() const;
     double promiseLifetime() const;
     double promiseTimeToResolution() const;
@@ -1514,16 +1516,18 @@ class DebuggerObject : public NativeObje
     static MOZ_MUST_USE bool requireGlobal(JSContext* cx, HandleDebuggerObject object);
     static MOZ_MUST_USE bool requirePromise(JSContext* cx, HandleDebuggerObject object);
     static MOZ_MUST_USE bool construct(JSContext* cx, unsigned argc, Value* vp);
 
     // JSNative properties
     static MOZ_MUST_USE bool callableGetter(JSContext* cx, unsigned argc, Value* vp);
     static MOZ_MUST_USE bool isBoundFunctionGetter(JSContext* cx, unsigned argc, Value* vp);
     static MOZ_MUST_USE bool isArrowFunctionGetter(JSContext* cx, unsigned argc, Value* vp);
+    static MOZ_MUST_USE bool isAsyncFunctionGetter(JSContext* cx, unsigned argc, Value* vp);
+    static MOZ_MUST_USE bool isGeneratorFunctionGetter(JSContext* cx, unsigned argc, Value* vp);
     static MOZ_MUST_USE bool protoGetter(JSContext* cx, unsigned argc, Value* vp);
     static MOZ_MUST_USE bool classGetter(JSContext* cx, unsigned argc, Value* vp);
     static MOZ_MUST_USE bool nameGetter(JSContext* cx, unsigned argc, Value* vp);
     static MOZ_MUST_USE bool displayNameGetter(JSContext* cx, unsigned argc, Value* vp);
     static MOZ_MUST_USE bool parameterNamesGetter(JSContext* cx, unsigned argc, Value* vp);
     static MOZ_MUST_USE bool scriptGetter(JSContext* cx, unsigned argc, Value* vp);
     static MOZ_MUST_USE bool environmentGetter(JSContext* cx, unsigned argc, Value* vp);
     static MOZ_MUST_USE bool boundTargetFunctionGetter(JSContext* cx, unsigned argc, Value* vp);
--- a/js/xpconnect/src/nsXPConnect.cpp
+++ b/js/xpconnect/src/nsXPConnect.cpp
@@ -179,17 +179,17 @@ nsXPConnect::IsISupportsDescendant(nsIIn
 }
 
 void
 xpc::ErrorBase::Init(JSErrorBase* aReport)
 {
     if (!aReport->filename)
         mFileName.SetIsVoid(true);
     else
-        mFileName.AssignWithConversion(aReport->filename);
+        CopyASCIItoUTF16(aReport->filename, mFileName);
 
     mLineNumber = aReport->lineno;
     mColumn = aReport->column;
 }
 
 void
 xpc::ErrorNote::Init(JSErrorNotes::Note* aNote)
 {
new file mode 100644
--- /dev/null
+++ b/layout/generic/crashtests/1059138-1.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="UTF-8">
+<title>Testcase for bug 1059138</title>
+<template>
+  <div class="inner" style="border: 1px solid black; display:flex; width: 500px;">
+    <button class="action-button">
+      ThisIsAButton
+    </button>
+    <content></content>
+  </div>
+</template>
+
+<script>
+  // Gets content from <template>
+  var template = document.querySelector('template').content;
+
+  // Creates an object based in the HTML Element prototype
+  var MyElementProto = Object.create(HTMLElement.prototype);
+
+  // Fires when an instance of the element is created
+  MyElementProto.createdCallback = function() {
+    // Creates the shadow root
+    var shadowRoot = this.createShadowRoot();
+
+    // Adds a template clone into shadow root
+    var clone = document.importNode(template, true);
+    shadowRoot.appendChild(clone);
+  };
+  // Registers <my-elem> in the main document
+  window.MyElement = document.registerElement('my-elem', {
+      prototype: MyElementProto
+  });
+</script>
+</head>
+<body>
+  <my-elem><div>ThisIsADivFlexItem</div></my-elem>
+</body>
+</html>
--- a/layout/generic/crashtests/crashtests.list
+++ b/layout/generic/crashtests/crashtests.list
@@ -540,17 +540,17 @@ load 849603.html
 asserts(0-12) load 850931.html # bug 569193
 load 851396-1.html
 load 854263-1.html
 load 862185.html
 load 862947-1.html
 load 863935.html
 load 866547-1.html
 needs-focus pref(accessibility.browsewithcaret,true) load 868906.html
-asserts(0-5) load 876074-1.html # bug 876749
+load 876074-1.html
 load 876155.html
 load 883514-1.html
 load 883514-2.html
 load 885009-1.html
 load 893496-1.html
 load 893523.html
 asserts(0-3) load 898871.html # bug 479160 - mostly OSX, sometimes Windows
 asserts(0-3) load 914501.html # bug 1144852 - all platforms
@@ -577,16 +577,17 @@ asserts(543) load 1015844.html # bug 574
 pref(font.size.inflation.minTwips,200) load 1032450.html
 load 1032613-1.svg
 load 1032613-2.html
 load 1037903.html
 load 1039454-1.html
 load 1042489.html
 load 1054010-1.html
 load 1058954-1.html
+pref(dom.webcomponents.enabled,true) load 1059138-1.html
 load 1134531.html
 load 1134667.html
 load 1137723-1.html
 load 1137723-2.html
 load 1140268-1.html
 load 1145768.html
 load 1146103.html
 load 1146107.html
--- a/layout/generic/nsBulletFrame.cpp
+++ b/layout/generic/nsBulletFrame.cpp
@@ -393,18 +393,22 @@ BulletRenderer::Paint(gfxContext& aRende
   return DrawResult::SUCCESS;
 }
 
 bool
 BulletRenderer::BuildGlyphForText(nsDisplayItem* aItem, bool disableSubpixelAA)
 {
   MOZ_ASSERT(IsTextType());
 
+  RefPtr<DrawTarget> screenTarget = gfxPlatform::GetPlatform()->ScreenReferenceDrawTarget();
   RefPtr<DrawTargetCapture> capture =
-    gfxPlatform::GetPlatform()->ScreenReferenceDrawTarget()->CreateCaptureDT(IntSize());
+    Factory::CreateCaptureDrawTarget(screenTarget->GetBackendType(),
+                                     IntSize(),
+                                     screenTarget->GetFormat());
+
   RefPtr<gfxContext> captureCtx = gfxContext::CreateOrNull(capture);
 
   {
     DrawTargetAutoDisableSubpixelAntialiasing
       disable(capture, disableSubpixelAA);
 
     captureCtx->SetColor(
       Color::FromABGR(mColor));
--- a/layout/generic/nsTextFrame.cpp
+++ b/layout/generic/nsTextFrame.cpp
@@ -5114,18 +5114,21 @@ nsDisplayText::nsDisplayText(nsDisplayLi
   MOZ_COUNT_CTOR(nsDisplayText);
   mIsFrameSelected = aIsSelected;
   mBounds = mFrame->GetVisualOverflowRectRelativeToSelf() + ToReferenceFrame();
     // Bug 748228
   mBounds.Inflate(mFrame->PresContext()->AppUnitsPerDevPixel());
 
   if (gfxPrefs::LayersAllowTextLayers() &&
       CanUseAdvancedLayer(aBuilder->GetWidgetLayerManager())) {
+    RefPtr<DrawTarget> screenTarget = gfxPlatform::GetPlatform()->ScreenReferenceDrawTarget();
     RefPtr<DrawTargetCapture> capture =
-      gfxPlatform::GetPlatform()->ScreenReferenceDrawTarget()->CreateCaptureDT(IntSize());
+      Factory::CreateCaptureDrawTarget(screenTarget->GetBackendType(),
+                                       IntSize(),
+                                       screenTarget->GetFormat());
     RefPtr<gfxContext> captureCtx = gfxContext::CreateOrNull(capture);
 
     // TODO: Paint() checks mDisableSubpixelAA, we should too.
     RenderToContext(captureCtx, aBuilder, true);
 
     // TODO: Ideally we'd re-use captureCtx in Paint() if we couldn't build
     // a layer here. We have to deal with the problem that the ScreenReferenceDrawTarget
     // might not be compatible with the DT used for layer rendering.
new file mode 100644
--- /dev/null
+++ b/layout/style/crashtests/1228789-1.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<html>
+<body style="border-image-source: -webkit-gradient();"></body>
+</html>
--- a/layout/style/crashtests/crashtests.list
+++ b/layout/style/crashtests/crashtests.list
@@ -127,16 +127,17 @@ load 1164813-1.html
 load 1167782-1.html
 load 1186768-1.xhtml
 load 1200568-1.html
 load 1206105-1.html
 load 1223688-1.html
 load 1223694-1.html
 load 1226400-1.html
 load 1227501-1.html
+load 1228789-1.html
 load 1230408-1.html
 load 1233135-1.html
 load 1233135-2.html
 load 1238660-1.html
 load 1245260-1.html
 load 1247865-1.html
 asserts-if(stylo,0-1) load 1264396-1.html # bug 1324677
 load 1264949.html
--- a/layout/style/nsCSSParser.cpp
+++ b/layout/style/nsCSSParser.cpp
@@ -6736,27 +6736,27 @@ CSSParserImpl::ParseColor(nsCSSValue& aV
     switch (tk->mType) {
       case eCSSToken_Ident:
         str.Assign(tk->mIdent);
         break;
 
       case eCSSToken_Number:
         if (tk->mIntegerValid && tk->mInteger < 1000000 && tk->mInteger >= 0) {
           SprintfLiteral(buffer, "%06d", tk->mInteger);
-          str.AssignWithConversion(buffer);
+          CopyASCIItoUTF16(buffer, str);
         }
         break;
 
       case eCSSToken_Dimension:
         if (tk->mIntegerValid &&
             tk->mIdent.Length() + CountNumbersForHashlessColor(tk->mInteger) <= 6 &&
             tk->mInteger >= 0) {
           SprintfLiteral(buffer, "%06d", tk->mInteger);
           nsAutoString temp;
-          temp.AssignWithConversion(buffer);
+          CopyASCIItoUTF16(buffer, temp);
           temp.Right(str, 6 - tk->mIdent.Length());
           str.Append(tk->mIdent);
         }
         break;
       default:
         // There is a whole bunch of cases that are
         // not handled by this switch.  Ignore them.
         break;
--- a/layout/xul/nsMenuPopupFrame.cpp
+++ b/layout/xul/nsMenuPopupFrame.cpp
@@ -558,16 +558,17 @@ nsMenuPopupFrame::LayoutPopup(nsBoxLayou
       SetSizeConstraints(pc, widget, minSize, maxSize);
     }
   }
 
   if (isOpen) {
     nsViewManager* viewManager = view->GetViewManager();
     nsRect rect = GetRect();
     rect.x = rect.y = 0;
+    rect.SizeTo(BoundsCheck(minSize, rect.Size(), maxSize));
     viewManager->ResizeView(view, rect);
 
     if (mPopupState == ePopupOpening) {
       mPopupState = ePopupVisible;
     }
 
     viewManager->SetViewVisibility(view, nsViewVisibility_kShow);
     SyncFrameViewProperties(view);
--- a/media/webrtc/trunk/webrtc/modules/desktop_capture/screen_capturer_mac.mm
+++ b/media/webrtc/trunk/webrtc/modules/desktop_capture/screen_capturer_mac.mm
@@ -421,33 +421,35 @@ class InvertedDesktopFrame : public Desk
  private:
   std::unique_ptr<DesktopFrame> original_frame_;
 
   RTC_DISALLOW_COPY_AND_ASSIGN(InvertedDesktopFrame);
 };
 
 ScreenCapturerMac::ScreenCapturerMac(
     rtc::scoped_refptr<DesktopConfigurationMonitor> desktop_config_monitor)
-    : screen_callback_data_(new ScreenCallbackData(this))
-    , desktop_config_monitor_(desktop_config_monitor) {
+    : desktop_config_monitor_(desktop_config_monitor) {
 #if defined(MAC_OS_X_VERSION_10_8) && \
   (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_8)
   display_stream_manager_ = new DisplayStreamManager;
+#else
+  screen_callback_data_ = new ScreenCallbackData(this);
 #endif
 }
 
 ScreenCapturerMac::~ScreenCapturerMac() {
   ReleaseBuffers();
+#if defined(MAC_OS_X_VERSION_10_8) && \
+  (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_8)
+  display_stream_manager_->PrepareForSelfDestruction();
+#else
   {
     rtc::CritScope lock(&screen_callback_data_->crit_sect_);
     screen_callback_data_->capturer = nullptr;
   }
-#if defined(MAC_OS_X_VERSION_10_8) && \
-  (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_8)
-  display_stream_manager_->PrepareForSelfDestruction();
 #endif
   dlclose(app_services_library_);
   dlclose(opengl_library_);
 }
 
 bool ScreenCapturerMac::Init() {
   desktop_config_monitor_->Lock();
   desktop_config_ = desktop_config_monitor_->desktop_configuration();
--- a/modules/libpref/init/all.js
+++ b/modules/libpref/init/all.js
@@ -4766,18 +4766,18 @@ pref("network.tcp.tcp_fastopen_consecuti
 pref("layers.acceleration.disabled", false);
 // Preference that when switched at runtime will run a series of benchmarks
 // and output the result to stderr.
 pref("layers.bench.enabled", false);
 
 #if defined(XP_WIN)
 pref("layers.gpu-process.enabled", true);
 pref("media.gpu-process-decoder", true);
+pref("layers.gpu-process.allow-software", true);
 #ifdef NIGHTLY_BUILD
-pref("layers.gpu-process.allow-software", true);
 pref("layers.gpu-process.max_restarts", 3);
 #endif
 #endif
 
 // Whether to force acceleration on, ignoring blacklists.
 #ifdef ANDROID
 // bug 838603 -- on Android, accidentally blacklisting OpenGL layers
 // means a startup crash for everyone.
--- a/netwerk/protocol/http/nsHttpConnectionMgr.cpp
+++ b/netwerk/protocol/http/nsHttpConnectionMgr.cpp
@@ -785,17 +785,17 @@ void
 nsHttpConnectionMgr::UpdateCoalescingForNewConn(nsHttpConnection *newConn,
                                                 nsConnectionEntry *ent)
 {
     MOZ_ASSERT(OnSocketThread(), "not on socket thread");
     MOZ_ASSERT(newConn);
     MOZ_ASSERT(newConn->ConnectionInfo());
     MOZ_DIAGNOSTIC_ASSERT(ent);
     MOZ_ASSERT(mCT.GetWeak(newConn->ConnectionInfo()->HashKey()) == ent);
-    CheckConnEntryMustBeInmCT(ent->mConnInfo);
+    CheckConnEntryMustBeInmCT(ent);
 
     nsHttpConnection *existingConn = FindCoalescableConnection(ent, true);
     if (existingConn) {
         LOG(("UpdateCoalescingForNewConn() found existing active conn that could have served newConn "
              "graceful close of newConn=%p to migrate to existingConn %p\n", newConn, existingConn));
         newConn->DontReuse();
         return;
     }
@@ -1248,17 +1248,17 @@ nsHttpConnectionMgr::AtActiveConnectionL
     bool result = (totalCount >= maxPersistConns);
     LOG(("AtActiveConnectionLimit result: %s", result ? "true" : "false"));
     return result;
 }
 
 void
 nsHttpConnectionMgr::ClosePersistentConnections(nsConnectionEntry *ent)
 {
-    CheckConnEntryMustBeInmCT(ent->mConnInfo);
+    CheckConnEntryMustBeInmCT(ent);
     LOG(("nsHttpConnectionMgr::ClosePersistentConnections [ci=%s]\n",
          ent->mConnInfo->HashKey().get()));
     while (ent->mIdleConns.Length()) {
         RefPtr<nsHttpConnection> conn(ent->mIdleConns[0]);
         ent->mIdleConns.RemoveElementAt(0);
         mNumIdleConns--;
         conn->Close(NS_ERROR_ABORT);
     }
@@ -1657,17 +1657,17 @@ nsHttpConnectionMgr::TryDispatchTransact
     return NS_ERROR_NOT_AVAILABLE;                /* queue it */
 }
 
 nsresult
 nsHttpConnectionMgr::DispatchTransaction(nsConnectionEntry *ent,
                                          nsHttpTransaction *trans,
                                          nsHttpConnection *conn)
 {
-    CheckConnEntryMustBeInmCT(ent->mConnInfo);
+    CheckConnEntryMustBeInmCT(ent);
     uint32_t caps = trans->Caps();
     int32_t priority = trans->Priority();
     nsresult rv;
 
     LOG(("nsHttpConnectionMgr::DispatchTransaction "
          "[ent-ci=%s %p trans=%p caps=%x conn=%p priority=%d]\n",
          ent->mConnInfo->HashKey().get(), ent, trans, caps, conn, priority));
 
@@ -1753,17 +1753,17 @@ NS_IMPL_ISUPPORTS0(ConnectionHandle)
 nsresult
 nsHttpConnectionMgr::DispatchAbstractTransaction(nsConnectionEntry *ent,
                                                  nsAHttpTransaction *aTrans,
                                                  uint32_t caps,
                                                  nsHttpConnection *conn,
                                                  int32_t priority)
 {
     MOZ_DIAGNOSTIC_ASSERT(ent);
-    CheckConnEntryMustBeInmCT(ent->mConnInfo);
+    CheckConnEntryMustBeInmCT(ent);
     nsresult rv;
     MOZ_ASSERT(!conn->UsingSpdy(),
                "Spdy Must Not Use DispatchAbstractTransaction");
     LOG(("nsHttpConnectionMgr::DispatchAbstractTransaction "
          "[ci=%s trans=%p caps=%x conn=%p]\n",
          ent->mConnInfo->HashKey().get(), aTrans, caps, conn));
 
     RefPtr<nsAHttpTransaction> transaction(aTrans);
@@ -1902,17 +1902,17 @@ nsHttpConnectionMgr::ProcessNewTransacti
     return rv;
 }
 
 
 void
 nsHttpConnectionMgr::AddActiveConn(nsHttpConnection *conn,
                                    nsConnectionEntry *ent)
 {
-    CheckConnEntryMustBeInmCT(ent->mConnInfo);
+    CheckConnEntryMustBeInmCT(ent);
     ent->mActiveConns.AppendElement(conn);
     mNumActiveConns++;
     ActivateTimeoutTick();
 }
 
 void
 nsHttpConnectionMgr::DecrementActiveConnCount(nsHttpConnection *conn)
 {
@@ -2091,17 +2091,17 @@ nsHttpConnectionMgr::OnMsgProcessAllSpdy
 
 // Given a connection entry, return an active h2 connection
 // that can be directly activated or null
 nsHttpConnection *
 nsHttpConnectionMgr::GetSpdyActiveConn(nsConnectionEntry *ent)
 {
     MOZ_ASSERT(OnSocketThread(), "not on socket thread");
     MOZ_DIAGNOSTIC_ASSERT(ent);
-    CheckConnEntryMustBeInmCT(ent->mConnInfo);
+    CheckConnEntryMustBeInmCT(ent);
 
     nsHttpConnection *experienced = nullptr;
     nsHttpConnection *noExperience = nullptr;
     uint32_t activeLen = ent->mActiveConns.Length();
     nsHttpConnectionInfo *ci = ent->mConnInfo;
     uint32_t index;
 
     // activeLen should generally be 1.. this is a setup race being resolved
@@ -2413,17 +2413,17 @@ nsHttpConnectionMgr::OnMsgCancelTransact
         // so we want to cancel any null transactions related to this connection
         // entry. They are just optimizations, but they aren't hooked up to
         // anything that might get canceled from the rest of gecko, so best
         // to assume that's what was meant by the cancel we did receive if
         // it only applied to something in the queue.
         for (uint32_t index = 0;
              ent && (index < ent->mActiveConns.Length());
              ++index) {
-            CheckConnEntryMustBeInmCT(ent->mConnInfo);
+            CheckConnEntryMustBeInmCT(ent);
             nsHttpConnection *activeConn = ent->mActiveConns[index];
             nsAHttpTransaction *liveTransaction = activeConn->Transaction();
             if (liveTransaction && liveTransaction->IsNullTransaction()) {
                 LOG(("nsHttpConnectionMgr::OnMsgCancelTransaction [trans=%p] "
                      "also canceling Null Transaction %p on conn %p\n",
                      trans, liveTransaction, activeConn));
                 activeConn->CloseTransaction(liveTransaction, closeCode);
             }
@@ -4070,17 +4070,25 @@ NS_IMETHODIMP
 nsHttpConnectionMgr::
 nsHalfOpenSocket::OnOutputStreamReady(nsIAsyncOutputStream *out)
 {
     MOZ_ASSERT(OnSocketThread(), "not on socket thread");
     MOZ_DIAGNOSTIC_ASSERT(mStreamOut || mBackupStreamOut);
     MOZ_DIAGNOSTIC_ASSERT(out == mStreamOut || out == mBackupStreamOut,
                           "stream mismatch");
     MOZ_DIAGNOSTIC_ASSERT(mEnt);
-    gHttpHandler->ConnMgr()->CheckConnEntryMustBeInmCT(mEnt->mConnInfo);
+    if (out == mStreamOut) {
+        LOG(("nsHalfOpenSocket::OnOutputStreamReady [this=%p ent=%s %s]\n",
+             this, mEnt->mConnInfo->Origin(), "primary"));
+        gHttpHandler->ConnMgr()->CheckConnEntryMustBeInmCT(mEnt);
+    } else {
+        LOG(("nsHalfOpenSocket::OnOutputStreamReady [this=%p ent=%s %s]\n",
+             this, mEnt->mConnInfo->Origin(), "backup"));
+        gHttpHandler->ConnMgr()->CheckConnEntryMustBeInmCT(mEnt);
+    }
 
     LOG(("nsHalfOpenSocket::OnOutputStreamReady [this=%p ent=%s %s]\n",
          this, mEnt->mConnInfo->Origin(),
          out == mStreamOut ? "primary" : "backup"));
 
     mEnt->mDoNotDestroy = true;
     gHttpHandler->ConnMgr()->RecvdConnect();
 
@@ -4131,33 +4139,33 @@ nsHalfOpenSocket::OnOutputStreamReady(ns
             mEnt->mUseFastOpen = false;
         }
 
         mFastOpenInProgress = false;
         mConnectionNegotiatingFastOpen = nullptr;
     }
 
     MOZ_DIAGNOSTIC_ASSERT(mEnt);
-    gHttpHandler->ConnMgr()->CheckConnEntryMustBeInmCT(mEnt->mConnInfo);
+    gHttpHandler->ConnMgr()->CheckConnEntryMustBeInmCT(mEnt);
     nsresult rv =  SetupConn(out, false);
     if (mEnt) {
         mEnt->mDoNotDestroy = false;
     }
     return rv;
 }
 
 bool
 nsHttpConnectionMgr::
 nsHalfOpenSocket::FastOpenEnabled()
 {
     LOG(("nsHalfOpenSocket::FastOpenEnabled [this=%p]\n", this));
 
     MOZ_DIAGNOSTIC_ASSERT(mEnt);
 
-    gHttpHandler->ConnMgr()->CheckConnEntryMustBeInmCT(mEnt->mConnInfo);
+    gHttpHandler->ConnMgr()->CheckConnEntryMustBeInmCT(mEnt);
 
     if (!mEnt) {
         return false;
     }
 
     // If mEnt is present this HalfOpen must be in the mHalfOpens,
     // but we want to be sure!!!
     if (!mEnt->mHalfOpens.Contains(this)) {
@@ -4201,34 +4209,31 @@ nsHalfOpenSocket::FastOpenEnabled()
 nsresult
 nsHttpConnectionMgr::
 nsHalfOpenSocket::StartFastOpen()
 {
     MOZ_DIAGNOSTIC_ASSERT(mStreamOut);
     MOZ_DIAGNOSTIC_ASSERT(!mBackupTransport);
     MOZ_DIAGNOSTIC_ASSERT(mEnt);
 
-    gHttpHandler->ConnMgr()->CheckConnEntryMustBeInmCT(mEnt->mConnInfo);
+    gHttpHandler->ConnMgr()->CheckConnEntryMustBeInmCT(mEnt);
 
     LOG(("nsHalfOpenSocket::StartFastOpen [this=%p]\n",
          this));
 
     RefPtr<nsHalfOpenSocket> deleteProtector(this);
 
     mFastOpenInProgress = true;
     mEnt->mDoNotDestroy = true;
     // Remove this HalfOpen from mEnt->mHalfOpens.
     // The new connection will take care of closing this HalfOpen from now on!
     if (!mEnt->mHalfOpens.RemoveElement(this)) {
         MOZ_ASSERT(false, "HalfOpen is not in mHalfOpens!");
         mSocketTransport->SetFastOpenCallback(nullptr);
         CancelBackupTimer();
-        mStreamOut = nullptr;
-        mStreamIn = nullptr;
-        mSocketTransport = nullptr;
         mFastOpenInProgress = false;
         Abandon();
         return NS_ERROR_ABORT;
     }
 
     MOZ_ASSERT(gHttpHandler->ConnMgr()->mNumHalfOpenConns);
     if (gHttpHandler->ConnMgr()->mNumHalfOpenConns) { // just in case
         gHttpHandler->ConnMgr()->mNumHalfOpenConns--;
@@ -4249,29 +4254,26 @@ nsHalfOpenSocket::StartFastOpen()
         if (NS_SUCCEEDED(rv)) {
             rv = NS_ERROR_ABORT;
         }
         // If SetupConn failed this will CloseTransaction and socketTransport
         // with an error, therefore we can close this HalfOpen. socketTransport
         // will remove reference to this HalfOpen as well.
         mSocketTransport->SetFastOpenCallback(nullptr);
         CancelBackupTimer();
-        mStreamOut = nullptr;
-        mStreamIn = nullptr;
-        mSocketTransport = nullptr;
         mFastOpenInProgress = false;
 
         // The connection is responsible to take care of the halfOpen so we
         // need to clean it up.
         Abandon();
     } else {
         LOG(("nsHalfOpenSocket::StartFastOpen [this=%p conn=%p]\n",
              this, mConnectionNegotiatingFastOpen.get()));
 
-        gHttpHandler->ConnMgr()->CheckConnEntryMustBeInmCT(mEnt->mConnInfo);
+        gHttpHandler->ConnMgr()->CheckConnEntryMustBeInmCT(mEnt);
 
         mEnt->mHalfOpenFastOpenBackups.AppendElement(this);
         // SetupBackupTimer should setup timer which will hold a ref to this
         // halfOpen. It will failed only if it cannot create timer. Anyway just
         // to be sure I will add this deleteProtector!!!
         if (!mSynTimer) {
             // For Fast Open we will setup backup timer also for
             // NullTransaction.
@@ -4287,17 +4289,17 @@ nsHalfOpenSocket::StartFastOpen()
 
 void
 nsHttpConnectionMgr::
 nsHalfOpenSocket::SetFastOpenConnected(nsresult aError, bool aWillRetry)
 {
     MOZ_DIAGNOSTIC_ASSERT(mFastOpenInProgress);
     MOZ_DIAGNOSTIC_ASSERT(mEnt);
 
-    gHttpHandler->ConnMgr()->CheckConnEntryMustBeInmCT(mEnt->mConnInfo);
+    gHttpHandler->ConnMgr()->CheckConnEntryMustBeInmCT(mEnt);
 
     LOG(("nsHalfOpenSocket::SetFastOpenConnected [this=%p conn=%p error=%x]\n",
          this, mConnectionNegotiatingFastOpen.get(),
          static_cast<uint32_t>(aError)));
 
     // mConnectionNegotiatingFastOpen is set after a StartFastOpen creates
     // and activates a nsHttpConnection successfully (SetupConn calls
     // DispatchTransaction and DispatchAbstractTransaction which calls
@@ -4349,17 +4351,17 @@ nsHalfOpenSocket::SetFastOpenConnected(n
             }
         }
         // We are doing a restart without fast open, so the easiest way is to
         // return mSocketTransport to the halfOpenSock and destroy connection.
         // This makes http2 implemenntation easier.
         // mConnectionNegotiatingFastOpen is going away and halfOpen is taking
         // this mSocketTransport so add halfOpen to mEnt and update
         // mNumActiveConns.
-        gHttpHandler->ConnMgr()->CheckConnEntryMustBeInmCT(mEnt->mConnInfo);
+        gHttpHandler->ConnMgr()->CheckConnEntryMustBeInmCT(mEnt);
         mEnt->mHalfOpens.AppendElement(this);
         gHttpHandler->ConnMgr()->mNumHalfOpenConns++;
         gHttpHandler->ConnMgr()->StartedConnect();
 
         // Restore callbacks.
         mStreamOut->AsyncWait(this, 0, 0, nullptr);
         mSocketTransport->SetEventSink(this, nullptr);
         mSocketTransport->SetSecurityCallbacks(this);
@@ -4408,17 +4410,17 @@ void
 nsHttpConnectionMgr::
 nsHalfOpenSocket::CancelFastOpenConnection()
 {
     MOZ_DIAGNOSTIC_ASSERT(mFastOpenInProgress);
 
     LOG(("nsHalfOpenSocket::CancelFastOpenConnection [this=%p conn=%p]\n",
          this, mConnectionNegotiatingFastOpen.get()));
 
-    gHttpHandler->ConnMgr()->CheckConnEntryMustBeInmCT(mEnt->mConnInfo);
+    gHttpHandler->ConnMgr()->CheckConnEntryMustBeInmCT(mEnt);
 
     RefPtr<nsHalfOpenSocket> deleteProtector(this);
     mEnt->mHalfOpenFastOpenBackups.RemoveElement(this);
     mSocketTransport->SetFastOpenCallback(nullptr);
     mConnectionNegotiatingFastOpen->SetFastOpen(false);
     RefPtr<nsAHttpTransaction> trans =
         mConnectionNegotiatingFastOpen->CloseConnectionFastOpenTakesTooLongOrError(true);
     mSocketTransport = nullptr;
@@ -4619,17 +4621,17 @@ nsHalfOpenSocket::SetupConn(nsIAsyncOutp
 
     // If this connection has a transaction get reference to its
     // ConnectionHandler.
     if (aFastOpen) {
         MOZ_DIAGNOSTIC_ASSERT(mEnt);
         MOZ_DIAGNOSTIC_ASSERT(static_cast<int32_t>(mEnt->mIdleConns.IndexOf(conn)) == -1);
         int32_t idx = mEnt->mActiveConns.IndexOf(conn);
         if (NS_SUCCEEDED(rv) && (idx != -1)) {
-            gHttpHandler->ConnMgr()->CheckConnEntryMustBeInmCT(mEnt->mConnInfo);
+            gHttpHandler->ConnMgr()->CheckConnEntryMustBeInmCT(mEnt);
             mConnectionNegotiatingFastOpen = conn;
         } else {
             conn->SetFastOpen(false);
         }
     }
 
     // If this halfOpenConn was speculative, but at the ende the conn got a
     // non-null transaction than this halfOpen is not speculative anymore!
@@ -5180,21 +5182,22 @@ nsHttpConnectionMgr::MoveToWildCardConnE
             ent->mIdleConns.RemoveElementAt(i);
             wcEnt->mIdleConns.InsertElementAt(0, proxyConn);
             return;
         }
     }
 }
 
 void
-nsHttpConnectionMgr::CheckConnEntryMustBeInmCT(nsHttpConnectionInfo *ci)
+nsHttpConnectionMgr::CheckConnEntryMustBeInmCT(nsConnectionEntry *ent)
 {
-    nsConnectionEntry *ent = mCT.GetWeak(ci->HashKey());
-    MOZ_DIAGNOSTIC_ASSERT(ent);
     if (ent->mHowItWasRemoved == nsConnectionEntry::CONN_ENTRY_CLEAR_CONNECTION_HISTORY) {
         MOZ_DIAGNOSTIC_ASSERT(false);
     } else if (ent->mHowItWasRemoved == nsConnectionEntry::CONN_ENTRY_REMOVED_SHUTDOWN) {
         MOZ_DIAGNOSTIC_ASSERT(false);
     }
+    MOZ_DIAGNOSTIC_ASSERT(ent->mConnInfo);
+    nsConnectionEntry *ent2 = mCT.GetWeak(ent->mConnInfo->HashKey());
+    MOZ_DIAGNOSTIC_ASSERT(ent2);
 }
 
 } // namespace net
 } // namespace mozilla
--- a/netwerk/protocol/http/nsHttpConnectionMgr.h
+++ b/netwerk/protocol/http/nsHttpConnectionMgr.h
@@ -747,17 +747,17 @@ private:
     bool mActiveTabUnthrottledTransactionsExist;
 
     void LogActiveTransactions(char);
 
     nsTArray<RefPtr<PendingTransactionInfo>>*
     GetTransactionPendingQHelper(nsConnectionEntry *ent, nsAHttpTransaction *trans);
 
     // This is only a diagnostic check end it will e removed soon.
-    void CheckConnEntryMustBeInmCT(nsHttpConnectionInfo *ci);
+    void CheckConnEntryMustBeInmCT(nsConnectionEntry *ent);
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsHttpConnectionMgr::nsHalfOpenSocket, NS_HALFOPENSOCKET_IID)
 
 } // namespace net
 } // namespace mozilla
 
 #endif // !nsHttpConnectionMgr_h__
--- a/python/mozbuild/mozbuild/backend/common.py
+++ b/python/mozbuild/mozbuild/backend/common.py
@@ -9,29 +9,32 @@ import json
 import os
 
 import mozpack.path as mozpath
 
 from mozbuild.backend.base import BuildBackend
 
 from mozbuild.frontend.context import (
     Context,
+    ObjDirPath,
     Path,
     RenamedSourcePath,
     VARIABLES,
 )
 from mozbuild.frontend.data import (
     BaseProgram,
     ChromeManifestEntry,
     ConfigFileSubstitution,
     ExampleWebIDLInterface,
+    Exports,
     IPDLFile,
     FinalTargetPreprocessedFiles,
     FinalTargetFiles,
     GeneratedEventWebIDLFile,
+    GeneratedSources,
     GeneratedWebIDLFile,
     PreprocessedTestWebIDLFile,
     PreprocessedWebIDLFile,
     SharedLibrary,
     TestWebIDLFile,
     UnifiedSources,
     XPIDLFile,
     WebIDLFile,
@@ -174,16 +177,17 @@ class CommonBackend(BuildBackend):
     """Holds logic common to all build backends."""
 
     def _init(self):
         self._idl_manager = XPIDLManager(self.environment)
         self._webidls = WebIDLCollection()
         self._binaries = BinariesCollection()
         self._configs = set()
         self._ipdl_sources = set()
+        self._generated_sources = set()
 
     def consume_object(self, obj):
         self._configs.add(obj.config)
 
         if isinstance(obj, XPIDLFile):
             # TODO bug 1240134 tracks not processing XPIDL files during
             # artifact builds.
             self._idl_manager.register_idl(obj)
@@ -272,24 +276,35 @@ class CommonBackend(BuildBackend):
         elif isinstance(obj, BaseProgram):
             self._binaries.programs.append(obj)
             return False
 
         elif isinstance(obj, SharedLibrary):
             self._binaries.shared_libraries.append(obj)
             return False
 
+        elif isinstance(obj, GeneratedSources):
+            self._handle_generated_sources(obj.files)
+            return False
+
+        elif isinstance(obj, Exports):
+            objdir_files = [f.full_path for path, files in obj.files.walk() for f in files if isinstance(f, ObjDirPath)]
+            if objdir_files:
+                self._handle_generated_sources(objdir_files)
+            return False
+
         else:
             return False
 
         return True
 
     def consume_finished(self):
         if len(self._idl_manager.idls):
             self._handle_idl_manager(self._idl_manager)
+            self._handle_generated_sources(mozpath.join(self.environment.topobjdir, 'dist/include/%s.h' % idl['root']) for idl in self._idl_manager.idls.values())
 
         self._handle_webidl_collection(self._webidls)
 
         sorted_ipdl_sources = list(sorted(self._ipdl_sources))
 
         def files_from(ipdl):
             base = mozpath.basename(ipdl)
             root, ext = mozpath.splitext(base)
@@ -300,16 +315,17 @@ class CommonBackend(BuildBackend):
                 # .ipdl also becomes Child/Parent.cpp files
                 files.extend(['%sChild.cpp' % root,
                               '%sParent.cpp' % root])
             return files
 
         ipdl_dir = mozpath.join(self.environment.topobjdir, 'ipc', 'ipdl')
 
         ipdl_cppsrcs = list(itertools.chain(*[files_from(p) for p in sorted_ipdl_sources]))
+        self._handle_generated_sources(mozpath.join(ipdl_dir, f) for f in ipdl_cppsrcs)
         unified_source_mapping = list(group_unified_files(ipdl_cppsrcs,
                                                           unified_prefix='UnifiedProtocols',
                                                           unified_suffix='cpp',
                                                           files_per_unified_file=16))
 
         self._write_unified_files(unified_source_mapping, ipdl_dir, poison_windows_h=False)
         self._handle_ipdl_sources(ipdl_dir, sorted_ipdl_sources, unified_source_mapping)
 
@@ -320,16 +336,26 @@ class CommonBackend(BuildBackend):
         topobjdir = self.environment.topobjdir
         with self._write_file(mozpath.join(topobjdir, 'binaries.json')) as fh:
             d = {
                 'shared_libraries': [s.to_dict() for s in self._binaries.shared_libraries],
                 'programs': [p.to_dict() for p in self._binaries.programs],
             }
             json.dump(d, fh, sort_keys=True, indent=4)
 
+        # Write out a file listing generated sources.
+        with self._write_file(mozpath.join(topobjdir, 'generated-sources.json')) as fh:
+            d = {
+                'sources': sorted(self._generated_sources),
+            }
+            json.dump(d, fh, sort_keys=True, indent=4)
+
+    def _handle_generated_sources(self, files):
+        self._generated_sources.update(mozpath.relpath(f, self.environment.topobjdir) for f in files)
+
     def _handle_webidl_collection(self, webidls):
         if not webidls.all_stems():
             return
 
         bindings_dir = mozpath.join(self.environment.topobjdir, 'dom', 'bindings')
 
         all_inputs = set(webidls.all_static_sources())
         for s in webidls.all_non_static_basenames():
@@ -353,17 +379,17 @@ class CommonBackend(BuildBackend):
 
         import mozwebidlcodegen
 
         manager = mozwebidlcodegen.create_build_system_manager(
             self.environment.topsrcdir,
             self.environment.topobjdir,
             mozpath.join(self.environment.topobjdir, 'dist')
         )
-
+        self._handle_generated_sources(manager.expected_build_output_files())
         # Bindings are compiled in unified mode to speed up compilation and
         # to reduce linker memory size. Note that test bindings are separated
         # from regular ones so tests bindings aren't shipped.
         unified_source_mapping = list(group_unified_files(webidls.all_regular_cpp_basenames(),
                                                           unified_prefix='UnifiedBindings',
                                                           unified_suffix='cpp',
                                                           files_per_unified_file=32))
         self._write_unified_files(unified_source_mapping, bindings_dir,
--- a/security/manager/ssl/PKCS11.cpp
+++ b/security/manager/ssl/PKCS11.cpp
@@ -84,23 +84,23 @@ PKCS11::DeleteModule(const nsAString& aM
 // to programmatically query the scalar key length limit, so we have to
 // hard-code the value here.)
 void
 GetModuleNameForTelemetry(/*in*/ const SECMODModule* module,
                           /*out*/nsString& result)
 {
   result.Truncate();
   if (module->dllName) {
-    result.AssignWithConversion(module->dllName);
+    CopyASCIItoUTF16(module->dllName, result);
     int32_t separatorIndex = result.RFind(FILE_PATH_SEPARATOR);
     if (separatorIndex != kNotFound) {
       result = Substring(result, separatorIndex + 1);
     }
   } else {
-    result.AssignWithConversion(module->commonName);
+    CopyASCIItoUTF16(module->commonName, result);
   }
   if (result.Length() >= 70) {
     result.Truncate(69);
   }
 }
 
 // Add a new PKCS11 module to the user's profile.
 NS_IMETHODIMP
--- a/security/nss/TAG-INFO
+++ b/security/nss/TAG-INFO
@@ -1,1 +1,1 @@
-f212be04f3d0
+NSS_3_32_RTM
--- a/security/nss/automation/release/nspr-version.txt
+++ b/security/nss/automation/release/nspr-version.txt
@@ -1,9 +1,9 @@
-4.15
+4.16
 
 # The first line of this file must contain the human readable NSPR
 # version number, which is the minimum required version of NSPR
 # that is supported by this version of NSS.
 #
 # This information is used by release automation,
 # when creating an NSS source archive.
 #
--- a/security/nss/coreconf/coreconf.dep
+++ b/security/nss/coreconf/coreconf.dep
@@ -5,9 +5,8 @@
 
 /*
  * A dummy header file that is a dependency for all the object files.
  * Used to force a full recompilation of NSS in Mozilla's Tinderbox
  * depend builds.  See comments in rules.mk.
  */
 
 #error "Do not include this header file."
-
--- a/security/nss/lib/nss/nss.h
+++ b/security/nss/lib/nss/nss.h
@@ -17,22 +17,22 @@
 
 /*
  * NSS's major version, minor version, patch level, build number, and whether
  * this is a beta release.
  *
  * The format of the version string should be
  *     "<major version>.<minor version>[.<patch level>[.<build number>]][ <ECC>][ <Beta>]"
  */
-#define NSS_VERSION "3.32" _NSS_CUSTOMIZED " Beta"
+#define NSS_VERSION "3.32" _NSS_CUSTOMIZED
 #define NSS_VMAJOR 3
 #define NSS_VMINOR 32
 #define NSS_VPATCH 0
 #define NSS_VBUILD 0
-#define NSS_BETA PR_TRUE
+#define NSS_BETA PR_FALSE
 
 #ifndef RC_INVOKED
 
 #include "seccomon.h"
 
 typedef struct NSSInitParametersStr NSSInitParameters;
 
 /*
--- a/security/nss/lib/softoken/softkver.h
+++ b/security/nss/lib/softoken/softkver.h
@@ -16,16 +16,16 @@
 
 /*
  * Softoken's major version, minor version, patch level, build number,
  * and whether this is a beta release.
  *
  * The format of the version string should be
  *     "<major version>.<minor version>[.<patch level>[.<build number>]][ <ECC>][ <Beta>]"
  */
-#define SOFTOKEN_VERSION "3.32" SOFTOKEN_ECC_STRING " Beta"
+#define SOFTOKEN_VERSION "3.32" SOFTOKEN_ECC_STRING
 #define SOFTOKEN_VMAJOR 3
 #define SOFTOKEN_VMINOR 32
 #define SOFTOKEN_VPATCH 0
 #define SOFTOKEN_VBUILD 0
-#define SOFTOKEN_BETA PR_TRUE
+#define SOFTOKEN_BETA PR_FALSE
 
 #endif /* _SOFTKVER_H_ */
--- a/security/nss/lib/util/nssutil.h
+++ b/security/nss/lib/util/nssutil.h
@@ -14,22 +14,22 @@
 
 /*
  * NSS utilities's major version, minor version, patch level, build number,
  * and whether this is a beta release.
  *
  * The format of the version string should be
  *     "<major version>.<minor version>[.<patch level>[.<build number>]][ <Beta>]"
  */
-#define NSSUTIL_VERSION "3.32 Beta"
+#define NSSUTIL_VERSION "3.32"
 #define NSSUTIL_VMAJOR 3
 #define NSSUTIL_VMINOR 32
 #define NSSUTIL_VPATCH 0
 #define NSSUTIL_VBUILD 0
-#define NSSUTIL_BETA PR_TRUE
+#define NSSUTIL_BETA PR_FALSE
 
 SEC_BEGIN_PROTOS
 
 /*
  * Returns a const string of the UTIL library version.
  */
 extern const char *NSSUTIL_GetVersion(void);
 
--- a/services/sync/modules/constants.js
+++ b/services/sync/modules/constants.js
@@ -1,18 +1,19 @@
-#filter substitution
 /* 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/. */
 
 // Process each item in the "constants hash" to add to "global" and give a name
 this.EXPORTED_SYMBOLS = [];
 for (let [key, val] of Object.entries({
 
-WEAVE_VERSION:                         "@weave_version@",
+// Don't manually modify this line, as it is automatically replaced on merge day
+// by the gecko_migration.py script.
+WEAVE_VERSION: "1.58.0",
 
 // Sync Server API version that the client supports.
 SYNC_API_VERSION:                      "1.5",
 
 // Version of the data format this client supports. The data format describes
 // how records are packaged; this is separate from the Server API version and
 // the per-engine cleartext formats.
 STORAGE_VERSION:                       5,
--- a/services/sync/moz.build
+++ b/services/sync/moz.build
@@ -19,40 +19,33 @@ EXTRA_COMPONENTS += [
 EXTRA_JS_MODULES['services-sync'] += [
     'modules/addonsreconciler.js',
     'modules/addonutils.js',
     'modules/bookmark_repair.js',
     'modules/bookmark_validator.js',
     'modules/browserid_identity.js',
     'modules/collection_repair.js',
     'modules/collection_validator.js',
+    'modules/constants.js',
     'modules/doctor.js',
     'modules/engines.js',
     'modules/keys.js',
     'modules/main.js',
     'modules/policies.js',
     'modules/record.js',
     'modules/resource.js',
     'modules/rest.js',
     'modules/service.js',
     'modules/status.js',
     'modules/SyncedTabs.jsm',
     'modules/telemetry.js',
     'modules/UIState.jsm',
     'modules/util.js',
 ]
 
-EXTRA_PP_JS_MODULES['services-sync'] += [
-    'modules/constants.js',
-]
-
-# Definitions used by constants.js
-DEFINES['weave_version'] = '1.58.0'
-DEFINES['weave_id'] = '{340c2bbc-ce74-4362-90b5-7c26312808ef}'
-
 EXTRA_JS_MODULES['services-sync'].engines += [
     'modules/engines/addons.js',
     'modules/engines/bookmarks.js',
     'modules/engines/clients.js',
     'modules/engines/extension-storage.js',
     'modules/engines/forms.js',
     'modules/engines/history.js',
     'modules/engines/passwords.js',
--- a/taskcluster/ci/test/tests.yml
+++ b/taskcluster/ci/test/tests.yml
@@ -1580,17 +1580,17 @@ talos-perf-reftest-singletons:
                     - talos/linux_config.py
         extra-options:
             - --suite=perf-reftest-singletons
 
 talos-quantum-pageload:
     description: "Talos quantum-pageload"
     suite: talos
     try-name: quantum-pageload
-    treeherder-symbol: tc-T(q)
+    treeherder-symbol: tc-T(tp6)
     run-on-projects:
         by-test-platform:
             windows.*: ['mozilla-beta', 'mozilla-central', 'mozilla-inbound', 'autoland', 'try', 'date']
             default: []
     max-run-time: 3600
     e10s: true
     mozharness:
         script: talos_script.py
@@ -1606,18 +1606,18 @@ talos-quantum-pageload:
         extra-options:
             - --suite=quantum-pageload
             - --add-option
             - --webServer,localhost
 
 talos-quantum-pageload-stylo:
     description: "Talos Quantum Pageload Stylo"
     suite: talos
-    try-name: q1s
-    treeherder-symbol: tc-T(q1s)
+    try-name: quantum-pageload-stylo
+    treeherder-symbol: tc-T(tp6s)
     virtualization: hardware
     run-on-projects:
         by-test-platform:
             windows.*: ['mozilla-beta', 'mozilla-central', 'mozilla-inbound', 'autoland', 'try']
             default: []
     max-run-time: 3600
     e10s: true
     mozharness:
--- a/testing/marionette/harness/marionette_harness/marionette_test/testcases.py
+++ b/testing/marionette/harness/marionette_harness/marionette_test/testcases.py
@@ -306,29 +306,29 @@ class MarionetteTestCase(CommonTestCase)
                                       methodName=testname,
                                       filepath=filepath,
                                       testvars=testvars,
                                       **kwargs))
 
     def setUp(self):
         super(MarionetteTestCase, self).setUp()
         self.marionette.test_name = self.test_name
-        self.marionette.execute_script("dump('TEST-START: {0}')"
+        self.marionette.execute_script(r"dump('TEST-START: {0}\n')"
                                        .format(self.test_name),
                                        sandbox="simpletest")
 
     def tearDown(self):
         # In the case no session is active (eg. the application was quit), start
         # a new session for clean-up steps.
         if not self.marionette.session:
             self.marionette.start_session()
 
         if not self.marionette.crashed:
             try:
-                self.marionette.execute_script("dump('TEST-END: {0}')"
+                self.marionette.execute_script(r"dump('TEST-END: {0}\n')"
                                                .format(self.test_name),
                                                sandbox="simpletest")
                 self.marionette.test_name = None
             except (MarionetteException, IOError):
                 # We have tried to log the test end when there is no listener
                 # object that we can access
                 pass
 
--- a/testing/mozharness/configs/beetmover/en_us_build.yml.tmpl
+++ b/testing/mozharness/configs/beetmover/en_us_build.yml.tmpl
@@ -3,83 +3,16 @@ metadata:
     name: "Beet Mover Manifest"
     description: "Maps artifact locations to s3 key names for the en-US locale"
     owner: "release@mozilla.com"
 
 mapping:
 {% for locale in locales %}
   {{ locale }}:
 
-  {% if platform == "win32" %}
-    buildinfo:
-      artifact: {{ artifact_base_url }}/firefox-{{ app_version }}.{{ locale }}.{{ platform }}.json
-      s3_key: {{ s3_prefix }}{{ platform }}/{{ locale }}/firefox-{{ version }}.json
-    mozinfo:
-      artifact: {{ artifact_base_url }}/firefox-{{ app_version }}.{{ locale }}.{{ platform }}.mozinfo.json
-      s3_key: {{ s3_prefix }}{{ platform }}/{{ locale }}/firefox-{{ version }}.mozinfo.json
-    socorroinfo:
-      artifact: {{ artifact_base_url }}/firefox-{{ app_version }}.{{ locale }}.{{ platform }}.txt
-      s3_key: {{ s3_prefix }}{{ platform }}/{{ locale }}/firefox-{{ version }}.txt
-    jsshell:
-      artifact: {{ artifact_base_url }}/jsshell-{{ platform }}.zip
-      s3_key: {{ s3_prefix }}jsshell-{{ platform }}.zip
-    mozharness_package:
-      artifact: {{ artifact_base_url }}/mozharness.zip
-      s3_key: {{ s3_prefix }}{{ platform }}/{{ locale }}/mozharness.zip
-    xpi:
-      artifact: {{ artifact_base_url }}/firefox-{{ app_version }}.{{ locale }}.langpack.xpi
-      s3_key: {{ s3_prefix }}{{ platform }}/xpi/{{ locale }}.xpi
-    symbols:
-      artifact: {{ artifact_base_url }}/firefox-{{ app_version }}.{{ locale }}.{{ platform }}.crashreporter-symbols.zip
-      s3_key: {{ s3_prefix }}{{ platform }}/{{ locale }}/firefox-{{ version }}.crashreporter-symbols.zip
-    buildid_info:
-      artifact: {{ artifact_base_url }}/firefox-{{ app_version }}.{{ locale }}.{{ platform }}_info.txt
-      s3_key: {{ s3_prefix }}win32_info.txt
-    mar_tools_mar:
-      artifact: {{ artifact_base_url }}/mar.exe
-      s3_key: {{ s3_prefix }}mar-tools/win32/mar.exe
-    mar_tools_mbdiff:
-      artifact: {{ artifact_base_url }}/mbsdiff.exe
-      s3_key: {{ s3_prefix }}mar-tools/win32/mbsdiff.exe
-  {% endif %}
-
-  {% if platform == "win64" %}
-    buildinfo:
-      artifact: {{ artifact_base_url }}/firefox-{{ app_version }}.{{ locale }}.{{ platform }}.json
-      s3_key: {{ s3_prefix }}{{ platform }}/{{ locale }}/firefox-{{ version }}.json
-    mozinfo:
-      artifact: {{ artifact_base_url }}/firefox-{{ app_version }}.{{ locale }}.{{ platform }}.mozinfo.json
-      s3_key: {{ s3_prefix }}{{ platform }}/{{ locale }}/firefox-{{ version }}.mozinfo.json
-    socorroinfo:
-      artifact: {{ artifact_base_url }}/firefox-{{ app_version }}.{{ locale }}.{{ platform }}.txt
-      s3_key: {{ s3_prefix }}{{ platform }}/{{ locale }}/firefox-{{ version }}.txt
-    jsshell:
-      artifact: {{ artifact_base_url }}/jsshell-{{ platform }}.zip
-      s3_key: {{ s3_prefix }}jsshell-{{ platform }}.zip
-    mozharness_package:
-      artifact: {{ artifact_base_url }}/mozharness.zip
-      s3_key: {{ s3_prefix }}{{ platform }}/{{ locale }}/mozharness.zip
-    xpi:
-      artifact: {{ artifact_base_url }}/firefox-{{ app_version }}.{{ locale }}.langpack.xpi
-      s3_key: {{ s3_prefix }}{{ platform }}/xpi/{{ locale }}.xpi
-    symbols:
-      artifact: {{ artifact_base_url }}/firefox-{{ app_version }}.{{ locale }}.{{ platform }}.crashreporter-symbols.zip
-      s3_key: {{ s3_prefix }}{{ platform }}/{{ locale }}/firefox-{{ version }}.crashreporter-symbols.zip
-    buildid_info:
-      artifact: {{ artifact_base_url }}/firefox-{{ app_version }}.{{ locale }}.{{ platform }}_info.txt
-      s3_key: {{ s3_prefix }}win64_info.txt
-    mar_tools_mar:
-      artifact: {{ artifact_base_url }}/mar.exe
-      s3_key: {{ s3_prefix }}mar-tools/win64/mar.exe
-    mar_tools_mbdiff:
-      artifact: {{ artifact_base_url }}/mbsdiff.exe
-      s3_key: {{ s3_prefix }}mar-tools/win64/mbsdiff.exe
-  {% endif %}
-
-  {% if platform == "linux-i686" %}
     buildinfo:
       artifact: {{ artifact_base_url }}/target.json
       s3_key: {{ s3_prefix }}{{ platform }}/{{ locale }}/firefox-{{ version }}.json
     mozinfo:
       artifact: {{ artifact_base_url }}/target.mozinfo.json
       s3_key: {{ s3_prefix }}{{ platform }}/{{ locale }}/firefox-{{ version }}.mozinfo.json
     socorroinfo:
       artifact: {{ artifact_base_url }}/target.txt
@@ -91,86 +24,64 @@ mapping:
       artifact: {{ artifact_base_url }}/mozharness.zip
       s3_key: {{ s3_prefix }}{{ platform }}/{{ locale }}/mozharness.zip
     xpi:
       artifact: {{ artifact_base_url }}/target.langpack.xpi
       s3_key: {{ s3_prefix }}{{ platform }}/xpi/{{ locale }}.xpi
     symbols:
       artifact: {{ artifact_base_url }}/target.crashreporter-symbols.zip
       s3_key: {{ s3_prefix }}{{ platform }}/{{ locale }}/firefox-{{ version }}.crashreporter-symbols.zip
+
+  {% if platform == "win32" %}
+    buildid_info:
+      artifact: {{ artifact_base_url }}/target_info.txt
+      s3_key: {{ s3_prefix }}win32_info.txt
+    mar_tools_mar:
+      artifact: {{ artifact_base_url }}/host/bin/mar.exe
+      s3_key: {{ s3_prefix }}mar-tools/win32/mar.exe
+    mar_tools_mbdiff:
+      artifact: {{ artifact_base_url }}/host/bin/mbsdiff.exe
+      s3_key: {{ s3_prefix }}mar-tools/win32/mbsdiff.exe
+  {% endif %}
+
+  {% if platform == "win64" %}
+    buildid_info:
+      artifact: {{ artifact_base_url }}/target_info.txt
+      s3_key: {{ s3_prefix }}win64_info.txt
+    mar_tools_mar:
+      artifact: {{ artifact_base_url }}/host/bin/mar.exe
+      s3_key: {{ s3_prefix }}mar-tools/win64/mar.exe
+    mar_tools_mbdiff:
+      artifact: {{ artifact_base_url }}/host/bin/mbsdiff.exe
+      s3_key: {{ s3_prefix }}mar-tools/win64/mbsdiff.exe
+  {% endif %}
+
+  {% if platform == "linux-i686" %}
     buildid_info:
       artifact: {{ artifact_base_url }}/target_info.txt
       s3_key: {{ s3_prefix }}linux_info.txt
     mar_tools_mar:
       artifact: {{ artifact_base_url }}/host/bin/mar
       s3_key: {{ s3_prefix }}mar-tools/linux/mar
     mar_tools_mbdiff:
       artifact: {{ artifact_base_url }}/host/bin/mbsdiff
       s3_key: {{ s3_prefix }}mar-tools/linux/mbsdiff
   {% endif %}
 
   {% if platform == "linux-x86_64" %}
-    buildinfo:
-      artifact: {{ artifact_base_url }}/target.json
-      s3_key: {{ s3_prefix }}{{ platform }}/{{ locale }}/firefox-{{ version }}.json
-    mozinfo:
-      artifact: {{ artifact_base_url }}/target.mozinfo.json
-      s3_key: {{ s3_prefix }}{{ platform }}/{{ locale }}/firefox-{{ version }}.mozinfo.json
-    socorroinfo:
-      artifact: {{ artifact_base_url }}/target.txt
-      s3_key: {{ s3_prefix }}{{ platform }}/{{ locale }}/firefox-{{ version }}.txt
-    jsshell:
-      artifact: {{ artifact_base_url }}/target.jsshell.zip
-      s3_key: {{ s3_prefix }}jsshell-{{ platform }}.zip
-    mozharness_package:
-      artifact: {{ artifact_base_url }}/mozharness.zip
-      s3_key: {{ s3_prefix }}{{ platform }}/{{ locale }}/mozharness.zip
-    xpi:
-      artifact: {{ artifact_base_url }}/target.langpack.xpi
-      s3_key: {{ s3_prefix }}{{ platform }}/xpi/{{ locale }}.xpi
-    symbols:
-      artifact: {{ artifact_base_url }}/target.crashreporter-symbols.zip
-      s3_key: {{ s3_prefix }}{{ platform }}/{{ locale }}/firefox-{{ version }}.crashreporter-symbols.zip
     buildid_info:
       artifact: {{ artifact_base_url }}/target_info.txt
       s3_key: {{ s3_prefix }}linux64_info.txt
     mar_tools_mar:
       artifact: {{ artifact_base_url }}/host/bin/mar
       s3_key: {{ s3_prefix }}mar-tools/linux64/mar
     mar_tools_mbdiff:
       artifact: {{ artifact_base_url }}/host/bin/mbsdiff
       s3_key: {{ s3_prefix }}mar-tools/linux64/mbsdiff
   {% endif %}
 
   {% if platform == "mac" %}
-    buildinfo:
-      artifact: {{ artifact_base_url }}/firefox-{{ app_version }}.{{ locale }}.{{ platform }}.json
-      s3_key: {{ s3_prefix }}{{ platform }}/{{ locale }}/firefox-{{ version }}.json
-    mozinfo:
-      artifact: {{ artifact_base_url }}/firefox-{{ app_version }}.{{ locale }}.{{ platform }}.mozinfo.json
-      s3_key: {{ s3_prefix }}{{ platform }}/{{ locale }}/firefox-{{ version }}.mozinfo.json
-    socorroinfo:
-      artifact: {{ artifact_base_url }}/firefox-{{ app_version }}.{{ locale }}.{{ platform }}.txt
-      s3_key: {{ s3_prefix }}{{ platform }}/{{ locale }}/firefox-{{ version }}.txt
-    jsshell:
-      artifact: {{ artifact_base_url }}/jsshell-{{ platform }}.zip
-      s3_key: {{ s3_prefix }}jsshell-{{ platform }}.zip
-    mozharness_package:
-      artifact: {{ artifact_base_url }}/mozharness.zip
-      s3_key: {{ s3_prefix }}{{ platform }}/{{ locale }}/mozharness.zip
-    xpi:
-      artifact: {{ artifact_base_url }}/firefox-{{ app_version }}.{{ locale }}.langpack.xpi
-      s3_key: {{ s3_prefix }}{{ platform }}/xpi/{{ locale }}.xpi
-    symbols:
-      artifact: {{ artifact_base_url }}/firefox-{{ app_version }}.{{ locale }}.{{ platform }}.crashreporter-symbols.zip
-      s3_key: {{ s3_prefix }}{{ platform }}/{{ locale }}/Firefox {{ version }}.crashreporter-symbols.zip
     buildid_info:
-      artifact: {{ artifact_base_url }}/firefox-{{ app_version }}.{{ locale }}.{{ platform }}_info.txt
+      artifact: {{ artifact_base_url }}/target_info.txt
       s3_key: {{ s3_prefix }}macosx64_info.txt
-    mar_tools_mar:
-      artifact: {{ artifact_base_url }}/mar
-      s3_key: {{ s3_prefix }}mar-tools/macosx64/mar
-    mar_tools_mbdiff:
-      artifact: {{ artifact_base_url }}/mbsdiff
-      s3_key: {{ s3_prefix }}mar-tools/macosx64/mbsdiff
   {% endif %}
 
 {% endfor %}
new file mode 100644
--- /dev/null
+++ b/testing/mozharness/configs/beetmover/en_us_repackage.yml.tmpl
@@ -0,0 +1,16 @@
+---
+metadata:
+    name: "Beet Mover Manifest"
+    description: "Maps artifact locations to s3 key names for the en-US locale"
+    owner: "release@mozilla.com"
+
+mapping:
+{% for locale in locales %}
+  {{ locale }}:
+  {% if platform == "mac" %}
+    package:
+      artifact: {{ artifact_base_url }}/target.dmg
+      s3_key: {{ s3_prefix }}{{ platform }}/{{ locale }}/Firefox {{ version }}.dmg
+  {% endif %}
+
+{% endfor %}
new file mode 100644
--- /dev/null
+++ b/testing/mozharness/configs/beetmover/en_us_repackage_signing.yml.tmpl
@@ -0,0 +1,40 @@
+---
+metadata:
+    name: "Beet Mover Manifest"
+    description: "Maps artifact locations to s3 key names for the en-US locale"
+    owner: "release@mozilla.com"
+
+mapping:
+{% for locale in locales %}
+  {{ locale }}:
+  {% if platform == "win32" %}
+    complete_mar:
+      artifact: {{ artifact_base_url }}/target.complete.mar
+      s3_key: {{ s3_prefix }}update/{{ platform }}/{{ locale }}/firefox-{{ version }}.complete.mar
+    full_installer:
+      artifact: {{ artifact_base_url }}/target.installer.exe
+      s3_key: {{ s3_prefix }}{{ platform }}/{{ locale }}/Firefox Setup {{ version }}.exe
+    {% if "esr" not in version %}
+    stub_installer:
+      artifact: {{ artifact_base_url }}/target.stub-installer.exe
+      s3_key: {{ s3_prefix }}{{ platform }}/{{ locale }}/Firefox Installer.exe
+    {% endif %}
+  {% endif %}
+
+  {% if platform == "win64" %}
+    complete_mar:
+      artifact: {{ artifact_base_url }}/target.complete.mar
+      s3_key: {{ s3_prefix }}update/{{ platform }}/{{ locale }}/firefox-{{ version }}.complete.mar
+    full_installer:
+      artifact: {{ artifact_base_url }}/target.installer.exe
+      s3_key: {{ s3_prefix }}{{ platform }}/{{ locale }}/Firefox Setup {{ version }}.exe
+  {% endif %}
+
+
+  {% if platform == "mac" %}
+    complete_mar:
+      artifact: {{ artifact_base_url }}/target.complete.mar
+      s3_key: {{ s3_prefix }}update/{{ platform }}/{{ locale }}/firefox-{{ version }}.complete.mar
+  {% endif %}
+
+{% endfor %}
--- a/testing/mozharness/configs/beetmover/en_us_signing.yml.tmpl
+++ b/testing/mozharness/configs/beetmover/en_us_signing.yml.tmpl
@@ -3,41 +3,24 @@ metadata:
     name: "Beet Mover Manifest"
     description: "Maps artifact locations to s3 key names for the en-US locale"
     owner: "release@mozilla.com"
 
 mapping:
 {% for locale in locales %}
   {{ locale }}:
   {% if platform == "win32" %}
-    complete_mar:
-      artifact: {{ artifact_base_url }}/firefox-{{ app_version }}.{{ locale }}.{{ platform }}.complete.mar
-      s3_key: {{ s3_prefix }}update/{{ platform }}/{{ locale }}/firefox-{{ version }}.complete.mar
-    full_installer:
-      artifact: {{ artifact_base_url }}/firefox-{{ app_version }}.{{ locale }}.{{ platform }}.installer.exe
-      s3_key: {{ s3_prefix }}{{ platform }}/{{ locale }}/Firefox Setup {{ version }}.exe
-    {% if "esr" not in version %}
-    stub_installer:
-      artifact: {{ artifact_base_url }}/firefox-{{ app_version }}.{{ locale }}.{{ platform }}.installer-stub.exe
-      s3_key: {{ s3_prefix }}{{ platform }}/{{ locale }}/Firefox Installer.exe
-    {% endif %}
     package:
-      artifact: {{ artifact_base_url }}/firefox-{{ app_version }}.{{ locale }}.{{ platform }}.zip
+      artifact: {{ artifact_base_url }}/target.zip
       s3_key: {{ s3_prefix }}{{ platform }}/{{ locale }}/firefox-{{ version }}.zip
   {% endif %}
 
   {% if platform == "win64" %}
-    complete_mar:
-      artifact: {{ artifact_base_url }}/firefox-{{ app_version }}.{{ locale }}.{{ platform }}.complete.mar
-      s3_key: {{ s3_prefix }}update/{{ platform }}/{{ locale }}/firefox-{{ version }}.complete.mar
-    full_installer:
-      artifact: {{ artifact_base_url }}/firefox-{{ app_version }}.{{ locale }}.{{ platform }}.installer.exe
-      s3_key: {{ s3_prefix }}{{ platform }}/{{ locale }}/Firefox Setup {{ version }}.exe
     package:
-      artifact: {{ artifact_base_url }}/firefox-{{ app_version }}.{{ locale }}.{{ platform }}.zip
+      artifact: {{ artifact_base_url }}/target.zip
       s3_key: {{ s3_prefix }}{{ platform }}/{{ locale }}/firefox-{{ version }}.zip
   {% endif %}
 
   {% if platform == "linux-i686" %}
     package:
       artifact: {{ artifact_base_url }}/target.tar.bz2
       s3_key: {{ s3_prefix }}{{ platform }}/{{ locale }}/firefox-{{ version }}.tar.bz2
     complete_mar:
@@ -50,17 +33,12 @@ mapping:
       artifact: {{ artifact_base_url }}/target.tar.bz2
       s3_key: {{ s3_prefix }}{{ platform }}/{{ locale }}/firefox-{{ version }}.tar.bz2
     complete_mar:
       artifact: {{ artifact_base_url }}/update/target.complete.mar
       s3_key: {{ s3_prefix }}update/{{ platform }}/{{ locale }}/firefox-{{ version }}.complete.mar
   {% endif %}
 
   {% if platform == "mac" %}
-    complete_mar:
-      artifact: {{ artifact_base_url }}/firefox-{{ app_version }}.{{ locale }}.{{ platform }}.complete.mar
-      s3_key: {{ s3_prefix }}update/{{ platform }}/{{ locale }}/firefox-{{ version }}.complete.mar
-    package:
-      artifact: {{ artifact_base_url }}/firefox-{{ app_version }}.{{ locale }}.{{ platform }}.dmg
-      s3_key: {{ s3_prefix }}{{ platform }}/{{ locale }}/Firefox {{ version }}.dmg
+  # nothing to see here
   {% endif %}
 
 {% endfor %}
--- a/testing/mozharness/scripts/merge_day/gecko_migration.py
+++ b/testing/mozharness/scripts/merge_day/gecko_migration.py
@@ -305,19 +305,19 @@ class GeckoMigration(MercurialScript, Ba
         # only applicable for m-c
         if bump_major:
             self.replace(
                 os.path.join(cwd, "xpcom/components/Module.h"),
                 "static const unsigned int kVersion = %s;" % curr_version,
                 "static const unsigned int kVersion = %s;" % next_version
             )
             self.replace(
-                os.path.join(cwd, "services/sync/moz.build"),
-                "DEFINES['weave_version'] = '1.%s.0'" % curr_weave_version,
-                "DEFINES['weave_version'] = '1.%s.0'" % next_weave_version
+                os.path.join(cwd, "services/sync/modules/constants.js"),
+                'WEAVE_VERSION: "1.%s.0"' % curr_weave_version,
+                'WEAVE_VERSION: "1.%s.0"' % next_weave_version
             )
 
     # Branch-specific workflow helper methods {{{1
     def central_to_beta(self, end_tag):
         """ mozilla-central -> mozilla-beta behavior.
 
             We could have all of these individually toggled by flags, but
             by separating into workflow methods we can be more precise about
--- a/testing/talos/talos.json
+++ b/testing/talos/talos.json
@@ -61,11 +61,22 @@
             "tests": ["quantum_pageload_google", "quantum_pageload_youtube", "quantum_pageload_amazon", "quantum_pageload_facebook"],
             "mitmproxy_recording_set": "mitmproxy-recording-set-win10.zip",
             "talos_options": [
                 "--stylo",
                 "--mitmproxy",
                 "mitmproxy-recording-google.mp mitmproxy-recording-youtube.mp mitmproxy-recording-amazon.mp mitmproxy-recording-facebook.mp",
                 "--firstNonBlankPaint"
             ]
+        },
+        "tp6-stylo-threads-e10s": {
+            "tests": ["tp6_google", "tp6_youtube", "tp6_amazon", "tp6_facebook"],
+            "mitmproxy_recording_set": "mitmproxy-recording-set-win10.zip",
+            "talos_options": [
+                "--stylo",
+                "--stylo-threads=1",
+                "--mitmproxy",
+                "mitmproxy-recording-google.mp mitmproxy-recording-youtube.mp mitmproxy-recording-amazon.mp mitmproxy-recording-facebook.mp",
+                "--firstNonBlankPaint"
+            ]
         }
     }
 }
--- a/testing/talos/talos/cmdline.py
+++ b/testing/talos/talos/cmdline.py
@@ -167,16 +167,19 @@ def create_parser(mach_interface=False):
             help="list available suites")
     add_arg('--no-upload-results', action="store_true",
             dest='no_upload_results',
             help="If given, it disables uploading of talos results.")
     add_arg('--stylo', action="store_true",
             dest='stylo',
             help='If given, enable Stylo via Environment variables and '
                  'upload results with Stylo options.')
+    add_arg('--stylo-threads', type=int,
+            dest='stylothreads',
+            help='If given, run stylo with a certain number of threads')
 
     add_logging_group(parser)
     return parser
 
 
 def parse_args(argv=None):
     parser = create_parser()
     return parser.parse_args(argv)
--- a/testing/talos/talos/config.py
+++ b/testing/talos/talos/config.py
@@ -434,16 +434,17 @@ def get_browser_config(config):
                 'repository': None,
                 'sourcestamp': None,
                 'symbols_path': None,
                 'test_timeout': 1200,
                 'xperf_path': None,
                 'error_filename': None,
                 'no_upload_results': False,
                 'stylo': False,
+                'stylothreads': 0,
                 }
     browser_config = dict(title=config['title'])
     browser_config.update(dict([(i, config[i]) for i in required]))
     browser_config.update(dict([(i, config.get(i, j))
                           for i, j in optional.items()]))
     return browser_config
 
 
--- a/testing/talos/talos/run_tests.py
+++ b/testing/talos/talos/run_tests.py
@@ -193,16 +193,20 @@ def run_tests(config, browser_config):
     # if e10s add as extra results option
     if config['e10s']:
         talos_results.add_extra_option('e10s')
 
     # stylo is another option for testing
     if config['stylo']:
         talos_results.add_extra_option('stylo')
 
+    # measuring the difference of a a certain thread level
+    if config.get('stylothreads', 0) > 0:
+        talos_results.add_extra_option('%s_thread' % config['stylothreads'])
+
     if config['gecko_profile']:
         talos_results.add_extra_option('geckoProfile')
 
     # some tests use mitmproxy to playback pages
     mitmproxy_recordings_list = config.get('mitmproxy', False)
     if mitmproxy_recordings_list is not False:
         # needed so can tell talos ttest to allow external connections
         browser_config['mitmproxy'] = True
--- a/testing/talos/talos/test.py
+++ b/testing/talos/talos/test.py
@@ -859,8 +859,40 @@ class quantum_pageload_amazon(QuantumPag
 
 
 @register_test()
 class quantum_pageload_facebook(QuantumPageloadTest):
     """
     Quantum Pageload Test - Facebook
     """
     tpmanifest = '${talos}/tests/quantum_pageload/quantum_pageload_facebook.manifest'
+
+
+@register_test()
+class tp6_google(QuantumPageloadTest):
+    """
+    Quantum Pageload Test - Google
+    """
+    tpmanifest = '${talos}/tests/quantum_pageload/quantum_pageload_google.manifest'
+
+
+@register_test()
+class tp6_youtube(QuantumPageloadTest):
+    """
+    Quantum Pageload Test - YouTube
+    """
+    tpmanifest = '${talos}/tests/quantum_pageload/quantum_pageload_youtube.manifest'
+
+
+@register_test()
+class tp6_amazon(QuantumPageloadTest):
+    """
+    Quantum Pageload Test - Amazon
+    """
+    tpmanifest = '${talos}/tests/quantum_pageload/quantum_pageload_amazon.manifest'
+
+
+@register_test()
+class tp6_facebook(QuantumPageloadTest):
+    """
+    Quantum Pageload Test - Facebook
+    """
+    tpmanifest = '${talos}/tests/quantum_pageload/quantum_pageload_facebook.manifest'
--- a/testing/talos/talos/ttest.py
+++ b/testing/talos/talos/ttest.py
@@ -91,16 +91,20 @@ class TTest(object):
         if test_config['mainthread']:
             mainthread_io = os.path.join(here, "mainthread_io.log")
             setup.env['MOZ_MAIN_THREAD_IO_LOG'] = mainthread_io
 
         # As we transition to Stylo, we need to set env vars and output data properly
         if browser_config['stylo']:
             setup.env['STYLO_FORCE_ENABLED'] = 1
 
+        # During the Stylo transition, measure different number of threads
+        if browser_config.get('stylothreads', 0) > 0:
+            setup.env['STYLO_THREADS'] = browser_config['stylothreads']
+
         test_config['url'] = utils.interpolate(
             test_config['url'],
             profile=setup.profile_dir,
             firefox=browser_config['browser_path']
         )
 
         # setup global (cross-cycle) counters:
         # shutdown, responsiveness
--- a/toolkit/components/printingui/win/nsPrintDialogUtil.cpp
+++ b/toolkit/components/printingui/win/nsPrintDialogUtil.cpp
@@ -250,19 +250,19 @@ static HWND CreateControl(LPCTSTR       
 //--------------------------------------------------------
 // Create a Radio Button
 static HWND CreateRadioBtn(HINSTANCE        aHInst,
                            HWND             aHdlg,
                            int              aId,
                            const char*      aStr,
                            const nsIntRect& aRect)
 {
-  nsString cStr;
-  cStr.AssignWithConversion(aStr);
-  return CreateControl("BUTTON", BS_RADIOBUTTON, aHInst, aHdlg, aId, cStr, aRect);
+  nsString str;
+  CopyASCIItoUTF16(aStr, str);
+  return CreateControl("BUTTON", BS_RADIOBUTTON, aHInst, aHdlg, aId, str, aRect);
 }
 
 //--------------------------------------------------------
 // Create a Group Box
 static HWND CreateGroupBox(HINSTANCE        aHInst,
                            HWND             aHdlg,
                            int              aId,
                            const nsAString& aStr,
--- a/toolkit/modules/Services.jsm
+++ b/toolkit/modules/Services.jsm
@@ -108,16 +108,16 @@ var initTable = [
   ["focus", "@mozilla.org/focus-manager;1", "nsIFocusManager"],
   ["uriFixup", "@mozilla.org/docshell/urifixup;1", "nsIURIFixup"],
   ["blocklist", "@mozilla.org/extensions/blocklist;1", "nsIBlocklistService"],
   ["netUtils", "@mozilla.org/network/util;1", "nsINetUtil"],
   ["loadContextInfo", "@mozilla.org/load-context-info-factory;1", "nsILoadContextInfoFactory"],
   ["qms", "@mozilla.org/dom/quota-manager-service;1", "nsIQuotaManagerService"],
 ];
 
-initTable.forEach(([name, contract, intf, enabled = true]) => {
+for (let [name, contract, intf, enabled = true] of initTable) {
   if (enabled) {
     XPCOMUtils.defineLazyServiceGetter(Services, name, contract, intf);
   }
-});
+}
 
 
 initTable = undefined;
--- a/toolkit/xre/nsEmbedFunctions.cpp
+++ b/toolkit/xre/nsEmbedFunctions.cpp
@@ -580,17 +580,17 @@ XRE_InitChildProcess(int aArgc,
   // On Win7+, register the application user model id passed in by
   // parent. This insures windows created by the container properly
   // group with the parent app on the Win7 taskbar.
   const char* const appModelUserId = aArgv[--aArgc];
   if (appModelUserId) {
     // '-' implies no support
     if (*appModelUserId != '-') {
       nsString appId;
-      appId.AssignWithConversion(nsDependentCString(appModelUserId));
+      CopyASCIItoUTF16(nsDependentCString(appModelUserId), appId);
       // The version string is encased in quotes
       appId.Trim("\"");
       // Set the id
       SetTaskbarGroupId(appId);
     }
   }
 #endif
 
--- a/widget/cocoa/nsCocoaUtils.mm
+++ b/widget/cocoa/nsCocoaUtils.mm
@@ -943,17 +943,17 @@ static const KeyConversionData gKeyConve
 uint32_t
 nsCocoaUtils::ConvertGeckoNameToMacCharCode(const nsAString& aKeyCodeName)
 {
   if (aKeyCodeName.IsEmpty()) {
     return 0;
   }
 
   nsAutoCString keyCodeName;
-  keyCodeName.AssignWithConversion(aKeyCodeName);
+  LossyCopyUTF16toASCII(aKeyCodeName, keyCodeName);
   // We want case-insensitive comparison with data stored as uppercase.
   ToUpperCase(keyCodeName);
 
   uint32_t keyCodeNameLength = keyCodeName.Length();
   const char* keyCodeNameStr = keyCodeName.get();
   for (uint16_t i = 0; i < ArrayLength(gKeyConversions); ++i) {
     if (keyCodeNameLength == gKeyConversions[i].strLength &&
         nsCRT::strcmp(gKeyConversions[i].str, keyCodeNameStr) == 0) {
--- a/xpcom/string/nsStringObsolete.cpp
+++ b/xpcom/string/nsStringObsolete.cpp
@@ -1026,26 +1026,9 @@ nsCString::ToDouble(nsresult* aErrorCode
 }
 
 double
 nsString::ToDouble(nsresult* aErrorCode) const
 {
   return NS_LossyConvertUTF16toASCII(*this).ToDouble(aErrorCode);
 }
 
-
-/**
- * nsTString::AssignWithConversion
- */
-
-void
-nsCString::AssignWithConversion( const nsAString& aData )
-{
-  LossyCopyUTF16toASCII(aData, *this);
-}
-
-void
-nsString::AssignWithConversion( const nsACString& aData )
-{
-  CopyASCIItoUTF16(aData, *this);
-}
-
 #endif // !MOZ_STRING_WITH_OBSOLETE_API
--- a/xpcom/string/nsTString.h
+++ b/xpcom/string/nsTString.h
@@ -425,25 +425,16 @@ public:
    *  string as well.
    *
    *  @param   aEliminateLeading controls stripping of leading ws
    *  @param   aEliminateTrailing controls stripping of trailing ws
    */
   void CompressWhitespace(bool aEliminateLeading = true,
                           bool aEliminateTrailing = true);
 
-
-  /**
-   * assign/append/insert with _LOSSY_ conversion
-   */
-
-  void AssignWithConversion(const nsTAString_IncompatibleCharT& aString);
-  void AssignWithConversion(const incompatible_char_type* aData,
-                            int32_t aLength = -1);
-
 #endif // !MOZ_STRING_WITH_OBSOLETE_API
 
   /**
    * Allow this string to be bound to a character buffer
    * until the string is rebound or mutated; the caller
    * must ensure that the buffer outlives the string.
    */
   void Rebind(const char_type* aData, size_type aLength);
--- a/xpcom/string/nsTStringObsolete.cpp
+++ b/xpcom/string/nsTStringObsolete.cpp
@@ -713,31 +713,8 @@ nsTString_CharT::CompressWhitespace( boo
   // If we need to trim the trailing whitespace, back up one character.
   if (aTrimTrailing && skipWS && to > mData) {
     to--;
   }
 
   *to = char_type(0); // add the null
   mLength = to - mData;
 }
-
-
-/**
- * nsTString::AssignWithConversion
- */
-
-void
-nsTString_CharT::AssignWithConversion( const incompatible_char_type* aData, int32_t aLength )
-{
-  // for compatibility with the old string implementation, we need to allow
-  // for a nullptr input buffer :-(
-  if (!aData)
-  {
-    Truncate();
-  }
-  else
-  {
-    if (aLength < 0)
-      aLength = nsCharTraits<incompatible_char_type>::length(aData);
-
-    AssignWithConversion(Substring(aData, aLength));
-  }
-}
--- a/xpcom/tests/gtest/TestCRT.cpp
+++ b/xpcom/tests/gtest/TestCRT.cpp
@@ -32,18 +32,18 @@ int sign(int val) {
 // iso-latin-1 strings, so the comparison must be valid.
 static void Check(const char* s1, const char* s2, int n)
 {
   int clib = PL_strcmp(s1, s2);
 
   int clib_n = PL_strncmp(s1, s2, n);
 
   nsAutoString t1,t2;
-  t1.AssignWithConversion(s1);
-  t2.AssignWithConversion(s2);
+  CopyASCIItoUTF16(s1, t1);
+  CopyASCIItoUTF16(s2, t2);
   const char16_t* us1 = t1.get();
   const char16_t* us2 = t2.get();
 
   int u2 = nsCRT::strcmp(us1, us2);
 
   int u2_n = nsCRT::strncmp(us1, us2, n);
 
   EXPECT_EQ(sign(clib), sign(u2));
--- a/xpcom/tests/gtest/TestStrings.cpp
+++ b/xpcom/tests/gtest/TestStrings.cpp
@@ -318,18 +318,18 @@ TEST(Strings, replace_substr)
 }
 
 TEST(Strings, replace_substr_2)
 {
   const char *oldName = nullptr;
   const char *newName = "user";
   nsString acctName; acctName.AssignLiteral("forums.foo.com");
   nsAutoString newAcctName, oldVal, newVal;
-  oldVal.AssignWithConversion(oldName);
-  newVal.AssignWithConversion(newName);
+  CopyASCIItoUTF16(oldName, oldVal);
+  CopyASCIItoUTF16(newName, newVal);
   newAcctName.Assign(acctName);
 
   // here, oldVal is empty.  we are testing that this function
   // does not hang.  see bug 235355.
   newAcctName.ReplaceSubstring(oldVal, newVal);
 
   // we expect that newAcctName will be unchanged.
   EXPECT_TRUE(newAcctName.Equals(acctName));
--- a/xpcom/threads/SystemGroup.cpp
+++ b/xpcom/threads/SystemGroup.cpp
@@ -83,22 +83,29 @@ SystemGroup::Initialized()
 {
   return SystemGroupImpl::Initialized();
 }
 
 /* static */ nsresult
 SystemGroup::Dispatch(TaskCategory aCategory,
                       already_AddRefed<nsIRunnable>&& aRunnable)
 {
+  if (!SystemGroupImpl::Initialized()) {
+    return NS_DispatchToMainThread(Move(aRunnable));
+  }
   return SystemGroupImpl::Get()->Dispatch(aCategory, Move(aRunnable));
 }
 
 /* static */ nsISerialEventTarget*
 SystemGroup::EventTargetFor(TaskCategory aCategory)
 {
+  if (!SystemGroupImpl::Initialized()) {
+    return GetMainThreadSerialEventTarget();
+  }
   return SystemGroupImpl::Get()->EventTargetFor(aCategory);
 }
 
 /* static */ AbstractThread*
 SystemGroup::AbstractMainThreadFor(TaskCategory aCategory)
 {
+  MOZ_ASSERT(SystemGroupImpl::Initialized());
   return SystemGroupImpl::Get()->AbstractMainThreadFor(aCategory);
 }
--- a/xpfe/appshell/nsXULWindow.cpp
+++ b/xpfe/appshell/nsXULWindow.cpp
@@ -1650,44 +1650,44 @@ NS_IMETHODIMP nsXULWindow::SavePersisten
   }
 
   bool shouldPersist = !isFullscreen && ownerXULDoc;
   ErrorResult rv;
   // (only for size elements which are persisted)
   if ((mPersistentAttributesDirty & PAD_POSITION) && gotRestoredBounds) {
     if (persistString.Find("screenX") >= 0) {
       SprintfLiteral(sizeBuf, "%d", NSToIntRound(rect.x / posScale.scale));
-      sizeString.AssignWithConversion(sizeBuf);
+      CopyASCIItoUTF16(sizeBuf, sizeString);
       docShellElement->SetAttribute(SCREENX_ATTRIBUTE, sizeString, rv);
       if (shouldPersist) {
         ownerXULDoc->Persist(windowElementId, SCREENX_ATTRIBUTE);
       }
     }
     if (persistString.Find("screenY") >= 0) {
       SprintfLiteral(sizeBuf, "%d", NSToIntRound(rect.y / posScale.scale));
-      sizeString.AssignWithConversion(sizeBuf);
+      CopyASCIItoUTF16(sizeBuf, sizeString);
       docShellElement->SetAttribute(SCREENY_ATTRIBUTE, sizeString, rv);
       if (shouldPersist) {
         ownerXULDoc->Persist(windowElementId, SCREENY_ATTRIBUTE);
       }
     }
   }
 
   if ((mPersistentAttributesDirty & PAD_SIZE) && gotRestoredBounds) {
     if (persistString.Find("width") >= 0) {
       SprintfLiteral(sizeBuf, "%d", NSToIntRound(rect.width / sizeScale.scale));
-      sizeString.AssignWithConversion(sizeBuf);
+      CopyASCIItoUTF16(sizeBuf, sizeString);
       docShellElement->SetAttribute(WIDTH_ATTRIBUTE, sizeString, rv);
       if (shouldPersist) {
         ownerXULDoc->Persist(windowElementId, WIDTH_ATTRIBUTE);
       }
     }
     if (persistString.Find("height") >= 0) {
       SprintfLiteral(sizeBuf, "%d", NSToIntRound(rect.height / sizeScale.scale));
-      sizeString.AssignWithConversion(sizeBuf);
+      CopyASCIItoUTF16(sizeBuf, sizeString);
       docShellElement->SetAttribute(HEIGHT_ATTRIBUTE, sizeString, rv);
       if (shouldPersist) {
         ownerXULDoc->Persist(windowElementId, HEIGHT_ATTRIBUTE);
       }
     }
   }
 
   if (mPersistentAttributesDirty & PAD_MISC) {
@@ -1706,17 +1706,17 @@ NS_IMETHODIMP nsXULWindow::SavePersisten
       }
     }
     if (persistString.Find("zlevel") >= 0) {
       uint32_t zLevel;
       nsCOMPtr<nsIWindowMediator> mediator(do_GetService(NS_WINDOWMEDIATOR_CONTRACTID));
       if (mediator) {
         mediator->GetZLevel(this, &zLevel);
         SprintfLiteral(sizeBuf, "%" PRIu32, zLevel);
-        sizeString.AssignWithConversion(sizeBuf);
+        CopyASCIItoUTF16(sizeBuf, sizeString);
         docShellElement->SetAttribute(ZLEVEL_ATTRIBUTE, sizeString, rv);
         if (shouldPersist) {
           ownerXULDoc->Persist(windowElementId, ZLEVEL_ATTRIBUTE);
         }
       }
     }
   }
 
--- a/xpfe/components/directory/nsDirectoryViewer.cpp
+++ b/xpfe/components/directory/nsDirectoryViewer.cpp
@@ -159,17 +159,17 @@ nsHTTPIndex::OnFTPControlLog(bool server
     dom::AutoEntryScript aes(globalObject,
                              "nsHTTPIndex OnFTPControlLog");
     JSContext* cx = aes.cx();
 
     JS::Rooted<JSObject*> global(cx, JS::CurrentGlobalOrNull(cx));
     NS_ENSURE_TRUE(global, NS_OK);
 
     nsString unicodeMsg;
-    unicodeMsg.AssignWithConversion(msg);
+    CopyASCIItoUTF16(msg, unicodeMsg);
     JSString* jsMsgStr = JS_NewUCStringCopyZ(cx, unicodeMsg.get());
     NS_ENSURE_TRUE(jsMsgStr, NS_ERROR_OUT_OF_MEMORY);
 
     JS::AutoValueArray<2> params(cx);
     params[0].setBoolean(server);
     params[1].setString(jsMsgStr);
 
     JS::Rooted<JS::Value> val(cx);
@@ -402,17 +402,17 @@ nsHTTPIndex::OnIndexAvailable(nsIRequest
   // constructed a resource for it, stored in entry. So now take a
   // second pass through the values and add as statements to the RDF
   // datasource.
 
   if (entry && NS_SUCCEEDED(rv)) {
     nsCOMPtr<nsIRDFLiteral> lit;
     nsString str;
 
-    str.AssignWithConversion(entryuriC.get());
+    CopyASCIItoUTF16(entryuriC, str);
 
     rv = mDirRDF->GetLiteral(str.get(), getter_AddRefs(lit));
 
     if (NS_SUCCEEDED(rv)) {
       rv = Assert(entry, kNC_URL, lit, true);
       if (NS_FAILED(rv)) return rv;
 
       nsXPIDLString xpstr;