Merge mozilla-inbound to mozilla-central. a=merge
authorCosmin Sabou <csabou@mozilla.com>
Sat, 27 Oct 2018 00:55:47 +0300
changeset 499628 3dc7cdbb2b5f
parent 499594 cffa05ba11d2 (current diff)
parent 499627 19c3422995b8 (diff)
child 499660 b5e9f8e954d6
child 499678 81402beaec3d
push id10290
push userffxbld-merge
push dateMon, 03 Dec 2018 16:23:23 +0000
treeherdermozilla-beta@700bed2445e6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone65.0a1
first release with
nightly linux32
3dc7cdbb2b5f / 65.0a1 / 20181026220839 / files
nightly linux64
3dc7cdbb2b5f / 65.0a1 / 20181026220839 / files
nightly mac
3dc7cdbb2b5f / 65.0a1 / 20181026220839 / files
nightly win32
3dc7cdbb2b5f / 65.0a1 / 20181026220839 / files
nightly win64
3dc7cdbb2b5f / 65.0a1 / 20181026220839 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge mozilla-inbound to mozilla-central. a=merge
js/src/moz.build
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -1192,16 +1192,18 @@ pref("services.sync.prefs.sync.privacy.c
 pref("services.sync.prefs.sync.privacy.clearOnShutdown.cookies", true);
 pref("services.sync.prefs.sync.privacy.clearOnShutdown.downloads", true);
 pref("services.sync.prefs.sync.privacy.clearOnShutdown.formdata", true);
 pref("services.sync.prefs.sync.privacy.clearOnShutdown.history", true);
 pref("services.sync.prefs.sync.privacy.clearOnShutdown.offlineApps", true);
 pref("services.sync.prefs.sync.privacy.clearOnShutdown.sessions", true);
 pref("services.sync.prefs.sync.privacy.clearOnShutdown.siteSettings", true);
 pref("services.sync.prefs.sync.privacy.donottrackheader.enabled", true);
+pref("services.sync.prefs.sync.privacy.fuzzyfox.enabled", true);
+pref("services.sync.prefs.sync.privacy.fuzzyfox.clockgrainus", true);
 pref("services.sync.prefs.sync.privacy.sanitize.sanitizeOnShutdown", true);
 pref("services.sync.prefs.sync.privacy.trackingprotection.enabled", true);
 pref("services.sync.prefs.sync.privacy.trackingprotection.pbmode.enabled", true);
 pref("services.sync.prefs.sync.privacy.resistFingerprinting", true);
 pref("services.sync.prefs.sync.privacy.reduceTimerPrecision", true);
 pref("services.sync.prefs.sync.privacy.resistFingerprinting.reduceTimerPrecision.microseconds", true);
 pref("services.sync.prefs.sync.privacy.resistFingerprinting.reduceTimerPrecision.jitter", true);
 pref("services.sync.prefs.sync.security.OCSP.enabled", true);
--- a/browser/config/mozconfigs/linux64/code-coverage-debug
+++ b/browser/config/mozconfigs/linux64/code-coverage-debug
@@ -1,3 +1,5 @@
 . "$topsrcdir/browser/config/mozconfigs/linux64/code-coverage"
 
 ac_add_options --enable-debug=-g1
+# We enable Rust tests on the debug build only, as the opt build is currently only used for fuzzing.
+ac_add_options --enable-rust-tests
--- a/browser/config/mozconfigs/win64/code-coverage
+++ b/browser/config/mozconfigs/win64/code-coverage
@@ -3,16 +3,17 @@ MOZ_AUTOMATION_L10N_CHECK=0
 . "$topsrcdir/browser/config/mozconfigs/common"
 . "$topsrcdir/browser/config/mozconfigs/win64/common-win64"
 
 ac_add_options --enable-optimize
 ac_add_options --enable-debug
 ac_add_options --disable-sandbox
 ac_add_options --disable-warnings-as-errors
 ac_add_options --enable-coverage
+ac_add_options --enable-rust-tests
 
 # Needed to enable breakpad in application.ini
 export MOZILLA_OFFICIAL=1
 
 # Enable Telemetry
 export MOZ_TELEMETRY_REPORTING=1
 
 . $topsrcdir/build/win64/mozconfig.vs-latest
--- 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: 2.0.936
+Current extension version is: 2.0.943
 
-Taken from upstream commit: d2189293
+Taken from upstream commit: dc98bf76
--- a/browser/extensions/pdfjs/content/build/pdf.js
+++ b/browser/extensions/pdfjs/content/build/pdf.js
@@ -118,18 +118,18 @@ return /******/ (function(modules) { // 
 /************************************************************************/
 /******/ ([
 /* 0 */
 /***/ (function(module, exports, __w_pdfjs_require__) {
 
 "use strict";
 
 
-var pdfjsVersion = '2.0.936';
-var pdfjsBuild = 'd2189293';
+var pdfjsVersion = '2.0.943';
+var pdfjsBuild = 'dc98bf76';
 var pdfjsSharedUtil = __w_pdfjs_require__(1);
 var pdfjsDisplayAPI = __w_pdfjs_require__(7);
 var pdfjsDisplayTextLayer = __w_pdfjs_require__(19);
 var pdfjsDisplayAnnotationLayer = __w_pdfjs_require__(20);
 var pdfjsDisplayDOMUtils = __w_pdfjs_require__(8);
 var pdfjsDisplaySVG = __w_pdfjs_require__(21);
 let pdfjsDisplayWorkerOptions = __w_pdfjs_require__(13);
 let pdfjsDisplayAPICompatibility = __w_pdfjs_require__(10);
@@ -4221,17 +4221,17 @@ function _fetchDocument(worker, source, 
     return Promise.reject(new Error('Worker was destroyed'));
   }
   if (pdfDataRangeTransport) {
     source.length = pdfDataRangeTransport.length;
     source.initialData = pdfDataRangeTransport.initialData;
   }
   return worker.messageHandler.sendWithPromise('GetDocRequest', {
     docId,
-    apiVersion: '2.0.936',
+    apiVersion: '2.0.943',
     source: {
       data: source.data,
       url: source.url,
       password: source.password,
       disableAutoFetch: source.disableAutoFetch,
       rangeChunkSize: source.rangeChunkSize,
       length: source.length
     },
@@ -4278,67 +4278,61 @@ var PDFDocumentLoadingTask = function PD
       });
     },
     then: function PDFDocumentLoadingTask_then(onFulfilled, onRejected) {
       return this.promise.then.apply(this.promise, arguments);
     }
   };
   return PDFDocumentLoadingTask;
 }();
-var PDFDataRangeTransport = function pdfDataRangeTransportClosure() {
-  function PDFDataRangeTransport(length, initialData) {
+class PDFDataRangeTransport {
+  constructor(length, initialData) {
     this.length = length;
     this.initialData = initialData;
     this._rangeListeners = [];
     this._progressListeners = [];
     this._progressiveReadListeners = [];
     this._readyCapability = (0, _util.createPromiseCapability)();
   }
-  PDFDataRangeTransport.prototype = {
-    addRangeListener: function PDFDataRangeTransport_addRangeListener(listener) {
-      this._rangeListeners.push(listener);
-    },
-    addProgressListener: function PDFDataRangeTransport_addProgressListener(listener) {
-      this._progressListeners.push(listener);
-    },
-    addProgressiveReadListener: function PDFDataRangeTransport_addProgressiveReadListener(listener) {
-      this._progressiveReadListeners.push(listener);
-    },
-    onDataRange: function PDFDataRangeTransport_onDataRange(begin, chunk) {
-      var listeners = this._rangeListeners;
-      for (var i = 0, n = listeners.length; i < n; ++i) {
-        listeners[i](begin, chunk);
-      }
-    },
-    onDataProgress: function PDFDataRangeTransport_onDataProgress(loaded) {
-      this._readyCapability.promise.then(() => {
-        var listeners = this._progressListeners;
-        for (var i = 0, n = listeners.length; i < n; ++i) {
-          listeners[i](loaded);
-        }
-      });
-    },
-    onDataProgressiveRead: function PDFDataRangeTransport_onDataProgress(chunk) {
-      this._readyCapability.promise.then(() => {
-        var listeners = this._progressiveReadListeners;
-        for (var i = 0, n = listeners.length; i < n; ++i) {
-          listeners[i](chunk);
-        }
-      });
-    },
-    transportReady: function PDFDataRangeTransport_transportReady() {
-      this._readyCapability.resolve();
-    },
-    requestDataRange: function PDFDataRangeTransport_requestDataRange(begin, end) {
-      (0, _util.unreachable)('Abstract method PDFDataRangeTransport.requestDataRange');
-    },
-    abort: function PDFDataRangeTransport_abort() {}
-  };
-  return PDFDataRangeTransport;
-}();
+  addRangeListener(listener) {
+    this._rangeListeners.push(listener);
+  }
+  addProgressListener(listener) {
+    this._progressListeners.push(listener);
+  }
+  addProgressiveReadListener(listener) {
+    this._progressiveReadListeners.push(listener);
+  }
+  onDataRange(begin, chunk) {
+    for (const listener of this._rangeListeners) {
+      listener(begin, chunk);
+    }
+  }
+  onDataProgress(loaded) {
+    this._readyCapability.promise.then(() => {
+      for (const listener of this._progressListeners) {
+        listener(loaded);
+      }
+    });
+  }
+  onDataProgressiveRead(chunk) {
+    this._readyCapability.promise.then(() => {
+      for (const listener of this._progressiveReadListeners) {
+        listener(chunk);
+      }
+    });
+  }
+  transportReady() {
+    this._readyCapability.resolve();
+  }
+  requestDataRange(begin, end) {
+    (0, _util.unreachable)('Abstract method PDFDataRangeTransport.requestDataRange');
+  }
+  abort() {}
+}
 class PDFDocumentProxy {
   constructor(pdfInfo, transport, loadingTask) {
     this.loadingTask = loadingTask;
     this._pdfInfo = pdfInfo;
     this._transport = transport;
   }
   get numPages() {
     return this._pdfInfo.numPages;
@@ -5556,18 +5550,18 @@ var InternalRenderTask = function Intern
         }
       });
     }
   };
   return InternalRenderTask;
 }();
 var version, build;
 {
-  exports.version = version = '2.0.936';
-  exports.build = build = 'd2189293';
+  exports.version = version = '2.0.943';
+  exports.build = build = 'dc98bf76';
 }
 exports.getDocument = getDocument;
 exports.LoopbackPort = LoopbackPort;
 exports.PDFDataRangeTransport = PDFDataRangeTransport;
 exports.PDFWorker = PDFWorker;
 exports.PDFDocumentProxy = PDFDocumentProxy;
 exports.PDFPageProxy = PDFPageProxy;
 exports.setPDFNetworkStreamFactory = setPDFNetworkStreamFactory;
--- a/browser/extensions/pdfjs/content/build/pdf.worker.js
+++ b/browser/extensions/pdfjs/content/build/pdf.worker.js
@@ -118,18 +118,18 @@ return /******/ (function(modules) { // 
 /************************************************************************/
 /******/ ([
 /* 0 */
 /***/ (function(module, exports, __w_pdfjs_require__) {
 
 "use strict";
 
 
-var pdfjsVersion = '2.0.936';
-var pdfjsBuild = 'd2189293';
+var pdfjsVersion = '2.0.943';
+var pdfjsBuild = 'dc98bf76';
 var pdfjsCoreWorker = __w_pdfjs_require__(1);
 exports.WorkerMessageHandler = pdfjsCoreWorker.WorkerMessageHandler;
 
 /***/ }),
 /* 1 */
 /***/ (function(module, exports, __w_pdfjs_require__) {
 
 "use strict";
@@ -322,17 +322,17 @@ var WorkerMessageHandler = {
     });
   },
   createDocumentHandler(docParams, port) {
     var pdfManager;
     var terminated = false;
     var cancelXHRs = null;
     var WorkerTasks = [];
     let apiVersion = docParams.apiVersion;
-    let workerVersion = '2.0.936';
+    let workerVersion = '2.0.943';
     if (apiVersion !== workerVersion) {
       throw new Error(`The API version "${apiVersion}" does not match ` + `the Worker version "${workerVersion}".`);
     }
     var docId = docParams.docId;
     var docBaseUrl = docParams.docBaseUrl;
     var workerHandlerName = docParams.docId + '_worker';
     var handler = new _message_handler.MessageHandler(workerHandlerName, docId, port);
     handler.postMessageTransfers = docParams.postMessageTransfers;
--- a/browser/extensions/pdfjs/content/web/viewer.js
+++ b/browser/extensions/pdfjs/content/web/viewer.js
@@ -9008,29 +9008,27 @@ class MozL10n {
       highlightAll: !!detail.highlightAll,
       findPrevious: !!detail.findPrevious
     });
   };
   for (let event of events) {
     window.addEventListener(event, handleEvent);
   }
 })();
-function FirefoxComDataRangeTransport(length, initialData) {
-  _pdfjsLib.PDFDataRangeTransport.call(this, length, initialData);
-}
-FirefoxComDataRangeTransport.prototype = Object.create(_pdfjsLib.PDFDataRangeTransport.prototype);
-FirefoxComDataRangeTransport.prototype.requestDataRange = function FirefoxComDataRangeTransport_requestDataRange(begin, end) {
-  FirefoxCom.request('requestDataRange', {
-    begin,
-    end
-  });
-};
-FirefoxComDataRangeTransport.prototype.abort = function FirefoxComDataRangeTransport_abort() {
-  FirefoxCom.requestSync('abortLoading', null);
-};
+class FirefoxComDataRangeTransport extends _pdfjsLib.PDFDataRangeTransport {
+  requestDataRange(begin, end) {
+    FirefoxCom.request('requestDataRange', {
+      begin,
+      end
+    });
+  }
+  abort() {
+    FirefoxCom.requestSync('abortLoading', null);
+  }
+}
 _app.PDFViewerApplication.externalServices = {
   updateFindControlState(data) {
     FirefoxCom.request('updateFindControlState', data);
   },
   updateFindMatchesCount(data) {
     FirefoxCom.request('updateFindMatchesCount', data);
   },
   initPassiveLoading(callbacks) {
--- a/browser/extensions/pdfjs/moz.yaml
+++ b/browser/extensions/pdfjs/moz.yaml
@@ -15,15 +15,15 @@ origin:
   description: Portable Document Format (PDF) viewer that is built with HTML5
 
   # Full URL for the package's homepage/etc
   # Usually different from repository url
   url: https://github.com/mozilla/pdf.js
 
   # Human-readable identifier for this version/release
   # Generally "version NNN", "tag SSS", "bookmark SSS"
-  release: version 2.0.936
+  release: version 2.0.943
 
   # The package's license, where possible using the mnemonic from
   # https://spdx.org/licenses/
   # Multiple licenses can be specified (as a YAML list)
   # A "LICENSE" file must exist containing the full license text
   license: Apache-2.0
--- a/config/external/ffi/moz.build
+++ b/config/external/ffi/moz.build
@@ -72,16 +72,18 @@ else:
     # Per-platform sources and flags.
     ffi_srcs = ()
     if CONFIG['FFI_TARGET'] == 'ARM':
         ffi_srcs = ('sysv.S', 'ffi.c')
         if CONFIG['CC_TYPE'] == 'clang':
             ASFLAGS += ['-no-integrated-as']
     elif CONFIG['FFI_TARGET'] == 'AARCH64':
         ffi_srcs = ('sysv.S', 'ffi.c')
+    elif CONFIG['FFI_TARGET'] == 'ARM64_WIN64':
+        ffi_srcs = ('win64.asm', 'ffi.c')
     elif CONFIG['FFI_TARGET'] == 'X86':
         ffi_srcs = ('ffi.c', 'sysv.S', 'win32.S')
     elif CONFIG['FFI_TARGET'] == 'X86_64':
         ffi_srcs = ('ffi64.c', 'unix64.S', 'ffi.c', 'sysv.S')
     elif CONFIG['FFI_TARGET'] == 'X86_WIN32':
         ffi_srcs = ['ffi.c']
         # MinGW Build for 32 bit
         if CONFIG['CC_TYPE'] in ('gcc', 'clang'):
--- a/dom/base/nsDeprecatedOperationList.h
+++ b/dom/base/nsDeprecatedOperationList.h
@@ -44,8 +44,9 @@ DEPRECATED_OPERATION(MixedDisplayObjectS
 DEPRECATED_OPERATION(MotionEvent)
 DEPRECATED_OPERATION(OrientationEvent)
 DEPRECATED_OPERATION(ProximityEvent)
 DEPRECATED_OPERATION(AmbientLightEvent)
 DEPRECATED_OPERATION(IDBOpenDBOptions_StorageType)
 DEPRECATED_OPERATION(DOMAttrModifiedEvent)
 DEPRECATED_OPERATION(MozBoxOrInlineBoxDisplay)
 DEPRECATED_OPERATION(DOMQuadBoundsAttr)
+DEPRECATED_OPERATION(CreateImageBitmapCanvasRenderingContext2D)
--- a/dom/base/nsDocument.cpp
+++ b/dom/base/nsDocument.cpp
@@ -10709,18 +10709,22 @@ public:
   {
   public:
     explicit Iterator(nsIDocument* aDoc, IteratorOption aOption)
       : mCurrent(PendingFullscreenChangeList::sList.getFirst())
       , mRootShellForIteration(aDoc->GetDocShell())
     {
       if (mCurrent) {
         if (mRootShellForIteration && aOption == eDocumentsWithSameRoot) {
+          // Use a temporary to avoid undefined behavior from passing
+          // mRootShellForIteration.
+          nsCOMPtr<nsIDocShellTreeItem> root;
           mRootShellForIteration->
-            GetRootTreeItem(getter_AddRefs(mRootShellForIteration));
+            GetRootTreeItem(getter_AddRefs(root));
+          mRootShellForIteration = root.forget();
         }
         SkipToNextMatch();
       }
     }
 
     UniquePtr<T> TakeAndNext()
     {
       auto thisChange = TakeAndNextInternal();
@@ -10746,17 +10750,19 @@ public:
           if (!docShell) {
             // Always automatically drop fullscreen changes which are
             // from a document detached from the doc shell.
             UniquePtr<T> change = TakeAndNextInternal();
             change->MayRejectPromise();
             continue;
           }
           while (docShell && docShell != mRootShellForIteration) {
-            docShell->GetParent(getter_AddRefs(docShell));
+            nsCOMPtr<nsIDocShellTreeItem> parent;
+            docShell->GetParent(getter_AddRefs(parent));
+            docShell = parent.forget();
           }
           if (docShell) {
             break;
           }
         }
         // The current one either don't have matched type, or isn't
         // inside the given subtree, so skip this item.
         mCurrent = mCurrent->getNext();
--- a/dom/canvas/ImageBitmap.cpp
+++ b/dom/canvas/ImageBitmap.cpp
@@ -1056,16 +1056,25 @@ ImageBitmap::CreateInternal(nsIGlobalObj
 
   return ret.forget();
 }
 
 /* static */ already_AddRefed<ImageBitmap>
 ImageBitmap::CreateInternal(nsIGlobalObject* aGlobal, CanvasRenderingContext2D& aCanvasCtx,
                             const Maybe<IntRect>& aCropRect, ErrorResult& aRv)
 {
+  nsCOMPtr<nsPIDOMWindowInner> win = do_QueryInterface(aGlobal);
+  nsGlobalWindowInner* window = nsGlobalWindowInner::Cast(win);
+  if (NS_WARN_IF(!window) || !window->GetExtantDoc()) {
+    aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
+    return nullptr;
+  }
+
+  window->GetExtantDoc()->WarnOnceAbout(nsIDocument::eCreateImageBitmapCanvasRenderingContext2D);
+
   // Check origin-clean.
   if (aCanvasCtx.GetCanvas()->IsWriteOnly()) {
     aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
     return nullptr;
   }
 
   RefPtr<SourceSurface> surface = aCanvasCtx.GetSurfaceSnapshot();
 
--- a/dom/locales/en-US/chrome/dom/dom.properties
+++ b/dom/locales/en-US/chrome/dom/dom.properties
@@ -353,8 +353,10 @@ MixedDisplayObjectSubrequestWarning=Load
 MotionEventWarning=Use of the motion sensor is deprecated.
 OrientationEventWarning=Use of the orientation sensor is deprecated.
 ProximityEventWarning=Use of the proximity sensor is deprecated.
 AmbientLightEventWarning=Use of the ambient light sensor is deprecated.
 # LOCALIZATION NOTE: Do not translate "storage", "indexedDB.open" and "navigator.storage.persist()".
 IDBOpenDBOptions_StorageTypeWarning=The ‘storage’ attribute in options passed to indexedDB.open is deprecated and will soon be removed. To get persistent storage, please use navigator.storage.persist() instead.
 DOMQuadBoundsAttrWarning=DOMQuad.bounds is deprecated in favor of DOMQuad.getBounds()
 UnsupportedEntryTypesIgnored=Ignoring unsupported entryTypes: %S.
+# LOCALIZATION NOTE (CreateImageBitmapCanvasRenderingContext2DWarning): Do not translate CanvasRenderingContext2D and createImageBitmap.
+CreateImageBitmapCanvasRenderingContext2DWarning=Use of CanvasRenderingContext2D in createImageBitmap is deprecated.
--- a/dom/performance/Performance.cpp
+++ b/dom/performance/Performance.cpp
@@ -104,17 +104,17 @@ Performance::Now()
   const double maxResolutionMs = 0.020;
   DOMHighResTimeStamp minimallyClamped = floor(rawTime / maxResolutionMs) * maxResolutionMs;
   return nsRFPService::ReduceTimePrecisionAsMSecs(minimallyClamped, GetRandomTimelineSeed());
 }
 
 DOMHighResTimeStamp
 Performance::NowUnclamped() const
 {
-  TimeDuration duration = TimeStamp::Now() - CreationTimeStamp();
+  TimeDuration duration = TimeStamp::NowUnfuzzed() - CreationTimeStamp();
   return duration.ToMilliseconds();
 }
 
 DOMHighResTimeStamp
 Performance::TimeOrigin()
 {
   if (!mPerformanceService) {
     mPerformanceService = PerformanceService::GetOrCreate();
--- a/ipc/glue/IPCMessageUtils.h
+++ b/ipc/glue/IPCMessageUtils.h
@@ -822,25 +822,53 @@ struct ParamTraits<mozilla::TimeStamp>
 template<>
 struct ParamTraits<mozilla::TimeStampValue>
 {
   typedef mozilla::TimeStampValue paramType;
   static void Write(Message* aMsg, const paramType& aParam)
   {
     WriteParam(aMsg, aParam.mGTC);
     WriteParam(aMsg, aParam.mQPC);
+    WriteParam(aMsg, aParam.mUsedCanonicalNow);
+    WriteParam(aMsg, aParam.mIsNull);
     WriteParam(aMsg, aParam.mHasQPC);
-    WriteParam(aMsg, aParam.mIsNull);
   }
   static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
   {
     return (ReadParam(aMsg, aIter, &aResult->mGTC) &&
             ReadParam(aMsg, aIter, &aResult->mQPC) &&
-            ReadParam(aMsg, aIter, &aResult->mHasQPC) &&
-            ReadParam(aMsg, aIter, &aResult->mIsNull));
+            ReadParam(aMsg, aIter, &aResult->mUsedCanonicalNow) &&
+            ReadParam(aMsg, aIter, &aResult->mIsNull) &&
+            ReadParam(aMsg, aIter, &aResult->mHasQPC));
+  }
+};
+
+#else
+
+template<>
+struct ParamTraits<mozilla::TimeStamp63Bit>
+{
+  typedef mozilla::TimeStamp63Bit paramType;
+  static void Write(Message* aMsg, const paramType& aParam)
+  {
+    WriteParam(aMsg, aParam.mUsedCanonicalNow);
+    WriteParam(aMsg, aParam.mTimeStamp);
+  }
+  static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
+  {
+    bool success = true;
+    uint64_t result;
+
+    success &= ReadParam(aMsg, aIter, &result);
+    aResult->mUsedCanonicalNow = result & 0x01;
+
+    success &= ReadParam(aMsg, aIter, &result);
+    aResult->mTimeStamp = result & 0x7FFFFFFFFFFFFFFF;
+
+    return success;
   }
 };
 
 #endif
 
 template <>
 struct ParamTraits<mozilla::dom::ipc::StructuredCloneData>
 {
--- a/js/ffi.configure
+++ b/js/ffi.configure
@@ -28,21 +28,21 @@ add_old_configure_assignment('MOZ_SYSTEM
 # Target selection, based on ffi/configure.ac.
 @depends(target, when=building_ffi)
 def ffi_target(target):
     if target.cpu not in ('x86', 'x86_64', 'arm', 'aarch64'):
         die('Building libffi from the tree is not supported on this platform. '
             'Use --with-system-ffi instead.')
 
     if target.os == 'WINNT':
-        target_dir = 'x86'
-        if target.cpu == 'x86_64':
-            target_name = 'X86_WIN64'
-        else:
-            target_name = 'X86_WIN32'
+        target_dir, target_name = {
+            'x86_64': ('x86', 'X86_WIN64'),
+            'x86': ('x86', 'X86_WIN32'),
+            'aarch64': ('aarch64', 'ARM64_WIN64'),
+        }[target.cpu]
     elif target.os == 'OSX':
         target_dir = 'x86'
         target_name = 'X86_DARWIN'
     elif target.cpu == 'arm':
         target_dir = 'arm'
         target_name = 'ARM'
     elif target.cpu == 'aarch64':
         target_dir = 'aarch64'
--- a/js/src/builtin/intl/DateTimeFormat.js
+++ b/js/src/builtin/intl/DateTimeFormat.js
@@ -875,59 +875,42 @@ function Intl_DateTimeFormat_resolvedOpt
     }
 
     resolveICUPattern(internals.pattern, result);
 
     // Step 6.
     return result;
 }
 
-// Table mapping ICU pattern characters back to the corresponding date-time
-// components of DateTimeFormat. See
-// http://unicode.org/reports/tr35/tr35-dates.html#Date_Field_Symbol_Table
-var icuPatternCharToComponent = {
-    E: "weekday",
-    G: "era",
-    y: "year",
-    M: "month",
-    L: "month",
-    d: "day",
-    h: "hour",
-    H: "hour",
-    k: "hour",
-    K: "hour",
-    m: "minute",
-    s: "second",
-    z: "timeZoneName",
-    v: "timeZoneName",
-    V: "timeZoneName",
-};
-
+/* eslint-disable complexity */
 /**
  * Maps an ICU pattern string to a corresponding set of date-time components
  * and their values, and adds properties for these components to the result
  * object, which will be returned by the resolvedOptions method. For the
  * interpretation of ICU pattern characters, see
  * http://unicode.org/reports/tr35/tr35-dates.html#Date_Field_Symbol_Table
  */
 function resolveICUPattern(pattern, result) {
     assert(IsObject(result), "resolveICUPattern");
+
+    var hourCycle, weekday, era, year, month, day, hour, minute, second, timeZoneName;
     var i = 0;
     while (i < pattern.length) {
         var c = pattern[i++];
         if (c === "'") {
             while (i < pattern.length && pattern[i] !== "'")
                 i++;
             i++;
         } else {
             var count = 1;
             while (i < pattern.length && pattern[i] === c) {
                 i++;
                 count++;
             }
+
             var value;
             switch (c) {
             // "text" cases
             case "G":
             case "E":
             case "z":
             case "v":
             case "V":
@@ -964,31 +947,93 @@ function resolveICUPattern(pattern, resu
                 else if (count === 4)
                     value = "long";
                 else
                     value = "narrow";
                 break;
             default:
                 // skip other pattern characters and literal text
             }
-            if (hasOwn(c, icuPatternCharToComponent))
-                _DefineDataProperty(result, icuPatternCharToComponent[c], value);
+
+            // Map ICU pattern characters back to the corresponding date-time
+            // components of DateTimeFormat. See
+            // http://unicode.org/reports/tr35/tr35-dates.html#Date_Field_Symbol_Table
             switch (c) {
+            case "E":
+                weekday = value;
+                break;
+            case "G":
+                era = value;
+                break;
+            case "y":
+                year = value;
+                break;
+            case "M":
+            case "L":
+                month = value;
+                break;
+            case "d":
+                day = value;
+                break;
             case "h":
-                _DefineDataProperty(result, "hourCycle", "h12");
-                _DefineDataProperty(result, "hour12", true);
+                hourCycle = "h12";
+                hour = value;
+                break;
+            case "H":
+                hourCycle = "h23";
+                hour = value;
+                break;
+            case "k":
+                hourCycle = "h24";
+                hour = value;
                 break;
             case "K":
-                _DefineDataProperty(result, "hourCycle", "h11");
-                _DefineDataProperty(result, "hour12", true);
+                hourCycle = "h11";
+                hour = value;
+                break;
+            case "m":
+                minute = value;
                 break;
-            case "H":
-                _DefineDataProperty(result, "hourCycle", "h23");
-                _DefineDataProperty(result, "hour12", false);
+            case "s":
+                second = value;
                 break;
-            case "k":
-                _DefineDataProperty(result, "hourCycle", "h24");
-                _DefineDataProperty(result, "hour12", false);
+            case "z":
+            case "v":
+            case "V":
+                timeZoneName = value;
                 break;
             }
         }
     }
+
+    if (hourCycle) {
+        _DefineDataProperty(result, "hourCycle", hourCycle);
+        _DefineDataProperty(result, "hour12", hourCycle === "h11" || hourCycle === "h12");
+    }
+    if (weekday) {
+        _DefineDataProperty(result, "weekday", weekday);
+    }
+    if (era) {
+        _DefineDataProperty(result, "era", era);
+    }
+    if (year) {
+        _DefineDataProperty(result, "year", year);
+    }
+    if (month) {
+        _DefineDataProperty(result, "month", month);
+    }
+    if (day) {
+        _DefineDataProperty(result, "day", day);
+    }
+    if (hour) {
+        _DefineDataProperty(result, "hour", hour);
+    }
+    if (minute) {
+        _DefineDataProperty(result, "minute", minute);
+    }
+    if (second) {
+        _DefineDataProperty(result, "second", second);
+    }
+    if (timeZoneName) {
+        _DefineDataProperty(result, "timeZoneName", timeZoneName);
+    }
 }
+/* eslint-enable complexity */
--- a/js/src/builtin/intl/NumberFormat.js
+++ b/js/src/builtin/intl/NumberFormat.js
@@ -475,40 +475,42 @@ function Intl_NumberFormat_resolvedOptio
 
     var internals = getNumberFormatInternals(nf);
 
     // Steps 4-5.
     var result = {
         locale: internals.locale,
         numberingSystem: internals.numberingSystem,
         style: internals.style,
-        minimumIntegerDigits: internals.minimumIntegerDigits,
-        minimumFractionDigits: internals.minimumFractionDigits,
-        maximumFractionDigits: internals.maximumFractionDigits,
-        useGrouping: internals.useGrouping,
     };
 
     // currency and currencyDisplay are only present for currency formatters.
     assert(hasOwn("currency", internals) === (internals.style === "currency"),
            "currency is present iff style is 'currency'");
     assert(hasOwn("currencyDisplay", internals) === (internals.style === "currency"),
            "currencyDisplay is present iff style is 'currency'");
 
     if (hasOwn("currency", internals)) {
         _DefineDataProperty(result, "currency", internals.currency);
         _DefineDataProperty(result, "currencyDisplay", internals.currencyDisplay);
     }
 
+    _DefineDataProperty(result, "minimumIntegerDigits", internals.minimumIntegerDigits);
+    _DefineDataProperty(result, "minimumFractionDigits", internals.minimumFractionDigits);
+    _DefineDataProperty(result, "maximumFractionDigits", internals.maximumFractionDigits);
+
     // Min/Max significant digits are either both present or not at all.
     assert(hasOwn("minimumSignificantDigits", internals) ===
            hasOwn("maximumSignificantDigits", internals),
            "minimumSignificantDigits is present iff maximumSignificantDigits is present");
 
     if (hasOwn("minimumSignificantDigits", internals)) {
         _DefineDataProperty(result, "minimumSignificantDigits",
                             internals.minimumSignificantDigits);
         _DefineDataProperty(result, "maximumSignificantDigits",
                             internals.maximumSignificantDigits);
     }
 
+    _DefineDataProperty(result, "useGrouping", internals.useGrouping);
+
     // Step 6.
     return result;
 }
--- a/js/src/builtin/intl/PluralRules.js
+++ b/js/src/builtin/intl/PluralRules.js
@@ -221,34 +221,20 @@ function Intl_PluralRules_resolvedOption
     // Steps 2-3.
     if (!IsObject(pluralRules) || (pluralRules = GuardToPluralRules(pluralRules)) === null) {
         ThrowTypeError(JSMSG_INTL_OBJECT_NOT_INITED, "PluralRules", "resolvedOptions",
                        "PluralRules");
     }
 
     var internals = getPluralRulesInternals(pluralRules);
 
-    var internalsPluralCategories = internals.pluralCategories;
-    if (internalsPluralCategories === null) {
-        internalsPluralCategories = intl_GetPluralCategories(pluralRules);
-        internals.pluralCategories = internalsPluralCategories;
-    }
-
-    // TODO: The current spec actually requires to return the internal array
-    // object and not a copy of it.
-    // <https://github.com/tc39/proposal-intl-plural-rules/issues/28#issuecomment-341557030>
-    var pluralCategories = [];
-    for (var i = 0; i < internalsPluralCategories.length; i++)
-        _DefineDataProperty(pluralCategories, i, internalsPluralCategories[i]);
-
     // Steps 4-5.
     var result = {
         locale: internals.locale,
         type: internals.type,
-        pluralCategories,
         minimumIntegerDigits: internals.minimumIntegerDigits,
         minimumFractionDigits: internals.minimumFractionDigits,
         maximumFractionDigits: internals.maximumFractionDigits,
     };
 
     // Min/Max significant digits are either both present or not at all.
     assert(hasOwn("minimumSignificantDigits", internals) ===
            hasOwn("maximumSignificantDigits", internals),
@@ -257,10 +243,24 @@ function Intl_PluralRules_resolvedOption
     if (hasOwn("minimumSignificantDigits", internals)) {
         _DefineDataProperty(result, "minimumSignificantDigits",
                             internals.minimumSignificantDigits);
         _DefineDataProperty(result, "maximumSignificantDigits",
                             internals.maximumSignificantDigits);
     }
 
     // Step 6.
+    var internalsPluralCategories = internals.pluralCategories;
+    if (internalsPluralCategories === null) {
+        internalsPluralCategories = intl_GetPluralCategories(pluralRules);
+        internals.pluralCategories = internalsPluralCategories;
+    }
+
+    var pluralCategories = [];
+    for (var i = 0; i < internalsPluralCategories.length; i++)
+        _DefineDataProperty(pluralCategories, i, internalsPluralCategories[i]);
+
+    // Step 7.
+    _DefineDataProperty(result, "pluralCategories", pluralCategories);
+
+    // Step 8.
     return result;
 }
--- a/js/src/builtin/intl/RelativeTimeFormat.js
+++ b/js/src/builtin/intl/RelativeTimeFormat.js
@@ -214,17 +214,17 @@ function Intl_RelativeTimeFormat_format(
         ThrowRangeError(JSMSG_INVALID_OPTION_VALUE, "unit", u);
     }
 
     // Step 5.
     return intl_FormatRelativeTime(relativeTimeFormat, t, u, internals.numeric);
 }
 
 /**
- * Returns the resolved options for a PluralRules object.
+ * Returns the resolved options for a RelativeTimeFormat object.
  *
  * Spec: ECMAScript 402 API, RelativeTimeFormat, 1.4.4.
  */
 function Intl_RelativeTimeFormat_resolvedOptions() {
     var relativeTimeFormat;
     // Check "this RelativeTimeFormat object" per introduction of section 1.4.
     if (!IsObject(this) || (relativeTimeFormat = GuardToRelativeTimeFormat(this)) === null) {
         ThrowTypeError(JSMSG_INTL_OBJECT_NOT_INITED, "RelativeTimeFormat", "resolvedOptions",
--- a/js/src/ctypes/CTypes.cpp
+++ b/js/src/ctypes/CTypes.cpp
@@ -6803,33 +6803,45 @@ GetABI(JSContext* cx, HandleValue abiTyp
   // given platform. ABI_DEFAULT specifies the default
   // C calling convention (cdecl) on each platform.
   switch (abi) {
   case ABI_DEFAULT:
     *result = FFI_DEFAULT_ABI;
     return true;
   case ABI_THISCALL:
 #if defined(_WIN64)
+#if defined(_M_X64)
     *result = FFI_WIN64;
+#elif defined(_M_ARM64)
+    *result = FFI_SYSV;
+#else
+#error unknown 64-bit Windows platform
+#endif
     return true;
 #elif defined(_WIN32)
     *result = FFI_THISCALL;
     return true;
 #else
     break;
 #endif
   case ABI_STDCALL:
   case ABI_WINAPI:
 #if (defined(_WIN32) && !defined(_WIN64)) || defined(_OS2)
     *result = FFI_STDCALL;
     return true;
 #elif (defined(_WIN64))
     // We'd like the same code to work across Win32 and Win64, so stdcall_api
     // and winapi_abi become aliases to the lone Win64 ABI.
+#if defined(_M_X64)
     *result = FFI_WIN64;
+#elif defined(_M_ARM64)
+    *result = FFI_SYSV;
+#else
+#error unknown 64-bit Windows platform
+#endif
     return true;
 #endif
   case INVALID_ABI:
     break;
   }
   return false;
 }
 
--- a/js/src/ctypes/libffi/src/aarch64/ffi.c
+++ b/js/src/ctypes/libffi/src/aarch64/ffi.c
@@ -21,16 +21,23 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 
 #include <stdio.h>
 
 #include <ffi.h>
 #include <ffi_common.h>
 
 #include <stdlib.h>
 
+#if defined(_WIN32)
+#if !defined(WIN32_LEAN_AND_MEAN)
+#define WIN32_LEAN_AND_MEAN
+#endif
+#include <windows.h>
+#endif
+
 /* Stack alignment requirement in bytes */
 #if defined (__APPLE__)
 #define AARCH64_STACK_ALIGN 1
 #else
 #define AARCH64_STACK_ALIGN 16
 #endif
 
 #define N_X_ARG_REG 8
@@ -60,16 +67,19 @@ sys_icache_invalidate (void *start, size
 
 static inline void
 ffi_clear_cache (void *start, void *end)
 {
 #if defined (__clang__) && defined (__APPLE__)
 	sys_icache_invalidate (start, (char *)end - (char *)start);
 #elif defined (__GNUC__)
 	__builtin___clear_cache (start, end);
+#elif defined (_WIN32)
+	FlushInstructionCache (GetCurrentProcess (), start,
+			       (char*)end - (char*)start);
 #else
 #error "Missing builtin to flush instruction cache"
 #endif
 }
 
 static void *
 get_x_addr (struct call_context *context, unsigned n)
 {
@@ -214,16 +224,20 @@ get_basic_type_size (unsigned short type
       return sizeof (SINT64);
 
     default:
       FFI_ASSERT (0);
       return 0;
     }
 }
 
+// XXX The Win64 and the SYSV ABI are very close, differing only in their
+// calling of varargs functions.  Since we don't care about calling varargs
+// functions in our use of libffi, we just hack our way through and use the
+// SYSV-designated functions everywhere.
 extern void
 ffi_call_SYSV (unsigned (*)(struct call_context *context, unsigned char *,
 			    extended_cif *),
                struct call_context *context,
                extended_cif *,
                size_t,
                void (*fn)(void));
 
@@ -486,17 +500,17 @@ allocate_to_stack (struct arg_state *sta
   state->nsaa = ALIGN (state->nsaa, alignment);
 #if defined (__APPLE__)
   if (state->allocating_variadic)
     state->nsaa = ALIGN (state->nsaa, 8);
 #else
   state->nsaa = ALIGN (state->nsaa, 8);
 #endif
 
-  allocation = stack + state->nsaa;
+  allocation = (char*)stack + state->nsaa;
 
   state->nsaa += size;
   return allocation;
 }
 
 static void
 copy_basic_type (void *dest, void *source, unsigned short type)
 {
@@ -570,17 +584,17 @@ copy_hfa_to_reg_or_stack (void *memory,
   else
     {
       int i;
       unsigned short type = get_homogeneous_type (ty);
       for (i = 0; i < elems; i++)
 	{
 	  void *reg = allocate_to_v (context, state);
 	  copy_basic_type (reg, memory, type);
-	  memory += get_basic_type_size (type);
+	  memory = (char*)memory + get_basic_type_size (type);
 	}
     }
 }
 
 /* Either allocate an appropriate register for the argument type, or if
    none are available, allocate a stack slot and return a pointer
    to the allocated space.  */
 
@@ -854,17 +868,17 @@ ffi_call (ffi_cif *cif, void (*fn)(void)
 		  {
 		    int j;
 		    unsigned short type = get_homogeneous_type (cif->rtype);
 		    unsigned elems = element_count (cif->rtype);
 		    for (j = 0; j < elems; j++)
 		      {
 			void *reg = get_basic_type_addr (type, &context, j);
 			copy_basic_type (rvalue, reg, type);
-			rvalue += get_basic_type_size (type);
+			rvalue = (char*)rvalue + get_basic_type_size (type);
 		      }
 		  }
                 else if ((cif->rtype->size + 7) / 8 < N_X_ARG_REG)
                   {
                     size_t size = ALIGN (cif->rtype->size, sizeof (UINT64));
                     memcpy (rvalue, get_x_addr (&context, 0), size);
                   }
                 else
@@ -897,26 +911,27 @@ static unsigned char trampoline [] =
 { 0x70, 0x00, 0x00, 0x58,	/* ldr	x16, 1f	*/
   0x91, 0x00, 0x00, 0x10,	/* adr	x17, 2f	*/
   0x00, 0x02, 0x1f, 0xd6	/* br	x16	*/
 };
 
 /* Build a trampoline.  */
 
 #define FFI_INIT_TRAMPOLINE(TRAMP,FUN,CTX,FLAGS)			\
-  ({unsigned char *__tramp = (unsigned char*)(TRAMP);			\
+  do {									\
+    unsigned char *__tramp = (unsigned char*)(TRAMP);			\
     UINT64  __fun = (UINT64)(FUN);					\
     UINT64  __ctx = (UINT64)(CTX);					\
     UINT64  __flags = (UINT64)(FLAGS);					\
     memcpy (__tramp, trampoline, sizeof (trampoline));			\
     memcpy (__tramp + 12, &__fun, sizeof (__fun));			\
     memcpy (__tramp + 20, &__ctx, sizeof (__ctx));			\
     memcpy (__tramp + 28, &__flags, sizeof (__flags));			\
     ffi_clear_cache(__tramp, __tramp + FFI_TRAMPOLINE_SIZE);		\
-  })
+  } while(0)
 
 ffi_status
 ffi_prep_closure_loc (ffi_closure* closure,
                       ffi_cif* cif,
                       void (*fun)(ffi_cif*,void*,void**,void*),
                       void *user_data,
                       void *codeloc)
 {
@@ -1136,17 +1151,17 @@ ffi_closure_SYSV_inner (ffi_closure *clo
 	    {
 	      int j;
 	      unsigned short type = get_homogeneous_type (cif->rtype);
 	      unsigned elems = element_count (cif->rtype);
 	      for (j = 0; j < elems; j++)
 		{
 		  void *reg = get_basic_type_addr (type, context, j);
 		  copy_basic_type (reg, rvalue, type);
-		  rvalue += get_basic_type_size (type);
+		  rvalue = (char*)rvalue + get_basic_type_size (type);
 		}
 	    }
           else if ((cif->rtype->size + 7) / 8 < N_X_ARG_REG)
             {
               size_t size = ALIGN (cif->rtype->size, sizeof (UINT64)) ;
               memcpy (get_x_addr (context, 0), rvalue, size);
             }
           else
new file mode 100644
--- /dev/null
+++ b/js/src/ctypes/libffi/src/aarch64/win64.asm
@@ -0,0 +1,272 @@
+;; Copyright (c) 2009, 2010, 2011, 2012 ARM Ltd.
+
+;; Permission is hereby granted, free of charge, to any person obtaining
+;; a copy of this software and associated documentation files (the
+;; ``Software''), to deal in the Software without restriction, including
+;; without limitation the rights to use, copy, modify, merge, publish,
+;; distribute, sublicense, and/or sell copies of the Software, and to
+;; permit persons to whom the Software is furnished to do so, subject to
+;; the following conditions:
+
+;; The above copyright notice and this permission notice shall be
+;; included in all copies or substantial portions of the Software.
+
+;; THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
+;; EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+;; MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+;; IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+;; CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+;; TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+;; SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+;; Hand-converted from the sysv.S file in this directory.
+
+        AREA |.text|, CODE, ARM64
+
+   ;; ffi_call_SYSV()
+
+   ;; Create a stack frame, setup an argument context, call the callee
+   ;; and extract the result.
+
+   ;; The maximum required argument stack size is provided,
+   ;; ffi_call_SYSV() allocates that stack space then calls the
+   ;; prepare_fn to populate register context and stack.  The
+   ;; argument passing registers are loaded from the register
+   ;; context and the callee called, on return the register passing
+   ;; register are saved back to the context.  Our caller will
+   ;; extract the return value from the final state of the saved
+   ;; register context.
+
+   ;; Prototype:
+
+   ;; extern unsigned
+   ;; ffi_call_SYSV (void (*)(struct call_context *context, unsigned char *,
+   ;; 			   extended_cif *),
+   ;;                struct call_context *context,
+   ;;                extended_cif *,
+   ;;                size_t required_stack_size,
+   ;;                void (*fn)(void));
+
+   ;; Therefore on entry we have:
+
+   ;; x0 prepare_fn
+   ;; x1 &context
+   ;; x2 &ecif
+   ;; x3 bytes
+   ;; x4 fn
+
+   ;; This function uses the following stack frame layout:
+
+   ;; ==
+   ;;              saved x30(lr)
+   ;; x29(fp)->    saved x29(fp)
+   ;;              saved x24
+   ;;              saved x23
+   ;;              saved x22
+   ;; sp'    ->    saved x21
+   ;;              ...
+   ;; sp     ->    (constructed callee stack arguments)
+   ;; ==
+
+   ;; Voila!
+
+	EXPORT |ffi_call_SYSV|
+
+|ffi_call_SYSV| PROC
+;#define ffi_call_SYSV_FS (8 * 4)
+
+        stp     x29, x30, [sp, #-16]!
+
+        mov     x29, sp
+        sub     sp, sp, #32 	; ffi_call_SYSV_FS
+
+        stp     x21, x22, [sp, #0]
+        stp     x23, x24, [sp, #16]
+
+        mov     x21, x1
+        mov     x22, x2
+        mov     x24, x4
+
+        ; Allocate the stack space for the actual arguments, many
+        ; arguments will be passed in registers, but we assume
+        ; worst case and allocate sufficient stack for ALL of
+        ; the arguments.
+        sub     sp, sp, x3
+
+        ; unsigned (*prepare_fn) (struct call_context *context,
+        ;                         unsigned char *stack, extended_cif *ecif);
+
+        mov     x23, x0
+        mov     x0, x1
+        mov     x1, sp
+        ; x2 already in place
+        blr     x23
+
+        ; Preserve the flags returned.
+        mov     x23, x0
+
+        ; Figure out if we should touch the vector registers.
+        tbz     x23, #0, noload_call
+
+        ; Load the vector argument passing registers.
+        ldp     q0, q1, [x21, #8*32 +  0]
+        ldp     q2, q3, [x21, #8*32 + 32]
+        ldp     q4, q5, [x21, #8*32 + 64]
+        ldp     q6, q7, [x21, #8*32 + 96]
+
+noload_call
+        ; Load the core argument passing registers.
+        ldp     x0, x1, [x21,  #0]
+        ldp     x2, x3, [x21, #16]
+        ldp     x4, x5, [x21, #32]
+        ldp     x6, x7, [x21, #48]
+
+        ; Don't forget x8 which may be holding the address of a return buffer.
+        ldr     x8,     [x21, #8*8]
+
+        blr     x24
+
+        ; Save the core argument passing registers.
+        stp     x0, x1, [x21,  #0]
+        stp     x2, x3, [x21, #16]
+        stp     x4, x5, [x21, #32]
+        stp     x6, x7, [x21, #48]
+
+        ; Note nothing useful ever comes back in x8!
+
+        ; Figure out if we should touch the vector registers.
+        tbz     x23, #0, nosave_call ; AARCH64_FFI_WITH_V_BIT
+
+        ; Save the vector argument passing registers.
+        stp     q0, q1, [x21, #8*32 + 0]
+        stp     q2, q3, [x21, #8*32 + 32]
+        stp     q4, q5, [x21, #8*32 + 64]
+        stp     q6, q7, [x21, #8*32 + 96]
+
+nosave_call
+        ; All done, unwind our stack frame.
+        ldp     x21, x22, [x29,  # - 32] ; ffi_call_SYSV_FS
+
+        ldp     x23, x24, [x29,  # - 32 + 16] ; ffi_call_SYSV_FS
+
+        mov     sp, x29
+
+        ldp     x29, x30, [sp], #16
+
+        ret
+
+	ENDP
+
+; #define ffi_closure_SYSV_FS (8 * 2 + AARCH64_CALL_CONTEXT_SIZE)
+
+   ;; ffi_closure_SYSV
+
+   ;; Closure invocation glue. This is the low level code invoked directly by
+   ;; the closure trampoline to setup and call a closure.
+
+   ;; On entry x17 points to a struct trampoline_data, x16 has been clobbered
+   ;; all other registers are preserved.
+
+   ;; We allocate a call context and save the argument passing registers,
+   ;; then invoked the generic C ffi_closure_SYSV_inner() function to do all
+   ;; the real work, on return we load the result passing registers back from
+   ;; the call context.
+
+   ;; On entry
+
+   ;; extern void
+   ;; ffi_closure_SYSV (struct trampoline_data *);
+
+   ;; struct trampoline_data
+   ;; {
+   ;;      UINT64 *ffi_closure;
+   ;;      UINT64 flags;
+   ;; };
+
+   ;; This function uses the following stack frame layout:
+
+   ;; ==
+   ;;              saved x30(lr)
+   ;; x29(fp)->    saved x29(fp)
+   ;;              saved x22
+   ;;              saved x21
+   ;;              ...
+   ;; sp     ->    call_context
+   ;; ==
+
+   ;; Voila!
+
+	IMPORT |ffi_closure_SYSV_inner|
+	EXPORT |ffi_closure_SYSV|
+
+|ffi_closure_SYSV| PROC
+        stp     x29, x30, [sp, #-16]!
+
+        mov     x29, sp
+
+        sub     sp, sp, #256+512+16
+
+        stp     x21, x22, [x29, #-16]
+
+        ; Load x21 with &call_context.
+        mov     x21, sp
+        ; Preserve our struct trampoline_data
+        mov     x22, x17
+
+        ; Save the rest of the argument passing registers.
+        stp     x0, x1, [x21, #0]
+        stp     x2, x3, [x21, #16]
+        stp     x4, x5, [x21, #32]
+        stp     x6, x7, [x21, #48]
+        ; Don't forget we may have been given a result scratch pad address.
+        str     x8,     [x21, #64]
+
+        ; Figure out if we should touch the vector registers.
+        ldr     x0, [x22, #8]
+        tbz     x0, #0, nosave_closure ; AARCH64_FFI_WITH_V_BIT
+
+        ; Save the argument passing vector registers.
+        stp     q0, q1, [x21, #8*32 + 0]
+        stp     q2, q3, [x21, #8*32 + 32]
+        stp     q4, q5, [x21, #8*32 + 64]
+        stp     q6, q7, [x21, #8*32 + 96]
+
+nosave_closure
+        ; Load &ffi_closure..
+        ldr     x0, [x22, #0]
+        mov     x1, x21
+        ; Compute the location of the stack at the point that the
+        ; trampoline was called.
+        add     x2, x29, #16
+
+        bl      ffi_closure_SYSV_inner
+
+        ; Figure out if we should touch the vector registers.
+        ldr     x0, [x22, #8]
+        tbz     x0, #0, noload_closure ; AARCH64_FFI_WITH_V_BIT
+
+        ; Load the result passing vector registers.
+        ldp     q0, q1, [x21, #8*32 + 0]
+        ldp     q2, q3, [x21, #8*32 + 32]
+        ldp     q4, q5, [x21, #8*32 + 64]
+        ldp     q6, q7, [x21, #8*32 + 96]
+
+noload_closure
+        ; Load the result passing core registers.
+        ldp     x0, x1, [x21,  #0]
+        ldp     x2, x3, [x21, #16]
+        ldp     x4, x5, [x21, #32]
+        ldp     x6, x7, [x21, #48]
+        ; Note nothing useful is returned in x8.
+
+        ; We are done, unwind our frame.
+        ldp     x21, x22, [x29,  #-16]
+
+        mov     sp, x29
+
+        ldp     x29, x30, [sp], #16
+
+        ret
+
+	ENDP
+	END
--- a/js/src/jit-test/jit_test.py
+++ b/js/src/jit-test/jit_test.py
@@ -370,19 +370,23 @@ def main(argv):
         elif options.debugger == 'lldb':
             debug_cmd = ['lldb', '--']
         elif options.debugger == 'rr':
             debug_cmd = ['rr', 'record']
         else:
             debug_cmd = options.debugger.split()
 
         with change_env(test_environment):
-            subprocess.call(debug_cmd + tc.command(prefix, jittests.LIB_DIR, jittests.MODULE_DIR))
             if options.debugger == 'rr':
-                subprocess.call(['rr', 'replay'])
+                subprocess.call(debug_cmd +
+                                tc.command(prefix, jittests.LIB_DIR, jittests.MODULE_DIR))
+                os.execvp('rr', ['rr', 'replay'])
+            else:
+                os.execvp(debug_cmd[0], debug_cmd +
+                          tc.command(prefix, jittests.LIB_DIR, jittests.MODULE_DIR))
         sys.exit()
 
     try:
         ok = None
         if options.remote:
             ok = jittests.run_tests(job_list, job_count, prefix, options, remote=True)
         else:
             with change_env(test_environment):
--- a/js/src/jit/JitRealm.h
+++ b/js/src/jit/JitRealm.h
@@ -633,44 +633,40 @@ const unsigned WINDOWS_BIG_FRAME_TOUCH_I
 // AutoWritableJitCodeFallible may only fail to make code writable; it cannot fail to
 // make JIT code executable (because the creating code has no chance to
 // recover from a failed destructor).
 class MOZ_RAII AutoWritableJitCodeFallible
 {
     JSRuntime* rt_;
     void* addr_;
     size_t size_;
-    bool madeWritable_;
 
   public:
     AutoWritableJitCodeFallible(JSRuntime* rt, void* addr, size_t size)
-      : rt_(rt), addr_(addr), size_(size), madeWritable_(false)
+      : rt_(rt), addr_(addr), size_(size)
     {
         rt_->toggleAutoWritableJitCodeActive(true);
     }
 
     AutoWritableJitCodeFallible(void* addr, size_t size)
       : AutoWritableJitCodeFallible(TlsContext.get()->runtime(), addr, size)
     {
     }
 
     explicit AutoWritableJitCodeFallible(JitCode* code)
       : AutoWritableJitCodeFallible(code->runtimeFromMainThread(), code->raw(), code->bufferSize())
     {}
 
     MOZ_MUST_USE bool makeWritable() {
-        madeWritable_ = ExecutableAllocator::makeWritable(addr_, size_);
-        return madeWritable_;
+        return ExecutableAllocator::makeWritable(addr_, size_);
     }
 
     ~AutoWritableJitCodeFallible() {
-        if (madeWritable_) {
-            if (!ExecutableAllocator::makeExecutable(addr_, size_)) {
-                MOZ_CRASH();
-            }
+        if (!ExecutableAllocator::makeExecutable(addr_, size_)) {
+            MOZ_CRASH();
         }
         rt_->toggleAutoWritableJitCodeActive(false);
     }
 
 };
 
 // Infallible variant of AutoWritableJitCodeFallible, ensures writable during construction
 class MOZ_RAII AutoWritableJitCode : private AutoWritableJitCodeFallible
new file mode 100644
--- /dev/null
+++ b/js/src/jit/moz.build
@@ -0,0 +1,240 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+FINAL_LIBRARY = 'js'
+
+FILES_PER_UNIFIED_FILE = 6
+
+# Includes should be relative to parent path
+LOCAL_INCLUDES += [
+    '!..',
+    '..'
+]
+
+include('../js-config.mozbuild')
+include('../js-cxxflags.mozbuild')
+
+
+# Generate jit/MOpcodes.h from jit/MIR.h
+GENERATED_FILES += ['MOpcodes.h']
+MOpcodesGenerated = GENERATED_FILES['MOpcodes.h']
+MOpcodesGenerated.script = 'GenerateOpcodeFiles.py:generate_mir_header'
+MOpcodesGenerated.inputs = ['MIR.h']
+
+# Generate jit/LOpcodes.h from jit/LIR.h, jit/shared/LIR-shared.h, and
+# platform-specific LIR files.
+GENERATED_FILES += ['LOpcodes.h']
+LOpcodesGenerated = GENERATED_FILES['LOpcodes.h']
+LOpcodesGenerated.script = 'GenerateOpcodeFiles.py:generate_lir_header'
+LOpcodesGenerated.inputs = ['LIR.h', 'shared/LIR-shared.h']
+
+
+UNIFIED_SOURCES += [
+    'AliasAnalysis.cpp',
+    'AlignmentMaskAnalysis.cpp',
+    'BacktrackingAllocator.cpp',
+    'Bailouts.cpp',
+    'BaselineBailouts.cpp',
+    'BaselineCacheIRCompiler.cpp',
+    'BaselineCompiler.cpp',
+    'BaselineDebugModeOSR.cpp',
+    'BaselineFrame.cpp',
+    'BaselineFrameInfo.cpp',
+    'BaselineIC.cpp',
+    'BaselineInspector.cpp',
+    'BaselineJIT.cpp',
+    'BitSet.cpp',
+    'BytecodeAnalysis.cpp',
+    'C1Spewer.cpp',
+    'CacheIR.cpp',
+    'CacheIRCompiler.cpp',
+    'CacheIRSpewer.cpp',
+    'CodeGenerator.cpp',
+    'CompileWrappers.cpp',
+    'EdgeCaseAnalysis.cpp',
+    'EffectiveAddressAnalysis.cpp',
+    'ExecutableAllocator.cpp',
+    'FoldLinearArithConstants.cpp',
+    'InstructionReordering.cpp',
+    'Ion.cpp',
+    'IonAnalysis.cpp',
+    'IonBuilder.cpp',
+    'IonCacheIRCompiler.cpp',
+    'IonControlFlow.cpp',
+    'IonIC.cpp',
+    'IonOptimizationLevels.cpp',
+    'Jit.cpp',
+    'JitcodeMap.cpp',
+    'JitFrames.cpp',
+    'JitOptions.cpp',
+    'JitSpewer.cpp',
+    'JSJitFrameIter.cpp',
+    'JSONSpewer.cpp',
+    'LICM.cpp',
+    'Linker.cpp',
+    'LIR.cpp',
+    'LoopUnroller.cpp',
+    'Lowering.cpp',
+    'MacroAssembler.cpp',
+    'MCallOptimize.cpp',
+    'MIR.cpp',
+    'MIRGraph.cpp',
+    'MoveResolver.cpp',
+    'OptimizationTracking.cpp',
+    'PerfSpewer.cpp',
+    'ProcessExecutableMemory.cpp',
+    'RangeAnalysis.cpp',
+    'Recover.cpp',
+    'RegisterAllocator.cpp',
+    'RematerializedFrame.cpp',
+    'Safepoints.cpp',
+    'ScalarReplacement.cpp',
+    'shared/Assembler-shared.cpp',
+    'shared/CodeGenerator-shared.cpp',
+    'shared/Disassembler-shared.cpp',
+    'shared/Lowering-shared.cpp',
+    'Sink.cpp',
+    'Snapshots.cpp',
+    'StupidAllocator.cpp',
+    'TypedObjectPrediction.cpp',
+    'TypePolicy.cpp',
+    'ValueNumbering.cpp',
+    'VMFunctions.cpp',
+    'WasmBCE.cpp',
+]
+
+if not CONFIG['ENABLE_ION']:
+    LOpcodesGenerated.inputs += ['none/LIR-none.h']
+    UNIFIED_SOURCES += [
+        'none/Trampoline-none.cpp'
+    ]
+elif CONFIG['JS_CODEGEN_X86'] or CONFIG['JS_CODEGEN_X64']:
+    LOpcodesGenerated.inputs += ['x86-shared/LIR-x86-shared.h']
+    UNIFIED_SOURCES += [
+        'x86-shared/Architecture-x86-shared.cpp',
+        'x86-shared/Assembler-x86-shared.cpp',
+        'x86-shared/AssemblerBuffer-x86-shared.cpp',
+        'x86-shared/CodeGenerator-x86-shared.cpp',
+        'x86-shared/Lowering-x86-shared.cpp',
+        'x86-shared/MacroAssembler-x86-shared-SIMD.cpp',
+        'x86-shared/MacroAssembler-x86-shared.cpp',
+        'x86-shared/MoveEmitter-x86-shared.cpp',
+    ]
+    if CONFIG['JS_CODEGEN_X64']:
+        LOpcodesGenerated.inputs += ['x64/LIR-x64.h']
+        UNIFIED_SOURCES += [
+            'x64/Assembler-x64.cpp',
+            'x64/Bailouts-x64.cpp',
+            'x64/CodeGenerator-x64.cpp',
+            'x64/Lowering-x64.cpp',
+            'x64/MacroAssembler-x64.cpp',
+            'x64/Trampoline-x64.cpp',
+        ]
+    else:
+        LOpcodesGenerated.inputs += ['x86/LIR-x86.h']
+        UNIFIED_SOURCES += [
+            'x86/Assembler-x86.cpp',
+            'x86/Bailouts-x86.cpp',
+            'x86/CodeGenerator-x86.cpp',
+            'x86/Lowering-x86.cpp',
+            'x86/MacroAssembler-x86.cpp',
+            'x86/Trampoline-x86.cpp',
+        ]
+elif CONFIG['JS_CODEGEN_ARM']:
+    LOpcodesGenerated.inputs += ['arm/LIR-arm.h']
+    UNIFIED_SOURCES += [
+        'arm/Architecture-arm.cpp',
+        'arm/Assembler-arm.cpp',
+        'arm/Bailouts-arm.cpp',
+        'arm/CodeGenerator-arm.cpp',
+        'arm/disasm/Constants-arm.cpp',
+        'arm/disasm/Disasm-arm.cpp',
+        'arm/Lowering-arm.cpp',
+        'arm/MacroAssembler-arm.cpp',
+        'arm/MoveEmitter-arm.cpp',
+        'arm/Trampoline-arm.cpp',
+    ]
+    if CONFIG['JS_SIMULATOR_ARM']:
+        UNIFIED_SOURCES += [
+            'arm/Simulator-arm.cpp'
+        ]
+    elif CONFIG['OS_ARCH'] == 'Darwin':
+        SOURCES += [
+            'arm/llvm-compiler-rt/arm/aeabi_idivmod.S',
+            'arm/llvm-compiler-rt/arm/aeabi_uidivmod.S',
+        ]
+elif CONFIG['JS_CODEGEN_ARM64']:
+    LOpcodesGenerated.inputs += ['arm64/LIR-arm64.h']
+    UNIFIED_SOURCES += [
+        'arm64/Architecture-arm64.cpp',
+        'arm64/Assembler-arm64.cpp',
+        'arm64/Bailouts-arm64.cpp',
+        'arm64/CodeGenerator-arm64.cpp',
+        'arm64/Lowering-arm64.cpp',
+        'arm64/MacroAssembler-arm64.cpp',
+        'arm64/MoveEmitter-arm64.cpp',
+        'arm64/Trampoline-arm64.cpp',
+        'arm64/vixl/Assembler-vixl.cpp',
+        'arm64/vixl/Cpu-vixl.cpp',
+        'arm64/vixl/Decoder-vixl.cpp',
+        'arm64/vixl/Disasm-vixl.cpp',
+        'arm64/vixl/Instructions-vixl.cpp',
+        'arm64/vixl/Instrument-vixl.cpp',
+        'arm64/vixl/MacroAssembler-vixl.cpp',
+        'arm64/vixl/MozAssembler-vixl.cpp',
+        'arm64/vixl/MozInstructions-vixl.cpp',
+        'arm64/vixl/Utils-vixl.cpp'
+    ]
+    if CONFIG['JS_SIMULATOR_ARM64']:
+        UNIFIED_SOURCES += [
+            'arm64/vixl/Debugger-vixl.cpp',
+            'arm64/vixl/Logic-vixl.cpp',
+            'arm64/vixl/MozSimulator-vixl.cpp',
+            'arm64/vixl/Simulator-vixl.cpp'
+        ]
+elif CONFIG['JS_CODEGEN_MIPS32'] or CONFIG['JS_CODEGEN_MIPS64']:
+    LOpcodesGenerated.inputs += ['mips-shared/LIR-mips-shared.h']
+    UNIFIED_SOURCES += [
+        'mips-shared/Architecture-mips-shared.cpp',
+        'mips-shared/Assembler-mips-shared.cpp',
+        'mips-shared/Bailouts-mips-shared.cpp',
+        'mips-shared/CodeGenerator-mips-shared.cpp',
+        'mips-shared/Lowering-mips-shared.cpp',
+        'mips-shared/MacroAssembler-mips-shared.cpp',
+        'mips-shared/MoveEmitter-mips-shared.cpp',
+    ]
+    if CONFIG['JS_CODEGEN_MIPS32']:
+        LOpcodesGenerated.inputs += ['mips32/LIR-mips32.h']
+        UNIFIED_SOURCES += [
+            'mips32/Architecture-mips32.cpp',
+            'mips32/Assembler-mips32.cpp',
+            'mips32/Bailouts-mips32.cpp',
+            'mips32/CodeGenerator-mips32.cpp',
+            'mips32/Lowering-mips32.cpp',
+            'mips32/MacroAssembler-mips32.cpp',
+            'mips32/MoveEmitter-mips32.cpp',
+            'mips32/Trampoline-mips32.cpp',
+        ]
+        if CONFIG['JS_SIMULATOR_MIPS32']:
+            UNIFIED_SOURCES += [
+                'mips32/Simulator-mips32.cpp'
+            ]
+    elif CONFIG['JS_CODEGEN_MIPS64']:
+        LOpcodesGenerated.inputs += ['mips64/LIR-mips64.h']
+        UNIFIED_SOURCES += [
+            'mips64/Architecture-mips64.cpp',
+            'mips64/Assembler-mips64.cpp',
+            'mips64/Bailouts-mips64.cpp',
+            'mips64/CodeGenerator-mips64.cpp',
+            'mips64/Lowering-mips64.cpp',
+            'mips64/MacroAssembler-mips64.cpp',
+            'mips64/MoveEmitter-mips64.cpp',
+            'mips64/Trampoline-mips64.cpp',
+        ]
+        if CONFIG['JS_SIMULATOR_MIPS64']:
+            UNIFIED_SOURCES += [
+                'mips64/Simulator-mips64.cpp'
+            ]
--- a/js/src/jsapi-tests/moz.build
+++ b/js/src/jsapi-tests/moz.build
@@ -136,16 +136,17 @@ if CONFIG['ENABLE_ION']:
         'testJitRegisterSet.cpp',
         'testJitRValueAlloc.cpp',
     ]
 
 if CONFIG['NIGHTLY_BUILD']:
     # The Error interceptor only exists on Nightly.
     UNIFIED_SOURCES += [
         'testErrorInterceptor.cpp',
+        'testErrorInterceptorGC.cpp',
     ]
 
 if CONFIG['JS_BUILD_BINAST'] and CONFIG['JS_STANDALONE'] and not CONFIG['FUZZING']:
     # Standalone builds leave the source directory untouched,
     # which lets us run tests with the data files intact.
     # Otherwise, in the current state of the build system,
     # we can't have data files in js/src tests.
     # Also, fuzzing builds modify the const matching in the
--- a/js/src/jsapi-tests/testErrorInterceptor.cpp
+++ b/js/src/jsapi-tests/testErrorInterceptor.cpp
@@ -7,17 +7,17 @@
 // Tests for JS_GetErrorInterceptorCallback and JS_SetErrorInterceptorCallback.
 
 
 namespace {
 static JS::PersistentRootedString gLatestMessage;
 
 // An interceptor that stores the error in `gLatestMessage`.
 struct SimpleInterceptor: JSErrorInterceptor {
-    virtual void interceptError(JSContext* cx, const JS::Value& val) override {
+    virtual void interceptError(JSContext* cx, JS::HandleValue val) override {
         js::StringBuffer buffer(cx);
         if (!ValueToStringBuffer(cx, val, buffer)) {
             MOZ_CRASH("Could not convert to string buffer");
         }
         gLatestMessage = buffer.finishString();
         if (!gLatestMessage) {
             MOZ_CRASH("Could not convert to string");
         }
new file mode 100644
--- /dev/null
+++ b/js/src/jsapi-tests/testErrorInterceptorGC.cpp
@@ -0,0 +1,34 @@
+#include "jsapi.h"
+
+#include "jsapi-tests/tests.h"
+
+namespace {
+
+// An interceptor that triggers GC:
+struct ErrorInterceptorWithGC : JSErrorInterceptor {
+    void interceptError(JSContext* cx, JS::HandleValue val) override {
+        JS::PrepareForFullGC(cx);
+        JS::NonIncrementalGC(cx, GC_SHRINK, JS::gcreason::DEBUG_GC);
+    }
+};
+
+}
+
+BEGIN_TEST(testErrorInterceptorGC)
+{
+    JSErrorInterceptor* original = JS_GetErrorInterceptorCallback(cx->runtime());
+
+    ErrorInterceptorWithGC interceptor;
+    JS_SetErrorInterceptorCallback(cx->runtime(), &interceptor);
+
+    CHECK(!execDontReport("0 = 0;", __FILE__, __LINE__));
+
+    CHECK(JS_IsExceptionPending(cx));
+    JS_ClearPendingException(cx);
+
+    // Restore the original error interceptor.
+    JS_SetErrorInterceptorCallback(cx->runtime(), original);
+
+    return true;
+}
+END_TEST(testErrorInterceptorGC)
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -257,17 +257,17 @@ using JSExternalStringSizeofCallback =
  * Callback used to intercept JavaScript errors.
  */
 struct JSErrorInterceptor {
     /**
      * This method is called whenever an error has been raised from JS code.
      *
      * This method MUST be infallible.
      */
-    virtual void interceptError(JSContext* cx, const JS::Value& error) = 0;
+    virtual void interceptError(JSContext* cx, JS::HandleValue error) = 0;
 };
 
 /************************************************************************/
 
 static MOZ_ALWAYS_INLINE JS::Value
 JS_NumberValue(double d)
 {
     int32_t i;
--- a/js/src/moz.build
+++ b/js/src/moz.build
@@ -93,29 +93,16 @@ CONFIGURE_DEFINE_FILES += [
     'js-config.h',
 ]
 
 if CONFIG['HAVE_DTRACE']:
     GENERATED_FILES += ['javascript-trace.h']
 
     EXPORTS += ['!javascript-trace.h']
 
-# Generate jit/MOpcodes.h from jit/MIR.h
-GENERATED_FILES += ['jit/MOpcodes.h']
-MOpcodesGenerated = GENERATED_FILES['jit/MOpcodes.h']
-MOpcodesGenerated.script = 'jit/GenerateOpcodeFiles.py:generate_mir_header'
-MOpcodesGenerated.inputs = ['jit/MIR.h']
-
-# Generate jit/LOpcodes.h from jit/LIR.h, jit/shared/LIR-shared.h, and
-# platform-specific LIR files.
-GENERATED_FILES += ['jit/LOpcodes.h']
-LOpcodesGenerated = GENERATED_FILES['jit/LOpcodes.h']
-LOpcodesGenerated.script = 'jit/GenerateOpcodeFiles.py:generate_lir_header'
-LOpcodesGenerated.inputs = ['jit/LIR.h', 'jit/shared/LIR-shared.h']
-
 # Changes to internal header files, used externally, massively slow down
 # browser builds.  Don't add new files here unless you know what you're
 # doing!
 EXPORTS += [
     '!js-config.h',
     'js.msg',
     'jsapi.h',
     'jsfriendapi.h',
@@ -266,87 +253,16 @@ UNIFIED_SOURCES += [
     'irregexp/NativeRegExpMacroAssembler.cpp',
     'irregexp/RegExpAST.cpp',
     'irregexp/RegExpCharacters.cpp',
     'irregexp/RegExpEngine.cpp',
     'irregexp/RegExpInterpreter.cpp',
     'irregexp/RegExpMacroAssembler.cpp',
     'irregexp/RegExpParser.cpp',
     'irregexp/RegExpStack.cpp',
-    'jit/AliasAnalysis.cpp',
-    'jit/AlignmentMaskAnalysis.cpp',
-    'jit/BacktrackingAllocator.cpp',
-    'jit/Bailouts.cpp',
-    'jit/BaselineBailouts.cpp',
-    'jit/BaselineCacheIRCompiler.cpp',
-    'jit/BaselineCompiler.cpp',
-    'jit/BaselineDebugModeOSR.cpp',
-    'jit/BaselineFrame.cpp',
-    'jit/BaselineFrameInfo.cpp',
-    'jit/BaselineIC.cpp',
-    'jit/BaselineInspector.cpp',
-    'jit/BaselineJIT.cpp',
-    'jit/BitSet.cpp',
-    'jit/BytecodeAnalysis.cpp',
-    'jit/C1Spewer.cpp',
-    'jit/CacheIR.cpp',
-    'jit/CacheIRCompiler.cpp',
-    'jit/CacheIRSpewer.cpp',
-    'jit/CodeGenerator.cpp',
-    'jit/CompileWrappers.cpp',
-    'jit/EdgeCaseAnalysis.cpp',
-    'jit/EffectiveAddressAnalysis.cpp',
-    'jit/ExecutableAllocator.cpp',
-    'jit/FoldLinearArithConstants.cpp',
-    'jit/InstructionReordering.cpp',
-    'jit/Ion.cpp',
-    'jit/IonAnalysis.cpp',
-    'jit/IonBuilder.cpp',
-    'jit/IonCacheIRCompiler.cpp',
-    'jit/IonControlFlow.cpp',
-    'jit/IonIC.cpp',
-    'jit/IonOptimizationLevels.cpp',
-    'jit/Jit.cpp',
-    'jit/JitcodeMap.cpp',
-    'jit/JitFrames.cpp',
-    'jit/JitOptions.cpp',
-    'jit/JitSpewer.cpp',
-    'jit/JSJitFrameIter.cpp',
-    'jit/JSONSpewer.cpp',
-    'jit/LICM.cpp',
-    'jit/Linker.cpp',
-    'jit/LIR.cpp',
-    'jit/LoopUnroller.cpp',
-    'jit/Lowering.cpp',
-    'jit/MacroAssembler.cpp',
-    'jit/MCallOptimize.cpp',
-    'jit/MIR.cpp',
-    'jit/MIRGraph.cpp',
-    'jit/MoveResolver.cpp',
-    'jit/OptimizationTracking.cpp',
-    'jit/PerfSpewer.cpp',
-    'jit/ProcessExecutableMemory.cpp',
-    'jit/RangeAnalysis.cpp',
-    'jit/Recover.cpp',
-    'jit/RegisterAllocator.cpp',
-    'jit/RematerializedFrame.cpp',
-    'jit/Safepoints.cpp',
-    'jit/ScalarReplacement.cpp',
-    'jit/shared/Assembler-shared.cpp',
-    'jit/shared/CodeGenerator-shared.cpp',
-    'jit/shared/Disassembler-shared.cpp',
-    'jit/shared/Lowering-shared.cpp',
-    'jit/Sink.cpp',
-    'jit/Snapshots.cpp',
-    'jit/StupidAllocator.cpp',
-    'jit/TypedObjectPrediction.cpp',
-    'jit/TypePolicy.cpp',
-    'jit/ValueNumbering.cpp',
-    'jit/VMFunctions.cpp',
-    'jit/WasmBCE.cpp',
     'jsapi.cpp',
     'jsdate.cpp',
     'jsexn.cpp',
     'jsfriendapi.cpp',
     'jsnum.cpp',
     'perf/jsperf.cpp',
     'proxy/BaseProxyHandler.cpp',
     'proxy/CrossCompartmentWrapper.cpp',
@@ -502,149 +418,16 @@ if CONFIG['MOZ_INSTRUMENTS']:
 
 if CONFIG['ENABLE_TRACE_LOGGING']:
     SOURCES += [
         'vm/TraceLogging.cpp',
         'vm/TraceLoggingGraph.cpp',
         'vm/TraceLoggingTypes.cpp',
     ]
 
-if not CONFIG['ENABLE_ION']:
-    LOpcodesGenerated.inputs += ['jit/none/LIR-none.h']
-    UNIFIED_SOURCES += [
-        'jit/none/Trampoline-none.cpp'
-    ]
-elif CONFIG['JS_CODEGEN_X86'] or CONFIG['JS_CODEGEN_X64']:
-    LOpcodesGenerated.inputs += ['jit/x86-shared/LIR-x86-shared.h']
-    UNIFIED_SOURCES += [
-        'jit/x86-shared/Architecture-x86-shared.cpp',
-        'jit/x86-shared/Assembler-x86-shared.cpp',
-        'jit/x86-shared/AssemblerBuffer-x86-shared.cpp',
-        'jit/x86-shared/CodeGenerator-x86-shared.cpp',
-        'jit/x86-shared/Lowering-x86-shared.cpp',
-        'jit/x86-shared/MacroAssembler-x86-shared-SIMD.cpp',
-        'jit/x86-shared/MacroAssembler-x86-shared.cpp',
-        'jit/x86-shared/MoveEmitter-x86-shared.cpp',
-    ]
-    if CONFIG['JS_CODEGEN_X64']:
-        LOpcodesGenerated.inputs += ['jit/x64/LIR-x64.h']
-        UNIFIED_SOURCES += [
-            'jit/x64/Assembler-x64.cpp',
-            'jit/x64/Bailouts-x64.cpp',
-            'jit/x64/CodeGenerator-x64.cpp',
-            'jit/x64/Lowering-x64.cpp',
-            'jit/x64/MacroAssembler-x64.cpp',
-            'jit/x64/Trampoline-x64.cpp',
-        ]
-    else:
-        LOpcodesGenerated.inputs += ['jit/x86/LIR-x86.h']
-        UNIFIED_SOURCES += [
-            'jit/x86/Assembler-x86.cpp',
-            'jit/x86/Bailouts-x86.cpp',
-            'jit/x86/CodeGenerator-x86.cpp',
-            'jit/x86/Lowering-x86.cpp',
-            'jit/x86/MacroAssembler-x86.cpp',
-            'jit/x86/Trampoline-x86.cpp',
-        ]
-elif CONFIG['JS_CODEGEN_ARM']:
-    LOpcodesGenerated.inputs += ['jit/arm/LIR-arm.h']
-    UNIFIED_SOURCES += [
-        'jit/arm/Architecture-arm.cpp',
-        'jit/arm/Assembler-arm.cpp',
-        'jit/arm/Bailouts-arm.cpp',
-        'jit/arm/CodeGenerator-arm.cpp',
-        'jit/arm/disasm/Constants-arm.cpp',
-        'jit/arm/disasm/Disasm-arm.cpp',
-        'jit/arm/Lowering-arm.cpp',
-        'jit/arm/MacroAssembler-arm.cpp',
-        'jit/arm/MoveEmitter-arm.cpp',
-        'jit/arm/Trampoline-arm.cpp',
-    ]
-    if CONFIG['JS_SIMULATOR_ARM']:
-        UNIFIED_SOURCES += [
-            'jit/arm/Simulator-arm.cpp'
-        ]
-    elif CONFIG['OS_ARCH'] == 'Darwin':
-        SOURCES += [
-            'jit/arm/llvm-compiler-rt/arm/aeabi_idivmod.S',
-            'jit/arm/llvm-compiler-rt/arm/aeabi_uidivmod.S',
-        ]
-elif CONFIG['JS_CODEGEN_ARM64']:
-    LOpcodesGenerated.inputs += ['jit/arm64/LIR-arm64.h']
-    UNIFIED_SOURCES += [
-        'jit/arm64/Architecture-arm64.cpp',
-        'jit/arm64/Assembler-arm64.cpp',
-        'jit/arm64/Bailouts-arm64.cpp',
-        'jit/arm64/CodeGenerator-arm64.cpp',
-        'jit/arm64/Lowering-arm64.cpp',
-        'jit/arm64/MacroAssembler-arm64.cpp',
-        'jit/arm64/MoveEmitter-arm64.cpp',
-        'jit/arm64/Trampoline-arm64.cpp',
-        'jit/arm64/vixl/Assembler-vixl.cpp',
-        'jit/arm64/vixl/Cpu-vixl.cpp',
-        'jit/arm64/vixl/Decoder-vixl.cpp',
-        'jit/arm64/vixl/Disasm-vixl.cpp',
-        'jit/arm64/vixl/Instructions-vixl.cpp',
-        'jit/arm64/vixl/Instrument-vixl.cpp',
-        'jit/arm64/vixl/MacroAssembler-vixl.cpp',
-        'jit/arm64/vixl/MozAssembler-vixl.cpp',
-        'jit/arm64/vixl/MozInstructions-vixl.cpp',
-        'jit/arm64/vixl/Utils-vixl.cpp'
-    ]
-    if CONFIG['JS_SIMULATOR_ARM64']:
-        UNIFIED_SOURCES += [
-            'jit/arm64/vixl/Debugger-vixl.cpp',
-            'jit/arm64/vixl/Logic-vixl.cpp',
-            'jit/arm64/vixl/MozSimulator-vixl.cpp',
-            'jit/arm64/vixl/Simulator-vixl.cpp'
-        ]
-elif CONFIG['JS_CODEGEN_MIPS32'] or CONFIG['JS_CODEGEN_MIPS64']:
-    LOpcodesGenerated.inputs += ['jit/mips-shared/LIR-mips-shared.h']
-    UNIFIED_SOURCES += [
-        'jit/mips-shared/Architecture-mips-shared.cpp',
-        'jit/mips-shared/Assembler-mips-shared.cpp',
-        'jit/mips-shared/Bailouts-mips-shared.cpp',
-        'jit/mips-shared/CodeGenerator-mips-shared.cpp',
-        'jit/mips-shared/Lowering-mips-shared.cpp',
-        'jit/mips-shared/MacroAssembler-mips-shared.cpp',
-        'jit/mips-shared/MoveEmitter-mips-shared.cpp',
-    ]
-    if CONFIG['JS_CODEGEN_MIPS32']:
-        LOpcodesGenerated.inputs += ['jit/mips32/LIR-mips32.h']
-        UNIFIED_SOURCES += [
-            'jit/mips32/Architecture-mips32.cpp',
-            'jit/mips32/Assembler-mips32.cpp',
-            'jit/mips32/Bailouts-mips32.cpp',
-            'jit/mips32/CodeGenerator-mips32.cpp',
-            'jit/mips32/Lowering-mips32.cpp',
-            'jit/mips32/MacroAssembler-mips32.cpp',
-            'jit/mips32/MoveEmitter-mips32.cpp',
-            'jit/mips32/Trampoline-mips32.cpp',
-        ]
-        if CONFIG['JS_SIMULATOR_MIPS32']:
-            UNIFIED_SOURCES += [
-                'jit/mips32/Simulator-mips32.cpp'
-            ]
-    elif CONFIG['JS_CODEGEN_MIPS64']:
-        LOpcodesGenerated.inputs += ['jit/mips64/LIR-mips64.h']
-        UNIFIED_SOURCES += [
-            'jit/mips64/Architecture-mips64.cpp',
-            'jit/mips64/Assembler-mips64.cpp',
-            'jit/mips64/Bailouts-mips64.cpp',
-            'jit/mips64/CodeGenerator-mips64.cpp',
-            'jit/mips64/Lowering-mips64.cpp',
-            'jit/mips64/MacroAssembler-mips64.cpp',
-            'jit/mips64/MoveEmitter-mips64.cpp',
-            'jit/mips64/Trampoline-mips64.cpp',
-        ]
-        if CONFIG['JS_SIMULATOR_MIPS64']:
-            UNIFIED_SOURCES += [
-                'jit/mips64/Simulator-mips64.cpp'
-            ]
-
 if CONFIG['OS_ARCH'] == 'WINNT':
     UNIFIED_SOURCES += [
         'threading/windows/CpuCount.cpp',
         'threading/windows/Thread.cpp',
     ]
 else:
     UNIFIED_SOURCES += [
         'threading/posix/CpuCount.cpp',
@@ -686,16 +469,17 @@ GENERATED_FILES += ['frontend/ReservedWo
 ReservedWordsGenerated = GENERATED_FILES['frontend/ReservedWordsGenerated.h']
 ReservedWordsGenerated.script = 'frontend/GenerateReservedWords.py'
 ReservedWordsGenerated.inputs += [
     'frontend/ReservedWords.h'
 ]
 
 DIRS += [
     'build',
+    'jit',
 ]
 
 FINAL_LIBRARY = 'js'
 
 if CONFIG['ENABLE_WASM_CRANELIFT']:
     DIRS += ['rust']
     UNIFIED_SOURCES += [
         'wasm/WasmCraneliftCompile.cpp',
--- a/js/src/tests/jstests.list
+++ b/js/src/tests/jstests.list
@@ -5,16 +5,26 @@
 skip include test/jstests.list
 
 skip script non262/String/normalize-generateddata-input.js # input data for other test
 
 # Timeouts on arm and cgc builds.
 slow script test262/built-ins/decodeURI/S15.1.3.1_A2.5_T1.js
 slow script test262/built-ins/decodeURIComponent/S15.1.3.2_A2.5_T1.js
 
+# Fields are not fully implemented yet
+# https://bugzilla.mozilla.org/show_bug.cgi?id=1499448
+skip script non262/fields/access.js
+skip script non262/fields/basic.js
+skip script non262/fields/error.js
+skip script non262/fields/field_types.js
+skip script non262/fields/literal.js
+skip script non262/fields/mixed_methods.js
+skip script non262/fields/quirks.js
+
 
 #################################################################
 # Tests disabled due to intentional alternative implementations #
 #################################################################
 
 # Legacy "caller" and "arguments" implemented as accessor properties on Function.prototype.
 skip script test262/built-ins/Function/prototype/restricted-property-arguments.js
 skip script test262/built-ins/Function/prototype/restricted-property-caller.js
@@ -438,29 +448,16 @@ skip script test262/intl402/RelativeTime
 skip script test262/intl402/RelativeTimeFormat/prototype/format/en-us-style-short.js
 skip script test262/intl402/RelativeTimeFormat/prototype/format/pl-pl-style-long.js
 skip script test262/intl402/RelativeTimeFormat/prototype/format/pl-pl-style-narrow.js
 skip script test262/intl402/RelativeTimeFormat/prototype/format/pl-pl-style-short.js
 
 # https://bugzilla.mozilla.org/show_bug.cgi?id=1473588
 skip script test262/intl402/RelativeTimeFormat/prototype/format/unit-plural.js
 
-# https://bugzilla.mozilla.org/show_bug.cgi?id=1499933
-skip script test262/intl402/DateTimeFormat/prototype/resolvedOptions/order.js
-skip script test262/intl402/PluralRules/prototype/resolvedOptions/order.js
-skip script test262/intl402/NumberFormat/prototype/resolvedOptions/order.js
-
-# Fields are not fully implemented yet
-skip script non262/fields/access.js
-skip script non262/fields/basic.js
-skip script non262/fields/error.js
-skip script non262/fields/field_types.js
-skip script non262/fields/literal.js
-skip script non262/fields/mixed_methods.js
-skip script non262/fields/quirks.js
 
 ###########################################################
 # Tests disabled due to issues in test262 importer script #
 ###########################################################
 
 # test262 importer merges all includes in a per directory shell.js file, breaking this harness test case.
 skip script test262/harness/detachArrayBuffer.js
 
--- a/js/src/vm/Time.cpp
+++ b/js/src/vm/Time.cpp
@@ -38,20 +38,36 @@ extern int gettimeofday(struct timeval* 
 #endif
 
 #include <sys/time.h>
 
 #endif /* XP_UNIX */
 
 using mozilla::DebugOnly;
 
-#if defined(XP_UNIX)
+// Forward declare the function
+static int64_t PRMJ_NowImpl();
+
 int64_t
 PRMJ_Now()
 {
+    if (mozilla::TimeStamp::GetFuzzyfoxEnabled()) {
+        return mozilla::TimeStamp::NowFuzzyTime();
+    }
+
+    int64_t now = PRMJ_NowImpl();
+    // We check the FuzzyFox clock in case it was recently disabled, to prevent time
+    // from going backwards.
+    return mozilla::TimeStamp::NowFuzzyTime() > now ? mozilla::TimeStamp::NowFuzzyTime() : now;
+}
+
+#if defined(XP_UNIX)
+static int64_t
+PRMJ_NowImpl()
+{
     struct timeval tv;
 
 #ifdef _SVID_GETTOD   /* Defined only on Solaris, see Solaris <sys/types.h> */
     gettimeofday(&tv);
 #else
     gettimeofday(&tv, 0);
 #endif /* _SVID_GETTOD */
 
@@ -145,24 +161,27 @@ PRMJ_NowShutdown()
     DeleteCriticalSection(&calibration.data_lock);
 }
 
 #define MUTEX_LOCK(m) EnterCriticalSection(m)
 #define MUTEX_UNLOCK(m) LeaveCriticalSection(m)
 #define MUTEX_SETSPINCOUNT(m, c) SetCriticalSectionSpinCount((m),(c))
 
 // Please see bug 363258 for why the win32 timing code is so complex.
-int64_t
-PRMJ_Now()
+static int64_t
+PRMJ_NowImpl()
 {
     if (pGetSystemTimePreciseAsFileTime) {
         // Windows 8 has a new API function that does all the work.
         FILETIME ft;
         pGetSystemTimePreciseAsFileTime(&ft);
-        return int64_t(FileTimeToUnixMicroseconds(ft));
+        int64_t now = int64_t(FileTimeToUnixMicroseconds(ft));
+        // We check the FuzzyFox clock in case it was recently disabled, to prevent time
+        // from going backwards.
+        return mozilla::TimeStamp::NowFuzzyTime() > now ? mozilla::TimeStamp::NowFuzzyTime() : now;
     }
 
     bool calibrated = false;
     bool needsCalibration = !calibration.calibrated;
     double cachedOffset = 0.0;
     while (true) {
         if (needsCalibration) {
             MUTEX_LOCK(&calibration.data_lock);
--- a/layout/base/nsRefreshDriver.cpp
+++ b/layout/base/nsRefreshDriver.cpp
@@ -25,16 +25,17 @@
 // to manually include it
 #include <mmsystem.h>
 #include "WinUtils.h"
 #endif
 
 #include "mozilla/AnimationEventDispatcher.h"
 #include "mozilla/ArrayUtils.h"
 #include "mozilla/AutoRestore.h"
+#include "mozilla/DebugOnly.h"
 #include "mozilla/IntegerRange.h"
 #include "mozilla/dom/FontTableURIProtocolHandler.h"
 #include "nsITimer.h"
 #include "nsLayoutUtils.h"
 #include "nsPresContext.h"
 #include "nsComponentManagerUtils.h"
 #include "mozilla/Logging.h"
 #include "nsAutoPtr.h"
@@ -657,17 +658,20 @@ private:
         MonitorAutoLock lock(mRefreshTickLock);
         aVsyncTimestamp = mRecentVsync;
         mProcessedVsync = true;
       } else {
 
         mLastChildTick = TimeStamp::Now();
         mLastProcessedTickInChildProcess = aVsyncTimestamp;
       }
-      MOZ_ASSERT(aVsyncTimestamp <= TimeStamp::Now());
+
+      // Do not compare timestamps unless they are both canonical or fuzzy
+      DebugOnly<TimeStamp> rightnow = TimeStamp::Now();
+      MOZ_ASSERT_IF((*&rightnow).UsedCanonicalNow() == aVsyncTimestamp.UsedCanonicalNow(), aVsyncTimestamp <= *&rightnow);
 
       // We might have a problem that we call ~VsyncRefreshDriverTimer() before
       // the scheduled TickRefreshDriver() runs. Check mVsyncRefreshDriverTimer
       // before use.
       if (mVsyncRefreshDriverTimer) {
         RefPtr<VsyncRefreshDriverTimer> timer = mVsyncRefreshDriverTimer;
         timer->RunRefreshDrivers(aVsyncTimestamp);
         // Note: mVsyncRefreshDriverTimer might be null now.
--- a/layout/build/nsLayoutStatics.cpp
+++ b/layout/build/nsLayoutStatics.cpp
@@ -97,16 +97,17 @@
 #include "mozilla/dom/CustomElementRegistry.h"
 #include "mozilla/EventDispatcher.h"
 #include "mozilla/IMEStateManager.h"
 #include "mozilla/dom/HTMLVideoElement.h"
 #include "TouchManager.h"
 #include "DecoderDoctorLogger.h"
 #include "MediaDecoder.h"
 #include "mozilla/ClearSiteData.h"
+#include "mozilla/Fuzzyfox.h"
 #include "mozilla/ServoBindings.h"
 #include "mozilla/StaticPresData.h"
 #include "mozilla/dom/WebIDLGlobalNameHash.h"
 #include "mozilla/dom/ipc/IPCBlobInputStreamStorage.h"
 #include "mozilla/dom/U2FTokenManager.h"
 #include "mozilla/dom/PointerEventHandler.h"
 #include "mozilla/dom/BlobURLProtocolHandler.h"
 #include "nsThreadManager.h"
@@ -279,16 +280,18 @@ nsLayoutStatics::Initialize()
   if (XRE_IsParentProcess()) {
     // On content process we initialize DOMPrefs when PContentChild is fully
     // initialized.
     mozilla::dom::DOMPrefs::Initialize();
   }
 
   nsThreadManager::InitializeShutdownObserver();
 
+  mozilla::Fuzzyfox::Start();
+
   ClearSiteData::Initialize();
 
   return NS_OK;
 }
 
 void
 nsLayoutStatics::Shutdown()
 {
--- a/mozglue/misc/TimeStamp.cpp
+++ b/mozglue/misc/TimeStamp.cpp
@@ -3,16 +3,17 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 /*
  * Implementation of the OS-independent methods of the TimeStamp class
  */
 
+#include "mozilla/Atomics.h"
 #include "mozilla/TimeStamp.h"
 #include <stdio.h>
 #include <string.h>
 #include <stdlib.h>
 
 namespace mozilla {
 
 /**
@@ -40,16 +41,45 @@ struct TimeStampInitialization
   };
 
   ~TimeStampInitialization()
   {
     TimeStamp::Shutdown();
   };
 };
 
+static bool sFuzzyfoxEnabled;
+
+/* static */ bool
+TimeStamp::GetFuzzyfoxEnabled()
+{
+  return sFuzzyfoxEnabled;
+}
+
+/* static */ void
+TimeStamp::SetFuzzyfoxEnabled(bool aValue)
+{
+  sFuzzyfoxEnabled = aValue;
+}
+
+// These variables store the frozen time (as a TimeStamp) for FuzzyFox that
+// will be reported if FuzzyFox is enabled.
+// We overload the top bit of sCanonicalNow and sCanonicalGTC to
+// indicate if a Timestamp is a fuzzed timestamp (bit set) or not
+// (bit unset).
+#ifdef XP_WIN
+static Atomic<uint64_t> sCanonicalGTC;
+static Atomic<uint64_t> sCanonicalQPC;
+static Atomic<bool> sCanonicalHasQPC;
+#else
+static Atomic<uint64_t> sCanonicalNowTimeStamp;
+#endif
+static Atomic<int64_t> sCanonicalNowTime;
+// This variable stores the frozen time (as ms since the epoch) for FuzzyFox
+// to report if FuzzyFox is enabled.
 static TimeStampInitialization sInitOnce;
 
 MFBT_API TimeStamp
 TimeStamp::ProcessCreation(bool* aIsInconsistent)
 {
   if (aIsInconsistent) {
     *aIsInconsistent = false;
   }
@@ -89,9 +119,56 @@ TimeStamp::ProcessCreation(bool* aIsInco
 }
 
 void
 TimeStamp::RecordProcessRestart()
 {
   sInitOnce.mProcessCreation = TimeStamp();
 }
 
+MFBT_API TimeStamp
+TimeStamp::NowFuzzy(TimeStampValue aValue)
+{
+#ifdef XP_WIN
+  TimeStampValue canonicalNow = TimeStampValue(sCanonicalGTC, sCanonicalQPC, sCanonicalHasQPC, true);
+#else
+  TimeStampValue canonicalNow = TimeStampValue(sCanonicalNowTimeStamp);
+#endif
+
+  if (TimeStamp::GetFuzzyfoxEnabled()) {
+    if(MOZ_LIKELY(!canonicalNow.IsNull())) {
+      return TimeStamp(canonicalNow);
+    }
+  }
+  // When we disable Fuzzyfox, time may goes backwards, so we need to make sure
+  // we don't do that.
+  else if (MOZ_UNLIKELY(canonicalNow > aValue)) {
+    return TimeStamp(canonicalNow);
+  }
+
+  return TimeStamp(aValue);
+}
+
+MFBT_API void
+TimeStamp::UpdateFuzzyTimeStamp(TimeStamp aValue)
+{
+#ifdef XP_WIN
+  sCanonicalGTC = aValue.mValue.mGTC;
+  sCanonicalQPC = aValue.mValue.mQPC;
+  sCanonicalHasQPC = aValue.mValue.mHasQPC;
+#else
+  sCanonicalNowTimeStamp = aValue.mValue.mTimeStamp;
+#endif
+}
+
+MFBT_API int64_t
+TimeStamp::NowFuzzyTime()
+{
+  return sCanonicalNowTime;
+}
+
+MFBT_API void
+TimeStamp::UpdateFuzzyTime(int64_t aValue)
+{
+  sCanonicalNowTime = aValue;
+}
+
 } // namespace mozilla
--- a/mozglue/misc/TimeStamp.h
+++ b/mozglue/misc/TimeStamp.h
@@ -24,17 +24,63 @@ template<typename T> struct ParamTraits;
 // defines TimeStampValue as a complex value keeping both
 // GetTickCount and QueryPerformanceCounter values
 #include "TimeStamp_windows.h"
 #endif
 
 namespace mozilla {
 
 #ifndef XP_WIN
-typedef uint64_t TimeStampValue;
+struct TimeStamp63Bit
+{
+  uint64_t mUsedCanonicalNow : 1;
+  uint64_t mTimeStamp        : 63;
+
+  constexpr TimeStamp63Bit()
+    : mUsedCanonicalNow(0)
+    , mTimeStamp(0) { }
+
+  MOZ_IMPLICIT constexpr TimeStamp63Bit(const uint64_t aValue)
+    : mUsedCanonicalNow(0)
+    , mTimeStamp(aValue) { }
+
+  constexpr TimeStamp63Bit(const bool aUsedCanonicalNow, const int64_t aTimeStamp)
+    : mUsedCanonicalNow(aUsedCanonicalNow ? 1 : 0)
+    , mTimeStamp(aTimeStamp) { }
+
+  bool operator==(const TimeStamp63Bit aOther) const
+  {
+    uint64_t here, there;
+    memcpy(&here, this, sizeof(TimeStamp63Bit));
+    memcpy(&there, &aOther, sizeof(TimeStamp63Bit));
+    return here == there;
+  }
+
+  operator uint64_t () const
+  {
+    return mTimeStamp;
+  }
+
+  bool IsNull() const
+  {
+    return mTimeStamp == 0;
+  }
+
+  bool UsedCanonicalNow() const
+  {
+    return mUsedCanonicalNow;
+  }
+
+  void SetCanonicalNow()
+  {
+    mUsedCanonicalNow = 1;
+  }
+};
+
+typedef TimeStamp63Bit TimeStampValue;
 #endif
 
 class TimeStamp;
 
 /**
  * Platform-specific implementation details of BaseTimeDuration.
  */
 class BaseTimeDurationPlatformUtils
@@ -408,17 +454,17 @@ typedef BaseTimeDuration<TimeDurationVal
  * unless there is a specific reason not to do so.
  */
 class TimeStamp
 {
 public:
   /**
    * Initialize to the "null" moment
    */
-  constexpr TimeStamp() : mValue(0) {}
+  constexpr TimeStamp() : mValue() {}
   // Default copy-constructor and assignment are OK
 
   /**
    * The system timestamps are the same as the TimeStamp
    * retrieved by mozilla::TimeStamp. Since we need this for
    * vsync timestamps, we enable the creation of mozilla::TimeStamps
    * on platforms that support vsync aligned refresh drivers / compositors
    * Verified true as of Jan 31, 2015: B2G and OS X
@@ -429,50 +475,59 @@ public:
    * compositors.
    * UNTESTED ON OTHER PLATFORMS
    */
 #if defined(XP_DARWIN) || defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GTK)
   static TimeStamp FromSystemTime(int64_t aSystemTime)
   {
     static_assert(sizeof(aSystemTime) == sizeof(TimeStampValue),
                   "System timestamp should be same units as TimeStampValue");
-    return TimeStamp(aSystemTime);
+    return TimeStamp(TimeStampValue(false, aSystemTime));
   }
 #endif
 
   /**
    * Return true if this is the "null" moment
    */
-  bool IsNull() const { return mValue == 0; }
+  bool IsNull() const { return mValue.IsNull(); }
 
   /**
    * Return true if this is not the "null" moment, may be used in tests, e.g.:
    * |if (timestamp) { ... }|
    */
   explicit operator bool() const
   {
-    return mValue != 0;
+    return !IsNull();
   }
 
+  bool UsedCanonicalNow() const
+  {
+    return mValue.UsedCanonicalNow();
+  }
+  static MFBT_API bool GetFuzzyfoxEnabled();
+  static MFBT_API void SetFuzzyfoxEnabled(bool aValue);
+
   /**
    * Return a timestamp reflecting the current elapsed system time. This
    * is monotonically increasing (i.e., does not decrease) over the
    * lifetime of this process' XPCOM session.
    *
    * Now() is trying to ensure the best possible precision on each platform,
    * at least one millisecond.
    *
    * NowLoRes() has been introduced to workaround performance problems of
    * QueryPerformanceCounter on the Windows platform.  NowLoRes() is giving
    * lower precision, usually 15.6 ms, but with very good performance benefit.
    * Use it for measurements of longer times, like >200ms timeouts.
    */
   static TimeStamp Now() { return Now(true); }
   static TimeStamp NowLoRes() { return Now(false); }
+  static TimeStamp NowUnfuzzed() { return NowUnfuzzed(true); }
 
+  static MFBT_API int64_t NowFuzzyTime();
   /**
    * Return a timestamp representing the time when the current process was
    * created which will be comparable with other timestamps taken with this
    * class. If the actual process creation time is detected to be inconsistent
    * the @a aIsInconsistent parameter will be set to true, the returned
    * timestamp however will still be valid though inaccurate.
    *
    * @param aIsInconsistent If non-null, set to true if an inconsistency was
@@ -526,30 +581,36 @@ public:
   TimeStamp& operator+=(const TimeDuration& aOther)
   {
     MOZ_ASSERT(!IsNull(), "Cannot compute with a null value");
     TimeStampValue value = mValue + aOther.mValue;
     // Check for underflow.
     // (We don't check for overflow because it's not obvious what the error
     //  behavior should be in that case.)
     if (aOther.mValue < 0 && value > mValue) {
-      value = 0;
+      value = TimeStampValue();
+    }
+    if (mValue.UsedCanonicalNow()) {
+      value.SetCanonicalNow();
     }
     mValue = value;
     return *this;
   }
   TimeStamp& operator-=(const TimeDuration& aOther)
   {
     MOZ_ASSERT(!IsNull(), "Cannot compute with a null value");
     TimeStampValue value = mValue - aOther.mValue;
     // Check for underflow.
     // (We don't check for overflow because it's not obvious what the error
     //  behavior should be in that case.)
     if (aOther.mValue > 0 && value > mValue) {
-      value = 0;
+      value = TimeStampValue();
+    }
+    if (mValue.UsedCanonicalNow()) {
+      value.SetCanonicalNow();
     }
     mValue = value;
     return *this;
   }
 
   bool operator<(const TimeStamp& aOther) const
   {
     MOZ_ASSERT(!IsNull(), "Cannot compute with a null value");
@@ -593,16 +654,21 @@ public:
   static MFBT_API void Shutdown();
 
 private:
   friend struct IPC::ParamTraits<mozilla::TimeStamp>;
 
   MOZ_IMPLICIT TimeStamp(TimeStampValue aValue) : mValue(aValue) {}
 
   static MFBT_API TimeStamp Now(bool aHighResolution);
+  static MFBT_API TimeStamp NowUnfuzzed(bool aHighResolution);
+  static MFBT_API TimeStamp NowFuzzy(TimeStampValue aValue);
+
+  static MFBT_API void UpdateFuzzyTime(int64_t aValue);
+  static MFBT_API void UpdateFuzzyTimeStamp(TimeStamp aValue);
 
   /**
    * Computes the uptime of the current process in microseconds. The result
    * is platform-dependent and needs to be checked against existing timestamps
    * for consistency.
    *
    * @returns The number of microseconds since the calling process was started
    *          or 0 if an error was encountered while computing the uptime
@@ -618,13 +684,15 @@ private:
    *
    * PR_INTERVAL_MAX is set at 100,000 ticks per second. So the minimum
    * time to wrap around is about 2^64/100000 seconds, i.e. about
    * 5,849,424 years.
    *
    * When using a system clock, a value is system dependent.
    */
   TimeStampValue mValue;
+
+  friend class Fuzzyfox;
 };
 
 } // namespace mozilla
 
 #endif /* mozilla_TimeStamp_h */
--- a/mozglue/misc/TimeStamp_darwin.cpp
+++ b/mozglue/misc/TimeStamp_darwin.cpp
@@ -154,22 +154,27 @@ TimeStamp::Startup()
 void
 TimeStamp::Shutdown()
 {
 }
 
 TimeStamp
 TimeStamp::Now(bool aHighResolution)
 {
-  return TimeStamp(ClockTime());
+  return TimeStamp::NowFuzzy(TimeStampValue(false, ClockTime()));
+}
+
+TimeStamp
+TimeStamp::NowUnfuzzed(bool aHighResolution)
+{
+  return TimeStamp(TimeStampValue(false, ClockTime()));
 }
 
 // Computes and returns the process uptime in microseconds.
 // Returns 0 if an error was encountered.
-
 uint64_t
 TimeStamp::ComputeProcessUptime()
 {
   struct timeval tv;
   int rv = gettimeofday(&tv, nullptr);
 
   if (rv == -1) {
     return 0;
--- a/mozglue/misc/TimeStamp_posix.cpp
+++ b/mozglue/misc/TimeStamp_posix.cpp
@@ -197,17 +197,23 @@ TimeStamp::Startup()
 void
 TimeStamp::Shutdown()
 {
 }
 
 TimeStamp
 TimeStamp::Now(bool aHighResolution)
 {
-  return TimeStamp(ClockTimeNs());
+  return TimeStamp::NowFuzzy(TimeStampValue(false, ClockTimeNs()));
+}
+
+TimeStamp
+TimeStamp::NowUnfuzzed(bool aHighResolution)
+{
+  return TimeStamp(TimeStampValue(false, ClockTimeNs()));
 }
 
 #if defined(XP_LINUX) || defined(ANDROID)
 
 // Calculates the amount of jiffies that have elapsed since boot and up to the
 // starttime value of a specific process as found in its /proc/*/stat file.
 // Returns 0 if an error occurred.
 
--- a/mozglue/misc/TimeStamp_windows.cpp
+++ b/mozglue/misc/TimeStamp_windows.cpp
@@ -58,36 +58,30 @@ static const uint32_t kFailureThreshold 
 // If we are not able to get the value of GTC time increment, use this value
 // which is the most usual increment.
 static const DWORD kDefaultTimeIncrement = 156001;
 
 // ----------------------------------------------------------------------------
 // Global variables, not changing at runtime
 // ----------------------------------------------------------------------------
 
-/**
- * The [mt] unit:
- *
- * Many values are kept in ticks of the Performance Coutner x 1000,
- * further just referred as [mt], meaning milli-ticks.
- *
- * This is needed to preserve maximum precision of the performance frequency
- * representation.  GetTickCount64 values in milliseconds are multiplied with
- * frequency per second.  Therefor we need to multiply QPC value by 1000 to
- * have the same units to allow simple arithmentic with both QPC and GTC.
- */
-
-#define ms2mt(x) ((x) * sFrequencyPerSec)
-#define mt2ms(x) ((x) / sFrequencyPerSec)
-#define mt2ms_f(x) (double(x) / sFrequencyPerSec)
-
 // Result of QueryPerformanceFrequency
 // We use default of 1 for the case we can't use QueryPerformanceCounter
 // to make mt/ms conversions work despite that.
-static LONGLONG sFrequencyPerSec = 1;
+static uint64_t sFrequencyPerSec = 1;
+
+namespace mozilla {
+
+MFBT_API uint64_t
+GetQueryPerformanceFrequencyPerSec()
+{
+  return sFrequencyPerSec;
+}
+
+}
 
 // How much we are tolerant to GTC occasional loose of resoltion.
 // This number says how many multiples of the minimal GTC resolution
 // detected on the system are acceptable.  This number is empirical.
 static const LONGLONG kGTCTickLeapTolerance = 4;
 
 // Base tolerance (more: "inability of detection" range) threshold is calculated
 // dynamically, and kept in sGTCResolutionThreshold.
@@ -270,22 +264,23 @@ InitResolution()
 
   sResolutionSigDigs = sigDigs;
 }
 
 // ----------------------------------------------------------------------------
 // TimeStampValue implementation
 // ----------------------------------------------------------------------------
 MFBT_API
-TimeStampValue::TimeStampValue(ULONGLONG aGTC, ULONGLONG aQPC, bool aHasQPC)
+TimeStampValue::TimeStampValue(ULONGLONG aGTC, ULONGLONG aQPC, bool aHasQPC, bool aUsedCanonicalNow)
   : mGTC(aGTC)
   , mQPC(aQPC)
+  , mUsedCanonicalNow(aUsedCanonicalNow)
   , mHasQPC(aHasQPC)
-  , mIsNull(false)
 {
+  mIsNull = aGTC == 0 && aQPC == 0;
 }
 
 MFBT_API TimeStampValue&
 TimeStampValue::operator+=(const int64_t aOther)
 {
   mGTC += aOther;
   mQPC += aOther;
   return *this;
@@ -373,17 +368,17 @@ TimeStampValue::CheckQPC(const TimeStamp
   }
 
   return deltaGTC;
 }
 
 MFBT_API uint64_t
 TimeStampValue::operator-(const TimeStampValue& aOther) const
 {
-  if (mIsNull && aOther.mIsNull) {
+  if (IsNull() && aOther.IsNull()) {
     return uint64_t(0);
   }
 
   return CheckQPC(aOther);
 }
 
 // ----------------------------------------------------------------------------
 // TimeDuration and TimeStamp implementation
@@ -524,26 +519,39 @@ TimeStamp::Startup()
 }
 
 MFBT_API void
 TimeStamp::Shutdown()
 {
   DeleteCriticalSection(&sTimeStampLock);
 }
 
-MFBT_API TimeStamp
-TimeStamp::Now(bool aHighResolution)
+
+TimeStampValue
+NowInternal(bool aHighResolution)
 {
   // sUseQPC is volatile
   bool useQPC = (aHighResolution && sUseQPC);
 
   // Both values are in [mt] units.
   ULONGLONG QPC = useQPC ? PerformanceCounter() : uint64_t(0);
   ULONGLONG GTC = ms2mt(GetTickCount64());
-  return TimeStamp(TimeStampValue(GTC, QPC, useQPC));
+  return TimeStampValue(GTC, QPC, useQPC, false);
+}
+
+MFBT_API TimeStamp
+TimeStamp::Now(bool aHighResolution)
+{
+  return TimeStamp::NowFuzzy(NowInternal(aHighResolution));
+}
+
+MFBT_API TimeStamp
+TimeStamp::NowUnfuzzed(bool aHighResolution)
+{
+  return TimeStamp(NowInternal(aHighResolution));
 }
 
 // Computes and returns the process uptime in microseconds.
 // Returns 0 if an error was encountered.
 
 MFBT_API uint64_t
 TimeStamp::ComputeProcessUptime()
 {
--- a/mozglue/misc/TimeStamp_windows.h
+++ b/mozglue/misc/TimeStamp_windows.h
@@ -6,52 +6,80 @@
 
 #ifndef mozilla_TimeStamp_windows_h
 #define mozilla_TimeStamp_windows_h
 
 #include "mozilla/Types.h"
 
 namespace mozilla {
 
+/**
+ * The [mt] unit:
+ *
+ * Many values are kept in ticks of the Performance Counter x 1000,
+ * further just referred as [mt], meaning milli-ticks.
+ *
+ * This is needed to preserve maximum precision of the performance frequency
+ * representation.  GetTickCount64 values in milliseconds are multiplied with
+ * frequency per second.  Therefore we need to multiply QPC value by 1000 to
+ * have the same units to allow simple arithmentic with both QPC and GTC.
+ */
+#define ms2mt(x) ((x) * mozilla::GetQueryPerformanceFrequencyPerSec())
+#define mt2ms(x) ((x) / mozilla::GetQueryPerformanceFrequencyPerSec())
+#define mt2ms_f(x) (double(x) / mozilla::GetQueryPerformanceFrequencyPerSec())
+
+MFBT_API uint64_t
+GetQueryPerformanceFrequencyPerSec();
+
 class TimeStamp;
+class TimeStampValue;
+
+TimeStampValue
+NowInternal(bool aHighResolution);
+
 
 class TimeStampValue
 {
+  friend TimeStampValue NowInternal(bool);
+  friend bool IsCanonicalTimeStamp(TimeStampValue);
   friend struct IPC::ParamTraits<mozilla::TimeStampValue>;
   friend class TimeStamp;
+  friend class Fuzzyfox;
 
   // Both QPC and GTC are kept in [mt] units.
   uint64_t mGTC;
   uint64_t mQPC;
-  bool mHasQPC;
+
+  bool mUsedCanonicalNow;
   bool mIsNull;
+  bool mHasQPC;
 
-  MFBT_API TimeStampValue(uint64_t aGTC, uint64_t aQPC, bool aHasQPC);
+  MFBT_API TimeStampValue(uint64_t aGTC, uint64_t aQPC, bool aHasQPC, bool aUsedCanonicalNow);
 
   MFBT_API uint64_t CheckQPC(const TimeStampValue& aOther) const;
 
-  struct _SomethingVeryRandomHere;
-  constexpr MOZ_IMPLICIT TimeStampValue(_SomethingVeryRandomHere* aNullValue)
+  constexpr MOZ_IMPLICIT TimeStampValue()
     : mGTC(0)
     , mQPC(0)
+    , mUsedCanonicalNow(false)
+    , mIsNull(true)
     , mHasQPC(false)
-    , mIsNull(true)
   {
   }
 
 public:
   MFBT_API uint64_t operator-(const TimeStampValue& aOther) const;
 
   TimeStampValue operator+(const int64_t aOther) const
   {
-    return TimeStampValue(mGTC + aOther, mQPC + aOther, mHasQPC);
+    return TimeStampValue(mGTC + aOther, mQPC + aOther, mHasQPC, mUsedCanonicalNow);
   }
   TimeStampValue operator-(const int64_t aOther) const
   {
-    return TimeStampValue(mGTC - aOther, mQPC - aOther, mHasQPC);
+    return TimeStampValue(mGTC - aOther, mQPC - aOther, mHasQPC, mUsedCanonicalNow);
   }
   MFBT_API TimeStampValue& operator+=(const int64_t aOther);
   MFBT_API TimeStampValue& operator-=(const int64_t aOther);
 
   bool operator<(const TimeStampValue& aOther) const
   {
     return int64_t(*this - aOther) < 0;
   }
@@ -70,13 +98,25 @@ public:
   bool operator==(const TimeStampValue& aOther) const
   {
     return int64_t(*this - aOther) == 0;
   }
   bool operator!=(const TimeStampValue& aOther) const
   {
     return int64_t(*this - aOther) != 0;
   }
+  bool UsedCanonicalNow() const
+  {
+    return mUsedCanonicalNow;
+  }
+  void SetCanonicalNow()
+  {
+    mUsedCanonicalNow = true;
+  }
+  bool IsNull() const
+  {
+    return mIsNull;
+  }
 };
 
 }
 
 #endif /* mozilla_TimeStamp_h */
new file mode 100644
--- /dev/null
+++ b/netwerk/protocol/http/DelayHttpChannelQueue.cpp
@@ -0,0 +1,127 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* vim:set et cin ts=4 sw=4 sts=4: */
+/* 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 "DelayHttpChannelQueue.h"
+#include "mozilla/Services.h"
+#include "mozilla/StaticPtr.h"
+
+using namespace mozilla;
+using namespace mozilla::net;
+
+namespace {
+StaticRefPtr<DelayHttpChannelQueue> sDelayHttpChannelQueue;
+}
+
+bool
+DelayHttpChannelQueue::AttemptQueueChannel(nsHttpChannel* aChannel)
+{
+  MOZ_ASSERT(aChannel);
+  MOZ_ASSERT(NS_IsMainThread());
+
+  if (!TimeStamp::GetFuzzyfoxEnabled()) {
+    return false;
+  }
+
+  if (!sDelayHttpChannelQueue) {
+    RefPtr<DelayHttpChannelQueue> queue = new DelayHttpChannelQueue();
+    if (!queue->Initialize()) {
+      return false;
+    }
+
+    sDelayHttpChannelQueue = queue;
+  }
+
+  if (NS_WARN_IF(!sDelayHttpChannelQueue->mQueue.AppendElement(aChannel, fallible))) {
+    return false;
+  }
+
+  return true;
+}
+
+DelayHttpChannelQueue::DelayHttpChannelQueue()
+{
+  MOZ_ASSERT(NS_IsMainThread());
+}
+
+DelayHttpChannelQueue::~DelayHttpChannelQueue()
+{
+  MOZ_ASSERT(NS_IsMainThread());
+}
+
+bool
+DelayHttpChannelQueue::Initialize()
+{
+  MOZ_ASSERT(NS_IsMainThread());
+
+  nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
+  if (NS_WARN_IF(!obs)) {
+    return false;
+  }
+
+  nsresult rv = obs->AddObserver(this, "fuzzyfox-fire-outbound", false);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return false;
+  }
+
+  rv = obs->AddObserver(this, "xpcom-shutdown", false);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return false;
+  }
+
+  return true;
+}
+
+NS_IMETHODIMP
+DelayHttpChannelQueue::Observe(nsISupports* aSubject, const char* aTopic,
+                               const char16_t* aData)
+{
+  MOZ_ASSERT(NS_IsMainThread());
+
+  if (!strcmp(aTopic, "fuzzyfox-fire-outbound")) {
+    FireQueue();
+    return NS_OK;
+  }
+
+  MOZ_ASSERT(!strcmp(aTopic, "xpcom-shutdown"));
+
+  nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
+  if (NS_WARN_IF(!obs)) {
+    return NS_OK;
+  }
+
+  obs->RemoveObserver(this, "fuzzyfox-fire-outbound");
+  obs->RemoveObserver(this, "xpcom-shutdown");
+
+  return NS_OK;
+}
+
+void
+DelayHttpChannelQueue::FireQueue()
+{
+  MOZ_ASSERT(NS_IsMainThread());
+
+  if (mQueue.IsEmpty()) {
+    return;
+  }
+
+  //TODO: get this from the DOM clock?
+  TimeStamp ts = TimeStamp::Now();
+
+  FallibleTArray<RefPtr<nsHttpChannel>> queue;
+  queue.SwapElements(mQueue);
+
+  for (RefPtr<nsHttpChannel>& channel : queue) {
+    channel->AsyncOpenFinal(ts);
+  }
+}
+
+NS_INTERFACE_MAP_BEGIN(DelayHttpChannelQueue)
+  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIObserver)
+  NS_INTERFACE_MAP_ENTRY(nsIObserver)
+NS_INTERFACE_MAP_END
+
+NS_IMPL_ADDREF(DelayHttpChannelQueue)
+NS_IMPL_RELEASE(DelayHttpChannelQueue)
new file mode 100644
--- /dev/null
+++ b/netwerk/protocol/http/DelayHttpChannelQueue.h
@@ -0,0 +1,50 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* vim:set et cin ts=4 sw=4 sts=4: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_net_DelayHttpChannelQueue_h
+#define mozilla_net_DelayHttpChannelQueue_h
+
+#include "nsIObserver.h"
+#include "nsTArray.h"
+
+namespace mozilla {
+namespace net {
+
+class nsHttpChannel;
+
+/**
+ * DelayHttpChannelQueue stores a set of nsHttpChannels that
+ * are ready to fire out onto the network. However, with FuzzyFox,
+ * we can only fire those events at a specific interval, so we
+ * delay them here, in an instance of this class, until we observe
+ * the topic notificaion that we can send them outbound.
+ */
+class DelayHttpChannelQueue final : public nsIObserver
+{
+public:
+  static bool
+  AttemptQueueChannel(nsHttpChannel* aChannel);
+
+  NS_DECL_ISUPPORTS
+  NS_DECL_NSIOBSERVER
+
+private:
+  DelayHttpChannelQueue();
+  ~DelayHttpChannelQueue();
+
+  bool
+  Initialize();
+
+  void
+  FireQueue();
+
+  FallibleTArray<RefPtr<nsHttpChannel>> mQueue;
+};
+
+} // net namespace
+} // mozilla namespace
+
+#endif // mozilla_net_DelayHttpChannelQueue_h
--- a/netwerk/protocol/http/HttpChannelChild.cpp
+++ b/netwerk/protocol/http/HttpChannelChild.cpp
@@ -25,16 +25,17 @@
 
 #include "AltDataOutputStreamChild.h"
 #include "CookieServiceChild.h"
 #include "HttpBackgroundChannelChild.h"
 #include "nsCOMPtr.h"
 #include "nsISupportsPrimitives.h"
 #include "nsChannelClassifier.h"
 #include "nsContentPolicyUtils.h"
+#include "nsDOMNavigationTiming.h"
 #include "nsGlobalWindow.h"
 #include "nsStringStream.h"
 #include "nsHttpChannel.h"
 #include "nsHttpHandler.h"
 #include "nsNetUtil.h"
 #include "nsSerializationHelper.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/dom/PerformanceStorage.h"
--- a/netwerk/protocol/http/moz.build
+++ b/netwerk/protocol/http/moz.build
@@ -64,16 +64,17 @@ SOURCES += [
 UNIFIED_SOURCES += [
     'AltDataOutputStreamChild.cpp',
     'AltDataOutputStreamParent.cpp',
     'AlternateServices.cpp',
     'ASpdySession.cpp',
     'BackgroundChannelRegistrar.cpp',
     'CacheControlParser.cpp',
     'ConnectionDiagnostics.cpp',
+    'DelayHttpChannelQueue.cpp',
     'Http2Compression.cpp',
     'Http2Push.cpp',
     'Http2Session.cpp',
     'Http2Stream.cpp',
     'HttpAuthUtils.cpp',
     'HttpBackgroundChannelChild.cpp',
     'HttpBackgroundChannelParent.cpp',
     'HttpBaseChannel.cpp',
--- a/netwerk/protocol/http/nsHttpChannel.cpp
+++ b/netwerk/protocol/http/nsHttpChannel.cpp
@@ -6416,25 +6416,40 @@ nsHttpChannel::AsyncOpen(nsIStreamListen
     }
 
     mIsPending = true;
     mWasOpened = true;
 
     mListener = listener;
     mListenerContext = context;
 
+    // PauseTask/DelayHttpChannel queuing
+    if (!DelayHttpChannelQueue::AttemptQueueChannel(this)) {
+        // If fuzzyfox is disabled; or adding to the queue failed, the channel must continue.
+        AsyncOpenFinal(TimeStamp::Now());
+    }
+
+    return NS_OK;
+}
+
+nsresult
+nsHttpChannel::AsyncOpenFinal(TimeStamp aTimeStamp)
+{
+    // Added due to PauseTask/DelayHttpChannel
+    nsresult rv;
+
     if (mLoadGroup)
         mLoadGroup->AddRequest(this, nullptr);
 
     // record asyncopen time unconditionally and clear it if we
     // don't want it after OnModifyRequest() weighs in. But waiting for
     // that to complete would mean we don't include proxy resolution in the
     // timing.
     if (!mAsyncOpenTimeOverriden) {
-      mAsyncOpenTime = TimeStamp::Now();
+      mAsyncOpenTime = aTimeStamp;
     }
 
     // Remember we have Authorization header set here.  We need to check on it
     // just once and early, AsyncOpen is the best place.
     mCustomAuthHeader = mRequestHead.HasHeader(nsHttp::Authorization);
 
     // The common case for HTTP channels is to begin proxy resolution and return
     // at this point. The only time we know mProxyInfo already is if we're
--- a/netwerk/protocol/http/nsHttpChannel.h
+++ b/netwerk/protocol/http/nsHttpChannel.h
@@ -2,16 +2,17 @@
 /* vim:set et cin ts=4 sw=4 sts=4: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef nsHttpChannel_h__
 #define nsHttpChannel_h__
 
+#include "DelayHttpChannelQueue.h"
 #include "HttpBaseChannel.h"
 #include "nsTArray.h"
 #include "nsICachingChannel.h"
 #include "nsICacheEntry.h"
 #include "nsICacheEntryOpenCallback.h"
 #include "nsIDNSListener.h"
 #include "nsIApplicationCacheChannel.h"
 #include "nsIChannelWithDivertableParentListener.h"
@@ -200,16 +201,18 @@ public:
     HttpChannelSecurityWarningReporter* GetWarningReporter();
 public: /* internal necko use only */
 
     uint32_t GetRequestTime() const
     {
         return mRequestTime;
     }
 
+    nsresult AsyncOpenFinal(TimeStamp aTimeStamp);
+
     MOZ_MUST_USE nsresult OpenCacheEntry(bool usingSSL);
     MOZ_MUST_USE nsresult OpenCacheEntryInternal(bool isHttps,
                                                  nsIApplicationCache *applicationCache,
                                                  bool noAppCache);
     MOZ_MUST_USE nsresult ContinueConnect();
 
     MOZ_MUST_USE nsresult StartRedirectChannelToURI(nsIURI *, uint32_t);
 
--- a/taskcluster/ci/build/linux.yml
+++ b/taskcluster/ci/build/linux.yml
@@ -977,16 +977,19 @@ linux64-ccov/debug:
         need-xvfb: true
     toolchains:
         - linux64-clang-7
         - linux64-rust-nightly
         - linux64-gcc
         - linux64-cbindgen
         - linux64-sccache
         - linux64-node
+    fetches:
+        toolchain:
+            - linux64-grcov
 
 linux64-ccov/opt:
     description: "Linux64-CCov Opt"
     index:
         product: firefox
         job-name: linux64-ccov-opt
     treeherder:
         platform: linux64-ccov/opt
--- a/taskcluster/ci/build/windows.yml
+++ b/taskcluster/ci/build/windows.yml
@@ -587,16 +587,19 @@ win64-ccov/debug:
     run-on-projects: ['mozilla-central', 'try']
     toolchains:
         - win64-clang-cl
         - win64-rust-nightly
         - win64-rust-size
         - win64-cbindgen
         - win64-sccache
         - win64-node
+    fetches:
+        toolchain:
+            - win64-grcov
 
 win64-asan/debug:
     description: "Win64 Debug ASAN"
     index:
         product: firefox
         job-name: win64-asan-debug
     treeherder:
         platform: windows2012-64/asan
--- a/testing/marionette/harness/requirements.txt
+++ b/testing/marionette/harness/requirements.txt
@@ -1,13 +1,13 @@
 browsermob-proxy >= 0.6.0
 manifestparser >= 1.1
 marionette-driver >= 2.7.0
 mozcrash >= 0.5
-mozdevice >= 1.0.0
+mozdevice >= 1.1.5
 mozinfo >= 0.8
 mozlog >= 3.0
 moznetwork >= 0.21
 mozprocess >= 0.9
 mozprofile >= 0.7
 mozrunner >= 7.0.1
 moztest >= 0.8
 mozversion >= 1.1
--- a/testing/mozbase/mozdevice/mozdevice/adb.py
+++ b/testing/mozbase/mozdevice/mozdevice/adb.py
@@ -640,26 +640,26 @@ class ADBDevice(ADBCommand):
         except ADBError:
             self._logger.debug("Check for su 0 failed")
 
         self._mkdir_p = None
         # Force the use of /system/bin/ls or /system/xbin/ls in case
         # there is /sbin/ls which embeds ansi escape codes to colorize
         # the output.  Detect if we are using busybox ls. We want each
         # entry on a single line and we don't want . or ..
-        system_dir = "/system"
+        ls_dir = "/sdcard"
 
-        if self.shell_bool("/system/bin/ls {}".format(system_dir), timeout=timeout):
+        if self.shell_bool("/system/bin/ls {}".format(ls_dir), timeout=timeout):
             self._ls = "/system/bin/ls"
-        elif self.shell_bool("/system/xbin/ls {}".format(system_dir), timeout=timeout):
+        elif self.shell_bool("/system/xbin/ls {}".format(ls_dir), timeout=timeout):
             self._ls = "/system/xbin/ls"
         else:
             raise ADBError("ADBDevice.__init__: ls could not be found")
         try:
-            self.shell_output("%s -1A {}".format(system_dir) % self._ls, timeout=timeout)
+            self.shell_output("%s -1A {}".format(ls_dir) % self._ls, timeout=timeout)
             self._ls += " -1A"
         except ADBError:
             self._ls += " -a"
 
         self._logger.info("%s supported" % self._ls)
 
         # Do we have cp?
         self._have_cp = self.shell_bool("type cp", timeout=timeout)
--- a/testing/mozbase/mozdevice/setup.py
+++ b/testing/mozbase/mozdevice/setup.py
@@ -3,17 +3,17 @@
 # License, v. 2.0. If a copy of the MPL was not distributed with this file,
 # You can obtain one at http://mozilla.org/MPL/2.0/.
 
 from __future__ import absolute_import
 
 from setuptools import setup
 
 PACKAGE_NAME = 'mozdevice'
-PACKAGE_VERSION = '1.1.3'
+PACKAGE_VERSION = '1.1.5'
 
 deps = ['mozfile >= 1.0',
         'mozlog >= 3.0',
         'moznetwork >= 0.24',
         'mozprocess >= 0.19',
         ]
 
 setup(name=PACKAGE_NAME,
--- a/testing/mozbase/mozrunner/setup.py
+++ b/testing/mozbase/mozrunner/setup.py
@@ -7,17 +7,17 @@ from __future__ import absolute_import
 from setuptools import setup, find_packages
 
 PACKAGE_NAME = 'mozrunner'
 PACKAGE_VERSION = '7.2.0'
 
 desc = """Reliable start/stop/configuration of Mozilla Applications (Firefox, Thunderbird, etc.)"""
 
 deps = [
-    'mozdevice>=1.*',
+    'mozdevice>=1.1.5',
     'mozfile>=1.2',
     'mozinfo>=0.7,<2',
     'mozlog==3.*',
     'mozprocess>=0.23,<1',
     'mozprofile~=2.1',
     'six>=1.10.0,<2',
 ]
 
--- a/testing/raptor/requirements.txt
+++ b/testing/raptor/requirements.txt
@@ -1,5 +1,5 @@
 mozrunner ~= 7.0
 mozprofile ~= 2.1
 manifestparser >= 1.1
 wptserve ~= 1.4.0
-mozdevice >= 1.1.1
\ No newline at end of file
+mozdevice >= 1.1.5
--- a/testing/web-platform/meta/svg/idlharness.window.js.ini
+++ b/testing/web-platform/meta/svg/idlharness.window.js.ini
@@ -462,19 +462,16 @@
     expected: FAIL
 
   [SVGElement interface: objects.script must inherit property "correspondingElement" with the proper type]
     expected: FAIL
 
   [SVGElement interface: objects.script must inherit property "correspondingUseElement" with the proper type]
     expected: FAIL
 
-  [SVGAElement interface: attribute relList]
-    expected: FAIL
-
   [SVGElement interface: objects.a must inherit property "correspondingElement" with the proper type]
     expected: FAIL
 
   [SVGElement interface: objects.a must inherit property "correspondingUseElement" with the proper type]
     expected: FAIL
 
   [SVGElement interface: objects.view must inherit property "correspondingElement" with the proper type]
     expected: FAIL
--- a/testing/web-platform/tests/interfaces/SVG.idl
+++ b/testing/web-platform/tests/interfaces/SVG.idl
@@ -671,17 +671,17 @@ interface SVGScriptElement : SVGElement 
 SVGScriptElement includes SVGURIReference;
 
 [Exposed=Window]
 interface SVGAElement : SVGGraphicsElement {
   [SameObject] readonly attribute SVGAnimatedString target;
   attribute DOMString download;
   attribute USVString ping;
   attribute DOMString rel;
-  [SameObject, PutsForward=value] readonly attribute DOMTokenList relList;
+  [SameObject, PutForwards=value] readonly attribute DOMTokenList relList;
   attribute DOMString hreflang;
   attribute DOMString type;
 
   attribute DOMString text;
 
   attribute DOMString referrerPolicy;
 };
 
new file mode 100644
--- /dev/null
+++ b/toolkit/components/fuzzyfox/Fuzzyfox.cpp
@@ -0,0 +1,383 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "Fuzzyfox.h"
+#include "mozilla/Logging.h"
+#include "mozilla/Preferences.h"
+#include "mozilla/Services.h"
+#include "mozilla/SystemGroup.h"
+#include "mozilla/TimeStamp.h"
+#include "nsComponentManagerUtils.h"
+#include "nsIPrefBranch.h"
+#include "nsIPrefService.h"
+#include "nsServiceManagerUtils.h"
+#include "prrng.h"
+#include "prtime.h"
+
+// For usleep/Sleep & QueryPerformanceFrequency
+#ifdef XP_WIN
+#include <windows.h>
+#else
+#include <unistd.h>
+#endif
+
+using namespace mozilla;
+
+static LazyLogModule sFuzzyfoxLog("Fuzzyfox");
+
+#define US_TO_NS(x) ((x)*1000)
+#define NS_TO_US(x) ((x)/1000)
+
+#ifdef LOG
+#undef LOG
+#endif
+
+#define LOG(level, args) MOZ_LOG(sFuzzyfoxLog, mozilla::LogLevel::level, args)
+
+#define FUZZYFOX_ENABLED_PREF             "privacy.fuzzyfox.enabled"
+#define FUZZYFOX_ENABLED_PREF_DEFAULT     false
+#define FUZZYFOX_CLOCKGRAIN_PREF          "privacy.fuzzyfox.clockgrainus"
+#define FUZZYFOX_CLOCKGRAIN_PREF_DEFAULT  100
+
+Atomic<uint32_t, Relaxed> Fuzzyfox::sFuzzyfoxClockGrain;
+
+NS_IMPL_ISUPPORTS_INHERITED(Fuzzyfox, Runnable, nsIObserver)
+
+/* static */ void
+Fuzzyfox::Start()
+{
+  MOZ_ASSERT(NS_IsMainThread());
+
+  RefPtr<Fuzzyfox> r = new Fuzzyfox();
+  SystemGroup::Dispatch(TaskCategory::Other, r.forget());
+}
+
+Fuzzyfox::Fuzzyfox()
+  : Runnable("Fuzzyfox")
+  , mSanityCheck(false)
+  , mStartTime(0)
+  , mDuration(PickDuration())
+  , mTickType(eUptick)
+{
+  MOZ_ASSERT(NS_IsMainThread());
+
+  // [[ I originally ran this after observing profile-after-change, but
+  // it turned out that this contructor was getting called _after_ that
+  // event had already fired. ]]
+  Preferences::AddAtomicUintVarCache(&sFuzzyfoxClockGrain,
+                                     FUZZYFOX_CLOCKGRAIN_PREF,
+                                     FUZZYFOX_CLOCKGRAIN_PREF_DEFAULT);
+
+  bool fuzzyfoxEnabled =
+    Preferences::GetBool(FUZZYFOX_ENABLED_PREF, FUZZYFOX_ENABLED_PREF_DEFAULT);
+
+  LOG(Info, ("PT(%p) Created Fuzzyfox, FuzzyFox is now %s \n",
+         this, (fuzzyfoxEnabled ? "enabled" : "disabled")));
+
+  TimeStamp::SetFuzzyfoxEnabled(fuzzyfoxEnabled);
+
+  // Should I see if these fail? And do what?
+  nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID);
+  prefs->AddObserver(FUZZYFOX_ENABLED_PREF, this, false);
+  prefs->AddObserver(FUZZYFOX_CLOCKGRAIN_PREF, this, false);
+}
+
+Fuzzyfox::~Fuzzyfox() = default;
+
+/*
+ * Fuzzyfox::Run is the core of FuzzyFox. Every so often we pop into this method, and pick
+ * a new point in the future to hold time constant until. If we have not reached the _previous_
+ * point in time we had picked, we sleep until we do so.
+ * Then we round the current time downwards to a configurable grain value, fix it in place so
+ * time does not advance, and let execution continue.
+ */
+NS_IMETHODIMP
+Fuzzyfox::Observe(nsISupports* aObject, const char* aTopic,
+                      const char16_t* aMessage)
+{
+  if (!strcmp(NS_PREFBRANCH_PREFCHANGE_TOPIC_ID, aTopic)) {
+    NS_ConvertUTF16toUTF8 pref(aMessage);
+
+    if (pref.EqualsLiteral(FUZZYFOX_ENABLED_PREF)) {
+      bool fuzzyfoxEnabled =
+        Preferences::GetBool(FUZZYFOX_ENABLED_PREF, FUZZYFOX_ENABLED_PREF_DEFAULT);
+
+      LOG(Info, ("PT(%p) Observed a pref change, FuzzyFox is now %s \n",
+         this, (fuzzyfoxEnabled ? "enabled" : "disabled")));
+
+
+      TimeStamp::SetFuzzyfoxEnabled(fuzzyfoxEnabled);
+
+
+      if (TimeStamp::GetFuzzyfoxEnabled()) {
+        // Queue a runnable
+        nsCOMPtr<nsIRunnable> r = this;
+        SystemGroup::Dispatch(TaskCategory::Other, r.forget());
+      } else {
+        mStartTime = 0;
+        mTickType = eUptick;
+        mSanityCheck = false;
+      }
+    }
+  }
+  return NS_OK;
+}
+
+#define DISPATCH_AND_RETURN() \
+  nsCOMPtr<nsIRunnable> r = this; \
+  SystemGroup::Dispatch(TaskCategory::Other, r.forget()); \
+  return NS_OK
+
+NS_IMETHODIMP
+Fuzzyfox::Run()
+{
+  MOZ_ASSERT(NS_IsMainThread());
+  if (!TimeStamp::GetFuzzyfoxEnabled()) {
+    LOG(Info, ("[FuzzyfoxEvent] PT(%p) Fuzzyfox is shut down, doing nothing \n", this));
+    return NS_OK;
+  }
+
+  if (mStartTime == 0) {
+    // This is the first time we are running afer enabling FuzzyFox. We need
+    // to prevent time from going backwards, so for the first run we round the time up
+    // to the next grain.
+    mStartTime = CeilToGrain(ActualTime());
+    MOZ_ASSERT(mStartTime != 0);
+    TimeStamp newTimeStamp = CeilToGrain(TimeStamp::NowUnfuzzed());
+    Fuzzyfox::UpdateClocks(mStartTime, newTimeStamp);
+
+    mSanityCheck = true;
+    LOG(Info, ("[FuzzyfoxEvent] PT(%p) Going to start Fuzzyfox, queuing up the job \n",
+       this));
+
+    DISPATCH_AND_RETURN();
+  }
+
+  // We need to check how long its been since we ran
+  uint64_t endTime = ActualTime();
+
+  uint64_t remaining = 0;
+
+  // Pick the amount to sleep
+  if (endTime < mStartTime) {
+    // This can only happen if we just enabled FuzzyFox, rounded up, and then re-ran the
+    // runnable before we advanced to the next grain.
+    // If that happens, then repeat the current time.
+    // We use mSanityCheck just to be sure (and will eventually remove it.)
+    MOZ_ASSERT(mSanityCheck);
+    LOG(Debug, ("[FuzzyfoxEvent] PT(%p) endTime < mStartTime mStartTime %" PRIu64 " endTime %" PRIu64 " \n",
+         this, mStartTime, endTime));
+
+    mSanityCheck = true;
+    DISPATCH_AND_RETURN();
+  }
+
+  uint64_t actualRunDuration = endTime - mStartTime;
+  if (actualRunDuration > mDuration) {
+    // We ran over our budget!
+    uint64_t over = actualRunDuration - mDuration;
+    LOG(Verbose, ("[FuzzyfoxEvent] PT(%p) Overran budget of %" PRIu32 " by %" PRIu64 " \n",
+         this, mDuration, over));
+
+    uint64_t nextDuration = PickDuration();
+    while (over > nextDuration) {
+      over -= nextDuration;
+      nextDuration = PickDuration();
+      mTickType = mTickType == eUptick ? eDowntick : eUptick;
+    }
+
+    remaining = nextDuration - over;
+  } else {
+    // Didn't go over budget
+    remaining = mDuration - actualRunDuration;
+    LOG(Verbose, ("[FuzzyfoxEvent] PT(%p) Finishing budget of %" PRIu32 " with %" PRIu64 " \n",
+        this, mDuration, remaining));
+  }
+  mSanityCheck = false;
+
+  // Sleep for now
+#ifdef XP_WIN
+  Sleep(remaining);
+#else
+  usleep(remaining);
+#endif
+
+  /*
+   * Update clocks (and fire pending events etc)
+   *
+   * Note: Anytime we round the current time to the grain, and then round the 'real'
+   * time to the grain, we are introducing the risk that we split the grain. That is,
+   * the time advances enough after the first rounding that the second rounding causes
+   * us to move to a different grain.
+   *
+   * In theory, such an occurance breaks the security of FuzzyFox, and if an
+   * attacker can influence the event to occur reliably, and then measure against it
+   * they can attack FuzzyFox. But such an attack is so difficult that it will
+   * never be acheived until you read this comment in a future Academic Publication
+   * that demonstrates it. And at that point the paper would surely never be accepted
+   * into any _respectable_ journal unless the authors had also presented a solution
+   * for the issue that was usable and incorporated into Firefox!
+   */
+  uint64_t newTime = FloorToGrain(ActualTime());
+  TimeStamp newTimeStamp = FloorToGrain(TimeStamp::NowUnfuzzed());
+  UpdateClocks(newTime, newTimeStamp);
+
+  // Reset values
+  mTickType = mTickType == eUptick ? eDowntick : eUptick;
+  mStartTime = ActualTime();
+  mDuration = PickDuration();
+
+  DISPATCH_AND_RETURN();
+}
+
+/*
+ * ActualTime returns the unfuzzed/unrounded time in microseconds since the epoch
+ */
+uint64_t
+Fuzzyfox::ActualTime()
+{
+  return PR_Now();
+}
+
+/*
+ * Calculate a duration we will wait until we allow time to advance again
+ */
+uint64_t
+Fuzzyfox::PickDuration()
+{
+  // TODO: Bug 1484298 - use a real RNG
+  long int rval = rand();
+
+  // Avoid divide by zero errors and overflow errors
+  uint32_t duration = sFuzzyfoxClockGrain <= 0 ? 1 : sFuzzyfoxClockGrain;
+  duration = duration >= (UINT32_MAX / 2) ? (UINT32_MAX / 2) : duration;
+
+  // We want uniform distribution from 1->duration*2
+  // so that the mean is duration
+  return 1 + (rval % (duration * 2));
+}
+
+/*
+ * Update the TimeStamp's class value for the current (constant) time and dispatch
+ * the new (constant) timestamp so observers can register to receive it to update
+ * their own time code.
+ */
+void
+Fuzzyfox::UpdateClocks(uint64_t aNewTime, TimeStamp aNewTimeStamp)
+{
+  // newTime is the new canonical time for this scope!
+  #ifndef XP_WIN
+  LOG(Verbose, ("[Time] New time is %" PRIu64 " (compare to %" PRIu64 ") and timestamp is %" PRIu64 " (compare to %" PRIu64 ")\n",
+    aNewTime, ActualTime(), aNewTimeStamp.mValue.mTimeStamp, TimeStamp::NowUnfuzzed().mValue.mTimeStamp));
+  #else
+  LOG(Verbose, ("[Time] New time is %" PRIu64 " (compare to %" PRIu64 ") \n", aNewTime, ActualTime()));
+  #endif
+
+  // Fire notifications
+  if (MOZ_UNLIKELY(!mObs)) {
+    mObs = services::GetObserverService();
+    if (NS_WARN_IF(!mObs)) {
+      return;
+    }
+  }
+
+  // Event firings on occur on downticks and have no data
+  if (mTickType == eDowntick) {
+    mObs->NotifyObservers(nullptr, FUZZYFOX_FIREOUTBOUND_OBSERVER_TOPIC, nullptr);
+  }
+
+  if (!mTimeUpdateWrapper) {
+    mTimeUpdateWrapper = do_CreateInstance(NS_SUPPORTS_PRINT64_CONTRACTID);
+    if (NS_WARN_IF(!mTimeUpdateWrapper)) {
+      return;
+    }
+  }
+
+  mTimeUpdateWrapper->SetData(aNewTime);
+
+  // Clocks get the new official (frozen) time. This happens on all ticks
+  mObs->NotifyObservers(mTimeUpdateWrapper, FUZZYFOX_UPDATECLOCK_OBSERVER_TOPIC, nullptr);
+
+  // Update the timestamp's canonicaltimes
+  TimeStamp::UpdateFuzzyTime(aNewTime);
+  TimeStamp::UpdateFuzzyTimeStamp(aNewTimeStamp);
+}
+
+uint64_t
+Fuzzyfox::GetClockGrain()
+{
+  return sFuzzyfoxClockGrain;
+}
+
+
+/*
+ * FloorToGrain accepts a timestamp in microsecond precision
+ * and returns it in microseconds, rounded down to the nearest
+ * ClockGrain value.
+ */
+uint64_t
+Fuzzyfox::FloorToGrain(uint64_t aValue)
+{
+  return aValue - (aValue % GetClockGrain());
+}
+
+
+/*
+ * FloorToGrain accepts a timestamp and returns it, rounded down
+ * to the nearest ClockGrain value.
+ */
+TimeStamp
+Fuzzyfox::FloorToGrain(TimeStamp aValue)
+{
+#ifdef XP_WIN
+  // grain is in us
+  uint64_t grain = GetClockGrain();
+  // GTC and QPS are stored in |mt| and need to be converted to
+  uint64_t GTC = mt2ms(aValue.mValue.mGTC) * 1000;
+  uint64_t QPC = mt2ms(aValue.mValue.mQPC) * 1000;
+
+  return TimeStamp(TimeStampValue(
+    ms2mt((GTC - (GTC % grain)) / 1000),
+    ms2mt((QPC - (QPC % grain)) / 1000),
+    aValue.mValue.mHasQPC, true));
+#else
+  return TimeStamp(TimeStampValue(true, US_TO_NS(FloorToGrain(NS_TO_US(aValue.mValue.mTimeStamp)))));
+#endif
+}
+
+/*
+ * CeilToGrain accepts a timestamp in microsecond precision
+ * and returns it in microseconds, rounded up to the nearest
+ * ClockGrain value.
+ */
+uint64_t
+Fuzzyfox::CeilToGrain(uint64_t aValue)
+{
+  return (aValue / GetClockGrain()) * GetClockGrain();
+}
+
+/*
+ * CeilToGrain accepts a timestamp and returns it, rounded up
+ * to the nearest ClockGrain value.
+ */
+TimeStamp
+Fuzzyfox::CeilToGrain(TimeStamp aValue)
+{
+#ifdef XP_WIN
+  // grain is in us
+  uint64_t grain = GetClockGrain();
+  // GTC and QPS are stored in |mt| and need to be converted
+  uint64_t GTC = mt2ms(aValue.mValue.mGTC) * 1000;
+  uint64_t QPC = mt2ms(aValue.mValue.mQPC) * 1000;
+
+  return TimeStamp(TimeStampValue(
+    ms2mt(((GTC / grain) * grain) / 1000),
+    ms2mt(((QPC / grain) * grain) / 1000),
+    aValue.mValue.mHasQPC, true));
+#else
+  return TimeStamp(TimeStampValue(true, US_TO_NS(CeilToGrain(NS_TO_US(aValue.mValue.mTimeStamp)))));
+#endif
+}
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/toolkit/components/fuzzyfox/Fuzzyfox.h
@@ -0,0 +1,137 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_Fuzzyfox_h
+#define mozilla_Fuzzyfox_h
+
+#include "nsIObserver.h"
+#include "nsIObserverService.h"
+#include "nsISupportsPrimitives.h"
+#include "nsThreadUtils.h"
+#include "mozilla/TimeStamp.h"
+
+
+/*
+ * This topic publishes the new canonical time according to Fuzzyfox,
+ * in microseconds since the epoch. If code needs to know the current time,
+ * it should listen for this topic and keep track of the 'current' time,
+ * so as to respect Fuzzyfox and be in sync with the rest of the browser's
+ * timekeeping.
+ */
+#define FUZZYFOX_UPDATECLOCK_OBSERVER_TOPIC   "fuzzyfox-update-clocks"
+
+/*
+ * For Fuzzyfox's security guarentees to hold, the browser must not execute
+ * actions while it should be paused. We currently only pause the main thread,
+ * so actions that occur on other threads should be queued until the browser
+ * unpaused (and moreso than unpauses: until it reaches a downtick.)
+ * This topic indicates when any queued outbound events should be delivered.
+ * TODO: Bug 1484300 and 1484299 would apply this to other communication channels
+ */
+#define FUZZYFOX_FIREOUTBOUND_OBSERVER_TOPIC  "fuzzyfox-fire-outbound"
+
+namespace mozilla {
+
+
+/*
+ * Fuzzyfox is an implementation of the Fermata concept presented in
+ * Trusted Browsers for Uncertain Times.
+ *
+ * Web Browsers expose explicit (performance.now()) and implicit
+ * (WebVTT, Video Frames) timers that, when combined with algorithmic
+ * improvements such as edge thresholding, produce extremely high
+ * resolution clocks.
+ *
+ * High Resolution clocks can be used to time network accesses, browser
+ * cache reads, web page rendering, access to the CPU cache, and other
+ * operations - and the time these operations take to perform can yield
+ * detailed information about user information we want to keep private.
+ *
+ * Fuzzyfox limits the information disclosure by limiting an attacker's
+ * ability to create a high resolution clock. It does this by introducing
+ * a concept called 'fuzzy time' that degrades all clocks (explicit and
+ * implicit). This is done through a combination of holding time constant
+ * during program execution and pausing program execution.
+ *
+ * @InProceedings{KS16,
+ *   author = {David Kohlbrenner and Hovav Shacham},
+ *   title = {Trusted Browsers for Uncertain Times},
+ *   booktitle = {Proceedings of USENIX Security 2016},
+ *   pages = {463-80},
+ *   year = 2016,
+ *   editor = {Thorsten Holz and Stefan Savage},
+ *   month = aug,
+ *   organization = {USENIX}
+ * }
+ * https://www.usenix.org/system/files/conference/usenixsecurity16/sec16_paper_kohlbrenner.pdf
+ *
+ * Fuzzyfox is an adaptation of
+ *   W.-M. Hu, “Reducing timing channels with fuzzy time,” in
+ *   Proceedings of IEEE Security and Privacy (“Oakland”)
+ *   1991, T. F. Lunt and J. McLean, Eds. IEEE Computer
+ *   Society, May 1991, pp. 8–20.
+ */
+class Fuzzyfox final : public Runnable, public nsIObserver
+{
+public:
+  NS_DECL_ISUPPORTS_INHERITED
+  NS_DECL_NSIOBSERVER
+
+  static void
+  Start();
+
+  NS_IMETHOD
+  Run() override;
+
+private:
+  Fuzzyfox();
+  ~Fuzzyfox();
+
+  uint64_t
+  ActualTime();
+
+  uint64_t
+  PickDuration();
+
+  void
+  UpdateClocks(uint64_t aNewTime, TimeStamp aNewTimeStamp);
+
+  uint64_t
+  GetClockGrain();
+
+  uint64_t
+  FloorToGrain(uint64_t aValue);
+
+  TimeStamp
+  FloorToGrain(TimeStamp aValue);
+
+  uint64_t
+  CeilToGrain(uint64_t aValue);
+
+  TimeStamp
+  CeilToGrain(TimeStamp aValue);
+
+  bool mSanityCheck;
+  uint64_t mStartTime;
+  uint32_t mDuration;
+
+  enum Tick {
+    eUptick,
+    eDowntick,
+  };
+
+  Tick mTickType;
+
+  nsCOMPtr<nsIObserverService> mObs = nullptr;
+  nsCOMPtr<nsISupportsPRInt64> mTimeUpdateWrapper = nullptr;
+
+  static Atomic<bool, Relaxed> sFuzzyfoxEnabledPrefMapped;
+  static Atomic<uint32_t, Relaxed> sFuzzyfoxClockGrain;
+};
+
+} // mozilla namespace
+
+#endif /* mozilla_Fuzzyfox_h */
new file mode 100644
--- /dev/null
+++ b/toolkit/components/fuzzyfox/moz.build
@@ -0,0 +1,15 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+SOURCES += [
+    'Fuzzyfox.cpp',
+]
+
+EXPORTS.mozilla += [
+    'Fuzzyfox.h'
+]
+
+FINAL_LIBRARY = 'xul'
--- a/toolkit/components/moz.build
+++ b/toolkit/components/moz.build
@@ -31,16 +31,17 @@ DIRS += [
     'crashes',
     'crashmonitor',
     'downloads',
     'enterprisepolicies',
     'extensions',
     'filewatcher',
     'finalizationwitness',
     'find',
+    'fuzzyfox',
     'jsoncpp/src/lib_json',
     'lz4',
     'mediasniffer',
     'microformats',
     'mozintl',
     'mozprotocol',
     'osfile',
     'parentalcontrols',
--- a/toolkit/components/telemetry/app/TelemetryEnvironment.jsm
+++ b/toolkit/components/telemetry/app/TelemetryEnvironment.jsm
@@ -248,16 +248,17 @@ const DEFAULT_ENVIRONMENT_PREFS = new Ma
   ["layout.css.devPixelsPerPx", {what: RECORD_PREF_VALUE}],
   ["marionette.enabled", {what: RECORD_PREF_VALUE}],
   ["network.proxy.autoconfig_url", {what: RECORD_PREF_STATE}],
   ["network.proxy.http", {what: RECORD_PREF_STATE}],
   ["network.proxy.ssl", {what: RECORD_PREF_STATE}],
   ["pdfjs.disabled", {what: RECORD_PREF_VALUE}],
   ["places.history.enabled", {what: RECORD_PREF_VALUE}],
   ["plugins.show_infobar", {what: RECORD_PREF_VALUE}],
+  ["privacy.fuzzyfox.enabled", {what: RECORD_PREF_VALUE}],
   ["privacy.trackingprotection.enabled", {what: RECORD_PREF_VALUE}],
   ["privacy.donottrackheader.enabled", {what: RECORD_PREF_VALUE}],
   ["security.mixed_content.block_active_content", {what: RECORD_PREF_VALUE}],
   ["security.mixed_content.block_display_content", {what: RECORD_PREF_VALUE}],
   ["xpinstall.signatures.required", {what: RECORD_PREF_VALUE}],
 ]);
 
 const LOGGER_NAME = "Toolkit.Telemetry";
--- a/xpcom/base/CycleCollectedJSRuntime.cpp
+++ b/xpcom/base/CycleCollectedJSRuntime.cpp
@@ -1594,17 +1594,17 @@ extern void DumpValue(const JS::Value& v
 void
 CycleCollectedJSRuntime::ErrorInterceptor::Shutdown(JSRuntime* rt)
 {
   JS_SetErrorInterceptorCallback(rt, nullptr);
   mThrownError.reset();
 }
 
 /* virtual */ void
-CycleCollectedJSRuntime::ErrorInterceptor::interceptError(JSContext* cx, const JS::Value& exn)
+CycleCollectedJSRuntime::ErrorInterceptor::interceptError(JSContext* cx, JS::HandleValue exn)
 {
   if (mThrownError) {
     // We already have an error, we don't need anything more.
     return;
   }
 
   if (!nsContentUtils::ThreadsafeIsSystemCaller(cx)) {
     // We are only interested in chrome code.
@@ -1626,26 +1626,25 @@ CycleCollectedJSRuntime::ErrorIntercepto
       // Not one of the errors we are interested in.
       return;
   }
 
   // Now copy the details of the exception locally.
   // While copying the details of an exception could be expensive, in most runs,
   // this will be done at most once during the execution of the process, so the
   // total cost should be reasonable.
-  JS::RootedValue value(cx, exn);
 
   ErrorDetails details;
   details.mType = *type;
   // If `exn` isn't an exception object, `ExtractErrorValues` could end up calling
   // `toString()`, which could in turn end up throwing an error. While this should
   // work, we want to avoid that complex use case.
   // Fortunately, we have already checked above that `exn` is an exception object,
   // so nothing such should happen.
-  nsContentUtils::ExtractErrorValues(cx, value, details.mFilename, &details.mLine, &details.mColumn, details.mMessage);
+  nsContentUtils::ExtractErrorValues(cx, exn, details.mFilename, &details.mLine, &details.mColumn, details.mMessage);
 
   JS::UniqueChars buf = JS::FormatStackDump(cx, /* showArgs = */ false, /* showLocals = */ false, /* showThisProps = */ false);
   CopyUTF8toUTF16(mozilla::MakeStringSpan(buf.get()), details.mStack);
 
   mThrownError.emplace(std::move(details));
 }
 
 void
--- a/xpcom/base/CycleCollectedJSRuntime.h
+++ b/xpcom/base/CycleCollectedJSRuntime.h
@@ -378,17 +378,17 @@ private:
   bool mShutdownCalled;
 #endif
 
 #ifdef NIGHTLY_BUILD
   // Implementation of the error interceptor.
   // Built on nightly only to avoid any possible performance impact on release
 
   struct ErrorInterceptor final : public JSErrorInterceptor {
-    virtual void interceptError(JSContext* cx, const JS::Value& val) override;
+    virtual void interceptError(JSContext* cx, JS::HandleValue exn) override;
     void Shutdown(JSRuntime* rt);
 
     // Copy of the details of the exception.
     // We store this rather than the exception itself to avoid dealing with complicated
     // garbage-collection scenarios, e.g. a JSContext being killed while we still hold
     // onto an exception thrown from it.
     struct ErrorDetails {
       nsString mFilename;