merge mozilla-inbound to mozilla-central a=merge
authorCarsten "Tomcat" Book <cbook@mozilla.com>
Tue, 15 Sep 2015 15:05:24 +0200
changeset 295156 5d61714cf5c3ec2440e9491ba30893ac37ca06c2
parent 295099 6d08fcbb0431ea105614dab3b7df75880a160ff4 (current diff)
parent 295155 7abc5253e8cf95a869a114604fdecdcf569c8d2e (diff)
child 295163 04d0b5249c1ce14c9c3708dc6e3e1a9d5f220ed6
child 295192 63bd80f07148ab85220c0e0b44c2bb7da8a339fc
child 295207 15f2e2c86ca9f9640cd9bc5ac5546f7441ef01e2
push id5245
push userraliiev@mozilla.com
push dateThu, 29 Oct 2015 11:30:51 +0000
treeherdermozilla-beta@dac831dc1bd0 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone43.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
merge mozilla-inbound to mozilla-central a=merge
extensions/spellcheck/hunspell/src/PRemoteSpellcheckEngine.ipdl
extensions/spellcheck/hunspell/src/RemoteSpellCheckEngineChild.cpp
extensions/spellcheck/hunspell/src/RemoteSpellCheckEngineChild.h
extensions/spellcheck/hunspell/src/RemoteSpellCheckEngineParent.cpp
extensions/spellcheck/hunspell/src/RemoteSpellCheckEngineParent.h
extensions/spellcheck/hunspell/src/hunspell_alloc_hooks.h
extensions/spellcheck/hunspell/src/hunspell_fopen_hooks.h
extensions/spellcheck/hunspell/src/mozHunspell.cpp
extensions/spellcheck/hunspell/src/mozHunspell.h
extensions/spellcheck/hunspell/src/mozHunspellAllocator.h
extensions/spellcheck/hunspell/src/mozHunspellDirProvider.cpp
extensions/spellcheck/hunspell/src/mozHunspellDirProvider.h
testing/talos/talos/sample.2.config
testing/web-platform/meta/2dcontext/drawing-images-to-the-canvas/2d.drawImage.negativedest.html.ini
testing/web-platform/meta/2dcontext/drawing-images-to-the-canvas/2d.drawImage.negativedir.html.ini
testing/web-platform/meta/2dcontext/drawing-images-to-the-canvas/2d.drawImage.negativesource.html.ini
testing/web-platform/meta/2dcontext/drawing-images-to-the-canvas/drawimage_canvas_8.html.ini
toolkit/locales/en-US/chrome/mozapps/plugins/plugins.dtd
toolkit/mozapps/plugins/content/pluginFinderBinding.css
toolkit/mozapps/plugins/content/pluginProblem.xml
toolkit/mozapps/plugins/content/pluginProblemBinding.css
toolkit/mozapps/plugins/content/pluginProblemContent.css
toolkit/mozapps/plugins/jar.mn
toolkit/mozapps/plugins/moz.build
toolkit/mozapps/plugins/pluginGlue.manifest
--- a/accessible/jsat/AccessFu.jsm
+++ b/accessible/jsat/AccessFu.jsm
@@ -853,21 +853,22 @@ var Input = {
 
   androidScroll: function androidScroll(aDirection) {
     let mm = Utils.getMessageManager(Utils.CurrentBrowser);
     mm.sendAsyncMessage('AccessFu:AndroidScroll',
                         { direction: aDirection, origin: 'top' });
   },
 
   moveByGranularity: function moveByGranularity(aDetails) {
-    const MOVEMENT_GRANULARITY_PARAGRAPH = 8;
+    const GRANULARITY_PARAGRAPH = 8;
+    const GRANULARITY_LINE = 4;
 
     if (!this.editState.editing) {
-      if (aDetails.granularity === MOVEMENT_GRANULARITY_PARAGRAPH) {
-        this.moveCursor('move' + aDetails.direction, 'Paragraph', 'gesture');
+      if (aDetails.granularity & (GRANULARITY_PARAGRAPH | GRANULARITY_LINE)) {
+        this.moveCursor('move' + aDetails.direction, 'Simple', 'gesture');
         return;
       }
     } else {
       aDetails.atStart = this.editState.atStart;
       aDetails.atEnd = this.editState.atEnd;
     }
 
     let mm = Utils.getMessageManager(Utils.CurrentBrowser);
--- a/accessible/xpcom/moz.build
+++ b/accessible/xpcom/moz.build
@@ -42,11 +42,8 @@ elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'co
         '/accessible/mac',
     ]
 else:
     LOCAL_INCLUDES += [
         '/accessible/other',
     ]
 
 FINAL_LIBRARY = 'xul'
-
-if not CONFIG['GNU_CXX']:
-    ALLOW_COMPILER_WARNINGS = True
--- a/aclocal.m4
+++ b/aclocal.m4
@@ -28,16 +28,17 @@ builtin(include, build/autoconf/zlib.m4)
 builtin(include, build/autoconf/linux.m4)dnl
 builtin(include, build/autoconf/python-virtualenv.m4)dnl
 builtin(include, build/autoconf/winsdk.m4)dnl
 builtin(include, build/autoconf/icu.m4)dnl
 builtin(include, build/autoconf/ffi.m4)dnl
 builtin(include, build/autoconf/clang-plugin.m4)dnl
 builtin(include, build/autoconf/alloc.m4)dnl
 builtin(include, build/autoconf/ios.m4)dnl
+builtin(include, build/autoconf/jemalloc.m4)dnl
 
 MOZ_PROG_CHECKMSYS()
 
 # Read the user's .mozconfig script.  We can't do this in
 # configure.in: autoconf puts the argument parsing code above anything
 # expanded from configure.in, and we need to get the configure options
 # from .mozconfig in place before that argument parsing code.
 MOZ_READ_MOZCONFIG(.)
new file mode 100644
--- /dev/null
+++ b/build/autoconf/jemalloc.m4
@@ -0,0 +1,100 @@
+dnl This Source Code Form is subject to the terms of the Mozilla Public
+dnl License, v. 2.0. If a copy of the MPL was not distributed with this
+dnl file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+AC_DEFUN([MOZ_SUBCONFIGURE_JEMALLOC], [
+
+if test -z "$BUILDING_JS" -o -n "$JS_STANDALONE"; then
+
+  # Run jemalloc configure script
+
+  if test -z "$MOZ_NATIVE_JEMALLOC" -a "$MOZ_MEMORY" && test -n "$MOZ_JEMALLOC4" -o -n "$MOZ_REPLACE_MALLOC"; then
+    ac_configure_args="--build=$build --host=$target --enable-stats --with-jemalloc-prefix=je_ --disable-valgrind"
+    # We're using memalign for _aligned_malloc in memory/build/mozmemory_wrap.c
+    # on Windows, so just export memalign on all platforms.
+    ac_configure_args="$ac_configure_args ac_cv_func_memalign=yes"
+    if test -n "$MOZ_REPLACE_MALLOC"; then
+      # When using replace_malloc, we always want valloc exported from jemalloc.
+      ac_configure_args="$ac_configure_args ac_cv_func_valloc=yes"
+      if test "${OS_ARCH}" = Darwin; then
+        # We also need to enable pointer validation on Mac because jemalloc's
+        # zone allocator is not used.
+        ac_configure_args="$ac_configure_args --enable-ivsalloc"
+      fi
+    fi
+    if test -n "$MOZ_JEMALLOC4"; then
+      case "${OS_ARCH}" in
+        WINNT|Darwin)
+          # We want jemalloc functions to be kept hidden on both Mac and Windows
+          # See memory/build/mozmemory_wrap.h for details.
+          ac_configure_args="$ac_configure_args --without-export"
+          ;;
+      esac
+      if test "${OS_ARCH}" = WINNT; then
+        # Lazy lock initialization doesn't play well with lazy linking of
+        # mozglue.dll on Windows XP (leads to startup crash), so disable it.
+        ac_configure_args="$ac_configure_args --disable-lazy-lock"
+      fi
+    elif test "${OS_ARCH}" = Darwin; then
+      # When building as a replace-malloc lib, disabling the zone allocator
+      # forces to use pthread_atfork.
+      ac_configure_args="$ac_configure_args --disable-zone-allocator"
+    fi
+    _MANGLE="malloc posix_memalign aligned_alloc calloc realloc free memalign valloc malloc_usable_size"
+    JEMALLOC_WRAPPER=
+    if test -z "$MOZ_REPLACE_MALLOC"; then
+      case "$OS_ARCH" in
+        Linux|DragonFly|FreeBSD|NetBSD|OpenBSD)
+          MANGLE=$_MANGLE
+          ;;
+      esac
+    elif test -z "$MOZ_JEMALLOC4"; then
+      MANGLE=$_MANGLE
+      JEMALLOC_WRAPPER=replace_
+    fi
+    if test -n "$MANGLE"; then
+      MANGLED=
+      for mangle in ${MANGLE}; do
+        if test -n "$MANGLED"; then
+          MANGLED="$mangle:$JEMALLOC_WRAPPER$mangle,$MANGLED"
+        else
+          MANGLED="$mangle:$JEMALLOC_WRAPPER$mangle"
+        fi
+      done
+      ac_configure_args="$ac_configure_args --with-mangling=$MANGLED"
+    fi
+    unset CONFIG_FILES
+    if test -z "$MOZ_TLS"; then
+      ac_configure_args="$ac_configure_args --disable-tls"
+    fi
+    EXTRA_CFLAGS="$CFLAGS"
+    for var in AS CC CXX CPP LD AR RANLIB STRIP CPPFLAGS EXTRA_CFLAGS LDFLAGS; do
+      ac_configure_args="$ac_configure_args $var='`eval echo \\${${var}}`'"
+    done
+    # Force disable DSS support in jemalloc.
+    ac_configure_args="$ac_configure_args ac_cv_func_sbrk=false"
+
+    # Make Linux builds munmap freed chunks instead of recycling them.
+    ac_configure_args="$ac_configure_args --enable-munmap"
+
+    # Disable cache oblivious behavior that appears to have a performance
+    # impact on Firefox.
+    ac_configure_args="$ac_configure_args --disable-cache-oblivious"
+
+    if ! test -e memory/jemalloc; then
+      mkdir -p memory/jemalloc
+    fi
+
+    # jemalloc's configure runs git to determine the version. But when building
+    # from a gecko git clone, the git commands it uses is going to pick gecko's
+    # information, not jemalloc's, which is useless. So pretend we don't have git
+    # at all. That will make jemalloc's configure pick the in-tree VERSION file.
+    (PATH="$srcdir/memory/jemalloc/helper:$PATH";
+    AC_OUTPUT_SUBDIRS(memory/jemalloc/src)
+    ) || exit 1
+    ac_configure_args="$_SUBDIR_CONFIG_ARGS"
+  fi
+
+fi
+
+])
--- a/configure.in
+++ b/configure.in
@@ -9135,105 +9135,17 @@ fi
 AC_SUBST(JS_SHARED_LIBRARY)
 
 MOZ_CREATE_CONFIG_STATUS()
 
 # No need to run subconfigures when building with LIBXUL_SDK_DIR
 if test "$COMPILE_ENVIRONMENT" -a -z "$LIBXUL_SDK_DIR"; then
   MOZ_SUBCONFIGURE_ICU()
   MOZ_SUBCONFIGURE_FFI()
-fi
-
-# Run jemalloc configure script
-
-if test -z "$MOZ_NATIVE_JEMALLOC" -a "$MOZ_MEMORY" && test -n "$MOZ_JEMALLOC4" -o -n "$MOZ_REPLACE_MALLOC"; then
-  ac_configure_args="--build=$build --host=$target --enable-stats --with-jemalloc-prefix=je_ --disable-valgrind"
-  # We're using memalign for _aligned_malloc in memory/build/mozmemory_wrap.c
-  # on Windows, so just export memalign on all platforms.
-  ac_configure_args="$ac_configure_args ac_cv_func_memalign=yes"
-  if test -n "$MOZ_REPLACE_MALLOC"; then
-    # When using replace_malloc, we always want valloc exported from jemalloc.
-    ac_configure_args="$ac_configure_args ac_cv_func_valloc=yes"
-    if test "${OS_ARCH}" = Darwin; then
-      # We also need to enable pointer validation on Mac because jemalloc's
-      # zone allocator is not used.
-      ac_configure_args="$ac_configure_args --enable-ivsalloc"
-    fi
-  fi
-  if test -n "$MOZ_JEMALLOC4"; then
-    case "${OS_ARCH}" in
-      WINNT|Darwin)
-        # We want jemalloc functions to be kept hidden on both Mac and Windows
-        # See memory/build/mozmemory_wrap.h for details.
-        ac_configure_args="$ac_configure_args --without-export"
-        ;;
-    esac
-    if test "${OS_ARCH}" = WINNT; then
-      # Lazy lock initialization doesn't play well with lazy linking of
-      # mozglue.dll on Windows XP (leads to startup crash), so disable it.
-      ac_configure_args="$ac_configure_args --disable-lazy-lock"
-    fi
-  elif test "${OS_ARCH}" = Darwin; then
-    # When building as a replace-malloc lib, disabling the zone allocator
-    # forces to use pthread_atfork.
-    ac_configure_args="$ac_configure_args --disable-zone-allocator"
-  fi
-  _MANGLE="malloc posix_memalign aligned_alloc calloc realloc free memalign valloc malloc_usable_size"
-  JEMALLOC_WRAPPER=
-  if test -z "$MOZ_REPLACE_MALLOC"; then
-    case "$OS_ARCH" in
-      Linux|DragonFly|FreeBSD|NetBSD|OpenBSD)
-        MANGLE=$_MANGLE
-        ;;
-    esac
-  elif test -z "$MOZ_JEMALLOC4"; then
-    MANGLE=$_MANGLE
-    JEMALLOC_WRAPPER=replace_
-  fi
-  if test -n "$MANGLE"; then
-    MANGLED=
-    for mangle in ${MANGLE}; do
-      if test -n "$MANGLED"; then
-        MANGLED="$mangle:$JEMALLOC_WRAPPER$mangle,$MANGLED"
-      else
-        MANGLED="$mangle:$JEMALLOC_WRAPPER$mangle"
-      fi
-    done
-    ac_configure_args="$ac_configure_args --with-mangling=$MANGLED"
-  fi
-  unset CONFIG_FILES
-  if test -z "$MOZ_TLS"; then
-    ac_configure_args="$ac_configure_args --disable-tls"
-  fi
-  EXTRA_CFLAGS="$CFLAGS"
-  for var in AS CC CXX CPP LD AR RANLIB STRIP CPPFLAGS EXTRA_CFLAGS LDFLAGS; do
-    ac_configure_args="$ac_configure_args $var='`eval echo \\${${var}}`'"
-  done
-  # Force disable DSS support in jemalloc.
-  ac_configure_args="$ac_configure_args ac_cv_func_sbrk=false"
-
-  # Make Linux builds munmap freed chunks instead of recycling them.
-  ac_configure_args="$ac_configure_args --enable-munmap"
-
-  # Disable cache oblivious behavior that appears to have a performance
-  # impact on Firefox.
-  ac_configure_args="$ac_configure_args --disable-cache-oblivious"
-
-  if ! test -e memory/jemalloc; then
-    mkdir -p memory/jemalloc
-  fi
-
-  # jemalloc's configure runs git to determine the version. But when building
-  # from a gecko git clone, the git commands it uses is going to pick gecko's
-  # information, not jemalloc's, which is useless. So pretend we don't have git
-  # at all. That will make jemalloc's configure pick the in-tree VERSION file.
-  (PATH="$srcdir/memory/jemalloc/helper:$PATH";
-  AC_OUTPUT_SUBDIRS(memory/jemalloc/src)
-  ) || exit 1
-  ac_configure_args="$_SUBDIR_CONFIG_ARGS"
+  MOZ_SUBCONFIGURE_JEMALLOC()
 fi
 
 # Run freetype configure script
 
 if test "$MOZ_TREE_FREETYPE"; then
    export CFLAGS="$CFLAGS $MOZ_DEBUG_FLAGS -std=c99"
    export CPPFLAGS="$CPPFLAGS $MOZ_DEBUG_FLAGS"
    export CXXFLAGS="$CXXFLAGS $MOZ_DEBUG_FLAGS"
--- a/dom/animation/test/mochitest.ini
+++ b/dom/animation/test/mochitest.ini
@@ -62,8 +62,10 @@ support-files = css-transitions/file_ele
 support-files = css-transitions/file_timeline-get-animations.html
 [document-timeline/test_document-timeline.html]
 support-files = document-timeline/file_document-timeline.html
 [document-timeline/test_request_animation_frame.html]
 skip-if = buildapp == 'mulet'
 [mozilla/test_deferred_start.html]
 support-files = mozilla/file_deferred_start.html
 skip-if = (toolkit == 'gonk' && debug)
+[mozilla/test_hide_and_show.html]
+support-files = mozilla/file_hide_and_show.html
new file mode 100644
--- /dev/null
+++ b/dom/animation/test/mozilla/file_hide_and_show.html
@@ -0,0 +1,75 @@
+<!doctype html>
+<meta charset=utf-8>
+<script src="../testcommon.js"></script>
+<style>
+@keyframes move {
+  100% {
+    transform: translateX(100px);
+  }
+}
+
+</style>
+<body>
+<script>
+'use strict';
+
+test(function(t) {
+  var div = addDiv(t, { style: 'animation: move 100s infinite' });
+  assert_equals(div.getAnimations().length, 1,
+                'display:initial element has animations');
+
+  div.style.display = 'none';
+  assert_equals(div.getAnimations().length, 0,
+                'display:none element has no animations');
+}, 'Animation stops playing when the element style display is set to "none"');
+
+test(function(t) {
+  var parentElement = addDiv(t);
+  var div = addDiv(t, { style: 'animation: move 100s infinite' });
+  parentElement.appendChild(div);
+  assert_equals(div.getAnimations().length, 1,
+                'display:initial element has animations');
+
+  parentElement.style.display = 'none';
+  assert_equals(div.getAnimations().length, 0,
+                'Element in display:none subtree has no animations');
+}, 'Animation stops playing when its parent element style display is set ' +
+   'to "none"');
+
+test(function(t) {
+  var div = addDiv(t, { style: 'animation: move 100s infinite' });
+  assert_equals(div.getAnimations().length, 1,
+                'display:initial element has animations');
+
+  div.style.display = 'none';
+  assert_equals(div.getAnimations().length, 0,
+                'display:none element has no animations');
+
+  div.style.display = '';
+  assert_equals(div.getAnimations().length, 1,
+                'Element which is no longer display:none has animations ' +
+                'again');
+}, 'Animation starts playing when the element gets shown from ' +
+   '"display:none" state');
+
+test(function(t) {
+  var parentElement = addDiv(t);
+  var div = addDiv(t, { style: 'animation: move 100s infinite' });
+  parentElement.appendChild(div);
+  assert_equals(div.getAnimations().length, 1,
+                'display:initial element has animations');
+
+  parentElement.style.display = 'none';
+  assert_equals(div.getAnimations().length, 0,
+                'Element in display:none subtree has no animations');
+
+  parentElement.style.display = '';
+  assert_equals(div.getAnimations().length, 1,
+                'Element which is no longer in display:none subtree has ' +
+                'animations again');
+}, 'Animation starts playing when its parent element is shown from ' +
+   '"display:none" state');
+
+done();
+</script>
+</body>
new file mode 100644
--- /dev/null
+++ b/dom/animation/test/mozilla/test_hide_and_show.html
@@ -0,0 +1,14 @@
+<!doctype html>
+<meta charset=utf-8>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+'use strict';
+setup({explicit_done: true});
+SpecialPowers.pushPrefEnv(
+  { "set": [["dom.animations-api.core.enabled", true]]},
+  function() {
+    window.open("file_hide_and_show.html");
+  });
+</script>
--- a/dom/base/nsContentUtils.cpp
+++ b/dom/base/nsContentUtils.cpp
@@ -4774,65 +4774,16 @@ static bool SchemeIs(nsIURI* aURI, const
 {
   nsCOMPtr<nsIURI> baseURI = NS_GetInnermostURI(aURI);
   NS_ENSURE_TRUE(baseURI, false);
 
   bool isScheme = false;
   return NS_SUCCEEDED(baseURI->SchemeIs(aScheme, &isScheme)) && isScheme;
 }
 
-/* static */
-nsresult
-nsContentUtils::CheckSecurityBeforeLoad(nsIURI* aURIToLoad,
-                                        nsIPrincipal* aLoadingPrincipal,
-                                        uint32_t aCheckLoadFlags,
-                                        bool aAllowData,
-                                        uint32_t aContentPolicyType,
-                                        nsISupports* aContext,
-                                        const nsAFlatCString& aMimeGuess,
-                                        nsISupports* aExtra)
-{
-  NS_PRECONDITION(aLoadingPrincipal, "Must have a loading principal here");
-
-  if (aLoadingPrincipal == sSystemPrincipal) {
-    return NS_OK;
-  }
-  
-  // XXXbz do we want to fast-path skin stylesheets loading XBL here somehow?
-  // CheckLoadURIWithPrincipal
-  nsresult rv = sSecurityManager->
-    CheckLoadURIWithPrincipal(aLoadingPrincipal, aURIToLoad, aCheckLoadFlags);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  // Content Policy
-  int16_t shouldLoad = nsIContentPolicy::ACCEPT;
-  rv = NS_CheckContentLoadPolicy(aContentPolicyType,
-                                 aURIToLoad,
-                                 aLoadingPrincipal,
-                                 aContext,
-                                 aMimeGuess,
-                                 aExtra,
-                                 &shouldLoad,
-                                 GetContentPolicy(),
-                                 sSecurityManager);
-  NS_ENSURE_SUCCESS(rv, rv);
-  if (NS_CP_REJECTED(shouldLoad)) {
-    return NS_ERROR_CONTENT_BLOCKED;
-  }
-
-  // Same Origin
-  if ((aAllowData && SchemeIs(aURIToLoad, "data")) ||
-      ((aCheckLoadFlags & nsIScriptSecurityManager::ALLOW_CHROME) &&
-       SchemeIs(aURIToLoad, "chrome"))) {
-    return NS_OK;
-  }
-
-  return aLoadingPrincipal->CheckMayLoad(aURIToLoad, true, false);
-}
-
 bool
 nsContentUtils::IsSystemPrincipal(nsIPrincipal* aPrincipal)
 {
   MOZ_ASSERT(IsInitialized());
   return aPrincipal == sSystemPrincipal;
 }
 
 bool
--- a/dom/base/nsContentUtils.h
+++ b/dom/base/nsContentUtils.h
@@ -1362,48 +1362,16 @@ public:
   /*
    * Notify when the first XUL menu is opened and when the all XUL menus are
    * closed. At opening, aInstalling should be TRUE, otherwise, it should be
    * FALSE.
    */
   static void NotifyInstalledMenuKeyboardListener(bool aInstalling);
 
   /**
-   * Do security checks before loading a resource. Does the following checks:
-   *   nsIScriptSecurityManager::CheckLoadURIWithPrincipal
-   *   NS_CheckContentLoadPolicy
-   *   nsIScriptSecurityManager::CheckSameOriginURI
-   *
-   * You will still need to do at least SameOrigin checks before on redirects.
-   *
-   * @param aURIToLoad         URI that is getting loaded.
-   * @param aLoadingPrincipal  Principal of the resource that is initiating
-   *                           the load
-   * @param aCheckLoadFlags    Flags to be passed to
-   *                           nsIScriptSecurityManager::CheckLoadURIWithPrincipal
-   *                           NOTE: If this contains ALLOW_CHROME the
-   *                                 CheckSameOriginURI check will be skipped if
-   *                                 aURIToLoad is a chrome uri.
-   * @param aAllowData         Set to true to skip CheckSameOriginURI check when
-                               aURIToLoad is a data uri.
-   * @param aContentPolicyType Type     \
-   * @param aContext           Context   |- to be passed to
-   * @param aMimeGuess         Mimetype  |      NS_CheckContentLoadPolicy
-   * @param aExtra             Extra    /
-   */
-  static nsresult CheckSecurityBeforeLoad(nsIURI* aURIToLoad,
-                                          nsIPrincipal* aLoadingPrincipal,
-                                          uint32_t aCheckLoadFlags,
-                                          bool aAllowData,
-                                          uint32_t aContentPolicyType,
-                                          nsISupports* aContext,
-                                          const nsAFlatCString& aMimeGuess = EmptyCString(),
-                                          nsISupports* aExtra = nullptr);
-
-  /**
    * Returns true if aPrincipal is the system principal.
    */
   static bool IsSystemPrincipal(nsIPrincipal* aPrincipal);
 
   /**
    * Returns true if aPrincipal is an nsExpandedPrincipal.
    */
   static bool IsExpandedPrincipal(nsIPrincipal* aPrincipal);
--- a/dom/base/nsDocument.cpp
+++ b/dom/base/nsDocument.cpp
@@ -9297,17 +9297,20 @@ nsDocument::OnPageHide(bool aPersisted,
     // move us around.
     mIsShowing = false;
   }
 
   if (mAnimationController) {
     mAnimationController->OnPageHide();
   }
 
-  if (aPersisted) {
+  // We do not stop the animations (bug 1024343)
+  // when the page is refreshing while being dragged out
+  nsDocShell* docShell = mDocumentContainer.get();
+  if (aPersisted && !(docShell && docShell->InFrameSwap())) {
     SetImagesNeedAnimating(false);
   }
 
   MozExitPointerLock();
 
   // Now send out a PageHide event.
   nsCOMPtr<EventTarget> target = aDispatchStartTarget;
   if (!target) {
--- a/dom/canvas/CanvasRenderingContext2D.cpp
+++ b/dom/canvas/CanvasRenderingContext2D.cpp
@@ -2473,33 +2473,55 @@ CanvasRenderingContext2D::UpdateFilter()
       gfxRect(0, 0, mWidth, mHeight),
       CurrentState().filterAdditionalImages);
 }
 
 //
 // rects
 //
 
+// bug 1074733
+// The canvas spec does not forbid rects with negative w or h, so given
+// corners (x, y), (x+w, y), (x+w, y+h), and (x, y+h) we must generate
+// the appropriate rect by flipping negative dimensions. This prevents
+// draw targets from receiving "empty" rects later on.
+static void
+NormalizeRect(double& aX, double& aY, double& aWidth, double& aHeight)
+{
+  if (aWidth < 0) {
+    aWidth = -aWidth;
+    aX -= aWidth;
+  }
+  if (aHeight < 0) {
+    aHeight = -aHeight;
+    aY -= aHeight;
+  }
+}
+
 void
 CanvasRenderingContext2D::ClearRect(double x, double y, double w,
                                     double h)
 {
+  NormalizeRect(x, y, w, h);
+
   EnsureTarget();
 
   mTarget->ClearRect(mgfx::Rect(x, y, w, h));
 
   RedrawUser(gfxRect(x, y, w, h));
 }
 
 void
 CanvasRenderingContext2D::FillRect(double x, double y, double w,
                                    double h)
 {
   const ContextState &state = CurrentState();
 
+  NormalizeRect(x, y, w, h);
+
   if (state.patternStyles[Style::FILL]) {
     CanvasPattern::RepeatMode repeat =
       state.patternStyles[Style::FILL]->mRepeat;
     // In the FillRect case repeat modes are easy to deal with.
     bool limitx = repeat == CanvasPattern::RepeatMode::NOREPEAT || repeat == CanvasPattern::RepeatMode::REPEATY;
     bool limity = repeat == CanvasPattern::RepeatMode::NOREPEAT || repeat == CanvasPattern::RepeatMode::REPEATX;
 
     IntSize patternSize =
@@ -2563,16 +2585,17 @@ CanvasRenderingContext2D::StrokeRect(dou
 {
   const ContextState &state = CurrentState();
 
   mgfx::Rect bounds;
 
   if (!w && !h) {
     return;
   }
+  NormalizeRect(x, y, w, h);
 
   EnsureTarget();
   if (!IsTargetValid()) {
     return;
   }
 
   if (NeedToCalculateBounds()) {
     bounds = mgfx::Rect(x - state.lineWidth / 2.0f, y - state.lineWidth / 2.0f,
@@ -4287,16 +4310,35 @@ CanvasRenderingContext2D::CachedSurfaceF
 
   return res;
 }
 
 //
 // image
 //
 
+static void
+ClipImageDimension(double& aSourceCoord, double& aSourceSize, int32_t aImageSize,
+                   double& aDestCoord, double& aDestSize)
+{
+  double scale = aDestSize / aSourceSize;
+  if (aSourceCoord < 0.0) {
+    double destEnd = aDestCoord + aDestSize;
+    aDestCoord -= aSourceCoord * scale;
+    aDestSize = destEnd - aDestCoord;
+    aSourceSize += aSourceCoord;
+    aSourceCoord = 0.0;
+  }
+  double delta = aImageSize - (aSourceCoord + aSourceSize);
+  if (delta < 0.0) {
+    aDestSize += delta * scale;
+    aSourceSize = aImageSize - aSourceCoord;
+  }
+}
+
 // drawImage(in HTMLImageElement image, in float dx, in float dy);
 //   -- render image from 0,0 at dx,dy top-left coords
 // drawImage(in HTMLImageElement image, in float dx, in float dy, in float sw, in float sh);
 //   -- render image from 0,0 at dx,dy top-left coords clipping it to sw,sh
 // drawImage(in HTMLImageElement image, in float sx, in float sy, in float sw, in float sh, in float dx, in float dy, in float dw, in float dh);
 //   -- render the region defined by (sx,sy,sw,wh) in image-local space into the region (dx,dy,dw,dh) on the canvas
 
 // If only dx and dy are passed in then optional_argc should be 0. If only
@@ -4313,16 +4355,21 @@ CanvasRenderingContext2D::DrawImage(cons
                                     ErrorResult& error)
 {
   if (mDrawObserver) {
     mDrawObserver->DidDrawCall(CanvasDrawObserver::DrawCallType::DrawImage);
   }
 
   MOZ_ASSERT(optional_argc == 0 || optional_argc == 2 || optional_argc == 6);
 
+  if (optional_argc == 6) {
+    NormalizeRect(sx, sy, sw, sh);
+    NormalizeRect(dx, dy, dw, dh);
+  }
+
   RefPtr<SourceSurface> srcSurf;
   gfx::IntSize imgSize;
 
   Element* element = nullptr;
 
   EnsureTarget();
   if (image.IsHTMLCanvasElement()) {
     HTMLCanvasElement* canvas = &image.GetAsHTMLCanvasElement();
@@ -4519,28 +4566,22 @@ CanvasRenderingContext2D::DrawImage(cons
     sh = (double) imgSize.height;
   }
 
   if (sw == 0.0 || sh == 0.0) {
     error.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
     return;
   }
 
-  if (dw == 0.0 || dh == 0.0) {
-    // not really failure, but nothing to do --
-    // and noone likes a divide-by-zero
-    return;
-  }
-
-  if (sx < 0.0 || sy < 0.0 ||
-      sw < 0.0 || sw > (double) imgSize.width ||
-      sh < 0.0 || sh > (double) imgSize.height ||
-      dw < 0.0 || dh < 0.0) {
-    // XXX - Unresolved spec issues here, for now return error.
-    error.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
+  ClipImageDimension(sx, sw, imgSize.width, dx, dw);
+  ClipImageDimension(sy, sh, imgSize.height, dy, dh);
+
+  if (sw <= 0.0 || sh <= 0.0 ||
+      dw <= 0.0 || dh <= 0.0) {
+    // source and/or destination are fully clipped, so nothing is painted
     return;
   }
 
   Filter filter;
 
   if (CurrentState().imageSmoothingEnabled)
     filter = mgfx::Filter::LINEAR;
   else
--- a/dom/canvas/test/test_canvas.html
+++ b/dom/canvas/test/test_canvas.html
@@ -3121,17 +3121,17 @@ isPixel(ctx, 48,48, 0,255,0,255, 2);
 isPixel(ctx, 51,1, 0,255,0,255, 2);
 isPixel(ctx, 51,48, 0,255,0,255, 2);
 isPixel(ctx, 25,25, 0,255,0,255, 2);
 isPixel(ctx, 75,25, 0,255,0,255, 2);
 
 } catch (e) {
     _thrown_outer = true;
 }
-todo(!_thrown_outer, 'should not throw exception');
+ok(!_thrown_outer, 'should not throw exception');
 
 
 }
 </script>
 <img src="image_ggrr-256x256.png" id="ggrr-256x256_1.png" class="resource">
 
 <!-- [[[ test_2d.drawImage.negativesource.html ]]] -->
 
@@ -3161,17 +3161,17 @@ isPixel(ctx, 48,48, 0,255,0,255, 2);
 isPixel(ctx, 51,1, 0,255,0,255, 2);
 isPixel(ctx, 51,48, 0,255,0,255, 2);
 isPixel(ctx, 25,25, 0,255,0,255, 2);
 isPixel(ctx, 75,25, 0,255,0,255, 2);
 
 } catch (e) {
     _thrown_outer = true;
 }
-todo(!_thrown_outer, 'should not throw exception');
+ok(!_thrown_outer, 'should not throw exception');
 
 
 }
 </script>
 <img src="image_ggrr-256x256.png" id="ggrr-256x256_2.png" class="resource">
 
 <!-- [[[ test_2d.drawImage.nonfinite.html ]]] -->
 
@@ -3546,72 +3546,16 @@ var _thrown = undefined; try {
   ctx.drawImage(null, 0, 0);
 } catch (e) { _thrown = e };
 
 ok(_thrown && _thrown.name == "TypeError", "should throw TypeError");
 
 }
 </script>
 
-<!-- [[[ test_2d.drawImage.outsidesource.html ]]] -->
-
-<p>Canvas test: 2d.drawImage.outsidesource</p>
-<canvas id="c122" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
-<script>
-
-
-
-function test_2d_drawImage_outsidesource() {
-
-var canvas = document.getElementById('c122');
-var ctx = canvas.getContext('2d');
-
-var _thrown_outer = false;
-try {
-
-ctx.drawImage(document.getElementById('green_7.png'), 10.5, 10.5, 89.5, 39.5, 0, 0, 100, 50);
-ctx.drawImage(document.getElementById('green_7.png'), 5.5, 5.5, -5.5, -5.5, 0, 0, 100, 50);
-ctx.drawImage(document.getElementById('green_7.png'), 100, 50, -5, -5, 0, 0, 100, 50);
-var _thrown = undefined; try {
-  ctx.drawImage(document.getElementById('red_11.png'), -0.001, 0, 100, 50, 0, 0, 100, 50);
-} catch (e) { _thrown = e }; ok(_thrown && _thrown.name == "IndexSizeError" && _thrown.code == DOMException.INDEX_SIZE_ERR, "should throw IndexSizeError");
-var _thrown = undefined; try {
-  ctx.drawImage(document.getElementById('red_11.png'), 0, -0.001, 100, 50, 0, 0, 100, 50);
-} catch (e) { _thrown = e }; ok(_thrown && _thrown.name == "IndexSizeError" && _thrown.code == DOMException.INDEX_SIZE_ERR, "should throw IndexSizeError");
-var _thrown = undefined; try {
-  ctx.drawImage(document.getElementById('red_11.png'), 0, 0, 100.001, 50, 0, 0, 100, 50);
-} catch (e) { _thrown = e }; ok(_thrown && _thrown.name == "IndexSizeError" && _thrown.code == DOMException.INDEX_SIZE_ERR, "should throw IndexSizeError");
-var _thrown = undefined; try {
-  ctx.drawImage(document.getElementById('red_11.png'), 0, 0, 100, 50.001, 0, 0, 100, 50);
-} catch (e) { _thrown = e }; ok(_thrown && _thrown.name == "IndexSizeError" && _thrown.code == DOMException.INDEX_SIZE_ERR, "should throw IndexSizeError");
-var _thrown = undefined; try {
-  ctx.drawImage(document.getElementById('red_11.png'), 50, 0, 50.001, 50, 0, 0, 100, 50);
-} catch (e) { _thrown = e }; todo(_thrown && _thrown.name == "IndexSizeError" && _thrown.code == DOMException.INDEX_SIZE_ERR, "should throw IndexSizeError");
-var _thrown = undefined; try {
-  ctx.drawImage(document.getElementById('red_11.png'), 0, 0, -5, 5, 0, 0, 100, 50);
-} catch (e) { _thrown = e }; ok(_thrown && _thrown.name == "IndexSizeError" && _thrown.code == DOMException.INDEX_SIZE_ERR, "should throw IndexSizeError");
-var _thrown = undefined; try {
-  ctx.drawImage(document.getElementById('red_11.png'), 0, 0, 5, -5, 0, 0, 100, 50);
-} catch (e) { _thrown = e }; ok(_thrown && _thrown.name == "IndexSizeError" && _thrown.code == DOMException.INDEX_SIZE_ERR, "should throw IndexSizeError");
-var _thrown = undefined; try {
-  ctx.drawImage(document.getElementById('red_11.png'), 110, 60, -20, -20, 0, 0, 100, 50);
-} catch (e) { _thrown = e }; ok(_thrown && _thrown.name == "IndexSizeError" && _thrown.code == DOMException.INDEX_SIZE_ERR, "should throw IndexSizeError");
-todo_isPixel(ctx, 50,25, 0,255,0,255, 2);
-
-} catch (e) {
-    _thrown_outer = true;
-}
-todo(!_thrown_outer, 'should not throw exception');
-
-
-}
-</script>
-<img src="image_green.png" id="green_7.png" class="resource">
-<img src="image_red.png" id="red_11.png" class="resource">
-
 <!-- [[[ test_2d.drawImage.path.html ]]] -->
 
 <p>Canvas test: 2d.drawImage.path</p>
 <canvas id="c123" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
 <script>
 
 
 function test_2d_drawImage_path() {
@@ -22123,21 +22067,16 @@ function runTests() {
   ok(false, "unexpected exception thrown in: test_2d_drawImage_nowrap");
  }
  try {
   test_2d_drawImage_null();
  } catch (e) {
   ok(false, "unexpected exception thrown in: test_2d_drawImage_null");
  }
  try {
-  test_2d_drawImage_outsidesource();
- } catch (e) {
-  ok(false, "unexpected exception thrown in: test_2d_drawImage_outsidesource");
- }
- try {
   test_2d_drawImage_path();
  } catch (e) {
   ok(false, "unexpected exception thrown in: test_2d_drawImage_path");
  }
  try {
   test_2d_drawImage_self_1();
  } catch (e) {
   ok(false, "unexpected exception thrown in: test_2d_drawImage_self_1");
--- a/dom/inputmethod/Keyboard.jsm
+++ b/dom/inputmethod/Keyboard.jsm
@@ -40,18 +40,20 @@ let Utils = {
   }
 };
 
 this.Keyboard = {
   _formMM: null,      // The current web page message manager.
   _keyboardMM: null,  // The keyboard app message manager.
   _keyboardID: -1,    // The keyboard app's ID number. -1 = invalid
   _nextKeyboardID: 0, // The ID number counter.
-  _systemMessageName: [
-    'SetValue', 'RemoveFocus', 'SetSelectedOption', 'SetSelectedOptions'
+  _supportsSwitchingTypes: [],
+  _systemMessageNames: [
+    'SetValue', 'RemoveFocus', 'SetSelectedOption', 'SetSelectedOptions',
+    'SetSupportsSwitchingTypes'
   ],
 
   _messageNames: [
     'RemoveFocus',
     'SetSelectionRange', 'ReplaceSurroundingText', 'ShowInputMethodPicker',
     'SwitchToNextInputMethod', 'HideInputMethod',
     'GetText', 'SendKey', 'GetContext',
     'SetComposition', 'EndComposition',
@@ -65,16 +67,22 @@ this.Keyboard = {
     return null;
   },
 
   set formMM(mm) {
     this._formMM = mm;
   },
 
   sendToForm: function(name, data) {
+    if (!this.formMM) {
+      dump("Keyboard.jsm: Attempt to send message " + name +
+        " to form but no message manager exists.\n");
+
+      return;
+    }
     try {
       this.formMM.sendAsyncMessage(name, data);
     } catch(e) { }
   },
 
   sendToKeyboard: function(name, data) {
     try {
       this._keyboardMM.sendAsyncMessage(name, data);
@@ -86,17 +94,17 @@ this.Keyboard = {
     Services.obs.addObserver(this, 'remote-browser-shown', false);
     Services.obs.addObserver(this, 'oop-frameloader-crashed', false);
     Services.obs.addObserver(this, 'message-manager-close', false);
 
     for (let name of this._messageNames) {
       ppmm.addMessageListener('Keyboard:' + name, this);
     }
 
-    for (let name of this._systemMessageName) {
+    for (let name of this._systemMessageNames) {
       ppmm.addMessageListener('System:' + name, this);
     }
 
     this.inputRegistryGlue = new InputRegistryGlue();
   },
 
   observe: function keyboardObserve(subject, topic, data) {
     let frameLoader = null;
@@ -105,17 +113,17 @@ this.Keyboard = {
     if (topic == 'message-manager-close') {
       mm = subject;
     } else {
       frameLoader = subject.QueryInterface(Ci.nsIFrameLoader);
       mm = frameLoader.messageManager;
     }
 
     if (topic == 'oop-frameloader-crashed' ||
-	topic == 'message-manager-close') {
+	      topic == 'message-manager-close') {
       if (this.formMM == mm) {
         // The application has been closed unexpectingly. Let's tell the
         // keyboard app that the focus has been lost.
         this.sendToKeyboard('Keyboard:Blur', {});
         // Notify system app to hide keyboard.
         SystemAppProxy.dispatchEvent({
           type: 'inputmethod-contextchange',
           inputType: 'blur'
@@ -147,38 +155,36 @@ this.Keyboard = {
     mm.addMessageListener('Forms:SetComposition:Result:OK', this);
     mm.addMessageListener('Forms:EndComposition:Result:OK', this);
   },
 
   receiveMessage: function keyboardReceiveMessage(msg) {
     // If we get a 'Keyboard:XXX'/'System:XXX' message, check that the sender
     // has the required permission.
     let mm;
-    let isKeyboardRegistration = msg.name == "Keyboard:Register" ||
-                                 msg.name == "Keyboard:Unregister";
-    if (msg.name.indexOf("Keyboard:") === 0 ||
-        msg.name.indexOf("System:") === 0) {
-      if (!this.formMM && !isKeyboardRegistration) {
+
+    // Assert the permission based on the prefix of the message.
+    let permName;
+    if (msg.name.startsWith("Keyboard:")) {
+      permName = "input";
+    } else if (msg.name.startsWith("System:")) {
+      permName = "input-manage";
+    }
+
+    // There is no permission to check (nor we need to get the mm)
+    // for Form: messages.
+    if (permName) {
+      mm = Utils.getMMFromMessage(msg);
+      if (!mm) {
+        dump("Keyboard.jsm: Message " + msg.name + " has no message manager.");
         return;
       }
-
-      mm = Utils.getMMFromMessage(msg);
-
-      // That should never happen.
-      if (!mm) {
-        dump("!! No message manager found for " + msg.name);
-        return;
-      }
-
-      let perm = (msg.name.indexOf("Keyboard:") === 0) ? "input"
-                                                       : "input-manage";
-
-      if (!isKeyboardRegistration && !Utils.checkPermissionForMM(mm, perm)) {
-        dump("Keyboard message " + msg.name +
-        " from a content process with no '" + perm + "' privileges.");
+      if (!Utils.checkPermissionForMM(mm, permName)) {
+        dump("Keyboard.jsm: Message " + msg.name +
+          " from a content process with no '" + permName + "' privileges.");
         return;
       }
     }
 
     // we don't process kb messages (other than register)
     // if they come from a kb that we're currently not regsitered for.
     // this decision is made with the kbID kept by us and kb app
     let kbID = null;
@@ -224,16 +230,19 @@ this.Keyboard = {
         this.removeFocus();
         break;
       case 'System:SetSelectedOption':
         this.setSelectedOption(msg);
         break;
       case 'System:SetSelectedOptions':
         this.setSelectedOption(msg);
         break;
+      case 'System:SetSupportsSwitchingTypes':
+        this.setSupportsSwitchingTypes(msg);
+        break;
       case 'Keyboard:SetSelectionRange':
         this.setSelectionRange(msg);
         break;
       case 'Keyboard:ReplaceSurroundingText':
         this.replaceSurroundingText(msg);
         break;
       case 'Keyboard:SwitchToNextInputMethod':
         this.switchToNextInputMethod();
@@ -336,16 +345,20 @@ this.Keyboard = {
     this.sendToForm('Forms:SetSelectionRange', msg.data);
   },
 
   setValue: function keyboardSetValue(msg) {
     this.sendToForm('Forms:Input:Value', msg.data);
   },
 
   removeFocus: function keyboardRemoveFocus() {
+    if (!this.formMM) {
+      return;
+    }
+
     this.sendToForm('Forms:Select:Blur', {});
   },
 
   replaceSurroundingText: function keyboardReplaceSurroundingText(msg) {
     this.sendToForm('Forms:ReplaceSurroundingText', msg.data);
   },
 
   showInputMethodPicker: function keyboardShowInputMethodPicker() {
@@ -364,42 +377,57 @@ this.Keyboard = {
     this.sendToForm('Forms:GetText', msg.data);
   },
 
   sendKey: function keyboardSendKey(msg) {
     this.sendToForm('Forms:Input:SendKey', msg.data);
   },
 
   getContext: function keyboardGetContext(msg) {
-    if (this._layouts) {
-      this.sendToKeyboard('Keyboard:LayoutsChange', this._layouts);
+    if (!this.formMM) {
+      return;
     }
 
+    this.sendToKeyboard('Keyboard:SupportsSwitchingTypesChange', {
+      types: this._supportsSwitchingTypes
+    });
+
     this.sendToForm('Forms:GetContext', msg.data);
   },
 
   setComposition: function keyboardSetComposition(msg) {
     this.sendToForm('Forms:SetComposition', msg.data);
   },
 
   endComposition: function keyboardEndComposition(msg) {
     this.sendToForm('Forms:EndComposition', msg.data);
   },
 
-  /**
-   * Get the number of keyboard layouts active from keyboard_manager
-   */
-  _layouts: null,
-  setLayouts: function keyboardSetLayoutCount(layouts) {
+  setSupportsSwitchingTypes: function setSupportsSwitchingTypes(msg) {
+    this._supportsSwitchingTypes = msg.data.types;
+    this.sendToKeyboard('Keyboard:SupportsSwitchingTypesChange', msg.data);
+  },
+  // XXX: To be removed with mozContentEvent support from shell.js
+  setLayouts: function keyboardSetLayouts(layouts) {
     // The input method plugins may not have loaded yet,
     // cache the layouts so on init we can respond immediately instead
     // of going back and forth between keyboard_manager
-    this._layouts = layouts;
+    var types = [];
 
-    this.sendToKeyboard('Keyboard:LayoutsChange', layouts);
+    Object.keys(layouts).forEach((type) => {
+      if (layouts[type] > 1) {
+        types.push(type);
+      }
+    });
+
+    this._supportsSwitchingTypes = types;
+
+    this.sendToKeyboard('Keyboard:SupportsSwitchingTypesChange', {
+      types: types
+    });
   }
 };
 
 function InputRegistryGlue() {
   this._messageId = 0;
   this._msgMap = new Map();
 
   ppmm.addMessageListener('InputRegistry:Add', this);
--- a/dom/inputmethod/MozKeyboard.js
+++ b/dom/inputmethod/MozKeyboard.js
@@ -131,17 +131,17 @@ let cpmmSendAsyncMessageWithKbID = funct
  * InputMethodManager
  * ==============================================
  */
 function MozInputMethodManager(win) {
   this._window = win;
 }
 
 MozInputMethodManager.prototype = {
-  _supportsSwitching: false,
+  supportsSwitchingForCurrentInputContext: false,
   _window: null,
 
   classID: Components.ID("{7e9d7280-ef86-11e2-b778-0800200c9a66}"),
 
   QueryInterface: XPCOMUtils.generateQI([]),
 
   showAll: function() {
     if (!WindowMap.isActive(this._window)) {
@@ -156,40 +156,46 @@ MozInputMethodManager.prototype = {
     }
     cpmmSendAsyncMessageWithKbID(this, 'Keyboard:SwitchToNextInputMethod', {});
   },
 
   supportsSwitching: function() {
     if (!WindowMap.isActive(this._window)) {
       return false;
     }
-    return this._supportsSwitching;
+    return this.supportsSwitchingForCurrentInputContext;
   },
 
   hide: function() {
     if (!WindowMap.isActive(this._window)) {
       return;
     }
     cpmmSendAsyncMessageWithKbID(this, 'Keyboard:RemoveFocus', {});
+  },
+
+  setSupportsSwitchingTypes: function(types) {
+    cpmm.sendAsyncMessage('System:SetSupportsSwitchingTypes', {
+      types: types
+    });
   }
 };
 
 /**
  * ==============================================
  * InputMethod
  * ==============================================
  */
 function MozInputMethod() { }
 
 MozInputMethod.prototype = {
   __proto__: DOMRequestIpcHelper.prototype,
 
   _inputcontext: null,
   _wrappedInputContext: null,
-  _layouts: {},
+  _supportsSwitchingTypes: [],
   _window: null,
 
   classID: Components.ID("{4607330d-e7d2-40a4-9eb8-43967eae0142}"),
 
   QueryInterface: XPCOMUtils.generateQI([
     Ci.nsIDOMGlobalPropertyInitializer,
     Ci.nsIObserver,
     Ci.nsISupportsWeakReference
@@ -203,30 +209,30 @@ MozInputMethod.prototype = {
                             .currentInnerWindowID;
 
     Services.obs.addObserver(this, "inner-window-destroyed", false);
 
     cpmm.addWeakMessageListener('Keyboard:Focus', this);
     cpmm.addWeakMessageListener('Keyboard:Blur', this);
     cpmm.addWeakMessageListener('Keyboard:SelectionChange', this);
     cpmm.addWeakMessageListener('Keyboard:GetContext:Result:OK', this);
-    cpmm.addWeakMessageListener('Keyboard:LayoutsChange', this);
+    cpmm.addWeakMessageListener('Keyboard:SupportsSwitchingTypesChange', this);
     cpmm.addWeakMessageListener('InputRegistry:Result:OK', this);
     cpmm.addWeakMessageListener('InputRegistry:Result:Error', this);
   },
 
   uninit: function mozInputMethodUninit() {
     this._window = null;
     this._mgmt = null;
 
     cpmm.removeWeakMessageListener('Keyboard:Focus', this);
     cpmm.removeWeakMessageListener('Keyboard:Blur', this);
     cpmm.removeWeakMessageListener('Keyboard:SelectionChange', this);
     cpmm.removeWeakMessageListener('Keyboard:GetContext:Result:OK', this);
-    cpmm.removeWeakMessageListener('Keyboard:LayoutsChange', this);
+    cpmm.removeWeakMessageListener('Keyboard:SupportsSwitchingTypesChange', this);
     cpmm.removeWeakMessageListener('InputRegistry:Result:OK', this);
     cpmm.removeWeakMessageListener('InputRegistry:Result:Error', this);
     this.setActive(false);
   },
 
   receiveMessage: function mozInputMethodReceiveMsg(msg) {
     if (!msg.name.startsWith('InputRegistry') &&
         !WindowMap.isActive(this._window)) {
@@ -248,18 +254,18 @@ MozInputMethod.prototype = {
       case 'Keyboard:SelectionChange':
         if (this.inputcontext) {
           this._inputcontext.updateSelectionContext(data, false);
         }
         break;
       case 'Keyboard:GetContext:Result:OK':
         this.setInputContext(data);
         break;
-      case 'Keyboard:LayoutsChange':
-        this._layouts = data;
+      case 'Keyboard:SupportsSwitchingTypesChange':
+        this._supportsSwitchingTypes = data.types;
         break;
 
       case 'InputRegistry:Result:OK':
         resolver.resolve();
 
         break;
 
       case 'InputRegistry:Result:Error':
@@ -294,23 +300,22 @@ MozInputMethod.prototype = {
     return this.__DOM_IMPL__.getEventHandler("oninputcontextchange");
   },
 
   setInputContext: function mozKeyboardContextChange(data) {
     if (this._inputcontext) {
       this._inputcontext.destroy();
       this._inputcontext = null;
       this._wrappedInputContext = null;
-      this._mgmt._supportsSwitching = false;
+      this._mgmt.supportsSwitchingForCurrentInputContext = false;
     }
 
     if (data) {
-      this._mgmt._supportsSwitching = this._layouts[data.inputType] ?
-        this._layouts[data.inputType] > 1 :
-        false;
+      this._mgmt.supportsSwitchingForCurrentInputContext =
+        (this._supportsSwitchingTypes.indexOf(data.inputType) !== -1);
 
       this._inputcontext = new MozInputContext(data);
       this._inputcontext.init(this._window);
       // inputcontext will be exposed as a WebIDL object. Create its
       // content-side object explicitly to avoid Bug 1001325.
       this._wrappedInputContext =
         this._window.MozInputContext._create(this._window, this._inputcontext);
     }
--- a/dom/inputmethod/mochitest/mochitest.ini
+++ b/dom/inputmethod/mochitest/mochitest.ini
@@ -16,14 +16,15 @@ support-files =
 [test_bug953044.html]
 [test_bug960946.html]
 [test_bug978918.html]
 [test_bug1026997.html]
 [test_bug1043828.html]
 [test_bug1059163.html]
 [test_bug1066515.html]
 [test_bug1175399.html]
+[test_bug1137557.html]
 [test_sendkey_cancel.html]
+[test_setSupportsSwitching.html]
 [test_sync_edit.html]
 [test_two_inputs.html]
 [test_two_selects.html]
 [test_unload.html]
-[test_bug1137557.html]
new file mode 100644
--- /dev/null
+++ b/dom/inputmethod/mochitest/test_setSupportsSwitching.html
@@ -0,0 +1,134 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1197682
+-->
+<head>
+  <title>Test inputcontext#inputType and MozInputMethodManager#supportsSwitching()</title>
+  <script type="application/javascript;version=1.7" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <script type="application/javascript;version=1.7" src="inputmethod_common.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1197682">Mozilla Bug 1197682</a>
+<p id="display"></p>
+<pre id="test">
+<script class="testbody" type="application/javascript;version=1.7">
+
+inputmethod_setup(function() {
+  runTest();
+});
+
+let appFrameScript = function appFrameScript() {
+  let input = content.document.body.firstElementChild;
+
+  let i = 1;
+
+  input.focus();
+
+  addMessageListener('test:next', function() {
+    i++;
+    switch (i) {
+      case 2:
+        content.document.body.children[1].focus();
+        i++; // keep the same count with the parent frame.
+
+        break;
+
+      case 4:
+        content.document.body.lastElementChild.focus();
+        i++; // keep the same count with the parent frame.
+
+        break;
+
+      case 6:
+        content.document.body.lastElementChild.blur();
+
+        break;
+    }
+  });
+};
+
+function runTest() {
+  let im = navigator.mozInputMethod;
+
+  let i = 0;
+  im.oninputcontextchange = function(evt) {
+    var inputcontext = navigator.mozInputMethod.inputcontext;
+
+    i++;
+    switch (i) {
+      case 1:
+        ok(!!inputcontext, '1) Receving the input context');
+        is(inputcontext.inputType, 'text', '1) input type');
+        is(im.mgmt.supportsSwitching(), true, '1) supports switching');
+
+        mm.sendAsyncMessage('test:next');
+        break;
+
+      case 2:
+        is(inputcontext, null, '2) Receving null inputcontext');
+
+        break;
+
+      case 3:
+        ok(!!inputcontext, '3) Receving the input context');
+        is(inputcontext.inputType, 'number', '3) input type');
+        is(im.mgmt.supportsSwitching(), false, '3) supports switching');
+
+        mm.sendAsyncMessage('test:next');
+        break;
+
+      case 4:
+        is(inputcontext, null, '4) Receving null inputcontext');
+
+        break;
+
+      case 5:
+        ok(!!inputcontext, '5) Receving the input context');
+        is(inputcontext.inputType, 'password', '5) input type');
+        is(im.mgmt.supportsSwitching(), true, '5) supports switching');
+
+        mm.sendAsyncMessage('test:next');
+        break;
+
+      case 6:
+        is(inputcontext, null, '6) Receving null inputcontext');
+        is(im.mgmt.supportsSwitching(), false, '6) supports switching');
+
+        inputmethod_cleanup();
+        break;
+
+      default:
+        ok(false, 'Receving extra inputcontextchange calls');
+        inputmethod_cleanup();
+
+        break;
+    }
+  };
+
+  // Set current page as an input method.
+  SpecialPowers.wrap(im).setActive(true);
+  // Set text and password inputs as supports switching (and not supported for number type)
+  im.mgmt.setSupportsSwitchingTypes(['text', 'password']);
+
+  let iframe = document.createElement('iframe');
+  iframe.src = 'data:text/html,<html><body>' +
+    '<input type="text">' +
+    '<input type="number">' +
+    '<input type="password">' +
+    '</body></html>';
+  iframe.setAttribute('mozbrowser', true);
+  document.body.appendChild(iframe);
+
+  let mm = SpecialPowers.getBrowserFrameMessageManager(iframe);
+
+  iframe.addEventListener('mozbrowserloadend', function() {
+    mm.loadFrameScript('data:,(' + encodeURIComponent(appFrameScript.toString()) + ')();', false);
+  });
+}
+
+</script>
+</pre>
+</body>
+</html>
--- a/dom/media/MediaDecoder.cpp
+++ b/dom/media/MediaDecoder.cpp
@@ -344,18 +344,16 @@ bool MediaDecoder::IsInfinite()
 {
   MOZ_ASSERT(NS_IsMainThread());
   return mInfiniteStream;
 }
 
 MediaDecoder::MediaDecoder() :
   mWatchManager(this, AbstractThread::MainThread()),
   mDormantSupported(false),
-  mDecoderPosition(0),
-  mPlaybackPosition(0),
   mLogicalPosition(0.0),
   mDuration(std::numeric_limits<double>::quiet_NaN()),
   mMediaSeekable(true),
   mReentrantMonitor("media.decoder"),
   mIgnoreProgressData(false),
   mInfiniteStream(false),
   mOwner(nullptr),
   mPlaybackStatistics(new MediaChannelStatistics()),
@@ -379,16 +377,18 @@ MediaDecoder::MediaDecoder() :
             "MediaDecoder::mBuffered (Mirror)"),
   mNextFrameStatus(AbstractThread::MainThread(),
                    MediaDecoderOwner::NEXT_FRAME_UNINITIALIZED,
                    "MediaDecoder::mNextFrameStatus (Mirror)"),
   mCurrentPosition(AbstractThread::MainThread(), 0,
                    "MediaDecoder::mCurrentPosition (Mirror)"),
   mStateMachineDuration(AbstractThread::MainThread(), NullableTimeUnit(),
                         "MediaDecoder::mStateMachineDuration (Mirror)"),
+  mPlaybackPosition(AbstractThread::MainThread(), 0,
+                    "MediaDecoder::mPlaybackPosition (Mirror)"),
   mVolume(AbstractThread::MainThread(), 0.0,
           "MediaDecoder::mVolume (Canonical)"),
   mPlaybackRate(AbstractThread::MainThread(), 1.0,
                 "MediaDecoder::mPlaybackRate (Canonical)"),
   mPreservesPitch(AbstractThread::MainThread(), true,
                   "MediaDecoder::mPreservesPitch (Canonical)"),
   mEstimatedDuration(AbstractThread::MainThread(), NullableTimeUnit(),
                      "MediaDecoder::mEstimatedDuration (Canonical)"),
@@ -396,17 +396,23 @@ MediaDecoder::MediaDecoder() :
                     "MediaDecoder::mExplicitDuration (Canonical)"),
   mPlayState(AbstractThread::MainThread(), PLAY_STATE_LOADING,
              "MediaDecoder::mPlayState (Canonical)"),
   mNextState(AbstractThread::MainThread(), PLAY_STATE_PAUSED,
              "MediaDecoder::mNextState (Canonical)"),
   mLogicallySeeking(AbstractThread::MainThread(), false,
                     "MediaDecoder::mLogicallySeeking (Canonical)"),
   mSameOriginMedia(AbstractThread::MainThread(), false,
-                   "MediaDecoder::mSameOriginMedia (Canonical)")
+                   "MediaDecoder::mSameOriginMedia (Canonical)"),
+  mPlaybackBytesPerSecond(AbstractThread::MainThread(), 0.0,
+                          "MediaDecoder::mPlaybackBytesPerSecond (Canonical)"),
+  mPlaybackRateReliable(AbstractThread::MainThread(), true,
+                        "MediaDecoder::mPlaybackRateReliable (Canonical)"),
+  mDecoderPosition(AbstractThread::MainThread(), 0,
+                   "MediaDecoder::mDecoderPosition (Canonical)")
 {
   MOZ_COUNT_CTOR(MediaDecoder);
   MOZ_ASSERT(NS_IsMainThread());
   MediaMemoryTracker::AddMediaDecoder(this);
 
   mAudioChannel = AudioChannelService::GetDefaultAudioChannel();
 
   //
@@ -811,73 +817,69 @@ void MediaDecoder::PlaybackEnded()
   if (IsInfinite()) {
     SetInfinite(false);
   }
 }
 
 MediaStatistics
 MediaDecoder::GetStatistics()
 {
-  MediaStatistics result;
-
+  MOZ_ASSERT(NS_IsMainThread());
   ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
-  if (mResource) {
-    result.mDownloadRate =
-      mResource->GetDownloadRate(&result.mDownloadRateReliable);
-    result.mDownloadPosition =
-      mResource->GetCachedDataEnd(mDecoderPosition);
-    result.mTotalBytes = mResource->GetLength();
-    result.mPlaybackRate = ComputePlaybackRate(&result.mPlaybackRateReliable);
-    result.mDecoderPosition = mDecoderPosition;
-    result.mPlaybackPosition = mPlaybackPosition;
-  }
-  else {
-    result.mDownloadRate = 0;
-    result.mDownloadRateReliable = true;
-    result.mPlaybackRate = 0;
-    result.mPlaybackRateReliable = true;
-    result.mDecoderPosition = 0;
-    result.mPlaybackPosition = 0;
-    result.mDownloadPosition = 0;
-    result.mTotalBytes = 0;
-  }
+  MOZ_ASSERT(mResource);
 
+  MediaStatistics result;
+  result.mDownloadRate = mResource->GetDownloadRate(&result.mDownloadRateReliable);
+  result.mDownloadPosition = mResource->GetCachedDataEnd(mDecoderPosition);
+  result.mTotalBytes = mResource->GetLength();
+  result.mPlaybackRate = mPlaybackBytesPerSecond;
+  result.mPlaybackRateReliable = mPlaybackRateReliable;
+  result.mDecoderPosition = mDecoderPosition;
+  result.mPlaybackPosition = mPlaybackPosition;
   return result;
 }
 
-double MediaDecoder::ComputePlaybackRate(bool* aReliable)
+void
+MediaDecoder::ComputePlaybackRate()
 {
-  GetReentrantMonitor().AssertCurrentThreadIn();
-  MOZ_ASSERT(NS_IsMainThread() || OnStateMachineTaskQueue() || OnDecodeTaskQueue());
+  MOZ_ASSERT(NS_IsMainThread());
+  ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
+  MOZ_ASSERT(mResource);
 
-  int64_t length = mResource ? mResource->GetLength() : -1;
+  int64_t length = mResource->GetLength();
   if (!IsNaN(mDuration) && !mozilla::IsInfinite<double>(mDuration) && length >= 0) {
-    *aReliable = true;
-    return length / mDuration;
+    mPlaybackRateReliable = true;
+    mPlaybackBytesPerSecond = length / mDuration;
+    return;
   }
-  return mPlaybackStatistics->GetRateAtLastStop(aReliable);
+
+  bool reliable = false;
+  mPlaybackBytesPerSecond = mPlaybackStatistics->GetRateAtLastStop(&reliable);
+  mPlaybackRateReliable = reliable;
 }
 
-void MediaDecoder::UpdatePlaybackRate()
+void
+MediaDecoder::UpdatePlaybackRate()
 {
   MOZ_ASSERT(NS_IsMainThread());
   GetReentrantMonitor().AssertCurrentThreadIn();
-  if (!mResource)
-    return;
-  bool reliable;
-  uint32_t rate = uint32_t(ComputePlaybackRate(&reliable));
-  if (reliable) {
+  MOZ_ASSERT(mResource);
+
+  ComputePlaybackRate();
+  uint32_t rate = mPlaybackBytesPerSecond;
+
+  if (mPlaybackRateReliable) {
     // Avoid passing a zero rate
     rate = std::max(rate, 1u);
-  }
-  else {
+  } else {
     // Set a minimum rate of 10,000 bytes per second ... sometimes we just
     // don't have good data
     rate = std::max(rate, 10000u);
   }
+
   mResource->SetPlaybackRate(rate);
 }
 
 void MediaDecoder::NotifySuspendedStatusChanged()
 {
   MOZ_ASSERT(NS_IsMainThread());
   if (mResource && mOwner) {
     bool suspended = mResource->IsSuspendedByCache();
@@ -1177,22 +1179,16 @@ void MediaDecoder::Resume(bool aForceBuf
 void MediaDecoder::SetLoadInBackground(bool aLoadInBackground)
 {
   MOZ_ASSERT(NS_IsMainThread());
   if (mResource) {
     mResource->SetLoadInBackground(aLoadInBackground);
   }
 }
 
-void MediaDecoder::UpdatePlaybackOffset(int64_t aOffset)
-{
-  GetReentrantMonitor().AssertCurrentThreadIn();
-  mPlaybackPosition = aOffset;
-}
-
 bool MediaDecoder::OnStateMachineTaskQueue() const
 {
   return mDecoderStateMachine->OnTaskQueue();
 }
 
 void MediaDecoder::SetPlaybackRate(double aPlaybackRate)
 {
   MOZ_ASSERT(NS_IsMainThread());
@@ -1230,22 +1226,24 @@ MediaDecoder::SetStateMachine(MediaDecod
   mDecoderStateMachine = aStateMachine;
 
   if (mDecoderStateMachine) {
     mStateMachineDuration.Connect(mDecoderStateMachine->CanonicalDuration());
     mBuffered.Connect(mDecoderStateMachine->CanonicalBuffered());
     mStateMachineIsShutdown.Connect(mDecoderStateMachine->CanonicalIsShutdown());
     mNextFrameStatus.Connect(mDecoderStateMachine->CanonicalNextFrameStatus());
     mCurrentPosition.Connect(mDecoderStateMachine->CanonicalCurrentPosition());
+    mPlaybackPosition.Connect(mDecoderStateMachine->CanonicalPlaybackOffset());
   } else {
     mStateMachineDuration.DisconnectIfConnected();
     mBuffered.DisconnectIfConnected();
     mStateMachineIsShutdown.DisconnectIfConnected();
     mNextFrameStatus.DisconnectIfConnected();
     mCurrentPosition.DisconnectIfConnected();
+    mPlaybackPosition.DisconnectIfConnected();
   }
 }
 
 ReentrantMonitor& MediaDecoder::GetReentrantMonitor() {
   return mReentrantMonitor;
 }
 
 ImageContainer* MediaDecoder::GetImageContainer()
--- a/dom/media/MediaDecoder.h
+++ b/dom/media/MediaDecoder.h
@@ -563,23 +563,25 @@ public:
       NS_NewRunnableFunction([self] () { self->mPlaybackStatistics->Start(); });
     AbstractThread::MainThread()->Dispatch(r.forget());
   }
 
   // Used to estimate rates of data passing through the decoder's channel.
   // Records activity stopping on the channel.
   void DispatchPlaybackStopped() {
     nsRefPtr<MediaDecoder> self = this;
-    nsCOMPtr<nsIRunnable> r =
-      NS_NewRunnableFunction([self] () { self->mPlaybackStatistics->Stop(); });
+    nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction([self] () {
+      self->mPlaybackStatistics->Stop();
+      self->ComputePlaybackRate();
+    });
     AbstractThread::MainThread()->Dispatch(r.forget());
   }
 
   // The actual playback rate computation. The monitor must be held.
-  virtual double ComputePlaybackRate(bool* aReliable);
+  void ComputePlaybackRate();
 
   // Returns true if we can play the entire media through without stopping
   // to buffer, given the current download and playback rates.
   bool CanPlayThrough();
 
   void SetAudioChannel(dom::AudioChannel aChannel) { mAudioChannel = aChannel; }
   dom::AudioChannel GetAudioChannel() { return mAudioChannel; }
 
@@ -647,20 +649,16 @@ public:
     MOZ_ASSERT(NS_IsMainThread());
     UpdateLogicalPosition(MediaDecoderEventVisibility::Observable);
   }
 
   // Find the end of the cached data starting at the current decoder
   // position.
   int64_t GetDownloadPosition();
 
-  // Updates the approximate byte offset which playback has reached. This is
-  // used to calculate the readyState transitions.
-  void UpdatePlaybackOffset(int64_t aOffset);
-
   // Provide access to the state machine object
   MediaDecoderStateMachine* GetStateMachine() const;
 
   // Drop reference to state machine.  Only called during shutdown dance.
   virtual void BreakCycles();
 
   // Notifies the element that decoding has failed.
   virtual void DecodeError();
@@ -874,27 +872,16 @@ protected:
 
   /******
    * The following members should be accessed with the decoder lock held.
    ******/
 
   // Whether the decoder implementation supports dormant mode.
   bool mDormantSupported;
 
-  // Current decoding position in the stream. This is where the decoder
-  // is up to consuming the stream. This is not adjusted during decoder
-  // seek operations, but it's updated at the end when we start playing
-  // back again.
-  int64_t mDecoderPosition;
-  // Current playback position in the stream. This is (approximately)
-  // where we're up to playing back the stream. This is not adjusted
-  // during decoder seek operations, but it's updated at the end when we
-  // start playing back again.
-  int64_t mPlaybackPosition;
-
   // The logical playback position of the media resource in units of
   // seconds. This corresponds to the "official position" in HTML5. Note that
   // we need to store this as a double, rather than an int64_t (like
   // mCurrentPosition), so that |v.currentTime = foo; v.currentTime == foo|
   // returns true without being affected by rounding errors.
   double mLogicalPosition;
 
   // The current playback position of the underlying playback infrastructure.
@@ -1046,16 +1033,22 @@ protected:
   Mirror<MediaDecoderOwner::NextFrameStatus> mNextFrameStatus;
 
   // NB: Don't use mCurrentPosition directly, but rather CurrentPosition().
   Mirror<int64_t> mCurrentPosition;
 
   // Duration of the media resource according to the state machine.
   Mirror<media::NullableTimeUnit> mStateMachineDuration;
 
+  // Current playback position in the stream. This is (approximately)
+  // where we're up to playing back the stream. This is not adjusted
+  // during decoder seek operations, but it's updated at the end when we
+  // start playing back again.
+  Mirror<int64_t> mPlaybackPosition;
+
   // Volume of playback.  0.0 = muted. 1.0 = full volume.
   Canonical<double> mVolume;
 
   // PlaybackRate and pitch preservation status we should start at.
   Canonical<double> mPlaybackRate;
 
   Canonical<bool> mPreservesPitch;
 
@@ -1083,16 +1076,28 @@ protected:
 
   // True if the decoder is seeking.
   Canonical<bool> mLogicallySeeking;
 
   // True if the media is same-origin with the element. Data can only be
   // passed to MediaStreams when this is true.
   Canonical<bool> mSameOriginMedia;
 
+  // Estimate of the current playback rate (bytes/second).
+  Canonical<double> mPlaybackBytesPerSecond;
+
+  // True if mPlaybackBytesPerSecond is a reliable estimate.
+  Canonical<bool> mPlaybackRateReliable;
+
+  // Current decoding position in the stream. This is where the decoder
+  // is up to consuming the stream. This is not adjusted during decoder
+  // seek operations, but it's updated at the end when we start playing
+  // back again.
+  Canonical<int64_t> mDecoderPosition;
+
 public:
   AbstractCanonical<media::NullableTimeUnit>* CanonicalDurationOrNull() override;
   AbstractCanonical<double>* CanonicalVolume() {
     return &mVolume;
   }
   AbstractCanonical<double>* CanonicalPlaybackRate() {
     return &mPlaybackRate;
   }
@@ -1112,13 +1117,22 @@ public:
     return &mNextState;
   }
   AbstractCanonical<bool>* CanonicalLogicallySeeking() {
     return &mLogicallySeeking;
   }
   AbstractCanonical<bool>* CanonicalSameOriginMedia() {
     return &mSameOriginMedia;
   }
+  AbstractCanonical<double>* CanonicalPlaybackBytesPerSecond() {
+    return &mPlaybackBytesPerSecond;
+  }
+  AbstractCanonical<bool>* CanonicalPlaybackRateReliable() {
+    return &mPlaybackRateReliable;
+  }
+  AbstractCanonical<int64_t>* CanonicalDecoderPosition() {
+    return &mDecoderPosition;
+  }
 };
 
 } // namespace mozilla
 
 #endif
--- a/dom/media/MediaDecoderStateMachine.cpp
+++ b/dom/media/MediaDecoderStateMachine.cpp
@@ -36,17 +36,16 @@
 
 #include "AudioSegment.h"
 #include "DOMMediaStream.h"
 #include "ImageContainer.h"
 #include "MediaDecoder.h"
 #include "MediaDecoderReader.h"
 #include "MediaDecoderStateMachine.h"
 #include "MediaShutdownManager.h"
-#include "MediaStatistics.h"
 #include "MediaTimer.h"
 #include "TimeUnits.h"
 #include "VideoSegment.h"
 #include "VideoUtils.h"
 
 namespace mozilla {
 
 using namespace mozilla::dom;
@@ -239,24 +238,32 @@ MediaDecoderStateMachine::MediaDecoderSt
                     "MediaDecoderStateMachine::mLogicallySeeking (Mirror)"),
   mVolume(mTaskQueue, 1.0, "MediaDecoderStateMachine::mVolume (Mirror)"),
   mLogicalPlaybackRate(mTaskQueue, 1.0,
                        "MediaDecoderStateMachine::mLogicalPlaybackRate (Mirror)"),
   mPreservesPitch(mTaskQueue, true,
                   "MediaDecoderStateMachine::mPreservesPitch (Mirror)"),
   mSameOriginMedia(mTaskQueue, false,
                    "MediaDecoderStateMachine::mSameOriginMedia (Mirror)"),
+  mPlaybackBytesPerSecond(mTaskQueue, 0.0,
+                          "MediaDecoderStateMachine::mPlaybackBytesPerSecond (Mirror)"),
+  mPlaybackRateReliable(mTaskQueue, true,
+                        "MediaDecoderStateMachine::mPlaybackRateReliable (Mirror)"),
+  mDecoderPosition(mTaskQueue, 0,
+                   "MediaDecoderStateMachine::mDecoderPosition (Mirror)"),
   mDuration(mTaskQueue, NullableTimeUnit(),
             "MediaDecoderStateMachine::mDuration (Canonical"),
   mIsShutdown(mTaskQueue, false,
               "MediaDecoderStateMachine::mIsShutdown (Canonical)"),
   mNextFrameStatus(mTaskQueue, MediaDecoderOwner::NEXT_FRAME_UNINITIALIZED,
                    "MediaDecoderStateMachine::mNextFrameStatus (Canonical)"),
   mCurrentPosition(mTaskQueue, 0,
-                   "MediaDecoderStateMachine::mCurrentPosition (Canonical)")
+                   "MediaDecoderStateMachine::mCurrentPosition (Canonical)"),
+  mPlaybackOffset(mTaskQueue, 0,
+                  "MediaDecoderStateMachine::mPlaybackOffset (Canonical)")
 {
   MOZ_COUNT_CTOR(MediaDecoderStateMachine);
   NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
 
   // Dispatch initialization that needs to happen on that task queue.
   nsCOMPtr<nsIRunnable> r = NS_NewRunnableMethod(this, &MediaDecoderStateMachine::InitializationTask);
   mTaskQueue->Dispatch(r.forget());
 
@@ -319,16 +326,19 @@ MediaDecoderStateMachine::Initialization
   mExplicitDuration.Connect(mDecoder->CanonicalExplicitDuration());
   mPlayState.Connect(mDecoder->CanonicalPlayState());
   mNextPlayState.Connect(mDecoder->CanonicalNextPlayState());
   mLogicallySeeking.Connect(mDecoder->CanonicalLogicallySeeking());
   mVolume.Connect(mDecoder->CanonicalVolume());
   mLogicalPlaybackRate.Connect(mDecoder->CanonicalPlaybackRate());
   mPreservesPitch.Connect(mDecoder->CanonicalPreservesPitch());
   mSameOriginMedia.Connect(mDecoder->CanonicalSameOriginMedia());
+  mPlaybackBytesPerSecond.Connect(mDecoder->CanonicalPlaybackBytesPerSecond());
+  mPlaybackRateReliable.Connect(mDecoder->CanonicalPlaybackRateReliable());
+  mDecoderPosition.Connect(mDecoder->CanonicalDecoderPosition());
 
   // Initialize watchers.
   mWatchManager.Watch(mBuffered, &MediaDecoderStateMachine::BufferedRangeUpdated);
   mWatchManager.Watch(mState, &MediaDecoderStateMachine::UpdateNextFrameStatus);
   mWatchManager.Watch(mAudioCompleted, &MediaDecoderStateMachine::UpdateNextFrameStatus);
   mWatchManager.Watch(mVolume, &MediaDecoderStateMachine::VolumeChanged);
   mWatchManager.Watch(mLogicalPlaybackRate, &MediaDecoderStateMachine::LogicalPlaybackRateChanged);
   mWatchManager.Watch(mPreservesPitch, &MediaDecoderStateMachine::PreservesPitchChanged);
@@ -681,27 +691,27 @@ MediaDecoderStateMachine::PushFront(Medi
   UpdateNextFrameStatus();
 }
 
 void
 MediaDecoderStateMachine::OnAudioPopped(const nsRefPtr<MediaData>& aSample)
 {
   MOZ_ASSERT(OnTaskQueue());
   ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
-  mDecoder->UpdatePlaybackOffset(std::max<int64_t>(0, aSample->mOffset));
+  mPlaybackOffset = std::max(mPlaybackOffset.Ref(), aSample->mOffset);
   UpdateNextFrameStatus();
   DispatchAudioDecodeTaskIfNeeded();
 }
 
 void
 MediaDecoderStateMachine::OnVideoPopped(const nsRefPtr<MediaData>& aSample)
 {
   MOZ_ASSERT(OnTaskQueue());
   ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
-  mDecoder->UpdatePlaybackOffset(aSample->mOffset);
+  mPlaybackOffset = std::max(mPlaybackOffset.Ref(), aSample->mOffset);
   UpdateNextFrameStatus();
   DispatchVideoDecodeTaskIfNeeded();
 }
 
 void
 MediaDecoderStateMachine::OnNotDecoded(MediaData::Type aType,
                                        MediaDecoderReader::NotDecodedReason aReason)
 {
@@ -2188,20 +2198,25 @@ MediaDecoderStateMachine::FinishShutdown
   mExplicitDuration.DisconnectIfConnected();
   mPlayState.DisconnectIfConnected();
   mNextPlayState.DisconnectIfConnected();
   mLogicallySeeking.DisconnectIfConnected();
   mVolume.DisconnectIfConnected();
   mLogicalPlaybackRate.DisconnectIfConnected();
   mPreservesPitch.DisconnectIfConnected();
   mSameOriginMedia.DisconnectIfConnected();
+  mPlaybackBytesPerSecond.DisconnectIfConnected();
+  mPlaybackRateReliable.DisconnectIfConnected();
+  mDecoderPosition.DisconnectIfConnected();
+
   mDuration.DisconnectAll();
   mIsShutdown.DisconnectAll();
   mNextFrameStatus.DisconnectAll();
   mCurrentPosition.DisconnectAll();
+  mPlaybackOffset.DisconnectAll();
 
   // Shut down the watch manager before shutting down our task queue.
   mWatchManager.Shutdown();
 
   MOZ_ASSERT(mState == DECODER_STATE_SHUTDOWN,
              "How did we escape from the shutdown state?");
   // We must daisy-chain these events to destroy the decoder. We must
   // destroy the decoder on the main thread, but we can't destroy the
@@ -2428,16 +2443,18 @@ MediaDecoderStateMachine::Reset()
 
   mMetadataRequest.DisconnectIfExists();
   mAudioDataRequest.DisconnectIfExists();
   mAudioWaitRequest.DisconnectIfExists();
   mVideoDataRequest.DisconnectIfExists();
   mVideoWaitRequest.DisconnectIfExists();
   mSeekRequest.DisconnectIfExists();
 
+  mPlaybackOffset = 0;
+
   nsCOMPtr<nsIRunnable> resetTask =
     NS_NewRunnableMethod(mReader, &MediaDecoderReader::ResetDecode);
   DecodeTaskQueue()->Dispatch(resetTask.forget());
 }
 
 bool MediaDecoderStateMachine::CheckFrameValidity(VideoData* aData)
 {
   MOZ_ASSERT(OnTaskQueue());
@@ -2785,17 +2802,32 @@ bool MediaDecoderStateMachine::JustExite
     mQuickBuffering &&
     (TimeStamp::Now() - mDecodeStartTime) < TimeDuration::FromMicroseconds(QUICK_BUFFER_THRESHOLD_USECS);
 }
 
 bool
 MediaDecoderStateMachine::CanPlayThrough()
 {
   MOZ_ASSERT(OnTaskQueue());
-  return IsRealTime() || mDecoder->GetStatistics().CanPlayThrough();
+  return IsRealTime() || GetStatistics().CanPlayThrough();
+}
+
+MediaStatistics
+MediaDecoderStateMachine::GetStatistics()
+{
+  MOZ_ASSERT(OnTaskQueue());
+  MediaStatistics result;
+  result.mDownloadRate = mResource->GetDownloadRate(&result.mDownloadRateReliable);
+  result.mDownloadPosition = mResource->GetCachedDataEnd(mDecoderPosition);
+  result.mTotalBytes = mResource->GetLength();
+  result.mPlaybackRate = mPlaybackBytesPerSecond;
+  result.mPlaybackRateReliable = mPlaybackRateReliable;
+  result.mDecoderPosition = mDecoderPosition;
+  result.mPlaybackPosition = mPlaybackOffset;
+  return result;
 }
 
 void MediaDecoderStateMachine::StartBuffering()
 {
   MOZ_ASSERT(OnTaskQueue());
   ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
 
   if (mState != DECODER_STATE_DECODING) {
@@ -2818,17 +2850,17 @@ void MediaDecoderStateMachine::StartBuff
   mQuickBuffering =
     !JustExitedQuickBuffering() &&
     decodeDuration < UsecsToDuration(QUICK_BUFFER_THRESHOLD_USECS);
   mBufferingStart = TimeStamp::Now();
 
   SetState(DECODER_STATE_BUFFERING);
   DECODER_LOG("Changed state from DECODING to BUFFERING, decoded for %.3lfs",
               decodeDuration.ToSeconds());
-  MediaStatistics stats = mDecoder->GetStatistics();
+  MediaStatistics stats = GetStatistics();
   DECODER_LOG("Playback rate: %.1lfKB/s%s download rate: %.1lfKB/s%s",
               stats.mPlaybackRate/1024, stats.mPlaybackRateReliable ? "" : " (unreliable)",
               stats.mDownloadRate/1024, stats.mDownloadRateReliable ? "" : " (unreliable)");
 }
 
 void MediaDecoderStateMachine::ScheduleStateMachineWithLockAndWakeDecoder()
 {
   MOZ_ASSERT(OnTaskQueue());
--- a/dom/media/MediaDecoderStateMachine.h
+++ b/dom/media/MediaDecoderStateMachine.h
@@ -88,16 +88,17 @@ hardware (via AudioStream).
 #include "mozilla/StateMirroring.h"
 
 #include "nsThreadUtils.h"
 #include "MediaDecoder.h"
 #include "MediaDecoderReader.h"
 #include "MediaDecoderOwner.h"
 #include "MediaEventSource.h"
 #include "MediaMetadataManager.h"
+#include "MediaStatistics.h"
 #include "MediaTimer.h"
 #include "ImageContainer.h"
 
 namespace mozilla {
 
 namespace media {
 class MediaSink;
 }
@@ -203,16 +204,18 @@ public:
 private:
   // Causes the state machine to switch to buffering state, and to
   // immediately stop playback and buffer downloaded data. Called on
   // the state machine thread.
   void StartBuffering();
 
   bool CanPlayThrough();
 
+  MediaStatistics GetStatistics();
+
 public:
   void DispatchStartBuffering()
   {
     nsCOMPtr<nsIRunnable> runnable =
       NS_NewRunnableMethod(this, &MediaDecoderStateMachine::StartBuffering);
     OwnerThread()->Dispatch(runnable.forget());
   }
 
@@ -1278,45 +1281,60 @@ private:
 
   // Pitch preservation for the playback rate.
   Mirror<bool> mPreservesPitch;
 
   // True if the media is same-origin with the element. Data can only be
   // passed to MediaStreams when this is true.
   Mirror<bool> mSameOriginMedia;
 
+  // Estimate of the current playback rate (bytes/second).
+  Mirror<double> mPlaybackBytesPerSecond;
+
+  // True if mPlaybackBytesPerSecond is a reliable estimate.
+  Mirror<bool> mPlaybackRateReliable;
+
+  // Current decoding position in the stream.
+  Mirror<int64_t> mDecoderPosition;
+
   // Duration of the media. This is guaranteed to be non-null after we finish
   // decoding the first frame.
   Canonical<media::NullableTimeUnit> mDuration;
 
   // Whether we're currently in or transitioning to shutdown state.
   Canonical<bool> mIsShutdown;
 
   // The status of our next frame. Mirrored on the main thread and used to
   // compute ready state.
   Canonical<NextFrameStatus> mNextFrameStatus;
 
   // The time of the current frame in microseconds, corresponding to the "current
   // playback position" in HTML5. This is referenced from 0, which is the initial
   // playback position.
   Canonical<int64_t> mCurrentPosition;
 
+  // Current playback position in the stream in bytes.
+  Canonical<int64_t> mPlaybackOffset;
+
 public:
   AbstractCanonical<media::TimeIntervals>* CanonicalBuffered() {
     return mReader->CanonicalBuffered();
   }
   AbstractCanonical<media::NullableTimeUnit>* CanonicalDuration() {
     return &mDuration;
   }
   AbstractCanonical<bool>* CanonicalIsShutdown() {
     return &mIsShutdown;
   }
   AbstractCanonical<NextFrameStatus>* CanonicalNextFrameStatus() {
     return &mNextFrameStatus;
   }
   AbstractCanonical<int64_t>* CanonicalCurrentPosition() {
     return &mCurrentPosition;
   }
+  AbstractCanonical<int64_t>* CanonicalPlaybackOffset() {
+    return &mPlaybackOffset;
+  }
 };
 
 } // namespace mozilla
 
 #endif
--- a/dom/media/gmp/rlz/moz.build
+++ b/dom/media/gmp/rlz/moz.build
@@ -14,11 +14,8 @@ USE_STATIC_LIBS = True
 UNIFIED_SOURCES += [
     'lib/string_utils.cc',
     'win/lib/machine_id_win.cc',
 ]
 
 LOCAL_INCLUDES += [
     '..',
 ]
-
-if not CONFIG['GNU_CXX']:
-    ALLOW_COMPILER_WARNINGS = True
--- a/dom/media/platforms/gonk/GonkVideoDecoderManager.cpp
+++ b/dom/media/platforms/gonk/GonkVideoDecoderManager.cpp
@@ -478,17 +478,17 @@ void GonkVideoDecoderManager::ReleaseVid
 void
 GonkVideoDecoderManager::codecReserved()
 {
   GVDM_LOG("codecReserved");
   sp<AMessage> format = new AMessage;
   sp<Surface> surface;
   status_t rv = OK;
   // Fixed values
-  GVDM_LOG("Configure video mime type: %s, widht:%d, height:%d", mMimeType.get(), mVideoWidth, mVideoHeight);
+  GVDM_LOG("Configure video mime type: %s, width:%d, height:%d", mMimeType.get(), mVideoWidth, mVideoHeight);
   format->setString("mime", mMimeType.get());
   format->setInt32("width", mVideoWidth);
   format->setInt32("height", mVideoHeight);
   if (mNativeWindow != nullptr) {
     surface = new Surface(mNativeWindow->getBufferQueue());
   }
   mDecoder->configure(format, surface, nullptr, 0);
   mDecoder->Prepare();
--- a/dom/media/webaudio/blink/DynamicsCompressorKernel.cpp
+++ b/dom/media/webaudio/blink/DynamicsCompressorKernel.cpp
@@ -162,17 +162,17 @@ float DynamicsCompressorKernel::slopeAt(
 }
 
 float DynamicsCompressorKernel::kAtSlope(float desiredSlope)
 {
     float xDb = m_dbThreshold + m_dbKnee;
     float x = WebAudioUtils::ConvertDecibelsToLinear(xDb);
 
     // Approximate k given initial values.
-    float minK = 0.1;
+    float minK = 0.1f;
     float maxK = 10000;
     float k = 5;
 
     for (int i = 0; i < 15; ++i) {
         // A high value for k will more quickly asymptotically approach a slope of 0.
         float slope = slopeAt(x, k);
 
         if (slope < desiredSlope) {
--- a/dom/media/webaudio/blink/PeriodicWave.cpp
+++ b/dom/media/webaudio/blink/PeriodicWave.cpp
@@ -232,17 +232,17 @@ void PeriodicWave::createBandLimitedTabl
 
         // Apply normalization scale.
         AudioBufferInPlaceScale(data, normalizationScale, m_periodicWaveSize);
     }
 }
 
 void PeriodicWave::generateBasicWaveform(OscillatorType shape)
 {
-    const float piFloat = M_PI;
+    const float piFloat = float(M_PI);
     unsigned fftSize = periodicWaveSize();
     unsigned halfSize = fftSize / 2;
 
     AudioFloatArray real(halfSize);
     AudioFloatArray imag(halfSize);
     float* realP = real.Elements();
     float* imagP = imag.Elements();
 
--- a/dom/media/webaudio/blink/moz.build
+++ b/dom/media/webaudio/blink/moz.build
@@ -25,11 +25,8 @@ UNIFIED_SOURCES += [
 ]
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
 LOCAL_INCLUDES += [
     '/dom/media/webaudio',
 ]
-
-if not CONFIG['GNU_CXX']:
-    ALLOW_COMPILER_WARNINGS = True
--- a/dom/notification/NotificationStorage.js
+++ b/dom/notification/NotificationStorage.js
@@ -1,15 +1,15 @@
 /* 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/. */
 
 "use strict";
 
-const DEBUG = true;
+const DEBUG = false;
 function debug(s) { dump("-*- NotificationStorage.js: " + s + "\n"); }
 
 const Cc = Components.classes;
 const Ci = Components.interfaces;
 const Cu = Components.utils;
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 
--- a/dom/plugins/test/testplugin/moz.build
+++ b/dom/plugins/test/testplugin/moz.build
@@ -3,13 +3,10 @@
 # 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/.
 
 DIRS += ['secondplugin', 'javaplugin', 'thirdplugin', 'flashplugin']
 
 SharedLibrary('nptest')
 
-if CONFIG['_MSC_VER']:
-    ALLOW_COMPILER_WARNINGS = True
-
 relative_path = '.'
 include('testplugin.mozbuild')
--- a/dom/security/nsContentSecurityManager.cpp
+++ b/dom/security/nsContentSecurityManager.cpp
@@ -27,80 +27,76 @@ ValidateSecurityFlags(nsILoadInfo* aLoad
       securityMode != nsILoadInfo::SEC_REQUIRE_CORS_DATA_INHERITS) {
     MOZ_ASSERT(false, "can not use cors-with-credentials without cors");
     return NS_ERROR_FAILURE;
   }
   // all good, found the right security flags
   return NS_OK;
 }
 
-nsresult
-DoSOPChecks(nsIURI* aURI, nsILoadInfo* aLoadInfo)
+static bool SchemeIs(nsIURI* aURI, const char* aScheme)
 {
-  nsSecurityFlags securityMode = aLoadInfo->GetSecurityMode();
+  nsCOMPtr<nsIURI> baseURI = NS_GetInnermostURI(aURI);
+  NS_ENSURE_TRUE(baseURI, false);
 
-  // if none of the REQUIRE_SAME_ORIGIN flags are set, then SOP does not apply
-  if ((securityMode != nsILoadInfo::SEC_REQUIRE_SAME_ORIGIN_DATA_INHERITS) &&
-      (securityMode != nsILoadInfo::SEC_REQUIRE_SAME_ORIGIN_DATA_IS_BLOCKED)) {
-    return NS_OK;
-  }
-
-  nsIPrincipal* loadingPrincipal = aLoadInfo->LoadingPrincipal();
-  bool sameOriginDataInherits =
-    securityMode == nsILoadInfo::SEC_REQUIRE_SAME_ORIGIN_DATA_INHERITS;
-  return loadingPrincipal->CheckMayLoad(aURI,
-                                        true, // report to console
-                                        sameOriginDataInherits);
+  bool isScheme = false;
+  return NS_SUCCEEDED(baseURI->SchemeIs(aScheme, &isScheme)) && isScheme;
 }
 
 nsresult
 DoCheckLoadURIChecks(nsIURI* aURI, nsILoadInfo* aLoadInfo)
 {
   nsresult rv = NS_OK;
-  nsSecurityFlags securityMode = aLoadInfo->GetSecurityMode();
-  // Please note that checkLoadURIWithPrincipal should only be enforced for
-  // cross origin requests. If the flag SEC_REQUIRE_CORS_DATA_INHERITS is set
-  // within the loadInfo, then then CheckLoadURIWithPrincipal is performed
-  // within nsCorsListenerProxy
-  if ((securityMode != nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_INHERITS) &&
-      (securityMode != nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL)) {
-    return NS_OK;
+
+  nsCOMPtr<nsIPrincipal> loadingPrincipal = aLoadInfo->LoadingPrincipal();
+  uint32_t flags = nsIScriptSecurityManager::STANDARD;
+  if (aLoadInfo->GetAllowChrome()) {
+    flags |= nsIScriptSecurityManager::ALLOW_CHROME;
   }
 
-  nsCOMPtr<nsIPrincipal> loadingPrincipal = aLoadInfo->LoadingPrincipal();
-  // XXX: @arg nsIScriptSecurityManager::STANDARD
-  // lets use STANDARD for now and evaluate on a callsite basis, see also:
-  // http://mxr.mozilla.org/mozilla-central/source/caps/nsIScriptSecurityManager.idl#62
   rv = nsContentUtils::GetSecurityManager()->
     CheckLoadURIWithPrincipal(loadingPrincipal,
                               aURI,
-                              nsIScriptSecurityManager::STANDARD);
+                              flags);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // If the loadingPrincipal and the triggeringPrincipal are different, then make
   // sure the triggeringPrincipal is allowed to access that URI.
   nsCOMPtr<nsIPrincipal> triggeringPrincipal = aLoadInfo->TriggeringPrincipal();
   if (loadingPrincipal != triggeringPrincipal) {
     rv = nsContentUtils::GetSecurityManager()->
            CheckLoadURIWithPrincipal(triggeringPrincipal,
                                      aURI,
-                                     nsIScriptSecurityManager::STANDARD);
+                                     flags);
     NS_ENSURE_SUCCESS(rv, rv);
   }
   return NS_OK;
 }
 
 nsresult
+DoSOPChecks(nsIURI* aURI, nsILoadInfo* aLoadInfo)
+{
+  if (aLoadInfo->GetAllowChrome() && SchemeIs(aURI, "chrome")) {
+    // Enforce same-origin policy, except to chrome.
+    return DoCheckLoadURIChecks(aURI, aLoadInfo);
+  }
+
+  nsIPrincipal* loadingPrincipal = aLoadInfo->LoadingPrincipal();
+  bool sameOriginDataInherits =
+    aLoadInfo->GetSecurityMode() == nsILoadInfo::SEC_REQUIRE_SAME_ORIGIN_DATA_INHERITS;
+  return loadingPrincipal->CheckMayLoad(aURI,
+                                        true, // report to console
+                                        sameOriginDataInherits);
+}
+
+nsresult
 DoCORSChecks(nsIChannel* aChannel, nsILoadInfo* aLoadInfo,
              nsCOMPtr<nsIStreamListener>& aInAndOutListener)
 {
-  if (aLoadInfo->GetSecurityMode() != nsILoadInfo::SEC_REQUIRE_CORS_DATA_INHERITS) {
-    return NS_OK;
-  }
-
+  MOZ_ASSERT(aInAndOutListener, "can not perform CORS checks without a listener");
   nsIPrincipal* loadingPrincipal = aLoadInfo->LoadingPrincipal();
   nsRefPtr<nsCORSListenerProxy> corsListener =
     new nsCORSListenerProxy(aInAndOutListener,
                             loadingPrincipal,
                             aLoadInfo->GetRequireCorsWithCredentials());
   // XXX: @arg: DataURIHandling::Allow
   // lets use  DataURIHandling::Allow for now and then decide on callsite basis. see also:
   // http://mxr.mozilla.org/mozilla-central/source/dom/security/nsCORSListenerProxy.h#33
@@ -139,19 +135,24 @@ DoContentSecurityChecks(nsIURI* aURI, ns
       mimeTypeGuess = NS_LITERAL_CSTRING("text/html");
       requestingContext = aLoadInfo->LoadingNode();
       MOZ_ASSERT(!requestingContext ||
                  requestingContext->NodeType() == nsIDOMNode::DOCUMENT_NODE,
                  "type_subdocument requires requestingContext of type Document");
       break;
     }
 
-    case nsIContentPolicy::TYPE_REFRESH:
+    case nsIContentPolicy::TYPE_REFRESH: {
+      MOZ_ASSERT(false, "contentPolicyType not supported yet");
+      break;
+    }
+
     case nsIContentPolicy::TYPE_XBL: {
-      MOZ_ASSERT(false, "contentPolicyType not supported yet");
+      mimeTypeGuess = EmptyCString();
+      requestingContext = aLoadInfo->LoadingNode();
       break;
     }
 
     case nsIContentPolicy::TYPE_PING: {
       mimeTypeGuess = EmptyCString();
       requestingContext = aLoadInfo->LoadingNode();
       break;
     }
@@ -302,32 +303,45 @@ nsContentSecurityManager::doContentSecur
   // we just set the flag again.
   rv = loadInfo->SetEnforceSecurity(true);
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsCOMPtr<nsIURI> finalChannelURI;
   rv = NS_GetFinalChannelURI(aChannel, getter_AddRefs(finalChannelURI));
   NS_ENSURE_SUCCESS(rv, rv);
 
-  // Perform Same Origin Policy check
-  rv = DoSOPChecks(finalChannelURI, loadInfo);
-  NS_ENSURE_SUCCESS(rv, rv);
+  nsSecurityFlags securityMode = loadInfo->GetSecurityMode();
+
+  // if none of the REQUIRE_SAME_ORIGIN flags are set, then SOP does not apply
+  if ((securityMode == nsILoadInfo::SEC_REQUIRE_SAME_ORIGIN_DATA_INHERITS) ||
+      (securityMode == nsILoadInfo::SEC_REQUIRE_SAME_ORIGIN_DATA_IS_BLOCKED)) {
+    rv = DoSOPChecks(finalChannelURI, loadInfo);
+    NS_ENSURE_SUCCESS(rv, rv);
+  }
 
   // if dealing with a redirected channel then we only enforce SOP
   // and can return at this point.
   if (initialSecurityCheckDone) {
     return NS_OK;
   }
 
-  rv = DoCheckLoadURIChecks(finalChannelURI, loadInfo);
-  NS_ENSURE_SUCCESS(rv, rv);
+  if ((securityMode == nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_INHERITS) ||
+      (securityMode == nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL)) {
+    // Please note that DoCheckLoadURIChecks should only be enforced for
+    // cross origin requests. If the flag SEC_REQUIRE_CORS_DATA_INHERITS is set
+    // within the loadInfo, then then CheckLoadURIWithPrincipal is performed
+    // within nsCorsListenerProxy
+    rv = DoCheckLoadURIChecks(finalChannelURI, loadInfo);
+    NS_ENSURE_SUCCESS(rv, rv);
+  }
 
-  // Check if CORS needs to be set up
-  rv = DoCORSChecks(aChannel, loadInfo, aInAndOutListener);
-  NS_ENSURE_SUCCESS(rv, rv);
+  if (securityMode == nsILoadInfo::SEC_REQUIRE_CORS_DATA_INHERITS) {
+    rv = DoCORSChecks(aChannel, loadInfo, aInAndOutListener);
+    NS_ENSURE_SUCCESS(rv, rv);
+  }
 
   // Perform all ContentPolicy checks (MixedContent, CSP, ...)
   rv = DoContentSecurityChecks(finalChannelURI, loadInfo);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // all security checks passed - lets allow the load
   return NS_OK;
 }
--- a/dom/settings/SettingsService.js
+++ b/dom/settings/SettingsService.js
@@ -46,37 +46,35 @@ const nsISettingsServiceLock         = C
 function makeSettingsServiceRequest(aCallback, aName, aValue) {
   return {
     callback: aCallback,
     name: aName,
     value: aValue
   };
 };
 
+const kLockListeners = ["Settings:Get:OK", "Settings:Get:KO",
+                        "Settings:Clear:OK", "Settings:Clear:KO",
+                        "Settings:Set:OK", "Settings:Set:KO",
+                        "Settings:Finalize:OK", "Settings:Finalize:KO"];
+
 function SettingsServiceLock(aSettingsService, aTransactionCallback) {
   if (VERBOSE) debug("settingsServiceLock constr!");
   this._open = true;
   this._settingsService = aSettingsService;
   this._id = uuidgen.generateUUID().toString();
   this._transactionCallback = aTransactionCallback;
   this._requests = {};
   let closeHelper = function() {
     if (VERBOSE) debug("closing lock " + this._id);
     this._open = false;
     this.runOrFinalizeQueries();
   }.bind(this);
 
-  let msgs =   ["Settings:Get:OK", "Settings:Get:KO",
-                "Settings:Clear:OK", "Settings:Clear:KO",
-                "Settings:Set:OK", "Settings:Set:KO",
-                "Settings:Finalize:OK", "Settings:Finalize:KO"];
-
-  for (let msg in msgs) {
-    cpmm.addMessageListener(msgs[msg], this);
-  }
+  this.addListeners();
 
   let createLockPayload = {
     lockID: this._id,
     isServiceLock: true,
     windowID: undefined,
     lockStack: (new Error).stack
   };
 
@@ -84,16 +82,28 @@ function SettingsServiceLock(aSettingsSe
   Services.tm.currentThread.dispatch(closeHelper, Ci.nsIThread.DISPATCH_NORMAL);
 }
 
 SettingsServiceLock.prototype = {
   get closed() {
     return !this._open;
   },
 
+  addListeners: function() {
+    for (let msg of kLockListeners) {
+      cpmm.addMessageListener(msg, this);
+    }
+  },
+
+  removeListeners: function() {
+    for (let msg of kLockListeners) {
+      cpmm.removeMessageListener(msg, this);
+    }
+  },
+
   returnMessage: function(aMessage, aData) {
     SettingsRequestManager.receiveMessage({
       name: aMessage,
       data: aData,
       target: undefined,
       principal: Services.scriptSecurityManager.getSystemPrincipal()
     });
   },
@@ -301,16 +311,17 @@ SettingsService.prototype = {
     this._createdLocks++;
   },
 
   unregisterLock: function(aLockID) {
     let lock_index = this._locks.indexOf(aLockID);
     if (lock_index != -1) {
       if (VERBOSE) debug("Unregistering lock " + aLockID);
       this._locks.splice(lock_index, 1);
+      this._serviceLocks[aLockID].removeListeners();
       this._serviceLocks[aLockID] = null;
       delete this._serviceLocks[aLockID];
       this._unregisteredLocks++;
     }
   },
 
   collectReports: function(aCallback, aData, aAnonymize) {
     aCallback.callback("",
--- a/dom/webidl/InputMethod.webidl
+++ b/dom/webidl/InputMethod.webidl
@@ -114,48 +114,62 @@ interface MozInputMethod : EventTarget {
   void setSelectedOptions(sequence<long> indexes);
 };
 
 /**
  * InputMethodManager contains a few of the global methods for the input app.
  */
 [JSImplementation="@mozilla.org/b2g-imm;1",
  Pref="dom.mozInputMethod.enabled",
- CheckAnyPermissions="input"]
+ CheckAnyPermissions="input input-manage"]
 interface MozInputMethodManager {
   /**
    * Ask the OS to show a list of available inputs for users to switch from.
    * OS should sliently ignore this request if the app is currently not the
    * active one.
    */
+  [CheckAllPermissions="input"]
   void showAll();
 
   /**
    * Ask the OS to switch away from the current active input app.
    * OS should sliently ignore this request if the app is currently not the
    * active one.
    */
+  [CheckAllPermissions="input"]
   void next();
 
   /**
-   * If this method returns true, it is recommented that the input app provides
+   * If this method returns true, it is recommended that the input app provides
    * a shortcut that would invoke the next() method above, for easy switching
    * between inputs -- i.e. show a "global" button on screen if the input app
    * implements an on-screen virtual keyboard.
    *
    * The returning value is depend on the inputType of the current input context.
    */
+  [CheckAllPermissions="input"]
   boolean supportsSwitching();
 
   /**
    * Ask the OS to remove the input focus, will cause the lost of input context.
    * OS should sliently ignore this request if the app is currently not the
    * active one.
    */
+  [CheckAllPermissions="input"]
   void hide();
+
+  /**
+   * Update Gecko with information on the input types which supportsSwitching()
+   * should return ture.
+   *
+   * @param types Array of input types in which supportsSwitching() should
+   *              return true.
+   */
+  [CheckAllPermissions="input-manage"]
+  void setSupportsSwitchingTypes(sequence<MozInputMethodInputContextInputTypes> types);
 };
 
 /**
  * The input context, which consists of attributes and information of current
  * input field. It also hosts the methods available to the keyboard app to
  * mutate the input field represented. An "input context" gets void when the
  * app is no longer allowed to interact with the text field,
  * e.g., the text field does no longer exist, the app is being switched to
--- a/dom/xbl/nsXBLService.cpp
+++ b/dom/xbl/nsXBLService.cpp
@@ -372,33 +372,29 @@ nsXBLStreamListener::HandleEvent(nsIDOME
 
   target->RemoveEventListener(NS_LITERAL_STRING("load"), this, false);
 
   return rv;
 }
 
 // Implementation /////////////////////////////////////////////////////////////////
 
-// Static member variable initialization
-bool nsXBLService::gAllowDataURIs = false;
-
 // Implement our nsISupports methods
 NS_IMPL_ISUPPORTS(nsXBLService, nsISupportsWeakReference)
 
 void
 nsXBLService::Init()
 {
   gInstance = new nsXBLService();
   NS_ADDREF(gInstance);
 }
 
 // Constructors/Destructors
 nsXBLService::nsXBLService(void)
 {
-  Preferences::AddBoolVarCache(&gAllowDataURIs, "layout.debug.enable_data_xbl");
 }
 
 nsXBLService::~nsXBLService(void)
 {
 }
 
 // static
 bool
@@ -842,91 +838,38 @@ nsXBLService::GetBinding(nsIContent* aBo
     }
 
     NS_ADDREF(*aResult = newBinding);
   }
 
   return NS_OK;
 }
 
-static bool SchemeIs(nsIURI* aURI, const char* aScheme)
-{
-  nsCOMPtr<nsIURI> baseURI = NS_GetInnermostURI(aURI);
-  NS_ENSURE_TRUE(baseURI, false);
-
-  bool isScheme = false;
-  return NS_SUCCEEDED(baseURI->SchemeIs(aScheme, &isScheme)) && isScheme;
-}
-
-static bool
-IsSystemOrChromeURLPrincipal(nsIPrincipal* aPrincipal)
-{
-  if (nsContentUtils::IsSystemPrincipal(aPrincipal)) {
-    return true;
-  }
-
-  nsCOMPtr<nsIURI> uri;
-  aPrincipal->GetURI(getter_AddRefs(uri));
-  NS_ENSURE_TRUE(uri, false);
-
-  bool isChrome = false;
-  return NS_SUCCEEDED(uri->SchemeIs("chrome", &isChrome)) && isChrome;
-}
-
 nsresult
 nsXBLService::LoadBindingDocumentInfo(nsIContent* aBoundElement,
                                       nsIDocument* aBoundDocument,
                                       nsIURI* aBindingURI,
                                       nsIPrincipal* aOriginPrincipal,
                                       bool aForceSyncLoad,
                                       nsXBLDocumentInfo** aResult)
 {
   NS_PRECONDITION(aBindingURI, "Must have a binding URI");
   NS_PRECONDITION(!aOriginPrincipal || aBoundDocument,
                   "If we're doing a security check, we better have a document!");
 
-  nsresult rv;
-  if (aOriginPrincipal) {
-    // Security check - Enforce same-origin policy, except to chrome.
-    // We have to be careful to not pass aContent as the context here.
-    // Otherwise, if there is a JS-implemented content policy, we will attempt
-    // to wrap the content node, which will try to load XBL bindings for it, if
-    // any. Since we're not done loading this binding yet, that will reenter
-    // this method and we'll end up creating a binding and then immediately
-    // clobbering it in our table.  That makes things very confused, leading to
-    // misbehavior and crashes.
-    rv = nsContentUtils::
-      CheckSecurityBeforeLoad(aBindingURI, aOriginPrincipal,
-                              nsIScriptSecurityManager::ALLOW_CHROME,
-                              gAllowDataURIs,
-                              nsIContentPolicy::TYPE_XBL,
-                              aBoundDocument);
-    NS_ENSURE_SUCCESS(rv, NS_ERROR_XBL_BLOCKED);
-
-    if (!IsSystemOrChromeURLPrincipal(aOriginPrincipal)) {
-      // Also make sure that we're same-origin with the bound document
-      // except if the stylesheet has the system principal.
-      if (!(gAllowDataURIs && SchemeIs(aBindingURI, "data")) &&
-          !SchemeIs(aBindingURI, "chrome")) {
-        rv = aBoundDocument->NodePrincipal()->CheckMayLoad(aBindingURI,
-                                                           true, false);
-        NS_ENSURE_SUCCESS(rv, NS_ERROR_XBL_BLOCKED);
-      }
-
-      // Finally check if this document is allowed to use XBL at all.
-      NS_ENSURE_TRUE(aBoundDocument->AllowXULXBL(),
-                     NS_ERROR_XBL_BLOCKED);
-    }
+  *aResult = nullptr;
+  if (aOriginPrincipal && !nsContentUtils::IsSystemPrincipal(aOriginPrincipal)) {
+    NS_ENSURE_TRUE(!aBoundDocument || aBoundDocument->AllowXULXBL(),
+                   NS_ERROR_XBL_BLOCKED);
   }
 
-  *aResult = nullptr;
   nsRefPtr<nsXBLDocumentInfo> info;
 
   nsCOMPtr<nsIURI> documentURI;
-  rv = aBindingURI->CloneIgnoringRef(getter_AddRefs(documentURI));
+  nsresult rv = aBindingURI->CloneIgnoringRef(getter_AddRefs(documentURI));
   NS_ENSURE_SUCCESS(rv, rv);
 
 #ifdef MOZ_XUL
   // We've got a file.  Check our XBL document cache.
   nsXULPrototypeCache* cache = nsXULPrototypeCache::GetInstance();
   bool useXULCache = cache && cache->IsEnabled();
 
   if (useXULCache) {
@@ -1000,19 +943,20 @@ nsXBLService::LoadBindingDocumentInfo(ns
       // document.
 
       // Always load chrome synchronously
       bool chrome;
       if (NS_SUCCEEDED(documentURI->SchemeIs("chrome", &chrome)) && chrome)
         aForceSyncLoad = true;
 
       nsCOMPtr<nsIDocument> document;
-      FetchBindingDocument(aBoundElement, aBoundDocument, documentURI,
-                           aBindingURI, aOriginPrincipal, aForceSyncLoad,
-                           getter_AddRefs(document));
+      rv = FetchBindingDocument(aBoundElement, aBoundDocument, documentURI,
+                                aBindingURI, aOriginPrincipal, aForceSyncLoad,
+                                getter_AddRefs(document));
+      NS_ENSURE_SUCCESS(rv, rv);
 
       if (document) {
         nsBindingManager *xblDocBindingManager = document->BindingManager();
         info = xblDocBindingManager->GetXBLDocumentInfo(documentURI);
         if (!info) {
           NS_ERROR("An XBL file is malformed.  Did you forget the XBL namespace on the bindings tag?");
           return NS_ERROR_FAILURE;
         }
@@ -1076,40 +1020,37 @@ nsXBLService::FetchBindingDocument(nsICo
   // set to null (to bypass security checks) when calling LoadBindingDocumentInfo() which calls
   // FetchBindingDocument().  LoadInfo will end up with no principal or node in those cases,
   // so we use systemPrincipal.  This achieves the same result of bypassing security checks,
   // but it gives the wrong information to potential future consumers of loadInfo.
   nsCOMPtr<nsIChannel> channel;
 
   if (aOriginPrincipal) {
     // if there is an originPrincipal we should also have aBoundDocument
-    NS_ASSERTION(aBoundDocument, "can not create a channel without aBoundDocument");
+    MOZ_ASSERT(aBoundDocument, "can not create a channel without aBoundDocument");
+
     rv = NS_NewChannelWithTriggeringPrincipal(getter_AddRefs(channel),
                                               aDocumentURI,
                                               aBoundDocument,
                                               aOriginPrincipal,
-                                              nsILoadInfo::SEC_NORMAL,
-                                              nsIContentPolicy::TYPE_OTHER,
+                                              nsILoadInfo::SEC_REQUIRE_SAME_ORIGIN_DATA_INHERITS |
+                                              nsILoadInfo::SEC_ALLOW_CHROME,
+                                              nsIContentPolicy::TYPE_XBL,
                                               loadGroup);
   }
   else {
     rv = NS_NewChannel(getter_AddRefs(channel),
                        aDocumentURI,
                        nsContentUtils::GetSystemPrincipal(),
-                       nsILoadInfo::SEC_NORMAL,
-                       nsIContentPolicy::TYPE_OTHER,
+                       nsILoadInfo::SEC_REQUIRE_SAME_ORIGIN_DATA_INHERITS,
+                       nsIContentPolicy::TYPE_XBL,
                        loadGroup);
   }
-
   NS_ENSURE_SUCCESS(rv, rv);
 
-  nsCOMPtr<nsIInterfaceRequestor> sameOriginChecker = nsContentUtils::SameOriginChecker();
-
-  channel->SetNotificationCallbacks(sameOriginChecker);
-
   if (!aForceSyncLoad) {
     // We can be asynchronous
     nsXBLStreamListener* xblListener =
       new nsXBLStreamListener(aBoundDocument, xblSink, doc);
 
     // Add ourselves to the list of loading docs.
     nsBindingManager *bindingManager;
     if (aBoundDocument)
@@ -1121,17 +1062,17 @@ nsXBLService::FetchBindingDocument(nsICo
       bindingManager->PutLoadingDocListener(aDocumentURI, xblListener);
 
     // Add our request.
     nsXBLBindingRequest* req = new nsXBLBindingRequest(aBindingURI,
                                                        aBoundElement);
     xblListener->AddRequest(req);
 
     // Now kick off the async read.
-    rv = channel->AsyncOpen(xblListener, nullptr);
+    rv = channel->AsyncOpen2(xblListener);
     if (NS_FAILED(rv)) {
       // Well, we won't be getting a load.  Make sure to clean up our stuff!
       if (bindingManager) {
         bindingManager->RemoveLoadingDocListener(aDocumentURI);
       }
     }
     return NS_OK;
   }
@@ -1143,17 +1084,17 @@ nsXBLService::FetchBindingDocument(nsICo
                               nullptr,
                               getter_AddRefs(listener),
                               true,
                               xblSink);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Now do a blocking synchronous parse of the file.
   nsCOMPtr<nsIInputStream> in;
-  rv = channel->Open(getter_AddRefs(in));
+  rv = channel->Open2(getter_AddRefs(in));
   NS_ENSURE_SUCCESS(rv, rv);
 
   rv = nsSyncLoadService::PushSyncStreamToListener(in, listener, channel);
   NS_ENSURE_SUCCESS(rv, rv);
 
   doc.swap(*aResult);
 
   return NS_OK;
--- a/dom/xbl/test/file_bug379959_cross.html
+++ b/dom/xbl/test/file_bug379959_cross.html
@@ -11,15 +11,22 @@
   -moz-binding: url(http://example.com/tests/dom/xbl/test/file_bug379959_xbl.xml#xbltest);
 }
 </style>
 <body>
 <div id="div1"></div>
 <div id="div2"></div>
 <script>
 onload = function() {
-  nodes = SpecialPowers.wrap(document).getAnonymousNodes(document.getElementById('div1'));
-  parent.postMessage(nodes ? nodes.length : 0, "http://mochi.test:8888");
-  nodes = SpecialPowers.wrap(document).getAnonymousNodes(document.getElementById('div2'));
-  parent.postMessage(nodes ? nodes.length : 0, "http://mochi.test:8888");
+  // same origin should be allowed
+  var nodes1 = SpecialPowers.wrap(document).getAnonymousNodes(document.getElementById('div1'));
+  parent.postMessage({test: "sameOriginIsAllowed",
+                      result: nodes1 ? nodes1.length : 0,
+                      senderURL: "http://mochi.test:8888"}, "*");
+
+  // cross origin should be blocked
+  var nodes2 = SpecialPowers.wrap(document).getAnonymousNodes(document.getElementById('div2'));
+  parent.postMessage({test: "crossOriginIsBlocked",
+                      result: nodes2 ? nodes2.length : 0,
+                      senderURL: "http://mochi.test:8888"}, "*");
 }
 </script>
 </html>
--- a/dom/xbl/test/file_bug379959_data.html
+++ b/dom/xbl/test/file_bug379959_data.html
@@ -6,13 +6,15 @@
   color: green;
   -moz-binding: url(data:text/xml;charset=utf-8,%3C%3Fxml%20version%3D%221.0%22%3F%3E%0A%3Cbindings%20id%3D%22xbltestBindings%22%20xmlns%3D%22http%3A//www.mozilla.org/xbl%22%3E%0A%20%20%3Cbinding%20id%3D%22xbltest%22%3E%3Ccontent%3EPASS%3C/content%3E%3C/binding%3E%0A%3C/bindings%3E%0A);
 }
 </style>
 <body>
 <div id="d"></div>
 <script>
 onload = function() {
-  nodes = SpecialPowers.wrap(document).getAnonymousNodes(document.getElementById('d'));
-  parent.postMessage(nodes ? nodes.length : 0, "http://mochi.test:8888");
+  var nodes = SpecialPowers.wrap(document).getAnonymousNodes(document.getElementById('d'));
+  parent.postMessage({test: "dataIsAllowed",
+                      result: nodes ? nodes.length : 0,
+                      senderURL: "http://mochi.test:8888"}, "*");
 }
 </script>
 </html>
--- a/dom/xbl/test/test_bug379959.html
+++ b/dom/xbl/test/test_bug379959.html
@@ -12,86 +12,58 @@ https://bugzilla.mozilla.org/show_bug.cg
   <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=379959">Mozilla Bug 379959</a>
   <p id="display">
     Note: In order to re-run this test correctly you need to shift-reload
     rather than simply reload. If you just reload we will restore the
     previous url in the iframe which will result in an extra unexpected
     message.
   </p>
   <div id="content" style="display: none"></div>
-  <iframe id="f"></iframe>
+  <iframe id="dataFrame"></iframe>
+  <iframe id="originFrame"></iframe>
 
   <pre id="test">
     <script class="testbody" type="application/javascript;version=1.7">
+
 SimpleTest.waitForExplicitFinish();
 
-var messages = 0;
+var seenData = false;
+var seenSameOrigin = false;
+var seenCrossOrign = false;
 
 function receiveMessage(e) {
   is(e.origin, "http://mochi.test:8888", "wrong sender!");
-  messages++;
 
-  switch (messages) {
-    case 1:
-      receiveMessage1(e.data);
-      break;
-    case 2:
-      receiveMessage2(e.data);
-      break;
-    case 3:
-      receiveMessage3(e.data);
-      break;
-    case 4:
-      receiveMessage4(e.data);
-      break;
-    default:
-      ok(false, "should not be reached");
-      Simpletest.finish();
+  if (e.data.test === "dataIsAllowed") {
+    is(e.data.result, 1, "data-url load should have succeeded");
+    seenData = true;
+  }
+  else if (e.data.test === "sameOriginIsAllowed") {
+    is(e.data.result, 1, "same site load should have succeeded");
+    seenSameOrigin = true;
+  }
+  else if (e.data.test === "crossOriginIsBlocked") {
+    is(e.data.result, 0, "cross site load should have failed");
+    seenCrossOrign = true;
+  }
+  else {
+    ok (false, "unrecognized test");
+  }
+
+  if (seenData && seenSameOrigin && seenCrossOrign) {
+    window.removeEventListener("message", receiveMessage, false);
+    SimpleTest.finish();
   }
 }
 
 window.addEventListener("message", receiveMessage, false);
 
-var iframe = document.getElementById('f');
-
 function runTest() {
-  // Test with data-urls off
-  SpecialPowers.pushPrefEnv({"set": [["layout.debug.enable_data_xbl", false]]}, runTest1);
-}
-
-function runTest1() {
-  iframe.src = "file_bug379959_data.html";
-}
-
-function receiveMessage1(aData) {
-  is(aData, 0, "data-url load should have failed");
-  // Test with data-urls on
-  SpecialPowers.pushPrefEnv({"set": [["layout.debug.enable_data_xbl", true]]}, runTest2);
-}
-
-function runTest2() {
-  iframe.src = "file_bug379959_data.html";
-}
-
-function receiveMessage2(aData) {
-  is(aData, 1, "data-url load should have been successful");
-  // Try a cross-site load
-  iframe.src = "file_bug379959_cross.html";
-}
-
-function receiveMessage3(aData) {
-  is(aData, 1, "same site load should have succeeded");
-}
-
-function receiveMessage4(aData) {
-  is(aData, 0, "cross site load should have failed");
-
-  // Check that we got the right number of messages to make sure that
-  // the right message has aligned with the right test
-  is(messages, 4, "wrong number of messages");
-
-  SimpleTest.finish();
+  // make sure data: is allowed
+  document.getElementById('dataFrame').src = "file_bug379959_data.html";
+  // make sure same-origin is allowed but cross site is blocked
+  document.getElementById('originFrame').src = "file_bug379959_cross.html";
 }
 
     </script>
   </pre>
 </body>
 </html>
--- a/editor/composer/test/chrome.ini
+++ b/editor/composer/test/chrome.ini
@@ -1,10 +1,11 @@
 [DEFAULT]
 skip-if = buildapp == 'b2g' || os == 'android'
 
 [test_async_UpdateCurrentDictionary.html]
 [test_bug338427.html]
 [test_bug434998.xul]
 [test_bug678842.html]
+[test_abug697981.html]
 [test_bug717433.html]
 [test_bug1204147.html]
 [test_bug1200533.html]
--- a/editor/composer/test/de-DE/de_DE.dic
+++ b/editor/composer/test/de-DE/de_DE.dic
@@ -1,4 +1,6 @@
-3
-Mary
-Paul
-Peter
+5
+ein
+guter
+heute
+ist
+Tag
new file mode 100644
--- /dev/null
+++ b/editor/composer/test/test_abug697981.html
@@ -0,0 +1,126 @@
+<!DOCTYPE html>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=697981
+-->
+<head>
+  <title>Test for Bug 697981</title>
+  <script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=697981">Mozilla Bug 697981</a>
+<p id="display"></p>
+</div>
+
+<textarea id="de-DE" lang="de-DE" onfocus="deFocus()">German heute ist ein guter Tag</textarea>
+<textarea id="en-US" lang="en-US" onfocus="enFocus()">Nogoodword today is a nice day</textarea>
+
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+function getMisspelledWords(editor) {
+  return editor.selectionController.getSelection(Components.interfaces.nsISelectionController.SELECTION_SPELLCHECK).toString();
+}
+
+var elem_de;
+var editor_de;
+var de_DE;
+var hunspell;
+
+/** Test for Bug 697981 **/
+/*
+ * Note the hack: This test fails of there are content preferences left behind from previous tests.
+ * That's why this test resides in a file "test_abug697981.html" so it runs first.
+ * We will fix this later.
+ */
+SimpleTest.waitForExplicitFinish();
+SimpleTest.waitForFocus(function() {
+  Components.utils.import("resource://gre/modules/AsyncSpellCheckTestHelper.jsm");
+
+  var dir = Components.classes["@mozilla.org/file/directory_service;1"]
+                      .getService(Components.interfaces.nsIProperties)
+                      .get("CurWorkD", Components.interfaces.nsIFile);
+  dir.append("tests");
+  dir.append("editor");
+  dir.append("composer");
+  dir.append("test");
+
+  hunspell = Components.classes["@mozilla.org/spellchecker/engine;1"]
+                       .getService(Components.interfaces.mozISpellCheckingEngine);
+
+  // Install de-DE dictionary.
+  de_DE = dir.clone();
+  de_DE.append("de-DE");
+  is(de_DE.exists(), true, "true expected (de_DE directory should exist)");
+  hunspell.addDirectory(de_DE);
+
+  document.getElementById('de-DE').focus();
+});
+
+function deFocus() {
+  elem_de = document.getElementById('de-DE');
+  editor_de = elem_de.QueryInterface(Components.interfaces.nsIDOMNSEditableElement).editor;
+  editor_de.setSpellcheckUserOverride(true);
+  var inlineSpellChecker = editor_de.getInlineSpellChecker(true);
+
+  onSpellCheck(elem_de, function () {
+    var spellchecker = inlineSpellChecker.spellChecker;
+    try {
+      var currentDictonary = spellchecker.GetCurrentDictionary();
+    } catch(e) {}
+
+    // Check that the German dictionary is loaded and that the spell check has worked.
+    is(currentDictonary, "de-DE", "expected de-DE");
+    is(getMisspelledWords(editor_de), "German", "one misspelled word expected: German");
+
+    // Now focus the other textarea, which requires English spelling.
+    document.getElementById('en-US').focus();
+  });
+}
+
+function enFocus() {
+  var elem_en = document.getElementById('en-US');
+  var editor_en = elem_en.QueryInterface(Components.interfaces.nsIDOMNSEditableElement).editor;
+  editor_en.setSpellcheckUserOverride(true);
+  var inlineSpellChecker = editor_en.getInlineSpellChecker(true);
+
+  onSpellCheck(elem_en, function () {
+    var spellchecker = inlineSpellChecker.spellChecker;
+    try {
+      currentDictonary = spellchecker.GetCurrentDictionary();
+    } catch(e) {}
+
+    // Check that the English dictionary is loaded and that the spell check has worked.
+    is(currentDictonary, "en-US", "expected en-US");
+    is(getMisspelledWords(editor_en), "Nogoodword", "one misspelled word expected: Nogoodword");
+
+    // So far all was boring. The important thing is whether the spell check result
+    // in the de-DE editor is still the same. After losing focus, no spell check
+    // updates should take place there.
+    is(getMisspelledWords(editor_de), "German", "one misspelled word expected: German");
+
+    // Remove the fake de_DE dictionary again.
+    hunspell.removeDirectory(de_DE);
+
+    // After removal, the de_DE editor should refresh the spelling with en-US.
+    onSpellCheck(elem_de, function () {
+      spellchecker = inlineSpellChecker.spellChecker;
+      try {
+        currentDictonary = spellchecker.GetCurrentDictionary();
+      } catch(e) {}
+
+      // Check that the default English dictionary is loaded and that the spell check has worked.
+      is(currentDictonary, "en-US", "expected en-US");
+      is(getMisspelledWords(editor_de), "heute" + "ist" + "ein" + "guter",
+         "some misspelled words expected: heute ist ein guter");
+
+      SimpleTest.finish();
+    });
+  });
+}
+
+</script>
+</pre>
+</body>
+</html>
--- a/editor/libeditor/nsEditor.cpp
+++ b/editor/libeditor/nsEditor.cpp
@@ -143,16 +143,17 @@ nsEditor::nsEditor()
 ,  mDocDirtyState(-1)
 ,  mSpellcheckCheckboxState(eTriUnset)
 ,  mShouldTxnSetSelection(true)
 ,  mDidPreDestroy(false)
 ,  mDidPostCreate(false)
 ,  mDispatchInputEvent(true)
 ,  mIsInEditAction(false)
 ,  mHidingCaret(false)
+,  mObservingDictionaryUpdates(false)
 {
 }
 
 nsEditor::~nsEditor()
 {
   NS_ASSERTION(!mDocWeak || mDidPreDestroy, "Why PreDestroy hasn't been called?");
 
   if (mComposition) {
@@ -302,17 +303,17 @@ nsEditor::PostCreate()
 
     // update the UI with our state
     NotifyDocumentListeners(eDocumentCreated);
     NotifyDocumentListeners(eDocumentStateChanged);
 
     nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
     if (obs) {
       obs->AddObserver(this,
-                       SPELLCHECK_DICTIONARY_UPDATE_NOTIFICATION,
+                       SPELLCHECK_DICTIONARY_REMOVE_NOTIFICATION,
                        false);
     }
   }
 
   // update nsTextStateManager and caret if we have focus
   nsCOMPtr<nsIContent> focusedContent = GetFocusedContent();
   if (focusedContent) {
     nsCOMPtr<nsIDOMEventTarget> target = do_QueryInterface(focusedContent);
@@ -446,16 +447,18 @@ nsEditor::PreDestroy(bool aDestroyingFra
     return NS_OK;
 
   IMEStateManager::OnEditorDestroying(this);
 
   nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
   if (obs) {
     obs->RemoveObserver(this,
                         SPELLCHECK_DICTIONARY_UPDATE_NOTIFICATION);
+    obs->RemoveObserver(this,
+                        SPELLCHECK_DICTIONARY_REMOVE_NOTIFICATION);
   }
 
   // Let spellchecker clean up its observers etc. It is important not to
   // actually free the spellchecker here, since the spellchecker could have
   // caused flush notifications, which could have gotten here if a textbox
   // is being removed. Setting the spellchecker to nullptr could free the
   // object that is still in use! It will be freed when the editor is
   // destroyed.
@@ -1310,17 +1313,19 @@ NS_IMETHODIMP nsEditor::GetInlineSpellCh
 
   return NS_OK;
 }
 
 NS_IMETHODIMP nsEditor::Observe(nsISupports* aSubj, const char *aTopic,
                                 const char16_t *aData)
 {
   NS_ASSERTION(!strcmp(aTopic,
-                       SPELLCHECK_DICTIONARY_UPDATE_NOTIFICATION),
+                       SPELLCHECK_DICTIONARY_UPDATE_NOTIFICATION) ||
+               !strcmp(aTopic,
+                       SPELLCHECK_DICTIONARY_REMOVE_NOTIFICATION),
                "Unexpected observer topic");
 
   // When mozInlineSpellChecker::CanEnableInlineSpellChecking changes
   SyncRealTimeSpell();
 
   // When nsIEditorSpellCheck::GetCurrentDictionary changes
   if (mInlineSpellChecker) {
     // if the current dictionary is no longer available, find another one
@@ -5197,16 +5202,39 @@ void
 nsEditor::OnFocus(nsIDOMEventTarget* aFocusEventTarget)
 {
   InitializeSelection(aFocusEventTarget);
   if (mInlineSpellChecker) {
     mInlineSpellChecker->UpdateCurrentDictionary();
   }
 }
 
+void
+nsEditor::StartWatchingDictionaryChanges()
+{
+  if (!mObservingDictionaryUpdates) {
+    nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
+    if (obs) {
+      obs->AddObserver(this, SPELLCHECK_DICTIONARY_UPDATE_NOTIFICATION, false);
+    }
+    mObservingDictionaryUpdates = true;
+  }
+}
+
+void
+nsEditor::StopWatchingDictionaryChanges()
+{
+  // Removing an observer that wasn't added doesn't cause any harm.
+  nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
+  if (obs) {
+    obs->RemoveObserver(this, SPELLCHECK_DICTIONARY_UPDATE_NOTIFICATION);
+  }
+  mObservingDictionaryUpdates = false;
+}
+
 NS_IMETHODIMP
 nsEditor::GetSuppressDispatchingInputEvent(bool *aSuppressed)
 {
   NS_ENSURE_ARG_POINTER(aSuppressed);
   *aSuppressed = !mDispatchInputEvent;
   return NS_OK;
 }
 
--- a/editor/libeditor/nsEditor.h
+++ b/editor/libeditor/nsEditor.h
@@ -244,16 +244,19 @@ public:
 
   // IME event handlers
   virtual nsresult BeginIMEComposition(mozilla::WidgetCompositionEvent* aEvent);
   virtual nsresult UpdateIMEComposition(nsIDOMEvent* aDOMTextEvent) = 0;
   void EndIMEComposition();
 
   void SwitchTextDirectionTo(uint32_t aDirection);
 
+  void StartWatchingDictionaryChanges();
+  void StopWatchingDictionaryChanges();
+
 protected:
   nsresult DetermineCurrentDirection();
   void FireInputEvent();
 
   /** Create a transaction for setting aAttribute to aValue on aElement.  Never
     * returns null.
     */
   already_AddRefed<mozilla::dom::ChangeAttributeTxn>
@@ -886,16 +889,17 @@ protected:
   uint8_t           mSpellcheckCheckboxState; // a Tristate value
 
   bool mShouldTxnSetSelection;  // turn off for conservative selection adjustment by txns
   bool mDidPreDestroy;    // whether PreDestroy has been called
   bool mDidPostCreate;    // whether PostCreate has been called
   bool mDispatchInputEvent;
   bool mIsInEditAction;   // true while the instance is handling an edit action
   bool mHidingCaret;      // whether caret is hidden forcibly.
+  bool mObservingDictionaryUpdates;  // whether the editor is observing dictionary changes.
 
   friend bool NSCanUnload(nsISupports* serviceMgr);
   friend class nsAutoTxnsConserveSelection;
   friend class nsAutoSelectionReset;
   friend class nsAutoRules;
   friend class nsRangeUpdater;
 };
 
--- a/editor/libeditor/nsEditorEventListener.cpp
+++ b/editor/libeditor/nsEditorEventListener.cpp
@@ -1109,32 +1109,36 @@ nsEditorEventListener::Focus(nsIDOMEvent
       nsCOMPtr<nsIDOMElement> element;
       fm->GetFocusedElement(getter_AddRefs(element));
       if (!SameCOMIdentity(element, target)) {
         return NS_OK;
       }
     }
   }
 
+  mEditor->StartWatchingDictionaryChanges();
+
   mEditor->OnFocus(target);
 
   nsCOMPtr<nsIPresShell> ps = GetPresShell();
   NS_ENSURE_TRUE(ps, NS_OK);
   nsCOMPtr<nsIContent> focusedContent = mEditor->GetFocusedContentForIME();
   IMEStateManager::OnFocusInEditor(ps->GetPresContext(), focusedContent,
                                    mEditor);
 
   return NS_OK;
 }
 
 nsresult
 nsEditorEventListener::Blur(nsIDOMEvent* aEvent)
 {
   NS_ENSURE_TRUE(aEvent, NS_OK);
 
+  mEditor->StopWatchingDictionaryChanges();
+
   // check if something else is focused. If another element is focused, then
   // we should not change the selection.
   nsIFocusManager* fm = nsFocusManager::GetFocusManager();
   NS_ENSURE_TRUE(fm, NS_OK);
 
   nsCOMPtr<nsIDOMElement> element;
   fm->GetFocusedElement(getter_AddRefs(element));
   if (!element) {
rename from extensions/spellcheck/hunspell/src/PRemoteSpellcheckEngine.ipdl
rename to extensions/spellcheck/hunspell/glue/PRemoteSpellcheckEngine.ipdl
rename from extensions/spellcheck/hunspell/src/RemoteSpellCheckEngineChild.cpp
rename to extensions/spellcheck/hunspell/glue/RemoteSpellCheckEngineChild.cpp
rename from extensions/spellcheck/hunspell/src/RemoteSpellCheckEngineChild.h
rename to extensions/spellcheck/hunspell/glue/RemoteSpellCheckEngineChild.h
rename from extensions/spellcheck/hunspell/src/RemoteSpellCheckEngineParent.cpp
rename to extensions/spellcheck/hunspell/glue/RemoteSpellCheckEngineParent.cpp
rename from extensions/spellcheck/hunspell/src/RemoteSpellCheckEngineParent.h
rename to extensions/spellcheck/hunspell/glue/RemoteSpellCheckEngineParent.h
rename from extensions/spellcheck/hunspell/src/hunspell_alloc_hooks.h
rename to extensions/spellcheck/hunspell/glue/hunspell_alloc_hooks.h
rename from extensions/spellcheck/hunspell/src/hunspell_fopen_hooks.h
rename to extensions/spellcheck/hunspell/glue/hunspell_fopen_hooks.h
copy from extensions/spellcheck/hunspell/src/moz.build
copy to extensions/spellcheck/hunspell/glue/moz.build
--- a/extensions/spellcheck/hunspell/src/moz.build
+++ b/extensions/spellcheck/hunspell/glue/moz.build
@@ -6,51 +6,30 @@
 
 SOURCES += [
     'mozHunspell.cpp',
     'mozHunspellDirProvider.cpp',
     'RemoteSpellCheckEngineChild.cpp',
     'RemoteSpellCheckEngineParent.cpp',
 ]
 
-if not CONFIG['MOZ_NATIVE_HUNSPELL']:
-    SOURCES += [
-        'affentry.cxx',
-        'affixmgr.cxx',
-        'csutil.cxx',
-        'dictmgr.cxx',
-        'filemgr.cxx',
-        'hashmgr.cxx',
-        'hunspell.cxx',
-        'hunzip.cxx',
-        'phonet.cxx',
-        'replist.cxx',
-        'suggestmgr.cxx',
-    ]
-    # This variable is referenced in configure.in.  Make sure to change that file
-    # too if you need to change this variable.
-    DEFINES['HUNSPELL_STATIC'] = True
-else:
-    CXXFLAGS += CONFIG['MOZ_HUNSPELL_CFLAGS']
+CXXFLAGS += CONFIG['MOZ_HUNSPELL_CFLAGS']
 
 FINAL_LIBRARY = 'xul'
 
 LOCAL_INCLUDES += [
+    '../src',
     '/dom/base',
     '/editor/libeditor',
     '/extensions/spellcheck/src',
 ]
 
-# XXX: This directory is a mix of Mozilla code and third-party code. We should
-# put the Mozilla code in a separate directory and disallow compiler warnings
-# there (bug 1200065). Until then, allow warnings for all of the code.
-ALLOW_COMPILER_WARNINGS = True
-
 include('/ipc/chromium/chromium-config.mozbuild')
 
 IPDL_SOURCES = [
     'PRemoteSpellcheckEngine.ipdl',
 ]
 
 EXPORTS.mozilla += [
      'RemoteSpellCheckEngineChild.h',
      'RemoteSpellCheckEngineParent.h',
 ]
+
rename from extensions/spellcheck/hunspell/src/mozHunspell.cpp
rename to extensions/spellcheck/hunspell/glue/mozHunspell.cpp
--- a/extensions/spellcheck/hunspell/src/mozHunspell.cpp
+++ b/extensions/spellcheck/hunspell/glue/mozHunspell.cpp
@@ -599,10 +599,16 @@ NS_IMETHODIMP mozHunspell::AddDirectory(
   LoadDictionaryList(true);
   return NS_OK;
 }
 
 NS_IMETHODIMP mozHunspell::RemoveDirectory(nsIFile *aDir)
 {
   mDynamicDirectories.RemoveObject(aDir);
   LoadDictionaryList(true);
+  nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
+  if (obs) {
+    obs->NotifyObservers(nullptr,
+                         SPELLCHECK_DICTIONARY_REMOVE_NOTIFICATION,
+                         nullptr);
+  }
   return NS_OK;
 }
rename from extensions/spellcheck/hunspell/src/mozHunspell.h
rename to extensions/spellcheck/hunspell/glue/mozHunspell.h
rename from extensions/spellcheck/hunspell/src/mozHunspellAllocator.h
rename to extensions/spellcheck/hunspell/glue/mozHunspellAllocator.h
rename from extensions/spellcheck/hunspell/src/mozHunspellDirProvider.cpp
rename to extensions/spellcheck/hunspell/glue/mozHunspellDirProvider.cpp
rename from extensions/spellcheck/hunspell/src/mozHunspellDirProvider.h
rename to extensions/spellcheck/hunspell/glue/mozHunspellDirProvider.h
--- a/extensions/spellcheck/hunspell/moz.build
+++ b/extensions/spellcheck/hunspell/moz.build
@@ -1,10 +1,12 @@
 # -*- Mode: python; c-basic-offset: 4; 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/.
 
-DIRS += ['src']
+DIRS += ['glue']
+if not CONFIG['MOZ_NATIVE_HUNSPELL']:
+    DIRS += ['src']
 
 if CONFIG['ENABLE_TESTS']:
-    XPCSHELL_TESTS_MANIFESTS += ['tests/unit/xpcshell.ini']
+    XPCSHELL_TESTS_MANIFESTS += ['tests/unit/xpcshell.ini']    
--- a/extensions/spellcheck/hunspell/src/moz.build
+++ b/extensions/spellcheck/hunspell/src/moz.build
@@ -1,56 +1,34 @@
 # -*- Mode: python; c-basic-offset: 4; 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 += [
-    'mozHunspell.cpp',
-    'mozHunspellDirProvider.cpp',
-    'RemoteSpellCheckEngineChild.cpp',
-    'RemoteSpellCheckEngineParent.cpp',
+    'affentry.cxx',
+    'affixmgr.cxx',
+    'csutil.cxx',
+    'dictmgr.cxx',
+    'filemgr.cxx',
+    'hashmgr.cxx',
+    'hunspell.cxx',
+    'hunzip.cxx',
+    'phonet.cxx',
+    'replist.cxx',
+    'suggestmgr.cxx',
 ]
 
-if not CONFIG['MOZ_NATIVE_HUNSPELL']:
-    SOURCES += [
-        'affentry.cxx',
-        'affixmgr.cxx',
-        'csutil.cxx',
-        'dictmgr.cxx',
-        'filemgr.cxx',
-        'hashmgr.cxx',
-        'hunspell.cxx',
-        'hunzip.cxx',
-        'phonet.cxx',
-        'replist.cxx',
-        'suggestmgr.cxx',
-    ]
-    # This variable is referenced in configure.in.  Make sure to change that file
-    # too if you need to change this variable.
-    DEFINES['HUNSPELL_STATIC'] = True
-else:
-    CXXFLAGS += CONFIG['MOZ_HUNSPELL_CFLAGS']
+# This variable is referenced in configure.in.  Make sure to change that file
+# too if you need to change this variable.
+DEFINES['HUNSPELL_STATIC'] = True
 
 FINAL_LIBRARY = 'xul'
 
 LOCAL_INCLUDES += [
-    '/dom/base',
-    '/editor/libeditor',
-    '/extensions/spellcheck/src',
+    '../glue',
 ]
 
-# XXX: This directory is a mix of Mozilla code and third-party code. We should
-# put the Mozilla code in a separate directory and disallow compiler warnings
-# there (bug 1200065). Until then, allow warnings for all of the code.
 ALLOW_COMPILER_WARNINGS = True
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
-IPDL_SOURCES = [
-    'PRemoteSpellcheckEngine.ipdl',
-]
-
-EXPORTS.mozilla += [
-     'RemoteSpellCheckEngineChild.h',
-     'RemoteSpellCheckEngineParent.h',
-]
--- a/extensions/spellcheck/idl/mozISpellCheckingEngine.idl
+++ b/extensions/spellcheck/idl/mozISpellCheckingEngine.idl
@@ -99,9 +99,11 @@ interface mozISpellCheckingEngine : nsIS
 };
 
 %{C++
 #define DICTIONARY_SEARCH_DIRECTORY "DictD"
 #define DICTIONARY_SEARCH_DIRECTORY_LIST "DictDL"
 
 #define SPELLCHECK_DICTIONARY_UPDATE_NOTIFICATION \
   "spellcheck-dictionary-update"
+#define SPELLCHECK_DICTIONARY_REMOVE_NOTIFICATION \
+  "spellcheck-dictionary-remove"
 %}
--- a/extensions/spellcheck/src/moz.build
+++ b/extensions/spellcheck/src/moz.build
@@ -14,15 +14,16 @@ SOURCES += [
     'mozSpellChecker.cpp',
     'mozSpellCheckerFactory.cpp',
     'mozSpellI18NManager.cpp',
 ]
 
 FINAL_LIBRARY = 'xul'
 
 LOCAL_INCLUDES += [
+    '../hunspell/glue',
     '../hunspell/src',
     '/dom/base',
     '/editor/libeditor',
 ]
 EXPORTS.mozilla += [
      'mozSpellChecker.h',
 ]
--- a/gfx/layers/ipc/CompositorParent.cpp
+++ b/gfx/layers/ipc/CompositorParent.cpp
@@ -1631,17 +1631,16 @@ class CrossProcessCompositorParent final
                                            public ShadowLayersManager
 {
   friend class CompositorParent;
 
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING_WITH_MAIN_THREAD_DESTRUCTION(CrossProcessCompositorParent)
 public:
   explicit CrossProcessCompositorParent(Transport* aTransport)
     : mTransport(aTransport)
-    , mCompositorThreadHolder(sCompositorThreadHolder)
     , mNotifyAfterRemotePaint(false)
   {
     MOZ_ASSERT(NS_IsMainThread());
   }
 
   // IToplevelProtocol::CloneToplevel()
   virtual IToplevelProtocol*
   CloneToplevel(const InfallibleTArray<mozilla::ipc::ProtocolFdMapping>& aFds,
@@ -1721,16 +1720,18 @@ public:
                                       const nsTArray<ScrollableLayerGuid>& aTargets) override;
 
   virtual AsyncCompositionManager* GetCompositionManager(LayerTransactionParent* aParent) override;
 
   void DidComposite(uint64_t aId,
                     TimeStamp& aCompositeStart,
                     TimeStamp& aCompositeEnd);
 
+protected:
+  void OnChannelConnected(int32_t pid) override { mCompositorThreadHolder = sCompositorThreadHolder; }
 private:
   // Private destructor, to discourage deletion outside of Release():
   virtual ~CrossProcessCompositorParent();
 
   void DeferredDestroy();
 
   // There can be many CPCPs, and IPDL-generated code doesn't hold a
   // reference to top-level actors.  So we hold a reference to
--- a/gfx/layers/ipc/ImageBridgeParent.cpp
+++ b/gfx/layers/ipc/ImageBridgeParent.cpp
@@ -53,17 +53,16 @@ MessageLoop* ImageBridgeParent::sMainLoo
 CompositorThreadHolder* GetCompositorThreadHolder();
 
 ImageBridgeParent::ImageBridgeParent(MessageLoop* aLoop,
                                      Transport* aTransport,
                                      ProcessId aChildProcessId)
   : mMessageLoop(aLoop)
   , mTransport(aTransport)
   , mSetChildThreadPriority(false)
-  , mCompositorThreadHolder(GetCompositorThreadHolder())
 {
   MOZ_ASSERT(NS_IsMainThread());
   sMainLoop = MessageLoop::current();
 
   // top-level actors must be destroyed on the main thread.
   SetMessageLoopToPostDestructionTo(sMainLoop);
 
   // creates the map only if it has not been created already, so it is safe
@@ -380,16 +379,22 @@ ImageBridgeParent::CloneToplevel(const I
       bridge->CloneManagees(this, aCtx);
       bridge->IToplevelProtocol::SetTransport(transport);
       return bridge;
     }
   }
   return nullptr;
 }
 
+void
+ImageBridgeParent::OnChannelConnected(int32_t aPid)
+{
+  mCompositorThreadHolder = GetCompositorThreadHolder();
+}
+
 bool ImageBridgeParent::IsSameProcess() const
 {
   return OtherPid() == base::GetCurrentProcId();
 }
 
 void
 ImageBridgeParent::ReplyRemoveTexture(const OpReplyRemoveTexture& aReply)
 {
--- a/gfx/layers/ipc/ImageBridgeParent.h
+++ b/gfx/layers/ipc/ImageBridgeParent.h
@@ -146,16 +146,19 @@ public:
   static bool NotifyImageComposites(nsTArray<ImageCompositeNotification>& aNotifications);
 
   // Overriden from IToplevelProtocol
   IToplevelProtocol*
   CloneToplevel(const InfallibleTArray<ProtocolFdMapping>& aFds,
                 base::ProcessHandle aPeerProcess,
                 mozilla::ipc::ProtocolCloneContext* aCtx) override;
 
+protected:
+  void OnChannelConnected(int32_t pid) override;
+
 private:
   void DeferredDestroy();
   MessageLoop* mMessageLoop;
   Transport* mTransport;
   // This keeps us alive until ActorDestroy(), at which point we do a
   // deferred destruction of ourselves.
   nsRefPtr<ImageBridgeParent> mSelfRef;
 
--- a/gfx/vr/moz.build
+++ b/gfx/vr/moz.build
@@ -32,15 +32,12 @@ SOURCES += [
 #CXXFLAGS += ["-Ic:/proj/ovr/OculusSDK-0.6.0-beta/LibOVR/Include"]
 #CFLAGS += ["-Ic:/proj/ovr/OculusSDK-0.6.0-beta/LibOVR/Include"]
 
 CXXFLAGS += CONFIG['MOZ_CAIRO_CFLAGS']
 CXXFLAGS += CONFIG['TK_CFLAGS']
 CFLAGS += CONFIG['MOZ_CAIRO_CFLAGS']
 CFLAGS += CONFIG['TK_CFLAGS']
 
-if CONFIG['_MSC_VER']:
-    ALLOW_COMPILER_WARNINGS = True
-
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
 
--- a/ipc/app/moz.build
+++ b/ipc/app/moz.build
@@ -108,17 +108,13 @@ LDFLAGS += [CONFIG['MOZ_ALLOW_HEAP_EXECU
 #
 # The default heap size is 1MB on Win32.
 # The heap will grow if need be.
 #
 # Set it to 256k.  See bug 127069.
 if CONFIG['OS_ARCH'] == 'WINNT' and not CONFIG['GNU_CC']:
     LDFLAGS += ['/HEAP:0x40000']
 
-# Windows builds have dll linkage warnings due to msvcrt static linkage
-if CONFIG['OS_ARCH'] == 'WINNT':
-    ALLOW_COMPILER_WARNINGS = True
-
 if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
     OS_LIBS += [
         'binder',
         'utils',
     ]
--- a/js/public/ProfilingStack.h
+++ b/js/public/ProfilingStack.h
@@ -62,18 +62,21 @@ class ProfileEntry
         // This ProfileEntry is a dummy entry indicating the start of a run
         // of JS pseudostack entries.
         BEGIN_PSEUDO_JS = 0x04,
 
         // This flag is used to indicate that an interpreter JS entry has OSR-ed
         // into baseline.
         OSR = 0x08,
 
+        // Union of all flags.
+        ALL = IS_CPP_ENTRY|FRAME_LABEL_COPY|BEGIN_PSEUDO_JS|OSR,
+
         // Mask for removing all flags except the category information.
-        CATEGORY_MASK = ~IS_CPP_ENTRY & ~FRAME_LABEL_COPY & ~BEGIN_PSEUDO_JS & ~OSR
+        CATEGORY_MASK = ~ALL
     };
 
     // Keep these in sync with browser/devtools/performance/modules/global.js
     enum class Category : uint32_t {
         OTHER    = 0x10,
         CSS      = 0x20,
         JS       = 0x40,
         GC       = 0x80,
@@ -82,16 +85,19 @@ class ProfileEntry
         GRAPHICS = 0x400,
         STORAGE  = 0x800,
         EVENTS   = 0x1000,
 
         FIRST    = OTHER,
         LAST     = EVENTS
     };
 
+    static_assert((static_cast<int>(Category::FIRST) & Flags::ALL) == 0,
+                  "The category bitflags should not intersect with the other flags!");
+
     // All of these methods are marked with the 'volatile' keyword because SPS's
     // representation of the stack is stored such that all ProfileEntry
     // instances are volatile. These methods would not be available unless they
     // were marked as volatile as well.
 
     bool isCpp() const volatile { return hasFlag(IS_CPP_ENTRY); }
     bool isJs() const volatile { return !isCpp(); }
 
--- a/js/public/UbiNodeCensus.h
+++ b/js/public/UbiNodeCensus.h
@@ -4,16 +4,18 @@
  * 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 js_UbiNodeCensus_h
 #define js_UbiNodeCensus_h
 
 #include "mozilla/Move.h"
 
+#include "jsapi.h"
+
 #include "js/UbiNode.h"
 #include "js/UbiNodeTraverse.h"
 
 // A census is a ubi::Node traversal that assigns each node to one or more
 // buckets, and returns a report with the size of each bucket.
 //
 // We summarize the results of a census with counts broken down according to
 // criteria selected by the API consumer code that is requesting the census. For
--- a/js/src/aclocal.m4
+++ b/js/src/aclocal.m4
@@ -26,16 +26,17 @@ builtin(include, ../../build/autoconf/an
 builtin(include, ../../build/autoconf/zlib.m4)dnl
 builtin(include, ../../build/autoconf/linux.m4)dnl
 builtin(include, ../../build/autoconf/python-virtualenv.m4)dnl
 builtin(include, ../../build/autoconf/winsdk.m4)dnl
 builtin(include, ../../build/autoconf/icu.m4)dnl
 builtin(include, ../../build/autoconf/ffi.m4)dnl
 builtin(include, ../../build/autoconf/clang-plugin.m4)dnl
 builtin(include, ../../build/autoconf/alloc.m4)dnl
+builtin(include, ../../build/autoconf/jemalloc.m4)dnl
 
 define([__MOZ_AC_INIT_PREPARE], defn([AC_INIT_PREPARE]))
 define([AC_INIT_PREPARE],
 [if test -z "$srcdir"; then
   srcdir=`dirname "[$]0"`
 fi
 srcdir="$srcdir/../.."
 __MOZ_AC_INIT_PREPARE($1)
--- a/js/src/asmjs/AsmJSValidate.cpp
+++ b/js/src/asmjs/AsmJSValidate.cpp
@@ -12371,22 +12371,22 @@ CheckModule(ExclusiveContext* cx, AsmJSP
         return false;
 
     if (!CheckModuleProcessingDirectives(m))
         return false;
 
     if (!CheckModuleGlobals(m))
         return false;
 
+    m.startFunctionBodies();
+
 #if !defined(ENABLE_SHARED_ARRAY_BUFFER)
     MOZ_ASSERT(!m.module().hasArrayView() || !m.module().isSharedView());
 #endif
 
-    m.startFunctionBodies();
-
     ScopedJSDeletePtr<ModuleCompileResults> mcd;
     if (!CheckFunctions(m, &mcd))
         return false;
 
     if (!m.finishFunctionBodies(&mcd))
         return false;
 
     if (!CheckFuncPtrTables(m))
--- a/js/src/configure.in
+++ b/js/src/configure.in
@@ -2397,16 +2397,17 @@ if test "$ac_cv_clock_monotonic" != "no"
     AC_DEFINE(HAVE_CLOCK_MONOTONIC)
     AC_SUBST(HAVE_CLOCK_MONOTONIC)
     AC_SUBST_LIST(REALTIME_LIBS)
 fi
 
 dnl Checks for math functions.
 dnl ========================================================
 AC_CHECK_LIB(m, sin)
+AC_CHECK_LIB(m, __sincos, AC_DEFINE(HAVE_SINCOS))
 AC_CHECK_FUNCS([log2 log1p expm1 sqrt1pm1 acosh asinh atanh cbrt])
 
 
 dnl check for wcrtomb/mbrtowc
 dnl =======================================================================
 if test -z "$MACOS_DEPLOYMENT_TARGET" || test "$MACOS_DEPLOYMENT_TARGET" -ge "100300"; then
 AC_LANG_SAVE
 AC_LANG_CPLUSPLUS
@@ -2976,16 +2977,20 @@ if test "$MOZ_MEMORY"; then
     AC_DEFINE(MOZ_MEMORY_WINDOWS)
     ;;
   *)
     AC_MSG_ERROR([--enable-jemalloc not supported on ${target}])
     ;;
   esac
 fi
 AC_SUBST(MOZ_MEMORY)
+AC_SUBST(MOZ_JEMALLOC4)
+if test -n "$MOZ_JEMALLOC4"; then
+  AC_DEFINE(MOZ_JEMALLOC4)
+fi
 AC_SUBST(MOZ_CRT)
 AC_SUBST(MOZ_GLUE_IN_PROGRAM)
 AC_SUBST_LIST(MOZ_GLUE_WRAP_LDFLAGS)
 
 dnl ========================================================
 dnl = Use malloc wrapper lib
 dnl ========================================================
 MOZ_ARG_ENABLE_BOOL(wrap-malloc,
@@ -3824,16 +3829,17 @@ fi
 AC_SUBST(JS_LIBRARY_NAME)
 AC_SUBST(JS_CONFIG_MOZ_JS_LIBS)
 AC_SUBST(JS_CONFIG_LIBS)
 
 if test -n "$MOZ_BUILD_NSPR"; then
     MOZ_SUBCONFIGURE_NSPR()
 fi
 MOZ_SUBCONFIGURE_FFI()
+MOZ_SUBCONFIGURE_JEMALLOC()
 
 dnl Spit out some output
 dnl ========================================================
 MOZ_CREATE_CONFIG_STATUS()
 
 if test "$JS_STANDALONE"; then
   MOZ_RUN_CONFIG_STATUS()
 fi
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/ion/bug984018.js
@@ -0,0 +1,62 @@
+var x = 0;
+function test() {
+    function sincos1(a, b) {
+        var sa = Math.sin(a);
+        var sb = Math.sin(b);
+        var ca = Math.cos(a);
+        var cb = Math.cos(b);
+        var ra = sa * sa + ca * ca;
+        var rb = sb * sb + cb * cb;
+        var dec = 100000;
+
+        assertEq(Math.round(ra * dec) / dec, Math.round(rb * dec) / dec);
+
+        ca = Math.cos(a);
+        cb = Math.cos(b);
+        sa = Math.sin(a);
+        sb = Math.sin(b);
+
+        var ra = sa * sa + ca * ca;
+        var rb = sb * sb + cb * cb;
+
+        assertEq(Math.round(ra * dec) / dec, Math.round(rb * dec) / dec);
+        return ra;
+    }
+
+    function sincos2(x) {
+        var s1 = Math.sin(x);
+        var c1 = Math.cos(x);
+
+        var c2 = Math.cos(x);
+        var s2 = Math.sin(x);
+        
+        return (s1 * s1 + c1 * c1) - (s2 * s2 + c2 * c2); 
+    }
+
+    function bailoutHere() { bailout(); }
+
+    function sincos3(x) {
+        var s = Math.sin(x);
+        bailoutHere();
+        var c = Math.cos(x);
+        assertEq(Math.round(s * s + c * c), 1);
+        return s;
+    }
+
+    function sincos4(x) {
+        if (x < 2500)
+            x = Math.sin(x);
+        else
+            x = Math.cos(x);
+        return x;
+    }
+
+    for (var i=0; i<5000; i++) {
+        x += sincos1(x, x + 1);
+        x += sincos2(x);
+        x += sincos3(x);
+        x += sincos4(i);
+    }
+}
+x += 1;
+test();
--- a/js/src/jit/CodeGenerator.cpp
+++ b/js/src/jit/CodeGenerator.cpp
@@ -6395,16 +6395,52 @@ CodeGenerator::visitFromCharCode(LFromCh
                   ool->entry());
 
     masm.movePtr(ImmPtr(&GetJitContext()->runtime->staticStrings().unitStaticTable), output);
     masm.loadPtr(BaseIndex(output, code, ScalePointer), output);
 
     masm.bind(ool->rejoin());
 }
 
+void
+CodeGenerator::visitSinCos(LSinCos *lir)
+{
+    Register temp = ToRegister(lir->temp());
+    Register params = ToRegister(lir->temp2());
+    FloatRegister input = ToFloatRegister(lir->input());
+    FloatRegister outputSin = ToFloatRegister(lir->outputSin());
+    FloatRegister outputCos = ToFloatRegister(lir->outputCos());
+
+    masm.reserveStack(sizeof(double) * 2);
+    masm.movePtr(masm.getStackPointer(), params);
+
+    const MathCache* mathCache = lir->mir()->cache();
+
+    masm.setupUnalignedABICall(temp);
+    if (mathCache) {
+        masm.movePtr(ImmPtr(mathCache), temp);
+        masm.passABIArg(temp);
+    }
+
+#define MAYBE_CACHED_(fcn) (mathCache ? (void*)fcn ## _impl : (void*)fcn ## _uncached)
+
+    masm.passABIArg(input, MoveOp::DOUBLE);
+    masm.passABIArg(MoveOperand(params, sizeof(double), MoveOperand::EFFECTIVE_ADDRESS),
+                                MoveOp::GENERAL);
+    masm.passABIArg(MoveOperand(params, 0, MoveOperand::EFFECTIVE_ADDRESS),
+                                MoveOp::GENERAL);
+
+    masm.callWithABI(JS_FUNC_TO_DATA_PTR(void*, MAYBE_CACHED_(js::math_sincos)));
+#undef MAYBE_CACHED_
+
+    masm.loadDouble(Address(masm.getStackPointer(), 0), outputCos);
+    masm.loadDouble(Address(masm.getStackPointer(), sizeof(double)), outputSin);
+    masm.freeStack(sizeof(double) * 2);
+}
+
 typedef JSObject* (*StringSplitFn)(JSContext*, HandleObjectGroup, HandleString, HandleString);
 static const VMFunction StringSplitInfo = FunctionInfo<StringSplitFn>(js::str_split_string);
 
 void
 CodeGenerator::visitStringSplit(LStringSplit* lir)
 {
     pushArg(ToRegister(lir->separator()));
     pushArg(ToRegister(lir->string()));
--- a/js/src/jit/CodeGenerator.h
+++ b/js/src/jit/CodeGenerator.h
@@ -237,16 +237,17 @@ class CodeGenerator : public CodeGenerat
     void visitIsNullOrLikeUndefinedV(LIsNullOrLikeUndefinedV* lir);
     void visitIsNullOrLikeUndefinedT(LIsNullOrLikeUndefinedT* lir);
     void visitIsNullOrLikeUndefinedAndBranchV(LIsNullOrLikeUndefinedAndBranchV* lir);
     void visitIsNullOrLikeUndefinedAndBranchT(LIsNullOrLikeUndefinedAndBranchT* lir);
     void emitConcat(LInstruction* lir, Register lhs, Register rhs, Register output);
     void visitConcat(LConcat* lir);
     void visitCharCodeAt(LCharCodeAt* lir);
     void visitFromCharCode(LFromCharCode* lir);
+    void visitSinCos(LSinCos *lir);
     void visitStringSplit(LStringSplit* lir);
     void visitFunctionEnvironment(LFunctionEnvironment* lir);
     void visitCallGetProperty(LCallGetProperty* lir);
     void visitCallGetElement(LCallGetElement* lir);
     void visitCallSetElement(LCallSetElement* lir);
     void visitCallInitElementArray(LCallInitElementArray* lir);
     void visitThrow(LThrow* lir);
     void visitTypeOfV(LTypeOfV* lir);
--- a/js/src/jit/Ion.cpp
+++ b/js/src/jit/Ion.cpp
@@ -1373,16 +1373,121 @@ jit::ToggleBarriers(JS::Zone* zone, bool
         if (comp->jitCompartment())
             comp->jitCompartment()->toggleBarriers(needs);
     }
 }
 
 namespace js {
 namespace jit {
 
+static void
+OptimizeSinCos(MIRGenerator *mir, MIRGraph &graph)
+{
+    // Now, we are looking for:
+    // var y = sin(x);
+    // var z = cos(x);
+    // Graph before:
+    // - 1 op
+    // - 6 mathfunction op1 Sin
+    // - 7 mathfunction op1 Cos
+    // Graph will look like:
+    // - 1 op
+    // - 5 sincos op1
+    // - 6 mathfunction sincos5 Sin
+    // - 7 mathfunction sincos5 Cos
+    for (MBasicBlockIterator block(graph.begin()); block != graph.end(); block++) {
+        for (MInstructionIterator iter(block->begin()), end(block->end()); iter != end; ) {
+            MInstruction *ins = *iter++;
+            if (!ins->isMathFunction() || ins->isRecoveredOnBailout())
+                continue;
+
+            MMathFunction *insFunc = ins->toMathFunction();
+            if (insFunc->function() != MMathFunction::Sin && insFunc->function() != MMathFunction::Cos)
+                continue;
+
+            // Check if sin/cos is already optimized.
+            if (insFunc->getOperand(0)->type() == MIRType_SinCosDouble)
+                continue;
+
+            // insFunc is either a |sin(x)| or |cos(x)| instruction. The
+            // following loop iterates over the uses of |x| to check if both
+            // |sin(x)| and |cos(x)| instructions exist.
+            bool hasSin = false;
+            bool hasCos = false;
+            for (MUseDefIterator uses(insFunc->input()); uses; uses++)
+            {
+                if (!uses.def()->isInstruction())
+                    continue;
+
+                // We should replacing the argument of the sin/cos just when it
+                // is dominated by the |block|.
+                if (!block->dominates(uses.def()->block()))
+                    continue;
+
+                MInstruction *insUse = uses.def()->toInstruction();
+                if (!insUse->isMathFunction() || insUse->isRecoveredOnBailout())
+                    continue;
+
+                MMathFunction *mathIns = insUse->toMathFunction();
+                if (!hasSin && mathIns->function() == MMathFunction::Sin) {
+                    hasSin = true;
+                    JitSpew(JitSpew_Sincos, "Found sin in block %d.", mathIns->block()->id());
+                }
+                else if (!hasCos && mathIns->function() == MMathFunction::Cos) {
+                    hasCos = true;
+                    JitSpew(JitSpew_Sincos, "Found cos in block %d.", mathIns->block()->id());
+                }
+
+                if (hasCos && hasSin)
+                    break;
+            }
+
+            if (!hasCos || !hasSin) {
+                JitSpew(JitSpew_Sincos, "No sin/cos pair found.");
+                continue;
+            }
+
+            JitSpew(JitSpew_Sincos, "Found, at least, a pair sin/cos. Adding sincos in block %d",
+                    block->id());
+            // Adding the MSinCos and replacing the parameters of the
+            // sin(x)/cos(x) to sin(sincos(x))/cos(sincos(x)).
+            MSinCos *insSinCos = MSinCos::New(graph.alloc(),
+                                              insFunc->input(),
+                                              insFunc->toMathFunction()->cache());
+            insSinCos->setImplicitlyUsedUnchecked();
+            block->insertBefore(insFunc, insSinCos);
+            for (MUseDefIterator uses(insFunc->input()); uses; )
+            {
+                MDefinition* def = uses.def();
+                uses++;
+                if (!def->isInstruction())
+                    continue;
+
+                // We should replacing the argument of the sin/cos just when it
+                // is dominated by the |block|.
+                if (!block->dominates(def->block()))
+                    continue;
+
+                MInstruction *insUse = def->toInstruction();
+                if (!insUse->isMathFunction() || insUse->isRecoveredOnBailout())
+                    continue;
+
+                MMathFunction *mathIns = insUse->toMathFunction();
+                if (mathIns->function() != MMathFunction::Sin && mathIns->function() != MMathFunction::Cos)
+                    continue;
+
+                mathIns->replaceOperand(0, insSinCos);
+                JitSpew(JitSpew_Sincos, "Replacing %s by sincos in block %d",
+                        mathIns->function() == MMathFunction::Sin ? "sin" : "cos",
+                        mathIns->block()->id());
+            }
+        }
+    }
+}
+
 bool
 OptimizeMIR(MIRGenerator* mir)
 {
     MIRGraph& graph = mir->graph();
     GraphSpewer& gs = mir->graphSpewer();
     TraceLoggerThread* logger;
     if (GetJitContext()->runtime->onMainThread())
         logger = TraceLoggerForMainThread(GetJitContext()->runtime);
@@ -1648,16 +1753,26 @@ OptimizeMIR(MIRGenerator* mir)
             return false;
         gs.spewPass("Effective Address Analysis");
         AssertExtendedGraphCoherency(graph);
 
         if (mir->shouldCancel("Effective Address Analysis"))
             return false;
     }
 
+    if (mir->optimizationInfo().sincosEnabled()) {
+        AutoTraceLog log(logger, TraceLogger_Sincos);
+        OptimizeSinCos(mir, graph);
+        gs.spewPass("Sincos optimization");
+        AssertExtendedGraphCoherency(graph);
+
+        if (mir->shouldCancel("Sincos optimization"))
+            return false;
+    }
+
     {
         AutoTraceLog log(logger, TraceLogger_EliminateDeadCode);
         if (!EliminateDeadCode(mir, graph))
             return false;
         gs.spewPass("DCE");
         AssertExtendedGraphCoherency(graph);
 
         if (mir->shouldCancel("DCE"))
--- a/js/src/jit/IonAnalysis.cpp
+++ b/js/src/jit/IonAnalysis.cpp
@@ -2089,16 +2089,17 @@ IsResumableMIRType(MIRType type)
       case MIRType_ObjectOrNull:
       case MIRType_None:
       case MIRType_Slots:
       case MIRType_Elements:
       case MIRType_Pointer:
       case MIRType_Shape:
       case MIRType_ObjectGroup:
       case MIRType_Doublex2: // NYI, see also RSimdBox::recover
+      case MIRType_SinCosDouble:
         return false;
     }
     MOZ_CRASH("Unknown MIRType.");
 }
 
 static void
 AssertResumableOperands(MNode* node)
 {
--- a/js/src/jit/IonOptimizationLevels.cpp
+++ b/js/src/jit/IonOptimizationLevels.cpp
@@ -30,16 +30,17 @@ OptimizationInfo::initNormalOptimization
     inlineNative_ = true;
     eagerSimdUnbox_ = true;
     gvn_ = true;
     licm_ = true;
     rangeAnalysis_ = true;
     loopUnrolling_ = true;
     reordering_ = true;
     autoTruncate_ = true;
+    sincos_ = true;
     sink_ = true;
     registerAllocator_ = RegisterAllocator_Backtracking;
 
     inlineMaxBytecodePerCallSiteMainThread_ = 500;
     inlineMaxBytecodePerCallSiteOffThread_ = 1000;
     inlineMaxCalleeInlinedBytecodeLength_ = 3000;
     inlineMaxTotalBytecodeLength_ = 80000;
     inliningMaxCallerBytecodeLength_ = 1500;
@@ -61,16 +62,17 @@ OptimizationInfo::initAsmjsOptimizationI
     initNormalOptimizationInfo();
 
     ama_ = true;
     level_ = Optimization_AsmJS;
     eagerSimdUnbox_ = false;           // AsmJS has no boxing / unboxing.
     edgeCaseAnalysis_ = false;
     eliminateRedundantChecks_ = false;
     autoTruncate_ = false;
+    sincos_ = false;
     sink_ = false;
     registerAllocator_ = RegisterAllocator_Backtracking;
     scalarReplacement_ = false;        // AsmJS has no objects.
 }
 
 uint32_t
 OptimizationInfo::compilerWarmUpThreshold(JSScript* script, jsbytecode* pc) const
 {
--- a/js/src/jit/IonOptimizationLevels.h
+++ b/js/src/jit/IonOptimizationLevels.h
@@ -80,16 +80,19 @@ class OptimizationInfo
     bool loopUnrolling_;
 
     // Toggles whether instruction reordering is performed.
     bool reordering_;
 
     // Toggles whether Truncation based on Range Analysis is used.
     bool autoTruncate_;
 
+    // Toggles whether sincos is used.
+    bool sincos_;
+
     // Toggles whether sink is used.
     bool sink_;
 
     // Describes which register allocator to use.
     IonRegisterAllocator registerAllocator_;
 
     // The maximum total bytecode size of an inline call site. We use a lower
     // value if off-thread compilation is not available, to avoid stalling the
@@ -181,16 +184,20 @@ class OptimizationInfo
     bool instructionReorderingEnabled() const {
         return reordering_ && !js_JitOptions.disableInstructionReordering;
     }
 
     bool autoTruncateEnabled() const {
         return autoTruncate_ && rangeAnalysisEnabled();
     }
 
+    bool sincosEnabled() const {
+        return sincos_ && !js_JitOptions.disableSincos;
+    }
+
     bool sinkEnabled() const {
         return sink_ && !js_JitOptions.disableSink;
     }
 
     bool eaaEnabled() const {
         return eaa_ && !js_JitOptions.disableEaa;
     }
 
--- a/js/src/jit/IonTypes.h
+++ b/js/src/jit/IonTypes.h
@@ -374,16 +374,17 @@ enum MIRType
     MIRType_Symbol,
     MIRType_Object,
     MIRType_MagicOptimizedArguments,   // JS_OPTIMIZED_ARGUMENTS magic value.
     MIRType_MagicOptimizedOut,         // JS_OPTIMIZED_OUT magic value.
     MIRType_MagicHole,                 // JS_ELEMENTS_HOLE magic value.
     MIRType_MagicIsConstructing,       // JS_IS_CONSTRUCTING magic value.
     MIRType_MagicUninitializedLexical, // JS_UNINITIALIZED_LEXICAL magic value.
     MIRType_Value,
+    MIRType_SinCosDouble,              // Optimizing a sin/cos to sincos.
     MIRType_ObjectOrNull,
     MIRType_None,                      // Invalid, used as a placeholder.
     MIRType_Slots,                     // A slots vector
     MIRType_Elements,                  // An elements vector
     MIRType_Pointer,                   // An opaque pointer that receives no special treatment
     MIRType_Shape,                     // A Shape pointer.
     MIRType_ObjectGroup,               // An ObjectGroup pointer.
     MIRType_Last = MIRType_ObjectGroup,
@@ -487,16 +488,18 @@ StringFromMIRType(MIRType type)
     case MIRType_MagicHole:
       return "MagicHole";
     case MIRType_MagicIsConstructing:
       return "MagicIsConstructing";
     case MIRType_MagicUninitializedLexical:
       return "MagicUninitializedLexical";
     case MIRType_Value:
       return "Value";
+    case MIRType_SinCosDouble:
+      return "SinCosDouble";
     case MIRType_ObjectOrNull:
       return "ObjectOrNull";
     case MIRType_None:
       return "None";
     case MIRType_Slots:
       return "Slots";
     case MIRType_Elements:
       return "Elements";
@@ -712,17 +715,30 @@ enum ABIFunctionType
     Args_Int_IntDouble = Args_General0 |
         (ArgType_Double << (ArgType_Shift * 1)) |
         (ArgType_General << (ArgType_Shift * 2)),
 
     // double f(double, double, double)
     Args_Double_DoubleDoubleDouble = Args_Double_DoubleDouble | (ArgType_Double << (ArgType_Shift * 3)),
 
     // double f(double, double, double, double)
-    Args_Double_DoubleDoubleDoubleDouble = Args_Double_DoubleDoubleDouble | (ArgType_Double << (ArgType_Shift * 4))
+    Args_Double_DoubleDoubleDoubleDouble = Args_Double_DoubleDoubleDouble | (ArgType_Double << (ArgType_Shift * 4)),
+
+    // int f(double, int, int)
+    Args_Int_DoubleIntInt = Args_General0 |
+       (ArgType_General << (ArgType_Shift * 1)) |
+       (ArgType_General << (ArgType_Shift * 2)) |
+       (ArgType_Double  << (ArgType_Shift * 3)),
+
+    // int f(int, double, int, int)
+    Args_Int_IntDoubleIntInt = Args_General0 |
+        (ArgType_General << (ArgType_Shift * 1)) |
+        (ArgType_General << (ArgType_Shift * 2)) |
+        (ArgType_Double  << (ArgType_Shift * 3)) |
+        (ArgType_General << (ArgType_Shift * 4))
 
 };
 
 enum class BarrierKind : uint32_t {
     // No barrier is needed.
     NoBarrier,
 
     // The barrier only has to check the value's type tag is in the TypeSet.
--- a/js/src/jit/JitOptions.cpp
+++ b/js/src/jit/JitOptions.cpp
@@ -105,16 +105,24 @@ JitOptions::JitOptions()
     SET_DEFAULT(disableRangeAnalysis, false);
 
     // Toggle whether eager scalar replacement is globally disabled.
     SET_DEFAULT(disableScalarReplacement, false);
 
     // Toggles whether shared stubs are used in Ionmonkey.
     SET_DEFAULT(disableSharedStubs, true);
 
+    // Toggles whether sincos optimization is globally disabled.
+    // See bug984018: The MacOS is the only one that has the sincos fast.
+    #if defined(XP_MACOSX)
+        SET_DEFAULT(disableSincos, false);
+    #else
+        SET_DEFAULT(disableSincos, true);
+    #endif
+
     // Toggles whether sink code motion is globally disabled.
     SET_DEFAULT(disableSink, true);
 
     // Whether functions are compiled immediately.
     SET_DEFAULT(eagerCompilation, false);
 
     // Whether IonBuilder should prefer IC generation above specialized MIR.
     SET_DEFAULT(forceInlineCaches, false);
--- a/js/src/jit/JitOptions.h
+++ b/js/src/jit/JitOptions.h
@@ -54,16 +54,17 @@ struct JitOptions
     bool disableGvn;
     bool disableInlining;
     bool disableLicm;
     bool disableLoopUnrolling;
     bool disableInstructionReordering;
     bool disableRangeAnalysis;
     bool disableScalarReplacement;
     bool disableSharedStubs;
+    bool disableSincos;
     bool disableSink;
     bool eagerCompilation;
     bool forceInlineCaches;
     bool limitScriptSize;
     bool osr;
     uint32_t baselineWarmUpThreshold;
     uint32_t exceptionBailoutThreshold;
     uint32_t frequentBailoutThreshold;
--- a/js/src/jit/JitSpewer.cpp
+++ b/js/src/jit/JitSpewer.cpp
@@ -399,16 +399,17 @@ jit::CheckLogging()
             "\n"
             "  aborts     Compilation abort messages\n"
             "  scripts    Compiled scripts\n"
             "  mir        MIR information\n"
             "  escape     Escape analysis\n"
             "  alias      Alias analysis\n"
             "  gvn        Global Value Numbering\n"
             "  licm       Loop invariant code motion\n"
+            "  sincos     Replace sin/cos by sincos\n"
             "  sink       Sink transformation\n"
             "  regalloc   Register allocation\n"
             "  inline     Inlining\n"
             "  snapshots  Snapshot information\n"
             "  codegen    Native code generation\n"
             "  bailouts   Bailouts\n"
             "  caches     Inline caches\n"
             "  osi        Invalidation\n"
@@ -450,16 +451,18 @@ jit::CheckLogging()
     if (ContainsFlag(env, "gvn"))
         EnableChannel(JitSpew_GVN);
     if (ContainsFlag(env, "range"))
         EnableChannel(JitSpew_Range);
     if (ContainsFlag(env, "unroll"))
         EnableChannel(JitSpew_Unrolling);
     if (ContainsFlag(env, "licm"))
         EnableChannel(JitSpew_LICM);
+    if (ContainsFlag(env, "sincos"))
+        EnableChannel(JitSpew_Sincos);
     if (ContainsFlag(env, "sink"))
         EnableChannel(JitSpew_Sink);
     if (ContainsFlag(env, "regalloc"))
         EnableChannel(JitSpew_RegAlloc);
     if (ContainsFlag(env, "inline"))
         EnableChannel(JitSpew_Inlining);
     if (ContainsFlag(env, "snapshots"))
         EnableChannel(JitSpew_IonSnapshots);
--- a/js/src/jit/JitSpewer.h
+++ b/js/src/jit/JitSpewer.h
@@ -21,16 +21,18 @@ namespace jit {
 // New channels may be added below.
 #define JITSPEW_CHANNEL_LIST(_)             \
     /* Information during escape analysis */\
     _(Escape)                               \
     /* Information during alias analysis */ \
     _(Alias)                                \
     /* Information during GVN */            \
     _(GVN)                                  \
+    /* Information during sincos */         \
+    _(Sincos)                               \
     /* Information during sinking */        \
     _(Sink)                                 \
     /* Information during Range analysis */ \
     _(Range)                                \
     /* Information during loop unrolling */ \
     _(Unrolling)                            \
     /* Information during LICM */           \
     _(LICM)                                 \
--- a/js/src/jit/LIR.cpp
+++ b/js/src/jit/LIR.cpp
@@ -345,16 +345,17 @@ static const char * const TypeChars[] =
     "g",            // GENERAL
     "i",            // INT32
     "o",            // OBJECT
     "s",            // SLOTS
     "f",            // FLOAT32
     "d",            // DOUBLE
     "i32x4",        // INT32X4
     "f32x4",        // FLOAT32X4
+    "sincos",       // SINCOS
 #ifdef JS_NUNBOX32
     "t",            // TYPE
     "p"             // PAYLOAD
 #elif JS_PUNBOX64
     "x"             // BOX
 #endif
 };
 
--- a/js/src/jit/LIR.h
+++ b/js/src/jit/LIR.h
@@ -417,16 +417,17 @@ class LDefinition
         GENERAL,    // Generic, integer or pointer-width data (GPR).
         INT32,      // int32 data (GPR).
         OBJECT,     // Pointer that may be collected as garbage (GPR).
         SLOTS,      // Slots/elements pointer that may be moved by minor GCs (GPR).
         FLOAT32,    // 32-bit floating-point value (FPU).
         DOUBLE,     // 64-bit floating-point value (FPU).
         INT32X4,    // SIMD data containing four 32-bit integers (FPU).
         FLOAT32X4,  // SIMD data containing four 32-bit floats (FPU).
+        SINCOS,
 #ifdef JS_NUNBOX32
         // A type virtual register must be followed by a payload virtual
         // register, as both will be tracked as a single gcthing.
         TYPE,
         PAYLOAD
 #else
         BOX         // Joined box, for punbox systems. (GPR, gcthing)
 #endif
@@ -557,16 +558,18 @@ class LDefinition
           case MIRType_Double:
             return LDefinition::DOUBLE;
           case MIRType_Float32:
             return LDefinition::FLOAT32;
 #if defined(JS_PUNBOX64)
           case MIRType_Value:
             return LDefinition::BOX;
 #endif
+          case MIRType_SinCosDouble:
+            return LDefinition::SINCOS;
           case MIRType_Slots:
           case MIRType_Elements:
             return LDefinition::SLOTS;
           case MIRType_Pointer:
             return LDefinition::GENERAL;
           case MIRType_Int32x4:
             return LDefinition::INT32X4;
           case MIRType_Float32x4:
@@ -1823,17 +1826,20 @@ LAllocation::toRegister() const
 #  include "jit/x64/LIR-x64.h"
 # endif
 # include "jit/x86-shared/LIR-x86-shared.h"
 #elif defined(JS_CODEGEN_ARM)
 # include "jit/arm/LIR-arm.h"
 #elif defined(JS_CODEGEN_ARM64)
 # include "jit/arm64/LIR-arm64.h"
 #elif defined(JS_CODEGEN_MIPS32)
-# include "jit/mips32/LIR-mips32.h"
+# if defined(JS_CODEGEN_MIPS32)
+#  include "jit/mips32/LIR-mips32.h"
+# endif
+# include "jit/mips-shared/LIR-mips-shared.h"
 #elif defined(JS_CODEGEN_NONE)
 # include "jit/none/LIR-none.h"
 #else
 # error "Unknown architecture!"
 #endif
 
 #undef LIR_HEADER
 
--- a/js/src/jit/Lowering.cpp
+++ b/js/src/jit/Lowering.cpp
@@ -1388,17 +1388,24 @@ LIRGenerator::visitPow(MPow* ins)
     }
     defineReturn(lir, ins);
 }
 
 void
 LIRGenerator::visitMathFunction(MMathFunction* ins)
 {
     MOZ_ASSERT(IsFloatingPointType(ins->type()));
-    MOZ_ASSERT(ins->type() == ins->input()->type());
+    MOZ_ASSERT_IF(ins->input()->type() != MIRType_SinCosDouble,
+                  ins->type() == ins->input()->type());
+
+    if (ins->input()->type() == MIRType_SinCosDouble) {
+        MOZ_ASSERT(ins->type() == MIRType_Double);
+        redefine(ins, ins->input(), ins->function());
+        return;
+    }
 
     LInstruction* lir;
     if (ins->type() == MIRType_Double) {
         // Note: useRegisterAtStart is safe here, the temp is not a FP register.
         lir = new(alloc()) LMathFunctionD(useRegisterAtStart(ins->input()),
                                           tempFixed(CallTempReg0));
     } else {
         lir = new(alloc()) LMathFunctionF(useRegisterAtStart(ins->input()),
@@ -2977,16 +2984,30 @@ LIRGenerator::visitArrayJoin(MArrayJoin*
 
     LArrayJoin* lir = new(alloc()) LArrayJoin(useRegisterAtStart(ins->array()),
                                               useRegisterAtStart(ins->sep()));
     defineReturn(lir, ins);
     assignSafepoint(lir, ins);
 }
 
 void
+LIRGenerator::visitSinCos(MSinCos *ins)
+{
+    MOZ_ASSERT(ins->type() == MIRType_SinCosDouble);
+    MOZ_ASSERT(ins->input()->type() == MIRType_Double  ||
+               ins->input()->type() == MIRType_Float32 ||
+               ins->input()->type() == MIRType_Int32);
+
+    LSinCos *lir = new (alloc()) LSinCos(useRegisterAtStart(ins->input()),
+                                         tempFixed(CallTempReg0),
+                                         temp());
+    defineSinCos(lir, ins);
+}
+
+void
 LIRGenerator::visitStringSplit(MStringSplit* ins)
 {
     MOZ_ASSERT(ins->type() == MIRType_Object);
     MOZ_ASSERT(ins->string()->type() == MIRType_String);
     MOZ_ASSERT(ins->separator()->type() == MIRType_String);
 
     LStringSplit* lir = new(alloc()) LStringSplit(useRegisterAtStart(ins->string()),
                                                   useRegisterAtStart(ins->separator()));
--- a/js/src/jit/Lowering.h
+++ b/js/src/jit/Lowering.h
@@ -136,16 +136,17 @@ class LIRGenerator : public LIRGenerator
     void visitAdd(MAdd* ins);
     void visitSub(MSub* ins);
     void visitMul(MMul* ins);
     void visitDiv(MDiv* ins);
     void visitMod(MMod* ins);
     void visitConcat(MConcat* ins);
     void visitCharCodeAt(MCharCodeAt* ins);
     void visitFromCharCode(MFromCharCode* ins);
+    void visitSinCos(MSinCos *ins);
     void visitStringSplit(MStringSplit* ins);
     void visitStart(MStart* start);
     void visitOsrEntry(MOsrEntry* entry);
     void visitNop(MNop* nop);
     void visitLimitedTruncate(MLimitedTruncate* nop);
     void visitOsrValue(MOsrValue* value);
     void visitOsrScopeChain(MOsrScopeChain* object);
     void visitOsrReturnValue(MOsrReturnValue* value);
--- a/js/src/jit/MIR.h
+++ b/js/src/jit/MIR.h
@@ -6114,16 +6114,18 @@ class MMathFunction
 
     bool isFloat32Commutative() const override {
         return function_ == Floor || function_ == Ceil || function_ == Round;
     }
     void trySpecializeFloat32(TempAllocator& alloc) override;
     void computeRange(TempAllocator& alloc) override;
     bool writeRecoverData(CompactBufferWriter& writer) const override;
     bool canRecoverOnBailout() const override {
+        if (input()->type() == MIRType_SinCosDouble)
+            return false;
         switch(function_) {
           case Sin:
           case Log:
           case Round:
             return true;
           default:
             return false;
         }
@@ -6621,16 +6623,50 @@ class MFromCharCode
     bool writeRecoverData(CompactBufferWriter& writer) const override;
     bool canRecoverOnBailout() const override {
         return true;
     }
 
     ALLOW_CLONE(MFromCharCode)
 };
 
+class MSinCos
+  : public MUnaryInstruction,
+    public FloatingPointPolicy<0>::Data
+{
+    const MathCache* cache_;
+
+    MSinCos(MDefinition *input, const MathCache *cache) : MUnaryInstruction(input), cache_(cache)
+    {
+        setResultType(MIRType_SinCosDouble);
+        specialization_ = MIRType_Double;
+        setMovable();
+    }
+
+  public:
+    INSTRUCTION_HEADER(SinCos)
+
+    static MSinCos *New(TempAllocator &alloc, MDefinition *input, const MathCache *cache)
+    {
+        return new (alloc) MSinCos(input, cache);
+    }
+    AliasSet getAliasSet() const override {
+        return AliasSet::None();
+    }
+    bool congruentTo(const MDefinition *ins) const override {
+        return congruentIfOperandsEqual(ins);
+    }
+    bool possiblyCalls() const override {
+        return true;
+    }
+    const MathCache* cache() const {
+        return cache_;
+    }
+};
+
 class MStringSplit
   : public MTernaryInstruction,
     public MixPolicy<StringPolicy<0>, StringPolicy<1> >::Data
 {
     MStringSplit(CompilerConstraintList* constraints, MDefinition* string, MDefinition* sep,
                  MConstant* templateObject)
       : MTernaryInstruction(string, sep, templateObject)
     {
--- a/js/src/jit/MOpcodes.h
+++ b/js/src/jit/MOpcodes.h
@@ -94,16 +94,17 @@ namespace jit {
     _(Add)                                                                  \
     _(Sub)                                                                  \
     _(Mul)                                                                  \
     _(Div)                                                                  \
     _(Mod)                                                                  \
     _(Concat)                                                               \
     _(CharCodeAt)                                                           \
     _(FromCharCode)                                                         \
+    _(SinCos)                                                               \
     _(StringSplit)                                                          \
     _(Substr)                                                               \
     _(Return)                                                               \
     _(Throw)                                                                \
     _(Box)                                                                  \
     _(Unbox)                                                                \
     _(GuardObject)                                                          \
     _(GuardString)                                                          \
--- a/js/src/jit/MacroAssembler-inl.h
+++ b/js/src/jit/MacroAssembler-inl.h
@@ -145,16 +145,18 @@ MacroAssembler::signature() const
       case Args_Int_Double:
       case Args_Float32_Float32:
       case Args_Double_Double:
       case Args_Double_Int:
       case Args_Double_DoubleInt:
       case Args_Double_DoubleDouble:
       case Args_Double_IntDouble:
       case Args_Int_IntDouble:
+      case Args_Int_DoubleIntInt:
+      case Args_Int_IntDoubleIntInt:
       case Args_Double_DoubleDoubleDouble:
       case Args_Double_DoubleDoubleDoubleDouble:
         break;
       default:
         MOZ_CRASH("Unexpected type");
     }
 #endif // DEBUG
 
--- a/js/src/jit/StackSlotAllocator.h
+++ b/js/src/jit/StackSlotAllocator.h
@@ -92,16 +92,17 @@ class StackSlotAllocator
 #ifdef JS_PUNBOX64
           case LDefinition::BOX:
 #endif
 #ifdef JS_NUNBOX32
           case LDefinition::TYPE:
           case LDefinition::PAYLOAD:
 #endif
           case LDefinition::DOUBLE:    return 8;
+          case LDefinition::SINCOS:
           case LDefinition::FLOAT32X4:
           case LDefinition::INT32X4:   return 16;
         }
         MOZ_CRASH("Unknown slot type");
     }
 
     void freeSlot(LDefinition::Type type, uint32_t index) {
         switch (width(type)) {
--- a/js/src/jit/TypePolicy.cpp
+++ b/js/src/jit/TypePolicy.cpp
@@ -488,17 +488,17 @@ TruncateToInt32Policy<Op>::staticAdjustI
 template bool TruncateToInt32Policy<2>::staticAdjustInputs(TempAllocator& alloc, MInstruction* def);
 template bool TruncateToInt32Policy<3>::staticAdjustInputs(TempAllocator& alloc, MInstruction* def);
 
 template <unsigned Op>
 bool
 DoublePolicy<Op>::staticAdjustInputs(TempAllocator& alloc, MInstruction* def)
 {
     MDefinition* in = def->getOperand(Op);
-    if (in->type() == MIRType_Double)
+    if (in->type() == MIRType_Double || in->type() == MIRType_SinCosDouble)
         return true;
 
     MToDouble* replace = MToDouble::New(alloc, in);
     def->block()->insertBefore(def, replace);
     def->replaceOperand(Op, replace);
 
     return replace->typePolicy()->adjustInputs(alloc, replace);
 }
--- a/js/src/jit/arm/Simulator-arm.cpp
+++ b/js/src/jit/arm/Simulator-arm.cpp
@@ -2057,16 +2057,19 @@ typedef int64_t (*Prototype_General7)(in
                                       int32_t arg4, int32_t arg5, int32_t arg6);
 typedef int64_t (*Prototype_General8)(int32_t arg0, int32_t arg1, int32_t arg2, int32_t arg3,
                                       int32_t arg4, int32_t arg5, int32_t arg6, int32_t arg7);
 
 typedef double (*Prototype_Double_None)();
 typedef double (*Prototype_Double_Double)(double arg0);
 typedef double (*Prototype_Double_Int)(int32_t arg0);
 typedef int32_t (*Prototype_Int_Double)(double arg0);
+typedef int32_t (*Prototype_Int_DoubleIntInt)(double arg0, int32_t arg1, int32_t arg2);
+typedef int32_t (*Prototype_Int_IntDoubleIntInt)(int32_t arg0, double arg1, int32_t arg2,
+                                                 int32_t arg3);
 typedef float (*Prototype_Float32_Float32)(float arg0);
 
 typedef double (*Prototype_DoubleInt)(double arg0, int32_t arg1);
 typedef double (*Prototype_Double_IntDouble)(int32_t arg0, double arg1);
 typedef double (*Prototype_Double_DoubleDouble)(double arg0, double arg1);
 typedef int32_t (*Prototype_Int_IntDouble)(int32_t arg0, double arg1);
 
 typedef double (*Prototype_Double_DoubleDoubleDouble)(double arg0, double arg1, double arg2);
@@ -2288,16 +2291,46 @@ Simulator::softwareInterrupt(SimInstruct
             else
                 dval0 = get_double_from_register_pair(2);
             Prototype_Int_IntDouble target = reinterpret_cast<Prototype_Int_IntDouble>(external);
             int32_t result = target(ival, dval0);
             scratchVolatileRegisters(/* scratchFloat = true */);
             set_register(r0, result);
             break;
           }
+          case Args_Int_DoubleIntInt: {
+            double dval;
+            int32_t result;
+            Prototype_Int_DoubleIntInt target = reinterpret_cast<Prototype_Int_DoubleIntInt>(external);
+            if (UseHardFpABI()) {
+                dval = get_double_from_d_register(0);
+                result = target(dval, arg0, arg1);
+            } else {
+                dval = get_double_from_register_pair(0);
+                result = target(dval, arg2, arg3);
+            }
+            scratchVolatileRegisters(/* scratchFloat = true */);
+            set_register(r0, result);
+            break;
+          }
+          case Args_Int_IntDoubleIntInt: {
+            double dval;
+            int32_t result;
+            Prototype_Int_IntDoubleIntInt target = reinterpret_cast<Prototype_Int_IntDoubleIntInt>(external);
+            if (UseHardFpABI()) {
+                dval = get_double_from_d_register(0);
+                result = target(arg0, dval, arg1, arg2);
+            } else {
+                dval = get_double_from_register_pair(2);
+                result = target(arg0, dval, arg4, arg5);
+            }
+            scratchVolatileRegisters(/* scratchFloat = true */);
+            set_register(r0, result);
+            break;
+          }
           case Args_Double_DoubleDoubleDouble: {
             double dval0, dval1, dval2;
             int32_t ival;
             getFpArgs(&dval0, &dval1, &ival);
             // the last argument is on stack
             getFpFromStack(stack_pointer, &dval2);
             Prototype_Double_DoubleDoubleDouble target = reinterpret_cast<Prototype_Double_DoubleDoubleDouble>(external);
             double dresult = target(dval0, dval1, dval2);
--- a/js/src/jit/arm64/vixl/MozSimulator-vixl.cpp
+++ b/js/src/jit/arm64/vixl/MozSimulator-vixl.cpp
@@ -462,16 +462,19 @@ typedef int64_t (*Prototype_General6)(in
                                       int64_t arg4, int64_t arg5);
 typedef int64_t (*Prototype_General7)(int64_t arg0, int64_t arg1, int64_t arg2, int64_t arg3,
                                       int64_t arg4, int64_t arg5, int64_t arg6);
 typedef int64_t (*Prototype_General8)(int64_t arg0, int64_t arg1, int64_t arg2, int64_t arg3,
                                       int64_t arg4, int64_t arg5, int64_t arg6, int64_t arg7);
 
 typedef int64_t (*Prototype_Int_Double)(double arg0);
 typedef int64_t (*Prototype_Int_IntDouble)(int32_t arg0, double arg1);
+typedef int64_t (*Prototype_Int_DoubleIntInt)(double arg0, uint64_t arg1, uint64_t arg2);
+typedef int64_t (*Prototype_Int_IntDoubleIntInt)(uint64_t arg0, double arg1,
+                                                 uint64_t arg2, uint64_t arg3);
 
 typedef float (*Prototype_Float32_Float32)(float arg0);
 
 typedef double (*Prototype_Double_None)();
 typedef double (*Prototype_Double_Double)(double arg0);
 typedef double (*Prototype_Double_Int)(int32_t arg0);
 typedef double (*Prototype_Double_DoubleInt)(double arg0, int64_t arg1);
 typedef double (*Prototype_Double_IntDouble)(int64_t arg0, double arg1);
@@ -587,16 +590,28 @@ Simulator::VisitCallRedirection(const In
       break;
     }
     case js::jit::Args_Int_IntDouble: {
       int64_t ret = reinterpret_cast<Prototype_Int_IntDouble>(nativeFn)(x0, d0);
       setGPR64Result(ret);
       break;
     }
 
+    case js::jit::Args_Int_IntDoubleIntInt: {
+      int64_t ret = reinterpret_cast<Prototype_Int_IntDoubleIntInt>(nativeFn)(x0, d0, x1, x2);
+      setGPR64Result(ret);
+      break;
+    }
+
+    case js::jit::Args_Int_DoubleIntInt: {
+      int64_t ret = reinterpret_cast<Prototype_Int_DoubleIntInt>(nativeFn)(d0, x0, x1);
+      setGPR64Result(ret);
+      break;
+    }
+
     // Cases with float return type.
     case js::jit::Args_Float32_Float32: {
       float ret = reinterpret_cast<Prototype_Float32_Float32>(nativeFn)(s0);
       setFP32Result(ret);
       break;
     }
 
     // Cases with double return type.
copy from js/src/jit/mips32/LIR-mips32.h
copy to js/src/jit/mips-shared/LIR-mips-shared.h
--- a/js/src/jit/mips32/LIR-mips32.h
+++ b/js/src/jit/mips-shared/LIR-mips-shared.h
@@ -1,86 +1,20 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
  * vim: set ts=8 sts=4 et sw=4 tw=99:
  * 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 jit_mips32_LIR_mips32_h
-#define jit_mips32_LIR_mips32_h
+#ifndef jit_mips_shared_LIR_mips_shared_h
+#define jit_mips_shared_LIR_mips_shared_h
 
 namespace js {
 namespace jit {
 
-class LBoxFloatingPoint : public LInstructionHelper<2, 1, 1>
-{
-    MIRType type_;
-
-  public:
-    LIR_HEADER(BoxFloatingPoint);
-
-    LBoxFloatingPoint(const LAllocation& in, const LDefinition& temp, MIRType type)
-      : type_(type)
-    {
-        setOperand(0, in);
-        setTemp(0, temp);
-    }
-
-    MIRType type() const {
-        return type_;
-    }
-    const char* extraName() const {
-        return StringFromMIRType(type_);
-    }
-};
-
-class LUnbox : public LInstructionHelper<1, 2, 0>
-{
-  public:
-    LIR_HEADER(Unbox);
-
-    MUnbox* mir() const {
-        return mir_->toUnbox();
-    }
-    const LAllocation* payload() {
-        return getOperand(0);
-    }
-    const LAllocation* type() {
-        return getOperand(1);
-    }
-    const char* extraName() const {
-        return StringFromMIRType(mir()->type());
-    }
-};
-
-class LUnboxFloatingPoint : public LInstructionHelper<1, 2, 0>
-{
-    MIRType type_;
-
-  public:
-    LIR_HEADER(UnboxFloatingPoint);
-
-    static const size_t Input = 0;
-
-    LUnboxFloatingPoint(MIRType type)
-      : type_(type)
-    { }
-
-    MUnbox* mir() const {
-        return mir_->toUnbox();
-    }
-
-    MIRType type() const {
-        return type_;
-    }
-    const char* extraName() const {
-        return StringFromMIRType(type_);
-    }
-};
-
 // Convert a 32-bit unsigned integer to a double.
 class LAsmJSUInt32ToDouble : public LInstructionHelper<1, 1, 0>
 {
   public:
     LIR_HEADER(AsmJSUInt32ToDouble)
 
     LAsmJSUInt32ToDouble(const LAllocation& input) {
         setOperand(0, input);
@@ -365,9 +299,9 @@ class LRandom : public LCallInstructionH
     const LDefinition* temp2() {
         return getTemp(1);
     }
 };
 
 } // namespace jit
 } // namespace js
 
-#endif /* jit_mips32_LIR_mips32_h */
+#endif /* jit_mips_shared_LIR_mips_shared_h */
--- a/js/src/jit/mips32/LIR-mips32.h
+++ b/js/src/jit/mips32/LIR-mips32.h
@@ -71,303 +71,12 @@ class LUnboxFloatingPoint : public LInst
     MIRType type() const {
         return type_;
     }
     const char* extraName() const {
         return StringFromMIRType(type_);
     }
 };
 
-// Convert a 32-bit unsigned integer to a double.
-class LAsmJSUInt32ToDouble : public LInstructionHelper<1, 1, 0>
-{
-  public:
-    LIR_HEADER(AsmJSUInt32ToDouble)
-
-    LAsmJSUInt32ToDouble(const LAllocation& input) {
-        setOperand(0, input);
-    }
-};
-
-// Convert a 32-bit unsigned integer to a float32.
-class LAsmJSUInt32ToFloat32 : public LInstructionHelper<1, 1, 0>
-{
-  public:
-    LIR_HEADER(AsmJSUInt32ToFloat32)
-
-    LAsmJSUInt32ToFloat32(const LAllocation& input) {
-        setOperand(0, input);
-    }
-};
-
-
-class LDivI : public LBinaryMath<1>
-{
-  public:
-    LIR_HEADER(DivI);
-
-    LDivI(const LAllocation& lhs, const LAllocation& rhs,
-          const LDefinition& temp) {
-        setOperand(0, lhs);
-        setOperand(1, rhs);
-        setTemp(0, temp);
-    }
-
-    MDiv* mir() const {
-        return mir_->toDiv();
-    }
-};
-
-class LDivPowTwoI : public LInstructionHelper<1, 1, 1>
-{
-    const int32_t shift_;
-
-  public:
-    LIR_HEADER(DivPowTwoI)
-
-    LDivPowTwoI(const LAllocation& lhs, int32_t shift, const LDefinition& temp)
-      : shift_(shift)
-    {
-        setOperand(0, lhs);
-        setTemp(0, temp);
-    }
-
-    const LAllocation* numerator() {
-        return getOperand(0);
-    }
-
-    int32_t shift() {
-        return shift_;
-    }
-
-    MDiv* mir() const {
-        return mir_->toDiv();
-    }
-};
-
-class LModI : public LBinaryMath<1>
-{
-  public:
-    LIR_HEADER(ModI);
-
-    LModI(const LAllocation& lhs, const LAllocation& rhs,
-          const LDefinition& callTemp)
-    {
-        setOperand(0, lhs);
-        setOperand(1, rhs);
-        setTemp(0, callTemp);
-    }
-
-    const LDefinition* callTemp() {
-        return getTemp(0);
-    }
-
-    MMod* mir() const {
-        return mir_->toMod();
-    }
-};
-
-class LModPowTwoI : public LInstructionHelper<1, 1, 0>
-{
-    const int32_t shift_;
-
-  public:
-    LIR_HEADER(ModPowTwoI);
-    int32_t shift()
-    {
-        return shift_;
-    }
-
-    LModPowTwoI(const LAllocation& lhs, int32_t shift)
-      : shift_(shift)
-    {
-        setOperand(0, lhs);
-    }
-
-    MMod* mir() const {
-        return mir_->toMod();
-    }
-};
-
-class LModMaskI : public LInstructionHelper<1, 1, 2>
-{
-    const int32_t shift_;
-
-  public:
-    LIR_HEADER(ModMaskI);
-
-    LModMaskI(const LAllocation& lhs, const LDefinition& temp0, const LDefinition& temp1,
-              int32_t shift)
-      : shift_(shift)
-    {
-        setOperand(0, lhs);
-        setTemp(0, temp0);
-        setTemp(1, temp1);
-    }
-
-    int32_t shift() const {
-        return shift_;
-    }
-
-    MMod* mir() const {
-        return mir_->toMod();
-    }
-};
-
-// Takes a tableswitch with an integer to decide
-class LTableSwitch : public LInstructionHelper<0, 1, 2>
-{
-  public:
-    LIR_HEADER(TableSwitch);
-
-    LTableSwitch(const LAllocation& in, const LDefinition& inputCopy,
-                 const LDefinition& jumpTablePointer, MTableSwitch* ins) {
-        setOperand(0, in);
-        setTemp(0, inputCopy);
-        setTemp(1, jumpTablePointer);
-        setMir(ins);
-    }
-
-    MTableSwitch* mir() const {
-        return mir_->toTableSwitch();
-    }
-
-    const LAllocation* index() {
-        return getOperand(0);
-    }
-    const LDefinition* tempInt() {
-        return getTemp(0);
-    }
-    // This is added to share the same CodeGenerator prefixes.
-    const LDefinition* tempPointer() {
-        return getTemp(1);
-    }
-};
-
-// Takes a tableswitch with an integer to decide
-class LTableSwitchV : public LInstructionHelper<0, BOX_PIECES, 3>
-{
-  public:
-    LIR_HEADER(TableSwitchV);
-
-    LTableSwitchV(const LDefinition& inputCopy, const LDefinition& floatCopy,
-                  const LDefinition& jumpTablePointer, MTableSwitch* ins)
-    {
-        setTemp(0, inputCopy);
-        setTemp(1, floatCopy);
-        setTemp(2, jumpTablePointer);
-        setMir(ins);
-    }
-
-    MTableSwitch* mir() const {
-        return mir_->toTableSwitch();
-    }
-
-    static const size_t InputValue = 0;
-
-    const LDefinition* tempInt() {
-        return getTemp(0);
-    }
-    const LDefinition* tempFloat() {
-        return getTemp(1);
-    }
-    const LDefinition* tempPointer() {
-        return getTemp(2);
-    }
-};
-
-class LGuardShape : public LInstructionHelper<0, 1, 1>
-{
-  public:
-    LIR_HEADER(GuardShape);
-
-    LGuardShape(const LAllocation& in, const LDefinition& temp) {
-        setOperand(0, in);
-        setTemp(0, temp);
-    }
-    const MGuardShape* mir() const {
-        return mir_->toGuardShape();
-    }
-    const LDefinition* tempInt() {
-        return getTemp(0);
-    }
-};
-
-class LGuardObjectGroup : public LInstructionHelper<0, 1, 1>
-{
-  public:
-    LIR_HEADER(GuardObjectGroup);
-
-    LGuardObjectGroup(const LAllocation& in, const LDefinition& temp) {
-        setOperand(0, in);
-        setTemp(0, temp);
-    }
-    const MGuardObjectGroup* mir() const {
-        return mir_->toGuardObjectGroup();
-    }
-    const LDefinition* tempInt() {
-        return getTemp(0);
-    }
-};
-
-class LMulI : public LBinaryMath<0>
-{
-  public:
-    LIR_HEADER(MulI);
-
-    MMul* mir() {
-        return mir_->toMul();
-    }
-};
-
-class LUDivOrMod : public LBinaryMath<0>
-{
-  public:
-    LIR_HEADER(UDivOrMod);
-
-    MBinaryArithInstruction* mir() const {
-        MOZ_ASSERT(mir_->isDiv() || mir_->isMod());
-        return static_cast<MBinaryArithInstruction*>(mir_);
-    }
-
-    bool canBeDivideByZero() const {
-        if (mir_->isMod())
-            return mir_->toMod()->canBeDivideByZero();
-        return mir_->toDiv()->canBeDivideByZero();
-    }
-};
-
-class LAsmJSLoadFuncPtr : public LInstructionHelper<1, 1, 0>
-{
-  public:
-    LIR_HEADER(AsmJSLoadFuncPtr);
-    LAsmJSLoadFuncPtr(const LAllocation& index) {
-        setOperand(0, index);
-    }
-    const MAsmJSLoadFuncPtr* mir() const {
-        return mir_->toAsmJSLoadFuncPtr();
-    }
-    const LAllocation* index() {
-        return getOperand(0);
-    }
-};
-
-// Math.random().
-class LRandom : public LCallInstructionHelper<1, 0, 2>
-{
-  public:
-    LIR_HEADER(Random)
-    LRandom(const LDefinition& temp, const LDefinition& temp2) {
-        setTemp(0, temp);
-        setTemp(1, temp2);
-    }
-    const LDefinition* temp() {
-        return getTemp(0);
-    }
-    const LDefinition* temp2() {
-        return getTemp(1);
-    }
-};
-
 } // namespace jit
 } // namespace js
 
 #endif /* jit_mips32_LIR_mips32_h */
--- a/js/src/jit/mips32/MacroAssembler-mips32.cpp
+++ b/js/src/jit/mips32/MacroAssembler-mips32.cpp
@@ -42,26 +42,25 @@ MacroAssemblerMIPSCompat::convertInt32To
 {
     as_mtc1(src, dest);
     as_cvtdw(dest, dest);
 }
 
 void
 MacroAssemblerMIPSCompat::convertInt32ToDouble(const Address& src, FloatRegister dest)
 {
-    ma_lw(ScratchRegister, src);
-    as_mtc1(ScratchRegister, dest);
+    ma_ls(dest, src);
     as_cvtdw(dest, dest);
 }
 
 void
 MacroAssemblerMIPSCompat::convertInt32ToDouble(const BaseIndex& src, FloatRegister dest)
 {
-    computeScaledAddress(src, SecondScratchReg);
-    convertInt32ToDouble(Address(SecondScratchReg, src.offset), dest);
+    computeScaledAddress(src, ScratchRegister);
+    convertInt32ToDouble(Address(ScratchRegister, src.offset), dest);
 }
 
 void
 MacroAssemblerMIPSCompat::convertUInt32ToDouble(Register src, FloatRegister dest)
 {
     // We use SecondScratchDoubleReg because MacroAssembler::loadFromTypedArray
     // calls with ScratchDoubleReg as dest.
     MOZ_ASSERT(dest != SecondScratchDoubleReg);
@@ -198,18 +197,17 @@ MacroAssemblerMIPSCompat::convertInt32To
 {
     as_mtc1(src, dest);
     as_cvtsw(dest, dest);
 }
 
 void
 MacroAssemblerMIPSCompat::convertInt32ToFloat32(const Address& src, FloatRegister dest)
 {
-    ma_lw(ScratchRegister, src);
-    as_mtc1(ScratchRegister, dest);
+    ma_ls(dest, src);
     as_cvtsw(dest, dest);
 }
 
 void
 MacroAssemblerMIPSCompat::addDouble(FloatRegister src, FloatRegister dest)
 {
     as_addd(dest, dest, src);
 }
@@ -261,17 +259,17 @@ MacroAssemblerMIPS::ma_move(Register rd,
 {
     as_or(rd, rs, zero);
 }
 
 void
 MacroAssemblerMIPS::ma_li(Register dest, ImmGCPtr ptr)
 {
     writeDataRelocation(ptr);
-    ma_liPatchable(dest, Imm32(uintptr_t(ptr.value)));
+    ma_liPatchable(dest, ImmPtr(ptr.value));
 }
 
 void
 MacroAssemblerMIPS::ma_li(Register dest, AbsoluteLabel* label)
 {
     MOZ_ASSERT(!label->bound());
     // Thread the patch list through the unpatched address word in the
     // instruction stream.
@@ -290,32 +288,43 @@ MacroAssemblerMIPS::ma_li(Register dest,
     } else if (Imm16::Lower(imm).encode() == 0) {
         as_lui(dest, Imm16::Upper(imm).encode());
     } else {
         as_lui(dest, Imm16::Upper(imm).encode());
         as_ori(dest, dest, Imm16::Lower(imm).encode());
     }
 }
 
+void
+MacroAssemblerMIPS::ma_li(Register dest, ImmWord imm)
+{
+    ma_li(dest, Imm32(uint32_t(imm.value)));
+}
 
 // This method generates lui and ori instruction pair that can be modified by
 // UpdateLuiOriValue, either during compilation (eg. Assembler::bind), or
 // during execution (eg. jit::PatchJump).
 void
 MacroAssemblerMIPS::ma_liPatchable(Register dest, Imm32 imm)
 {
     m_buffer.ensureSpace(2 * sizeof(uint32_t));
     as_lui(dest, Imm16::Upper(imm).encode());
     as_ori(dest, dest, Imm16::Lower(imm).encode());
 }
 
 void
 MacroAssemblerMIPS::ma_liPatchable(Register dest, ImmPtr imm)
 {
-    return ma_liPatchable(dest, Imm32(int32_t(imm.value)));
+    ma_liPatchable(dest, ImmWord(uintptr_t(imm.value)));
+}
+
+void
+MacroAssemblerMIPS::ma_liPatchable(Register dest, ImmWord imm)
+{
+    ma_liPatchable(dest, Imm32(int32_t(imm.value)));
 }
 
 // Shifts
 void
 MacroAssemblerMIPS::ma_sll(Register rd, Register rt, Imm32 shift)
 {
     as_sll(rd, rt, shift.value % 32);
 }
@@ -1551,17 +1560,17 @@ MacroAssemblerMIPSCompat::move32(Registe
 void
 MacroAssemblerMIPSCompat::movePtr(Register src, Register dest)
 {
     ma_move(dest, src);
 }
 void
 MacroAssemblerMIPSCompat::movePtr(ImmWord imm, Register dest)
 {
-    ma_li(dest, Imm32(imm.value));
+    ma_li(dest, imm);
 }
 
 void
 MacroAssemblerMIPSCompat::movePtr(ImmGCPtr imm, Register dest)
 {
     ma_li(dest, imm);
 }
 
@@ -1569,17 +1578,17 @@ void
 MacroAssemblerMIPSCompat::movePtr(ImmPtr imm, Register dest)
 {
     movePtr(ImmWord(uintptr_t(imm.value)), dest);
 }
 void
 MacroAssemblerMIPSCompat::movePtr(AsmJSImmPtr imm, Register dest)
 {
     append(AsmJSAbsoluteLink(CodeOffsetLabel(nextOffset().getOffset()), imm.kind()));
-    ma_liPatchable(dest, Imm32(-1));
+    ma_liPatchable(dest, ImmWord(-1));
 }
 
 void
 MacroAssemblerMIPSCompat::load8ZeroExtend(const Address& address, Register dest)
 {
     ma_load(dest, address, SizeByte, ZeroExtend);
 }
 
@@ -1623,55 +1632,63 @@ void
 MacroAssemblerMIPSCompat::load16SignExtend(const BaseIndex& src, Register dest)
 {
     ma_load(dest, src, SizeHalfWord, SignExtend);
 }
 
 void
 MacroAssemblerMIPSCompat::load32(const Address& address, Register dest)
 {
-    ma_lw(dest, address);
+    ma_load(dest, address, SizeWord);
 }
 
 void
 MacroAssemblerMIPSCompat::load32(const BaseIndex& address, Register dest)
 {
     ma_load(dest, address, SizeWord);
 }
 
 void
 MacroAssemblerMIPSCompat::load32(AbsoluteAddress address, Register dest)
 {
-    ma_li(ScratchRegister, Imm32((uint32_t)address.addr));
-    as_lw(dest, ScratchRegister, 0);
+    movePtr(ImmPtr(address.addr), ScratchRegister);
+    load32(Address(ScratchRegister, 0), dest);
+}
+
+void
+MacroAssemblerMIPSCompat::load32(AsmJSAbsoluteAddress address, Register dest)
+{
+    movePtr(AsmJSImmPtr(address.kind()), ScratchRegister);
+    load32(Address(ScratchRegister, 0), dest);
 }
 
 void
 MacroAssemblerMIPSCompat::loadPtr(const Address& address, Register dest)
 {
-    ma_lw(dest, address);
+    ma_load(dest, address, SizeWord);
 }
 
 void
 MacroAssemblerMIPSCompat::loadPtr(const BaseIndex& src, Register dest)
 {
-    load32(src, dest);
+    ma_load(dest, src, SizeWord);
 }
 
 void
 MacroAssemblerMIPSCompat::loadPtr(AbsoluteAddress address, Register dest)
 {
-    ma_li(ScratchRegister, Imm32((uint32_t)address.addr));
-    as_lw(dest, ScratchRegister, 0);
-}
+    movePtr(ImmPtr(address.addr), ScratchRegister);
+    loadPtr(Address(ScratchRegister, 0), dest);
+}
+
 void
 MacroAssemblerMIPSCompat::loadPtr(AsmJSAbsoluteAddress address, Register dest)
 {
     movePtr(AsmJSImmPtr(address.kind()), ScratchRegister);
-    loadPtr(Address(ScratchRegister, 0x0), dest);
+    loadPtr(Address(ScratchRegister, 0), dest);
 }
 
 void
 MacroAssemblerMIPSCompat::loadPrivate(const Address& address, Register dest)
 {
     ma_lw(dest, Address(address.base, address.offset + PAYLOAD_OFFSET));
 }
 
@@ -1763,30 +1780,31 @@ void
 MacroAssemblerMIPSCompat::store16(Register src, const BaseIndex& address)
 {
     ma_store(src, address, SizeHalfWord);
 }
 
 void
 MacroAssemblerMIPSCompat::store32(Register src, AbsoluteAddress address)
 {
-    storePtr(src, address);
+    movePtr(ImmPtr(address.addr), ScratchRegister);
+    store32(src, Address(ScratchRegister, 0));
 }
 
 void
 MacroAssemblerMIPSCompat::store32(Register src, const Address& address)
 {
-    storePtr(src, address);
+    ma_store(src, address, SizeWord);
 }
 
 void
 MacroAssemblerMIPSCompat::store32(Imm32 src, const Address& address)
 {
     move32(src, SecondScratchReg);
-    storePtr(SecondScratchReg, address);
+    ma_store(SecondScratchReg, address, SizeWord);
 }
 
 void
 MacroAssemblerMIPSCompat::store32(Imm32 imm, const BaseIndex& dest)
 {
     ma_store(imm, dest, SizeWord);
 }
 
@@ -1795,18 +1813,18 @@ MacroAssemblerMIPSCompat::store32(Regist
 {
     ma_store(src, dest, SizeWord);
 }
 
 template <typename T>
 void
 MacroAssemblerMIPSCompat::storePtr(ImmWord imm, T address)
 {
-    ma_li(SecondScratchReg, Imm32(imm.value));
-    ma_sw(SecondScratchReg, address);
+    ma_li(SecondScratchReg, imm);
+    ma_store(SecondScratchReg, address, SizeWord);
 }
 
 template void MacroAssemblerMIPSCompat::storePtr<Address>(ImmWord imm, Address address);
 template void MacroAssemblerMIPSCompat::storePtr<BaseIndex>(ImmWord imm, BaseIndex address);
 
 template <typename T>
 void
 MacroAssemblerMIPSCompat::storePtr(ImmPtr imm, T address)
@@ -1816,40 +1834,39 @@ MacroAssemblerMIPSCompat::storePtr(ImmPt
 
 template void MacroAssemblerMIPSCompat::storePtr<Address>(ImmPtr imm, Address address);
 template void MacroAssemblerMIPSCompat::storePtr<BaseIndex>(ImmPtr imm, BaseIndex address);
 
 template <typename T>
 void
 MacroAssemblerMIPSCompat::storePtr(ImmGCPtr imm, T address)
 {
-    ma_li(SecondScratchReg, imm);
-    ma_sw(SecondScratchReg, address);
+    storePtr(ImmWord(uintptr_t(imm.value)), address);
 }
 
 template void MacroAssemblerMIPSCompat::storePtr<Address>(ImmGCPtr imm, Address address);
 template void MacroAssemblerMIPSCompat::storePtr<BaseIndex>(ImmGCPtr imm, BaseIndex address);
 
 void
 MacroAssemblerMIPSCompat::storePtr(Register src, const Address& address)
 {
-    ma_sw(src, address);
+    ma_store(src, address, SizeWord);
 }
 
 void
 MacroAssemblerMIPSCompat::storePtr(Register src, const BaseIndex& address)
 {
     ma_store(src, address, SizeWord);
 }
 
 void
 MacroAssemblerMIPSCompat::storePtr(Register src, AbsoluteAddress dest)
 {
-    ma_li(ScratchRegister, Imm32((uint32_t)dest.addr));
-    as_sw(src, ScratchRegister, 0);
+    movePtr(ImmPtr(dest.addr), ScratchRegister);
+    storePtr(src, Address(ScratchRegister, 0));
 }
 
 // Note: this function clobbers the input register.
 void
 MacroAssembler::clampDoubleToUint8(FloatRegister input, Register output)
 {
     MOZ_ASSERT(input != ScratchDoubleReg);
     Label positive, done;
@@ -2799,17 +2816,17 @@ MacroAssemblerMIPSCompat::tagValue(JSVal
     if (payload != dest.payloadReg())
         ma_move(dest.payloadReg(), payload);
 }
 
 void
 MacroAssemblerMIPSCompat::pushValue(ValueOperand val)
 {
     // Allocate stack slots for type and payload. One for each.
-    ma_subu(StackPointer, StackPointer, Imm32(sizeof(Value)));
+    subPtr(Imm32(sizeof(Value)), StackPointer);
     // Store type and payload.
     storeValue(val, Address(StackPointer, 0));
 }
 
 void
 MacroAssemblerMIPSCompat::pushValue(const Address& addr)
 {
     // Allocate stack slots for type and payload. One for each.
@@ -2969,79 +2986,79 @@ MacroAssembler::restoreFrameAlignmentFor
         freeStack(aic.alignmentPadding);
 }
 
 void
 MacroAssemblerMIPSCompat::handleFailureWithHandlerTail(void* handler)
 {
     // Reserve space for exception information.
     int size = (sizeof(ResumeFromException) + ABIStackAlignment) & ~(ABIStackAlignment - 1);
-    ma_subu(StackPointer, StackPointer, Imm32(size));
+    subPtr(Imm32(size), StackPointer);
     ma_move(a0, StackPointer); // Use a0 since it is a first function argument
 
     // Call the handler.
     asMasm().setupUnalignedABICall(a1);
     asMasm().passABIArg(a0);
     asMasm().callWithABI(handler);
 
     Label entryFrame;
     Label catch_;
     Label finally;
     Label return_;
     Label bailout;
 
     // Already clobbered a0, so use it...
-    ma_lw(a0, Address(StackPointer, offsetof(ResumeFromException, kind)));
+    load32(Address(StackPointer, offsetof(ResumeFromException, kind)), a0);
     branch32(Assembler::Equal, a0, Imm32(ResumeFromException::RESUME_ENTRY_FRAME), &entryFrame);
     branch32(Assembler::Equal, a0, Imm32(ResumeFromException::RESUME_CATCH), &catch_);
     branch32(Assembler::Equal, a0, Imm32(ResumeFromException::RESUME_FINALLY), &finally);
     branch32(Assembler::Equal, a0, Imm32(ResumeFromException::RESUME_FORCED_RETURN), &return_);
     branch32(Assembler::Equal, a0, Imm32(ResumeFromException::RESUME_BAILOUT), &bailout);
 
     breakpoint(); // Invalid kind.
 
     // No exception handler. Load the error value, load the new stack pointer
     // and return from the entry frame.
     bind(&entryFrame);
     moveValue(MagicValue(JS_ION_ERROR), JSReturnOperand);
-    ma_lw(StackPointer, Address(StackPointer, offsetof(ResumeFromException, stackPointer)));
+    loadPtr(Address(StackPointer, offsetof(ResumeFromException, stackPointer)), StackPointer);
 
     // We're going to be returning by the ion calling convention
     ma_pop(ra);
     as_jr(ra);
     as_nop();
 
     // If we found a catch handler, this must be a baseline frame. Restore
     // state and jump to the catch block.
     bind(&catch_);
-    ma_lw(a0, Address(StackPointer, offsetof(ResumeFromException, target)));
-    ma_lw(BaselineFrameReg, Address(StackPointer, offsetof(ResumeFromException, framePointer)));
-    ma_lw(StackPointer, Address(StackPointer, offsetof(ResumeFromException, stackPointer)));
+    loadPtr(Address(StackPointer, offsetof(ResumeFromException, target)), a0);
+    loadPtr(Address(StackPointer, offsetof(ResumeFromException, framePointer)), BaselineFrameReg);
+    loadPtr(Address(StackPointer, offsetof(ResumeFromException, stackPointer)), StackPointer);
     jump(a0);
 
     // If we found a finally block, this must be a baseline frame. Push
     // two values expected by JSOP_RETSUB: BooleanValue(true) and the
     // exception.
     bind(&finally);
     ValueOperand exception = ValueOperand(a1, a2);
     loadValue(Address(sp, offsetof(ResumeFromException, exception)), exception);
 
-    ma_lw(a0, Address(sp, offsetof(ResumeFromException, target)));
-    ma_lw(BaselineFrameReg, Address(sp, offsetof(ResumeFromException, framePointer)));
-    ma_lw(sp, Address(sp, offsetof(ResumeFromException, stackPointer)));
+    loadPtr(Address(sp, offsetof(ResumeFromException, target)), a0);
+    loadPtr(Address(sp, offsetof(ResumeFromException, framePointer)), BaselineFrameReg);
+    loadPtr(Address(sp, offsetof(ResumeFromException, stackPointer)), sp);
 
     pushValue(BooleanValue(true));
     pushValue(exception);
     jump(a0);
 
     // Only used in debug mode. Return BaselineFrame->returnValue() to the
     // caller.
     bind(&return_);
-    ma_lw(BaselineFrameReg, Address(StackPointer, offsetof(ResumeFromException, framePointer)));
-    ma_lw(StackPointer, Address(StackPointer, offsetof(ResumeFromException, stackPointer)));
+    loadPtr(Address(StackPointer, offsetof(ResumeFromException, framePointer)), BaselineFrameReg);
+    loadPtr(Address(StackPointer, offsetof(ResumeFromException, stackPointer)), StackPointer);
     loadValue(Address(BaselineFrameReg, BaselineFrame::reverseOffsetOfReturnValue()),
               JSReturnOperand);
     ma_move(StackPointer, BaselineFrameReg);
     pop(BaselineFrameReg);
 
     // If profiling is enabled, then update the lastProfilingFrame to refer to caller
     // frame before returning.
     {
@@ -3053,19 +3070,19 @@ MacroAssemblerMIPSCompat::handleFailureW
         bind(&skipProfilingInstrumentation);
     }
 
     ret();
 
     // If we are bailing out to baseline to handle an exception, jump to
     // the bailout tail stub.
     bind(&bailout);
-    ma_lw(a2, Address(sp, offsetof(ResumeFromException, bailoutInfo)));
+    loadPtr(Address(sp, offsetof(ResumeFromException, bailoutInfo)), a2);
     ma_li(ReturnReg, Imm32(BAILOUT_RETURN_OK));
-    ma_lw(a1, Address(sp, offsetof(ResumeFromException, target)));
+    loadPtr(Address(sp, offsetof(ResumeFromException, target)), a1);
     jump(a1);
 }
 
 CodeOffsetLabel
 MacroAssemblerMIPSCompat::toggledJump(Label* label)
 {
     CodeOffsetLabel ret(nextOffset().getOffset());
     ma_b(label);
@@ -3220,17 +3237,17 @@ MacroAssembler::Push(const Imm32 imm)
     ma_li(ScratchRegister, imm);
     ma_push(ScratchRegister);
     adjustFrame(sizeof(intptr_t));
 }
 
 void
 MacroAssembler::Push(const ImmWord imm)
 {
-    ma_li(ScratchRegister, Imm32(imm.value));
+    ma_li(ScratchRegister, imm);
     ma_push(ScratchRegister);
     adjustFrame(sizeof(intptr_t));
 }
 
 void
 MacroAssembler::Push(const ImmPtr imm)
 {
     Push(ImmWord(uintptr_t(imm.value)));
@@ -3264,17 +3281,17 @@ MacroAssembler::Pop(const ValueOperand& 
     popValue(val);
     framePushed_ -= sizeof(Value);
 }
 
 void
 MacroAssembler::reserveStack(uint32_t amount)
 {
     if (amount)
-        ma_subu(StackPointer, StackPointer, Imm32(amount));
+        subPtr(Imm32(amount), StackPointer);
     adjustFrame(amount);
 }
 
 // ===============================================================
 // Simple call functions.
 
 void
 MacroAssembler::call(Register reg)
@@ -3310,53 +3327,53 @@ MacroAssembler::call(ImmPtr target)
     ma_call(target);
 }
 
 void
 MacroAssembler::call(JitCode* c)
 {
     BufferOffset bo = m_buffer.nextOffset();
     addPendingJump(bo, ImmPtr(c->raw()), Relocation::JITCODE);
-    ma_liPatchable(ScratchRegister, Imm32((uint32_t)c->raw()));
+    ma_liPatchable(ScratchRegister, ImmPtr(c->raw()));
     callJitNoProfiler(ScratchRegister);
 }
 
 void
 MacroAssembler::callAndPushReturnAddress(Register callee)
 {
     // Push return address during jalr delay slot.
-    as_addiu(StackPointer, StackPointer, -sizeof(intptr_t));
+    subPtr(Imm32(sizeof(intptr_t)), StackPointer);
     as_jalr(callee);
-    as_sw(ra, StackPointer, 0);
+    storePtr(ra, Address(StackPointer, 0));
 }
 
 void
 MacroAssembler::callAndPushReturnAddress(Label* label)
 {
     // Push return address during bal delay slot.
-    as_addiu(StackPointer, StackPointer, -sizeof(intptr_t));
+    subPtr(Imm32(sizeof(intptr_t)), StackPointer);
     ma_bal(label, DontFillDelaySlot);
-    as_sw(ra, StackPointer, 0);
+    storePtr(ra, Address(StackPointer, 0));
 }
 
 // ===============================================================
 // ABI function calls.
 
 void
 MacroAssembler::setupUnalignedABICall(Register scratch)
 {
     setupABICall();
     dynamicAlignment_ = true;
 
     ma_move(scratch, StackPointer);
 
     // Force sp to be aligned
-    ma_subu(StackPointer, StackPointer, Imm32(sizeof(uint32_t)));
+    subPtr(Imm32(sizeof(uintptr_t)), StackPointer);
     ma_and(StackPointer, StackPointer, Imm32(~(ABIStackAlignment - 1)));
-    as_sw(scratch, StackPointer, 0);
+    storePtr(scratch, Address(StackPointer, 0));
 }
 
 void
 MacroAssembler::callWithABIPre(uint32_t* stackAdjust, bool callFromAsmJS)
 {
     MOZ_ASSERT(inCall_);
     uint32_t stackForCall = abiArgs_.stackBytesConsumedSoFar();
 
@@ -3370,19 +3387,19 @@ MacroAssembler::callWithABIPre(uint32_t*
         stackForCall += ComputeByteAlignment(stackForCall + framePushed() + alignmentAtPrologue,
                                              ABIStackAlignment);
     }
 
     *stackAdjust = stackForCall;
     reserveStack(stackForCall);
 
     // Save $ra because call is going to clobber it. Restore it in
-    // callWithABIPost. NOTE: This is needed for calls from BaselineIC.
+    // callWithABIPost. NOTE: This is needed for calls from SharedIC.
     // Maybe we can do this differently.
-    ma_sw(ra, Address(StackPointer, stackForCall - sizeof(intptr_t)));
+    storePtr(ra, Address(StackPointer, stackForCall - sizeof(intptr_t)));
 
     // Position all arguments.
     {
         enoughMemory_ = enoughMemory_ && moveResolver_.resolve();
         if (!enoughMemory_)
             return;
 
         MoveEmitter emitter(*this);
@@ -3392,21 +3409,21 @@ MacroAssembler::callWithABIPre(uint32_t*
 
     assertStackAlignment(ABIStackAlignment);
 }
 
 void
 MacroAssembler::callWithABIPost(uint32_t stackAdjust, MoveOp::Type result)
 {
     // Restore ra value (as stored in callWithABIPre()).
-    ma_lw(ra, Address(StackPointer, stackAdjust - sizeof(intptr_t)));
+    loadPtr(Address(StackPointer, stackAdjust - sizeof(intptr_t)), ra);
 
     if (dynamicAlignment_) {
         // Restore sp value from stack (as stored in setupUnalignedABICall()).
-        ma_lw(StackPointer, Address(StackPointer, stackAdjust));
+        loadPtr(Address(StackPointer, stackAdjust), StackPointer);
         // Use adjustFrame instead of freeStack because we already restored sp.
         adjustFrame(-stackAdjust);
     } else {
         freeStack(stackAdjust);
     }
 
 #ifdef DEBUG
     MOZ_ASSERT(inCall_);
@@ -3426,17 +3443,17 @@ MacroAssembler::callWithABINoProfiler(Re
     call(t9);
     callWithABIPost(stackAdjust, result);
 }
 
 void
 MacroAssembler::callWithABINoProfiler(const Address& fun, MoveOp::Type result)
 {
     // Load the callee in t9, as above.
-    ma_lw(t9, Address(fun.base, fun.offset));
+    loadPtr(Address(fun.base, fun.offset), t9);
     uint32_t stackAdjust;
     callWithABIPre(&stackAdjust);
     call(t9);
     callWithABIPost(stackAdjust, result);
 }
 
 // ===============================================================
 // Jit Frames.
--- a/js/src/jit/mips32/MacroAssembler-mips32.h
+++ b/js/src/jit/mips32/MacroAssembler-mips32.h
@@ -83,17 +83,19 @@ class MacroAssemblerMIPS : public Assemb
     void ma_move(Register rd, Register rs);
 
     void ma_li(Register dest, ImmGCPtr ptr);
 
     void ma_li(Register dest, AbsoluteLabel* label);
 
     void ma_li(Register dest, Imm32 imm);
     void ma_liPatchable(Register dest, Imm32 imm);
+    void ma_li(Register dest, ImmWord imm);
     void ma_liPatchable(Register dest, ImmPtr imm);
+    void ma_liPatchable(Register dest, ImmWord imm);
 
     // Shift operations
     void ma_sll(Register rd, Register rt, Imm32 shift);
     void ma_srl(Register rd, Register rt, Imm32 shift);
     void ma_sra(Register rd, Register rt, Imm32 shift);
     void ma_ror(Register rd, Register rt, Imm32 shift);
     void ma_rol(Register rd, Register rt, Imm32 shift);
 
@@ -175,17 +177,17 @@ class MacroAssemblerMIPS : public Assemb
 
     void ma_pop(Register r);
     void ma_push(Register r);
 
     // branches when done from within mips-specific code
     void ma_b(Register lhs, Register rhs, Label* l, Condition c, JumpKind jumpKind = LongJump);
     void ma_b(Register lhs, Imm32 imm, Label* l, Condition c, JumpKind jumpKind = LongJump);
     void ma_b(Register lhs, ImmPtr imm, Label* l, Condition c, JumpKind jumpKind = LongJump) {
-        ma_b(lhs, Imm32(uint32_t(imm.value)), l, c, jumpKind);
+        ma_b(lhs, ImmWord(uintptr_t(imm.value)), l, c, jumpKind);
     }
     void ma_b(Register lhs, ImmGCPtr imm, Label* l, Condition c, JumpKind jumpKind = LongJump) {
         MOZ_ASSERT(lhs != ScratchRegister);
         ma_li(ScratchRegister, imm);
         ma_b(lhs, ScratchRegister, l, c, jumpKind);
     }
     void ma_b(Register lhs, ImmWord imm, Label* l, Condition c, JumpKind jumpKind = LongJump)
     {
@@ -196,17 +198,17 @@ class MacroAssemblerMIPS : public Assemb
         ma_b(addr, Imm32(uint32_t(imm.value)), l, c, jumpKind);
     }
 
     void ma_b(Register lhs, Address addr, Label* l, Condition c, JumpKind jumpKind = LongJump);
     void ma_b(Address addr, Imm32 imm, Label* l, Condition c, JumpKind jumpKind = LongJump);
     void ma_b(Address addr, ImmGCPtr imm, Label* l, Condition c, JumpKind jumpKind = LongJump);
     void ma_b(Address addr, Register rhs, Label* l, Condition c, JumpKind jumpKind = LongJump) {
         MOZ_ASSERT(rhs != ScratchRegister);
-        ma_lw(ScratchRegister, addr);
+        ma_load(ScratchRegister, addr, SizeWord);
         ma_b(ScratchRegister, rhs, l, c, jumpKind);
     }
 
     void ma_b(Label* l, JumpKind jumpKind = LongJump);
     void ma_bal(Label* l, DelaySlotFill delaySlotFill = FillDelaySlot);
 
     // fp instructions
     void ma_lis(FloatRegister dest, float value);
@@ -317,44 +319,44 @@ class MacroAssemblerMIPSCompat : public 
 
     void computeEffectiveAddress(const Address& address, Register dest) {
         ma_addu(dest, address.base, Imm32(address.offset));
     }
 
     void computeEffectiveAddress(const BaseIndex& address, Register dest) {
         computeScaledAddress(address, dest);
         if (address.offset) {
-            ma_addu(dest, dest, Imm32(address.offset));
+            addPtr(Imm32(address.offset), dest);
         }
     }
 
     void j(Label* dest) {
         ma_b(dest);
     }
 
     void mov(Register src, Register dest) {
-        as_or(dest, src, zero);
+        as_ori(dest, src, 0);
     }
     void mov(ImmWord imm, Register dest) {
-        ma_li(dest, Imm32(imm.value));
+        ma_li(dest, imm);
     }
     void mov(ImmPtr imm, Register dest) {
         mov(ImmWord(uintptr_t(imm.value)), dest);
     }
     void mov(Register src, Address dest) {
         MOZ_CRASH("NYI-IC");
     }
     void mov(Address src, Register dest) {
         MOZ_CRASH("NYI-IC");
     }
 
     void branch(JitCode* c) {
         BufferOffset bo = m_buffer.nextOffset();
         addPendingJump(bo, ImmPtr(c->raw()), Relocation::JITCODE);
-        ma_liPatchable(ScratchRegister, Imm32((uint32_t)c->raw()));
+        ma_liPatchable(ScratchRegister, ImmPtr(c->raw()));
         as_jr(ScratchRegister);
         as_nop();
     }
     void branch(const Register reg) {
         as_jr(reg);
         as_nop();
     }
     void nop() {
@@ -362,35 +364,35 @@ class MacroAssemblerMIPSCompat : public 
     }
     void ret() {
         ma_pop(ra);
         as_jr(ra);
         as_nop();
     }
     void retn(Imm32 n) {
         // pc <- [sp]; sp += n
-        ma_lw(ra, Address(StackPointer, 0));
-        ma_addu(StackPointer, StackPointer, n);
+        loadPtr(Address(StackPointer, 0), ra);
+        addPtr(n, StackPointer);
         as_jr(ra);
         as_nop();
     }
     void push(Imm32 imm) {
         ma_li(ScratchRegister, imm);
         ma_push(ScratchRegister);
     }
     void push(ImmWord imm) {
-        ma_li(ScratchRegister, Imm32(imm.value));
+        ma_li(ScratchRegister, imm);
         ma_push(ScratchRegister);
     }
     void push(ImmGCPtr imm) {
         ma_li(ScratchRegister, imm);
         ma_push(ScratchRegister);
     }
     void push(const Address& address) {
-        ma_lw(ScratchRegister, address);
+        loadPtr(address, ScratchRegister);
         ma_push(ScratchRegister);
     }
     void push(Register reg) {
         ma_push(reg);
     }
     void push(FloatRegister reg) {
         ma_push(reg);
     }
@@ -418,32 +420,32 @@ class MacroAssemblerMIPSCompat : public 
     CodeOffsetLabel pushWithPatch(ImmWord imm) {
         CodeOffsetLabel label = movWithPatch(imm, ScratchRegister);
         ma_push(ScratchRegister);
         return label;
     }
 
     CodeOffsetLabel movWithPatch(ImmWord imm, Register dest) {
         CodeOffsetLabel label = CodeOffsetLabel(currentOffset());
-        ma_liPatchable(dest, Imm32(imm.value));
+        ma_liPatchable(dest, imm);
         return label;
     }
     CodeOffsetLabel movWithPatch(ImmPtr imm, Register dest) {
         return movWithPatch(ImmWord(uintptr_t(imm.value)), dest);
     }
 
     void jump(Label* label) {
         ma_b(label);
     }
     void jump(Register reg) {
         as_jr(reg);
         as_nop();
     }
     void jump(const Address& address) {
-        ma_lw(ScratchRegister, address);
+        loadPtr(address, ScratchRegister);
         as_jr(ScratchRegister);
         as_nop();
     }
 
     void jump(JitCode* code) {
         branch(code);
     }
 
@@ -550,29 +552,30 @@ class MacroAssemblerMIPSCompat : public 
     void branch32(Condition cond, const Operand& lhs, Imm32 rhs, Label* label) {
         if (lhs.getTag() == Operand::REG) {
             ma_b(lhs.toReg(), rhs, label, cond);
         } else {
             branch32(cond, lhs.toAddress(), rhs, label);
         }
     }
     void branch32(Condition cond, const Address& lhs, Register rhs, Label* label) {
-        ma_lw(ScratchRegister, lhs);
-        ma_b(ScratchRegister, rhs, label, cond);
+        load32(lhs, SecondScratchReg);
+        ma_b(SecondScratchReg, rhs, label, cond);
     }
     void branch32(Condition cond, const Address& lhs, Imm32 rhs, Label* label) {
-        ma_lw(SecondScratchReg, lhs);
+        load32(lhs, SecondScratchReg);
         ma_b(SecondScratchReg, rhs, label, cond);
     }
     void branch32(Condition cond, const BaseIndex& lhs, Imm32 rhs, Label* label) {
         load32(lhs, SecondScratchReg);
         ma_b(SecondScratchReg, rhs, label, cond);
     }
     void branchPtr(Condition cond, const Address& lhs, Register rhs, Label* label) {
-        branch32(cond, lhs, rhs, label);
+        loadPtr(lhs, SecondScratchReg);
+        ma_b(SecondScratchReg, rhs, label, cond);
     }
 
     void branchPrivatePtr(Condition cond, const Address& lhs, ImmPtr ptr, Label* label) {
         branchPtr(cond, lhs, ptr, label);
     }
 
     void branchPrivatePtr(Condition cond, const Address& lhs, Register ptr, Label* label) {
         branchPtr(cond, lhs, ptr, label);
@@ -644,55 +647,62 @@ class MacroAssemblerMIPSCompat : public 
             ma_b(ScratchRegister, ScratchRegister, label, cond);
         }
     }
     void branchTest32(Condition cond, Register lhs, Imm32 imm, Label* label) {
         ma_li(ScratchRegister, imm);
         branchTest32(cond, lhs, ScratchRegister, label);
     }
     void branchTest32(Condition cond, const Address& address, Imm32 imm, Label* label) {
-        ma_lw(SecondScratchReg, address);
+        load32(address, SecondScratchReg);
         branchTest32(cond, SecondScratchReg, imm, label);
     }
     void branchTest32(Condition cond, AbsoluteAddress address, Imm32 imm, Label* label) {
-        loadPtr(address, ScratchRegister);
+        load32(address, ScratchRegister);
         branchTest32(cond, ScratchRegister, imm, label);
     }
     void branchTestPtr(Condition cond, Register lhs, Register rhs, Label* label) {
-        branchTest32(cond, lhs, rhs, label);
+        MOZ_ASSERT(cond == Zero || cond == NonZero || cond == Signed || cond == NotSigned);
+        if (lhs == rhs) {
+            ma_b(lhs, rhs, label, cond);
+        } else {
+            as_and(ScratchRegister, lhs, rhs);
+            ma_b(ScratchRegister, ScratchRegister, label, cond);
+        }
     }
     void branchTestPtr(Condition cond, Register lhs, const Imm32 rhs, Label* label) {
-        branchTest32(cond, lhs, rhs, label);
+        ma_li(ScratchRegister, rhs);
+        branchTestPtr(cond, lhs, ScratchRegister, label);
     }
     void branchTestPtr(Condition cond, const Address& lhs, Imm32 imm, Label* label) {
-        branchTest32(cond, lhs, imm, label);
+        loadPtr(lhs, SecondScratchReg);
+        branchTestPtr(cond, SecondScratchReg, imm, label);
     }
     void branchPtr(Condition cond, Register lhs, Register rhs, Label* label) {
         ma_b(lhs, rhs, label, cond);
     }
     void branchPtr(Condition cond, Register lhs, ImmGCPtr ptr, Label* label) {
-        ma_li(ScratchRegister, ptr);
-        ma_b(lhs, ScratchRegister, label, cond);
+        ma_b(lhs, ptr, label, cond);
     }
     void branchPtr(Condition cond, Register lhs, ImmWord imm, Label* label) {
-        ma_b(lhs, Imm32(imm.value), label, cond);
+        ma_b(lhs, imm, label, cond);
     }
     void branchPtr(Condition cond, Register lhs, ImmPtr imm, Label* label) {
-        branchPtr(cond, lhs, ImmWord(uintptr_t(imm.value)), label);
+        ma_b(lhs, imm, label, cond);
     }
     void branchPtr(Condition cond, Register lhs, AsmJSImmPtr imm, Label* label) {
-        movePtr(imm, ScratchRegister);
-        branchPtr(cond, lhs, ScratchRegister, label);
+        movePtr(imm, SecondScratchReg);
+        ma_b(lhs, SecondScratchReg, label, cond);
     }
     void branchPtr(Condition cond, Register lhs, Imm32 imm, Label* label) {
         ma_b(lhs, imm, label, cond);
     }
     void decBranchPtr(Condition cond, Register lhs, Imm32 imm, Label* label) {
         subPtr(imm, lhs);
-        branch32(cond, lhs, Imm32(0), label);
+        branchPtr(cond, lhs, Imm32(0), label);
     }
 
     // higher level tag testing code
     Operand ToPayload(Operand base);
     Address ToPayload(Address base) {
         return ToPayload(Operand(base)).toAddress();
     }
 
@@ -726,53 +736,51 @@ class MacroAssemblerMIPSCompat : public 
         movePtr(ptr, ScratchRegister);
         Label skipJump;
         ma_b(SecondScratchReg, ScratchRegister, &skipJump, InvertCondition(cond), ShortJump);
         CodeOffsetJump off = jumpWithPatch(label);
         bind(&skipJump);
         return off;
     }
     void branchPtr(Condition cond, Address addr, ImmGCPtr ptr, Label* label) {
-        ma_lw(SecondScratchReg, addr);
-        ma_li(ScratchRegister, ptr);
-        ma_b(SecondScratchReg, ScratchRegister, label, cond);
+        loadPtr(addr, SecondScratchReg);
+        ma_b(SecondScratchReg, ptr, label, cond);
     }
 
     void branchPtr(Condition cond, Address addr, ImmWord ptr, Label* label) {
-        ma_lw(SecondScratchReg, addr);
-        ma_b(SecondScratchReg, Imm32(ptr.value), label, cond);
+        loadPtr(addr, SecondScratchReg);
+        ma_b(SecondScratchReg, ptr, label, cond);
     }
     void branchPtr(Condition cond, Address addr, ImmPtr ptr, Label* label) {
-        branchPtr(cond, addr, ImmWord(uintptr_t(ptr.value)), label);
+        loadPtr(addr, SecondScratchReg);
+        ma_b(SecondScratchReg, ptr, label, cond);
     }
     void branchPtr(Condition cond, AbsoluteAddress addr, Register ptr, Label* label) {
-        loadPtr(addr, ScratchRegister);
-        ma_b(ScratchRegister, ptr, label, cond);
+        loadPtr(addr, SecondScratchReg);
+        ma_b(SecondScratchReg, ptr, label, cond);
     }
     void branchPtr(Condition cond, AbsoluteAddress addr, ImmWord ptr, Label* label) {
-        loadPtr(addr, ScratchRegister);
-        ma_b(ScratchRegister, Imm32(ptr.value), label, cond);
+        loadPtr(addr, SecondScratchReg);
+        ma_b(SecondScratchReg, ptr, label, cond);
     }
-    void branchPtr(Condition cond, AsmJSAbsoluteAddress addr, Register ptr,
-                   Label* label) {
-        loadPtr(addr, ScratchRegister);
-        ma_b(ScratchRegister, ptr, label, cond);
+    void branchPtr(Condition cond, AsmJSAbsoluteAddress addr, Register ptr, Label* label) {
+        loadPtr(addr, SecondScratchReg);
+        ma_b(SecondScratchReg, ptr, label, cond);
     }
     void branch32(Condition cond, AbsoluteAddress lhs, Imm32 rhs, Label* label) {
-        loadPtr(lhs, SecondScratchReg); // ma_b might use scratch
+        load32(lhs, SecondScratchReg);
         ma_b(SecondScratchReg, rhs, label, cond);
     }
     void branch32(Condition cond, AbsoluteAddress lhs, Register rhs, Label* label) {
-        loadPtr(lhs, ScratchRegister);
-        ma_b(ScratchRegister, rhs, label, cond);
+        load32(lhs, SecondScratchReg);
+        ma_b(SecondScratchReg, rhs, label, cond);
     }
-    void branch32(Condition cond, AsmJSAbsoluteAddress addr, Imm32 imm,
-                  Label* label) {
-        loadPtr(addr, ScratchRegister);
-        ma_b(ScratchRegister, imm, label, cond);
+    void branch32(Condition cond, AsmJSAbsoluteAddress addr, Imm32 imm, Label* label) {
+        load32(addr, SecondScratchReg);
+        ma_b(SecondScratchReg, imm, label, cond);
     }
 
     void loadUnboxedValue(Address address, MIRType type, AnyRegister dest) {
         if (dest.isFloat())
             loadInt32OrDouble(address, dest.fpu());
         else
             ma_lw(dest.gpr(), address);
     }
@@ -787,17 +795,17 @@ class MacroAssemblerMIPSCompat : public 
     template <typename T>
     void storeUnboxedValue(ConstantOrRegister value, MIRType valueType, const T& dest,
                            MIRType slotType);
 
     template <typename T>
     void storeUnboxedPayload(ValueOperand value, T address, size_t nbytes) {
         switch (nbytes) {
           case 4:
-            storePtr(value.payloadReg(), address);
+            store32(value.payloadReg(), address);
             return;
           case 1:
             store8(value.payloadReg(), address);
             return;
           default: MOZ_CRASH("Bad payload width");
         }
     }
 
@@ -1149,16 +1157,17 @@ class MacroAssemblerMIPSCompat : public 
     void load16SignExtend(const BaseIndex& src, Register dest);
 
     void load16ZeroExtend(const Address& address, Register dest);
     void load16ZeroExtend(const BaseIndex& src, Register dest);
 
     void load32(const Address& address, Register dest);
     void load32(const BaseIndex& address, Register dest);
     void load32(AbsoluteAddress address, Register dest);
+    void load32(AsmJSAbsoluteAddress address, Register dest);
 
     void loadPtr(const Address& address, Register dest);
     void loadPtr(const BaseIndex& src, Register dest);
     void loadPtr(AbsoluteAddress address, Register dest);
     void loadPtr(AsmJSAbsoluteAddress address, Register dest);
 
     void loadPrivate(const Address& address, Register dest);
 
@@ -1356,17 +1365,17 @@ class MacroAssemblerMIPSCompat : public 
     }
 
     void ma_storeImm(Imm32 imm, const Address& addr) {
         ma_sw(imm, addr);
     }
 
     BufferOffset ma_BoundsCheck(Register bounded) {
         BufferOffset bo = m_buffer.nextOffset();
-        ma_liPatchable(bounded, Imm32(0));
+        ma_liPatchable(bounded, ImmWord(0));
         return bo;
     }
 
     void moveFloat32(FloatRegister src, FloatRegister dest) {
         as_movs(dest, src);
     }
 
     void branchPtrInNurseryRange(Condition cond, Register ptr, Register temp, Label* label);
--- a/js/src/jit/mips32/Simulator-mips32.cpp
+++ b/js/src/jit/mips32/Simulator-mips32.cpp
@@ -1821,16 +1821,19 @@ typedef int64_t (*Prototype_General7)(in
                                       int32_t arg4, int32_t arg5, int32_t arg6);
 typedef int64_t (*Prototype_General8)(int32_t arg0, int32_t arg1, int32_t arg2, int32_t arg3,
                                       int32_t arg4, int32_t arg5, int32_t arg6, int32_t arg7);
 
 typedef double (*Prototype_Double_None)();
 typedef double (*Prototype_Double_Double)(double arg0);
 typedef double (*Prototype_Double_Int)(int32_t arg0);
 typedef int32_t (*Prototype_Int_Double)(double arg0);
+typedef int32_t (*Prototype_Int_DoubleIntInt)(double arg0, int32_t arg1, int32_t arg2);
+typedef int32_t (*Prototype_Int_IntDoubleIntInt)(int32_t arg0, double arg1, int32_t arg2,
+                                                 int32_t arg3);
 typedef float (*Prototype_Float32_Float32)(float arg0);
 
 typedef double (*Prototype_DoubleInt)(double arg0, int32_t arg1);
 typedef double (*Prototype_Double_IntDouble)(int32_t arg0, double arg1);
 typedef double (*Prototype_Double_DoubleDouble)(double arg0, double arg1);
 typedef int32_t (*Prototype_Int_IntDouble)(int32_t arg0, double arg1);
 
 typedef double (*Prototype_Double_DoubleDoubleDouble)(double arg0, double arg1, double arg2);
@@ -1940,16 +1943,30 @@ Simulator::softwareInterrupt(SimInstruct
             double dval0, dval1;
             int32_t ival;
             getFpArgs(&dval0, &dval1, &ival);
             Prototype_Int_Double target = reinterpret_cast<Prototype_Int_Double>(external);
             int32_t res = target(dval0);
             setRegister(v0, res);
             break;
           }
+          case Args_Int_DoubleIntInt: {
+            double dval = getFpuRegisterDouble(12);
+            Prototype_Int_DoubleIntInt target = reinterpret_cast<Prototype_Int_DoubleIntInt>(external);
+            int32_t res = target(dval, arg2, arg3);
+            setRegister(v0, res);
+            break;
+          }
+          case Args_Int_IntDoubleIntInt: {
+            double dval = getDoubleFromRegisterPair(a2);
+            Prototype_Int_IntDoubleIntInt target = reinterpret_cast<Prototype_Int_IntDoubleIntInt>(external);
+            int32_t res = target(arg0, dval, arg4, arg5);
+            setRegister(v0, res);
+            break;
+          }
           case Args_Double_Double: {
             double dval0, dval1;
             int32_t ival;
             getFpArgs(&dval0, &dval1, &ival);
             Prototype_Double_Double target = reinterpret_cast<Prototype_Double_Double>(external);
             double dresult = target(dval0);
             setCallResultDouble(dresult);
             break;
--- a/js/src/jit/shared/LIR-shared.h
+++ b/js/src/jit/shared/LIR-shared.h
@@ -3306,16 +3306,48 @@ class LFromCharCode : public LInstructio
         setOperand(0, code);
     }
 
     const LAllocation* code() {
         return this->getOperand(0);
     }
 };
 
+// Calculates sincos(x) and returns two values (sin/cos).
+class LSinCos : public LCallInstructionHelper<2, 1, 2>
+{
+  public:
+    LIR_HEADER(SinCos)
+
+    LSinCos(const LAllocation &input, const LDefinition &temp, const LDefinition &temp2)
+    {
+        setOperand(0, input);
+        setTemp(0, temp);
+        setTemp(1, temp2);
+    }
+    const LAllocation *input() {
+        return getOperand(0);
+    }
+    const LDefinition *outputSin() {
+        return getDef(0);
+    }
+    const LDefinition *outputCos() {
+        return getDef(1);
+    }
+    const LDefinition *temp() {
+        return getTemp(0);
+    }
+    const LDefinition *temp2() {
+        return getTemp(1);
+    }
+    const MSinCos *mir() const {
+        return mir_->toSinCos();
+    }
+};
+
 class LStringSplit : public LCallInstructionHelper<1, 2, 0>
 {
   public:
     LIR_HEADER(StringSplit)
 
     LStringSplit(const LAllocation& string, const LAllocation& separator) {
         setOperand(0, string);
         setOperand(1, separator);
--- a/js/src/jit/shared/LOpcodes-shared.h
+++ b/js/src/jit/shared/LOpcodes-shared.h
@@ -157,16 +157,17 @@
     _(DivPowTwoI)                   \
     _(ModI)                         \
     _(ModPowTwoI)                   \
     _(ModD)                         \
     _(BinaryV)                      \
     _(Concat)                       \
     _(CharCodeAt)                   \
     _(FromCharCode)                 \
+    _(SinCos)                       \
     _(StringSplit)                  \
     _(Int32ToDouble)                \
     _(Float32ToDouble)              \
     _(DoubleToFloat32)              \
     _(Int32ToFloat32)               \
     _(ValueToDouble)                \
     _(ValueToInt32)                 \
     _(ValueToFloat32)               \
--- a/js/src/jit/shared/Lowering-shared-inl.h
+++ b/js/src/jit/shared/Lowering-shared-inl.h
@@ -171,16 +171,45 @@ LIRGeneratorShared::defineReturn(LInstru
         lir->setDef(0, LDefinition(vreg, type, LGeneralReg(ReturnReg)));
         break;
     }
 
     mir->setVirtualRegister(vreg);
     add(lir);
 }
 
+template <size_t Ops, size_t Temps> void
+LIRGeneratorShared::defineSinCos(LInstructionHelper<2, Ops, Temps> *lir, MDefinition *mir,
+                                 LDefinition::Policy policy)
+{
+    MOZ_ASSERT(lir->isCall());
+
+    uint32_t vreg = getVirtualRegister();
+    lir->setDef(0, LDefinition(vreg, LDefinition::DOUBLE, LFloatReg(ReturnDoubleReg)));
+#if defined(JS_CODEGEN_ARM) || defined(JS_CODEGEN_ARM64)
+    lir->setDef(1, LDefinition(vreg + VREG_INCREMENT, LDefinition::DOUBLE, LFloatReg(d1)));
+#elif defined(JS_CODEGEN_MIPS)
+    lir->setDef(1, LDefinition(vreg + VREG_INCREMENT, LDefinition::DOUBLE, LFloatReg(f2)));
+#elif defined(JS_CODEGEN_NONE)
+    MOZ_CRASH();
+#elif defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_X64)
+    lir->setDef(1, LDefinition(vreg + VREG_INCREMENT, LDefinition::DOUBLE, LFloatReg(xmm1)));
+#else
+#error "Unsupported architecture for SinCos"
+#endif
+
+    getVirtualRegister();
+
+    lir->setMir(mir);
+    mir->setVirtualRegister(vreg);
+    add(lir);
+
+    return;
+}
+
 // In LIR, we treat booleans and integers as the same low-level type (INTEGER).
 // When snapshotting, we recover the actual JS type from MIR. This function
 // checks that when making redefinitions, we don't accidentally coerce two
 // incompatible types.
 static inline bool
 IsCompatibleLIRCoercion(MIRType to, MIRType from)
 {
     if (to == from)
@@ -190,16 +219,40 @@ IsCompatibleLIRCoercion(MIRType to, MIRT
         return true;
     }
     // SIMD types can be coerced with from*Bits operators.
     if (IsSimdType(to) && IsSimdType(from))
         return true;
     return false;
 }
 
+
+// We can redefine the sin(x) and cos(x) function to return the sincos result.
+void
+LIRGeneratorShared::redefine(MDefinition* def, MDefinition* as, MMathFunction::Function func)
+{
+    MOZ_ASSERT(def->isMathFunction());
+    MOZ_ASSERT(def->type() == MIRType_Double && as->type() == MIRType_SinCosDouble);
+    MOZ_ASSERT(MMathFunction::Sin == func || MMathFunction::Cos == func);
+
+    ensureDefined(as);
+    MMathFunction *math = def->toMathFunction();
+
+    MOZ_ASSERT(math->function() == MMathFunction::Cos ||
+               math->function() == MMathFunction::Sin);
+
+    // The sincos returns two values:
+    // - VREG: it returns the sin's value of the sincos;
+    // - VREG + VREG_INCREMENT: it returns the cos' value of the sincos.
+    if (math->function() == MMathFunction::Sin)
+        def->setVirtualRegister(as->virtualRegister());
+    else
+        def->setVirtualRegister(as->virtualRegister() + VREG_INCREMENT);
+}
+
 void
 LIRGeneratorShared::redefine(MDefinition* def, MDefinition* as)
 {
     MOZ_ASSERT(IsCompatibleLIRCoercion(def->type(), as->type()));
 
     // Try to emit MIR marked as emitted-at-uses at, well, uses. For
     // snapshotting reasons we delay the MIRTypes match, or when we are
     // coercing between bool and int32 constants.
--- a/js/src/jit/shared/Lowering-shared.h
+++ b/js/src/jit/shared/Lowering-shared.h
@@ -137,16 +137,20 @@ class LIRGeneratorShared : public MDefin
     template <size_t Ops, size_t Temps>
     inline void defineFixed(LInstructionHelper<1, Ops, Temps>* lir, MDefinition* mir,
                             const LAllocation& output);
 
     template <size_t Ops, size_t Temps>
     inline void defineBox(LInstructionHelper<BOX_PIECES, Ops, Temps>* lir, MDefinition* mir,
                           LDefinition::Policy policy = LDefinition::REGISTER);
 
+    template <size_t Ops, size_t Temps>
+    inline void defineSinCos(LInstructionHelper<2, Ops, Temps> *lir, MDefinition *mir,
+                             LDefinition::Policy policy = LDefinition::REGISTER);
+
     inline void defineSharedStubReturn(LInstruction* lir, MDefinition* mir);
     inline void defineReturn(LInstruction* lir, MDefinition* mir);
 
     template <size_t X>
     inline void define(details::LInstructionFixedDefsTempsHelper<1, X>* lir, MDefinition* mir,
                        LDefinition::Policy policy = LDefinition::REGISTER);
     template <size_t X>
     inline void define(details::LInstructionFixedDefsTempsHelper<1, X>* lir, MDefinition* mir,
@@ -158,16 +162,19 @@ class LIRGeneratorShared : public MDefin
     // Adds a use at operand |n| of a value-typed insturction.
     inline void useBox(LInstruction* lir, size_t n, MDefinition* mir,
                        LUse::Policy policy = LUse::REGISTER, bool useAtStart = false);
 
     // Rather than defining a new virtual register, sets |ins| to have the same
     // virtual register as |as|.
     inline void redefine(MDefinition* ins, MDefinition* as);
 
+    // Redefine a sin/cos call to sincos.
+    inline void redefine(MDefinition* def, MDefinition* as, MMathFunction::Function func);
+
     TempAllocator& alloc() const {
         return graph.alloc();
     }
 
     uint32_t getVirtualRegister() {
         uint32_t vreg = lirGraph_.getVirtualRegister();
 
         // If we run out of virtual registers, mark code generation as having
--- a/js/src/jsmath.cpp
+++ b/js/src/jsmath.cpp
@@ -948,16 +948,50 @@ js::math_sin(JSContext* cx, unsigned arg
     if (args.length() == 0) {
         args.rval().setNaN();
         return true;
     }
 
     return math_sin_handle(cx, args[0], args.rval());
 }
 
+void
+js::math_sincos_uncached(double x, double *sin, double *cos)
+{
+#if defined(__GLIBC__)
+    sincos(x, sin, cos);
+#elif defined(HAVE_SINCOS)
+    __sincos(x, sin, cos);
+#else
+    *sin = js::math_sin_uncached(x);
+    *cos = js::math_cos_uncached(x);
+#endif
+}
+
+void
+js::math_sincos_impl(MathCache* mathCache, double x, double *sin, double *cos)
+{
+    unsigned indexSin;
+    unsigned indexCos;
+    bool hasSin = mathCache->isCached(x, MathCache::Sin, sin, &indexSin);
+    bool hasCos = mathCache->isCached(x, MathCache::Cos, cos, &indexCos);
+    if (!(hasSin || hasCos)) {
+        js::math_sincos_uncached(x, sin, cos);
+        mathCache->store(MathCache::Sin, x, *sin, indexSin);
+        mathCache->store(MathCache::Cos, x, *cos, indexCos);
+        return;
+    }
+
+    if (!hasSin)
+        *sin = js::math_sin_impl(mathCache, x);
+
+    if (!hasCos)
+        *cos = js::math_cos_impl(mathCache, x);
+}
+
 bool
 js::math_sqrt_handle(JSContext* cx, HandleValue number, MutableHandleValue result)
 {
     double x;
     if (!ToNumber(cx, number, &x))
         return false;
 
     MathCache* mathCache = cx->runtime()->getMathCache(cx);
--- a/js/src/jsmath.h
+++ b/js/src/jsmath.h
@@ -75,16 +75,35 @@ class MathCache
         Entry& e = table[index];
         if (e.in == x && e.id == id)
             return e.out;
         e.in = x;
         e.id = id;
         return e.out = f(x);
     }
 
+    bool isCached(double x, MathFuncId id, double *r, unsigned *index) {
+        *index = hash(x, id);
+        Entry& e = table[*index];
+        if (e.in == x && e.id == id) {
+            *r = e.out;
+            return true;
+        }
+        return false;
+    }
+
+    void store(MathFuncId id, double x, double v, unsigned index) {
+        Entry &e = table[index];
+        if (e.in == x && e.id == id)
+            return;
+        e.in = x;
+        e.id = id;
+        e.out = v;
+    }
+
     size_t sizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf);
 };
 
 /*
  * JS math functions.
  */
 
 extern JSObject*
@@ -144,16 +163,22 @@ math_pow_handle(JSContext* cx, js::Handl
 
 extern bool
 math_pow(JSContext* cx, unsigned argc, js::Value* vp);
 
 extern bool
 minmax_impl(JSContext* cx, bool max, js::HandleValue a, js::HandleValue b,
             js::MutableHandleValue res);
 
+extern void
+math_sincos_uncached(double x, double *sin, double *cos);
+
+extern void
+math_sincos_impl(MathCache* mathCache, double x, double *sin, double *cos);
+
 extern bool
 math_sqrt_handle(JSContext* cx, js::HandleValue number, js::MutableHandleValue result);
 
 extern bool
 math_imul(JSContext* cx, unsigned argc, js::Value* vp);
 
 extern bool
 RoundFloat32(JSContext* cx, HandleValue v, float* out);
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -5913,16 +5913,25 @@ SetRuntimeOptions(JSRuntime* rt, const O
         if (strcmp(str, "on") == 0)
             jit::js_JitOptions.disableRangeAnalysis = false;
         else if (strcmp(str, "off") == 0)
             jit::js_JitOptions.disableRangeAnalysis = true;
         else
             return OptionFailure("ion-range-analysis", str);
     }
 
+    if (const char *str = op.getStringOption("ion-sincos")) {
+        if (strcmp(str, "on") == 0)
+            jit::js_JitOptions.disableSincos = false;
+        else if (strcmp(str, "off") == 0)
+            jit::js_JitOptions.disableSincos = true;
+        else
+            return OptionFailure("ion-sincos", str);
+    }
+
     if (const char* str = op.getStringOption("ion-sink")) {
         if (strcmp(str, "on") == 0)
             jit::js_JitOptions.disableSink = false;
         else if (strcmp(str, "off") == 0)
             jit::js_JitOptions.disableSink = true;
         else
             return OptionFailure("ion-sink", str);
     }
@@ -6251,16 +6260,23 @@ main(int argc, char** argv, char** envp)
                                "  off: disable GVN\n"
                                "  on:  enable GVN (default)\n")
         || !op.addStringOption('\0', "ion-licm", "on/off",
                                "Loop invariant code motion (default: on, off to disable)")
         || !op.addStringOption('\0', "ion-edgecase-analysis", "on/off",
                                "Find edge cases where Ion can avoid bailouts (default: on, off to disable)")
         || !op.addStringOption('\0', "ion-range-analysis", "on/off",
                                "Range analysis (default: on, off to disable)")
+#if defined(__APPLE__)
+        || !op.addStringOption('\0', "ion-sincos", "on/off",
+                               "Replace sin(x)/cos(x) to sincos(x) (default: on, off to disable)")
+#else
+        || !op.addStringOption('\0', "ion-sincos", "on/off",
+                               "Replace sin(x)/cos(x) to sincos(x) (default: off, on to enable)")
+#endif
         || !op.addStringOption('\0', "ion-sink", "on/off",
                                "Sink code motion (default: off, on to enable)")
         || !op.addStringOption('\0', "ion-loop-unrolling", "on/off",
                                "Loop unrolling (default: off, on to enable)")
         || !op.addStringOption('\0', "ion-instruction-reordering", "on/off",
                                "Instruction reordering (default: off, on to enable)")
         || !op.addBoolOption('\0', "ion-check-range-analysis",
                                "Range analysis checking")
--- a/js/src/vm/TraceLoggingTypes.h
+++ b/js/src/vm/TraceLoggingTypes.h
@@ -44,16 +44,17 @@
     _(DominatorTree)                                  \
     _(PhiAnalysis)                                    \
     _(MakeLoopsContiguous)                            \
     _(ApplyTypes)                                     \
     _(EagerSimdUnbox)                                 \
     _(AliasAnalysis)                                  \
     _(GVN)                                            \
     _(LICM)                                           \
+    _(Sincos)                                         \
     _(RangeAnalysis)                                  \
     _(LoopUnrolling)                                  \
     _(EffectiveAddressAnalysis)                       \
     _(AlignmentMaskAnalysis)                          \
     _(EliminateDeadCode)                              \
     _(ReorderInstructions)                            \
     _(EdgeCaseAnalysis)                               \
     _(EliminateRedundantChecks)                       \
--- a/js/src/vm/UbiNodeCensus.cpp
+++ b/js/src/vm/UbiNodeCensus.cpp
@@ -1,16 +1,20 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
  * vim: set ts=8 sts=4 et sw=4 tw=99:
  * 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 "js/UbiNodeCensus.h"
 
+#include "jscntxt.h"
+#include "jscompartment.h"
+#include "jsobjinlines.h"
+
 using namespace js;
 
 namespace JS {
 namespace ubi {
 
 void
 CountDeleter::operator()(CountBase* ptr)
 {
--- a/layout/base/RestyleManager.cpp
+++ b/layout/base/RestyleManager.cpp
@@ -85,16 +85,17 @@ RestyleManager::RestyleManager(nsPresCon
   , mHavePendingNonAnimationRestyles(false)
   , mHoverGeneration(0)
   , mRebuildAllExtraHint(nsChangeHint(0))
   , mRebuildAllRestyleHint(nsRestyleHint(0))
   , mLastUpdateForThrottledAnimations(aPresContext->RefreshDriver()->
                                         MostRecentRefresh())
   , mAnimationGeneration(0)
   , mReframingStyleContexts(nullptr)
+  , mAnimationsWithDestroyedFrame(nullptr)
   , mPendingRestyles(ELEMENT_HAS_PENDING_RESTYLE |
                      ELEMENT_IS_POTENTIAL_RESTYLE_ROOT |
                      ELEMENT_IS_CONDITIONAL_RESTYLE_ANCESTOR)
 #ifdef DEBUG
   , mIsProcessingRestyles(false)
 #endif
 #ifdef RESTYLE_LOGGING
   , mLoggingDepth(0)
@@ -1076,16 +1077,54 @@ RestyleManager::ReframingStyleContexts::
   // Before we go away, we need to flush out any frame construction that
   // was enqueued, so that we start transitions.
   // Note that this is a little bit evil in that we're calling into code
   // that calls our member functions from our destructor, but it's at
   // the beginning of our destructor, so it shouldn't be too bad.
   mRestyleManager->mPresContext->FrameConstructor()->CreateNeededFrames();
 }
 
+RestyleManager::AnimationsWithDestroyedFrame::AnimationsWithDestroyedFrame(
+                                          RestyleManager* aRestyleManager)
+  : mRestyleManager(aRestyleManager)
+  , mRestorePointer(mRestyleManager->mAnimationsWithDestroyedFrame)
+{
+  MOZ_ASSERT(!mRestyleManager->mAnimationsWithDestroyedFrame,
+             "shouldn't construct recursively");
+  mRestyleManager->mAnimationsWithDestroyedFrame = this;
+}
+
+void
+RestyleManager::AnimationsWithDestroyedFrame::StopAnimationsForElementsWithoutFrames()
+{
+  StopAnimationsWithoutFrame(mContents,
+    nsCSSPseudoElements::ePseudo_NotPseudoElement);
+  StopAnimationsWithoutFrame(mBeforeContents,
+    nsCSSPseudoElements::ePseudo_before);
+  StopAnimationsWithoutFrame(mAfterContents,
+    nsCSSPseudoElements::ePseudo_after);
+}
+
+void
+RestyleManager::AnimationsWithDestroyedFrame::StopAnimationsWithoutFrame(
+  nsTArray<nsRefPtr<nsIContent>>& aArray,
+  nsCSSPseudoElements::Type aPseudoType)
+{
+  nsAnimationManager* animationManager =
+    mRestyleManager->PresContext()->AnimationManager();
+  for (nsIContent* content : aArray) {
+    if (content->GetPrimaryFrame()) {
+      continue;
+    }
+    dom::Element* element = content->AsElement();
+
+    animationManager->StopAnimationsForElement(element, aPseudoType);
+  }
+}
+
 static inline dom::Element*
 ElementForStyleContext(nsIContent* aParentContent,
                        nsIFrame* aFrame,
                        nsCSSPseudoElements::Type aPseudoType);
 
 // Forwarded nsIDocumentObserver method, to handle restyling (and
 // passing the notification to the frame).
 nsresult
@@ -1775,16 +1814,20 @@ RestyleManager::BeginProcessingRestyles(
   }
 }
 
 void
 RestyleManager::EndProcessingRestyles()
 {
   FlushOverflowChangedTracker();
 
+  MOZ_ASSERT(mAnimationsWithDestroyedFrame);
+  mAnimationsWithDestroyedFrame->
+    StopAnimationsForElementsWithoutFrames();
+
   // Set mInStyleRefresh to false now, since the EndUpdate call might
   // add more restyles.
   mInStyleRefresh = false;
 
   if (mInRebuildAllStyleData) {
     FinishRebuildAllStyleData();
   }
 
--- a/layout/base/RestyleManager.h
+++ b/layout/base/RestyleManager.h
@@ -44,16 +44,18 @@ public:
   explicit RestyleManager(nsPresContext* aPresContext);
 
 private:
   // Private destructor, to discourage deletion outside of Release():
   ~RestyleManager()
   {
     MOZ_ASSERT(!mReframingStyleContexts,
                "temporary member should be nulled out before destruction");
+    MOZ_ASSERT(!mAnimationsWithDestroyedFrame,
+               "leaving dangling pointers from AnimationsWithDestroyedFrame");
   }
 
 public:
   NS_INLINE_DECL_REFCOUNTING(mozilla::RestyleManager)
 
   void Disconnect() {
     mPresContext = nullptr;
   }
@@ -242,16 +244,75 @@ public:
    * For the pseudo-elements, aContent must be the anonymous content
    * that we're creating for that pseudo-element, not the real element.
    */
   static bool
   TryStartingTransition(nsPresContext* aPresContext, nsIContent* aContent,
                         nsStyleContext* aOldStyleContext,
                         nsRefPtr<nsStyleContext>* aNewStyleContext /* inout */);
 
+  // AnimationsWithDestroyedFrame is used to stop animations on elements that
+  // have no frame at the end of the restyling process.
+  // It only lives during the restyling process.
+  class MOZ_STACK_CLASS AnimationsWithDestroyedFrame final {
+  public:
+    // Construct a AnimationsWithDestroyedFrame object.  The caller must
+    // ensure that aRestyleManager lives at least as long as the
+    // object.  (This is generally easy since the caller is typically a
+    // method of RestyleManager.)
+    explicit AnimationsWithDestroyedFrame(RestyleManager* aRestyleManager);
+    ~AnimationsWithDestroyedFrame()
+    {
+    }
+
+    // This method takes the content node for the generated content for
+    // animation on ::before and ::after, rather than the content node for
+    // the real element.
+    void Put(nsIContent* aContent, nsStyleContext* aStyleContext) {
+      MOZ_ASSERT(aContent);
+      nsCSSPseudoElements::Type pseudoType = aStyleContext->GetPseudoType();
+      if (pseudoType == nsCSSPseudoElements::ePseudo_NotPseudoElement) {
+        mContents.AppendElement(aContent);
+      } else if (pseudoType == nsCSSPseudoElements::ePseudo_before) {
+        MOZ_ASSERT(aContent->NodeInfo()->NameAtom() == nsGkAtoms::mozgeneratedcontentbefore);
+        mBeforeContents.AppendElement(aContent->GetParent());
+      } else if (pseudoType == nsCSSPseudoElements::ePseudo_after) {
+        MOZ_ASSERT(aContent->NodeInfo()->NameAtom() == nsGkAtoms::mozgeneratedcontentafter);
+        mAfterContents.AppendElement(aContent->GetParent());
+      }
+    }
+
+    void StopAnimationsForElementsWithoutFrames();
+
+  private:
+    void StopAnimationsWithoutFrame(nsTArray<nsRefPtr<nsIContent>>& aArray,
+                                    nsCSSPseudoElements::Type aPseudoType);
+
+    RestyleManager* mRestyleManager;
+    AutoRestore<AnimationsWithDestroyedFrame*> mRestorePointer;
+
+    // Below three arrays might include elements that have already had their
+    // animations stopped.
+    //
+    // mBeforeContents and mAfterContents hold the real element rather than
+    // the content node for the generated content (which might change during
+    // a reframe)
+    nsTArray<nsRefPtr<nsIContent>> mContents;
+    nsTArray<nsRefPtr<nsIContent>> mBeforeContents;
+    nsTArray<nsRefPtr<nsIContent>> mAfterContents;
+  };
+
+  /**
+   * Return the current AnimationsWithDestroyedFrame struct, or null if we're
+   * not currently in a restyling operation.
+   */
+  AnimationsWithDestroyedFrame* GetAnimationsWithDestroyedFrame() {
+    return mAnimationsWithDestroyedFrame;
+  }
+
 private:
   void RestyleForEmptyChange(Element* aContainer);
 
 public:
   // Restyling for a ContentInserted (notification after insertion) or
   // for a CharacterDataChanged.  |aContainer| must be non-null; when
   // the container is null, no work is needed.
   void RestyleForInsertOrChange(Element* aContainer, nsIContent* aChild);
@@ -486,16 +547,17 @@ private:
 
   OverflowChangedTracker mOverflowChangedTracker;
 
   // The total number of animation flushes by this frame constructor.
   // Used to keep the layer and animation manager in sync.
   uint64_t mAnimationGeneration;
 
   ReframingStyleContexts* mReframingStyleContexts;
+  AnimationsWithDestroyedFrame* mAnimationsWithDestroyedFrame;
 
   RestyleTracker mPendingRestyles;
 
 #ifdef DEBUG
   bool mIsProcessingRestyles;
 #endif
 
 #ifdef RESTYLE_LOGGING
--- a/layout/base/RestyleTracker.cpp
+++ b/layout/base/RestyleTracker.cpp
@@ -220,16 +220,22 @@ RestyleTracker::DoProcessRestyles()
 
   bool isTimelineRecording = false;
   nsDocShell* docShell =
     static_cast<nsDocShell*>(mRestyleManager->PresContext()->GetDocShell());
   if (docShell) {
     docShell->GetRecordProfileTimelineMarkers(&isTimelineRecording);
   }
 
+  // Create a AnimationsWithDestroyedFrame during restyling process to
+  // stop animations on elements that have no frame at the end of the
+  // restyling process.
+  RestyleManager::AnimationsWithDestroyedFrame
+    animationsWithDestroyedFrame(mRestyleManager);
+
   // Create a ReframingStyleContexts struct on the stack and put it in our
   // mReframingStyleContexts for almost all of the remaining scope of
   // this function.
   //
   // It needs to be *in* scope during BeginProcessingRestyles, which
   // might (if mDoRebuildAllStyleData is true) do substantial amounts of
   // restyle processing.
   //
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -682,16 +682,27 @@ nsFrame::DestroyFrom(nsIFrame* aDestruct
     // specifies CSS transitions.
     RestyleManager::ReframingStyleContexts* rsc =
       presContext->RestyleManager()->GetReframingStyleContexts();
     if (rsc) {
       rsc->Put(mContent, mStyleContext);
     }
   }
 
+  if (nsLayoutUtils::HasCurrentAnimations(static_cast<nsIFrame*>(this))) {
+    // If no new frame for this element is created by the end of the
+    // restyling process, stop animations for this frame
+    RestyleManager::AnimationsWithDestroyedFrame* adf =
+      presContext->RestyleManager()->GetAnimationsWithDestroyedFrame();
+    // AnimationsWithDestroyedFrame only lives during the restyling process.
+    if (adf) {
+      adf->Put(mContent, mStyleContext);
+    }
+  }
+
   shell->NotifyDestroyingFrame(this);
 
   if (mState & NS_FRAME_EXTERNAL_REFERENCE) {
     shell->ClearFrameRefs(this);
   }
 
   if (view) {
     // Break association between view and frame
--- a/layout/reftests/bugs/1127107-1a-nowrap.html
+++ b/layout/reftests/bugs/1127107-1a-nowrap.html
@@ -3,17 +3,16 @@
 <head>
   <style>
     div.test {
       /* Author expects this to prevent wrapping, and may add
          "overflow:hidden;text-overflow:ellipsis" for nice effect: */
       white-space: nowrap;
 
       /* BUT these (combined) seem to allow wrapping: */
-      -moz-hyphens: auto;
       -ms-hyphens: auto;
       -webkit-hyphens: auto;
       hyphens: auto;
       word-break: break-all;
 
       width: 200px;
       border: 1px solid black;
     }
--- a/layout/reftests/bugs/1127107-1b-pre.html
+++ b/layout/reftests/bugs/1127107-1b-pre.html
@@ -3,17 +3,16 @@
 <head>
   <style>
     div.test {
       /* Author expects this to prevent wrapping, and may add
          "overflow:hidden;text-overflow:ellipsis" for nice effect: */
       white-space: pre;
 
       /* BUT these (combined) seem to allow wrapping: */
-      -moz-hyphens: auto;
       -ms-hyphens: auto;
       -webkit-hyphens: auto;
       hyphens: auto;
       word-break: break-all;
 
       width: 200px;
       border: 1px solid black;
     }
new file mode 100644
--- /dev/null
+++ b/layout/reftests/canvas/1074733-1-ref.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <meta charset="UTF-8">
+    <script type="text/javascript">
+      function bodyonload() {
+        var canvas=document.getElementById('test');
+        var ctx = canvas.getContext("2d");
+        ctx.fillStyle = 'green';
+        ctx.fillRect(-1, 50, 151, 50); // left at -1
+        ctx.fillStyle = 'red';
+        ctx.rect(-1, 100, 151, 50); // left at -1
+        ctx.fill();
+        ctx.fillStyle = 'blue';
+        ctx.fillRect(0, 150, 150, 50); // left at 0
+      }
+    </script>
+  </head>
+  <body onload="bodyonload();">
+    <canvas id="test" width="200" height="200"></canvas>
+  </body>
+</html>
+
new file mode 100644
--- /dev/null
+++ b/layout/reftests/canvas/1074733-1.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <meta charset="UTF-8">
+    <script type="text/javascript">
+      function bodyonload() {
+        var canvas=document.getElementById('test');
+        var ctx = canvas.getContext("2d");
+        ctx.fillStyle = 'green';
+        ctx.fillRect(150, 50, -151, 50); // left at -1
+        ctx.fillStyle = 'red';
+        ctx.rect(150, 100, -151, 50); // left at -1
+        ctx.fill();
+        ctx.fillStyle = 'blue';
+        ctx.fillRect(150, 150, -150, 50); // left at 0
+      }
+    </script>
+  </head>
+  <body onload="bodyonload();">
+    <canvas id="test" width="200" height="200"></canvas>
+  </body>
+</html>
+
--- a/layout/reftests/canvas/reftest.list
+++ b/layout/reftests/canvas/reftest.list
@@ -98,11 +98,12 @@ fails-if(azureQuartz&&OSX==1006) == 6726
 == transformed-path.html transformed-path.html
 
 == 749467-1.html 749467-1-ref.html
 
 # You get a little bit of rounding fuzz on OSX from transforming the paths between user space and device space
 fuzzy-if(azureQuartz,2,128) fuzzy-if(d2d,12,21) fuzzy-if(d2d&&/^Windows\x20NT\x2010\.0/.test(http.oscpu),2,141) == 784573-1.html 784573-1-ref.html
 
 == 802658-1.html 802658-1-ref.html
+== 1074733-1.html 1074733-1-ref.html
 fuzzy-if(Mulet,45,2) == 1107096-invisibles.html 1107096-invisibles-ref.html
 == 1151821-1.html 1151821-1-ref.html
 == 1201272-1.html 1201272-1-ref.html
--- a/layout/reftests/text/auto-hyphenation-1-ref.html
+++ b/layout/reftests/text/auto-hyphenation-1-ref.html
@@ -1,9 +1,9 @@
 <!DOCTYPE html>
 <html>
 <body lang="en-us">
-<div style="width: 5em; -moz-hyphens: manual; font-family:sans-serif;">
+<div style="width: 5em; hyphens: manual; font-family:sans-serif;">
 su&shy;per&shy;cal&shy;ifrag&shy;ilis&shy;tic&shy;ex&shy;pi&shy;ali&shy;do&shy;cious
 </div>
 </body>
 </html>
 
--- a/layout/reftests/text/auto-hyphenation-1.html
+++ b/layout/reftests/text/auto-hyphenation-1.html
@@ -1,10 +1,10 @@
 <!DOCTYPE html>
 <html>
 <!-- simple test for automatic hyphenation -->
 <body lang="en-us">
-<div style="width: 5em; -moz-hyphens: auto; font-family:sans-serif;">
+<div style="width: 5em; hyphens: auto; font-family:sans-serif;">
 supercalifragilisticexpialidocious
 </div>
 </body>
 </html>
 
--- a/layout/reftests/text/auto-hyphenation-10-ref.html
+++ b/layout/reftests/text/auto-hyphenation-10-ref.html
@@ -1,11 +1,11 @@
 <!DOCTYPE html>
 <html>
 <meta charset="UTF-8">
 <!-- check that hyphenation is not applied when language is not specified -->
 <body>
-<div style="width: 5em; -moz-hyphens: none;">
+<div style="width: 5em; hyphens: none;">
 supercalifragilisticexpialidocious
 </div>
 </body>
 </html>
 
--- a/layout/reftests/text/auto-hyphenation-10.html
+++ b/layout/reftests/text/auto-hyphenation-10.html
@@ -1,11 +1,11 @@
 <!DOCTYPE html>
 <html>
 <meta charset="UTF-8">
 <!-- check that hyphenation is not applied when language is not specified -->
 <body>
-<div style="width: 5em; -moz-hyphens: auto;">
+<div style="width: 5em; hyphens: auto;">
 supercalifragilisticexpialidocious
 </div>
 </body>
 </html>
 
--- a/layout/reftests/text/auto-hyphenation-1a.html
+++ b/layout/reftests/text/auto-hyphenation-1a.html
@@ -1,10 +1,10 @@
 <!DOCTYPE html>
 <html>
 <!-- adding random <span>s should not affect hyphenation -->
 <body lang="en-us">
-<div style="width: 5em; -moz-hyphens: auto; font-family:sans-serif;">
+<div style="width: 5em; hyphens: auto; font-family:sans-serif;">
 super<span>cali</span>frag<span>ili</span>sti<span>cex</span>pialidoc<span>i</span>ous
 </div>
 </body>
 </html>
 
--- a/layout/reftests/text/auto-hyphenation-2-ref.html
+++ b/layout/reftests/text/auto-hyphenation-2-ref.html
@@ -1,11 +1,11 @@
 <!DOCTYPE html>
 <html>
 <body lang="en-us">
-<div style="width: 5em; -moz-hyphens: auto; font-family:sans-serif;">
+<div style="width: 5em; hyphens: auto; font-family:sans-serif;">
 supercalifragilisticexpialidocious
-<span style="-moz-hyphens:none">super<span lang="foo">cali</span>fragilisticexpialidocious</span>
+<span style="hyphens:none">super<span lang="foo">cali</span>fragilisticexpialidocious</span>
 supercalifragilisticexpialidocious
 </div>
 </body>
 </html>
 
--- a/layout/reftests/text/auto-hyphenation-2.html
+++ b/layout/reftests/text/auto-hyphenation-2.html
@@ -1,12 +1,12 @@
 <!DOCTYPE html>
 <html>
 <!-- mixed languages in a word should inhibit automatic hyphenation -->
 <body lang="en-us">
-<div style="width: 5em; -moz-hyphens: auto; font-family:sans-serif;">
+<div style="width: 5em; hyphens: auto; font-family:sans-serif;">
 supercalifragilisticexpialidocious
 super<span lang="foo">cali</span>fragilisticexpialidocious
 supercalifragilisticexpialidocious
 </div>
 </body>
 </html>
 
--- a/layout/reftests/text/auto-hyphenation-3.html
+++ b/layout/reftests/text/auto-hyphenation-3.html
@@ -1,10 +1,10 @@
 <!DOCTYPE html>
 <html>
-<!-- check that -moz-hyphens:none prevents break at &shy; -->
+<!-- check that hyphens:none prevents break at &shy; -->
 <body lang="en-us">
-<div style="width: 5em; -moz-hyphens: none;">
+<div style="width: 5em; hyphens: none;">
 su&shy;per&shy;cal&shy;ifrag&shy;ilis&shy;tic&shy;ex&shy;pi&shy;ali&shy;do&shy;cious
 </div>
 </body>
 </html>
 
--- a/layout/reftests/text/auto-hyphenation-4-ref.html
+++ b/layout/reftests/text/auto-hyphenation-4-ref.html
@@ -1,9 +1,9 @@
 <!DOCTYPE html>
 <html>
 <body lang="x-unknown-language">
-<div style="width: 5em; -moz-hyphens: none;">
+<div style="width: 5em; hyphens: none;">
 supercalifragilisticexpialidocious
 </div>
 </body>
 </html>
 
--- a/layout/reftests/text/auto-hyphenation-4.html
+++ b/layout/reftests/text/auto-hyphenation-4.html
@@ -1,10 +1,10 @@
 <!DOCTYPE html>
 <html>
 <!-- check that hyphenation is not applied to unknown language -->
 <body lang="x-unknown-language">
-<div style="width: 5em; -moz-hyphens: auto;">
+<div style="width: 5em; hyphens: auto;">
 supercalifragilisticexpialidocious
 </div>
 </body>
 </html>
 
--- a/layout/reftests/text/auto-hyphenation-5-ref.html
+++ b/layout/reftests/text/auto-hyphenation-5-ref.html
@@ -1,17 +1,17 @@
 <!DOCTYPE html>
 <html>
 <head>
 <style type="text/css">
 div {
   margin:       10px;
   width:        10px;
   font-family:  monospace;
-  -moz-hyphens: manual;
+  hyphens: manual;
 }
 </style>
 </head>
 <!-- test some hyphenations that involve overlapping patterns -->
 <body lang="en-us">
 <div>
 photo
 </div>
--- a/layout/reftests/text/auto-hyphenation-5.html
+++ b/layout/reftests/text/auto-hyphenation-5.html
@@ -1,17 +1,17 @@
 <!DOCTYPE html>
 <html>
 <head>
 <style type="text/css">
 div {
   margin:       10px;
   width:        10px;
   font-family:  monospace;
-  -moz-hyphens: auto;
+  hyphens: auto;
 }
 </style>
 </head>
 <!-- test some hyphenations that involve overlapping patterns -->
 <body lang="en-us">
 <div>
 photo
 </div>
--- a/layout/reftests/text/auto-hyphenation-6-ref.html
+++ b/layout/reftests/text/auto-hyphenation-6-ref.html
@@ -1,9 +1,9 @@
 <!DOCTYPE html>
 <html>
 <body lang="en-us">
-<div style="width: 0; -moz-hyphens: manual;">
+<div style="width: 0; hyphens: manual;">
 hy&shy;<span style="color:red">phen&shy;</span>ation
 </div>
 </body>
 </html>
 
--- a/layout/reftests/text/auto-hyphenation-6.html
+++ b/layout/reftests/text/auto-hyphenation-6.html
@@ -1,10 +1,10 @@
 <!DOCTYPE html>
 <html>
 <!-- style changes don't break hyphenation -->
 <body lang="en-us">
-<div style="width: 0; -moz-hyphens: auto;">
+<div style="width: 0; hyphens: auto;">
 hy<span style="color:red">phen</span>ation
 </div>
 </body>
 </html>
 
--- a/layout/reftests/text/auto-hyphenation-7-ref.html
+++ b/layout/reftests/text/auto-hyphenation-7-ref.html
@@ -1,9 +1,9 @@
 <!DOCTYPE html>
 <html>
 <body lang="en-us">
-<div style="width: 0; -moz-hyphens: manual;">
+<div style="width: 0; hyphens: manual;">
 h<span style="color:red">y&shy;phen&shy;a</span>tion
 </div>
 </body>
 </html>
 
--- a/layout/reftests/text/auto-hyphenation-7.html
+++ b/layout/reftests/text/auto-hyphenation-7.html
@@ -1,10 +1,10 @@
 <!DOCTYPE html>
 <html>
 <!-- style changes don't break hyphenation -->
 <body lang="en-us">
-<div style="width: 0; -moz-hyphens: auto;">
+<div style="width: 0; hyphens: auto;">
 h<span style="color:red">yphena</span>tion
 </div>
 </body>
 </html>
 
--- a/layout/reftests/text/auto-hyphenation-8-ref.html
+++ b/layout/reftests/text/auto-hyphenation-8-ref.html
@@ -1,10 +1,10 @@
 <!DOCTYPE html>
 <html>
 <!-- check that hyphenation is not applied when language is not specified -->
 <body>
-<div style="width: 5em; -moz-hyphens: none;">
+<div style="width: 5em; hyphens: none;">
 supercalifragilisticexpialidocious
 </div>
 </body>
 </html>
 
--- a/layout/reftests/text/auto-hyphenation-8.html
+++ b/layout/reftests/text/auto-hyphenation-8.html
@@ -1,10 +1,10 @@
 <!DOCTYPE html>
 <html>
 <!-- check that hyphenation is not applied when language is not specified -->
 <body>
-<div style="width: 5em; -moz-hyphens: auto;">
+<div style="width: 5em; hyphens: auto;">
 supercalifragilisticexpialidocious
 </div>
 </body>
 </html>
 
--- a/layout/reftests/text/auto-hyphenation-9-ref.html
+++ b/layout/reftests/text/auto-hyphenation-9-ref.html
@@ -1,11 +1,11 @@
 <!DOCTYPE html>
 <html>
 <meta charset="iso-8859-1">
 <!-- check that hyphenation is not applied when language is not specified -->
 <body>
-<div style="width: 5em; -moz-hyphens: none;">
+<div style="width: 5em; hyphens: none;">
 supercalifragilisticexpialidocious
 </div>
 </body>
 </html>
 
--- a/layout/reftests/text/auto-hyphenation-9.html
+++ b/layout/reftests/text/auto-hyphenation-9.html
@@ -1,11 +1,11 @@
 <!DOCTYPE html>
 <html>
 <meta charset="iso-8859-1">
 <!-- check that hyphenation is not applied when language is not specified -->
 <body>
-<div style="width: 5em; -moz-hyphens: auto;">
+<div style="width: 5em; hyphens: auto;">
 supercalifragilisticexpialidocious
 </div>
 </body>
 </html>
 
--- a/layout/reftests/text/auto-hyphenation-af-1-ref.html
+++ b/layout/reftests/text/auto-hyphenation-af-1-ref.html
@@ -1,11 +1,11 @@
 <!DOCTYPE html>
 <html>
 <head>
 <meta http-equiv="content-type" content="text/html; charset=utf-8">
 </head>
 <body>
-<div style="width:1em; -moz-hyphens:manual;" lang="af">
+<div style="width:1em; hyphens:manual;" lang="af">
 Al&shy;le mens&shy;li&shy;ke we&shy;sens word vry, met ge&shy;ly&shy;ke waar&shy;dig&shy;heid en reg&shy;te, ge&shy;bo&shy;re.
 </div>
 </body>
 </html>
--- a/layout/reftests/text/auto-hyphenation-af-1.html
+++ b/layout/reftests/text/auto-hyphenation-af-1.html
@@ -1,11 +1,11 @@
 <!DOCTYPE html>
 <html>
 <head>
 <meta http-equiv="content-type" content="text/html; charset=utf-8">
 </head>
 <body>
-<div style="width:1em; -moz-hyphens:auto;" lang="af">
+<div style="width:1em; hyphens:auto;" lang="af">
 Alle menslike wesens word vry, met gelyke waardigheid en regte, gebore.
 </div>
 </body>
 </html>
--- a/layout/reftests/text/auto-hyphenation-bg-1-ref.html
+++ b/layout/reftests/text/auto-hyphenation-bg-1-ref.html
@@ -1,11 +1,11 @@
 <!DOCTYPE html>
 <html>
 <head>
 <meta http-equiv="content-type" content="text/html; charset=utf-8">
 </head>
 <body>
-<div style="width:1em; -moz-hyphens:manual;" lang="bg">
+<div style="width:1em; hyphens:manual;" lang="bg">
 Всич&shy;ки хо&shy;ра се раж&shy;дат сво&shy;бод&shy;ни и рав&shy;ни по дос&shy;тойн&shy;с&shy;т&shy;во и пра&shy;ва.
 </div>
 </body>
 </html>
--- a/layout/reftests/text/auto-hyphenation-bg-1.html
+++ b/layout/reftests/text/auto-hyphenation-bg-1.html
@@ -1,11 +1,11 @@
 <!DOCTYPE html>
 <html>
 <head>
 <meta http-equiv="content-type" content="text/html; charset=utf-8">
 </head>
 <body>
-<div style="width:1em; -moz-hyphens:auto;" lang="bg">
+<div style="width:1em; hyphens:auto;" lang="bg">
 Всички хора се раждат свободни и равни по достойнство и права.
 </div>
 </body>
 </html>
--- a/layout/reftests/text/auto-hyphenation-ca-1-ref.html
+++ b/layout/reftests/text/auto-hyphenation-ca-1-ref.html
@@ -1,11 +1,11 @@
 <!DOCTYPE html>
 <html>
 <head>
 <meta http-equiv="content-type" content="text/html; charset=utf-8">
 </head>
 <body>
-<div style="width:1em; -moz-hyphens:manual;" lang="ca">
+<div style="width:1em; hyphens:manual;" lang="ca">
 Tots els és&shy;sers hu&shy;mans nei&shy;xen lliu&shy;res i iguals en dig&shy;ni&shy;tat i en drets.
 </div>
 </body>
 </html>
--- a/layout/reftests/text/auto-hyphenation-ca-1.html
+++ b/layout/reftests/text/auto-hyphenation-ca-1.html
@@ -1,11 +1,11 @@
 <!DOCTYPE html>
 <html>
 <head>
 <meta http-equiv="content-type" content="text/html; charset=utf-8">
 </head>
 <body>
-<div style="width:1em; -moz-hyphens:auto;" lang="ca">
+<div style="width:1em; hyphens:auto;" lang="ca">
 Tots els éssers humans neixen lliures i iguals en dignitat i en drets.
 </div>
 </body>
 </html>
--- a/layout/reftests/text/auto-hyphenation-cy-1-ref.html
+++ b/layout/reftests/text/auto-hyphenation-cy-1-ref.html
@@ -1,11 +1,11 @@
 <!DOCTYPE html>
 <html>
 <head>
 <meta http-equiv="content-type" content="text/html; charset=utf-8">
 </head>
 <body>
-<div style="width:1em; -moz-hyphens:manual;" lang="cy">
+<div style="width:1em; hyphens:manual;" lang="cy">
 Gen&shy;ir pawb yn rhydd ac yn gyd&shy;radd â'i gil&shy;ydd mewn urdd&shy;as a hawl&shy;iau.
 </div>
 </body>
 </html>
--- a/layout/reftests/text/auto-hyphenation-cy-1.html
+++ b/layout/reftests/text/auto-hyphenation-cy-1.html
@@ -1,11 +1,11 @@
 <!DOCTYPE html>
 <html>
 <head>
 <meta http-equiv="content-type" content="text/html; charset=utf-8">
 </head>
 <body>
-<div style="width:1em; -moz-hyphens:auto;" lang="cy">
+<div style="width:1em; hyphens:auto;" lang="cy">
 Genir pawb yn rhydd ac yn gydradd â'i gilydd mewn urddas a hawliau.
 </div>
 </body>
 </html>
--- a/layout/reftests/text/auto-hyphenation-da-1-ref.html
+++ b/layout/reftests/text/auto-hyphenation-da-1-ref.html
@@ -1,11 +1,11 @@
 <!DOCTYPE html>
 <html>
 <head>
 <meta http-equiv="content-type" content="text/html; charset=utf-8">
 </head>
 <body>
-<div style="width:1em; -moz-hyphens:manual;" lang="da">
+<div style="width:1em; hyphens:manual;" lang="da">
 Al&shy;le men&shy;ne&shy;sker er født frie og li&shy;ge i vær&shy;dig&shy;hed og ret&shy;tig&shy;he&shy;der.
 </div>
 </body>
 </html>
--- a/layout/reftests/text/auto-hyphenation-da-1.html
+++ b/layout/reftests/text/auto-hyphenation-da-1.html
@@ -1,11 +1,11 @@
 <!DOCTYPE html>
 <html>
 <head>
 <meta http-equiv="content-type" content="text/html; charset=utf-8">
 </head>
 <body>
-<div style="width:1em; -moz-hyphens:auto;" lang="da">
+<div style="width:1em; hyphens:auto;" lang="da">
 Alle mennesker er født frie og lige i værdighed og rettigheder.
 </div>
 </body>
 </html>
--- a/layout/reftests/text/auto-hyphenation-de-1901-1-ref.html
+++ b/layout/reftests/text/auto-hyphenation-de-1901-1-ref.html
@@ -1,13 +1,13 @@
 <!DOCTYPE html>
 <html>
 <head>
 <meta http-equiv="content-type" content="text/html; charset=utf-8">
 </head>
 <body>
-<div style="width:1em; -moz-hyphens:manual;" lang="de-1901">
+<div style="width:1em; hyphens:manual;" lang="de-1901">
 Al&shy;le Men&shy;schen sind frei und gleich an Wür&shy;de und Rech&shy;ten ge&shy;bo&shy;ren.
 <p>
 bu&shy;sser <!-- example word that is hyphenated differently by de-1901 and de-1996 -->
 </div>
 </body>
 </html>
--- a/layout/reftests/text/auto-hyphenation-de-1901-1.html
+++ b/layout/reftests/text/auto-hyphenation-de-1901-1.html
@@ -1,13 +1,13 @@
 <!DOCTYPE html>
 <html>
 <head>
 <meta http-equiv="content-type" content="text/html; charset=utf-8">
 </head>
 <body>
-<div style="width:1em; -moz-hyphens:auto;" lang="de-1901">
+<div style="width:1em; hyphens:auto;" lang="de-1901">
 Alle Menschen sind frei und gleich an Würde und Rechten geboren.
 <p>
 busser <!-- example word that is hyphenated differently by de-1901 and de-1996 -->
 </div>
 </body>
 </html>
--- a/layout/reftests/text/auto-hyphenation-de-1996-1-ref.html
+++ b/layout/reftests/text/auto-hyphenation-de-1996-1-ref.html
@@ -1,13 +1,13 @@
 <!DOCTYPE html>
 <html>
 <head>
 <meta http-equiv="content-type" content="text/html; charset=utf-8">
 </head>
 <body>
-<div style="width:1em; -moz-hyphens:manual;" lang="de-1996">
+<div style="width:1em; hyphens:manual;" lang="de-1996">
 Al&shy;le Men&shy;schen sind frei und gleich an Wür&shy;de und Rech&shy;ten ge&shy;bo&shy;ren.
 <p>
 bus&shy;ser <!-- example word that is hyphenated differently by de-1901 and de-1996 -->
 </div>
 </body>
 </html>
--- a/layout/reftests/text/auto-hyphenation-de-1996-1.html
+++ b/layout/reftests/text/auto-hyphenation-de-1996-1.html
@@ -1,13 +1,13 @@
 <!DOCTYPE html>
 <html>
 <head>
 <meta http-equiv="content-type" content="text/html; charset=utf-8">
 </head>
 <body>
-<div style="width:1em; -moz-hyphens:auto;" lang="de-1996">
+<div style="width:1em; hyphens:auto;" lang="de-1996">
 Alle Menschen sind frei und gleich an Würde und Rechten geboren.
 <p>
 busser <!-- example word that is hyphenated differently by de-1901 and de-1996 -->
 </div>
 </body>
 </html>
--- a/layout/reftests/text/auto-hyphenation-de-ch-1-ref.html
+++ b/layout/reftests/text/auto-hyphenation-de-ch-1-ref.html
@@ -1,11 +1,11 @@
 <!DOCTYPE html>
 <html>
 <head>
 <meta http-equiv="content-type" content="text/html; charset=utf-8">
 </head>
 <body>
-<div style="width:1em; -moz-hyphens:manual;" lang="de-CH">
+<div style="width:1em; hyphens:manual;" lang="de-CH">
 Al&shy;le Men&shy;schen sind frei und gleich an Wür&shy;de und Rech&shy;ten ge&shy;bo&shy;ren.
 </div>
 </body>
 </html>
--- a/layout/reftests/text/auto-hyphenation-de-ch-1.html
+++ b/layout/reftests/text/auto-hyphenation-de-ch-1.html
@@ -1,11 +1,11 @@
 <!DOCTYPE html>
 <html>
 <head>
 <meta http-equiv="content-type" content="text/html; charset=utf-8">
 </head>
 <body>
-<div style="width:1em; -moz-hyphens:auto;" lang="de-CH">
+<div style="width:1em; hyphens:auto;" lang="de-CH">
 Alle Menschen sind frei und gleich an Würde und Rechten geboren.
 </div>
 </body>
 </html>
--- a/layout/reftests/text/auto-hyphenation-eo-1-ref.html
+++ b/layout/reftests/text/auto-hyphenation-eo-1-ref.html
@@ -1,11 +1,11 @@
 <!DOCTYPE html>
 <html>
 <head>
 <meta http-equiv="content-type" content="text/html; charset=utf-8">
 </head>
 <body>
-<div style="width:1em; -moz-hyphens:manual;" lang="eo">
+<div style="width:1em; hyphens:manual;" lang="eo">
 Ĉiuj ho&shy;moj es&shy;tas de&shy;na&shy;s&shy;ke li&shy;be&shy;raj kaj ega&shy;laj laŭ di&shy;g&shy;no kaj raj&shy;toj.
 </div>
 </body>
 </html>
--- a/layout/reftests/text/auto-hyphenation-eo-1.html
+++ b/layout/reftests/text/auto-hyphenation-eo-1.html
@@ -1,11 +1,11 @@
 <!DOCTYPE html>
 <html>
 <head>
 <meta http-equiv="content-type" content="text/html; charset=utf-8">
 </head>
 <body>
-<div style="width:1em; -moz-hyphens:auto;" lang="eo">
+<div style="width:1em; hyphens:auto;" lang="eo">
 Ĉiuj homoj estas denaske liberaj kaj egalaj laŭ digno kaj rajtoj.
 </div>
 </body>
 </html>
--- a/layout/reftests/text/auto-hyphenation-es-1-ref.html
+++ b/layout/reftests/text/auto-hyphenation-es-1-ref.html
@@ -1,11 +1,11 @@
 <!DOCTYPE html>
 <html>
 <head>
 <meta http-equiv="content-type" content="text/html; charset=utf-8">
 </head>
 <body>
-<div style="width:1em; -moz-hyphens:manual;" lang="es">
+<div style="width:1em; hyphens:manual;" lang="es">
 To&shy;dos los se&shy;res hu&shy;ma&shy;nos na&shy;cen li&shy;bres e igua&shy;les en dig&shy;ni&shy;dad y de&shy;re&shy;chos
 </div>
 </body>
 </html>
--- a/layout/reftests/text/auto-hyphenation-es-1.html
+++ b/layout/reftests/text/auto-hyphenation-es-1.html
@@ -1,11 +1,11 @@
 <!DOCTYPE html>
 <html>
 <head>
 <meta http-equiv="content-type" content="text/html; charset=utf-8">
 </head>
 <body>
-<div style="width:1em; -moz-hyphens:auto;" lang="es">
+<div style="width:1em; hyphens:auto;" lang="es">
 Todos los seres humanos nacen libres e iguales en dignidad y derechos
 </div>
 </body>
 </html>
--- a/layout/reftests/text/auto-hyphenation-et-1-ref.html
+++ b/layout/reftests/text/auto-hyphenation-et-1-ref.html
@@ -1,11 +1,11 @@
 <!DOCTYPE html>
 <html>
 <head>
 <meta http-equiv="content-type" content="text/html; charset=utf-8">
 </head>
 <body>
-<div style="width:1em; -moz-hyphens:manual;" lang="et">
+<div style="width:1em; hyphens:manual;" lang="et">
 Kõik ini&shy;me&shy;sed sün&shy;nivad va&shy;ba&shy;de&shy;na ja võrds&shy;ete&shy;na oma vää&shy;ri&shy;ku&shy;selt ja õi&shy;gus&shy;telt
 </div>
 </body>
 </html>
--- a/layout/reftests/text/auto-hyphenation-et-1.html
+++ b/layout/reftests/text/auto-hyphenation-et-1.html
@@ -1,11 +1,11 @@
 <!DOCTYPE html>
 <html>
 <head>
 <meta http-equiv="content-type" content="text/html; charset=utf-8">
 </head>
 <body>
-<div style="width:1em; -moz-hyphens:auto;" lang="et">
+<div style="width:1em; hyphens:auto;" lang="et">
 Kõik inimesed sünnivad vabadena ja võrdsetena oma väärikuselt ja õigustelt
 </div>
 </body>
 </html>
--- a/layout/reftests/text/auto-hyphenation-fi-1-ref.html
+++ b/layout/reftests/text/auto-hyphenation-fi-1-ref.html
@@ -1,11 +1,11 @@
 <!DOCTYPE html>
 <html>
 <head>
 <meta http-equiv="content-type" content="text/html; charset=utf-8">
 </head>
 <body>
-<div style="width:1em; -moz-hyphens:manual;" lang="fi">
+<div style="width:1em; hyphens:manual;" lang="fi">
 Kaik&shy;ki ih&shy;mi&shy;set syn&shy;ty&shy;vät va&shy;pai&shy;na ja ta&shy;sa&shy;ver&shy;tai&shy;si&shy;na ar&shy;vol&shy;taan ja oi&shy;keuk&shy;sil&shy;taan.
 </div>
 </body>
 </html>
--- a/layout/reftests/text/auto-hyphenation-fi-1.html
+++ b/layout/reftests/text/auto-hyphenation-fi-1.html
@@ -1,11 +1,11 @@
 <!DOCTYPE html>
 <html>
 <head>
 <meta http-equiv="content-type" content="text/html; charset=utf-8">
 </head>
 <body>
-<div style="width:1em; -moz-hyphens:auto;" lang="fi">
+<div style="width:1em; hyphens:auto;" lang="fi">
 Kaikki ihmiset syntyvät vapaina ja tasavertaisina arvoltaan ja oikeuksiltaan.
 </div>
 </body>
 </html>
--- a/layout/reftests/text/auto-hyphenation-fr-1-ref.html
+++ b/layout/reftests/text/auto-hyphenation-fr-1-ref.html
@@ -1,11 +1,11 @@
 <!DOCTYPE html>
 <html>
 <head>
 <meta http-equiv="content-type" content="text/html; charset=utf-8">
 </head>
 <body>
-<div style="width:1em; -moz-hyphens:manual;" lang="fr">
+<div style="width:1em; hyphens:manual;" lang="fr">
 Tout in&shy;di&shy;vi&shy;du a droit à la vie, à la li&shy;ber&shy;té et à la sû&shy;re&shy;té de sa per&shy;sonne.
 </div>
 </body>
 </html>
--- a/layout/reftests/text/auto-hyphenation-fr-1.html
+++ b/layout/reftests/text/auto-hyphenation-fr-1.html
@@ -1,11 +1,11 @@
 <!DOCTYPE html>
 <html>
 <head>
 <meta http-equiv="content-type" content="text/html; charset=utf-8">
 </head>
 <body>
-<div style="width:1em; -moz-hyphens:auto;" lang="fr">
+<div style="width:1em; hyphens:auto;" lang="fr">
 Tout individu a droit à la vie, à la liberté et à la sûreté de sa personne.
 </div>
 </body>
 </html>
--- a/layout/reftests/text/auto-hyphenation-gl-1-ref.html
+++ b/layout/reftests/text/auto-hyphenation-gl-1-ref.html
@@ -1,11 +1,11 @@
 <!DOCTYPE html>
 <html>
 <head>
 <meta http-equiv="content-type" content="text/html; charset=utf-8">
 </head>
 <body>
-<div style="width:1em; -moz-hyphens:manual;" lang="gl">
+<div style="width:1em; hyphens:manual;" lang="gl">
 Tó&shy;do&shy;los se&shy;res hu&shy;ma&shy;nos na&shy;cen li&shy;bres e iguais en dig&shy;ni&shy;da&shy;de e de&shy;rei&shy;tos
 </div>
 </body>
 </html>
--- a/layout/reftests/text/auto-hyphenation-gl-1.html
+++ b/layout/reftests/text/auto-hyphenation-gl-1.html
@@ -1,11 +1,11 @@
 <!DOCTYPE html>
 <html>
 <head>
 <meta http-equiv="content-type" content="text/html; charset=utf-8">
 </head>
 <body>
-<div style="width:1em; -moz-hyphens:auto;" lang="gl">
+<div style="width:1em; hyphens:auto;" lang="gl">
 Tódolos seres humanos nacen libres e iguais en dignidade e dereitos
 </div>
 </body>
 </html>
--- a/layout/reftests/text/auto-hyphenation-hr-1-ref.html
+++ b/layout/reftests/text/auto-hyphenation-hr-1-ref.html
@@ -1,11 +1,11 @@
 <!DOCTYPE html>
 <html>
 <head>
 <meta http-equiv="content-type" content="text/html; charset=utf-8">
 </head>
 <body>
-<div style="width:1em; -moz-hyphens:manual;" lang="hr">
+<div style="width:1em; hyphens:manual;" lang="hr">
 Sva ljud&shy;ska bi&shy;ća ra&shy;ća&shy;ju se slo&shy;bod&shy;na i jed&shy;na&shy;ka u dos&shy;to&shy;jans&shy;tvu i pra&shy;vi&shy;ma
 </div>
 </body>
 </html>
--- a/layout/reftests/text/auto-hyphenation-hr-1.html
+++ b/layout/reftests/text/auto-hyphenation-hr-1.html
@@ -1,11 +1,11 @@
 <!DOCTYPE html>
 <html>
 <head>
 <meta http-equiv="content-type" content="text/html; charset=utf-8">
 </head>
 <body>
-<div style="width:1em; -moz-hyphens:auto;" lang="hr">
+<div style="width:1em; hyphens:auto;" lang="hr">
 Sva ljudska bića raćaju se slobodna i jednaka u dostojanstvu i pravima
 </div>
 </body>
 </html>
--- a/layout/reftests/text/auto-hyphenation-hsb-1-ref.html
+++ b/layout/reftests/text/auto-hyphenation-hsb-1-ref.html
@@ -1,11 +1,11 @@
 <!DOCTYPE html>
 <html>
 <head>
 <meta http-equiv="content-type" content="text/html; charset=utf-8">
 </head>
 <body>
-<div style="width:1em; -moz-hyphens:manual;" lang="hsb">
+<div style="width:1em; hyphens:manual;" lang="hsb">
 Wšitcy čło&shy;wje&shy;ko&shy;jo su wot na&shy;ro&shy;da swo&shy;bod&shy;ni a su je&shy;na&shy;cy po do&shy;stoj&shy;nos&shy;ći a pra&shy;wach
 </div>
 </body>
 </html>
--- a/layout/reftests/text/auto-hyphenation-hsb-1.html
+++ b/layout/reftests/text/auto-hyphenation-hsb-1.html
@@ -1,11 +1,11 @@
 <!DOCTYPE html>
 <html>
 <head>
 <meta http-equiv="content-type" content="text/html; charset=utf-8">
 </head>
 <body>
-<div style="width:1em; -moz-hyphens:auto;" lang="hsb">
+<div style="width:1em; hyphens:auto;" lang="hsb">
 Wšitcy čłowjekojo su wot naroda swobodni a su jenacy po dostojnosći a prawach
 </div>
 </body>
 </html>
--- a/layout/reftests/text/auto-hyphenation-hu-1-ref.html
+++ b/layout/reftests/text/auto-hyphenation-hu-1-ref.html
@@ -1,11 +1,11 @@
 <!DOCTYPE html>
 <html>
 <head>
 <meta http-equiv="content-type" content="text/html; charset=utf-8">
 </head>
 <body>
-<div style="width:1em; -moz-hyphens:manual;" lang="hu">
+<div style="width:1em; hyphens:manual;" lang="hu">
 Min&shy;den em&shy;be&shy;ri lény sza&shy;ba&shy;don szü&shy;le&shy;tik és egyen&shy;lő mél&shy;tó&shy;sá&shy;ga és jo&shy;ga van.
 </div>
 </body>
 </html>
--- a/layout/reftests/text/auto-hyphenation-hu-1.html
+++ b/layout/reftests/text/auto-hyphenation-hu-1.html
@@ -1,11 +1,11 @@
 <!DOCTYPE html>
 <html>
 <head>
 <meta http-equiv="content-type" content="text/html; charset=utf-8">
 </head>
 <body>
-<div style="width:1em; -moz-hyphens:auto;" lang="hu">
+<div style="width:1em; hyphens:auto;" lang="hu">
 Minden emberi lény szabadon születik és egyenlő méltósága és joga van.
 </div>
 </body>
 </html>
--- a/layout/reftests/text/auto-hyphenation-ia-1-ref.html
+++ b/layout/reftests/text/auto-hyphenation-ia-1-ref.html
@@ -1,11 +1,11 @@
 <!DOCTYPE html>
 <html>
 <head>
 <meta http-equiv="content-type" content="text/html; charset=utf-8">
 </head>
 <body>
-<div style="width:1em; -moz-hyphens:manual;" lang="ia">
+<div style="width:1em; hyphens:manual;" lang="ia">
 To&shy;te le es&shy;se&shy;res hu&shy;man na&shy;sce li&shy;be&shy;re e equal in dig&shy;ni&shy;ta&shy;te e in de&shy;rec&shy;tos
 </div>
 </body>
 </html>
--- a/layout/reftests/text/auto-hyphenation-ia-1.html
+++ b/layout/reftests/text/auto-hyphenation-ia-1.html
@@ -1,11 +1,11 @@
 <!DOCTYPE html>
 <html>
 <head>
 <meta http-equiv="content-type" content="text/html; charset=utf-8">
 </head>
 <body>
-<div style="width:1em; -moz-hyphens:auto;" lang="ia">
+<div style="width:1em; hyphens:auto;" lang="ia">
 Tote le esseres human nasce libere e equal in dignitate e in derectos
 </div>
 </body>
 </html>
--- a/layout/reftests/text/auto-hyphenation-is-1-ref.html
+++ b/layout/reftests/text/auto-hyphenation-is-1-ref.html
@@ -1,11 +1,11 @@
 <!DOCTYPE html>
 <html>
 <head>
 <meta http-equiv="content-type" content="text/html; charset=utf-8">
 </head>
 <body>
-<div style="width:1em; -moz-hyphens:manual;" lang="is">
+<div style="width:1em; hyphens:manual;" lang="is">
 Hver mað&shy;ur er bor&shy;inn frjáls og jafn öðr&shy;um að virð&shy;ingu og rétt&shy;ind&shy;um
 </div>
 </body>
 </html>
--- a/layout/reftests/text/auto-hyphenation-is-1.html
+++ b/layout/reftests/text/auto-hyphenation-is-1.html
@@ -1,11 +1,11 @@
 <!DOCTYPE html>
 <html>
 <head>
 <meta http-equiv="content-type" content="text/html; charset=utf-8">
 </head>
 <body>
-<div style="width:1em; -moz-hyphens:auto;" lang="is">
+<div style="width:1em; hyphens:auto;" lang="is">
 Hver maður er borinn frjáls og jafn öðrum að virðingu og réttindum
 </div>
 </body>
 </html>
--- a/layout/reftests/text/auto-hyphenation-it-1-ref.html
+++ b/layout/reftests/text/auto-hyphenation-it-1-ref.html
@@ -1,11 +1,11 @@
 <!DOCTYPE html>
 <html>
 <head>
 <meta http-equiv="content-type" content="text/html; charset=utf-8">
 </head>
 <body>
-<div style="width:1em; -moz-hyphens:manual;" lang="it">
+<div style="width:1em; hyphens:manual;" lang="it">
 Tut&shy;ti gli es&shy;se&shy;ri uma&shy;ni na&shy;sco&shy;no li&shy;be&shy;ri ed egua&shy;li in di&shy;gni&shy;tà e di&shy;rit&shy;ti.
 </div>
 </body>
 </html>
--- a/layout/reftests/text/auto-hyphenation-it-1.html
+++ b/layout/reftests/text/auto-hyphenation-it-1.html
@@ -1,11 +1,11 @@
 <!DOCTYPE html>
 <html>
 <head>
 <meta http-equiv="content-type" content="text/html; charset=utf-8">
 </head>
 <body>
-<div style="width:1em; -moz-hyphens:auto;" lang="it">
+<div style="width:1em; hyphens:auto;" lang="it">
 Tutti gli esseri umani nascono liberi ed eguali in dignità e diritti.
 </div>
 </body>
 </html>
--- a/layout/reftests/text/auto-hyphenation-kmr-1-ref.html
+++ b/layout/reftests/text/auto-hyphenation-kmr-1-ref.html
@@ -1,11 +1,11 @@
 <!DOCTYPE html>
 <html>
 <head>
 <meta http-equiv="content-type" content="text/html; charset=utf-8">
 </head>
 <body>
-<div style="width:1em; -moz-hyphens:manual;" lang="kmr">
+<div style="width:1em; hyphens:manual;" lang="kmr">
 He&shy;mû mi&shy;rov azad û di we&shy;qar û ma&shy;fan de we&shy;k&shy;hev tên din&shy;ya&shy;yê
 </div>
 </body>
 </html>
--- a/layout/reftests/text/auto-hyphenation-kmr-1.html
+++ b/layout/reftests/text/auto-hyphenation-kmr-1.html
@@ -1,11 +1,11 @@
 <!DOCTYPE html>
 <html>
 <head>
 <meta http-equiv="content-type" content="text/html; charset=utf-8">
 </head>
 <body>
-<div style="width:1em; -moz-hyphens:auto;" lang="kmr">
+<div style="width:1em; hyphens:auto;" lang="kmr">
 Hemû mirov azad û di weqar û mafan de wekhev tên dinyayê
 </div>
 </body>
 </html>
--- a/layout/reftests/text/auto-hyphenation-la-1-ref.html
+++ b/layout/reftests/text/auto-hyphenation-la-1-ref.html
@@ -1,11 +1,11 @@
 <!DOCTYPE html>
 <html>
 <head>
 <meta http-equiv="content-type" content="text/html; charset=utf-8">
 </head>
 <body>
-<div style="width:1em; -moz-hyphens:manual;" lang="la">
+<div style="width:1em; hyphens:manual;" lang="la">
 Om&shy;nes ho&shy;mi&shy;nes di&shy;gni&shy;ta&shy;te et iu&shy;re li&shy;be&shy;ri et pa&shy;res na&shy;scun&shy;tur
 </div>
 </body>
 </html>
--- a/layout/reftests/text/auto-hyphenation-la-1.html
+++ b/layout/reftests/text/auto-hyphenation-la-1.html
@@ -1,11 +1,11 @@
 <!DOCTYPE html>
 <html>
 <head>
 <meta http-equiv="content-type" content="text/html; charset=utf-8">
 </head>
 <body>
-<div style="width:1em; -moz-hyphens:auto;" lang="la">
+<div style="width:1em; hyphens:auto;" lang="la">
 Omnes homines dignitate et iure liberi et pares nascuntur
 </div>
 </body>
 </html>
--- a/layout/reftests/text/auto-hyphenation-lt-1-ref.html
+++ b/layout/reftests/text/auto-hyphenation-lt-1-ref.html
@@ -1,11 +1,11 @@
 <!DOCTYPE html>
 <html>
 <head>
 <meta http-equiv="content-type" content="text/html; charset=utf-8">
 </head>
 <body>
-<div style="width:1em; -moz-hyphens:manual;" lang="lt">
+<div style="width:1em; hyphens:manual;" lang="lt">
 Vi&shy;si žmo&shy;nės gims&shy;ta lais&shy;vi ir ly&shy;gūs sa&shy;vo oru&shy;mu ir tei&shy;sė&shy;mis.
 </div>
 </body>
 </html>
--- a/layout/reftests/text/auto-hyphenation-lt-1.html
+++ b/layout/reftests/text/auto-hyphenation-lt-1.html
@@ -1,11 +1,11 @@
 <!DOCTYPE html>
 <html>
 <head>
 <meta http-equiv="content-type" content="text/html; charset=utf-8">
 </head>
 <body>
-<div style="width:1em; -moz-hyphens:auto;" lang="lt">
+<div style="width:1em; hyphens:auto;" lang="lt">
 Visi žmonės gimsta laisvi ir lygūs savo orumu ir teisėmis.
 </div>
 </body>
 </html>
--- a/layout/reftests/text/auto-hyphenation-mn-1-ref.html
+++ b/layout/reftests/text/auto-hyphenation-mn-1-ref.html
@@ -1,11 +1,11 @@
 <!DOCTYPE html>
 <html>
 <head>
 <meta http-equiv="content-type" content="text/html; charset=utf-8">
 </head>
 <body>
-<div style="width:1em; -moz-hyphens:manual;" lang="mn">
+<div style="width:1em; hyphens:manual;" lang="mn">
 Хүн бүр төрж мэнд&shy;лэ&shy;хэд эрх чө&shy;лөө&shy;тэй, адил&shy;хан нэр төр&shy;тэй, ижил эрх&shy;тэй бай&shy;даг
 </div>
 </body>
 </html>
--- a/layout/reftests/text/auto-hyphenation-mn-1.html
+++ b/layout/reftests/text/auto-hyphenation-mn-1.html
@@ -1,11 +1,11 @@
 <!DOCTYPE html>
 <html>
 <head>
 <meta http-equiv="content-type" content="text/html; charset=utf-8">
 </head>
 <body>
-<div style="width:1em; -moz-hyphens:auto;" lang="mn">
+<div style="width:1em; hyphens:auto;" lang="mn">
 Хүн бүр төрж мэндлэхэд эрх чөлөөтэй, адилхан нэр төртэй, ижил эрхтэй байдаг
 </div>
 </body>
 </html>
--- a/layout/reftests/text/auto-hyphenation-nb-1-ref.html
+++ b/layout/reftests/text/auto-hyphenation-nb-1-ref.html
@@ -1,15 +1,15 @@
 <!DOCTYPE html>
 <html>
 <head>
 <meta http-equiv="content-type" content="text/html; charset=utf-8">
 </head>
 <body>
-<div style="width:1em; -moz-hyphens:manual;" lang="nb">
+<div style="width:1em; hyphens:manual;" lang="nb">
 Alle men&shy;nes&shy;ker er født frie og med sam&shy;me men&shy;neske&shy;verd og men&shy;neske&shy;ret&shy;tig&shy;he&shy;ter.
 <p>
 <!-- words that differ in nb/nn locales -->
 at&shy;ten&shy;de
 be&shy;tre
 </div>
 </body>
 </html>
--- a/layout/reftests/text/auto-hyphenation-nb-1.html
+++ b/layout/reftests/text/auto-hyphenation-nb-1.html
@@ -1,15 +1,15 @@
 <!DOCTYPE html>
 <html>
 <head>
 <meta http-equiv="content-type" content="text/html; charset=utf-8">
 </head>
 <body>
-<div style="width:1em; -moz-hyphens:auto;" lang="nb">
+<div style="width:1em; hyphens:auto;" lang="nb">
 Alle mennesker er født frie og med samme menneskeverd og menneskerettigheter.
 <p>
 <!-- words that differ in nb/nn locales -->
 attende
 betre
 </div>
 </body>
 </html>
--- a/layout/reftests/text/auto-hyphenation-nl-1-ref.html
+++ b/layout/reftests/text/auto-hyphenation-nl-1-ref.html
@@ -1,11 +1,11 @@
 <!DOCTYPE html>
 <html>
 <head>
 <meta http-equiv="content-type" content="text/html; charset=utf-8">
 </head>
 <body>
-<div style="width:1em; -moz-hyphens:manual;" lang="nl">
+<div style="width:1em; hyphens:manual;" lang="nl">
 Al&shy;le men&shy;sen wor&shy;den vrij en ge&shy;lijk in waar&shy;dig&shy;heid en rech&shy;ten ge&shy;bo&shy;ren
 </div>
 </body>
 </html>
--- a/layout/reftests/text/auto-hyphenation-nl-1.html
+++ b/layout/reftests/text/auto-hyphenation-nl-1.html
@@ -1,11 +1,11 @@
 <!DOCTYPE html>
 <html>
 <head>
 <meta http-equiv="content-type" content="text/html; charset=utf-8">
 </head>
 <body>
-<div style="width:1em; -moz-hyphens:auto;" lang="nl">
+<div style="width:1em; hyphens:auto;" lang="nl">
 Alle mensen worden vrij en gelijk in waardigheid en rechten geboren
 </div>
 </body>
 </html>
--- a/layout/reftests/text/auto-hyphenation-nn-1-ref.html
+++ b/layout/reftests/text/auto-hyphenation-nn-1-ref.html
@@ -1,15 +1,15 @@
 <!DOCTYPE html>
 <html>
 <head>
 <meta http-equiv="content-type" content="text/html; charset=utf-8">
 </head>
 <body>
-<div style="width:1em; -moz-hyphens:manual;" lang="nn">
+<div style="width:1em; hyphens:manual;" lang="nn">
 Alle men&shy;nes&shy;ke er fød&shy;de til fri&shy;dom og med same men&shy;neske&shy;verd og men&shy;neske&shy;ret&shy;tar.
 <p>
 <!-- words that differ in nb/nn locales -->
 att&shy;en&shy;de
 bet&shy;re
 </div>
 </body>
 </html>
--- a/layout/reftests/text/auto-hyphenation-nn-1.html
+++ b/layout/reftests/text/auto-hyphenation-nn-1.html
@@ -1,15 +1,15 @@
 <!DOCTYPE html>
 <html>
 <head>
 <meta http-equiv="content-type" content="text/html; charset=utf-8">
 </head>
 <body>
-<div style="width:1em; -moz-hyphens:auto;" lang="nn">
+<div style="width:1em; hyphens:auto;" lang="nn">
 Alle menneske er fødde til fridom og med same menneskeverd og menneskerettar.
 <p>
 <!-- words that differ in nb/nn locales -->
 attende
 betre
 </div>
 </body>
 </html>
--- a/layout/reftests/text/auto-hyphenation-pl-1.html
+++ b/layout/reftests/text/auto-hyphenation-pl-1.html
@@ -6,15 +6,15 @@
 <style>
 body {
   font-family: "Times New Roman", serif; /* prefer TNR to Times (default) on OS X... */
   font-feature-settings: 'kern' off;
 }
 </style>
 </head>
 <body>
-<div style="width:0pt; -moz-hyphens:auto">
+<div style="width:0pt; hyphens:auto">
 Unikod przypisuje unikalny numer każdemu znakowi,
 niezależny od używanej platformy,
 programu czy języka.
 </div>
 </body>
 </html>
--- a/layout/reftests/text/auto-hyphenation-pt-1-ref.html
+++ b/layout/reftests/text/auto-hyphenation-pt-1-ref.html
@@ -1,11 +1,11 @@
 <!DOCTYPE html>
 <html>
 <head>
 <meta http-equiv="content-type" content="text/html; charset=utf-8">
 </head>
 <body>
-<div style="width:1em; -moz-hyphens:manual;" lang="pt">
+<div style="width:1em; hyphens:manual;" lang="pt">
 To&shy;dos os se&shy;res hu&shy;ma&shy;nos nas&shy;cem li&shy;vres e iguais em dig&shy;ni&shy;da&shy;de e em di&shy;rei&shy;tos
 </div>
 </body>
 </html>
--- a/layout/reftests/text/auto-hyphenation-pt-1.html
+++ b/layout/reftests/text/auto-hyphenation-pt-1.html
@@ -1,11 +1,11 @@
 <!DOCTYPE html>
 <html>
 <head>
 <meta http-equiv="content-type" content="text/html; charset=utf-8">
 </head>
 <body>
-<div style="width:1em; -moz-hyphens:auto;" lang="pt">
+<div style="width:1em; hyphens:auto;" lang="pt">
 Todos os seres humanos nascem livres e iguais em dignidade e em direitos
 </div>
 </body>
 </html>
--- a/layout/reftests/text/auto-hyphenation-ru-1-ref.html
+++ b/layout/reftests/text/auto-hyphenation-ru-1-ref.html
@@ -1,11 +1,11 @@
 <!DOCTYPE html>
 <html>
 <head>
 <meta http-equiv="content-type" content="text/html; charset=utf-8">
 </head>
 <body>
-<div style="width:1em; -moz-hyphens:manual;" lang="ru">
+<div style="width:1em; hyphens:manual;" lang="ru">
 Все лю&shy;ди рож&shy;да&shy;ют&shy;ся сво&shy;бод&shy;ны&shy;ми и рав&shy;ны&shy;ми в сво&shy;ем до&shy;сто&shy;ин&shy;стве и пра&shy;вах.
 </div>
 </body>
 </html>
--- a/layout/reftests/text/auto-hyphenation-ru-1.html
+++ b/layout/reftests/text/auto-hyphenation-ru-1.html
@@ -1,11 +1,11 @@
 <!DOCTYPE html>
 <html>
 <head>
 <meta http-equiv="content-type" content="text/html; charset=utf-8">
 </head>
 <body>
-<div style="width:1em; -moz-hyphens:auto;" lang="ru">
+<div style="width:1em; hyphens:auto;" lang="ru">
 Все люди рождаются свободными и равными в своем достоинстве и правах.
 </div>
 </body>
 </html>
--- a/layout/reftests/text/auto-hyphenation-sh-1-ref.html
+++ b/layout/reftests/text/auto-hyphenation-sh-1-ref.html
@@ -1,13 +1,13 @@
 <!DOCTYPE html>
 <html>
 <head>
 <meta http-equiv="content-type" content="text/html; charset=utf-8">
 </head>
 <body>
-<div style="width:1em; -moz-hyphens:manual; font-size:5px" lang="sh">
+<div style="width:1em; hyphens:manual; font-size:5px" lang="sh">
 Сва људ&shy;ска би&shy;ћа ра&shy;ђа&shy;ју се сло&shy;бод&shy;на и јед&shy;на&shy;ка у до&shy;сто&shy;јан&shy;ству и пра&shy;ви&shy;ма.
 <p>
 Sva ljud&shy;ska bi&shy;ća ra&shy;đa&shy;ju se slo&shy;bod&shy;na i jed&shy;na&shy;ka u do&shy;sto&shy;jan&shy;stvu i pra&shy;vi&shy;ma.
 </div>
 </body>
 </html>
--- a/layout/reftests/text/auto-hyphenation-sh-1.html
+++ b/layout/reftests/text/auto-hyphenation-sh-1.html
@@ -1,13 +1,13 @@
 <!DOCTYPE html>
 <html>
 <head>
 <meta http-equiv="content-type" content="text/html; charset=utf-8">
 </head>
 <body>
-<div style="width:1em; -moz-hyphens:auto; font-size:5px" lang="sh">
+<div style="width:1em; hyphens:auto; font-size:5px" lang="sh">
 Сва људска бића рађају се слободна и једнака у достојанству и правима.
 <p>
 Sva ljudska bića rađaju se slobodna i jednaka u dostojanstvu i pravima.
 </div>
 </body>
 </html>
--- a/layout/reftests/text/auto-hyphenation-sl-1-ref.html
+++ b/layout/reftests/text/auto-hyphenation-sl-1-ref.html
@@ -1,11 +1,11 @@
 <!DOCTYPE html>
 <html>
 <head>
 <meta http-equiv="content-type" content="text/html; charset=utf-8">
 </head>
 <body>
-<div style="width:1em; -moz-hyphens:manual;" lang="sl">
+<div style="width:1em; hyphens:manual;" lang="sl">
 Vsi lju&shy;dje se ro&shy;di&shy;jo svo&shy;bo&shy;dni in ima&shy;jo ena&shy;ko do&shy;sto&shy;jan&shy;stvo in ena&shy;ke pra&shy;vi&shy;ce
 </div>
 </body>
 </html>
--- a/layout/reftests/text/auto-hyphenation-sl-1.html
+++ b/layout/reftests/text/auto-hyphenation-sl-1.html
@@ -1,11 +1,11 @@
 <!DOCTYPE html>
 <html>
 <head>
 <meta http-equiv="content-type" content="text/html; charset=utf-8">
 </head>
 <body>
-<div style="width:1em; -moz-hyphens:auto;" lang="sl">
+<div style="width:1em; hyphens:auto;" lang="sl">
 Vsi ljudje se rodijo svobodni in imajo enako dostojanstvo in enake pravice
 </div>
 </body>
 </html>
--- a/layout/reftests/text/auto-hyphenation-sr-1-ref.html
+++ b/layout/reftests/text/auto-hyphenation-sr-1-ref.html
@@ -1,13 +1,13 @@
 <!DOCTYPE html>
 <html>
 <head>
 <meta http-equiv="content-type" content="text/html; charset=utf-8">
 </head>
 <body>
-<div style="width:1em; -moz-hyphens:manual; font-size:5px" lang="sr">
+<div style="width:1em; hyphens:manual; font-size:5px" lang="sr">
 Сва људ&shy;ска би&shy;ћа ра&shy;ђа&shy;ју се сло&shy;бод&shy;на и јед&shy;на&shy;ка у до&shy;сто&shy;јан&shy;ству и пра&shy;ви&shy;ма.
 <p>
 Sva ljud&shy;ska bi&shy;ća ra&shy;đa&shy;ju se slo&shy;bod&shy;na i jed&shy;na&shy;ka u do&shy;sto&shy;jan&shy;stvu i pra&shy;vi&shy;ma.
 </div>
 </body>
 </html>
--- a/layout/reftests/text/auto-hyphenation-sr-1.html
+++ b/layout/reftests/text/auto-hyphenation-sr-1.html
@@ -1,13 +1,13 @@
 <!DOCTYPE html>
 <html>
 <head>
 <meta http-equiv="content-type" content="text/html; charset=utf-8">
 </head>
 <body>
-<div style="width:1em; -moz-hyphens:auto; font-size:5px" lang="sr">
+<div style="width:1em; hyphens:auto; font-size:5px" lang="sr">
 Сва људска бића рађају се слободна и једнака у достојанству и правима.
 <p>
 Sva ljudska bića rađaju se slobodna i jednaka u dostojanstvu i pravima.
 </div>
 </body>
 </html>
--- a/layout/reftests/text/auto-hyphenation-sv-1-notref.html
+++ b/layout/reftests/text/auto-hyphenation-sv-1-notref.html
@@ -1,11 +1,11 @@
 <!DOCTYPE html>
 <html>
 <head>
 <meta http-equiv="content-type" content="text/html; charset=utf-8">
 </head>
 <body>
-<div style="width:1em; -moz-hyphens:auto;" lang="en-US">
+<div style="width:1em; hyphens:auto;" lang="en-US">
 Alla människor äro födda fria och lika i värde och rättigheter
 </div>
 </body>
 </html>
--- a/layout/reftests/text/auto-hyphenation-sv-1-ref.html
+++ b/layout/reftests/text/auto-hyphenation-sv-1-ref.html
@@ -1,11 +1,11 @@
 <!DOCTYPE html>
 <html>
 <head>
 <meta http-equiv="content-type" content="text/html; charset=utf-8">
 </head>
 <body>
-<div style="width:1em; -moz-hyphens:manual;" lang="sv">
+<div style="width:1em; hyphens:manual;" lang="sv">
 Al&shy;la män&shy;ni&shy;skor äro föd&shy;da fria och li&shy;ka i vär&shy;de och rät&shy;tig&shy;he&shy;ter
 </div>
 </body>
 </html>
--- a/layout/reftests/text/auto-hyphenation-sv-1.html
+++ b/layout/reftests/text/auto-hyphenation-sv-1.html
@@ -1,11 +1,11 @@
 <!DOCTYPE html>
 <html>
 <head>
 <meta http-equiv="content-type" content="text/html; charset=utf-8">
 </head>
 <body>
-<div style="width:1em; -moz-hyphens:auto;" lang="sv">
+<div style="width:1em; hyphens:auto;" lang="sv">
 Alla människor äro födda fria och lika i värde och rättigheter
 </div>
 </body>
 </html>
--- a/layout/reftests/text/auto-hyphenation-tr-1-ref.html
+++ b/layout/reftests/text/auto-hyphenation-tr-1-ref.html
@@ -1,11 +1,11 @@
 <!DOCTYPE html>
 <html>
 <head>
 <meta http-equiv="content-type" content="text/html; charset=utf-8">
 </head>
 <body>
-<div style="width:1em; -moz-hyphens:manual;" lang="tr">
+<div style="width:1em; hyphens:manual;" lang="tr">
 Bü&shy;tün in&shy;san&shy;lar hür, hay&shy;si&shy;yet ve hak&shy;lar ba&shy;kı&shy;mın&shy;dan eşit do&shy;ğar&shy;lar.
 </div>
 </body>
 </html>
--- a/layout/reftests/text/auto-hyphenation-tr-1.html
+++ b/layout/reftests/text/auto-hyphenation-tr-1.html
@@ -1,11 +1,11 @@
 <!DOCTYPE html>
 <html>
 <head>
 <meta http-equiv="content-type" content="text/html; charset=utf-8">
 </head>
 <body>
-<div style="width:1em; -moz-hyphens:auto;" lang="tr">
+<div style="width:1em; hyphens:auto;" lang="tr">
 Bütün insanlar hür, haysiyet ve haklar bakımından eşit doğarlar.
 </div>
 </body>
 </html>
--- a/layout/reftests/text/auto-hyphenation-transformed-1.html
+++ b/layout/reftests/text/auto-hyphenation-transformed-1.html
@@ -1,18 +1,18 @@
 <!DOCTYPE html>
 <html lang="de">
 <head>
 <meta charset="utf-8">
 <title>Test for auto hyphenation with text-transform</title>
 </head>
 <body>
-<div style="width:0px; -moz-hyphens:auto">
+<div style="width:0px; hyphens:auto">
 masse<br>maße
 </div>
-<div style="width:0px; -moz-hyphens:auto; text-transform:uppercase">
+<div style="width:0px; hyphens:auto; text-transform:uppercase">
 masse<br>maße
 </div>
-<div style="width:0px; -moz-hyphens:auto; text-transform:capitalize">
+<div style="width:0px; hyphens:auto; text-transform:capitalize">
 masse<br>maße
 </div>
 </body>
 </html>
--- a/layout/reftests/text/auto-hyphenation-uk-1-ref.html
+++ b/layout/reftests/text/auto-hyphenation-uk-1-ref.html
@@ -1,11 +1,11 @@
 <!DOCTYPE html>
 <html>
 <head>
 <meta http-equiv="content-type" content="text/html; charset=utf-8">
 </head>
 <body>
-<div style="width:1em; -moz-hyphens:manual;" lang="uk">
+<div style="width:1em; hyphens:manual;" lang="uk">
 Всі лю&shy;ди на&shy;ро&shy;джу&shy;ю&shy;ться віль&shy;ни&shy;ми і рів&shy;ни&shy;ми у сво&shy;їй гі&shy;дно&shy;сті та пра&shy;вах
 </div>
 </body>
 </html>
--- a/layout/reftests/text/auto-hyphenation-uk-1.html
+++ b/layout/reftests/text/auto-hyphenation-uk-1.html
@@ -1,11 +1,11 @@
 <!DOCTYPE html>
 <html>
 <head>
 <meta http-equiv="content-type" content="text/html; charset=utf-8">
 </head>
 <body>
-<div style="width:1em; -moz-hyphens:auto;" lang="uk">
+<div style="width:1em; hyphens:auto;" lang="uk">
 Всі люди народжуються вільними і рівними у своїй гідності та правах
 </div>
 </body>
 </html>
--- a/layout/reftests/text/auto-hyphenation-xmllang-1.xhtml
+++ b/layout/reftests/text/auto-hyphenation-xmllang-1.xhtml
@@ -1,11 +1,11 @@
 <!DOCTYPE html>
 <html xmlns="http://www.w3.org/1999/xhtml">
 <head><title>Hyphenation test</title></head>
 <!-- simple test for automatic hyphenation -->
 <body xml:lang="en-us">
-<div style="width: 5em; -moz-hyphens: auto; font-family:sans-serif;">
+<div style="width: 5em; hyphens: auto; font-family:sans-serif;">
 supercalifragilisticexpialidocious
 </div>
 </body>
 </html>
 
--- a/layout/reftests/text/auto-hyphenation-xmllang-10.xhtml
+++ b/layout/reftests/text/auto-hyphenation-xmllang-10.xhtml
@@ -1,12 +1,12 @@
 <?xml version="1.0" encoding="UTF-8" ?>
 <!DOCTYPE html>
 <html xmlns="http://www.w3.org/1999/xhtml">
 <head><title>Hyphenation test</title></head>
 <!-- check that hyphenation is not applied when language is not specified -->
 <body>
-<div style="width: 5em; -moz-hyphens: auto;">
+<div style="width: 5em; hyphens: auto;">
 supercalifragilisticexpialidocious
 </div>
 </body>
 </html>
 
--- a/layout/reftests/text/auto-hyphenation-xmllang-11a.xhtml
+++ b/layout/reftests/text/auto-hyphenation-xmllang-11a.xhtml
@@ -1,11 +1,11 @@
 <!DOCTYPE html>
 <html xmlns="http://www.w3.org/1999/xhtml">
 <head><title>Hyphenation test</title></head>
 <!-- check that xml:lang beats lang -->
 <body xml:lang="en-us" lang="x-unknown-language">
-<div style="width: 5em; -moz-hyphens: auto; font-family:sans-serif;">
+<div style="width: 5em; hyphens: auto; font-family:sans-serif;">
 supercalifragilisticexpialidocious
 </div>
 </body>
 </html>
 
--- a/layout/reftests/text/auto-hyphenation-xmllang-11b.xhtml
+++ b/layout/reftests/text/auto-hyphenation-xmllang-11b.xhtml
@@ -1,11 +1,11 @@
 <!DOCTYPE html>
 <html xmlns="http://www.w3.org/1999/xhtml">
 <head><title>Hyphenation test</title></head>
 <!-- check that xml:lang beats lang -->
 <body lang="x-unknown-language" xml:lang="en-us">
-<div style="width: 5em; -moz-hyphens: auto; font-family:sans-serif;">
+<div style="width: 5em; hyphens: auto; font-family:sans-serif;">
 supercalifragilisticexpialidocious
 </div>
 </body>
 </html>
 
--- a/layout/reftests/text/auto-hyphenation-xmllang-12a.xhtml
+++ b/layout/reftests/text/auto-hyphenation-xmllang-12a.xhtml
@@ -1,12 +1,12 @@
 <!DOCTYPE html>
 <html xmlns="http://www.w3.org/1999/xhtml">
 <head><title>Hyphenation test</title></head>
 <!-- check that xml:lang beats lang -->
 <!-- check that hyphenation is not applied to unknown language -->
 <body xml:lang="x-unknown-language" lang="en-us">
-<div style="width: 5em; -moz-hyphens: auto;">
+<div style="width: 5em; hyphens: auto;">
 supercalifragilisticexpialidocious
 </div>
 </body>
 </html>
 
--- a/layout/reftests/text/auto-hyphenation-xmllang-12b.xhtml
+++ b/layout/reftests/text/auto-hyphenation-xmllang-12b.xhtml
@@ -1,12 +1,12 @@
 <!DOCTYPE html>
 <html xmlns="http://www.w3.org/1999/xhtml">
 <head><title>Hyphenation test</title></head>
 <!-- check that xml:lang beats lang -->
 <!-- check that hyphenation is not applied to unknown language -->
 <body lang="en-us" xml:lang="x-unknown-language">
-<div style="width: 5em; -moz-hyphens: auto;">
+<div style="width: 5em; hyphens: auto;">
 supercalifragilisticexpialidocious
 </div>
 </body>
 </html>
 
--- a/layout/reftests/text/auto-hyphenation-xmllang-13a.xhtml
+++ b/layout/reftests/text/auto-hyphenation-xmllang-13a.xhtml
@@ -1,13 +1,13 @@
 <!DOCTYPE html>
 <html xmlns="http://www.w3.org/1999/xhtml">
 <head><title>Hyphenation test</title></head>
 <!-- check that innermost beats xml:lang vs. lang difference -->
 <body lang="x-unknown-language">
 <div xml:lang="en-us">
-<div style="width: 5em; -moz-hyphens: auto; font-family:sans-serif;">
+<div style="width: 5em; hyphens: auto; font-family:sans-serif;">
 supercalifragilisticexpialidocious
 </div>
 </div>
 </body>
 </html>
 
--- a/layout/reftests/text/auto-hyphenation-xmllang-13b.xhtml
+++ b/layout/reftests/text/auto-hyphenation-xmllang-13b.xhtml
@@ -1,13 +1,13 @@
 <!DOCTYPE html>
 <html xmlns="http://www.w3.org/1999/xhtml">
 <head><title>Hyphenation test</title></head>
 <!-- check that innermost beats xml:lang vs. lang difference -->
 <body xml:lang="x-unknown-language">
 <div lang="en-us">
-<div style="width: 5em; -moz-hyphens: auto; font-family:sans-serif;">
+<div style="width: 5em; hyphens: auto; font-family:sans-serif;">
 supercalifragilisticexpialidocious
 </div>
 </div>
 </body>
 </html>
 
--- a/layout/reftests/text/auto-hyphenation-xmllang-14a.xhtml
+++ b/layout/reftests/text/auto-hyphenation-xmllang-14a.xhtml
@@ -1,14 +1,14 @@
 <!DOCTYPE html>
 <html xmlns="http://www.w3.org/1999/xhtml">
 <head><title>Hyphenation test</title></head>
 <!-- check that innermost beats xml:lang vs. lang difference -->
 <!-- check that hyphenation is not applied to unknown language -->
 <body lang="en-us">
 <div xml:lang="x-unknown-language">
-<div style="width: 5em; -moz-hyphens: auto;">
+<div style="width: 5em; hyphens: auto;">
 supercalifragilisticexpialidocious
 </div>
 </div>
 </body>
 </html>
 
--- a/layout/reftests/text/auto-hyphenation-xmllang-14b.xhtml
+++ b/layout/reftests/text/auto-hyphenation-xmllang-14b.xhtml
@@ -1,14 +1,14 @@
 <!DOCTYPE html>
 <html xmlns="http://www.w3.org/1999/xhtml">
 <head><title>Hyphenation test</title></head>
 <!-- check that innermost beats xml:lang vs. lang difference -->
 <!-- check that hyphenation is not applied to unknown language -->
 <body xml:lang="en-us">
 <div lang="x-unknown-language">
-<div style="width: 5em; -moz-hyphens: auto;">
+<div style="width: 5em; hyphens: auto;">
 supercalifragilisticexpialidocious
 </div>
 </div>
 </body>
 </html>
 
--- a/layout/reftests/text/auto-hyphenation-xmllang-1a.xhtml
+++ b/layout/reftests/text/auto-hyphenation-xmllang-1a.xhtml
@@ -1,11 +1,11 @@
 <!DOCTYPE html>
 <html xmlns="http://www.w3.org/1999/xhtml">
 <head><title>Hyphenation test</title></head>
 <!-- adding random <span>s should not affect hyphenation -->
 <body xml:lang="en-us">
-<div style="width: 5em; -moz-hyphens: auto; font-family:sans-serif;">
+<div style="width: 5em; hyphens: auto; font-family:sans-serif;">
 super<span>cali</span>frag<span>ili</span>sti<span>cex</span>pialidoc<span>i</span>ous
 </div>
 </body>
 </html>
 
--- a/layout/reftests/text/auto-hyphenation-xmllang-2.xhtml
+++ b/layout/reftests/text/auto-hyphenation-xmllang-2.xhtml
@@ -1,13 +1,13 @@
 <!DOCTYPE html>
 <html xmlns="http://www.w3.org/1999/xhtml">
 <head><title>Hyphenation test</title></head>
 <!-- mixed languages in a word should inhibit automatic hyphenation -->
 <body xml:lang="en-us">
-<div style="width: 5em; -moz-hyphens: auto; font-family:sans-serif;">
+<div style="width: 5em; hyphens: auto; font-family:sans-serif;">
 supercalifragilisticexpialidocious
 super<span xml:lang="foo">cali</span>fragilisticexpialidocious
 supercalifragilisticexpialidocious
 </div>
 </body>
 </html>
 
--- a/layout/reftests/text/auto-hyphenation-xmllang-3.xhtml
+++ b/layout/reftests/text/auto-hyphenation-xmllang-3.xhtml
@@ -1,11 +1,11 @@
 <!DOCTYPE html>
 <html xmlns="http://www.w3.org/1999/xhtml">
 <head><title>Hyphenation test</title></head>
-<!-- check that -moz-hyphens:none prevents break at &shy; -->
+<!-- check that hyphens:none prevents break at &shy; -->
 <body xml:lang="en-us">
-<div style="width: 5em; -moz-hyphens: none;">
+<div style="width: 5em; hyphens: none;">
 su&#173;per&#173;cal&#173;ifrag&#173;ilis&#173;tic&#173;ex&#173;pi&#173;ali&#173;do&#173;cious
 </div>
 </body>
 </html>
 
--- a/layout/reftests/text/auto-hyphenation-xmllang-4.xhtml
+++ b/layout/reftests/text/auto-hyphenation-xmllang-4.xhtml
@@ -1,11 +1,11 @@
 <!DOCTYPE html>
 <html xmlns="http://www.w3.org/1999/xhtml">
 <head><title>Hyphenation test</title></head>
 <!-- check that hyphenation is not applied to unknown language -->
 <body xml:lang="x-unknown-language">
-<div style="width: 5em; -moz-hyphens: auto;">
+<div style="width: 5em; hyphens: auto;">
 supercalifragilisticexpialidocious
 </div>
 </body>
 </html>
 
--- a/layout/reftests/text/auto-hyphenation-xmllang-5.xhtml
+++ b/layout/reftests/text/auto-hyphenation-xmllang-5.xhtml
@@ -1,17 +1,17 @@
 <!DOCTYPE html>
 <html xmlns="http://www.w3.org/1999/xhtml">
 <head>
 <style type="text/css">
 div {
   margin:       10px;
   width:        10px;
   font-family:  monospace;
-  -moz-hyphens: auto;
+  hyphens: auto;
 }
 </style>
 </head>
 <!-- test some hyphenations that involve overlapping patterns -->
 <body xml:lang="en-us">
 <div>
 photo
 </div>
--- a/layout/reftests/text/auto-hyphenation-xmllang-6.xhtml
+++ b/layout/reftests/text/auto-hyphenation-xmllang-6.xhtml
@@ -1,11 +1,11 @@
 <!DOCTYPE html>
 <html xmlns="http://www.w3.org/1999/xhtml">
 <head><title>Hyphenation test</title></head>
 <!-- style changes don't break hyphenation -->
 <body xml:lang="en-us">
-<div style="width: 0; -moz-hyphens: auto;">
+<div style="width: 0; hyphens: auto;">
 hy<span style="color:red">phen</span>ation
 </div>
 </body>
 </html>
 
--- a/layout/reftests/text/auto-hyphenation-xmllang-7.xhtml
+++ b/layout/reftests/text/auto-hyphenation-xmllang-7.xhtml
@@ -1,11 +1,11 @@
 <!DOCTYPE html>
 <html xmlns="http://www.w3.org/1999/xhtml">
 <head><title>Hyphenation test</title></head>
 <!-- style changes don't break hyphenation -->
 <body xml:lang="en-us">
-<div style="width: 0; -moz-hyphens: auto;">
+<div style="width: 0; hyphens: auto;">
 h<span style="color:red">yphena</span>tion
 </div>
 </body>
 </html>
 
--- a/layout/reftests/text/auto-hyphenation-xmllang-8.xhtml
+++ b/layout/reftests/text/auto-hyphenation-xmllang-8.xhtml
@@ -1,11 +1,11 @@
 <!DOCTYPE html>
 <html xmlns="http://www.w3.org/1999/xhtml">
 <head><title>Hyphenation test</title></head>
 <!-- check that hyphenation is not applied when language is not specified -->
 <body>
-<div style="width: 5em; -moz-hyphens: auto;">
+<div style="width: 5em; hyphens: auto;">
 supercalifragilisticexpialidocious
 </div>
 </body>
 </html>
 
--- a/layout/reftests/text/auto-hyphenation-xmllang-9.xhtml
+++ b/layout/reftests/text/auto-hyphenation-xmllang-9.xhtml
@@ -1,12 +1,12 @@
 <?xml version="1.0" encoding="iso-8859-1" ?>
 <!DOCTYPE html>
 <html xmlns="http://www.w3.org/1999/xhtml">
 <head><title>Hyphenation test</title></head>
 <!-- check that hyphenation is not applied when language is not specified -->
 <body>
-<div style="width: 5em; -moz-hyphens: auto;">
+<div style="width: 5em; hyphens: auto;">
 supercalifragilisticexpialidocious
 </div>
 </body>
 </html>
 
--- a/layout/reftests/text/reftest.list
+++ b/layout/reftests/text/reftest.list
@@ -219,17 +219,17 @@ HTTP(..) == graphite-05-lang.html graphi
 HTTP(..) == graphite-05-badlang.html graphite-05-ref.html
 HTTP(..) == graphite-05-feat.html graphite-05-ref.html
 
 # comparing composed and decomposed characters that should render identically
 # under both OpenType and Graphite shaping
 pref(gfx.font_rendering.graphite.enabled,false) HTTP(..) == glyph-decomposition-opentype.html glyph-decomposition-opentype-ref.html
 pref(gfx.font_rendering.graphite.enabled,true) HTTP(..) == glyph-decomposition-graphite.html glyph-decomposition-graphite-ref.html
 
-# Tests for hyphenation with -moz-hyphens
+# Tests for hyphenation with hyphens property
 == auto-hyphenation-1.html auto-hyphenation-1-ref.html
 != auto-hyphenation-1.html auto-hyphenation-1-notref.html
 == auto-hyphenation-1a.html auto-hyphenation-1-ref.html
 == auto-hyphenation-2.html auto-hyphenation-2-ref.html
 == auto-hyphenation-3.html auto-hyphenation-3-ref.html
 == auto-hyphenation-4.html auto-hyphenation-4-ref.html
 == auto-hyphenation-5.html auto-hyphenation-5-ref.html
 == auto-hyphenation-6.html auto-hyphenation-6-ref.html
--- a/layout/style/nsAnimationManager.cpp
+++ b/layout/style/nsAnimationManager.cpp
@@ -546,16 +546,32 @@ nsAnimationManager::CheckAnimationRule(n
   // nsPresShell::FlushPendingNotifications.
   if (mEventDispatcher.HasQueuedEvents()) {
     mPresContext->Document()->SetNeedStyleFlush();
   }
 
   return GetAnimationRule(aElement, aStyleContext->GetPseudoType());
 }
 
+void
+nsAnimationManager::StopAnimationsForElement(
+  mozilla::dom::Element* aElement,
+  nsCSSPseudoElements::Type aPseudoType)
+{
+  MOZ_ASSERT(aElement);
+  AnimationCollection* collection =
+    GetAnimations(aElement, aPseudoType, false);
+  if (!collection) {
+    return;
+  }
+
+  nsAutoAnimationMutationBatch mb(aElement->OwnerDoc());
+  collection->Destroy();
+}
+
 struct KeyframeData {
   float mKey;
   uint32_t mIndex; // store original order since sort algorithm is not stable
   nsCSSKeyframeRule *mRule;
 };
 
 struct KeyframeDataComparator {
   bool Equals(const KeyframeData& A, const KeyframeData& B) const {
--- a/layout/style/nsAnimationManager.h
+++ b/layout/style/nsAnimationManager.h
@@ -285,16 +285,22 @@ public:
    * animationiteration events only during refresh driver notifications
    * (and dispatch them at the end of such notifications), but we
    * accumulate animationstart events at other points when style
    * contexts are created.
    */
   void DispatchEvents()  { mEventDispatcher.DispatchEvents(mPresContext); }
   void ClearEventQueue() { mEventDispatcher.ClearEventQueue(); }
 
+  // Stop animations on the element. This method takes the real element
+  // rather than the element for the generated content for animations on
+  // ::before and ::after.
+  void StopAnimationsForElement(mozilla::dom::Element* aElement,
+                                nsCSSPseudoElements::Type aPseudoType);
+
 protected:
   virtual ~nsAnimationManager() {}
 
   virtual nsIAtom* GetAnimationsAtom() override {
     return nsGkAtoms::animationsProperty;
   }
   virtual nsIAtom* GetAnimationsBeforeAtom() override {
     return nsGkAtoms::animationsOfBeforeProperty;
--- a/layout/style/nsCSSPropAliasList.h
+++ b/layout/style/nsCSSPropAliasList.h
@@ -170,8 +170,12 @@ CSS_PROP_ALIAS(-moz-border-start-color,
 CSS_PROP_ALIAS(-moz-border-start-style,
                border_inline_start_style,
                MozBorderStartStyle,
                "")
 CSS_PROP_ALIAS(-moz-border-start-width,
                border_inline_start_width,
                MozBorderStartWidth,
                "")
+CSS_PROP_ALIAS(-moz-hyphens,
+               hyphens,
+               MozHyphens,
+               "")
--- a/layout/style/nsCSSPropList.h
+++ b/layout/style/nsCSSPropList.h
@@ -3635,19 +3635,19 @@ CSS_PROP_TEXT(
     WordWrap,
     CSS_PROPERTY_PARSE_VALUE,
     "",
     VARIANT_HK,
     kWordWrapKTable,
     CSS_PROP_NO_OFFSET,
     eStyleAnimType_None)
 CSS_PROP_TEXT(
-    -moz-hyphens,
+    hyphens,
     hyphens,
-    CSS_PROP_DOMPROP_PREFIXED(Hyphens),
+    Hyphens,
     CSS_PROPERTY_PARSE_VALUE,
     "",
     VARIANT_HK,
     kHyphensKTable,
     CSS_PROP_NO_OFFSET,
     eStyleAnimType_None)
 CSS_PROP_VISIBILITY(
     writing-mode,
--- a/layout/style/nsComputedDOMStylePropertyList.h
+++ b/layout/style/nsComputedDOMStylePropertyList.h
@@ -140,16 +140,17 @@ COMPUTED_STYLE_PROP(grid_auto_rows,     
 COMPUTED_STYLE_PROP(grid_column_end,               GridColumnEnd)
 COMPUTED_STYLE_PROP(grid_column_start,             GridColumnStart)
 COMPUTED_STYLE_PROP(grid_row_end,                  GridRowEnd)
 COMPUTED_STYLE_PROP(grid_row_start,                GridRowStart)
 COMPUTED_STYLE_PROP(grid_template_areas,           GridTemplateAreas)
 COMPUTED_STYLE_PROP(grid_template_columns,         GridTemplateColumns)
 COMPUTED_STYLE_PROP(grid_template_rows,            GridTemplateRows)
 COMPUTED_STYLE_PROP(height,                        Height)
+COMPUTED_STYLE_PROP(hyphens,                       Hyphens)
 COMPUTED_STYLE_PROP(image_orientation,             ImageOrientation)
 COMPUTED_STYLE_PROP(ime_mode,                      IMEMode)
 COMPUTED_STYLE_PROP(isolation,                     Isolation)
 COMPUTED_STYLE_PROP(justify_content,               JustifyContent)
 COMPUTED_STYLE_PROP(left,                          Left)
 COMPUTED_STYLE_PROP(letter_spacing,                LetterSpacing)
 COMPUTED_STYLE_PROP(line_height,                   LineHeight)
 //// COMPUTED_STYLE_PROP(list_style,               ListStyle)
@@ -265,17 +266,16 @@ COMPUTED_STYLE_PROP(_moz_column_fill,   
 COMPUTED_STYLE_PROP(_moz_column_gap,               ColumnGap)
 //// COMPUTED_STYLE_PROP(_moz_column_rule,         ColumnRule)
 COMPUTED_STYLE_PROP(_moz_column_rule_color,        ColumnRuleColor)
 COMPUTED_STYLE_PROP(_moz_column_rule_style,        ColumnRuleStyle)
 COMPUTED_STYLE_PROP(_moz_column_rule_width,        ColumnRuleWidth)
 COMPUTED_STYLE_PROP(_moz_column_width,             ColumnWidth)
 COMPUTED_STYLE_PROP(float_edge,                    FloatEdge)
 COMPUTED_STYLE_PROP(force_broken_image_icon,       ForceBrokenImageIcon)
-COMPUTED_STYLE_PROP(hyphens,                       Hyphens)
 COMPUTED_STYLE_PROP(image_region,                  ImageRegion)
 COMPUTED_STYLE_PROP(orient,                        Orient)
 COMPUTED_STYLE_PROP(osx_font_smoothing,            OsxFontSmoothing)
 COMPUTED_STYLE_PROP(_moz_outline_radius_bottomLeft, OutlineRadiusBottomLeft)
 COMPUTED_STYLE_PROP(_moz_outline_radius_bottomRight,OutlineRadiusBottomRight)
 COMPUTED_STYLE_PROP(_moz_outline_radius_topLeft,    OutlineRadiusTopLeft)
 COMPUTED_STYLE_PROP(_moz_outline_radius_topRight,   OutlineRadiusTopRight)
 COMPUTED_STYLE_PROP(stack_sizing,                  StackSizing)
--- a/layout/style/test/property_database.js
+++ b/layout/style/test/property_database.js
@@ -3676,18 +3676,18 @@ var gCSSProperties = {
   "word-wrap": {
     domProp: "wordWrap",
     inherited: true,
     type: CSS_TYPE_LONGHAND,
     initial_values: [ "normal" ],
     other_values: [ "break-word" ],
     invalid_values: []
   },
-  "-moz-hyphens": {
-    domProp: "MozHyphens",
+  "hyphens": {
+    domProp: "hyphens",
     inherited: true,
     type: CSS_TYPE_LONGHAND,
     initial_values: [ "manual" ],
     other_values: [ "none", "auto" ],
     invalid_values: []
   },
   "z-index": {
     domProp: "zIndex",
@@ -4551,16 +4551,26 @@ var gCSSProperties = {
     domProp: "MozFontLanguageOverride",
     inherited: true,
     type: CSS_TYPE_SHORTHAND_AND_LONGHAND,
     alias_for: "font-language-override",
     subproperties: [ "font-language-override" ],
     initial_values: [ "normal" ],
     other_values: [ "'ENG'", "'TRK'", "\"TRK\"", "'N\\'Ko'" ],
     invalid_values: [ "TRK", "ja" ]
+  },
+  "-moz-hyphens": {
+    domProp: "MozHyphens",
+    inherited: true,
+    type: CSS_TYPE_SHORTHAND_AND_LONGHAND,
+    alias_for: "hyphens",
+    subproperties: [ "hyphens" ],
+    initial_values: [ "manual" ],
+    other_values: [ "none", "auto" ],
+    invalid_values: []
   }
 }
 
 function logical_axis_prop_get_computed(cs, property)
 {
   // Use defaults for these two properties in case the vertical text
   // pref (which they live behind) is turned off.
   var writingMode = cs.getPropertyValue("writing-mode") || "horizontal-tb";
--- a/layout/style/xbl-marquee/jar.mn
+++ b/layout/style/xbl-marquee/jar.mn
@@ -1,8 +1,8 @@
 # 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/.
 
 toolkit.jar:
-%   content xbl-marquee %content/xbl-marquee/
+%   content xbl-marquee %content/xbl-marquee/ contentaccessible=yes
     content/xbl-marquee/xbl-marquee.xml
     content/xbl-marquee/xbl-marquee.css
--- a/media/libstagefright/binding/H264.cpp
+++ b/media/libstagefright/binding/H264.cpp
@@ -489,22 +489,26 @@ H264::DecodeSPSFromExtraData(const mozil
     return false;
   }
 
   const uint8_t* ptr = reader.Read(length);
   if (!ptr) {
     return false;
   }
 
+  reader.DiscardRemaining();
+
   nsRefPtr<mozilla::MediaByteBuffer> rawNAL = new mozilla::MediaByteBuffer;
   rawNAL->AppendElements(ptr, length);
 
   nsRefPtr<mozilla::MediaByteBuffer> sps = DecodeNALUnit(rawNAL);
 
-  reader.DiscardRemaining();
+  if (!sps) {
+    return false;
+  }
 
   return DecodeSPS(sps, aDest);
 }
 
 /* static */ bool
 H264::EnsureSPSIsSane(SPSData& aSPS)
 {
   bool valid = true;
--- a/media/libstagefright/frameworks/av/media/libstagefright/MPEG4Extractor.cpp
+++ b/media/libstagefright/frameworks/av/media/libstagefright/MPEG4Extractor.cpp
@@ -1325,21 +1325,16 @@ status_t MPEG4Extractor::parseChunk(off6
             if (!mLastTrack) {
               return ERROR_MALFORMED;
             }
             if (chunk_type != FOURCC('e', 'n', 'c', 'a')) {
                 // if the chunk type is enca, we'll get the type from the sinf/frma box later
                 mLastTrack->meta->setCString(kKeyMIMEType, FourCC2MIME(chunk_type));
                 AdjustChannelsAndRate(chunk_type, &num_channels, &sample_rate);
             }
-            ALOGV("*** coding='%s' %d channels, size %d, rate %d\n",
-                   chunk, num_channels, sample_size, sample_rate);
-            mLastTrack->meta->setInt32(kKeyChannelCount, num_channels);
-            mLastTrack->meta->setInt32(kKeySampleSize, sample_size);
-            mLastTrack->meta->setInt32(kKeySampleRate, sample_rate);
 
             uint64_t skip = 0;
             if (qt_version == 1) {
                 // Skip QTv1 extension
                 // uint32_t SamplesPerPacket
                 // uint32_t BytesPerPacket
                 // uint32_t BytesPerFrame
                 // uint32_t BytesPerSample
@@ -1359,21 +1354,46 @@ status_t MPEG4Extractor::parseChunk(off6
                 // }
                 uint32_t structSize32;
                 if (mDataSource->readAt(
                             data_offset + 28, &structSize32, sizeof(structSize32))
                         < (ssize_t)sizeof(structSize32)) {
                     return ERROR_IO;
                 }
                 uint32_t structSize = ntohl(structSize32);
+                // Read SampleRate.
+                uint64_t sample_rate64;
+                if (mDataSource->readAt(
+                            data_offset + 32, &sample_rate64, sizeof(sample_rate64))
+                        < (ssize_t)sizeof(sample_rate64)) {
+                    return ERROR_IO;
+                }
+                uint64_t i_value = ntoh64(sample_rate64);
+                void* v_value = reinterpret_cast<void*>(&i_value);
+                sample_rate = uint32_t(*reinterpret_cast<double*>(v_value));
+                // Read ChannelCount.
+                uint32_t channel_count32;
+                if (mDataSource->readAt(
+                            data_offset + 40, &channel_count32, sizeof(channel_count32))
+                        < (ssize_t)sizeof(channel_count32)) {
+                    return ERROR_IO;
+                }
+                num_channels = ntohl(channel_count32);
+
                 skip += 36;
                 if (structSize > 72) {
                     skip += structSize - 72;
                 }
             }
+            ALOGV("*** coding='%s' %d channels, size %d, rate %d\n",
+                   chunk, num_channels, sample_size, sample_rate);
+            mLastTrack->meta->setInt32(kKeyChannelCount, num_channels);
+            mLastTrack->meta->setInt32(kKeySampleSize, sample_size);
+            mLastTrack->meta->setInt32(kKeySampleRate, sample_rate);
+
             off64_t stop_offset = *offset + chunk_size;
             *offset = data_offset + sizeof(buffer) + skip;
             while (*offset < stop_offset) {
                 status_t err = parseChunk(offset, depth + 1);
                 if (err != OK) {
                     return err;
                 }
             }
@@ -1514,17 +1534,17 @@ status_t MPEG4Extractor::parseChunk(off6
                 mLastTrack->meta->setInt32(kKeyMaxInputSize, max_size + 10 * 2);
             } else {
                 // No size was specified. Pick a conservatively large size.
                 int32_t width, height;
                 if (mLastTrack->meta->findInt32(kKeyWidth, &width) &&
                         mLastTrack->meta->findInt32(kKeyHeight, &height)) {
                     mLastTrack->meta->setInt32(kKeyMaxInputSize, width * height * 3 / 2);
                 } else {
-                    ALOGE("No width or height, assuming worst case 1080p");
+                    ALOGV("No width or height, assuming worst case 1080p");
                     mLastTrack->meta->setInt32(kKeyMaxInputSize, 3110400);
                 }
             }
             *offset += chunk_size;
 
             // Calculate average frame rate.
             const char *mime;
             CHECK(mLastTrack->meta->findCString(kKeyMIMEType, &mime));
--- a/media/libstagefright/frameworks/av/media/libstagefright/Utils.cpp
+++ b/media/libstagefright/frameworks/av/media/libstagefright/Utils.cpp
@@ -55,21 +55,28 @@ uint16_t U16LE_AT(const uint8_t *ptr) {
 uint32_t U32LE_AT(const uint8_t *ptr) {
     return ptr[3] << 24 | ptr[2] << 16 | ptr[1] << 8 | ptr[0];
 }
 
 uint64_t U64LE_AT(const uint8_t *ptr) {
     return ((uint64_t)U32LE_AT(ptr + 4)) << 32 | U32LE_AT(ptr);
 }
 
-// XXX warning: these won't work on big-endian host.
 uint64_t ntoh64(uint64_t x) {
-    return ((uint64_t)ntohl(x & 0xffffffff) << 32) | ntohl(x >> 32);
+    return ((x & 0xFF00000000000000ull) >> 56) |
+           ((x & 0x00FF000000000000ull) >> 40) |
+           ((x & 0x0000FF0000000000ull) >> 24) |
+           ((x & 0x000000FF00000000ull) >>  8) |
+           ((x & 0x00000000FF000000ull) <<  8) |
+           ((x & 0x0000000000FF0000ull) << 24) |
+           ((x & 0x000000000000FF00ull) << 40) |
+           ((x & 0x00000000000000FFull) << 56);
 }
 
+// XXX warning: this won't work on big-endian host.
 uint64_t hton64(uint64_t x) {
     return ((uint64_t)htonl(x & 0xffffffff) << 32) | htonl(x >> 32);
 }
 
 #if 0
 status_t convertMetaDataToMessage(
         const sp<MetaData> &meta, sp<AMessage> *format) {
     format->clear();
--- a/mfbt/unused.h
+++ b/mfbt/unused.h
@@ -14,26 +14,23 @@
 namespace mozilla {
 
 //
 // Suppress GCC warnings about unused return values with
 //   unused << SomeFuncDeclaredWarnUnusedReturnValue();
 //
 struct unused_t
 {
+  template<typename T>
+  inline void
+  operator<<(const T& /*unused*/) const {}
 };
 
 extern MFBT_DATA const unused_t unused;
 
-template<typename T>
-inline void
-operator<<(const unused_t& /*unused*/, const T& /*unused*/)
-{
-}
-
 } // namespace mozilla
 
 #endif // __cplusplus
 
 // An alternative to mozilla::unused for use in (a) C code and (b) code where
 // linking with unused.o is difficult.
 #define MOZ_UNUSED(expr) \
   do { if (expr) { (void)0; } } while (0)
--- a/mobile/android/base/GeckoAccessibility.java
+++ b/mobile/android/base/GeckoAccessibility.java
@@ -332,16 +332,17 @@ public class GeckoAccessibility {
                                 info.addAction(AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY);
                                 info.addAction(AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY);
                                 info.addAction(AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD);
                                 info.addAction(AccessibilityNodeInfo.ACTION_SCROLL_FORWARD);
                                 info.addAction(AccessibilityNodeInfo.ACTION_NEXT_HTML_ELEMENT);
                                 info.addAction(AccessibilityNodeInfo.ACTION_PREVIOUS_HTML_ELEMENT);
                                 info.setMovementGranularities(AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER |
                                                               AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD |
+                                                              AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE |
                                                               AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
                                 break;
                             }
                             return info;
                         }
 
                         @Override
                         public boolean performAction (int virtualViewId, int action, Bundle arguments) {
@@ -385,51 +386,59 @@ public class GeckoAccessibility {
                                     traversalRule = arguments.getString(AccessibilityNodeInfo.ACTION_ARGUMENT_HTML_ELEMENT_STRING);
                                 }
                                 GeckoAppShell.
                                     sendEventToGecko(GeckoEvent.createBroadcastEvent("Accessibility:PreviousObject", traversalRule));
                                 return true;
                             } else if (action == AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY &&
                                        virtualViewId == VIRTUAL_CURSOR_POSITION) {
                                 // XXX: Self brailling gives this action with a bogus argument instead of an actual click action;
-                                // the argument value is the BRAILLE_CLICK_BASE_INDEX - the index of the routing key that was hit
+                                // the argument value is the BRAILLE_CLICK_BASE_INDEX - the index of the routing key that was hit.
+                                // Other negative values are used by ChromeVox, but we don't support them.
+                                // FAKE_GRANULARITY_READ_CURRENT = -1
+                                // FAKE_GRANULARITY_READ_TITLE = -2
+                                // FAKE_GRANULARITY_STOP_SPEECH = -3
+                                // FAKE_GRANULARITY_CHANGE_SHIFTER = -4
                                 int granularity = arguments.getInt(AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
                                 if (granularity <= BRAILLE_CLICK_BASE_INDEX) {
                                     int keyIndex = BRAILLE_CLICK_BASE_INDEX - granularity;
                                     JSONObject activationData = new JSONObject();
                                     try {
                                         activationData.put("keyIndex", keyIndex);
                                     } catch (JSONException e) {
                                         return true;
                                     }
                                     GeckoAppShell.
                                         sendEventToGecko(GeckoEvent.createBroadcastEvent("Accessibility:ActivateObject", activationData.toString()));
-                                } else {
+                                } else if (granularity > 0) {
                                     JSONObject movementData = new JSONObject();
                                     try {
                                         movementData.put("direction", "Next");
                                         movementData.put("granularity", granularity);
                                     } catch (JSONException e) {
                                         return true;
                                     }
                                     GeckoAppShell.
                                         sendEventToGecko(GeckoEvent.createBroadcastEvent("Accessibility:MoveByGranularity", movementData.toString()));
                                 }
                                 return true;
                             } else if (action == AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY &&
                                        virtualViewId == VIRTUAL_CURSOR_POSITION) {
                                 JSONObject movementData = new JSONObject();
+                                int granularity = arguments.getInt(AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
                                 try {
                                     movementData.put("direction", "Previous");
-                                    movementData.put("granularity", arguments.getInt(AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT));
+                                    movementData.put("granularity", granularity);
                                 } catch (JSONException e) {
                                     return true;
                                 }
-                                GeckoAppShell.
-                                    sendEventToGecko(GeckoEvent.createBroadcastEvent("Accessibility:MoveByGranularity", movementData.toString()));
+                                if (granularity > 0) {
+                                    GeckoAppShell.
+                                      sendEventToGecko(GeckoEvent.createBroadcastEvent("Accessibility:MoveByGranularity", movementData.toString()));
+                                }
                                 return true;
                             }
                             return host.performAccessibilityAction(action, arguments);
                         }
                     };
 
             return mAccessibilityNodeProvider;
         }
--- a/mobile/android/locales/jar.mn
+++ b/mobile/android/locales/jar.mn
@@ -53,17 +53,17 @@ relativesrcdir toolkit/locales:
   locale/@AB_CD@/browser/overrides/charsetMenu.properties          (%chrome/global/charsetMenu.properties)
   locale/@AB_CD@/browser/overrides/commonDialogs.properties        (%chrome/global/commonDialogs.properties)
   locale/@AB_CD@/browser/overrides/intl.properties                 (%chrome/global/intl.properties)
   locale/@AB_CD@/browser/overrides/intl.css                        (%chrome/global/intl.css)
   locale/@AB_CD@/browser/overrides/passwordmgr.properties          (%chrome/passwordmgr/passwordmgr.properties)
   locale/@AB_CD@/browser/overrides/search/search.properties        (%chrome/search/search.properties)
   locale/@AB_CD@/browser/overrides/update/updates.properties       (%chrome/mozapps/update/updates.properties)
 # plugins
-  locale/@AB_CD@/browser/overrides/plugins/plugins.dtd             (%chrome/mozapps/plugins/plugins.dtd)
+  locale/@AB_CD@/browser/overrides/plugins/pluginproblem.dtd       (%chrome/pluginproblem/pluginproblem.dtd)
 # about:support
   locale/@AB_CD@/browser/overrides/global/aboutSupport.dtd         (%chrome/global/aboutSupport.dtd)
   locale/@AB_CD@/browser/overrides/global/aboutSupport.properties  (%chrome/global/aboutSupport.properties)
 #about:crashes
   locale/@AB_CD@/browser/overrides/crashreporter/crashes.dtd         (%crashreporter/crashes.dtd)
   locale/@AB_CD@/browser/overrides/crashreporter/crashes.properties  (%crashreporter/crashes.properties)
 #about:mozilla
   locale/@AB_CD@/browser/overrides/global/mozilla.dtd                (%chrome/global/mozilla.dtd)
@@ -80,17 +80,17 @@ relativesrcdir toolkit/locales:
 % override chrome://global/locale/charsetMenu.properties chrome://browser/locale/overrides/charsetMenu.properties
 % override chrome://global/locale/commonDialogs.properties chrome://browser/locale/overrides/commonDialogs.properties
 % override chrome://mozapps/locale/handling/handling.properties chrome://browser/locale/handling.properties
 % override chrome://global/locale/intl.properties chrome://browser/locale/overrides/intl.properties
 % override chrome://global/locale/intl.css chrome://browser/locale/overrides/intl.css
 % override chrome://passwordmgr/locale/passwordmgr.properties chrome://browser/locale/overrides/passwordmgr/passwordmgr.properties
 % override chrome://global/locale/search/search.properties chrome://browser/locale/overrides/search/search.properties
 % override chrome://mozapps/locale/update/updates.properties chrome://browser/locale/overrides/update/updates.properties
-% override chrome://mozapps/locale/plugins/plugins.dtd chrome://browser/locale/overrides/plugins/plugins.dtd
+% override chrome://pluginproblem/locale/pluginproblem.dtd chrome://browser/locale/overrides/plugins/pluginproblem.dtd
 % override chrome://global/locale/aboutSupport.dtd chrome://browser/locale/overrides/global/aboutSupport.dtd
 % override chrome://global/locale/aboutSupport.properties chrome://browser/locale/overrides/global/aboutSupport.properties
 % override chrome://global/locale/crashes.dtd chrome://browser/locale/overrides/crashreporter/crashes.dtd
 % override chrome://global/locale/crashes.properties chrome://browser/locale/overrides/crashreporter/crashes.properties
 % override chrome://global/locale/mozilla.dtd chrome://browser/locale/overrides/global/mozilla.dtd
 % override chrome://global/locale/aboutTelemetry.dtd chrome://browser/locale/overrides/global/aboutTelemetry.dtd
 % override chrome://global/locale/aboutTelemetry.properties chrome://browser/locale/overrides/global/aboutTelemetry.properties
 % override chrome://global/locale/aboutWebrtc.properties chrome://browser/locale/overrides/global/aboutWebrtc.properties
--- a/netwerk/base/LoadInfo.cpp
+++ b/netwerk/base/LoadInfo.cpp
@@ -207,16 +207,24 @@ NS_IMETHODIMP
 LoadInfo::GetAboutBlankInherits(bool* aResult)
 {
   *aResult =
     (mSecurityFlags & nsILoadInfo::SEC_ABOUT_BLANK_INHERITS);
   return NS_OK;
 }
 
 NS_IMETHODIMP
+LoadInfo::GetAllowChrome(bool* aResult)
+{
+  *aResult =
+    (mSecurityFlags & nsILoadInfo::SEC_ALLOW_CHROME);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
 LoadInfo::GetContentPolicyType(nsContentPolicyType* aResult)
 {
   *aResult = nsContentUtils::InternalContentPolicyTypeToExternal(mContentPolicyType);
   return NS_OK;
 }
 
 nsContentPolicyType
 LoadInfo::InternalContentPolicyType()
--- a/netwerk/base/nsILoadInfo.idl
+++ b/netwerk/base/nsILoadInfo.idl
@@ -17,17 +17,17 @@ interface nsIPrincipal;
 
 [ref] native const_nsIPrincipalArray(const nsTArray<nsCOMPtr<nsIPrincipal>>);
 
 typedef unsigned long nsSecurityFlags;
 
 /**
  * An nsILoadOwner represents per-load information about who started the load.
  */
-[scriptable, builtinclass, uuid(99abb145-29d2-4a0a-8bca-213fa6211cc9)]
+[scriptable, builtinclass, uuid(ef0080f3-33f5-475f-a3d6-9fd3be0612e3)]
 interface nsILoadInfo : nsISupports
 {
   /**
    * No special security flags:
    */
   const unsigned long SEC_NORMAL = 0;
 
   /**
@@ -118,16 +118,21 @@ interface nsILoadInfo : nsISupports
   const unsigned long SEC_SANDBOXED = (1<<7);
 
   /**
    * Inherit the Principal for about:blank.
    */
   const unsigned long SEC_ABOUT_BLANK_INHERITS = (1<<8);
 
   /**
+   * Allow chrome: to bypass security checks.
+   */
+  const unsigned long SEC_ALLOW_CHROME = (1<<9);
+
+  /**
    * The loadingPrincipal is the principal that is responsible for the load.
    * It is *NOT* the principal tied to the resource/URI that this
    * channel is loading, it's the principal of the resource's
    * caller or requester. For example, if this channel is loading
    * an image from http://b.com that is embedded in a document
    * who's origin is http://a.com, the loadingPrincipal is http://a.com.
    *
    * The loadingPrincipal will never be null.
@@ -233,16 +238,22 @@ interface nsILoadInfo : nsISupports
 
   /**
    * If aboutBlankInherits is true, then about:blank should inherit
    * the principal.
    */
   [infallible] readonly attribute boolean aboutBlankInherits;
 
   /**
+   * If allowChrome is true, then use nsIScriptSecurityManager::ALLOW_CHROME
+   * when calling CheckLoadURIWithPrincipal().
+   */
+  [infallible] readonly attribute boolean allowChrome;
+
+  /**
    * The external contentPolicyType of the channel, used for security checks
    * like Mixed Content Blocking and Content Security Policy.
    *
    * Specifically, content policy types with _INTERNAL_ in their name will
    * never get returned from this attribute.
    */
   readonly attribute nsContentPolicyType contentPolicyType;
 
--- a/netwerk/base/nsSecCheckWrapChannel.cpp
+++ b/netwerk/base/nsSecCheckWrapChannel.cpp
@@ -1,13 +1,14 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 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 "nsContentSecurityManager.h"
 #include "nsSecCheckWrapChannel.h"
 #include "nsHttpChannel.h"
 #include "nsCOMPtr.h"
 
 static PRLogModuleInfo*
 GetChannelWrapperLog()
 {
   static PRLogModuleInfo* gChannelWrapperPRLog;
@@ -23,28 +24,32 @@ NS_IMPL_ADDREF(nsSecCheckWrapChannelBase
 NS_IMPL_RELEASE(nsSecCheckWrapChannelBase)
 
 NS_INTERFACE_MAP_BEGIN(nsSecCheckWrapChannelBase)
   NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIHttpChannel, mHttpChannel)
   NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIHttpChannelInternal, mHttpChannelInternal)
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIHttpChannel)
   NS_INTERFACE_MAP_ENTRY(nsIRequest)
   NS_INTERFACE_MAP_ENTRY(nsIChannel)
+  NS_INTERFACE_MAP_ENTRY(nsIUploadChannel)
+  NS_INTERFACE_MAP_ENTRY(nsIUploadChannel2)
   NS_INTERFACE_MAP_ENTRY(nsISecCheckWrapChannel)
 NS_INTERFACE_MAP_END
 
 //---------------------------------------------------------
 // nsSecCheckWrapChannelBase implementation
 //---------------------------------------------------------
 
 nsSecCheckWrapChannelBase::nsSecCheckWrapChannelBase(nsIChannel* aChannel)
  : mChannel(aChannel)
  , mHttpChannel(do_QueryInterface(aChannel))
  , mHttpChannelInternal(do_QueryInterface(aChannel))
  , mRequest(do_QueryInterface(aChannel))
+ , mUploadChannel(do_QueryInterface(aChannel))
+ , mUploadChannel2(do_QueryInterface(aChannel))
 {
   MOZ_ASSERT(mChannel, "can not create a channel wrapper without a channel");
 }
 
 nsSecCheckWrapChannelBase::~nsSecCheckWrapChannelBase()
 {
 }
 
@@ -97,8 +102,26 @@ nsSecCheckWrapChannel::GetLoadInfo(nsILo
 
 NS_IMETHODIMP
 nsSecCheckWrapChannel::SetLoadInfo(nsILoadInfo* aLoadInfo)
 {
   CHANNELWRAPPERLOG(("nsSecCheckWrapChannel::SetLoadInfo() [%p]", this));
   mLoadInfo = aLoadInfo;
   return NS_OK;
 }
+
+NS_IMETHODIMP
+nsSecCheckWrapChannel::AsyncOpen2(nsIStreamListener *aListener)
+{
+  nsCOMPtr<nsIStreamListener> listener = aListener;
+  nsresult rv = nsContentSecurityManager::doContentSecurityCheck(this, listener);
+  NS_ENSURE_SUCCESS(rv, rv);
+  return AsyncOpen(listener, nullptr);
+}
+
+NS_IMETHODIMP
+nsSecCheckWrapChannel::Open2(nsIInputStream** aStream)
+{
+  nsCOMPtr<nsIStreamListener> listener;
+  nsresult rv = nsContentSecurityManager::doContentSecurityCheck(this, listener);
+  NS_ENSURE_SUCCESS(rv, rv);
+  return Open(aStream);
+}
--- a/netwerk/base/nsSecCheckWrapChannel.h
+++ b/netwerk/base/nsSecCheckWrapChannel.h
@@ -3,16 +3,18 @@
  * 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 nsSecCheckWrapChannel_h__
 #define nsSecCheckWrapChannel_h__
 
 #include "nsIHttpChannel.h"
 #include "nsIHttpChannelInternal.h"
+#include "nsIUploadChannel.h"
+#include "nsIUploadChannel2.h"
 #include "nsISecCheckWrapChannel.h"
 #include "nsIWyciwygChannel.h"
 #include "mozilla/LoadInfo.h"
 
 /*
  * The nsSecCheckWrapChannelBase wraps channels that do *not*
  *  * provide a newChannel2() implementation
  *  * provide get/setLoadInfo functions
@@ -29,56 +31,67 @@
  * We do not want to break those addons hence we wrap such channels
  * using the provided wrapper in this class.
  *
  * Please note that the wrapper only forwards calls for
  *  * nsIRequest
  *  * nsIChannel
  *  * nsIHttpChannel
  *  * nsIHttpChannelInternal
+ *  * nsIUploadChannel
+ *  * nsIUploadChannel2
  *
  * In case any addon needs to query the inner channel this class
  * provides a readonly function to query the wrapped channel.
  *
  */
 
 class nsSecCheckWrapChannelBase : public nsIHttpChannel
                                 , public nsIHttpChannelInternal
                                 , public nsISecCheckWrapChannel
+                                , public nsIUploadChannel
+                                , public nsIUploadChannel2
 {
 public:
   NS_FORWARD_NSIHTTPCHANNEL(mHttpChannel->)
   NS_FORWARD_NSIHTTPCHANNELINTERNAL(mHttpChannelInternal->)
   NS_FORWARD_NSICHANNEL(mChannel->)
   NS_FORWARD_NSIREQUEST(mRequest->)
+  NS_FORWARD_NSIUPLOADCHANNEL(mUploadChannel->)
+  NS_FORWARD_NSIUPLOADCHANNEL2(mUploadChannel2->)
   NS_DECL_NSISECCHECKWRAPCHANNEL
   NS_DECL_ISUPPORTS
 
   explicit nsSecCheckWrapChannelBase(nsIChannel* aChannel);
 
 protected:
   virtual ~nsSecCheckWrapChannelBase();
 
   nsCOMPtr<nsIChannel>             mChannel;
   // We do a QI in the constructor to set the following pointers.
   nsCOMPtr<nsIHttpChannel>         mHttpChannel;
   nsCOMPtr<nsIHttpChannelInternal> mHttpChannelInternal;
   nsCOMPtr<nsIRequest>             mRequest;
+  nsCOMPtr<nsIUploadChannel>       mUploadChannel;
+  nsCOMPtr<nsIUploadChannel2>      mUploadChannel2;
 };
 
-/* We define a separate class here to make it clear that we're
- * overriding Get/SetLoadInfo, rather that using the forwarded
- * implementations provided by NS_FORWARD_NSICHANNEL"
+/* We define a separate class here to make it clear that we're overriding
+ * Get/SetLoadInfo as well as AsyncOpen2() and Open2(), rather that using
+ * the forwarded implementations provided by NS_FORWARD_NSICHANNEL"
  */
 class nsSecCheckWrapChannel : public nsSecCheckWrapChannelBase
 {
 public:
   NS_IMETHOD GetLoadInfo(nsILoadInfo **aLoadInfo);
   NS_IMETHOD SetLoadInfo(nsILoadInfo *aLoadInfo);
 
+  NS_IMETHOD AsyncOpen2(nsIStreamListener *aListener);
+  NS_IMETHOD Open2(nsIInputStream** aStream);
+
   nsSecCheckWrapChannel(nsIChannel* aChannel, nsILoadInfo* aLoadInfo);
 
 protected:
   virtual ~nsSecCheckWrapChannel();
 
   nsCOMPtr<nsILoadInfo> mLoadInfo;
 };
 
--- a/netwerk/wifi/moz.build
+++ b/netwerk/wifi/moz.build
@@ -20,20 +20,16 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk
     UNIFIED_SOURCES += [
         'nsWifiMonitorGonk.cpp',
     ]
 else:
     UNIFIED_SOURCES += [
         'nsWifiMonitor.cpp',
     ]
 
-# osx_corewlan.mm has warnings I don't understand.
-if CONFIG['OS_ARCH'] == 'Darwin':
-    ALLOW_COMPILER_WARNINGS = True
-
 if CONFIG['OS_ARCH'] == 'Darwin':
     UNIFIED_SOURCES += [
         'nsWifiScannerMac.cpp',
     ]
     UNIFIED_SOURCES += [
         'osx_corewlan.mm',
     ]
 elif CONFIG['OS_ARCH'] in ('DragonFly', 'FreeBSD'):
--- a/testing/profiles/prefs_general.js
+++ b/testing/profiles/prefs_general.js
@@ -23,17 +23,16 @@ user_pref("signed.applets.codebase_princ
 user_pref("browser.shell.checkDefaultBrowser", false);
 user_pref("shell.checkDefaultClient", false);
 user_pref("browser.warnOnQuit", false);
 user_pref("accessibility.typeaheadfind.autostart", false);
 user_pref("javascript.options.showInConsole", true);
 user_pref("devtools.browsertoolbox.panel", "jsdebugger");
 user_pref("devtools.errorconsole.enabled", true);
 user_pref("devtools.debugger.remote-port", 6023);
-user_pref("layout.debug.enable_data_xbl", true);
 user_pref("browser.EULA.override", true);
 user_pref("gfx.color_management.force_srgb", true);
 user_pref("network.manage-offline-status", false);
 // Disable speculative connections so they aren't reported as leaking when they're hanging around.
 user_pref("network.http.speculative-parallel-limit", 0);
 user_pref("dom.min_background_timeout_value", 1000);
 user_pref("test.mousescroll", true);
 user_pref("security.default_personal_cert", "Select Automatically"); // Need to client auth test be w/o any dialogs
--- a/testing/talos/talos/output.py
+++ b/testing/talos/talos/output.py
@@ -179,19 +179,18 @@ class GraphserverOutput(Output):
             # counter results
             for cd in test.all_counter_results:
                 for counter_type, values in cd.items():
                     # get the counter name
                     counterName = '%s_%s' % (test.name(),
                                              self.shortName(counter_type))
                     if not values:
                         # failed to collect any data for this counter
-                        utils.stamped_msg(
-                            "No results collected for: " + counterName,
-                            "Error"
+                        logging.error(
+                            "No results collected for: " + counterName
                         )
 # NOTE: we are not going to enforce this warning for now as this happens too
 # frequently: bugs 803413, 802475, 805925
 #                        raise utils.TalosError("Unable to proceed with missing
 # counter '%s'" % counterName)
 # (jhammel: we probably should do this in e.g. results.py vs in
 # graphserver-specific code anyway)
 
@@ -214,21 +213,19 @@ class GraphserverOutput(Output):
                     # append test name extension but only for tpformat tests
                     if test.format == 'tpformat':
                         counterName += test.extension()
 
                     info = info_dict.copy()
                     info['testname'] = counterName
 
                     # append the counter string
-                    utils.stamped_msg(
-                        "Generating results file: %s" % counterName, "Started")
+                    logging.info(
+                        "Generating results file: %s" % counterName)
                     result_strings.append(self.construct_results(vals, **info))
-                    utils.stamped_msg(
-                        "Generating results file: %s" % counterName, "Stopped")
 
         return result_strings
 
     def responsiveness_test(self, testname):
         """returns if the test is a responsiveness test"""
         # XXX currently this just looks for the string
         # 'responsiveness' in the test name.
         # It would be nice to be more declarative about this
deleted file mode 100755
--- a/testing/talos/talos/sample.2.config
+++ /dev/null
@@ -1,11 +0,0 @@
-extraPrefs:
-  extensions.autoDisableScopes:
-  extensions.enabledScopes:
-
-test_overrides:
-  tp5r:
-    tpcycles: 10
-    win_counters : ['Main_RSS', 'Private Bytes', '% Processor Time']
-    w7_counters : ['Main_RSS', 'Private Bytes', '% Processor Time', 'Modified Page List Bytes']
-    linux_counters : ['Private Bytes', 'XRes', 'Main_RSS']
-    mac_counters : ['Private Bytes', 'Main_RSS']
--- a/testing/talos/talos/ttest.py
+++ b/testing/talos/talos/ttest.py
@@ -233,30 +233,22 @@ class TTest(object):
             if os.path.exists(browser_config['error_filename']) or \
                mainthread_error_count > 0:
                 raise TalosRegression(
                     "Talos has found a regression, if you have questions"
                     " ask for help in irc on #perf"
                 )
 
             # add the results from the browser output
-            try:
-                test_results.add(
-                    '\n'.join(pcontext.output),
-                    counter_results=(counter_management.results()
-                                     if counter_management
-                                     else None))
-            except Exception:
-                # Log the exception, but continue. One way to get here
-                # is if the browser hangs, and we'd still like to get
-                # symbolicated profiles in that case.
-                # TODO: the browser can't be hanging here anymore
-                # check if we can remove this, or if we should adjust the
-                # above comment.
-                logging.exception("Unable to add results for cycle %d" % i)
+            test_results.add(
+                '\n'.join(pcontext.output),
+                counter_results=(counter_management.results()
+                                 if counter_management
+                                 else None)
+            )
 
             if setup.sps_profile:
                 setup.sps_profile.symbolicate(i)
 
             self.check_for_crashes(browser_config, setup.profile_dir,
                                    test_config['name'])
 
         # include global (cross-cycle) counters
--- a/testing/talos/talos/utils.py
+++ b/testing/talos/talos/utils.py
@@ -34,26 +34,16 @@ class Timer(object):
 
 def startLogger(levelChoice):
     # declare and define global logger object to send logging messages to
     log_levels = {'debug': logging.DEBUG, 'info': logging.INFO}
     logging.basicConfig(format='%(asctime)-15s %(levelname)s : %(message)s',
                         level=log_levels[levelChoice])
 
 
-def stamped_msg(msg_title, msg_action):
-    """Prints a message to the console with a time stamp
-    """
-    time_format = "%a, %d %b %Y %H:%M:%S"
-    msg_format = "%s: \n\t\t%s %s"
-    print msg_format % (msg_title, msg_action,
-                        time.strftime(time_format, time.localtime()))
-    sys.stdout.flush()
-
-
 class TalosError(Exception):
     "Errors found while running the talos harness."
 
 
 class TalosRegression(Exception):
     """When a regression is detected at runtime, report it properly
        Currently this is a simple definition so we can detect the class type
     """
--- a/testing/taskcluster/mach_commands.py
+++ b/testing/taskcluster/mach_commands.py
@@ -189,20 +189,25 @@ def set_interactive_task(task, interacti
         payload["features"] = {}
     payload["features"]["interactive"] = True
 
 def remove_caches_from_task(task):
     r"""Remove all caches but tc-vcs from the task.
 
     :param task: task definition.
     """
+    whitelist = [
+        "tc-vcs",
+        "tc-vcs-public-source",
+        "tooltool-cache",
+    ]
     try:
         caches = task["task"]["payload"]["cache"]
         for cache in caches.keys():
-            if cache != "tc-vcs":
+            if cache not in whitelist:
                 caches.pop(cache)
     except KeyError:
         pass
 
 @CommandProvider
 class DecisionTask(object):
     @Command('taskcluster-decision', category="ci",
         description="Build a decision task")
deleted file mode 100644
--- a/testing/web-platform/meta/2dcontext/drawing-images-to-the-canvas/2d.drawImage.negativedest.html.ini
+++ /dev/null
@@ -1,5 +0,0 @@
-[2d.drawImage.negativedest.html]
-  type: testharness
-  [Negative destination width/height represents the correct rectangle]
-    expected: FAIL
-
deleted file mode 100644
--- a/testing/web-platform/meta/2dcontext/drawing-images-to-the-canvas/2d.drawImage.negativedir.html.ini
+++ /dev/null
@@ -1,5 +0,0 @@
-[2d.drawImage.negativedir.html]
-  type: testharness
-  [Negative dimensions do not affect the direction of the image]
-    expected: FAIL
-
deleted file mode 100644
--- a/testing/web-platform/meta/2dcontext/drawing-images-to-the-canvas/2d.drawImage.negativesource.html.ini
+++ /dev/null
@@ -1,5 +0,0 @@
-[2d.drawImage.negativesource.html]
-  type: testharness
-  [Negative source width/height represents the correct rectangle]
-    expected: FAIL
-
deleted file mode 100644
--- a/testing/web-platform/meta/2dcontext/drawing-images-to-the-canvas/drawimage_canvas_8.html.ini
+++ /dev/null
@@ -1,9 +0,0 @@
-[drawimage_canvas_8.html]
-  type: reftest
-  expected:
-    if (os == "linux") and (version == "Ubuntu 12.04") and (processor == "x86") and (bits == 32): FAIL
-    if (os == "linux") and (version == "Ubuntu 12.04") and (processor == "x86_64") and (bits == 64): FAIL
-    if (os == "win") and (version == "6.2.9200") and (processor == "x86_64") and (bits == 64): FAIL
-    if (os == "win") and (version == "6.1.7601") and (processor == "x86") and (bits == 32): FAIL
-    if debug and (os == "win") and (version == "10.0.10240") and (processor == "x86_64") and (bits == 64): FAIL
-    if not debug and (os == "win") and (version == "10.0.10240") and (processor == "x86_64") and (bits == 64): FAIL
--- a/toolkit/components/url-classifier/Classifier.cpp
+++ b/toolkit/components/url-classifier/Classifier.cpp
@@ -246,24 +246,22 @@ Classifier::Check(const nsACString& aSpe
     // Get list of host keys to look up
     Completion hostKey;
     rv = LookupCache::GetKey(fragments[i], &hostKey, mCryptoHash);
     if (NS_FAILED(rv)) {
       // Local host on the network.
       continue;
     }
 
-#if DEBUG
     if (LOG_ENABLED()) {
       nsAutoCString checking;
       lookupHash.ToHexString(checking);
       LOG(("Checking fragment %s, hash %s (%X)", fragments[i].get(),
            checking.get(), lookupHash.ToUint32()));
     }
-#endif
 
     for (uint32_t i = 0; i < cacheArray.Length(); i++) {
       LookupCache *cache = cacheArray[i];
       bool has, complete;
       rv = cache->Has(lookupHash, &has, &complete);
       NS_ENSURE_SUCCESS(rv, rv);
       if (has) {
         LookupResult *result = aResults.AppendElement();
--- a/toolkit/components/url-classifier/Entries.h
+++ b/toolkit/components/url-classifier/Entries.h
@@ -83,30 +83,31 @@ struct SafebrowsingHash
 
 #ifdef DEBUG
   void ToString(nsACString& aStr) const {
     uint32_t len = ((sHashSize + 2) / 3) * 4;
     aStr.SetCapacity(len + 1);
     PL_Base64Encode((char*)buf, sHashSize, aStr.BeginWriting());
     aStr.BeginWriting()[len] = '\0';
   }
+#endif
 
   void ToHexString(nsACString& aStr) const {
     static const char* const lut = "0123456789ABCDEF";
     // 32 bytes is the longest hash
     size_t len = 32;
 
     aStr.SetCapacity(2 * len);
     for (size_t i = 0; i < len; ++i) {
       const char c = static_cast<const char>(buf[i]);
       aStr.Append(lut[(c >> 4) & 0x0F]);
       aStr.Append(lut[c & 15]);
     }
   }
-#endif
+
   uint32_t ToUint32() const {
       return *((uint32_t*)buf);
   }
   void FromUint32(uint32_t aHash) {
       *((uint32_t*)buf) = aHash;
   }
 };
 
--- a/toolkit/components/url-classifier/ProtocolParser.cpp
+++ b/toolkit/components/url-classifier/ProtocolParser.cpp
@@ -7,20 +7,19 @@
 #include "LookupCache.h"
 #include "nsNetCID.h"
 #include "mozilla/Logging.h"
 #include "prnetdb.h"
 #include "prprf.h"
 
 #include "nsUrlClassifierUtils.h"
 
-// NSPR_LOG_MODULES=UrlClassifierDbService:5
-extern PRLogModuleInfo *gUrlClassifierDbServiceLog;
-#define LOG(args) MOZ_LOG(gUrlClassifierDbServiceLog, mozilla::LogLevel::Debug, args)
-#define LOG_ENABLED() MOZ_LOG_TEST(gUrlClassifierDbServiceLog, mozilla::LogLevel::Debug)
+// NSPR_LOG_MODULES=UrlClassifierProtocolParser:5
+PRLogModuleInfo *gUrlClassifierProtocolParserLog = nullptr;
+#define PARSER_LOG(args) MOZ_LOG(gUrlClassifierProtocolParserLog, mozilla::LogLevel::Debug, args)
 
 namespace mozilla {
 namespace safebrowsing {
 
 // Updates will fail if fed chunks larger than this
 const uint32_t MAX_CHUNK_SIZE = (1024 * 1024);
 // Updates will fail if the total number of tocuhed chunks is larger than this
 const uint32_t MAX_CHUNK_RANGE = 1000000;
@@ -72,16 +71,20 @@ ProtocolParser::ProtocolParser()
 ProtocolParser::~ProtocolParser()
 {
   CleanupUpdates();
 }
 
 nsresult
 ProtocolParser::Init(nsICryptoHash* aHasher)
 {
+  if (!gUrlClassifierProtocolParserLog) {
+    gUrlClassifierProtocolParserLog =
+      PR_NewLogModule("UrlClassifierProtocolParser");
+  }
   mCryptoHash = aHasher;
   return NS_OK;
 }
 
 void
 ProtocolParser::SetCurrentTable(const nsACString& aTable)
 {
   mTableUpdate = GetTableUpdate(aTable);
@@ -117,24 +120,24 @@ ProtocolParser::AppendStream(const nsACS
 nsresult
 ProtocolParser::ProcessControl(bool* aDone)
 {
   nsresult rv;
 
   nsAutoCString line;
   *aDone = true;
   while (NextLine(line)) {
-    //LOG(("Processing %s\n", line.get()));
+    PARSER_LOG(("Processing %s\n", line.get()));
 
     if (StringBeginsWith(line, NS_LITERAL_CSTRING("i:"))) {
       // Set the table name from the table header line.
       SetCurrentTable(Substring(line, 2));
     } else if (StringBeginsWith(line, NS_LITERAL_CSTRING("n:"))) {
       if (PR_sscanf(line.get(), "n:%d", &mUpdateWait) != 1) {
-        LOG(("Error parsing n: '%s' (%d)", line.get(), mUpdateWait));
+        PARSER_LOG(("Error parsing n: '%s' (%d)", line.get(), mUpdateWait));
         mUpdateWait = 0;
       }
     } else if (line.EqualsLiteral("r:pleasereset")) {
       mResetRequested = true;
     } else if (StringBeginsWith(line, NS_LITERAL_CSTRING("u:"))) {
       rv = ProcessForward(line);
       NS_ENSURE_SUCCESS(rv, rv);
     } else if (StringBeginsWith(line, NS_LITERAL_CSTRING("a:")) ||
@@ -204,37 +207,39 @@ ProtocolParser::ProcessChunkControl(cons
   mChunkState.Clear();
 
   if (PR_sscanf(aLine.get(),
                 "%c:%d:%d:%d",
                 &command,
                 &mChunkState.num, &mChunkState.hashSize, &mChunkState.length)
       != 4)
   {
+    NS_WARNING(("PR_sscanf failed"));
     return NS_ERROR_FAILURE;
   }
 
   if (mChunkState.length > MAX_CHUNK_SIZE) {
+    NS_WARNING("Invalid length specified in update.");
     return NS_ERROR_FAILURE;
   }
 
   if (!(mChunkState.hashSize == PREFIX_SIZE || mChunkState.hashSize == COMPLETE_SIZE)) {
     NS_WARNING("Invalid hash size specified in update.");
     return NS_ERROR_FAILURE;
   }
 
   if (StringEndsWith(mTableUpdate->TableName(),
                      NS_LITERAL_CSTRING("-shavar")) ||
       StringEndsWith(mTableUpdate->TableName(),
                      NS_LITERAL_CSTRING("-simple"))) {
     // Accommodate test tables ending in -simple for now.
     mChunkState.type = (command == 'a') ? CHUNK_ADD : CHUNK_SUB;
   } else if (StringEndsWith(mTableUpdate->TableName(),
     NS_LITERAL_CSTRING("-digest256"))) {
-    LOG(("Processing digest256 data"));
+    PARSER_LOG(("Processing digest256 data"));
     mChunkState.type = (command == 'a') ? CHUNK_ADD_DIGEST : CHUNK_SUB_DIGEST;
   }
   nsresult rv;
   switch (mChunkState.type) {
     case CHUNK_ADD:
       rv = mTableUpdate->NewAddChunk(mChunkState.num);
       if (NS_FAILED(rv)) {
         return rv;
@@ -303,17 +308,17 @@ ProtocolParser::ProcessChunk(bool* aDone
   // Pull the chunk out of the pending stream data.
   nsAutoCString chunk;
   chunk.Assign(Substring(mPending, 0, mChunkState.length));
   mPending.Cut(0, mChunkState.length);
 
   *aDone = false;
   mState = PROTOCOL_STATE_CONTROL;
 
-  //LOG(("Handling a %d-byte chunk", chunk.Length()));
+  PARSER_LOG(("Handling a %d-byte chunk", chunk.Length()));
   if (StringEndsWith(mTableUpdate->TableName(),
                      NS_LITERAL_CSTRING("-shavar"))) {
     return ProcessShaChunk(chunk);
   }
   if (StringEndsWith(mTableUpdate->TableName(),
              NS_LITERAL_CSTRING("-digest256"))) {
     return ProcessDigestChunk(chunk);
   }
@@ -410,17 +415,17 @@ ProtocolParser::ProcessShaChunk(const ns
     } else if (mChunkState.type == CHUNK_ADD && mChunkState.hashSize == COMPLETE_SIZE) {
       rv = ProcessHostAddComplete(numEntries, aChunk, &start);
     } else if (mChunkState.type == CHUNK_SUB && mChunkState.hashSize == PREFIX_SIZE) {
       rv = ProcessHostSub(domain, numEntries, aChunk, &start);
     } else if (mChunkState.type == CHUNK_SUB && mChunkState.hashSize == COMPLETE_SIZE) {
       rv = ProcessHostSubComplete(numEntries, aChunk, &start);
     } else {
       NS_WARNING("Unexpected chunk type/hash size!");
-      LOG(("Got an unexpected chunk type/hash size: %s:%d",
+      PARSER_LOG(("Got an unexpected chunk type/hash size: %s:%d",
            mChunkState.type == CHUNK_ADD ? "add" : "sub",
            mChunkState.hashSize));
       return NS_ERROR_FAILURE;
     }
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   return NS_OK;
--- a/toolkit/components/url-classifier/nsUrlClassifierDBService.cpp
+++ b/toolkit/components/url-classifier/nsUrlClassifierDBService.cpp
@@ -28,16 +28,17 @@
 #include "nsTArray.h"
 #include "nsNetCID.h"
 #include "nsThreadUtils.h"
 #include "nsXPCOMStrings.h"
 #include "nsProxyRelease.h"
 #include "nsString.h"
 #include "mozilla/Atomics.h"
 #include "mozilla/DebugOnly.h"
+#include "mozilla/ErrorNames.h"
 #include "mozilla/Mutex.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/TimeStamp.h"
 #include "mozilla/Telemetry.h"
 #include "mozilla/Logging.h"
 #include "prprf.h"
 #include "prnetdb.h"
 #include "Entries.h"
@@ -511,16 +512,18 @@ nsUrlClassifierDBServiceWorker::FinishSt
       const ProtocolParser::ForwardedUpdate &forward = forwards[i];
       mUpdateObserver->UpdateUrlRequested(forward.url, forward.table);
     }
     // Hold on to any TableUpdate objects that were created by the
     // parser.
     mTableUpdates.AppendElements(mProtocolParser->GetTableUpdates());
     mProtocolParser->ForgetTableUpdates();
   } else {
+    LOG(("nsUrlClassifierDBService::FinishStream Failed to parse the stream "
+         "using mProtocolParser."));
     mUpdateStatus = mProtocolParser->Status();
   }
   mUpdateObserver->StreamFinished(mProtocolParser->Status(), 0);
 
   if (NS_SUCCEEDED(mUpdateStatus)) {
     if (mProtocolParser->ResetRequested()) {
       mClassifier->Reset();
    }
@@ -535,25 +538,33 @@ NS_IMETHODIMP
 nsUrlClassifierDBServiceWorker::FinishUpdate()
 {
   if (gShuttingDownThread)
     return NS_ERROR_NOT_INITIALIZED;
   NS_ENSURE_STATE(mUpdateObserver);
 
   if (NS_SUCCEEDED(mUpdateStatus)) {
     mUpdateStatus = ApplyUpdate();
+  } else {
+    LOG(("nsUrlClassifierDBServiceWorker::FinishUpdate() Not running "
+         "ApplyUpdate() since the update has already failed."));
   }
 
   mMissCache.Clear();
 
   if (NS_SUCCEEDED(mUpdateStatus)) {
     LOG(("Notifying success: %d", mUpdateWait));
     mUpdateObserver->UpdateSuccess(mUpdateWait);
   } else {
-    LOG(("Notifying error: %d", mUpdateStatus));
+    if (LOG_ENABLED()) {
+      nsAutoCString errorName;
+      mozilla::GetErrorName(mUpdateStatus, errorName);
+      LOG(("Notifying error: %s (%d)", errorName.get(), mUpdateStatus));
+    }
+
     mUpdateObserver->UpdateError(mUpdateStatus);
     /*
      * mark the tables as spoiled, we don't want to block hosts
      * longer than normal because our update failed
     */
     mClassifier->MarkSpoiled(mUpdateTables);
   }
   mUpdateObserver = nullptr;
@@ -798,16 +809,18 @@ nsUrlClassifierLookupCallback::LookupCom
       nsCOMPtr<nsIUrlClassifierHashCompleter> completer;
       nsCString gethashUrl;
       nsresult rv;
       nsCOMPtr<nsIUrlListManager> listManager = do_GetService(
         "@mozilla.org/url-classifier/listmanager;1", &rv);
       NS_ENSURE_SUCCESS(rv, rv);
       rv = listManager->GetGethashUrl(result.mTableName, gethashUrl);
       NS_ENSURE_SUCCESS(rv, rv);
+      LOG(("The match from %s needs to be completed at %s",
+           result.mTableName.get(), gethashUrl.get()));
       // gethashUrls may be empty in 2 cases: test tables, and on startup where
       // we may have found a prefix in an existing table before the listmanager
       // has registered the table. In the second case we should not call
       // complete.
       if ((!gethashUrl.IsEmpty() ||
            StringBeginsWith(result.mTableName, NS_LITERAL_CSTRING("test-"))) &&
           mDBService->GetCompleter(result.mTableName,
                                    getter_AddRefs(completer))) {
@@ -820,16 +833,18 @@ nsUrlClassifierLookupCallback::LookupCom
           mPendingCompletions++;
         }
       } else {
         // For tables with no hash completer, a complete hash match is
         // good enough, we'll consider it fresh, even if it hasn't been updated
         // in 45 minutes.
         if (result.Complete()) {
           result.mFresh = true;
+          LOG(("Skipping completion in a table without a valid completer (%s).",
+               result.mTableName.get()));
         } else {
           NS_WARNING("Partial match in a table without a valid completer, ignoring partial match.");
         }
       }
     }
   }
 
   if (mPendingCompletions == 0) {
@@ -906,18 +921,21 @@ nsUrlClassifierLookupCallback::HandleRes
   nsTArray<nsCString> tables;
   // Build a stringified list of result tables.
   for (uint32_t i = 0; i < mResults->Length(); i++) {
     LookupResult& result = mResults->ElementAt(i);
 
     // Leave out results that weren't confirmed, as their existence on
     // the list can't be verified.  Also leave out randomly-generated
     // noise.
-    if (!result.Confirmed() || result.mNoise) {
-      LOG(("Skipping result from table %s", result.mTableName.get()));
+    if (!result.Confirmed()) {
+      LOG(("Skipping result from table %s (not confirmed)", result.mTableName.get()));
+      continue;
+    } else if (result.mNoise) {
+      LOG(("Skipping result from table %s (noise)", result.mTableName.get()));
       continue;
     }
 
     LOG(("Confirmed result from table %s", result.mTableName.get()));
 
     if (tables.IndexOf(result.mTableName) == nsTArray<nsCString>::NoIndex) {
       tables.AppendElement(result.mTableName);
     }
--- a/toolkit/components/url-classifier/nsUrlClassifierHashCompleter.js
+++ b/toolkit/components/url-classifier/nsUrlClassifierHashCompleter.js
@@ -23,16 +23,33 @@ const PARTIAL_LENGTH = 4;
 
 const BACKOFF_ERRORS = 2;
 const BACKOFF_INTERVAL = 30 * 60 * 1000;
 const BACKOFF_MAX = 8 * 60 * 60 * 1000;
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
 
+// Log only if browser.safebrowsing.debug is true
+function log(...stuff) {
+  let logging = null;
+  try {
+    logging = Services.prefs.getBoolPref("browser.safebrowsing.debug");
+  } catch(e) {
+    return;
+  }
+  if (!logging) {
+    return;
+  }
+
+  var d = new Date();
+  let msg = "hashcompleter: " + d.toTimeString() + ": " + stuff.join(" ");
+  dump(msg + "\n");
+}
+
 function HashCompleter() {
   // The current HashCompleterRequest in flight. Once it is started, it is set
   // to null. It may be used by multiple calls to |complete| in succession to
   // avoid creating multiple requests to the same gethash URL.
   this._currentRequest = null;
   // A map of gethashUrls to HashCompleterRequests that haven't yet begun.
   this._pendingRequests = {};
 
@@ -270,16 +287,17 @@ HashCompleterRequest.prototype = {
       prefixes[i] = prefixes[j];
       prefixes[j] = temp;
     }
 
     let body;
     body = PARTIAL_LENGTH + ":" + (PARTIAL_LENGTH * prefixes.length) +
            "\n" + prefixes.join("");
 
+    log('Requesting completions for ' + prefixes.length + ' ' + PARTIAL_LENGTH + '-byte prefixes: ' + body);
     return body;
   },
 
   // Sets the request body of this._channel.
   addRequestBody: function HCR_addRequestBody(aBody) {
     let inputStream = Cc["@mozilla.org/io/string-input-stream;1"].
                       createInstance(Ci.nsIStringInputStream);
 
@@ -294,16 +312,17 @@ HashCompleterRequest.prototype = {
 
   // Parses the response body and eventually adds items to the |responses| array
   // for elements of |this._requests|.
   handleResponse: function HCR_handleResponse() {
     if (this._response == "") {
       return;
     }
 
+    log('Response: ' + this._response);
     let start = 0;
 
     let length = this._response.length;
     while (start != length) {
       start = this.handleTable(start);
     }
   },
 
@@ -323,16 +342,17 @@ HashCompleterRequest.prototype = {
     if (entries.length != 3) {
       throw errorWithStack();
     }
 
     let list = entries[0];
     let addChunk = parseInt(entries[1]);
     let dataLength = parseInt(entries[2]);
 
+    log('Response includes add chunks for ' + list + ': ' + addChunk);
     if (dataLength % COMPLETE_LENGTH != 0 ||
         dataLength == 0 ||
         dataLength > body.length - (newlineIndex + 1)) {
       throw errorWithStack();
     }
 
     let data = body.substr(newlineIndex + 1, dataLength);
     for (let i = 0; i < (dataLength / COMPLETE_LENGTH); i++) {
@@ -409,16 +429,17 @@ HashCompleterRequest.prototype = {
     if (Components.isSuccessCode(aStatusCode)) {
       let channel = aRequest.QueryInterface(Ci.nsIHttpChannel);
       let success = channel.requestSucceeded;
       httpStatus = channel.responseStatus;
       if (!success) {
         aStatusCode = Cr.NS_ERROR_ABORT;
       }
     }
+    log('Received a ' + httpStatus + ' status code from the gethash server.');
 
     let success = Components.isSuccessCode(aStatusCode);
     // Notify the RequestBackoff once a response is received.
     this._completer.finishRequest(this.gethashUrl, httpStatus);
 
     if (success) {
       try {
         this.handleResponse();
--- a/toolkit/content/tests/widgets/videocontrols_direction-1-ref.html
+++ b/toolkit/content/tests/widgets/videocontrols_direction-1-ref.html
@@ -1,10 +1,10 @@
 <!DOCTYPE HTML>
 <html>
 <head>
 <link rel="stylesheet" type="text/css" href="videomask.css">
 </head>
 <body style="text-align: right;">
-<video controls preload="auto" id="av" source="audio.wav"></video>
+<video controls preload="none" id="av" source="audio.wav"></video>
 <div id="mask"></div>
 </body>
 </html>
--- a/toolkit/content/tests/widgets/videocontrols_direction-1a.html
+++ b/toolkit/content/tests/widgets/videocontrols_direction-1a.html
@@ -1,10 +1,10 @@
 <!DOCTYPE HTML>
 <html dir="rtl">
 <head>
 <link rel="stylesheet" type="text/css" href="videomask.css">
 </head>
 <body>
-<video controls preload="auto" id="av" source="audio.wav"></video>
+<video controls preload="none" id="av" source="audio.wav"></video>
 <div id="mask"></div>
 </body>
 </html>
--- a/toolkit/content/tests/widgets/videocontrols_direction-1b.html
+++ b/toolkit/content/tests/widgets/videocontrols_direction-1b.html
@@ -1,10 +1,10 @@
 <!DOCTYPE HTML>
 <html style="direction: rtl">
 <head>
 <link rel="stylesheet" type="text/css" href="videomask.css">
 </head>
 <body>
-<video controls preload="auto" id="av" source="audio.wav"></video>
+<video controls preload="none" id="av" source="audio.wav"></video>
 <div id="mask"></div>
 </body>
 </html>
--- a/toolkit/content/tests/widgets/videocontrols_direction-1c.html
+++ b/toolkit/content/tests/widgets/videocontrols_direction-1c.html
@@ -1,10 +1,10 @@
 <!DOCTYPE HTML>
 <html>
 <head>
 <link rel="stylesheet" type="text/css" href="videomask.css">
 </head>
 <body style="direction: rtl">
-<video controls preload="auto" id="av" source="audio.wav"></video>
+<video controls preload="none" id="av" source="audio.wav"></video>
 <div id="mask"></div>
 </body>
 </html>
--- a/toolkit/content/tests/widgets/videocontrols_direction-1d.html
+++ b/toolkit/content/tests/widgets/videocontrols_direction-1d.html
@@ -1,10 +1,10 @@
 <!DOCTYPE HTML>
 <html>
 <head>
 <link rel="stylesheet" type="text/css" href="videomask.css">
 </head>
 <body style="text-align: right;">
-<video controls preload="auto" id="av" source="audio.wav" dir="rtl"></video>
+<video controls preload="none" id="av" source="audio.wav" dir="rtl"></video>
 <div id="mask"></div>
 </body>
 </html>
--- a/toolkit/content/tests/widgets/videocontrols_direction-1e.html
+++ b/toolkit/content/tests/widgets/videocontrols_direction-1e.html
@@ -1,10 +1,10 @@
 <!DOCTYPE HTML>
 <html>
 <head>
 <link rel="stylesheet" type="text/css" href="videomask.css">
 </head>
 <body style="text-align: right;">
-<video controls preload="auto" id="av" source="audio.wav" style="direction: rtl;"></video>
+<video controls preload="none" id="av" source="audio.wav" style="direction: rtl;"></video>
 <div id="mask"></div>
 </body>
 </html>
--- a/toolkit/content/tests/widgets/videocontrols_direction-2-ref.html
+++ b/toolkit/content/tests/widgets/videocontrols_direction-2-ref.html
@@ -1,10 +1,10 @@
 <!DOCTYPE HTML>
 <html>
 <head>
 <link rel="stylesheet" type="text/css" href="videomask.css">
 </head>
 <body style="text-align: right;">
-<audio controls preload="auto" id="av" source="audio.wav"></audio>
+<audio controls preload="none" id="av" source="audio.wav"></audio>
 <div id="mask"></div>
 </body>
 </html>
--- a/toolkit/content/tests/widgets/videocontrols_direction-2a.html
+++ b/toolkit/content/tests/widgets/videocontrols_direction-2a.html
@@ -1,10 +1,10 @@
 <!DOCTYPE HTML>
 <html dir="rtl">
 <head>
 <link rel="stylesheet" type="text/css" href="videomask.css">
 </head>
 <body>
-<audio controls preload="auto" id="av" source="audio.wav"></audio>
+<audio controls preload="none" id="av" source="audio.wav"></audio>
 <div id="mask"></div>
 </body>
 </html>
--- a/toolkit/content/tests/widgets/videocontrols_direction-2b.html
+++ b/toolkit/content/tests/widgets/videocontrols_direction-2b.html
@@ -1,10 +1,10 @@
 <!DOCTYPE HTML>
 <html style="direction: rtl">
 <head>
 <link rel="stylesheet" type="text/css" href="videomask.css">
 </head>
 <body>
-<audio controls preload="auto" id="av" source="audio.wav"></audio>
+<audio controls preload="none" id="av" source="audio.wav"></audio>
 <div id="mask"></div>
 </body>
 </html>
--- a/toolkit/content/tests/widgets/videocontrols_direction-2c.html
+++ b/toolkit/content/tests/widgets/videocontrols_direction-2c.html
@@ -1,10 +1,10 @@
 <!DOCTYPE HTML>
 <html>
 <head>
 <link rel="stylesheet" type="text/css" href="videomask.css">
 </head>
 <body style="direction: rtl">
-<audio controls preload="auto" id="av" source="audio.wav"></audio>
+<audio controls preload="none" id="av" source="audio.wav"></audio>
 <div id="mask"></div>
 </body>
 </html>
--- a/toolkit/content/tests/widgets/videocontrols_direction-2d.html
+++ b/toolkit/content/tests/widgets/videocontrols_direction-2d.html
@@ -1,10 +1,10 @@
 <!DOCTYPE HTML>
 <html>
 <head>
 <link rel="stylesheet" type="text/css" href="videomask.css">
 </head>
 <body style="text-align: right;">
<