merge mozilla-inbound to mozilla-central a=merge
authorCarsten "Tomcat" Book <cbook@mozilla.com>
Tue, 21 Jun 2016 11:56:06 +0200
changeset 302160 0ffa18cfc8b4e9970275ab6dd94686792a5c8ae1
parent 302159 027db1e33f89606c4996feae0203e5f3bb5db43d (current diff)
parent 302133 629faa5d9254287324f40989941fca237beb93ac (diff)
child 302161 70cb21780f68346c5f771f73d39056813814fba5
child 302198 7fb69043ac05ed4c505a4a14f9c1a3130aa1715d
child 302208 eb945fc547afc9a4254ef339335fe831c0f68db2
push id78626
push usercbook@mozilla.com
push dateTue, 21 Jun 2016 10:14:39 +0000
treeherdermozilla-inbound@70cb21780f68 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone50.0a1
first release with
nightly linux32
0ffa18cfc8b4 / 50.0a1 / 20160621030208 / files
nightly linux64
0ffa18cfc8b4 / 50.0a1 / 20160621030208 / files
nightly mac
0ffa18cfc8b4 / 50.0a1 / 20160621030208 / files
nightly win32
0ffa18cfc8b4 / 50.0a1 / 20160621030208 / files
nightly win64
0ffa18cfc8b4 / 50.0a1 / 20160621030208 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
merge mozilla-inbound to mozilla-central a=merge
modules/brotli/dec/streams.c
modules/brotli/dec/streams.h
taskcluster/ci/legacy/tasks/decision/periodic_alder.yml
--- a/Makefile.in
+++ b/Makefile.in
@@ -232,16 +232,19 @@ recurse_pre-export:: install-manifests
 binaries::
 	@$(MAKE) install-manifests NO_REMOVE=1 install_manifests=dist/include
 endif
 
 # For historical reasons that are unknown, $(DIST)/sdk is always blown away
 # with no regard for PGO passes. This decision could probably be revisited.
 recurse_pre-export:: install-dist/sdk
 
+recurse_artifact:
+	$(topsrcdir)/mach --log-no-times artifact install
+
 ifndef JS_STANDALONE
 ifdef ENABLE_TESTS
 # Additional makefile targets to call automated test suites
 include $(topsrcdir)/testing/testsuite-targets.mk
 endif
 endif
 
 default all::
--- a/accessible/base/EventTree.cpp
+++ b/accessible/base/EventTree.cpp
@@ -31,62 +31,20 @@ TreeMutation::TreeMutation(Accessible* a
 
 #ifdef A11Y_LOG
   if (mEventTree != kNoEventTree && logging::IsEnabled(logging::eEventTree)) {
     logging::MsgBegin("EVENTS_TREE", "reordering tree before");
     logging::AccessibleInfo("reordering for", mParent);
     Controller()->RootEventTree().Log();
     logging::MsgEnd();
 
-    logging::MsgBegin("EVENTS_TREE", "Container tree");
     if (logging::IsEnabled(logging::eVerbose)) {
-      nsAutoString level;
-      Accessible* root = mParent->Document();
-      do {
-        const char* prefix = "";
-        if (mParent == root) {
-          prefix = "_X_";
-        }
-        else {
-          const EventTree& ret = Controller()->RootEventTree();
-          if (ret.Find(root)) {
-            prefix = "_с_";
-          }
-        }
-
-        printf("%s", NS_ConvertUTF16toUTF8(level).get());
-        logging::AccessibleInfo(prefix, root);
-        if (root->FirstChild() && !root->FirstChild()->IsDoc()) {
-          level.Append(NS_LITERAL_STRING("  "));
-          root = root->FirstChild();
-          continue;
-        }
-        int32_t idxInParent = root->mParent ?
-          root->mParent->mChildren.IndexOf(root) : -1;
-        if (idxInParent != -1 &&
-            idxInParent < static_cast<int32_t>(root->mParent->mChildren.Length() - 1)) {
-          root = root->mParent->mChildren.ElementAt(idxInParent + 1);
-          continue;
-        }
-
-        while ((root = root->Parent()) && !root->IsDoc()) {
-          level.Cut(0, 2);
-
-          int32_t idxInParent = root->mParent ?
-          root->mParent->mChildren.IndexOf(root) : -1;
-          if (idxInParent != -1 &&
-              idxInParent < static_cast<int32_t>(root->mParent->mChildren.Length() - 1)) {
-            root = root->mParent->mChildren.ElementAt(idxInParent + 1);
-            break;
-          }
-        }
-      }
-      while (root && !root->IsDoc());
+      logging::Tree("EVENTS_TREE", "Container tree", mParent->Document(),
+                    PrefixLog, static_cast<void*>(this));
     }
-    logging::MsgEnd();
   }
 #endif
 
   mParent->mStateFlags |= Accessible::eKidsMutating;
 }
 
 TreeMutation::~TreeMutation()
 {
@@ -168,16 +126,32 @@ TreeMutation::Done()
     logging::MsgBegin("EVENTS_TREE", "reordering tree after");
     logging::AccessibleInfo("reordering for", mParent);
     Controller()->RootEventTree().Log();
     logging::MsgEnd();
   }
 #endif
 }
 
+#ifdef A11Y_LOG
+const char*
+TreeMutation::PrefixLog(void* aData, Accessible* aAcc)
+{
+  TreeMutation* thisObj = reinterpret_cast<TreeMutation*>(aData);
+  if (thisObj->mParent == aAcc) {
+    return "_X_";
+  }
+  const EventTree& ret = thisObj->Controller()->RootEventTree();
+  if (ret.Find(aAcc)) {
+    return "_с_";
+  }
+  return "";
+}
+#endif
+
 
 ////////////////////////////////////////////////////////////////////////////////
 // EventTree
 
 void
 EventTree::Process(const RefPtr<DocAccessible>& aDeathGrip)
 {
   while (mFirst) {
--- a/accessible/base/EventTree.h
+++ b/accessible/base/EventTree.h
@@ -34,16 +34,20 @@ public:
   void Done();
 
 private:
   NotificationController* Controller() const
     { return mParent->Document()->Controller(); }
 
   static EventTree* const kNoEventTree;
 
+#ifdef A11Y_LOG
+  static const char* PrefixLog(void* aData, Accessible*);
+#endif
+
   Accessible* mParent;
   uint32_t mStartIdx;
   uint32_t mStateFlagsCopy;
   EventTree* mEventTree;
 
 #ifdef DEBUG
   bool mIsDone;
 #endif
--- a/accessible/base/Logging.cpp
+++ b/accessible/base/Logging.cpp
@@ -669,16 +669,57 @@ logging::TreeInfo(const char* aMsg, uint
     for (uint32_t idx = 0; idx < aParent->ChildCount(); idx++) {
       AccessibleInfo("child", aParent->GetChildAt(idx));
     }
     MsgEnd();
   }
 }
 
 void
+logging::Tree(const char* aTitle, const char* aMsgText,
+              DocAccessible* aDocument, GetTreePrefix aPrefixFunc,
+              void* aGetTreePrefixData)
+{
+  logging::MsgBegin(aTitle, aMsgText);
+
+  nsAutoString level;
+  Accessible* root = aDocument;
+  do {
+    const char* prefix = aPrefixFunc ? aPrefixFunc(aGetTreePrefixData, root) : "";
+    printf("%s", NS_ConvertUTF16toUTF8(level).get());
+    logging::AccessibleInfo(prefix, root);
+    if (root->FirstChild() && !root->FirstChild()->IsDoc()) {
+      level.Append(NS_LITERAL_STRING("  "));
+      root = root->FirstChild();
+      continue;
+    }
+    int32_t idxInParent = !root->IsDoc() && root->mParent ?
+      root->mParent->mChildren.IndexOf(root) : -1;
+    if (idxInParent != -1 &&
+        idxInParent < static_cast<int32_t>(root->mParent->mChildren.Length() - 1)) {
+      root = root->mParent->mChildren.ElementAt(idxInParent + 1);
+      continue;
+    }
+    while (!root->IsDoc() && (root = root->Parent())) {
+      level.Cut(0, 2);
+      int32_t idxInParent = !root->IsDoc() && root->mParent ?
+        root->mParent->mChildren.IndexOf(root) : -1;
+      if (idxInParent != -1 &&
+          idxInParent < static_cast<int32_t>(root->mParent->mChildren.Length() - 1)) {
+        root = root->mParent->mChildren.ElementAt(idxInParent + 1);
+        break;
+      }
+    }
+  }
+  while (root && !root->IsDoc());
+
+  logging::MsgEnd();
+}
+
+void
 logging::MsgBegin(const char* aTitle, const char* aMsgText, ...)
 {
   printf("\nA11Y %s: ", aTitle);
 
   va_list argptr;
   va_start(argptr, aMsgText);
   vprintf(aMsgText, argptr);
   va_end(argptr);
--- a/accessible/base/Logging.h
+++ b/accessible/base/Logging.h
@@ -135,16 +135,23 @@ void SelChange(nsISelection* aSelection,
  */
 void TreeInfo(const char* aMsg, uint32_t aExtraFlags, ...);
 void TreeInfo(const char* aMsg, uint32_t aExtraFlags,
               const char* aMsg1, Accessible* aAcc,
               const char* aMsg2, nsINode* aNode);
 void TreeInfo(const char* aMsg, uint32_t aExtraFlags, Accessible* aParent);
 
 /**
+ * Log the accessible tree.
+ */
+typedef const char* (*GetTreePrefix)(void* aData, Accessible*);
+void Tree(const char* aTitle, const char* aMsgText, DocAccessible* aDoc,
+          GetTreePrefix aPrefixFunc = nullptr, void* aGetTreePrefixData = nullptr);
+
+/**
  * Log the message ('title: text' format) on new line. Print the start and end
  * boundaries of the message body designated by '{' and '}' (2 spaces indent for
  * body).
  */
 void MsgBegin(const char* aTitle, const char* aMsgText, ...);
 void MsgEnd();
 
 /**
--- a/accessible/generic/Accessible.h
+++ b/accessible/generic/Accessible.h
@@ -45,16 +45,24 @@ class ProxyAccessible;
 class Relation;
 class RootAccessible;
 class TableAccessible;
 class TableCellAccessible;
 class TextLeafAccessible;
 class XULLabelAccessible;
 class XULTreeAccessible;
 
+#ifdef A11Y_LOG
+namespace logging {
+  typedef const char* (*GetTreePrefix)(void* aData, Accessible*);
+  void Tree(const char* aTitle, const char* aMsgText, DocAccessible* aDoc,
+            GetTreePrefix aPrefixFunc, void* GetTreePrefixData);
+};
+#endif
+
 /**
  * Name type flags.
  */
 enum ENameValueFlag {
   /**
    * Name either
    *  a) present (not empty): !name.IsEmpty()
    *  b) no name (was missed): name.IsVoid()
@@ -1115,16 +1123,22 @@ protected:
    */
   uint32_t mStateFlags : kStateFlagsBits;
   uint32_t mContextFlags : kContextFlagsBits;
   uint32_t mType : kTypeBits;
   uint32_t mGenericTypes : kGenericTypesBits;
 
   void StaticAsserts() const;
 
+#ifdef A11Y_LOG
+  friend void logging::Tree(const char* aTitle, const char* aMsgText,
+                            DocAccessible* aDoc,
+                            logging::GetTreePrefix aPrefixFunc,
+                            void* aGetTreePrefixData);
+#endif
   friend class DocAccessible;
   friend class xpcAccessible;
   friend class TreeMutation;
 
   nsAutoPtr<mozilla::a11y::EmbeddedObjCollector> mEmbeddedObjCollector;
   union {
     int32_t mIndexOfEmbeddedChild;
     uint32_t mProxyInterfaces;
--- a/accessible/interfaces/moz.build
+++ b/accessible/interfaces/moz.build
@@ -1,15 +1,15 @@
 # -*- 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/.
 
-if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
+if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows' and CONFIG['COMPILE_ENVIRONMENT']:
     DIRS += ['msaa', 'ia2']
 
 XPIDL_SOURCES += [
     'nsIAccessible.idl',
     'nsIAccessibleApplication.idl',
     'nsIAccessibleCaretMoveEvent.idl',
     'nsIAccessibleDocument.idl',
     'nsIAccessibleEditableText.idl',
--- a/addon-sdk/source/lib/toolkit/loader.js
+++ b/addon-sdk/source/lib/toolkit/loader.js
@@ -176,17 +176,17 @@ function readURI(uri) {
     let proto = Cc["@mozilla.org/network/protocol;1?name=resource"].
                 getService(Ci.nsIResProtocolHandler);
     uri = proto.resolveURI(nsURI);
   }
 
   let stream = NetUtil.newChannel({
     uri: NetUtil.newURI(uri, 'UTF-8'),
     loadUsingSystemPrincipal: true}
-  ).open();
+  ).open2();
   let count = stream.available();
   let data = NetUtil.readInputStreamToString(stream, count, {
     charset: 'UTF-8'
   });
 
   stream.close();
 
   return data;
--- a/build/autoconf/compiler-opts.m4
+++ b/build/autoconf/compiler-opts.m4
@@ -90,40 +90,16 @@ fi
 
 dnl ========================================================
 dnl =
 dnl = Debugging Options
 dnl =
 dnl ========================================================
 AC_DEFUN([MOZ_DEBUGGING_OPTS],
 [
-dnl Debug info is ON by default.
-if test -z "$MOZ_DEBUG_FLAGS"; then
-  if test -n "$_MSC_VER"; then
-    MOZ_DEBUG_FLAGS="-Zi"
-  else
-    MOZ_DEBUG_FLAGS="-g"
-  fi
-fi
-
-AC_SUBST(MOZ_DEBUG_FLAGS)
-
-MOZ_ARG_ENABLE_STRING(debug,
-[  --enable-debug[=DBG]    Enable building with developer debug info
-                           (using compiler flags DBG)],
-[ if test "$enableval" != "no"; then
-    MOZ_DEBUG=1
-    if test -n "$enableval" -a "$enableval" != "yes"; then
-        MOZ_DEBUG_FLAGS=`echo $enableval | sed -e 's|\\\ | |g'`
-        _MOZ_DEBUG_FLAGS_SET=1
-    fi
-  else
-    MOZ_DEBUG=
-  fi ],
-  MOZ_DEBUG=)
 
 if test -z "$MOZ_DEBUG" -o -n "$MOZ_ASAN"; then
     MOZ_NO_DEBUG_RTL=1
 fi
 
 AC_SUBST(MOZ_NO_DEBUG_RTL)
 
 MOZ_DEBUG_ENABLE_DEFS="DEBUG TRACING"
@@ -151,41 +127,16 @@ if test -n "$MOZ_DEBUG"; then
 
     MOZ_DEBUG_DEFINES="$MOZ_DEBUG_ENABLE_DEFS"
 else
     MOZ_DEBUG_DEFINES="NDEBUG TRIMMED"
 fi
 
 AC_SUBST_LIST(MOZ_DEBUG_DEFINES)
 
-dnl ========================================================
-dnl = Enable generation of debug symbols
-dnl ========================================================
-MOZ_ARG_ENABLE_STRING(debug-symbols,
-[  --enable-debug-symbols[=DBG]
-                          Enable debugging symbols (using compiler flags DBG)],
-[ if test "$enableval" != "no"; then
-      MOZ_DEBUG_SYMBOLS=1
-      if test -n "$enableval" -a "$enableval" != "yes"; then
-          if test -z "$_MOZ_DEBUG_FLAGS_SET"; then
-              MOZ_DEBUG_FLAGS=`echo $enableval | sed -e 's|\\\ | |g'`
-          else
-              AC_MSG_ERROR([--enable-debug-symbols flags cannot be used with --enable-debug flags])
-          fi
-      fi
-  else
-      MOZ_DEBUG_SYMBOLS=
-  fi ],
-  MOZ_DEBUG_SYMBOLS=1)
-
-if test -n "$MOZ_DEBUG" -o -n "$MOZ_DEBUG_SYMBOLS"; then
-    AC_DEFINE(MOZ_DEBUG_SYMBOLS)
-    export MOZ_DEBUG_SYMBOLS
-fi
-
 ])
 
 dnl A high level macro for selecting compiler options.
 AC_DEFUN([MOZ_COMPILER_OPTS],
 [
   MOZ_DEBUGGING_OPTS
   MOZ_RTTI
 if test "$CLANG_CXX"; then
--- a/build/moz.configure/old.configure
+++ b/build/moz.configure/old.configure
@@ -167,19 +167,17 @@ def old_configure_options(*options):
     '--enable-clang-plugin',
     '--enable-content-sandbox',
     '--enable-cookies',
     '--enable-cpp-rtti',
     '--enable-crashreporter',
     '--enable-ctypes',
     '--enable-dbm',
     '--enable-dbus',
-    '--enable-debug',
     '--enable-debug-js-modules',
-    '--enable-debug-symbols',
     '--enable-directshow',
     '--enable-dtrace',
     '--enable-dump-painting',
     '--enable-elf-hack',
     '--enable-extensions',
     '--enable-faststripe',
     '--enable-feeds',
     '--enable-gamepad',
--- a/build/moz.configure/toolchain.configure
+++ b/build/moz.configure/toolchain.configure
@@ -599,8 +599,44 @@ def compiler(language, host_or_target, c
 
 
 c_compiler = compiler('C', target)
 cxx_compiler = compiler('C++', target, c_compiler=c_compiler)
 host_c_compiler = compiler('C', host, other_compiler=c_compiler)
 host_cxx_compiler = compiler('C++', host, c_compiler=host_c_compiler,
                              other_compiler=cxx_compiler,
                              other_c_compiler=c_compiler)
+
+@depends(c_compiler)
+def default_debug_flags(compiler_info):
+    # Debug info is ON by default.
+    if compiler_info.type == 'msvc':
+        return '-Zi'
+    return '-g'
+
+option(env='MOZ_DEBUG_FLAGS',
+       nargs=1,
+       help='Debug compiler flags')
+
+imply_option('--enable-debug-symbols',
+             depends_if('--enable-debug')(lambda v: v))
+
+js_option('--enable-debug-symbols',
+          nargs='?',
+          default=True,
+          help='Enable debug symbols using the given compiler flags')
+
+set_config('MOZ_DEBUG_SYMBOLS',
+           depends_if('--enable-debug-symbols')(lambda _: True))
+
+@depends('MOZ_DEBUG_FLAGS', '--enable-debug-symbols', default_debug_flags)
+def debug_flags(env_debug_flags, enable_debug_flags, default_debug_flags):
+    # If MOZ_DEBUG_FLAGS is set, and --enable-debug-symbols is set to a value,
+    # --enable-debug-symbols takes precedence. Note, the value of
+    # --enable-debug-symbols may be implied by --enable-debug.
+    if len(enable_debug_flags):
+        return enable_debug_flags[0]
+    if env_debug_flags:
+        return env_debug_flags[0]
+    return default_debug_flags
+
+set_config('MOZ_DEBUG_FLAGS', debug_flags)
+add_old_configure_assignment('MOZ_DEBUG_FLAGS', debug_flags)
--- a/config/baseconfig.mk
+++ b/config/baseconfig.mk
@@ -40,17 +40,17 @@ ifeq (a,$(firstword a$(subst /, ,$(srcdi
 $(error MSYS-style srcdir are not supported for Windows builds.)
 endif
 endif
 endif # WINNT
 
 ifndef INCLUDED_AUTOCONF_MK
 default::
 else
-TIERS := pre-export export $(if $(COMPILE_ENVIRONMENT),compile )misc libs tools
+TIERS := $(if $(MOZ_ARTIFACT_BUILDS),artifact )pre-export export $(if $(COMPILE_ENVIRONMENT),compile )misc libs tools
 endif
 
 # These defines are used to support the twin-topsrcdir model for comm-central.
 ifdef MOZILLA_SRCDIR
   MOZILLA_DIR = $(MOZILLA_SRCDIR)
 else
   MOZILLA_DIR = $(topsrcdir)
 endif
--- a/docshell/shistory/nsSHistory.cpp
+++ b/docshell/shistory/nsSHistory.cpp
@@ -1691,17 +1691,17 @@ nsSHistory::CompareFrames(nsISHEntry* aP
 
   // Create an array for child docshells.
   nsCOMArray<nsIDocShell> docshells;
   for (int32_t i = 0; i < dsCount; ++i) {
     nsCOMPtr<nsIDocShellTreeItem> treeItem;
     aParent->GetChildAt(i, getter_AddRefs(treeItem));
     nsCOMPtr<nsIDocShell> shell = do_QueryInterface(treeItem);
     if (shell) {
-      docshells.AppendObject(shell);
+      docshells.AppendElement(shell.forget());
     }
   }
 
   // Search for something to load next.
   for (int32_t i = 0; i < ncnt; ++i) {
     // First get an entry which may cause a new page to be loaded.
     nsCOMPtr<nsISHEntry> nChild;
     nextContainer->GetChildAt(i, getter_AddRefs(nChild));
--- a/dom/base/ScriptSettings.cpp
+++ b/dom/base/ScriptSettings.cpp
@@ -263,39 +263,16 @@ GetWebIDLCallerPrincipal()
 
   // If we have an entry point that is not NoJSAPI, we know it must be an
   // AutoEntryScript.
   if (!entry || entry->NoJSAPI()) {
     return nullptr;
   }
   AutoEntryScript* aes = static_cast<AutoEntryScript*>(entry);
 
-  // We can't yet rely on the Script Settings Stack to properly determine the
-  // entry script, because there are still lots of places in the tree where we
-  // don't yet use an AutoEntryScript (bug 951991 tracks this work). In the
-  // mean time though, we can make some observations to hack around the
-  // problem:
-  //
-  // (1) All calls into JS-implemented WebIDL go through CallSetup, which goes
-  //     through AutoEntryScript.
-  // (2) The top candidate entry point in the Script Settings Stack is the
-  //     entry point if and only if no other JSContexts have been pushed on
-  //     top of the push made by that entry's AutoEntryScript.
-  //
-  // Because of (1), all of the cases where we might return a non-null
-  // WebIDL Caller are guaranteed to have put an entry on the Script Settings
-  // Stack, so we can restrict our search to that. Moreover, (2) gives us a
-  // criterion to determine whether an entry in the Script Setting Stack means
-  // that we should return a non-null WebIDL Caller.
-  //
-  // Once we fix bug 951991, this can all be simplified.
-  if (!aes->CxPusherIsStackTop()) {
-    return nullptr;
-  }
-
   return aes->mWebIDLCallerPrincipal;
 }
 
 AutoJSAPI::AutoJSAPI()
   : mCx(nullptr)
   , mIsMainThread(false) // For lack of anything better
 {
 }
@@ -750,19 +727,19 @@ AutoNoJSAPI::AutoNoJSAPI(bool aIsMainThr
 }
 
 danger::AutoCxPusher::AutoCxPusher(JSContext* cx, bool allowNull)
 {
   MOZ_ASSERT_IF(!allowNull, cx);
 
   XPCJSContextStack *stack = XPCJSRuntime::Get()->GetJSContextStack();
   stack->Push(cx);
-  mStackDepthAfterPush = stack->Count();
 
 #ifdef DEBUG
+  mStackDepthAfterPush = stack->Count();
   mPushedContext = cx;
   mCompartmentDepthOnEntry = cx ? js::GetEnterCompartmentDepth(cx) : 0;
 #endif
 
   // Enter a request and a compartment for the duration that the cx is on the
   // stack if non-null.
   if (cx) {
     mAutoRequest.emplace(cx);
@@ -776,28 +753,29 @@ danger::AutoCxPusher::~AutoCxPusher()
 
   // When we push a context, we may save the frame chain and pretend like we
   // haven't entered any compartment. This gets restored on Pop(), but we can
   // run into trouble if a Push/Pop are interleaved with a
   // JSAutoEnterCompartment. Make sure the compartment depth right before we
   // pop is the same as it was right after we pushed.
   MOZ_ASSERT_IF(mPushedContext, mCompartmentDepthOnEntry ==
                                 js::GetEnterCompartmentDepth(mPushedContext));
-  DebugOnly<JSContext*> stackTop;
   MOZ_ASSERT(mPushedContext == nsXPConnect::XPConnect()->GetCurrentJSContext());
   XPCJSRuntime::Get()->GetJSContextStack()->Pop();
 }
 
+#ifdef DEBUG
 bool
 danger::AutoCxPusher::IsStackTop() const
 {
   uint32_t currentDepth = XPCJSRuntime::Get()->GetJSContextStack()->Count();
   MOZ_ASSERT(currentDepth >= mStackDepthAfterPush);
   return currentDepth == mStackDepthAfterPush;
 }
+#endif
 
 } // namespace dom
 
 AutoJSContext::AutoJSContext(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM_IN_IMPL)
   : mCx(nullptr)
 {
   JS::AutoSuppressGCAnalysis nogc;
   MOZ_ASSERT(!mCx, "mCx should not be initialized!");
--- a/dom/base/ScriptSettings.h
+++ b/dom/base/ScriptSettings.h
@@ -41,18 +41,18 @@ public:
   ~AutoCxPusher();
 
   // Returns true if this AutoCxPusher performed the push that is currently at
   // the top of the cx stack.
   bool IsStackTop() const;
 
 private:
   mozilla::Maybe<JSAutoRequest> mAutoRequest;
+#ifdef DEBUG
   uint32_t mStackDepthAfterPush;
-#ifdef DEBUG
   JSContext* mPushedContext;
   unsigned mCompartmentDepthOnEntry;
 #endif
 };
 
 } /* namespace danger */
 
 /*
@@ -257,17 +257,19 @@ public:
   bool Init(nsGlobalWindow* aWindow, JSContext* aCx);
 
   JSContext* cx() const {
     MOZ_ASSERT(mCx, "Must call Init before using an AutoJSAPI");
     MOZ_ASSERT_IF(mIsMainThread, CxPusherIsStackTop());
     return mCx;
   }
 
+#ifdef DEBUG
   bool CxPusherIsStackTop() const { return mCxPusher->IsStackTop(); }
+#endif
 
   // If HasException, report it.  Otherwise, a no-op.
   void ReportException();
 
   bool HasException() const {
     MOZ_ASSERT_IF(NS_IsMainThread(), CxPusherIsStackTop());
     return JS_IsExceptionPending(cx());
   };
--- a/dom/base/nsDOMWindowUtils.cpp
+++ b/dom/base/nsDOMWindowUtils.cpp
@@ -118,16 +118,61 @@ using namespace mozilla;
 using namespace mozilla::dom;
 using namespace mozilla::ipc;
 using namespace mozilla::layers;
 using namespace mozilla::widget;
 using namespace mozilla::gfx;
 
 class gfxContext;
 
+class OldWindowSize : public LinkedListElement<OldWindowSize>
+{
+public:
+  static void Set(nsIWeakReference* aWindowRef, const nsSize& aSize)
+  {
+    OldWindowSize* item = GetItem(aWindowRef);
+    if (item) {
+      item->mSize = aSize;
+    } else {
+      item = new OldWindowSize(aWindowRef, aSize);
+      sList.insertBack(item);
+    }
+  }
+
+  static nsSize GetAndRemove(nsIWeakReference* aWindowRef)
+  {
+    nsSize result;
+    if (OldWindowSize* item = GetItem(aWindowRef)) {
+      result = item->mSize;
+      delete item;
+    }
+    return result;
+  }
+
+private:
+  explicit OldWindowSize(nsIWeakReference* aWindowRef, const nsSize& aSize)
+    : mWindowRef(aWindowRef), mSize(aSize) { }
+  ~OldWindowSize() { };
+
+  static OldWindowSize* GetItem(nsIWeakReference* aWindowRef)
+  {
+    OldWindowSize* item = sList.getFirst();
+    while (item && item->mWindowRef != aWindowRef) {
+      item = item->getNext();
+    }
+    return item;
+  }
+
+  static LinkedList<OldWindowSize> sList;
+  nsWeakPtr mWindowRef;
+  nsSize mSize;
+};
+
+LinkedList<OldWindowSize> OldWindowSize::sList;
+
 NS_INTERFACE_MAP_BEGIN(nsDOMWindowUtils)
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMWindowUtils)
   NS_INTERFACE_MAP_ENTRY(nsIDOMWindowUtils)
   NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
 NS_INTERFACE_MAP_END
 
 NS_IMPL_ADDREF(nsDOMWindowUtils)
 NS_IMPL_RELEASE(nsDOMWindowUtils)
@@ -136,16 +181,17 @@ nsDOMWindowUtils::nsDOMWindowUtils(nsGlo
 {
   nsCOMPtr<nsISupports> supports = do_QueryObject(aWindow);
   mWindow = do_GetWeakReference(supports);
   NS_ASSERTION(aWindow->IsOuterWindow(), "How did that happen?");
 }
 
 nsDOMWindowUtils::~nsDOMWindowUtils()
 {
+  OldWindowSize::GetAndRemove(mWindow);
 }
 
 nsIPresShell*
 nsDOMWindowUtils::GetPresShell()
 {
   nsCOMPtr<nsPIDOMWindowOuter> window = do_QueryReferent(mWindow);
   if (!window)
     return nullptr;
@@ -3099,72 +3145,16 @@ PrepareForFullscreenChange(nsIPresShell*
       if (aOldSize) {
         viewManager->GetWindowDimensions(&aOldSize->width, &aOldSize->height);
       }
       viewManager->SetWindowDimensions(aSize.width, aSize.height);
     }
   }
 }
 
-class OldWindowSize : public LinkedListElement<OldWindowSize>
-{
-public:
-  static void Set(nsPIDOMWindowOuter* aWindow, const nsSize& aSize)
-  {
-    OldWindowSize* item = GetItem(aWindow);
-    if (item) {
-      item->mSize = aSize;
-    } else if (aWindow) {
-      item = new OldWindowSize(do_GetWeakReference(aWindow), aSize);
-      sList.insertBack(item);
-    }
-  }
-
-  static nsSize GetAndRemove(nsPIDOMWindowOuter* aWindow)
-  {
-    nsSize result;
-    if (OldWindowSize* item = GetItem(aWindow)) {
-      result = item->mSize;
-      delete item;
-    }
-    return result;
-  }
-
-private:
-  explicit OldWindowSize(already_AddRefed<nsIWeakReference>&& aWindow,
-                         const nsSize& aSize)
-    : mWindow(Move(aWindow)), mSize(aSize) { }
-  ~OldWindowSize() { };
-
-  static OldWindowSize* GetItem(nsPIDOMWindowOuter* aWindow)
-  {
-    OldWindowSize* item = sList.getFirst();
-    while (item) {
-      nsCOMPtr<nsPIDOMWindowOuter> window = do_QueryReferent(item->mWindow);
-      if (!window) {
-        OldWindowSize* thisItem = item;
-        item = thisItem->getNext();
-        delete thisItem;
-        continue;
-      }
-      if (window == aWindow) {
-        break;
-      }
-      item = item->getNext();
-    }
-    return item;
-  }
-
-  static LinkedList<OldWindowSize> sList;
-  nsWeakPtr mWindow;
-  nsSize mSize;
-};
-
-LinkedList<OldWindowSize> OldWindowSize::sList;
-
 NS_IMETHODIMP
 nsDOMWindowUtils::HandleFullscreenRequests(bool* aRetVal)
 {
   PROFILER_MARKER("Enter fullscreen");
   nsCOMPtr<nsIDocument> doc = GetDocument();
   NS_ENSURE_STATE(doc);
 
   // Notify the pres shell that we are starting fullscreen change, and
@@ -3172,32 +3162,32 @@ nsDOMWindowUtils::HandleFullscreenReques
   // comes after the fullscreen change call, doing so could avoid an
   // extra resize reflow after this point.
   nsRect screenRect;
   if (nsPresContext* presContext = GetPresContext()) {
     presContext->DeviceContext()->GetRect(screenRect);
   }
   nsSize oldSize;
   PrepareForFullscreenChange(GetPresShell(), screenRect.Size(), &oldSize);
-  OldWindowSize::Set(doc->GetWindow(), oldSize);
+  OldWindowSize::Set(mWindow, oldSize);
 
   *aRetVal = nsIDocument::HandlePendingFullscreenRequests(doc);
   return NS_OK;
 }
 
 nsresult
 nsDOMWindowUtils::ExitFullscreen()
 {
   PROFILER_MARKER("Exit fullscreen");
   nsCOMPtr<nsIDocument> doc = GetDocument();
   NS_ENSURE_STATE(doc);
 
   // Although we would not use the old size if we have already exited
   // fullscreen, we still want to cleanup in case we haven't.
-  nsSize oldSize = OldWindowSize::GetAndRemove(doc->GetWindow());
+  nsSize oldSize = OldWindowSize::GetAndRemove(mWindow);
   if (!doc->GetFullscreenElement()) {
     return NS_OK;
   }
 
   // Notify the pres shell that we are starting fullscreen change, and
   // set the window dimensions in advance. Since the resize message
   // comes after the fullscreen change call, doing so could avoid an
   // extra resize reflow after this point.
--- a/dom/base/nsScriptLoader.cpp
+++ b/dom/base/nsScriptLoader.cpp
@@ -893,17 +893,17 @@ ResolveRequestedModules(nsModuleLoadRequ
       HandleResolveFailure(cx, ms, specifier);
       return NS_ERROR_FAILURE;
     }
 
     bool isAncestor;
     nsresult rv = RequestedModuleIsInAncestorList(aRequest, uri, &isAncestor);
     NS_ENSURE_SUCCESS(rv, rv);
     if (!isAncestor) {
-      aUrls.AppendElement(uri);
+      aUrls.AppendElement(uri.forget());
     }
   }
 
   return NS_OK;
 }
 
 void
 nsScriptLoader::StartFetchingModuleDependencies(nsModuleLoadRequest* aRequest)
--- a/dom/events/EventListenerManager.cpp
+++ b/dom/events/EventListenerManager.cpp
@@ -1554,17 +1554,17 @@ EventListenerManager::GetListenerInfo(ns
     }
     // EventListenerInfo is defined in XPCOM, so we have to go ahead
     // and convert to an XPCOM callback here...
     RefPtr<EventListenerInfo> info =
       new EventListenerInfo(eventType, listener.mListener.ToXPCOMCallback(),
                             listener.mFlags.mCapture,
                             listener.mFlags.mAllowUntrustedEvents,
                             listener.mFlags.mInSystemGroup);
-    aList->AppendObject(info);
+    aList->AppendElement(info.forget());
   }
   return NS_OK;
 }
 
 bool
 EventListenerManager::HasUnloadListeners()
 {
   uint32_t count = mListeners.Length();
--- a/dom/ipc/ContentChild.cpp
+++ b/dom/ipc/ContentChild.cpp
@@ -2520,23 +2520,21 @@ ContentChild::RecvAddPermission(const IP
 #if MOZ_PERMISSIONS
   nsCOMPtr<nsIPermissionManager> permissionManagerIface =
     services::GetPermissionManager();
   nsPermissionManager* permissionManager =
     static_cast<nsPermissionManager*>(permissionManagerIface.get());
   MOZ_ASSERT(permissionManager,
          "We have no permissionManager in the Content process !");
 
+  // note we do not need to force mUserContextId to the default here because
+  // the permission manager does that internally.
   nsAutoCString originNoSuffix;
   PrincipalOriginAttributes attrs;
   attrs.PopulateFromOrigin(permission.origin, originNoSuffix);
-  // we're doing this because we currently don't support isolating permissions
-  // by userContextId.
-  MOZ_ASSERT(attrs.mUserContextId == nsIScriptSecurityManager::DEFAULT_USER_CONTEXT_ID,
-      "permission user context should be set to default!");
 
   nsCOMPtr<nsIURI> uri;
   nsresult rv = NS_NewURI(getter_AddRefs(uri), originNoSuffix);
   NS_ENSURE_SUCCESS(rv, true);
 
   nsCOMPtr<nsIPrincipal> principal = mozilla::BasePrincipal::CreateCodebasePrincipal(uri, attrs);
 
   // child processes don't care about modification time.
--- a/dom/ipc/TabChild.cpp
+++ b/dom/ipc/TabChild.cpp
@@ -1916,63 +1916,65 @@ TabChild::RecvSynthMouseMoveEvent(const 
   return RecvRealMouseButtonEvent(aEvent, aGuid, aInputBlockId);
 }
 
 bool
 TabChild::RecvRealMouseButtonEvent(const WidgetMouseEvent& aEvent,
                                    const ScrollableLayerGuid& aGuid,
                                    const uint64_t& aInputBlockId)
 {
-  if (aInputBlockId) {
-    MOZ_ASSERT(aEvent.mFlags.mHandledByAPZ);
+  // Mouse events like eMouseEnterIntoWidget, that are created in the parent
+  // process EventStateManager code, have an input block id which they get from
+  // the InputAPZContext in the parent process stack. However, they did not
+  // actually go through the APZ code and so their mHandledByAPZ flag is false.
+  // Since thos events didn't go through APZ, we don't need to send notifications
+  // for them.
+  if (aInputBlockId && aEvent.mFlags.mHandledByAPZ) {
     nsCOMPtr<nsIDocument> document(GetDocument());
     APZCCallbackHelper::SendSetTargetAPZCNotification(
       mPuppetWidget, document, aEvent, aGuid, aInputBlockId);
   }
 
   nsEventStatus unused;
   InputAPZContext context(aGuid, aInputBlockId, unused);
 
   WidgetMouseEvent localEvent(aEvent);
   localEvent.mWidget = mPuppetWidget;
   APZCCallbackHelper::ApplyCallbackTransform(localEvent, aGuid,
       mPuppetWidget->GetDefaultScale());
   APZCCallbackHelper::DispatchWidgetEvent(localEvent);
 
-  if (aInputBlockId) {
-    MOZ_ASSERT(aEvent.mFlags.mHandledByAPZ);
+  if (aInputBlockId && aEvent.mFlags.mHandledByAPZ) {
     mAPZEventState->ProcessMouseEvent(aEvent, aGuid, aInputBlockId);
   }
   return true;
 }
 
 bool
 TabChild::RecvMouseWheelEvent(const WidgetWheelEvent& aEvent,
                               const ScrollableLayerGuid& aGuid,
                               const uint64_t& aInputBlockId)
 {
-  if (aInputBlockId) {
-    MOZ_ASSERT(aEvent.mFlags.mHandledByAPZ);
+  if (aInputBlockId && aEvent.mFlags.mHandledByAPZ) {
     nsCOMPtr<nsIDocument> document(GetDocument());
     APZCCallbackHelper::SendSetTargetAPZCNotification(
       mPuppetWidget, document, aEvent, aGuid, aInputBlockId);
   }
 
   WidgetWheelEvent localEvent(aEvent);
   localEvent.mWidget = mPuppetWidget;
   APZCCallbackHelper::ApplyCallbackTransform(localEvent, aGuid,
       mPuppetWidget->GetDefaultScale());
   APZCCallbackHelper::DispatchWidgetEvent(localEvent);
 
   if (localEvent.mCanTriggerSwipe) {
     SendRespondStartSwipeEvent(aInputBlockId, localEvent.TriggersSwipe());
   }
 
-  if (aInputBlockId) {
-    MOZ_ASSERT(aEvent.mFlags.mHandledByAPZ);
+  if (aInputBlockId && aEvent.mFlags.mHandledByAPZ) {
     mAPZEventState->ProcessWheelEvent(localEvent, aGuid, aInputBlockId);
   }
   return true;
 }
 
 bool
 TabChild::RecvMouseScrollTestEvent(const uint64_t& aLayersId,
                                    const FrameMetrics::ViewID& aScrollId, const nsString& aEvent)
--- a/dom/media/tests/mochitest/head.js
+++ b/dom/media/tests/mochitest/head.js
@@ -307,17 +307,18 @@ function setupEnvironment() {
   };
 
   const isAndroid = !!navigator.userAgent.includes("Android");
 
   if (isAndroid) {
     defaultMochitestPrefs.set.push(
       ["media.navigator.video.default_width", 320],
       ["media.navigator.video.default_height", 240],
-      ["media.navigator.video.max_fr", 10]
+      ["media.navigator.video.max_fr", 10],
+      ["media.autoplay.enabled", true]
     );
   }
 
   // Running as a Mochitest.
   SimpleTest.requestFlakyTimeout("WebRTC inherently depends on timeouts");
   window.finish = () => SimpleTest.finish();
   SpecialPowers.pushPrefEnv(defaultMochitestPrefs, setTestOptions);
 
--- a/dom/plugins/base/nsPluginHost.cpp
+++ b/dom/plugins/base/nsPluginHost.cpp
@@ -2011,17 +2011,17 @@ GetExtensionDirectories(nsCOMArray<nsIFi
   while (NS_SUCCEEDED(list->HasMoreElements(&more)) && more) {
     nsCOMPtr<nsISupports> next;
     if (NS_FAILED(list->GetNext(getter_AddRefs(next)))) {
       break;
     }
     nsCOMPtr<nsIFile> file = do_QueryInterface(next);
     if (file) {
       file->Normalize();
-      dirs.AppendElement(file);
+      dirs.AppendElement(file.forget());
     }
   }
 }
 
 struct CompareFilesByTime
 {
   bool
   LessThan(const nsCOMPtr<nsIFile>& a, const nsCOMPtr<nsIFile>& b) const
--- a/extensions/cookie/nsPermissionManager.cpp
+++ b/extensions/cookie/nsPermissionManager.cpp
@@ -117,16 +117,19 @@ GetOriginFromPrincipal(nsIPrincipal* aPr
   if (!attrs.PopulateFromSuffix(suffix)) {
     return NS_ERROR_FAILURE;
   }
 
   // mPrivateBrowsingId must be set to false because PermissionManager is not supposed to have
   // any knowledge of private browsing. Allowing it to be true changes the suffix being hashed.
   attrs.mPrivateBrowsingId = 0;
 
+  // set to default to disable user context isolation for permissions
+  attrs.mUserContextId = nsIScriptSecurityManager::DEFAULT_USER_CONTEXT_ID;
+
   attrs.CreateSuffix(suffix);
   aOrigin.Append(suffix);
   return NS_OK;
 }
 
 nsresult
 GetPrincipalFromOrigin(const nsACString& aOrigin, nsIPrincipal** aPrincipal)
 {
--- a/gfx/gl/SharedSurfaceANGLE.h
+++ b/gfx/gl/SharedSurfaceANGLE.h
@@ -35,19 +35,16 @@ public:
 
 protected:
     GLLibraryEGL* const mEGL;
     const EGLSurface mPBuffer;
 public:
     const HANDLE mShareHandle;
 protected:
     RefPtr<IDXGIKeyedMutex> mKeyedMutex;
-    RefPtr<IDXGIKeyedMutex> mConsumerKeyedMutex;
-    RefPtr<ID3D11Texture2D> mConsumerTexture;
-
     const GLuint mFence;
 
     SharedSurface_ANGLEShareHandle(GLContext* gl,
                                    GLLibraryEGL* egl,
                                    const gfx::IntSize& size,
                                    bool hasAlpha,
                                    EGLSurface pbuffer,
                                    HANDLE shareHandle,
@@ -62,20 +59,16 @@ public:
     virtual void LockProdImpl() override;
     virtual void UnlockProdImpl() override;
 
     virtual void ProducerAcquireImpl() override;
     virtual void ProducerReleaseImpl() override;
     virtual void ProducerReadAcquireImpl() override;
     virtual void ProducerReadReleaseImpl() override;
 
-    const RefPtr<ID3D11Texture2D>& GetConsumerTexture() const {
-        return mConsumerTexture;
-    }
-
     virtual bool ToSurfaceDescriptor(layers::SurfaceDescriptor* const out_descriptor) override;
 
     virtual bool ReadbackBySharedHandle(gfx::DataSourceSurface* out_surface) override;
 };
 
 
 
 class SurfaceFactory_ANGLEShareHandle
--- a/gfx/gl/SharedSurfaceD3D11Interop.h
+++ b/gfx/gl/SharedSurfaceD3D11Interop.h
@@ -27,19 +27,16 @@ public:
     const RefPtr<DXGLDevice> mDXGL;
     const HANDLE mObjectWGL;
     const HANDLE mSharedHandle;
     const RefPtr<ID3D11Texture2D> mTextureD3D;
     const bool mNeedsFinish;
 
 protected:
     RefPtr<IDXGIKeyedMutex> mKeyedMutex;
-    RefPtr<IDXGIKeyedMutex> mConsumerKeyedMutex;
-    RefPtr<ID3D11Texture2D> mConsumerTexture;
-
     bool mLockedForGL;
 
 public:
     static UniquePtr<SharedSurface_D3D11Interop> Create(const RefPtr<DXGLDevice>& dxgl,
                                                         GLContext* gl,
                                                         const gfx::IntSize& size,
                                                         bool hasAlpha);
 
--- a/gfx/layers/LayersLogging.h
+++ b/gfx/layers/LayersLogging.h
@@ -4,16 +4,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef GFX_LAYERSLOGGING_H
 #define GFX_LAYERSLOGGING_H
 
 #include "FrameMetrics.h"               // for FrameMetrics, etc
 #include "mozilla/gfx/Matrix.h"         // for Matrix4x4
 #include "mozilla/gfx/Point.h"          // for IntSize, etc
+#include "mozilla/gfx/TiledRegion.h"    // for TiledRegion
 #include "mozilla/gfx/Types.h"          // for SamplingFilter, SurfaceFormat
 #include "mozilla/layers/CompositorTypes.h"  // for TextureFlags
 #include "nsAString.h"
 #include "nsPrintfCString.h"            // for nsPrintfCString
 #include "nsRegion.h"                   // for nsRegion, nsIntRegion
 #include "nscore.h"                     // for nsACString, etc
 
 namespace mozilla {
@@ -105,16 +106,28 @@ AppendToString(std::stringstream& aStrea
     AppendToString(aStream, iter.Get());
     aStream << "; ";
   }
   aStream << ">";
 
   aStream << sfx;
 }
 
+template <typename T>
+void
+AppendToString(std::stringstream& aStream, const mozilla::gfx::TiledRegion<T>& r,
+               const char* pfx="", const char* sfx="")
+{
+  aStream << pfx;
+  AppendToString(aStream, r.GetRegion());
+  aStream << " (bounds=";
+  AppendToString(aStream, r.GetBounds());
+  aStream << ", covers=" << r.CoversBounds() << ")" << sfx;
+}
+
 void
 AppendToString(std::stringstream& aStream, const EventRegions& e,
                const char* pfx="", const char* sfx="");
 
 void
 AppendToString(std::stringstream& aStream, const ScrollMetadata& m,
                const char* pfx="", const char* sfx="");
 
--- a/gfx/layers/client/ClientLayerManager.cpp
+++ b/gfx/layers/client/ClientLayerManager.cpp
@@ -521,35 +521,40 @@ ClientLayerManager::MakeSnapshotIfRequir
           RotateRect(bounds, outerBounds.ToUnknownRect(), mTargetRotation);
       }
 
       SurfaceDescriptor inSnapshot;
       if (!bounds.IsEmpty() &&
           mForwarder->AllocSurfaceDescriptor(bounds.Size(),
                                              gfxContentType::COLOR_ALPHA,
                                              &inSnapshot)) {
+
+        // Make a copy of |inSnapshot| because the call to send it over IPC
+        // will call forget() on the Shmem inside, and zero it out.
+        SurfaceDescriptor outSnapshot = inSnapshot;
+
         if (remoteRenderer->SendMakeSnapshot(inSnapshot, bounds)) {
-          RefPtr<DataSourceSurface> surf = GetSurfaceForDescriptor(inSnapshot);
+          RefPtr<DataSourceSurface> surf = GetSurfaceForDescriptor(outSnapshot);
           DrawTarget* dt = mShadowTarget->GetDrawTarget();
 
           Rect dstRect(bounds.x, bounds.y, bounds.width, bounds.height);
           Rect srcRect(0, 0, bounds.width, bounds.height);
 
           gfx::Matrix rotate =
             ComputeTransformForUnRotation(outerBounds.ToUnknownRect(),
                                           mTargetRotation);
 
           gfx::Matrix oldMatrix = dt->GetTransform();
           dt->SetTransform(rotate * oldMatrix);
           dt->DrawSurface(surf, dstRect, srcRect,
                           DrawSurfaceOptions(),
                           DrawOptions(1.0f, CompositionOp::OP_OVER));
           dt->SetTransform(oldMatrix);
         }
-        mForwarder->DestroySurfaceDescriptor(&inSnapshot);
+        mForwarder->DestroySurfaceDescriptor(&outSnapshot);
       }
     }
   }
   mShadowTarget = nullptr;
 }
 
 void
 ClientLayerManager::FlushRendering()
--- a/gfx/layers/ipc/ImageBridgeChild.cpp
+++ b/gfx/layers/ipc/ImageBridgeChild.cpp
@@ -338,20 +338,21 @@ ImageBridgeChild::NotifyNotUsedToNonRecy
     return;
   }
 
   MOZ_ASSERT(aTextureId == client->GetSerial());
   client->ClearWaitFenceHandleOnImageBridge(mWaitingFenceHandleMutex);
   mTexturesWaitingFenceHandle.Remove(aTextureId);
 
   // Release TextureClient on allocator's message loop.
-  TextureClientReleaseTask* task = new TextureClientReleaseTask(client);
+  RefPtr<TextureClientReleaseTask> task =
+    MakeAndAddRef<TextureClientReleaseTask>(client);
   RefPtr<ClientIPCAllocator> allocator = client->GetAllocator();
   client = nullptr;
-  allocator->AsClientAllocator()->GetMessageLoop()->PostTask(FROM_HERE, task);
+  allocator->AsClientAllocator()->GetMessageLoop()->PostTask(task.forget());
 #else
   NS_RUNTIMEABORT("not reached");
 #endif
 }
 
 void
 ImageBridgeChild::CancelWaitFenceHandle(TextureClient* aClient)
 {
--- a/gfx/src/TiledRegion.cpp
+++ b/gfx/src/TiledRegion.cpp
@@ -9,16 +9,17 @@
 #include <algorithm>
 
 #include "mozilla/fallible.h"
 
 namespace mozilla {
 namespace gfx {
 
 static const int32_t kTileSize = 256;
+static const size_t kMaxTiles = 100;
 
 /**
  * TiledRegionImpl stores an array of non-empty rectangles (pixman_box32_ts) to
  * represent the region. Each rectangle is contained in a single tile;
  * rectangles never cross tile boundaries. The rectangles are sorted by their
  * tile's origin in top-to-bottom, left-to-right order.
  * (Note that this can mean that a rectangle r1 can come before another
  * rectangle r2 even if r2.y1 < r1.y1, as long as the two rects are in the same
@@ -277,17 +278,18 @@ TiledRegionImpl::AddRect(const pixman_bo
 {
   // We are adding a rectangle that can span multiple tiles.
   // For each empty tile that aRect intersects, we need to add the intersection
   // of aRect with that tile to mRects, respecting the order of mRects.
   // For each tile that already has a rectangle, we need to enlarge that
   // existing rectangle to include the intersection of aRect with the tile.
   return ProcessIntersectedTiles(aRect, mRects,
     [&aRect](nsTArray<pixman_box32_t>& rects, size_t& rectIndex, TileRange emptyTiles) {
-      if (!rects.InsertElementsAt(rectIndex, emptyTiles.Length(), fallible)) {
+      if (rects.Length() + emptyTiles.Length() >= kMaxTiles ||
+          !rects.InsertElementsAt(rectIndex, emptyTiles.Length(), fallible)) {
         return IterationAction::STOP;
       }
       for (TileIterator tileIt = emptyTiles.Begin();
            tileIt != emptyTiles.End();
            ++tileIt, ++rectIndex) {
         rects[rectIndex] = tileIt.IntersectionWith(aRect);
       }
       return IterationAction::CONTINUE;
--- a/gfx/src/TiledRegion.h
+++ b/gfx/src/TiledRegion.h
@@ -89,37 +89,29 @@ public:
       return;
     }
 
     mBounds = mBounds.Union(aRect);
 
     if (mCoversBounds) {
       return;
     }
-    if (ExceedsMaximumSize()) {
-      FallBackToBounds();
-      return;
-    }
 
     if (!mImpl.AddRect(RectToBox(aRect))) {
       FallBackToBounds();
     }
   }
 
   void Add(const RegionT& aRegion)
   {
     mBounds = mBounds.Union(aRegion.GetBounds());
 
     if (mCoversBounds) {
       return;
     }
-    if (ExceedsMaximumSize()) {
-      FallBackToBounds();
-      return;
-    }
 
     for (auto iter = aRegion.RectIter(); !iter.Done(); iter.Next()) {
       RectT r = iter.Get();
       MOZ_ASSERT(!r.IsEmpty());
       if (!mImpl.AddRect(RectToBox(r))) {
         FallBackToBounds();
         return;
       }
@@ -131,16 +123,17 @@ public:
   void SetEmpty()
   {
     mBounds.SetEmpty();
     mImpl.Clear();
     mCoversBounds = false;
   }
 
   RectT GetBounds() const { return mBounds; }
+  bool CoversBounds() const { return mCoversBounds; }
 
   bool Intersects(const RectT& aRect) const
   {
     if (!mBounds.Intersects(aRect)) {
       return false;
     }
     if (mCoversBounds) {
       return true;
@@ -157,22 +150,16 @@ public:
     if (mCoversBounds) {
       return true;
     }
     return mImpl.Contains(RectToBox(aRect));
   }
 
 private:
 
-  bool ExceedsMaximumSize() const
-  {
-    // This stops us from allocating insane numbers of tiles.
-    return mBounds.width >= 50 * 256 || mBounds.height >= 50 * 256;
-  }
-
   void FallBackToBounds()
   {
     mCoversBounds = true;
     mImpl.Clear();
   }
 
   static pixman_box32_t RectToBox(const RectT& aRect)
   {
--- a/image/decoders/nsGIFDecoder2.cpp
+++ b/image/decoders/nsGIFDecoder2.cpp
@@ -490,16 +490,18 @@ nsGIFDecoder2::WriteInternal(const char*
           case State::FINISHED_LOCAL_COLOR_TABLE:
             return FinishedLocalColorTable();
           case State::IMAGE_DATA_BLOCK:
             return ReadImageDataBlock(aData);
           case State::IMAGE_DATA_SUB_BLOCK:
             return ReadImageDataSubBlock(aData);
           case State::LZW_DATA:
             return ReadLZWData(aData, aLength);
+          case State::SKIP_LZW_DATA:
+            return Transition::ContinueUnbuffered(State::SKIP_LZW_DATA);
           case State::FINISHED_LZW_DATA:
             return Transition::To(State::IMAGE_DATA_SUB_BLOCK, SUB_BLOCK_HEADER_LEN);
           case State::SKIP_SUB_BLOCKS:
             return SkipSubBlocks(aData);
           case State::SKIP_DATA_THEN_SKIP_SUB_BLOCKS:
             return Transition::ContinueUnbuffered(State::SKIP_DATA_THEN_SKIP_SUB_BLOCKS);
           case State::FINISHED_SKIPPING_DATA:
             return Transition::To(State::SKIP_SUB_BLOCKS, SUB_BLOCK_HEADER_LEN);
@@ -982,26 +984,30 @@ nsGIFDecoder2::ReadImageDataSubBlock(con
   const uint8_t subBlockLength = aData[0];
   if (subBlockLength == 0) {
     // We hit the block terminator.
     EndImageFrame();
     return Transition::To(State::BLOCK_HEADER, BLOCK_HEADER_LEN);
   }
 
   if (mGIFStruct.pixels_remaining == 0) {
-    // We've already written to the entire image. |subBlockLength| should've
-    // been zero.
+    // We've already written to the entire image; we should've hit the block
+    // terminator at this point. This image is corrupt, but we'll tolerate it.
+
     if (subBlockLength == GIF_TRAILER) {
       // This GIF is missing the block terminator for the final block; we'll put
       // up with it.
       FinishInternal();
       return Transition::TerminateSuccess();
     }
 
-    return Transition::To(State::IMAGE_DATA_SUB_BLOCK, SUB_BLOCK_HEADER_LEN);
+    // We're not at the end of the image, so just skip the extra data.
+    return Transition::ToUnbuffered(State::FINISHED_LZW_DATA,
+                                    State::SKIP_LZW_DATA,
+                                    subBlockLength);
   }
 
   // Handle the standard case: there's data in the sub-block and pixels left to
   // fill in the image. We read the sub-block unbuffered so we can get pixels on
   // the screen as soon as possible.
   return Transition::ToUnbuffered(State::FINISHED_LZW_DATA,
                                   State::LZW_DATA,
                                   subBlockLength);
--- a/image/decoders/nsGIFDecoder2.h
+++ b/image/decoders/nsGIFDecoder2.h
@@ -85,16 +85,17 @@ private:
     NETSCAPE_EXTENSION_SUB_BLOCK,
     NETSCAPE_EXTENSION_DATA,
     IMAGE_DESCRIPTOR,
     LOCAL_COLOR_TABLE,
     FINISHED_LOCAL_COLOR_TABLE,
     IMAGE_DATA_BLOCK,
     IMAGE_DATA_SUB_BLOCK,
     LZW_DATA,
+    SKIP_LZW_DATA,
     FINISHED_LZW_DATA,
     SKIP_SUB_BLOCKS,
     SKIP_DATA_THEN_SKIP_SUB_BLOCKS,
     FINISHED_SKIPPING_DATA
   };
 
   LexerTransition<State> ReadGIFHeader(const char* aData);
   LexerTransition<State> ReadScreenDescriptor(const char* aData);
--- a/image/imgFrame.cpp
+++ b/image/imgFrame.cpp
@@ -10,18 +10,16 @@
 
 #include "prenv.h"
 
 #include "gfx2DGlue.h"
 #include "gfxPlatform.h"
 #include "gfxUtils.h"
 #include "gfxAlphaRecovery.h"
 
-static bool gDisableOptimize = false;
-
 #include "GeckoProfiler.h"
 #include "mozilla/Likely.h"
 #include "MainThreadUtils.h"
 #include "mozilla/MemoryReporting.h"
 #include "nsMargin.h"
 #include "nsThreadUtils.h"
 #include "mozilla/CheckedInt.h"
 #include "mozilla/gfx/Tools.h"
@@ -144,23 +142,16 @@ imgFrame::imgFrame()
   , mFinished(false)
   , mOptimizable(false)
   , mPalettedImageData(nullptr)
   , mPaletteDepth(0)
   , mNonPremult(false)
   , mSinglePixel(false)
   , mCompositingFailed(false)
 {
-  static bool hasCheckedOptimize = false;
-  if (!hasCheckedOptimize) {
-    if (PR_GetEnv("MOZ_DISABLE_IMAGE_OPTIMIZE")) {
-      gDisableOptimize = true;
-    }
-    hasCheckedOptimize = true;
-  }
 }
 
 imgFrame::~imgFrame()
 {
 #ifdef DEBUG
   MonitorAutoLock lock(mMonitor);
   MOZ_ASSERT(mAborted || AreAllPixelsWritten());
   MOZ_ASSERT(mAborted || mFinished);
@@ -334,16 +325,26 @@ imgFrame::InitWithDrawable(gfxDrawable* 
 nsresult
 imgFrame::Optimize()
 {
   MOZ_ASSERT(NS_IsMainThread());
   mMonitor.AssertCurrentThreadOwns();
   MOZ_ASSERT(mLockCount == 1,
              "Should only optimize when holding the lock exclusively");
 
+  // Check whether image optimization is disabled -- not thread safe!
+  static bool gDisableOptimize = false;
+  static bool hasCheckedOptimize = false;
+  if (!hasCheckedOptimize) {
+    if (PR_GetEnv("MOZ_DISABLE_IMAGE_OPTIMIZE")) {
+      gDisableOptimize = true;
+    }
+    hasCheckedOptimize = true;
+  }
+
   // Don't optimize during shutdown because gfxPlatform may not be available.
   if (ShutdownTracker::ShutdownHasStarted()) {
     return NS_OK;
   }
 
   if (!mOptimizable || gDisableOptimize) {
     return NS_OK;
   }
--- a/image/test/gtest/Common.cpp
+++ b/image/test/gtest/Common.cpp
@@ -528,16 +528,24 @@ ImageTestCase NoFrameDelayGIFTestCase()
 {
   // This is an invalid (or at least, questionably valid) GIF that's animated
   // even though it specifies a frame delay of zero. It's animated, but it's not
   // marked TEST_CASE_IS_ANIMATED because the metadata decoder can't detect that
   // it's animated.
   return ImageTestCase("no-frame-delay.gif", "image/gif", IntSize(100, 100));
 }
 
+ImageTestCase ExtraImageSubBlocksAnimatedGIFTestCase()
+{
+  // This is a corrupt GIF that has extra image sub blocks between the first and
+  // second frame.
+  return ImageTestCase("animated-with-extra-image-sub-blocks.gif", "image/gif",
+                       IntSize(100, 100));
+}
+
 ImageTestCase DownscaledPNGTestCase()
 {
   // This testcase (and all the other "downscaled") testcases) consists of 25
   // lines of green, followed by 25 lines of red, followed by 25 lines of green,
   // followed by 25 more lines of red. It's intended that tests downscale it
   // from 100x100 to 20x20, so we specify a 20x20 output size.
   return ImageTestCase("downscaled.png", "image/png", IntSize(100, 100),
                        IntSize(20, 20));
--- a/image/test/gtest/Common.h
+++ b/image/test/gtest/Common.h
@@ -327,16 +327,17 @@ ImageTestCase GreenFirstFrameAnimatedGIF
 ImageTestCase GreenFirstFrameAnimatedPNGTestCase();
 
 ImageTestCase CorruptTestCase();
 
 ImageTestCase TransparentPNGTestCase();
 ImageTestCase TransparentGIFTestCase();
 ImageTestCase FirstFramePaddingGIFTestCase();
 ImageTestCase NoFrameDelayGIFTestCase();
+ImageTestCase ExtraImageSubBlocksAnimatedGIFTestCase();
 
 ImageTestCase TransparentBMPWhenBMPAlphaEnabledTestCase();
 ImageTestCase RLE4BMPTestCase();
 ImageTestCase RLE8BMPTestCase();
 
 ImageTestCase DownscaledPNGTestCase();
 ImageTestCase DownscaledGIFTestCase();
 ImageTestCase DownscaledJPGTestCase();
--- a/image/test/gtest/TestDecoders.cpp
+++ b/image/test/gtest/TestDecoders.cpp
@@ -344,8 +344,77 @@ TEST(ImageDecoders, CorruptSingleChunk)
 {
   CheckDecoderSingleChunk(CorruptTestCase());
 }
 
 TEST(ImageDecoders, CorruptMultiChunk)
 {
   CheckDecoderMultiChunk(CorruptTestCase());
 }
+
+TEST(ImageDecoders, AnimatedGIFWithExtraImageSubBlocks)
+{
+  ImageTestCase testCase = ExtraImageSubBlocksAnimatedGIFTestCase();
+
+  // Verify that we can decode this test case and get two frames, even though
+  // there are extra image sub blocks between the first and second frame. The
+  // extra data shouldn't confuse the decoder or cause the decode to fail.
+
+  // Create an image.
+  RefPtr<Image> image =
+    ImageFactory::CreateAnonymousImage(nsDependentCString(testCase.mMimeType));
+  ASSERT_TRUE(!image->HasError());
+
+  nsCOMPtr<nsIInputStream> inputStream = LoadFile(testCase.mPath);
+  ASSERT_TRUE(inputStream);
+
+  // Figure out how much data we have.
+  uint64_t length;
+  nsresult rv = inputStream->Available(&length);
+  ASSERT_TRUE(NS_SUCCEEDED(rv));
+
+  // Write the data into the image.
+  rv = image->OnImageDataAvailable(nullptr, nullptr, inputStream, 0,
+                                   static_cast<uint32_t>(length));
+  ASSERT_TRUE(NS_SUCCEEDED(rv));
+
+  // Let the image know we've sent all the data.
+  rv = image->OnImageDataComplete(nullptr, nullptr, NS_OK, true);
+  ASSERT_TRUE(NS_SUCCEEDED(rv));
+
+  RefPtr<ProgressTracker> tracker = image->GetProgressTracker();
+  tracker->SyncNotifyProgress(FLAG_LOAD_COMPLETE);
+
+  // Use GetFrame() to force a sync decode of the image.
+  RefPtr<SourceSurface> surface =
+    image->GetFrame(imgIContainer::FRAME_CURRENT,
+                    imgIContainer::FLAG_SYNC_DECODE);
+
+  // Ensure that the image's metadata meets our expectations.
+  IntSize imageSize(0, 0);
+  rv = image->GetWidth(&imageSize.width);
+  EXPECT_TRUE(NS_SUCCEEDED(rv));
+  rv = image->GetHeight(&imageSize.height);
+  EXPECT_TRUE(NS_SUCCEEDED(rv));
+
+  EXPECT_EQ(testCase.mSize.width, imageSize.width);
+  EXPECT_EQ(testCase.mSize.height, imageSize.height);
+
+  Progress imageProgress = tracker->GetProgress();
+
+  EXPECT_TRUE(bool(imageProgress & FLAG_HAS_TRANSPARENCY) == false);
+  EXPECT_TRUE(bool(imageProgress & FLAG_IS_ANIMATED) == true);
+
+  // Ensure that we decoded both frames of the image.
+  LookupResult firstFrameLookupResult =
+    SurfaceCache::Lookup(ImageKey(image.get()),
+                         RasterSurfaceKey(imageSize,
+                                          DefaultSurfaceFlags(),
+                                          /* aFrameNum = */ 0));
+  EXPECT_EQ(MatchType::EXACT, firstFrameLookupResult.Type());
+
+  LookupResult secondFrameLookupResult =
+    SurfaceCache::Lookup(ImageKey(image.get()),
+                         RasterSurfaceKey(imageSize,
+                                          DefaultSurfaceFlags(),
+                                          /* aFrameNum = */ 1));
+  EXPECT_EQ(MatchType::EXACT, secondFrameLookupResult.Type());
+}
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..a145c814a684c454e4003ab41699798db0ed8366
GIT binary patch
literal 434
zc${<hbhEHbOkqf2_`txx@E?d76o0ZXaDnLm+<vYh!Oo5Wu10zW%#1)G9gsXoF#}U^
zOaIE#Z}}I`*>bCU^SwR4`P&|OOncV3?A57l@3@bD^11%4_xZ1L-~aLRaJ3&<^s&Q7
zYx<dGpE-NImS0)*wd-uw_B-pobMti{f3oRkkKgL+Z?^sB?LYne%dWqD=U;#Sv+qB@
qgocGjL`Fr&j1@ah+<5VWBQt_wAnb$(2i)%s_4V}(0~7)b)?5Ivyyp%8
--- a/image/test/gtest/moz.build
+++ b/image/test/gtest/moz.build
@@ -25,16 +25,17 @@ if CONFIG['MOZ_ENABLE_SKIA']:
     ]
 
 SOURCES += [
     # Can't be unified because it manipulates the preprocessor environment.
     'TestDownscalingFilterNoSkia.cpp',
 ]
 
 TEST_HARNESS_FILES.gtest += [
+    'animated-with-extra-image-sub-blocks.gif',
     'corrupt.jpg',
     'downscaled.bmp',
     'downscaled.gif',
     'downscaled.ico',
     'downscaled.icon',
     'downscaled.jpg',
     'downscaled.png',
     'first-frame-green.gif',
--- a/js/public/RootingAPI.h
+++ b/js/public/RootingAPI.h
@@ -581,17 +581,17 @@ struct JS_PUBLIC_API(MovableCellHasher<J
 };
 
 } /* namespace js */
 
 namespace js {
 
 // After switching to MSVC2015, this can be eliminated and replaced with
 // alignas(n) everywhere.
-#ifdef XP_WIN
+#if defined(_MSC_VER) && (_MSC_VER < 1900)
 # define JS_ALIGNAS(n) __declspec(align(n))
 #else
 # define JS_ALIGNAS(n) alignas(n)
 #endif
 
 // The alignment must be set because the Rooted and PersistentRooted ptr fields
 // may be accessed through reinterpret_cast<Rooted<ConcreteTraceable>*>, and
 // the compiler may choose a different alignment for the ptr field when it
--- a/js/public/UbiNode.h
+++ b/js/public/UbiNode.h
@@ -178,16 +178,19 @@ namespace JS {
 namespace ubi {
 
 using mozilla::Forward;
 using mozilla::Maybe;
 using mozilla::Move;
 using mozilla::RangedPtr;
 using mozilla::Variant;
 
+template <typename T>
+using Vector = mozilla::Vector<T, 0, js::SystemAllocPolicy>;
+
 /*** ubi::StackFrame ******************************************************************************/
 
 // Concrete JS::ubi::StackFrame instances backed by a live SavedFrame object
 // store their strings as JSAtom*, while deserialized stack frames from offline
 // heap snapshots store their strings as const char16_t*. In order to provide
 // zero-cost accessors to these strings in a single interface that works with
 // both cases, we use this variant type.
 class AtomOrTwoByteChars : public Variant<JSAtom*, const char16_t*> {
--- a/js/public/UbiNodeDominatorTree.h
+++ b/js/public/UbiNodeDominatorTree.h
@@ -89,20 +89,20 @@ class JS_PUBLIC_API(DominatorTree)
      * `DominatedSetRange`.
      *
      * @see JS::ubi::DominatorTree::getDominatedSet
      */
     class DominatedNodePtr
     {
         friend class DominatedSetRange;
 
-        const mozilla::Vector<Node>& postOrder;
+        const JS::ubi::Vector<Node>& postOrder;
         const uint32_t* ptr;
 
-        DominatedNodePtr(const mozilla::Vector<Node>& postOrder, const uint32_t* ptr)
+        DominatedNodePtr(const JS::ubi::Vector<Node>& postOrder, const uint32_t* ptr)
           : postOrder(postOrder)
           , ptr(ptr)
         { }
 
       public:
         bool operator!=(const DominatedNodePtr& rhs) const { return ptr != rhs.ptr; }
         void operator++() { ptr++; }
         const Node& operator*() const { return postOrder[*ptr]; }
@@ -113,21 +113,21 @@ class JS_PUBLIC_API(DominatorTree)
      * range-based for loops.
      *
      * @see JS::ubi::DominatorTree::getDominatedSet
      */
     class DominatedSetRange
     {
         friend class DominatedSets;
 
-        const mozilla::Vector<Node>& postOrder;
+        const JS::ubi::Vector<Node>& postOrder;
         const uint32_t* beginPtr;
         const uint32_t* endPtr;
 
-        DominatedSetRange(mozilla::Vector<Node>& postOrder, const uint32_t* begin, const uint32_t* end)
+        DominatedSetRange(JS::ubi::Vector<Node>& postOrder, const uint32_t* begin, const uint32_t* end)
           : postOrder(postOrder)
           , beginPtr(begin)
           , endPtr(end)
         {
             MOZ_ASSERT(begin <= end);
         }
 
       public:
@@ -174,20 +174,20 @@ class JS_PUBLIC_API(DominatorTree)
      * The set of all dominated sets in a dominator tree.
      *
      * Internally stores the sets in a contiguous array, with a side table of
      * indices into that contiguous array to denote the start index of each
      * individual set.
      */
     class DominatedSets
     {
-        mozilla::Vector<uint32_t> dominated;
-        mozilla::Vector<uint32_t> indices;
+        JS::ubi::Vector<uint32_t> dominated;
+        JS::ubi::Vector<uint32_t> indices;
 
-        DominatedSets(mozilla::Vector<uint32_t>&& dominated, mozilla::Vector<uint32_t>&& indices)
+        DominatedSets(JS::ubi::Vector<uint32_t>&& dominated, JS::ubi::Vector<uint32_t>&& indices)
           : dominated(mozilla::Move(dominated))
           , indices(mozilla::Move(indices))
         { }
 
       public:
         // DominatedSets is not copy-able.
         DominatedSets(const DominatedSets& rhs) = delete;
         DominatedSets& operator=(const DominatedSets& rhs) = delete;
@@ -205,17 +205,17 @@ class JS_PUBLIC_API(DominatorTree)
             return *this;
         }
 
         /**
          * Create the DominatedSets given the mapping of a node index to its
          * immediate dominator. Returns `Some` on success, `Nothing` on OOM
          * failure.
          */
-        static mozilla::Maybe<DominatedSets> Create(const mozilla::Vector<uint32_t>& doms) {
+        static mozilla::Maybe<DominatedSets> Create(const JS::ubi::Vector<uint32_t>& doms) {
             auto length = doms.length();
             MOZ_ASSERT(length < UINT32_MAX);
 
             // Create a vector `dominated` holding a flattened set of buckets of
             // immediately dominated children nodes, with a lookup table
             // `indices` mapping from each node to the beginning of its bucket.
             //
             // This has three phases:
@@ -230,18 +230,18 @@ class JS_PUBLIC_API(DominatorTree)
             //    bucket.
             //
             // 3. Iterate over the full set of nodes again, filling in bucket
             //    entries from the end of the bucket's range to its
             //    beginning. This decrements each index as a bucket entry is
             //    filled in. After having filled in all of a bucket's entries,
             //    the index points to the start of the bucket.
 
-            mozilla::Vector<uint32_t> dominated;
-            mozilla::Vector<uint32_t> indices;
+            JS::ubi::Vector<uint32_t> dominated;
+            JS::ubi::Vector<uint32_t> indices;
             if (!dominated.growBy(length) || !indices.growBy(length))
                 return mozilla::Nothing();
 
             // 1
             memset(indices.begin(), 0, length * sizeof(uint32_t));
             for (uint32_t i = 0; i < length; i++)
                 indices[doms[i]]++;
 
@@ -273,63 +273,63 @@ class JS_PUBLIC_API(DominatorTree)
 
             return mozilla::Some(DominatedSets(mozilla::Move(dominated), mozilla::Move(indices)));
         }
 
         /**
          * Get the set of nodes immediately dominated by the node at
          * `postOrder[nodeIndex]`.
          */
-        DominatedSetRange dominatedSet(mozilla::Vector<Node>& postOrder, uint32_t nodeIndex) const {
+        DominatedSetRange dominatedSet(JS::ubi::Vector<Node>& postOrder, uint32_t nodeIndex) const {
             MOZ_ASSERT(postOrder.length() == indices.length());
             MOZ_ASSERT(nodeIndex < indices.length());
             auto end = nodeIndex == indices.length() - 1
                 ? dominated.end()
                 : &dominated[indices[nodeIndex + 1]];
             return DominatedSetRange(postOrder, &dominated[indices[nodeIndex]], end);
         }
     };
 
   private:
     // Data members.
-    mozilla::Vector<Node> postOrder;
+    JS::ubi::Vector<Node> postOrder;
     NodeToIndexMap nodeToPostOrderIndex;
-    mozilla::Vector<uint32_t> doms;
+    JS::ubi::Vector<uint32_t> doms;
     DominatedSets dominatedSets;
-    mozilla::Maybe<mozilla::Vector<JS::ubi::Node::Size>> retainedSizes;
+    mozilla::Maybe<JS::ubi::Vector<JS::ubi::Node::Size>> retainedSizes;
 
   private:
     // We use `UNDEFINED` as a sentinel value in the `doms` vector to signal
     // that we haven't found any dominators for the node at the corresponding
     // index in `postOrder` yet.
     static const uint32_t UNDEFINED = UINT32_MAX;
 
-    DominatorTree(mozilla::Vector<Node>&& postOrder, NodeToIndexMap&& nodeToPostOrderIndex,
-                  mozilla::Vector<uint32_t>&& doms, DominatedSets&& dominatedSets)
+    DominatorTree(JS::ubi::Vector<Node>&& postOrder, NodeToIndexMap&& nodeToPostOrderIndex,
+                  JS::ubi::Vector<uint32_t>&& doms, DominatedSets&& dominatedSets)
         : postOrder(mozilla::Move(postOrder))
         , nodeToPostOrderIndex(mozilla::Move(nodeToPostOrderIndex))
         , doms(mozilla::Move(doms))
         , dominatedSets(mozilla::Move(dominatedSets))
         , retainedSizes(mozilla::Nothing())
     { }
 
-    static uint32_t intersect(mozilla::Vector<uint32_t>& doms, uint32_t finger1, uint32_t finger2) {
+    static uint32_t intersect(JS::ubi::Vector<uint32_t>& doms, uint32_t finger1, uint32_t finger2) {
         while (finger1 != finger2) {
             if (finger1 < finger2)
                 finger1 = doms[finger1];
             else if (finger2 < finger1)
                 finger2 = doms[finger2];
         }
         return finger1;
     }
 
     // Do the post order traversal of the heap graph and populate our
     // predecessor sets.
     static MOZ_MUST_USE bool doTraversal(JSRuntime* rt, AutoCheckCannotGC& noGC, const Node& root,
-                                         mozilla::Vector<Node>& postOrder,
+                                         JS::ubi::Vector<Node>& postOrder,
                                          PredecessorSets& predecessorSets) {
         uint32_t nodeCount = 0;
         auto onNode = [&](const Node& node) {
             nodeCount++;
             if (MOZ_UNLIKELY(nodeCount == UINT32_MAX))
                 return false;
             return postOrder.append(node);
         };
@@ -352,36 +352,36 @@ class JS_PUBLIC_API(DominatorTree)
         PostOrder traversal(rt, noGC);
         return traversal.init() &&
                traversal.addStart(root) &&
                traversal.traverse(onNode, onEdge);
     }
 
     // Populates the given `map` with an entry for each node to its index in
     // `postOrder`.
-    static MOZ_MUST_USE bool mapNodesToTheirIndices(mozilla::Vector<Node>& postOrder,
+    static MOZ_MUST_USE bool mapNodesToTheirIndices(JS::ubi::Vector<Node>& postOrder,
                                                     NodeToIndexMap& map) {
         MOZ_ASSERT(!map.initialized());
         MOZ_ASSERT(postOrder.length() < UINT32_MAX);
         uint32_t length = postOrder.length();
         if (!map.init(length))
             return false;
         for (uint32_t i = 0; i < length; i++)
             map.putNewInfallible(postOrder[i], i);
         return true;
     }
 
     // Convert the Node -> NodeSet predecessorSets to a index -> Vector<index>
     // form.
     static MOZ_MUST_USE bool convertPredecessorSetsToVectors(
         const Node& root,
-        mozilla::Vector<Node>& postOrder,
+        JS::ubi::Vector<Node>& postOrder,
         PredecessorSets& predecessorSets,
         NodeToIndexMap& nodeToPostOrderIndex,
-        mozilla::Vector<mozilla::Vector<uint32_t>>& predecessorVectors)
+        JS::ubi::Vector<JS::ubi::Vector<uint32_t>>& predecessorVectors)
     {
         MOZ_ASSERT(postOrder.length() < UINT32_MAX);
         uint32_t length = postOrder.length();
 
         MOZ_ASSERT(predecessorVectors.length() == 0);
         if (!predecessorVectors.growBy(length))
             return false;
 
@@ -405,17 +405,17 @@ class JS_PUBLIC_API(DominatorTree)
             }
         }
         predecessorSets.finish();
         return true;
     }
 
     // Initialize `doms` such that the immediate dominator of the `root` is the
     // `root` itself and all others are `UNDEFINED`.
-    static MOZ_MUST_USE bool initializeDominators(mozilla::Vector<uint32_t>& doms,
+    static MOZ_MUST_USE bool initializeDominators(JS::ubi::Vector<uint32_t>& doms,
                                                   uint32_t length) {
         MOZ_ASSERT(doms.length() == 0);
         if (!doms.growByUninitialized(length))
             return false;
         doms[length - 1] = length - 1;
         for (uint32_t i = 0; i < length - 1; i++)
             doms[i] = UNDEFINED;
         return true;
@@ -509,17 +509,17 @@ class JS_PUBLIC_API(DominatorTree)
      * that embedders with knowledge of the graph's implementation will do the
      * Right Thing.
      *
      * Returns `mozilla::Nothing()` on OOM failure. It is the caller's
      * responsibility to handle and report the OOM.
      */
     static mozilla::Maybe<DominatorTree>
     Create(JSRuntime* rt, AutoCheckCannotGC& noGC, const Node& root) {
-        mozilla::Vector<Node> postOrder;
+        JS::ubi::Vector<Node> postOrder;
         PredecessorSets predecessorSets;
         if (!predecessorSets.init() || !doTraversal(rt, noGC, root, postOrder, predecessorSets))
             return mozilla::Nothing();
 
         MOZ_ASSERT(postOrder.length() < UINT32_MAX);
         uint32_t length = postOrder.length();
         MOZ_ASSERT(postOrder[length - 1] == root);
 
@@ -528,22 +528,22 @@ class JS_PUBLIC_API(DominatorTree)
         // possible. This greatly improves the performance of this
         // implementation, but we have to pay a little bit of upfront cost to
         // convert our data structures to play along first.
 
         NodeToIndexMap nodeToPostOrderIndex;
         if (!mapNodesToTheirIndices(postOrder, nodeToPostOrderIndex))
             return mozilla::Nothing();
 
-        mozilla::Vector<mozilla::Vector<uint32_t>> predecessorVectors;
+        JS::ubi::Vector<JS::ubi::Vector<uint32_t>> predecessorVectors;
         if (!convertPredecessorSetsToVectors(root, postOrder, predecessorSets, nodeToPostOrderIndex,
                                              predecessorVectors))
             return mozilla::Nothing();
 
-        mozilla::Vector<uint32_t> doms;
+        JS::ubi::Vector<uint32_t> doms;
         if (!initializeDominators(doms, length))
             return mozilla::Nothing();
 
         bool changed = true;
         while (changed) {
             changed = false;
 
             // Iterate over the non-root nodes in reverse post order.
--- a/js/public/UbiNodeShortestPaths.h
+++ b/js/public/UbiNodeShortestPaths.h
@@ -64,29 +64,29 @@ struct JS_PUBLIC_API(BackEdge)
     EdgeName& name() { return name_; }
 
     const JS::ubi::Node& predecessor() const { return predecessor_; }
 };
 
 /**
  * A path is a series of back edges from which we discovered a target node.
  */
-using Path = mozilla::Vector<BackEdge*>;
+using Path = JS::ubi::Vector<BackEdge*>;
 
 /**
  * The `JS::ubi::ShortestPaths` type represents a collection of up to N shortest
  * retaining paths for each of a target set of nodes, starting from the same
  * root node.
  */
 struct JS_PUBLIC_API(ShortestPaths)
 {
   private:
     // Types, type aliases, and data members.
 
-    using BackEdgeVector = mozilla::Vector<BackEdge::Ptr>;
+    using BackEdgeVector = JS::ubi::Vector<BackEdge::Ptr>;
     using NodeToBackEdgeVectorMap = js::HashMap<Node, BackEdgeVector, js::DefaultHasher<Node>,
                                                 js::SystemAllocPolicy>;
 
     struct Handler;
     using Traversal = BreadthFirst<Handler>;
 
     /**
      * A `JS::ubi::BreadthFirst` traversal handler that records back edges for
--- a/js/src/builtin/TestingFunctions.cpp
+++ b/js/src/builtin/TestingFunctions.cpp
@@ -2657,21 +2657,26 @@ FindPath(JSContext* cx, unsigned argc, V
         // We can't tolerate the GC moving things around while we're searching
         // the heap. Check that nothing we do causes a GC.
         JS::AutoCheckCannotGC autoCannotGC;
 
         JS::ubi::Node start(args[0]), target(args[1]);
 
         heaptools::FindPathHandler handler(cx, start, target, &nodes, edges);
         heaptools::FindPathHandler::Traversal traversal(cx->runtime(), handler, autoCannotGC);
-        if (!traversal.init() || !traversal.addStart(start))
+        if (!traversal.init() || !traversal.addStart(start)) {
+            ReportOutOfMemory(cx);
             return false;
-
-        if (!traversal.traverse())
+        }
+
+        if (!traversal.traverse()) {
+            if (!cx->isExceptionPending())
+                ReportOutOfMemory(cx);
             return false;
+        }
 
         if (!handler.foundPath) {
             // We didn't find any paths from the start to the target.
             args.rval().setUndefined();
             return true;
         }
     }
 
@@ -3344,16 +3349,21 @@ SetGCCallback(JSContext* cx, unsigned ar
     if (gcCallback::prevMinorGC) {
         JS_SetGCCallback(cx->runtime(), nullptr, nullptr);
         js_delete<gcCallback::MinorGC>(gcCallback::prevMinorGC);
         gcCallback::prevMinorGC = nullptr;
     }
 
     if (strcmp(action.ptr(), "minorGC") == 0) {
         auto info = js_new<gcCallback::MinorGC>();
+        if (!info) {
+            ReportOutOfMemory(cx);
+            return false;
+        }
+
         info->phases = phases;
         info->active = true;
         JS_SetGCCallback(cx->runtime(), gcCallback::minorGC, info);
     } else if (strcmp(action.ptr(), "majorGC") == 0) {
         if (!JS_GetProperty(cx, opts, "depth", &v))
             return false;
         int32_t depth = 1;
         if (!v.isUndefined()) {
@@ -3361,16 +3371,21 @@ SetGCCallback(JSContext* cx, unsigned ar
                 return false;
         }
         if (depth > int32_t(gcstats::Statistics::MAX_NESTING - 4)) {
             JS_ReportError(cx, "Nesting depth too large, would overflow");
             return false;
         }
 
         auto info = js_new<gcCallback::MajorGC>();
+        if (!info) {
+            ReportOutOfMemory(cx);
+            return false;
+        }
+
         info->phases = phases;
         info->depth = depth;
         JS_SetGCCallback(cx->runtime(), gcCallback::majorGC, info);
     } else {
         JS_ReportError(cx, "Unknown GC callback action");
         return false;
     }
 
--- a/js/src/ds/LifoAlloc.h
+++ b/js/src/ds/LifoAlloc.h
@@ -157,16 +157,19 @@ class LifoAlloc
 
     BumpChunk*  first;
     BumpChunk*  latest;
     BumpChunk*  last;
     size_t      markCount;
     size_t      defaultChunkSize_;
     size_t      curSize_;
     size_t      peakSize_;
+#if defined(DEBUG) || defined(JS_OOM_BREAKPOINT)
+    bool        fallibleScope_;
+#endif
 
     void operator=(const LifoAlloc&) = delete;
     LifoAlloc(const LifoAlloc&) = delete;
 
     // Return a BumpChunk that can perform an allocation of at least size |n|
     // and add it to the chain appropriately.
     //
     // Side effect: if retval is non-null, |first| and |latest| are initialized
@@ -226,16 +229,19 @@ class LifoAlloc
         result = latest->tryAlloc(n);
         MOZ_ASSERT(result);
         return result;
     }
 
   public:
     explicit LifoAlloc(size_t defaultChunkSize)
       : peakSize_(0)
+#if defined(DEBUG) || defined(JS_OOM_BREAKPOINT)
+      , fallibleScope_(true)
+#endif
     {
         reset(defaultChunkSize);
     }
 
     // Steal allocated chunks from |other|.
     void steal(LifoAlloc* other) {
         MOZ_ASSERT(!other->markCount);
         MOZ_ASSERT(!latest);
@@ -265,60 +271,84 @@ class LifoAlloc
     static const unsigned HUGE_ALLOCATION = 50 * 1024 * 1024;
     void freeAllIfHugeAndUnused() {
         if (markCount == 0 && curSize_ > HUGE_ALLOCATION)
             freeAll();
     }
 
     MOZ_ALWAYS_INLINE
     void* alloc(size_t n) {
-        JS_OOM_POSSIBLY_FAIL();
+#if defined(DEBUG) || defined(JS_OOM_BREAKPOINT)
+        // Only simulate OOMs when we are not using the LifoAlloc as an
+        // infallible allocator.
+        if (fallibleScope_)
+            JS_OOM_POSSIBLY_FAIL();
+#endif
         return allocImpl(n);
     }
 
     MOZ_ALWAYS_INLINE
-    void* allocInfallibleOrAssert(size_t n) {
-        void* result = allocImpl(n);
-        MOZ_RELEASE_ASSERT(result, "[OOM] Is it really infallible?");
-        return result;
-    }
-
-    MOZ_ALWAYS_INLINE
-    void* allocInfallibleOrCrash(size_t n) {
+    void* allocInfallible(size_t n) {
         AutoEnterOOMUnsafeRegion oomUnsafe;
         if (void* result = allocImpl(n))
             return result;
         oomUnsafe.crash("LifoAlloc::allocInfallible");
         return nullptr;
     }
 
-    MOZ_ALWAYS_INLINE
-    void* allocInfallible(size_t n) {
-        return allocInfallibleOrCrash(n);
-    }
-
     // Ensures that enough space exists to satisfy N bytes worth of
     // allocation requests, not necessarily contiguous. Note that this does
     // not guarantee a successful single allocation of N bytes.
     MOZ_ALWAYS_INLINE
     MOZ_MUST_USE bool ensureUnusedApproximate(size_t n) {
+        AutoFallibleScope fallibleAllocator(this);
         size_t total = 0;
         for (BumpChunk* chunk = latest; chunk; chunk = chunk->next()) {
             total += chunk->unused();
             if (total >= n)
                 return true;
         }
         BumpChunk* latestBefore = latest;
         if (!getOrCreateChunk(n))
             return false;
         if (latestBefore)
             latest = latestBefore;
         return true;
     }
 
+    MOZ_ALWAYS_INLINE
+    void setAsInfallibleByDefault() {
+#if defined(DEBUG) || defined(JS_OOM_BREAKPOINT)
+        fallibleScope_ = false;
+#endif
+    }
+
+    class MOZ_NON_TEMPORARY_CLASS AutoFallibleScope {
+#if defined(DEBUG) || defined(JS_OOM_BREAKPOINT)
+        LifoAlloc* lifoAlloc_;
+        bool prevFallibleScope_;
+        MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
+
+      public:
+        explicit AutoFallibleScope(LifoAlloc* lifoAlloc MOZ_GUARD_OBJECT_NOTIFIER_PARAM) {
+            MOZ_GUARD_OBJECT_NOTIFIER_INIT;
+            lifoAlloc_ = lifoAlloc;
+            prevFallibleScope_ = lifoAlloc->fallibleScope_;
+            lifoAlloc->fallibleScope_ = true;
+        }
+
+        ~AutoFallibleScope() {
+            lifoAlloc_->fallibleScope_ = prevFallibleScope_;
+        }
+#else
+      public:
+        explicit AutoFallibleScope(LifoAlloc*) {}
+#endif
+    };
+
     template <typename T>
     T* newArray(size_t count) {
         static_assert(mozilla::IsPod<T>::value,
                       "T must be POD so that constructors (and destructors, "
                       "when the LifoAlloc is freed) need not be called");
         return newArrayUninitialized<T>(count);
     }
 
@@ -494,24 +524,26 @@ class LifoAlloc
         }
     };
 };
 
 class MOZ_NON_TEMPORARY_CLASS LifoAllocScope
 {
     LifoAlloc*      lifoAlloc;
     LifoAlloc::Mark mark;
+    LifoAlloc::AutoFallibleScope fallibleScope;
     bool            shouldRelease;
     MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
 
   public:
     explicit LifoAllocScope(LifoAlloc* lifoAlloc
                             MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
       : lifoAlloc(lifoAlloc),
         mark(lifoAlloc->mark()),
+        fallibleScope(lifoAlloc),
         shouldRelease(true)
     {
         MOZ_GUARD_OBJECT_NOTIFIER_INIT;
     }
 
     ~LifoAllocScope() {
         if (shouldRelease)
             lifoAlloc->release(mark);
--- a/js/src/frontend/Parser.cpp
+++ b/js/src/frontend/Parser.cpp
@@ -9347,17 +9347,22 @@ Parser<ParseHandler>::objectLiteral(Yiel
             if (!tokenStream.checkForKeyword(propAtom, nullptr))
                 return null();
 
             Node lhs = identifierName(yieldHandling);
             if (!lhs)
                 return null();
 
             tokenStream.consumeKnownToken(TOK_ASSIGN);
+            bool saved = pc->inDeclDestructuring;
+            // Setting `inDeclDestructuring` to false allows name use to be noted
+            // in `identifierName` See Bug: 1255167.
+            pc->inDeclDestructuring = false;
             Node rhs = assignExpr(InAllowed, yieldHandling, TripledotProhibited);
+            pc->inDeclDestructuring = saved;
             if (!rhs)
                 return null();
 
             Node propExpr = handler.newAssignment(PNK_ASSIGN, lhs, rhs, pc, JSOP_NOP);
             if (!propExpr)
                 return null();
 
             if (!handler.addPropertyDefinition(literal, propName, propExpr))
--- a/js/src/gc/Statistics.cpp
+++ b/js/src/gc/Statistics.cpp
@@ -189,23 +189,23 @@ static const PhaseInfo phases[] = {
     // numbers.
 };
 
 static ExtraPhaseInfo phaseExtra[PHASE_LIMIT] = { { 0, 0 } };
 
 // Mapping from all nodes with a multi-parented child to a Vector of all
 // multi-parented children and their descendants. (Single-parented children will
 // not show up in this list.)
-static mozilla::Vector<Phase> dagDescendants[Statistics::NumTimingArrays];
+static mozilla::Vector<Phase, 0, SystemAllocPolicy> dagDescendants[Statistics::NumTimingArrays];
 
 struct AllPhaseIterator {
     int current;
     int baseLevel;
     size_t activeSlot;
-    mozilla::Vector<Phase>::Range descendants;
+    mozilla::Vector<Phase, 0, SystemAllocPolicy>::Range descendants;
 
     explicit AllPhaseIterator(const Statistics::PhaseTimeTable table)
       : current(0)
       , baseLevel(0)
       , activeSlot(PHASE_DAG_NONE)
       , descendants(dagDescendants[PHASE_DAG_NONE].all()) /* empty range */
     {
     }
@@ -824,17 +824,17 @@ Statistics::initialize()
                 return false;
             j++;
         } while (j != PHASE_LIMIT && phases[j].parent != PHASE_MULTI_PARENTS);
     }
     MOZ_ASSERT(dagSlot <= MaxMultiparentPhases - 1);
 
     // Fill in the depth of each node in the tree. Multi-parented nodes
     // have depth 0.
-    mozilla::Vector<Phase> stack;
+    mozilla::Vector<Phase, 0, SystemAllocPolicy> stack;
     if (!stack.append(PHASE_LIMIT)) // Dummy entry to avoid special-casing the first node
         return false;
     for (int i = 0; i < PHASE_LIMIT; i++) {
         if (phases[i].parent == PHASE_NO_PARENT ||
             phases[i].parent == PHASE_MULTI_PARENTS)
         {
             stack.clear();
         } else {
--- a/js/src/irregexp/RegExpEngine.cpp
+++ b/js/src/irregexp/RegExpEngine.cpp
@@ -1715,16 +1715,22 @@ RegExpCode
 RegExpCompiler::Assemble(JSContext* cx,
                          RegExpMacroAssembler* assembler,
                          RegExpNode* start,
                          int capture_count)
 {
     macro_assembler_ = assembler;
     macro_assembler_->set_slow_safe(false);
 
+    // The LifoAlloc used by the regexp compiler is infallible and is currently
+    // expected to crash on OOM. Thus we have to disable the assertions made to
+    // prevent us from allocating any new chunk in the LifoAlloc. This is needed
+    // because the jit::MacroAssembler turns these assertions on by default.
+    LifoAlloc::AutoFallibleScope fallibleAllocator(alloc());
+
     jit::Label fail;
     macro_assembler_->PushBacktrack(&fail);
     Trace new_trace;
     start->Emit(this, &new_trace);
     macro_assembler_->BindBacktrack(&fail);
     macro_assembler_->Fail();
 
     while (!work_list_.empty())
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/gc/bug-1280588.js
@@ -0,0 +1,6 @@
+if (!('oomTest' in this))
+    quit();
+
+var x = [];
+oomTest(() => setGCCallback({ action: "minorGC" }));
+oomTest(() => setGCCallback({ action: "majorGC" }));
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/gc/oomInByteSize.js
@@ -0,0 +1,19 @@
+if (!('oomTest' in this))
+    quit();
+
+oomTest(() => byteSize({}));
+oomTest(() => byteSize({ w: 1, x: 2, y: 3 }));
+oomTest(() => byteSize({ w:1, x:2, y:3, z:4, a:6, 0:0, 1:1, 2:2 }));
+oomTest(() => byteSize([1, 2, 3]));
+oomTest(() => byteSize(function () {}));
+
+function f1() {
+  return 42;
+}
+oomTest(() => byteSizeOfScript(f1));
+
+oomTest(() => byteSize("1234567"));
+oomTest(() => byteSize("千早ぶる神代"));
+
+let s = Symbol();
+oomTest(() => byteSize(s));
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/gc/oomInFindPath.js
@@ -0,0 +1,19 @@
+if (!('oomTest' in this))
+    quit();
+
+var o = { w: { x: { y: { z: {} } } } };
+oomTest(() => findPath(o, o.w.x.y.z));
+
+var a = [ , o ];
+oomTest(() => findPath(a, o));
+
+function C() {}
+C.prototype.obj = {};
+var c = new C;
+
+oomTest(() => findPath(c, c.obj));
+
+function f(x) { return function g(y) { return x+y; }; }
+var o = {}
+var gc = f(o);
+oomTest(() => findPath(gc, o));
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/ion/bug1264948-1.js
@@ -0,0 +1,9 @@
+// |jit-test| error: ReferenceError
+
+var N = 70 * 1000;
+var x = build("&&")();
+function build(operation) {
+    var a = [];
+    for (var i = 1; i != N - 1; ++i) a.push("f()");
+    return new Function(a.join(operation));
+}
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/ion/bug1264948.js
@@ -0,0 +1,21 @@
+if (!('oomTest' in this))
+    quit();
+
+loadFile(`
+  T = TypedObject
+  ObjectStruct = new T.StructType({f: T.Object})
+  var o = new ObjectStruct
+  function testGC(p) {
+    for (; i < 5; i++)
+        whatever.push;
+  }
+  testGC(o)
+  function writeObject()
+    o.f = v
+    writeObject({function() { } })
+  for (var i ; i < 5 ; ++i)
+    try {} catch (StringStruct) {}
+`);
+function loadFile(lfVarx) {
+  oomTest(Function(lfVarx));
+}
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/ion/bug1269756.js
@@ -0,0 +1,8 @@
+if (!('oomTest' in this))
+    quit();
+
+oomTest(function() {
+    m = parseModule(`while (x && NaN) prototype; let x`);
+    m.declarationInstantiation();
+    m.evaluation();
+})
--- a/js/src/jit/IonBuilder.cpp
+++ b/js/src/jit/IonBuilder.cpp
@@ -761,17 +761,23 @@ IonBuilder::pushLoop(CFGState::State ini
     state.loop.initialStopAt = stopAt;
     state.loop.loopHead = loopHead;
     return cfgStack_.append(state);
 }
 
 bool
 IonBuilder::init()
 {
-    if (!TypeScript::FreezeTypeSets(constraints(), script(), &thisTypes, &argTypes, &typeArray))
+    {
+        LifoAlloc::AutoFallibleScope fallibleAllocator(alloc().lifoAlloc());
+        if (!TypeScript::FreezeTypeSets(constraints(), script(), &thisTypes, &argTypes, &typeArray))
+            return false;
+    }
+
+    if (!alloc().ensureBallast())
         return false;
 
     if (inlineCallInfo_) {
         // If we're inlining, the actual this/argument types are not necessarily
         // a subset of the script's observed types. |argTypes| is never accessed
         // for inlined scripts, so we just null it.
         thisTypes = inlineCallInfo_->thisArg()->resultTypeSet();
         argTypes = nullptr;
@@ -1403,16 +1409,19 @@ IonBuilder::maybeAddOsrTypeBarriers()
     MOZ_ASSERT(stackDepth == osrBlock->stackDepth());
     for (uint32_t slot = info().startArgSlot(); slot < stackDepth; slot++) {
         // Aliased slots are never accessed, since they need to go through
         // the callobject. The typebarriers are added there and can be
         // discarded here.
         if (info().isSlotAliasedAtOsr(slot))
             continue;
 
+        if (!alloc().ensureBallast())
+            return false;
+
         MInstruction* def = osrBlock->getSlot(slot)->toInstruction();
         MPhi* preheaderPhi = preheader->getSlot(slot)->toPhi();
         MPhi* headerPhi = headerRp->getOperand(slot)->toPhi();
 
         MIRType type = headerPhi->type();
         TemporaryTypeSet* typeSet = headerPhi->resultTypeSet();
 
         if (!addOsrValueTypeBarrier(slot, &def, type, typeSet))
--- a/js/src/jit/JitAllocPolicy.h
+++ b/js/src/jit/JitAllocPolicy.h
@@ -29,53 +29,57 @@ class TempAllocator
     // KiB. And with a ballast of 16 KiB, a chunk size of 32 KiB works well,
     // because TempAllocators with a peak allocation size of less than 16 KiB
     // (which is most of them) only have to allocate a single chunk.
     static const size_t BallastSize;            // 16 KiB
     static const size_t PreferredLifoChunkSize; // 32 KiB
 
     explicit TempAllocator(LifoAlloc* lifoAlloc)
       : lifoScope_(lifoAlloc)
-    { }
+    {
+        lifoAlloc->setAsInfallibleByDefault();
+    }
 
     void* allocateInfallible(size_t bytes)
     {
-        return lifoScope_.alloc().allocInfallibleOrAssert(bytes);
+        return lifoScope_.alloc().allocInfallible(bytes);
     }
 
-    void* allocate(size_t bytes)
+    MOZ_MUST_USE void* allocate(size_t bytes)
     {
+        LifoAlloc::AutoFallibleScope fallibleAllocator(lifoAlloc());
         void* p = lifoScope_.alloc().alloc(bytes);
         if (!ensureBallast())
             return nullptr;
         return p;
     }
 
     template <typename T>
-    T* allocateArray(size_t n)
+    MOZ_MUST_USE T* allocateArray(size_t n)
     {
+        LifoAlloc::AutoFallibleScope fallibleAllocator(lifoAlloc());
         size_t bytes;
         if (MOZ_UNLIKELY(!CalculateAllocSize<T>(n, &bytes)))
             return nullptr;
         T* p = static_cast<T*>(lifoScope_.alloc().alloc(bytes));
         if (MOZ_UNLIKELY(!ensureBallast()))
             return nullptr;
         return p;
     }
 
     // View this allocator as a fallible allocator.
     struct Fallible { TempAllocator& alloc; };
     Fallible fallible() { return { *this }; }
 
-    LifoAlloc* lifoAlloc()
-    {
+    LifoAlloc* lifoAlloc() {
         return &lifoScope_.alloc();
     }
 
     MOZ_MUST_USE bool ensureBallast() {
+        JS_OOM_POSSIBLY_FAIL_BOOL();
         return lifoScope_.alloc().ensureUnusedApproximate(BallastSize);
     }
 };
 
 class JitAllocPolicy
 {
     TempAllocator& alloc_;
 
@@ -145,17 +149,17 @@ class AutoJitContextAlloc
     ~AutoJitContextAlloc() {
         MOZ_ASSERT(jcx_->temp == &tempAlloc_);
         jcx_->temp = prevAlloc_;
     }
 };
 
 struct TempObject
 {
-    inline void* operator new(size_t nbytes, TempAllocator::Fallible view) noexcept {
+    inline void* operator new(size_t nbytes, TempAllocator::Fallible view) throw() {
         return view.alloc.allocate(nbytes);
     }
     inline void* operator new(size_t nbytes, TempAllocator& alloc) {
         return alloc.allocateInfallible(nbytes);
     }
     template <class T>
     inline void* operator new(size_t nbytes, T* pos) {
         static_assert(mozilla::IsConvertible<T*, TempObject*>::value,
--- a/js/src/jit/MCallOptimize.cpp
+++ b/js/src/jit/MCallOptimize.cpp
@@ -521,16 +521,18 @@ IonBuilder::inlineArray(CallInfo& callIn
 
     if (!jsop_newarray(templateObject, initLength))
         return InliningStatus_Error;
 
     MDefinition* array = current->peek(-1);
     if (callInfo.argc() >= 2) {
         JSValueType unboxedType = GetBoxedOrUnboxedType(templateObject);
         for (uint32_t i = 0; i < initLength; i++) {
+            if (!alloc().ensureBallast())
+                return InliningStatus_Error;
             MDefinition* value = callInfo.getArg(i);
             if (!initializeArrayElement(array, i, value, unboxedType, /* addResumePoint = */ false))
                 return InliningStatus_Error;
         }
 
         MInstruction* setLength = setInitializedLength(array, unboxedType, initLength);
         if (!resumeAfter(setLength))
             return InliningStatus_Error;
--- a/js/src/jit/MIR.h
+++ b/js/src/jit/MIR.h
@@ -7151,16 +7151,19 @@ class MPhi final
 #endif
     {
         setResultType(resultType);
     }
 
     static MPhi* New(TempAllocator& alloc, MIRType resultType = MIRType::Value) {
         return new(alloc) MPhi(alloc, resultType);
     }
+    static MPhi* New(TempAllocator::Fallible alloc, MIRType resultType = MIRType::Value) {
+        return new(alloc) MPhi(alloc.alloc, resultType);
+    }
 
     void removeOperand(size_t index);
     void removeAllOperands();
 
     MDefinition* getOperand(size_t index) const override {
         return inputs_[index].producer();
     }
     size_t numOperands() const override {
--- a/js/src/jit/MIRGraph.cpp
+++ b/js/src/jit/MIRGraph.cpp
@@ -553,17 +553,19 @@ MBasicBlock::inherit(TempAllocator& allo
 
     if (pred) {
         if (!predecessors_.append(pred))
             return false;
 
         if (kind_ == PENDING_LOOP_HEADER) {
             size_t i = 0;
             for (i = 0; i < info().firstStackSlot(); i++) {
-                MPhi* phi = MPhi::New(alloc);
+                MPhi* phi = MPhi::New(alloc.fallible());
+                if (!phi)
+                    return false;
                 phi->addInlineInput(pred->getSlot(i));
                 addPhi(phi);
                 setSlot(i, phi);
                 entryResumePoint()->initOperand(i, phi);
             }
 
             MOZ_ASSERT(stackPhiCount <= stackDepth());
             MOZ_ASSERT(info().firstStackSlot() <= stackDepth() - stackPhiCount);
@@ -573,17 +575,19 @@ MBasicBlock::inherit(TempAllocator& allo
             // stack are part of the loop.
             for (; i < stackDepth() - stackPhiCount; i++) {
                 MDefinition* val = pred->getSlot(i);
                 setSlot(i, val);
                 entryResumePoint()->initOperand(i, val);
             }
 
             for (; i < stackDepth(); i++) {
-                MPhi* phi = MPhi::New(alloc);
+                MPhi* phi = MPhi::New(alloc.fallible());
+                if (!phi)
+                    return false;
                 phi->addInlineInput(pred->getSlot(i));
                 addPhi(phi);
                 setSlot(i, phi);
                 entryResumePoint()->initOperand(i, phi);
             }
         } else {
             for (size_t i = 0; i < stackDepth(); i++)
                 entryResumePoint()->initOperand(i, getSlot(i));
@@ -1188,19 +1192,21 @@ MBasicBlock::addPredecessorPopN(TempAllo
             if (mine->isPhi() && mine->block() == this) {
                 MOZ_ASSERT(predecessors_.length());
                 if (!mine->toPhi()->addInputSlow(other))
                     return false;
             } else {
                 // Otherwise, create a new phi node.
                 MPhi* phi;
                 if (mine->type() == other->type())
-                    phi = MPhi::New(alloc, mine->type());
+                    phi = MPhi::New(alloc.fallible(), mine->type());
                 else
-                    phi = MPhi::New(alloc);
+                    phi = MPhi::New(alloc.fallible());
+                if (!phi)
+                    return false;
                 addPhi(phi);
 
                 // Prime the phi for each predecessor, so input(x) comes from
                 // predecessor(x).
                 if (!phi->reserveLength(predecessors_.length() + 1))
                     return false;
 
                 for (size_t j = 0, numPreds = predecessors_.length(); j < numPreds; ++j) {
--- a/js/src/jit/mips32/Assembler-mips32.cpp
+++ b/js/src/jit/mips32/Assembler-mips32.cpp
@@ -451,10 +451,10 @@ Assembler::ToggleCall(CodeLocationLabel 
 void
 Assembler::UpdateBoundsCheck(uint8_t* patchAt, uint32_t heapLength)
 {
     Instruction* inst = (Instruction*) patchAt;
     InstImm* i0 = (InstImm*) inst;
     InstImm* i1 = (InstImm*) i0->next();
 
     // Replace with new value
-    Assembler::UpdateLuiOriValue(i0, i1, heapSize);
+    Assembler::UpdateLuiOriValue(i0, i1, heapLength);
 }
--- a/js/src/jit/mips64/Architecture-mips64.h
+++ b/js/src/jit/mips64/Architecture-mips64.h
@@ -54,16 +54,17 @@ class FloatRegisters : public FloatRegis
     static const SetType SpreadSingle = SetType(1) << (uint32_t(Single) * TotalPhys);
     static const SetType SpreadDouble = SetType(1) << (uint32_t(Double) * TotalPhys);
     static const SetType SpreadScalar = SpreadSingle | SpreadDouble;
     static const SetType SpreadVector = 0;
     static const SetType Spread = SpreadScalar | SpreadVector;
 
     static const SetType AllPhysMask = ((SetType(1) << TotalPhys) - 1);
     static const SetType AllMask = AllPhysMask * Spread;
+    static const SetType AllSingleMask = AllPhysMask * SpreadSingle;
     static const SetType AllDoubleMask = AllPhysMask * SpreadDouble;
 
     static const SetType NonVolatileMask =
         ( (1U << FloatRegisters::f24) |
           (1U << FloatRegisters::f25) |
           (1U << FloatRegisters::f26) |
           (1U << FloatRegisters::f27) |
           (1U << FloatRegisters::f28) |
--- a/js/src/jsapi-tests/testThreadingThread.cpp
+++ b/js/src/jsapi-tests/testThreadingThread.cpp
@@ -4,16 +4,19 @@
 /* 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 "mozilla/Atomics.h"
 #include "mozilla/IntegerRange.h"
 #include "mozilla/Move.h"
 #include "mozilla/Vector.h"
+
+#include "jsalloc.h"
+
 #include "jsapi-tests/tests.h"
 #include "threading/Thread.h"
 
 BEGIN_TEST(testThreadingThreadJoin)
 {
     bool flag = false;
     js::Thread thread([](bool* flagp){*flagp = true;}, &flag);
     CHECK(thread.joinable());
@@ -57,17 +60,17 @@ BEGIN_TEST(testThreadingThreadId)
     return true;
 }
 END_TEST(testThreadingThreadId)
 
 BEGIN_TEST(testThreadingThreadVectorMoveConstruct)
 {
     const static size_t N = 10;
     mozilla::Atomic<int> count(0);
-    mozilla::Vector<js::Thread> v;
+    mozilla::Vector<js::Thread, 0, js::SystemAllocPolicy> v;
     for (auto i : mozilla::MakeRange(N)) {
         CHECK(v.emplaceBack([](mozilla::Atomic<int>* countp){(*countp)++;}, &count));
         CHECK(v.length() == i + 1);
     }
     for (auto& th : v)
         th.join();
     CHECK(count == 10);
     return true;
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -6145,16 +6145,18 @@ struct PerformanceGroup {
 
   public:
     // Compatibility with RefPtr<>
     void AddRef();
     void Release();
     uint64_t refCount_;
 };
 
+using PerformanceGroupVector = mozilla::Vector<RefPtr<js::PerformanceGroup>, 0, SystemAllocPolicy>;
+
 /**
  * Commit any Performance Monitoring data.
  *
  * Until `FlushMonitoring` has been called, all PerformanceMonitoring data is invisible
  * to the outside world and can cancelled with a call to `ResetMonitoring`.
  */
 extern JS_PUBLIC_API(bool)
 FlushPerformanceMonitoring(JSRuntime*);
@@ -6203,21 +6205,21 @@ extern JS_PUBLIC_API(void)
 AddCPOWPerformanceDelta(JSRuntime*, uint64_t delta);
 
 typedef bool
 (*StopwatchStartCallback)(uint64_t, void*);
 extern JS_PUBLIC_API(bool)
 SetStopwatchStartCallback(JSRuntime*, StopwatchStartCallback, void*);
 
 typedef bool
-(*StopwatchCommitCallback)(uint64_t, mozilla::Vector<RefPtr<PerformanceGroup>>&, void*);
+(*StopwatchCommitCallback)(uint64_t, PerformanceGroupVector&, void*);
 extern JS_PUBLIC_API(bool)
 SetStopwatchCommitCallback(JSRuntime*, StopwatchCommitCallback, void*);
 
 typedef bool
-(*GetGroupsCallback)(JSContext*, mozilla::Vector<RefPtr<PerformanceGroup>>&, void*);
+(*GetGroupsCallback)(JSContext*, PerformanceGroupVector&, void*);
 extern JS_PUBLIC_API(bool)
 SetGetPerformanceGroupsCallback(JSRuntime*, GetGroupsCallback, void*);
 
 } /* namespace js */
 
 
 #endif /* jsapi_h */
--- a/js/src/jsgc.cpp
+++ b/js/src/jsgc.cpp
@@ -967,17 +967,17 @@ GCRuntime::setNextScheduled(uint32_t cou
     nextScheduled = count;
 }
 
 bool
 GCRuntime::parseAndSetZeal(const char* str)
 {
     int frequency = -1;
     bool foundFrequency = false;
-    mozilla::Vector<int> zeals;
+    mozilla::Vector<int, 0, SystemAllocPolicy> zeals;
 
     static const struct {
         const char* const zealMode;
         size_t length;
         uint32_t zeal;
     } zealModes[] = {
 #define ZEAL_MODE(name, value) {#name, sizeof(#name) - 1, value},
         JS_FOR_EACH_ZEAL_MODE(ZEAL_MODE)
@@ -2638,18 +2638,19 @@ GCRuntime::releaseRelocatedArenasWithout
 // Sometimes protect them instead and hold onto them until the next GC sweep
 // phase to catch any pointers to them that didn't get forwarded.
 
 void
 GCRuntime::releaseHeldRelocatedArenas()
 {
 #ifdef DEBUG
     unprotectHeldRelocatedArenas();
-    releaseRelocatedArenas(relocatedArenasToRelease);
+    Arena* arenas = relocatedArenasToRelease;
     relocatedArenasToRelease = nullptr;
+    releaseRelocatedArenas(arenas);
 #endif
 }
 
 void
 GCRuntime::releaseHeldRelocatedArenasWithoutUnlocking(const AutoLockGC& lock)
 {
 #ifdef DEBUG
     unprotectHeldRelocatedArenas();
@@ -3129,17 +3130,17 @@ GCRuntime::decommitArenas(AutoLockGC& lo
 {
     // Verify that all entries in the empty chunks pool are decommitted.
     for (ChunkPool::Iter chunk(emptyChunks(lock)); !chunk.done(); chunk.next())
         MOZ_ASSERT(!chunk->info.numArenasFreeCommitted);
 
     // Build a Vector of all current available Chunks. Since we release the
     // gc lock while doing the decommit syscall, it is dangerous to iterate
     // the available list directly, as concurrent operations can modify it.
-    mozilla::Vector<Chunk*> toDecommit;
+    mozilla::Vector<Chunk*, 0, SystemAllocPolicy> toDecommit;
     MOZ_ASSERT(availableChunks(lock).verify());
     for (ChunkPool::Iter iter(availableChunks(lock)); !iter.done(); iter.next()) {
         if (!toDecommit.append(iter.get())) {
             // The OOM handler does a full, immediate decommit, so there is
             // nothing more to do here in any case.
             return onOutOfMallocMemory(lock);
         }
     }
--- a/js/src/old-configure.in
+++ b/js/src/old-configure.in
@@ -2427,17 +2427,16 @@ AC_SUBST(AS_DASH_C_FLAG)
 AC_SUBST(LD)
 AC_SUBST(RC)
 AC_SUBST(RCFLAGS)
 AC_SUBST(WINDRES)
 AC_SUBST(IMPLIB)
 AC_SUBST(FILTER)
 AC_SUBST(BIN_FLAGS)
 AC_SUBST(MOZ_DEBUG)
-AC_SUBST(MOZ_DEBUG_SYMBOLS)
 AC_SUBST(MOZ_DEBUG_LDFLAGS)
 AC_SUBST(WARNINGS_AS_ERRORS)
 AC_SUBST(LIBICONV)
 
 AC_SUBST(ENABLE_STRIP)
 AC_SUBST(PKG_SKIP_STRIP)
 AC_SUBST(INCREMENTAL_LINKER)
 
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -5217,18 +5217,18 @@ WasmLoop(JSContext* cx, unsigned argc, V
         return false;
 
     while (__AFL_LOOP(1000)) {
         Rooted<JSObject*> ret(cx, FileAsTypedArray(cx, filename.ptr()));
         if (!ret)
             return false;
 
         Rooted<TypedArrayObject*> typedArray(cx, &ret->as<TypedArrayObject>());
-        RootedObject exportObj(cx);
-        if (!wasm::Eval(cx, typedArray, importObj, &exportObj)) {
+        RootedWasmInstanceObject instanceObj(cx);
+        if (!wasm::Eval(cx, typedArray, importObj, &instanceObj)) {
             // Clear any pending exceptions, we don't care about them
             cx->clearPendingException();
         }
     }
 
     return true;
 }
 #endif // __AFL_HAVE_MANUAL_CONTROL
--- a/js/src/tests/ecma_6/Object/destructuring-shorthand-defaults.js
+++ b/js/src/tests/ecma_6/Object/destructuring-shorthand-defaults.js
@@ -118,10 +118,19 @@ assertEq((({a = 0} = {}) => a)({a: 1}), 
 
 {
     let {x={i=1, j=2}={}}={};
     assertDeepEq(x, ({}));
     assertEq(i, 1);
     assertEq(j, 2);
 }
 
+// Default destructuring values, which are variables, should be defined
+// within closures (Bug 1255167).
+{
+    let f = function(a){
+        return (function({aa = a}){ return aa; })({});
+    };
+    assertEq(f(9999), 9999);
+}
+
 if (typeof reportCompare == "function")
     reportCompare(true, true);
--- a/js/src/vm/Stopwatch.cpp
+++ b/js/src/vm/Stopwatch.cpp
@@ -147,17 +147,17 @@ PerformanceMonitoring::commit()
         return true;
     }
 
     if (startedAtIteration_ != iteration_) {
         // No JS code has been monitored during this iteration.
         return true;
     }
 
-    GroupVector recentGroups;
+    PerformanceGroupVector recentGroups;
     recentGroups_.swap(recentGroups);
 
     bool success = true;
     if (stopwatchCommitCallback)
         success = stopwatchCommitCallback(iteration_, recentGroups, stopwatchCommitClosure);
 
     // Reset immediately, to make sure that we're not hit by the end
     // of a nested event loop (which would cause `commit` to be called
@@ -195,17 +195,17 @@ PerformanceGroupHolder::~PerformanceGrou
 
 void
 PerformanceGroupHolder::unlink()
 {
     initialized_ = false;
     groups_.clear();
 }
 
-const GroupVector*
+const PerformanceGroupVector*
 PerformanceGroupHolder::getGroups(JSContext* cx)
 {
     if (initialized_)
         return &groups_;
 
     if (!runtime_->performanceMonitoring.getGroupsCallback)
         return nullptr;
 
@@ -228,17 +228,17 @@ AutoStopwatch::AutoStopwatch(JSContext* 
 
     JSCompartment* compartment = cx_->compartment();
     if (compartment->scheduledForDestruction)
         return;
 
     JSRuntime* runtime = cx_->runtime();
     iteration_ = runtime->performanceMonitoring.iteration();
 
-    const GroupVector* groups = compartment->performanceMonitoring.getGroups(cx);
+    const PerformanceGroupVector* groups = compartment->performanceMonitoring.getGroups(cx);
     if (!groups) {
       // Either the embedding has not provided any performance
       // monitoring logistics or there was an error that prevents
       // performance monitoring.
       return;
     }
     for (auto group = groups->begin(); group < groups->end(); group++) {
       auto acquired = acquireGroup(*group);
--- a/js/src/vm/Stopwatch.h
+++ b/js/src/vm/Stopwatch.h
@@ -14,18 +14,16 @@
 
 /*
   An API for following in real-time the amount of CPU spent executing
   webpages, add-ons, etc.
 */
 
 namespace js {
 
-typedef mozilla::Vector<RefPtr<js::PerformanceGroup>> GroupVector;
-
 /**
  * A container for performance groups.
  *
  * Performance monitoring deals with the execution duration of code
  * that belongs to components, for a notion of components defined by
  * the embedding.  Typically, in a web browser, a component may be a
  * webpage and/or a frame and/or a module and/or an add-on and/or a
  * sandbox and/or a process etc.
@@ -38,33 +36,33 @@ struct PerformanceGroupHolder {
     /**
      * Get the groups to which this compartment belongs.
      *
      * Pre-condition: Execution must have entered the compartment.
      *
      * May return `nullptr` if the embedding has not initialized
      * support for performance groups.
      */
-    const GroupVector* getGroups(JSContext*);
+    const PerformanceGroupVector* getGroups(JSContext*);
 
     explicit PerformanceGroupHolder(JSRuntime* runtime)
       : runtime_(runtime)
       , initialized_(false)
     {  }
     ~PerformanceGroupHolder();
     void unlink();
   private:
     JSRuntime* runtime_;
 
     // `true` once a call to `getGroups` has succeeded.
     bool initialized_;
 
     // The groups to which this compartment belongs. Filled if and only
     // if `initialized_` is `true`.
-    GroupVector groups_;
+    PerformanceGroupVector groups_;
 };
 
 /**
  * Container class for everything related to performance monitoring.
  */
 struct PerformanceMonitoring {
     /**
      * The number of the current iteration of the event loop.
@@ -287,17 +285,17 @@ struct PerformanceMonitoring {
      * during the same event loop and to avoid committing stale
      * stopwatch results.
      */
     uint64_t startedAtIteration_;
 
     /**
      * Groups used in the current iteration.
      */
-    GroupVector recentGroups_;
+    PerformanceGroupVector recentGroups_;
 
     /**
      * The highest value of the timestamp counter encountered
      * during this iteration.
      */
     uint64_t highestTimestampCounter_;
 };
 
@@ -339,17 +337,17 @@ class AutoStopwatch final {
     // Timestamps captured while starting the stopwatch.
     uint64_t cyclesStart_;
     uint64_t CPOWTimeStart_;
 
     // The CPU on which we started the measure. Defined only
     // if `isMonitoringJank_` is `true`.
     cpuid_t cpuStart_;
 
-    mozilla::Vector<RefPtr<js::PerformanceGroup>> groups_;
+    PerformanceGroupVector groups_;
 
   public:
     // If the stopwatch is active, constructing an instance of
     // AutoStopwatch causes it to become the current owner of the
     // stopwatch.
     //
     // Previous owner is restored upon destruction.
     explicit AutoStopwatch(JSContext* cx MOZ_GUARD_OBJECT_NOTIFIER_PARAM);
--- a/js/src/vm/UbiNodeCensus.cpp
+++ b/js/src/vm/UbiNodeCensus.cpp
@@ -122,17 +122,17 @@ SimpleCount::report(JSContext* cx, Count
     return true;
 }
 
 
 // A count type that collects all matching nodes in a bucket.
 class BucketCount : public CountType {
 
     struct Count : CountBase {
-        mozilla::Vector<JS::ubi::Node::Id> ids_;
+        JS::ubi::Vector<JS::ubi::Node::Id> ids_;
 
         explicit Count(BucketCount& count)
           : CountBase(count),
             ids_()
         { }
     };
 
   public:
@@ -344,17 +344,17 @@ using CStringCountMap = HashMap<const ch
 // `const char*`.
 template <class Map, class GetName>
 static PlainObject*
 countMapToObject(JSContext* cx, Map& map, GetName getName) {
     // Build a vector of pointers to entries; sort by total; and then use
     // that to build the result object. This makes the ordering of entries
     // more interesting, and a little less non-deterministic.
 
-    mozilla::Vector<typename Map::Entry*> entries;
+    JS::ubi::Vector<typename Map::Entry*> entries;
     if (!entries.reserve(map.count())) {
         ReportOutOfMemory(cx);
         return nullptr;
     }
 
     for (auto r = map.all(); !r.empty(); r.popFront())
         entries.infallibleAppend(&r.front());
 
@@ -565,17 +565,17 @@ ByUbinodeType::count(CountBase& countBas
 bool
 ByUbinodeType::report(JSContext* cx, CountBase& countBase, MutableHandleValue report)
 {
     Count& count = static_cast<Count&>(countBase);
 
     // Build a vector of pointers to entries; sort by total; and then use
     // that to build the result object. This makes the ordering of entries
     // more interesting, and a little less non-deterministic.
-    mozilla::Vector<Entry*> entries;
+    JS::ubi::Vector<Entry*> entries;
     if (!entries.reserve(count.table.count()))
         return false;
     for (Table::Range r = count.table.all(); !r.empty(); r.popFront())
         entries.infallibleAppend(&r.front());
     qsort(entries.begin(), entries.length(), sizeof(*entries.begin()), compareEntries<Entry>);
 
     // Now build the result by iterating over the sorted vector.
     RootedPlainObject obj(cx, NewBuiltinClassInstance<PlainObject>(cx));
@@ -731,17 +731,17 @@ ByAllocationStack::report(JSContext* cx,
 #ifdef DEBUG
     // Check that nothing rehashes our table while we hold pointers into it.
     Generation generation = count.table.generation();
 #endif
 
     // Build a vector of pointers to entries; sort by total; and then use
     // that to build the result object. This makes the ordering of entries
     // more interesting, and a little less non-deterministic.
-    mozilla::Vector<Entry*> entries;
+    JS::ubi::Vector<Entry*> entries;
     if (!entries.reserve(count.table.count()))
         return false;
     for (Table::Range r = count.table.all(); !r.empty(); r.popFront())
         entries.infallibleAppend(&r.front());
     qsort(entries.begin(), entries.length(), sizeof(*entries.begin()), compareEntries<Entry>);
 
     // Now build the result by iterating over the sorted vector.
     Rooted<MapObject*> map(cx, MapObject::create(cx));
--- a/layout/base/nsCSSRenderingBorders.cpp
+++ b/layout/base/nsCSSRenderingBorders.cpp
@@ -27,16 +27,18 @@
 #include "mozilla/gfx/2D.h"
 #include "gfx2DGlue.h"
 #include "gfxGradientCache.h"
 #include <algorithm>
 
 using namespace mozilla;
 using namespace mozilla::gfx;
 
+#define MAX_COMPOSITE_BORDER_WIDTH LayoutDeviceIntCoord(10000)
+
 /**
  * nsCSSRendering::PaintBorder
  * nsCSSRendering::PaintOutline
  *   -> DrawBorders
  *
  * DrawBorders
  *   -> Ability to use specialized approach?
  *      |- Draw using specialized function
@@ -1368,19 +1370,26 @@ nsCSSBorderRenderer::DrawBorderSides(int
     return;
   }
 
   // -moz-border-colors is a hack; if we have it for a border, then
   // it's always drawn solid, and each color is given 1px.  The last
   // color is used for the remainder of the border's size.  Just
   // hand off to another function to do all that.
   if (compositeColors) {
-    DrawBorderSidesCompositeColors(aSides, compositeColors);
-    return;
-  }
+    Float maxBorderWidth(0);
+    NS_FOR_CSS_SIDES (i) {
+      maxBorderWidth = std::max(maxBorderWidth, mBorderWidths[i]);
+    }
+    if (maxBorderWidth <= MAX_COMPOSITE_BORDER_WIDTH) {
+      DrawBorderSidesCompositeColors(aSides, compositeColors);
+      return;
+    }
+    NS_WARNING("DrawBorderSides: too large border width for composite colors");
+ }
 
   // We're not doing compositeColors, so we can calculate the
   // borderColorStyle based on the specified style.  The
   // borderColorStyle array goes from the outer to the inner style.
   //
   // If the border width is 1, we need to change the borderRenderStyle
   // a bit to make sure that we get the right colors -- e.g. 'ridge'
   // with a 1px border needs to look like solid, not like 'outset'.
--- a/layout/base/nsRefreshDriver.cpp
+++ b/layout/base/nsRefreshDriver.cpp
@@ -1871,17 +1871,17 @@ nsRefreshDriver::Tick(int64_t aNowEpoch,
     nsCOMArray<imgIContainer> imagesToRefresh(mRequests.Count());
 
     for (auto iter = mRequests.Iter(); !iter.Done(); iter.Next()) {
       nsISupportsHashKey* entry = iter.Get();
       auto req = static_cast<imgIRequest*>(entry->GetKey());
       MOZ_ASSERT(req, "Unable to retrieve the image request");
       nsCOMPtr<imgIContainer> image;
       if (NS_SUCCEEDED(req->GetImage(getter_AddRefs(image)))) {
-        imagesToRefresh.AppendElement(image);
+        imagesToRefresh.AppendElement(image.forget());
       }
     }
 
     for (uint32_t i = 0; i < imagesToRefresh.Length(); i++) {
       imagesToRefresh[i]->RequestRefresh(aNowTime);
     }
   }
 
--- a/layout/generic/nsGridContainerFrame.cpp
+++ b/layout/generic/nsGridContainerFrame.cpp
@@ -1076,16 +1076,17 @@ struct nsGridContainerFrame::TrackSizing
 
 /**
  * State for the tracks in one dimension.
  */
 struct nsGridContainerFrame::Tracks
 {
   explicit Tracks(LogicalAxis aAxis)
     : mAxis(aAxis)
+    , mCanResolveLineRangeSize(false)
   {
     mBaselineSubtreeAlign[BaselineSharingGroup::eFirst] = NS_STYLE_ALIGN_AUTO;
     mBaselineSubtreeAlign[BaselineSharingGroup::eLast] = NS_STYLE_ALIGN_AUTO;
   }
 
   void Initialize(const TrackSizingFunctions& aFunctions,
                   const nsStyleCoord&         aGridGap,
                   uint32_t                    aNumTracks,
@@ -1477,18 +1478,19 @@ struct nsGridContainerFrame::Tracks
                       nscoord                     aContentSize,
                       LineRange GridArea::*       aRange,
                       IntrinsicISizeType          aConstraint);
 
   /**
    * Apply 'align/justify-content', whichever is relevant for this axis.
    * https://drafts.csswg.org/css-align-3/#propdef-align-content
    */
-  void AlignJustifyContent(const nsHTMLReflowState& aReflowState,
-                           const LogicalSize& aContainerSize);
+  void AlignJustifyContent(const nsStylePosition* aStyle,
+                           WritingMode            aWM,
+                           const LogicalSize&     aContainerSize);
 
   nscoord GridLineEdge(uint32_t aLine, GridLineSide aSide) const
   {
     if (MOZ_UNLIKELY(mSizes.IsEmpty())) {
       // https://drafts.csswg.org/css-grid/#grid-definition
       // "... the explicit grid still contains one grid line in each axis."
       MOZ_ASSERT(aLine == 0, "We should only resolve line 1 in an empty grid");
       return nscoord(0);
@@ -1549,16 +1551,25 @@ struct nsGridContainerFrame::Tracks
     NS_WARN_IF_FALSE(delta != nscoord(0), "Useless call to ResizeRow");
     sz.mBase = aNewSize;
     const uint32_t numRows = mSizes.Length();
     for (uint32_t r = aRow + 1; r < numRows; ++r) {
       mSizes[r].mPosition += delta;
     }
   }
 
+  nscoord ResolveSize(const LineRange& aRange) const
+  {
+    MOZ_ASSERT(mCanResolveLineRangeSize);
+    MOZ_ASSERT(aRange.Extent() > 0, "grid items cover at least one track");
+    nscoord pos, size;
+    aRange.ToPositionAndLength(mSizes, &pos, &size);
+    return size;
+  }
+
 #ifdef DEBUG
   void Dump() const
   {
     for (uint32_t i = 0, len = mSizes.Length(); i < len; ++i) {
       printf("  %d: ", i);
       mSizes[i].Dump();
       printf("\n");
     }
@@ -1569,16 +1580,18 @@ struct nsGridContainerFrame::Tracks
   nscoord mContentBoxSize;
   nscoord mGridGap;
   LogicalAxis mAxis;
   // Used for aligning a baseline-aligned subtree of items.  The only possible
   // values are NS_STYLE_ALIGN_{START,END,CENTER,AUTO}.  AUTO means there are
   // no baseline-aligned items in any track in that axis.
   // There is one alignment value for each BaselineSharingGroup.
   uint8_t mBaselineSubtreeAlign[2];
+  // True if track positions and sizes are final in this axis.
+  bool mCanResolveLineRangeSize;
 };
 
 /**
  * Grid data shared by all continuations, owned by the first-in-flow.
  * The data is initialized from the first-in-flow's GridReflowState at
  * the end of its reflow.  Fragmentation will modify mRows.mSizes -
  * the mPosition to remove the row gap at the break boundary, the mState
  * by setting the eBreakBefore flag, and mBase is modified when we decide
@@ -1810,16 +1823,18 @@ private:
     if (aReflowState) {
       mBorderPadding = aReflowState->ComputedLogicalBorderPadding();
       mSkipSides = aFrame->PreReflowBlockLevelLogicalSkipSides();
       mBorderPadding.ApplySkipSides(mSkipSides);
     }
   }
 };
 
+using GridReflowState = nsGridContainerFrame::GridReflowState;
+
 /**
  * The Grid implements grid item placement and the state of the grid -
  * the size of the explicit/implicit grid, which cells are occupied etc.
  */
 struct MOZ_STACK_CLASS nsGridContainerFrame::Grid
 {
   /**
    * Place all child frames into the grid and expand the (implicit) grid as
@@ -2194,16 +2209,19 @@ nsGridContainerFrame::GridReflowState::C
   mCols.Initialize(mColFunctions, mGridStyle->mGridColumnGap,
                    aGrid.mGridColEnd, aContentBox.ISize(mWM));
   mRows.Initialize(mRowFunctions, mGridStyle->mGridRowGap,
                    aGrid.mGridRowEnd, aContentBox.BSize(mWM));
 
   mCols.CalculateSizes(*this, mGridItems, mColFunctions,
                        aContentBox.ISize(mWM), &GridArea::mCols,
                        aConstraint);
+  mCols.AlignJustifyContent(mGridStyle, mWM, aContentBox);
+  // Column positions and sizes are now final.
+  mCols.mCanResolveLineRangeSize = true;
 
   mRows.CalculateSizes(*this, mGridItems, mRowFunctions,
                        aContentBox.BSize(mWM), &GridArea::mRows,
                        aConstraint);
 }
 
 /**
  * (XXX share this utility function with nsFlexContainerFrame at some point)
@@ -3389,73 +3407,84 @@ MeasuringReflow(nsIFrame*               
 }
 
 /**
  * Return the [min|max]-content contribution of aChild to its parent (i.e.
  * the child's margin-box) in aAxis.
  */
 static nscoord
 ContentContribution(const GridItemInfo&               aGridItem,
-                    const nsHTMLReflowState*          aReflowState,
+                    const GridReflowState&            aState,
                     nsRenderingContext*               aRC,
                     WritingMode                       aCBWM,
                     LogicalAxis                       aAxis,
                     nsLayoutUtils::IntrinsicISizeType aConstraint,
                     uint32_t                          aFlags = 0)
 {
   nsIFrame* child = aGridItem.mFrame;
   PhysicalAxis axis(aCBWM.PhysicalAxis(aAxis));
   nscoord size = nsLayoutUtils::IntrinsicForAxis(axis, aRC, child, aConstraint,
                    aFlags | nsLayoutUtils::BAIL_IF_REFLOW_NEEDED);
   if (size == NS_INTRINSIC_WIDTH_UNKNOWN) {
     // We need to reflow the child to find its BSize contribution.
     // XXX this will give mostly correct results for now (until bug 1174569).
-    LogicalSize availableSize(child->GetWritingMode(), INFINITE_ISIZE_COORD, NS_UNCONSTRAINEDSIZE);
-    size = ::MeasuringReflow(child, aReflowState, aRC, availableSize);
+    nscoord cbISize = INFINITE_ISIZE_COORD;
+    nscoord cbBSize = NS_UNCONSTRAINEDSIZE;
+    auto childWM = child->GetWritingMode();
+    if (aState.mCols.mCanResolveLineRangeSize) {
+      nscoord sz = aState.mCols.ResolveSize(aGridItem.mArea.mCols);
+      if (childWM.IsOrthogonalTo(aCBWM)) {
+        cbBSize = sz;
+      } else {
+        cbISize = sz;
+      }
+    }
+    LogicalSize availableSize(childWM, cbISize, cbBSize);
+    size = ::MeasuringReflow(child, aState.mReflowState, aRC, availableSize);
     nsIFrame::IntrinsicISizeOffsetData offsets = child->IntrinsicBSizeOffsets();
     size += offsets.hMargin;
     size = nsLayoutUtils::AddPercents(aConstraint, size, offsets.hPctMargin);
   }
   MOZ_ASSERT(aGridItem.mBaselineOffset[aAxis] >= 0,
              "baseline offset should be non-negative at this point");
   MOZ_ASSERT((aGridItem.mState[aAxis] & ItemState::eIsBaselineAligned) ||
              aGridItem.mBaselineOffset[aAxis] == nscoord(0),
              "baseline offset should be zero when not baseline-aligned");
   size += aGridItem.mBaselineOffset[aAxis];
   return std::max(size, 0);
 }
 
 static nscoord
-MinContentContribution(const GridItemInfo&      aGridItem,
-                       const nsHTMLReflowState* aRS,
-                       nsRenderingContext*      aRC,
-                       WritingMode              aCBWM,
-                       LogicalAxis              aAxis)
+MinContentContribution(const GridItemInfo&    aGridItem,
+                       const GridReflowState& aState,
+                       nsRenderingContext*    aRC,
+                       WritingMode            aCBWM,
+                       LogicalAxis            aAxis)
 {
-  return ContentContribution(aGridItem, aRS, aRC, aCBWM, aAxis,
+  return ContentContribution(aGridItem, aState, aRC, aCBWM, aAxis,
                              nsLayoutUtils::MIN_ISIZE);
 }
 
 static nscoord
-MaxContentContribution(const GridItemInfo&      aGridItem,
-                       const nsHTMLReflowState* aRS,
-                       nsRenderingContext*      aRC,
-                       WritingMode              aCBWM,
-                       LogicalAxis              aAxis)
+MaxContentContribution(const GridItemInfo&    aGridItem,
+                       const GridReflowState& aState,
+                       nsRenderingContext*    aRC,
+                       WritingMode            aCBWM,
+                       LogicalAxis            aAxis)
 {
-  return ContentContribution(aGridItem, aRS, aRC, aCBWM, aAxis,
+  return ContentContribution(aGridItem, aState, aRC, aCBWM, aAxis,
                              nsLayoutUtils::PREF_ISIZE);
 }
 
 static nscoord
-MinSize(const GridItemInfo&      aGridItem,
-        const nsHTMLReflowState* aRS,
-        nsRenderingContext*      aRC,
-        WritingMode              aCBWM,
-        LogicalAxis              aAxis)
+MinSize(const GridItemInfo&    aGridItem,
+        const GridReflowState& aState,
+        nsRenderingContext*    aRC,
+        WritingMode            aCBWM,
+        LogicalAxis            aAxis)
 {
   nsIFrame* child = aGridItem.mFrame;
   PhysicalAxis axis(aCBWM.PhysicalAxis(aAxis));
   const nsStylePosition* stylePos = child->StylePosition();
   const nsStyleCoord& style = axis == eAxisHorizontal ? stylePos->mMinWidth
                                                       : stylePos->mMinHeight;
   // https://drafts.csswg.org/css-grid/#min-size-auto
   // This calculates the min-content contribution from either a definite
@@ -3472,17 +3501,17 @@ MinSize(const GridItemInfo&      aGridIt
     nsLayoutUtils::MinSizeContributionForAxis(axis, aRC, child,
                                               nsLayoutUtils::MIN_ISIZE);
   auto unit = style.GetUnit();
   if (unit == eStyleUnit_Enumerated ||
       (unit == eStyleUnit_Auto &&
        child->StyleDisplay()->mOverflowX == NS_STYLE_OVERFLOW_VISIBLE)) {
     // Now calculate the "content size" part and return whichever is smaller.
     MOZ_ASSERT(unit != eStyleUnit_Enumerated || sz == NS_UNCONSTRAINEDSIZE);
-    sz = std::min(sz, ContentContribution(aGridItem, aRS, aRC, aCBWM, aAxis,
+    sz = std::min(sz, ContentContribution(aGridItem, aState, aRC, aCBWM, aAxis,
                                           nsLayoutUtils::MIN_ISIZE,
                                           nsLayoutUtils::MIN_INTRINSIC_ISIZE));
   }
   return sz;
 }
 
 void
 nsGridContainerFrame::Tracks::CalculateSizes(
@@ -3547,47 +3576,46 @@ nsGridContainerFrame::Tracks::ResolveInt
   const LineRange&            aRange,
   const GridItemInfo&         aGridItem)
 {
   Maybe<nscoord> minContentContribution;
   Maybe<nscoord> maxContentContribution;
   // min sizing
   TrackSize& sz = mSizes[aRange.mStart];
   WritingMode wm = aState.mWM;
-  const nsHTMLReflowState* rs = aState.mReflowState;
   nsRenderingContext* rc = &aState.mRenderingContext;
   if (sz.mState & TrackSize::eAutoMinSizing) {
-    nscoord s = MinSize(aGridItem, rs, rc, wm, mAxis);
+    nscoord s = MinSize(aGridItem, aState, rc, wm, mAxis);
     sz.mBase = std::max(sz.mBase, s);
   } else if ((sz.mState & TrackSize::eMinContentMinSizing) ||
              (aConstraint == nsLayoutUtils::MIN_ISIZE &&
               (sz.mState & TrackSize::eFlexMinSizing))) {
-    nscoord s = MinContentContribution(aGridItem, rs, rc, wm, mAxis);
+    nscoord s = MinContentContribution(aGridItem, aState, rc, wm, mAxis);
     minContentContribution.emplace(s);
     sz.mBase = std::max(sz.mBase, minContentContribution.value());
   } else if (sz.mState & TrackSize::eMaxContentMinSizing) {
-    nscoord s = MaxContentContribution(aGridItem, rs, rc, wm, mAxis);
+    nscoord s = MaxContentContribution(aGridItem, aState, rc, wm, mAxis);
     maxContentContribution.emplace(s);
     sz.mBase = std::max(sz.mBase, maxContentContribution.value());
   }
   // max sizing
   if (sz.mState & TrackSize::eMinContentMaxSizing) {
     if (minContentContribution.isNothing()) {
-      nscoord s = MinContentContribution(aGridItem, rs, rc, wm, mAxis);
+      nscoord s = MinContentContribution(aGridItem, aState, rc, wm, mAxis);
       minContentContribution.emplace(s);
     }
     if (sz.mLimit == NS_UNCONSTRAINEDSIZE) {
       sz.mLimit = minContentContribution.value();
     } else {
       sz.mLimit = std::max(sz.mLimit, minContentContribution.value());
     }
   } else if (sz.mState & (TrackSize::eAutoMaxSizing |
                           TrackSize::eMaxContentMaxSizing)) {
     if (maxContentContribution.isNothing()) {
-      nscoord s = MaxContentContribution(aGridItem, rs, rc, wm, mAxis);
+      nscoord s = MaxContentContribution(aGridItem, aState, rc, wm, mAxis);
       maxContentContribution.emplace(s);
     }
     if (sz.mLimit == NS_UNCONSTRAINEDSIZE) {
       sz.mLimit = maxContentContribution.value();
     } else {
       sz.mLimit = std::max(sz.mLimit, maxContentContribution.value());
     }
   }
@@ -3919,28 +3947,28 @@ nsGridContainerFrame::Tracks::ResolveInt
           stateBitsPerSpan.SetCapacity(len);
           for (uint32_t i = stateBitsPerSpan.Length(); i < len; ++i) {
             stateBitsPerSpan.AppendElement(TrackSize::StateBits(0));
           }
         }
         stateBitsPerSpan[span] |= state;
         nscoord minSize = 0;
         if (state & (flexMin | TrackSize::eIntrinsicMinSizing)) { // for 2.1
-          minSize = MinSize(gridItem, aState.mReflowState, rc, wm, mAxis);
+          minSize = MinSize(gridItem, aState, rc, wm, mAxis);
         }
         nscoord minContent = 0;
         if (state & (flexMin | TrackSize::eMinOrMaxContentMinSizing | // for 2.2
                      TrackSize::eIntrinsicMaxSizing)) {               // for 2.5
-          minContent = MinContentContribution(gridItem, aState.mReflowState,
+          minContent = MinContentContribution(gridItem, aState,
                                               rc, wm, mAxis);
         }
         nscoord maxContent = 0;
         if (state & (TrackSize::eMaxContentMinSizing |         // for 2.3
                      TrackSize::eAutoOrMaxContentMaxSizing)) { // for 2.6
-          maxContent = MaxContentContribution(gridItem, aState.mReflowState,
+          maxContent = MaxContentContribution(gridItem, aState,
                                               rc, wm, mAxis);
         }
         step2Items.AppendElement(
           Step2ItemData({span, state, lineRange, minSize,
                          minContent, maxContent, *iter}));
       } else if (state & TrackSize::eFlexMaxSizing) {
         gridItem.mState[mAxis] |= ItemState::eIsFlexing;
       }
@@ -4184,25 +4212,24 @@ nsGridContainerFrame::Tracks::FindUsedFl
   for (uint32_t track : aFlexTracks) {
     float flexFactor = aFunctions.MaxSizingFor(track).GetFlexFractionValue();
     if (flexFactor > 0.0f) {
       fr = std::max(fr, mSizes[track].mBase / flexFactor);
     }
   }
   WritingMode wm = aState.mWM;
   nsRenderingContext* rc = &aState.mRenderingContext;
-  const nsHTMLReflowState* rs = aState.mReflowState;
   GridItemCSSOrderIterator& iter = aState.mIter;
   iter.Reset();
   // ... the result of 'finding the size of an fr' for each item that spans
   // a flex track with its max-content contribution as 'space to fill'
   for (; !iter.AtEnd(); iter.Next()) {
     const GridItemInfo& item = aGridItems[iter.GridItemIndex()];
     if (item.mState[mAxis] & ItemState::eIsFlexing) {
-      nscoord spaceToFill = MaxContentContribution(item, rs, rc, wm, mAxis);
+      nscoord spaceToFill = MaxContentContribution(item, aState, rc, wm, mAxis);
       if (spaceToFill <= 0) {
         continue;
       }
       // ... and all its spanned tracks as input.
       const LineRange& range =
         mAxis == eLogicalAxisInline ? item.mArea.mCols : item.mArea.mRows;
       nsTArray<uint32_t> itemFlexTracks;
       for (uint32_t i = range.mStart, end = range.mEnd; i < end; ++i) {
@@ -4248,30 +4275,29 @@ nsGridContainerFrame::Tracks::StretchFle
         base = flexLength;
       }
     }
   }
 }
 
 void
 nsGridContainerFrame::Tracks::AlignJustifyContent(
-  const nsHTMLReflowState& aReflowState,
+  const nsStylePosition* aStyle,
+  WritingMode            aWM,
   const LogicalSize&     aContainerSize)
 {
   if (mSizes.IsEmpty()) {
     return;
   }
 
   const bool isAlign = mAxis == eLogicalAxisBlock;
-  auto stylePos = aReflowState.mStylePosition;
-  auto valueAndFallback = isAlign ? stylePos->ComputedAlignContent() :
-                                    stylePos->ComputedJustifyContent();
-  WritingMode wm = aReflowState.GetWritingMode();
+  auto valueAndFallback = isAlign ? aStyle->ComputedAlignContent() :
+                                    aStyle->ComputedJustifyContent();
   bool overflowSafe;
-  auto alignment = ::GetAlignJustifyValue(valueAndFallback, wm, isAlign,
+  auto alignment = ::GetAlignJustifyValue(valueAndFallback, aWM, isAlign,
                                           &overflowSafe);
   if (alignment == NS_STYLE_ALIGN_NORMAL) {
     MOZ_ASSERT(valueAndFallback == NS_STYLE_ALIGN_NORMAL,
                "*-content:normal cannot be specified with explicit fallback");
     alignment = NS_STYLE_ALIGN_STRETCH;
     valueAndFallback = alignment; // we may need a fallback for 'stretch' below
   }
 
@@ -4281,23 +4307,23 @@ nsGridContainerFrame::Tracks::AlignJusti
   if (alignment != NS_STYLE_ALIGN_START) {
     nscoord trackSizeSum = 0;
     for (const TrackSize& sz : mSizes) {
       trackSizeSum += sz.mBase;
       if (sz.mState & TrackSize::eAutoMaxSizing) {
         ++numAutoTracks;
       }
     }
-    nscoord cbSize = isAlign ? aContainerSize.BSize(wm)
-                             : aContainerSize.ISize(wm);
+    nscoord cbSize = isAlign ? aContainerSize.BSize(aWM)
+                             : aContainerSize.ISize(aWM);
     space = cbSize - trackSizeSum - SumOfGridGaps();
     // Use the fallback value instead when applicable.
     if (space < 0 ||
         (alignment == NS_STYLE_ALIGN_SPACE_BETWEEN && mSizes.Length() == 1)) {
-      auto fallback = ::GetAlignJustifyFallbackIfAny(valueAndFallback, wm,
+      auto fallback = ::GetAlignJustifyFallbackIfAny(valueAndFallback, aWM,
                                                      isAlign, &overflowSafe);
       if (fallback) {
         alignment = fallback;
       }
     }
     if (space == 0 || (space < 0 && overflowSafe)) {
       // XXX check that this makes sense also for [last-]baseline (bug 1151204).
       alignment = NS_STYLE_ALIGN_START;
@@ -5538,18 +5564,18 @@ nsGridContainerFrame::Reflow(nsPresConte
   }
   bSize = std::max(bSize - consumedBSize, 0);
   auto& bp = gridReflowState.mBorderPadding;
   LogicalRect contentArea(wm, bp.IStart(wm), bp.BStart(wm),
                           computedISize, bSize);
 
   if (!prevInFlow) {
     // Apply 'align/justify-content' to the grid.
-    gridReflowState.mCols.AlignJustifyContent(aReflowState, contentArea.Size(wm));
-    gridReflowState.mRows.AlignJustifyContent(aReflowState, contentArea.Size(wm));
+    // CalculateTrackSizes did the columns.
+    gridReflowState.mRows.AlignJustifyContent(stylePos, wm, contentArea.Size(wm));
   }
 
   bSize = ReflowChildren(gridReflowState, contentArea, aDesiredSize, aStatus);
   bSize = std::max(bSize - consumedBSize, 0);
 
   // Skip our block-end border if we're INCOMPLETE.
   if (!NS_FRAME_IS_COMPLETE(aStatus) &&
       !gridReflowState.mSkipSides.BEnd() &&
--- a/layout/generic/nsGridContainerFrame.h
+++ b/layout/generic/nsGridContainerFrame.h
@@ -102,31 +102,31 @@ public:
   NS_DECLARE_FRAME_PROPERTY_DELETABLE(GridRowTrackInfo, ComputedGridTrackInfo)
   const ComputedGridTrackInfo* GetComputedTemplateRows()
   {
     return Properties().Get(GridRowTrackInfo());
   }
 
   struct TrackSize;
   struct GridItemInfo;
+  struct GridReflowState;
 protected:
   static const uint32_t kAutoLine;
   // The maximum line number, in the zero-based translated grid.
   static const uint32_t kTranslatedMaxLine;
   typedef mozilla::LogicalPoint LogicalPoint;
   typedef mozilla::LogicalRect LogicalRect;
   typedef mozilla::LogicalSize LogicalSize;
   typedef mozilla::WritingMode WritingMode;
   typedef mozilla::css::GridNamedArea GridNamedArea;
   typedef mozilla::layout::AutoFrameListPtr AutoFrameListPtr;
   typedef nsLayoutUtils::IntrinsicISizeType IntrinsicISizeType;
   struct Grid;
   struct GridArea;
   class GridItemCSSOrderIterator;
-  struct GridReflowState;
   class LineNameMap;
   struct LineRange;
   struct SharedGridData;
   struct TrackSizingFunctions;
   struct Tracks;
   struct TranslatedLineRange;
   friend nsContainerFrame* NS_NewGridContainerFrame(nsIPresShell* aPresShell,
                                                     nsStyleContext* aContext);
--- a/layout/generic/nsTextFrame.cpp
+++ b/layout/generic/nsTextFrame.cpp
@@ -5513,59 +5513,65 @@ nsTextFrame::DrawSelectionDecorations(gf
                                       bool aVertical,
                                       gfxFloat aDecorationOffsetDir,
                                       uint8_t aDecoration)
 {
   PaintDecorationLineParams params;
   params.context = aContext;
   params.dirtyRect = aDirtyRect;
   params.pt = aPt;
-  params.lineSize = Size(
-      aWidth, ComputeSelectionUnderlineHeight(aTextPaintStyle.PresContext(),
-                                              aFontMetrics, aSelectionType));
+  params.lineSize.width = aWidth;
   params.ascent = aAscent;
   params.offset = aDecoration == NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE ?
                   aFontMetrics.underlineOffset : aFontMetrics.maxAscent;
   params.decoration = aDecoration;
   params.decorationType = DecorationType::Selection;
   params.callbacks = aCallbacks;
   params.vertical = aVertical;
   params.descentLimit =
     ComputeDescentLimitForSelectionUnderline(aTextPaintStyle.PresContext(),
                                              aFontMetrics);
 
   float relativeSize;
-  int32_t index =
-    nsTextPaintStyle::GetUnderlineStyleIndexForSelectionType(aSelectionType);
-  bool weDefineSelectionUnderline =
-    aTextPaintStyle.GetSelectionUnderlineForPaint(index, &params.color,
-                                                  &relativeSize, &params.style);
-
 
   switch (aSelectionType) {
     case SelectionType::eIMERawClause:
     case SelectionType::eIMESelectedRawClause:
     case SelectionType::eIMEConvertedClause:
-    case SelectionType::eIMESelectedClause: {
-      // IME decoration lines should not be drawn on the both ends, i.e., we
-      // need to cut both edges of the decoration lines.  Because same style
-      // IME selections can adjoin, but the users need to be able to know
-      // where are the boundaries of the selections.
-      //
-      //  X: underline
-      //
-      //     IME selection #1        IME selection #2      IME selection #3
-      //  |                     |                      |                    
-      //  | XXXXXXXXXXXXXXXXXXX | XXXXXXXXXXXXXXXXXXXX | XXXXXXXXXXXXXXXXXXX
-      //  +---------------------+----------------------+--------------------
-      //   ^                   ^ ^                    ^ ^
-      //  gap                  gap                    gap
-      params.pt.x += 1.0;
-      params.lineSize.width -= 2.0;
-      if (aRangeStyle.IsDefined()) {
+    case SelectionType::eIMESelectedClause:
+    case SelectionType::eSpellCheck: {
+      int32_t index = nsTextPaintStyle::
+        GetUnderlineStyleIndexForSelectionType(aSelectionType);
+      bool weDefineSelectionUnderline =
+        aTextPaintStyle.GetSelectionUnderlineForPaint(index, &params.color,
+                                                      &relativeSize,
+                                                      &params.style);
+      params.lineSize.height =
+        ComputeSelectionUnderlineHeight(aTextPaintStyle.PresContext(),
+                                        aFontMetrics, aSelectionType);
+      bool isIMEType = aSelectionType != SelectionType::eSpellCheck;
+
+      if (isIMEType) {
+        // IME decoration lines should not be drawn on the both ends, i.e., we
+        // need to cut both edges of the decoration lines.  Because same style
+        // IME selections can adjoin, but the users need to be able to know
+        // where are the boundaries of the selections.
+        //
+        //  X: underline
+        //
+        //     IME selection #1        IME selection #2      IME selection #3
+        //  |                     |                      |                    
+        //  | XXXXXXXXXXXXXXXXXXX | XXXXXXXXXXXXXXXXXXXX | XXXXXXXXXXXXXXXXXXX
+        //  +---------------------+----------------------+--------------------
+        //   ^                   ^ ^                    ^ ^
+        //  gap                  gap                    gap
+        params.pt.x += 1.0;
+        params.lineSize.width -= 2.0;
+      }
+      if (isIMEType && aRangeStyle.IsDefined()) {
         // If IME defines the style, that should override our definition.
         if (aRangeStyle.IsLineStyleDefined()) {
           if (aRangeStyle.mLineStyle == TextRangeStyle::LINESTYLE_NONE) {
             return;
           }
           params.style = aRangeStyle.mLineStyle;
           relativeSize = aRangeStyle.mIsBoldLine ? 2.0f : 1.0f;
         } else if (!weDefineSelectionUnderline) {
@@ -5595,29 +5601,28 @@ nsTextFrame::DrawSelectionDecorations(gf
         }
       } else if (!weDefineSelectionUnderline) {
         // IME doesn't specify the selection style and we don't define selection
         // underline.
         return;
       }
       break;
     }
-    case SelectionType::eSpellCheck:
-      if (!weDefineSelectionUnderline)
-        return;
-      break;
     case SelectionType::eURLStrikeout: {
       nscoord inflationMinFontSize =
         nsLayoutUtils::InflationMinFontSizeFor(this);
       float inflation =
         GetInflationForTextDecorations(this, inflationMinFontSize);
       const gfxFont::Metrics metrics =
         GetFirstFontMetrics(GetFontGroupForFrame(this, inflation), aVertical);
 
       relativeSize = 2.0f;
+      aTextPaintStyle.GetURLSecondaryColor(&params.color);
+      params.style = NS_STYLE_TEXT_DECORATION_STYLE_SOLID;
+      params.lineSize.height = metrics.strikeoutSize;
       params.offset = metrics.strikeoutOffset + 0.5;
       params.decoration = NS_STYLE_TEXT_DECORATION_LINE_LINE_THROUGH;
       break;
     }
     default:
       NS_WARNING("Requested selection decorations when there aren't any");
       return;
   }
@@ -7071,17 +7076,19 @@ nsTextFrame::CombineSelectionUnderlineRe
   params.offset = fontGroup->GetUnderlineOffset();
   params.descentLimit =
     ComputeDescentLimitForSelectionUnderline(aPresContext, metrics);
   params.vertical = verticalRun;
 
   SelectionDetails *details = GetSelectionDetails();
   for (SelectionDetails *sd = details; sd; sd = sd->mNext) {
     if (sd->mStart == sd->mEnd ||
-        !(sd->mSelectionType & kRawSelectionTypesWithDecorations)) {
+        !(sd->mSelectionType & kRawSelectionTypesWithDecorations) ||
+        // URL strikeout does not use underline.
+        sd->mSelectionType == SelectionType::eURLStrikeout) {
       continue;
     }
 
     float relativeSize;
     int32_t index =
       nsTextPaintStyle::GetUnderlineStyleIndexForSelectionType(
         sd->mSelectionType);
     if (sd->mSelectionType == SelectionType::eSpellCheck) {
--- a/layout/inspector/inDOMView.cpp
+++ b/layout/inspector/inDOMView.cpp
@@ -1257,28 +1257,28 @@ inDOMView::AppendKidsToArray(nsIDOMNodeL
         NS_ASSERTION(data, "Does not implement nsIDOMCharacterData!");
         bool ignore;
         mDOMUtils->IsIgnorableWhitespace(data, &ignore);
         if (ignore) {
           continue;
         }
       }
 
-      aArray.AppendObject(kid);
+      aArray.AppendElement(kid.forget());
     }
   }
 
   return NS_OK;
 }
 
 nsresult
 inDOMView::AppendAttrsToArray(nsIDOMMozNamedAttrMap* aAttributes,
                               nsCOMArray<nsIDOMNode>& aArray)
 {
   uint32_t l = 0;
   aAttributes->GetLength(&l);
   nsCOMPtr<nsIDOMAttr> attribute;
   for (uint32_t i = 0; i < l; ++i) {
     aAttributes->Item(i, getter_AddRefs(attribute));
-    aArray.AppendObject(attribute);
+    aArray.AppendElement(attribute.forget());
   }
   return NS_OK;
 }
--- a/layout/style/nsStyleContext.cpp
+++ b/layout/style/nsStyleContext.cpp
@@ -891,17 +891,17 @@ nsStyleContext::ApplyStyleFixups(bool aS
   }
 
   // Compute User Interface style, to trigger loads of cursors
   StyleUserInterface();
 #undef GET_UNIQUE_STYLE_DATA
 }
 
 nsChangeHint
-nsStyleContext::CalcStyleDifference(nsStyleContext* aOther,
+nsStyleContext::CalcStyleDifference(nsStyleContext* aNewContext,
                                     nsChangeHint aParentHintsNotHandledForDescendants,
                                     uint32_t* aEqualStructs,
                                     uint32_t* aSamePointerStructs)
 {
   PROFILER_LABEL("nsStyleContext", "CalcStyleDifference",
     js::ProfileEntry::Category::CSS);
 
   MOZ_ASSERT(NS_IsHintSubset(aParentHintsNotHandledForDescendants,
@@ -909,17 +909,17 @@ nsStyleContext::CalcStyleDifference(nsSt
              "caller is passing inherited hints, but shouldn't be");
 
   static_assert(nsStyleStructID_Length <= 32,
                 "aEqualStructs is not big enough");
 
   *aEqualStructs = 0;
 
   nsChangeHint hint = NS_STYLE_HINT_NONE;
-  NS_ENSURE_TRUE(aOther, hint);
+  NS_ENSURE_TRUE(aNewContext, hint);
   // We must always ensure that we populate the structs on the new style
   // context that are filled in on the old context, so that if we get
   // two style changes in succession, the second of which causes a real
   // style change, the PeekStyleData doesn't return null (implying that
   // nobody ever looked at that struct's data).  In other words, we
   // can't skip later structs if we get a big change up front, because
   // we could later get a small change in one of those structs that we
   // don't want to miss.
@@ -932,44 +932,44 @@ nsStyleContext::CalcStyleDifference(nsSt
   // the rule node tree (if applicable) is also the same.
   // However, if there were noninherited style change hints on the
   // parent, we might produce these same noninherited hints on this
   // style context's frame due to 'inherit' values, so we do need to
   // compare.
   // (Things like 'em' units are handled by the change hint produced
   // by font-size changing, so we don't need to worry about them like
   // we worry about 'inherit' values.)
-  bool compare = mSource != aOther->mSource;
+  bool compare = mSource != aNewContext->mSource;
 
   DebugOnly<uint32_t> structsFound = 0;
 
   // If we had any change in variable values, then we'll need to examine
   // all of the other style structs too, even if the new style context has
   // the same source as the old one.
   const nsStyleVariables* thisVariables = PeekStyleVariables();
   if (thisVariables) {
     structsFound |= NS_STYLE_INHERIT_BIT(Variables);
-    const nsStyleVariables* otherVariables = aOther->StyleVariables();
+    const nsStyleVariables* otherVariables = aNewContext->StyleVariables();
     if (thisVariables->mVariables == otherVariables->mVariables) {
       *aEqualStructs |= NS_STYLE_INHERIT_BIT(Variables);
     } else {
       compare = true;
     }
   } else {
     *aEqualStructs |= NS_STYLE_INHERIT_BIT(Variables);
   }
 
   DebugOnly<int> styleStructCount = 1;  // count Variables already
 
 #define DO_STRUCT_DIFFERENCE(struct_)                                         \
   PR_BEGIN_MACRO                                                              \
     const nsStyle##struct_* this##struct_ = PeekStyle##struct_();             \
     if (this##struct_) {                                                      \
       structsFound |= NS_STYLE_INHERIT_BIT(struct_);                          \
-      const nsStyle##struct_* other##struct_ = aOther->Style##struct_();      \
+      const nsStyle##struct_* other##struct_ = aNewContext->Style##struct_(); \
       nsChangeHint maxDifference = nsStyle##struct_::MaxDifference();         \
       nsChangeHint differenceAlwaysHandledForDescendants =                    \
         nsStyle##struct_::DifferenceAlwaysHandledForDescendants();            \
       if (this##struct_ == other##struct_) {                                  \
         /* The very same struct, so we know that there will be no */          \
         /* differences.                                           */          \
         *aEqualStructs |= NS_STYLE_INHERIT_BIT(struct_);                      \
       } else if (compare ||                                                   \
@@ -1060,41 +1060,41 @@ nsStyleContext::CalcStyleDifference(nsSt
   // struct.)  This is important for callers in RestyleManager that
   // need to know the equality or not of the final set of cached struct
   // pointers.
   *aSamePointerStructs = 0;
 
 #define STYLE_STRUCT(name_, callback_)                                        \
   {                                                                           \
     const nsStyle##name_* data = PeekStyle##name_();                          \
-    if (!data || data == aOther->Style##name_()) {                            \
+    if (!data || data == aNewContext->Style##name_()) {                       \
       *aSamePointerStructs |= NS_STYLE_INHERIT_BIT(name_);                    \
     }                                                                         \
   }
 #include "nsStyleStructList.h"
 #undef STYLE_STRUCT
 
   // Note that we do not check whether this->RelevantLinkVisited() !=
-  // aOther->RelevantLinkVisited(); we don't need to since
+  // aNewContext->RelevantLinkVisited(); we don't need to since
   // nsCSSFrameConstructor::DoContentStateChanged always adds
   // nsChangeHint_RepaintFrame for NS_EVENT_STATE_VISITED changes (and
   // needs to, since HasStateDependentStyle probably doesn't work right
   // for NS_EVENT_STATE_VISITED).  Hopefully this doesn't actually
   // expose whether links are visited to performance tests since all
   // link coloring happens asynchronously at a time when it's hard for
   // the page to measure.
   // However, we do need to compute the larger of the changes that can
   // happen depending on whether the link is visited or unvisited, since
   // doing only the one that's currently appropriate would expose which
   // links are in history to easy performance measurement.  Therefore,
   // here, we add nsChangeHint_RepaintFrame hints (the maximum for
   // things that can depend on :visited) for the properties on which we
   // call GetVisitedDependentColor.
   nsStyleContext *thisVis = GetStyleIfVisited(),
-                *otherVis = aOther->GetStyleIfVisited();
+                *otherVis = aNewContext->GetStyleIfVisited();
   if (!thisVis != !otherVis) {
     // One style context has a style-if-visited and the other doesn't.
     // Presume a difference.
     hint |= nsChangeHint_RepaintFrame;
   } else if (thisVis && !NS_IsHintSubset(nsChangeHint_RepaintFrame, hint)) {
     // Both style contexts have a style-if-visited.
     bool change = false;
 
--- a/layout/style/nsStyleContext.h
+++ b/layout/style/nsStyleContext.h
@@ -371,34 +371,34 @@ public:
     const nsStyle##name_ * PeekStyle##name_() {           \
       return DoGetStyle##name_<false>();                  \
     }
   #include "nsStyleStructList.h"
   #undef STYLE_STRUCT
 
   /**
    * Compute the style changes needed during restyling when this style
-   * context is being replaced by aOther.  (This is nonsymmetric since
+   * context is being replaced by aNewContext.  (This is nonsymmetric since
    * we optimize by skipping comparison for styles that have never been
    * requested.)
    *
    * This method returns a change hint (see nsChangeHint.h).  All change
    * hints apply to the frame and its later continuations or ib-split
    * siblings.  Most (all of those except the "NotHandledForDescendants"
    * hints) also apply to all descendants.  The caller must pass in any
    * non-inherited hints that resulted from the parent style context's
    * style change.  The caller *may* pass more hints than needed, but
    * must not pass less than needed; therefore if the caller doesn't
    * know, the caller should pass
    * nsChangeHint_Hints_NotHandledForDescendants.
    *
    * aEqualStructs must not be null.  Into it will be stored a bitfield
    * representing which structs were compared to be non-equal.
    */
-  nsChangeHint CalcStyleDifference(nsStyleContext* aOther,
+  nsChangeHint CalcStyleDifference(nsStyleContext* aNewContext,
                                    nsChangeHint aParentHintsNotHandledForDescendants,
                                    uint32_t* aEqualStructs,
                                    uint32_t* aSamePointerStructs);
 
   /**
    * Get a color that depends on link-visitedness using this and
    * this->GetStyleIfVisited().
    *
--- a/layout/style/nsStyleStruct.cpp
+++ b/layout/style/nsStyleStruct.cpp
@@ -179,36 +179,36 @@ nsStyleFont::EnableZoom(nsPresContext* a
     mSize = nsStyleFont::UnZoomText(aContext, mSize);
     mFont.size = nsStyleFont::UnZoomText(aContext, mFont.size);
     mScriptUnconstrainedSize =
       nsStyleFont::UnZoomText(aContext, mScriptUnconstrainedSize);
   }
 }
 
 nsChangeHint
-nsStyleFont::CalcDifference(const nsStyleFont& aOther) const
+nsStyleFont::CalcDifference(const nsStyleFont& aNewData) const
 {
-  MOZ_ASSERT(mAllowZoom == aOther.mAllowZoom,
+  MOZ_ASSERT(mAllowZoom == aNewData.mAllowZoom,
              "expected mAllowZoom to be the same on both nsStyleFonts");
-  if (mSize != aOther.mSize ||
-      mFont != aOther.mFont ||
-      mLanguage != aOther.mLanguage ||
-      mExplicitLanguage != aOther.mExplicitLanguage ||
-      mMathVariant != aOther.mMathVariant ||
-      mMathDisplay != aOther.mMathDisplay ||
-      mMinFontSizeRatio != aOther.mMinFontSizeRatio) {
+  if (mSize != aNewData.mSize ||
+      mFont != aNewData.mFont ||
+      mLanguage != aNewData.mLanguage ||
+      mExplicitLanguage != aNewData.mExplicitLanguage ||
+      mMathVariant != aNewData.mMathVariant ||
+      mMathDisplay != aNewData.mMathDisplay ||
+      mMinFontSizeRatio != aNewData.mMinFontSizeRatio) {
     return NS_STYLE_HINT_REFLOW;
   }
 
   // XXX Should any of these cause a non-nsChangeHint_NeutralChange change?
-  if (mGenericID != aOther.mGenericID ||
-      mScriptLevel != aOther.mScriptLevel ||
-      mScriptUnconstrainedSize != aOther.mScriptUnconstrainedSize ||
-      mScriptMinSize != aOther.mScriptMinSize ||
-      mScriptSizeMultiplier != aOther.mScriptSizeMultiplier) {
+  if (mGenericID != aNewData.mGenericID ||
+      mScriptLevel != aNewData.mScriptLevel ||
+      mScriptUnconstrainedSize != aNewData.mScriptUnconstrainedSize ||
+      mScriptMinSize != aNewData.mScriptMinSize ||
+      mScriptSizeMultiplier != aNewData.mScriptSizeMultiplier) {
     return nsChangeHint_NeutralChange;
   }
 
   return NS_STYLE_HINT_NONE;
 }
 
 /* static */ nscoord
 nsStyleFont::ZoomText(StyleStructContext aContext, nscoord aSize)
@@ -275,19 +275,19 @@ nsStyleMargin::nsStyleMargin(const nsSty
 void 
 nsStyleMargin::Destroy(nsPresContext* aContext) {
   this->~nsStyleMargin();
   aContext->PresShell()->
     FreeByObjectID(eArenaObjectID_nsStyleMargin, this);
 }
 
 nsChangeHint
-nsStyleMargin::CalcDifference(const nsStyleMargin& aOther) const
+nsStyleMargin::CalcDifference(const nsStyleMargin& aNewData) const
 {
-  if (mMargin == aOther.mMargin) {
+  if (mMargin == aNewData.mMargin) {
     return NS_STYLE_HINT_NONE;
   }
   // Margin differences can't affect descendant intrinsic sizes and
   // don't need to force children to reflow.
   return nsChangeHint_NeedReflow |
          nsChangeHint_ReflowChangesSizeOrPosition |
          nsChangeHint_ClearAncestorIntrinsics;
 }
@@ -310,19 +310,19 @@ nsStylePadding::nsStylePadding(const nsS
 void 
 nsStylePadding::Destroy(nsPresContext* aContext) {
   this->~nsStylePadding();
   aContext->PresShell()->
     FreeByObjectID(eArenaObjectID_nsStylePadding, this);
 }
 
 nsChangeHint
-nsStylePadding::CalcDifference(const nsStylePadding& aOther) const
+nsStylePadding::CalcDifference(const nsStylePadding& aNewData) const
 {
-  if (mPadding == aOther.mPadding) {
+  if (mPadding == aNewData.mPadding) {
     return NS_STYLE_HINT_NONE;
   }
   // Padding differences can't affect descendant intrinsic sizes, but do need
   // to force children to reflow so that we can reposition them, since their
   // offsets are from our frame bounds but our content rect's position within
   // those bounds is moving.
   return NS_STYLE_HINT_REFLOW & ~nsChangeHint_ClearDescendantIntrinsics;
 }
@@ -446,79 +446,79 @@ void
 nsStyleBorder::Destroy(nsPresContext* aContext) {
   UntrackImage(aContext);
   this->~nsStyleBorder();
   aContext->PresShell()->
     FreeByObjectID(eArenaObjectID_nsStyleBorder, this);
 }
 
 nsChangeHint
-nsStyleBorder::CalcDifference(const nsStyleBorder& aOther) const
+nsStyleBorder::CalcDifference(const nsStyleBorder& aNewData) const
 {
   // XXXbz we should be able to return a more specific change hint for
   // at least GetComputedBorder() differences...
-  if (mTwipsPerPixel != aOther.mTwipsPerPixel ||
-      GetComputedBorder() != aOther.GetComputedBorder() ||
-      mFloatEdge != aOther.mFloatEdge ||
-      mBorderImageOutset != aOther.mBorderImageOutset ||
-      mBoxDecorationBreak != aOther.mBoxDecorationBreak)
+  if (mTwipsPerPixel != aNewData.mTwipsPerPixel ||
+      GetComputedBorder() != aNewData.GetComputedBorder() ||
+      mFloatEdge != aNewData.mFloatEdge ||
+      mBorderImageOutset != aNewData.mBorderImageOutset ||
+      mBoxDecorationBreak != aNewData.mBoxDecorationBreak)
     return NS_STYLE_HINT_REFLOW;
 
   NS_FOR_CSS_SIDES(ix) {
     // See the explanation in nsChangeHint.h of
     // nsChangeHint_BorderStyleNoneChange .
     // Furthermore, even though we know *this* side is 0 width, just
     // assume a repaint hint for some other change rather than bother
     // tracking this result through the rest of the function.
-    if (HasVisibleStyle(ix) != aOther.HasVisibleStyle(ix)) {
+    if (HasVisibleStyle(ix) != aNewData.HasVisibleStyle(ix)) {
       return nsChangeHint_RepaintFrame |
              nsChangeHint_BorderStyleNoneChange;
     }
   }
 
   // Note that mBorderStyle stores not only the border style but also
   // color-related flags.  Given that we've already done an mComputedBorder
   // comparison, border-style differences can only lead to a repaint hint.  So
   // it's OK to just compare the values directly -- if either the actual
   // style or the color flags differ we want to repaint.
   NS_FOR_CSS_SIDES(ix) {
-    if (mBorderStyle[ix] != aOther.mBorderStyle[ix] || 
-        mBorderColor[ix] != aOther.mBorderColor[ix])
+    if (mBorderStyle[ix] != aNewData.mBorderStyle[ix] ||
+        mBorderColor[ix] != aNewData.mBorderColor[ix])
       return nsChangeHint_RepaintFrame;
   }
 
-  if (mBorderRadius != aOther.mBorderRadius ||
-      !mBorderColors != !aOther.mBorderColors)
+  if (mBorderRadius != aNewData.mBorderRadius ||
+      !mBorderColors != !aNewData.mBorderColors)
     return nsChangeHint_RepaintFrame;
 
-  if (IsBorderImageLoaded() || aOther.IsBorderImageLoaded()) {
-    if (mBorderImageSource  != aOther.mBorderImageSource  ||
-        mBorderImageRepeatH != aOther.mBorderImageRepeatH ||
-        mBorderImageRepeatV != aOther.mBorderImageRepeatV ||
-        mBorderImageSlice   != aOther.mBorderImageSlice   ||
-        mBorderImageFill    != aOther.mBorderImageFill    ||
-        mBorderImageWidth   != aOther.mBorderImageWidth   ||
-        mBorderImageOutset  != aOther.mBorderImageOutset)
+  if (IsBorderImageLoaded() || aNewData.IsBorderImageLoaded()) {
+    if (mBorderImageSource  != aNewData.mBorderImageSource  ||
+        mBorderImageRepeatH != aNewData.mBorderImageRepeatH ||
+        mBorderImageRepeatV != aNewData.mBorderImageRepeatV ||
+        mBorderImageSlice   != aNewData.mBorderImageSlice   ||
+        mBorderImageFill    != aNewData.mBorderImageFill    ||
+        mBorderImageWidth   != aNewData.mBorderImageWidth   ||
+        mBorderImageOutset  != aNewData.mBorderImageOutset)
       return nsChangeHint_RepaintFrame;
   }
 
   // Note that at this point if mBorderColors is non-null so is
-  // aOther.mBorderColors
+  // aNewData.mBorderColors
   if (mBorderColors) {
     NS_FOR_CSS_SIDES(ix) {
       if (!nsBorderColors::Equal(mBorderColors[ix],
-                                 aOther.mBorderColors[ix]))
+                                 aNewData.mBorderColors[ix]))
         return nsChangeHint_RepaintFrame;
     }
   }
 
   // mBorder is the specified border value.  Changes to this don't
   // need any change processing, since we operate on the computed
   // border values instead.
-  if (mBorder != aOther.mBorder) {
+  if (mBorder != aNewData.mBorder) {
     return nsChangeHint_NeutralChange;
   }
 
   return NS_STYLE_HINT_NONE;
 }
 
 nsStyleOutline::nsStyleOutline(StyleStructContext aContext)
   : mOutlineWidth(NS_STYLE_BORDER_WIDTH_MEDIUM, eStyleUnit_Enumerated)
@@ -563,37 +563,37 @@ nsStyleOutline::RecalcData()
       std::max(CalcCoord(mOutlineWidth,
                          StaticPresData::Get()->GetBorderWidthTable(), 3), 0);
     mActualOutlineWidth =
       NS_ROUND_BORDER_TO_PIXELS(mActualOutlineWidth, mTwipsPerPixel);
   }
 }
 
 nsChangeHint
-nsStyleOutline::CalcDifference(const nsStyleOutline& aOther) const
+nsStyleOutline::CalcDifference(const nsStyleOutline& aNewData) const
 {
-  if (mActualOutlineWidth != aOther.mActualOutlineWidth ||
+  if (mActualOutlineWidth != aNewData.mActualOutlineWidth ||
       (mActualOutlineWidth > 0 &&
-       mOutlineOffset != aOther.mOutlineOffset)) {
+       mOutlineOffset != aNewData.mOutlineOffset)) {
     return nsChangeHint_UpdateOverflow |
            nsChangeHint_SchedulePaint;
   }
 
-  if (mOutlineStyle != aOther.mOutlineStyle ||
-      mOutlineColor != aOther.mOutlineColor ||
-      mOutlineRadius != aOther.mOutlineRadius) {
+  if (mOutlineStyle != aNewData.mOutlineStyle ||
+      mOutlineColor != aNewData.mOutlineColor ||
+      mOutlineRadius != aNewData.mOutlineRadius) {
     if (mActualOutlineWidth > 0) {
       return nsChangeHint_RepaintFrame;
     }
     return nsChangeHint_NeutralChange;
   }
 
-  if (mOutlineWidth != aOther.mOutlineWidth ||
-      mOutlineOffset != aOther.mOutlineOffset ||
-      mTwipsPerPixel != aOther.mTwipsPerPixel) {
+  if (mOutlineWidth != aNewData.mOutlineWidth ||
+      mOutlineOffset != aNewData.mOutlineOffset ||
+      mTwipsPerPixel != aNewData.mTwipsPerPixel) {
     return nsChangeHint_NeutralChange;
   }
 
   return NS_STYLE_HINT_NONE;
 }
 
 // --------------------
 // nsStyleList
@@ -668,34 +668,34 @@ nsStyleList::SetQuotes(nsStyleQuoteValue
 
 const nsStyleQuoteValues::QuotePairArray&
 nsStyleList::GetQuotePairs() const
 {
   return mQuotes->mQuotePairs;
 }
 
 nsChangeHint
-nsStyleList::CalcDifference(const nsStyleList& aOther) const
+nsStyleList::CalcDifference(const nsStyleList& aNewData) const
 {
   // If the quotes implementation is ever going to change we might not need
   // a framechange here and a reflow should be sufficient.  See bug 35768.
-  if (mQuotes != aOther.mQuotes &&
-      (mQuotes || aOther.mQuotes) &&
-      GetQuotePairs() != aOther.GetQuotePairs()) {
+  if (mQuotes != aNewData.mQuotes &&
+      (mQuotes || aNewData.mQuotes) &&
+      GetQuotePairs() != aNewData.GetQuotePairs()) {
     return NS_STYLE_HINT_FRAMECHANGE;
   }
-  if (mListStylePosition != aOther.mListStylePosition)
+  if (mListStylePosition != aNewData.mListStylePosition)
     return NS_STYLE_HINT_FRAMECHANGE;
-  if (EqualImages(mListStyleImage, aOther.mListStyleImage) &&
-      mCounterStyle == aOther.mCounterStyle) {
-    if (mImageRegion.IsEqualInterior(aOther.mImageRegion)) {
+  if (EqualImages(mListStyleImage, aNewData.mListStyleImage) &&
+      mCounterStyle == aNewData.mCounterStyle) {
+    if (mImageRegion.IsEqualInterior(aNewData.mImageRegion)) {
       return NS_STYLE_HINT_NONE;
     }
-    if (mImageRegion.width == aOther.mImageRegion.width &&
-        mImageRegion.height == aOther.mImageRegion.height)
+    if (mImageRegion.width == aNewData.mImageRegion.width &&
+        mImageRegion.height == aNewData.mImageRegion.height)
       return NS_STYLE_HINT_VISUAL;
   }
   return NS_STYLE_HINT_REFLOW;
 }
 
 StaticRefPtr<nsStyleQuoteValues>
 nsStyleList::sInitialQuotes;
 
@@ -731,27 +731,27 @@ nsStyleXUL::nsStyleXUL(const nsStyleXUL&
   , mBoxOrient(aSource.mBoxOrient)
   , mBoxPack(aSource.mBoxPack)
   , mStretchStack(aSource.mStretchStack)
 {
   MOZ_COUNT_CTOR(nsStyleXUL);
 }
 
 nsChangeHint
-nsStyleXUL::CalcDifference(const nsStyleXUL& aOther) const
+nsStyleXUL::CalcDifference(const nsStyleXUL& aNewData) const
 {
-  if (mBoxAlign == aOther.mBoxAlign &&
-      mBoxDirection == aOther.mBoxDirection &&
-      mBoxFlex == aOther.mBoxFlex &&
-      mBoxOrient == aOther.mBoxOrient &&
-      mBoxPack == aOther.mBoxPack &&
-      mBoxOrdinal == aOther.mBoxOrdinal &&
-      mStretchStack == aOther.mStretchStack)
+  if (mBoxAlign == aNewData.mBoxAlign &&
+      mBoxDirection == aNewData.mBoxDirection &&
+      mBoxFlex == aNewData.mBoxFlex &&
+      mBoxOrient == aNewData.mBoxOrient &&
+      mBoxPack == aNewData.mBoxPack &&
+      mBoxOrdinal == aNewData.mBoxOrdinal &&
+      mStretchStack == aNewData.mStretchStack)
     return NS_STYLE_HINT_NONE;
-  if (mBoxOrdinal != aOther.mBoxOrdinal)
+  if (mBoxOrdinal != aNewData.mBoxOrdinal)
     return NS_STYLE_HINT_FRAMECHANGE;
   return NS_STYLE_HINT_REFLOW;
 }
 
 // --------------------
 // nsStyleColumn
 //
 /* static */ const uint32_t nsStyleColumn::kMaxColumnCount = 1000;
@@ -786,41 +786,41 @@ nsStyleColumn::nsStyleColumn(const nsSty
   , mColumnRuleColorIsForeground(aSource.mColumnRuleColorIsForeground)
   , mColumnRuleWidth(aSource.mColumnRuleWidth)
   , mTwipsPerPixel(aSource.mTwipsPerPixel)
 {
   MOZ_COUNT_CTOR(nsStyleColumn);
 }
 
 nsChangeHint
-nsStyleColumn::CalcDifference(const nsStyleColumn& aOther) const
+nsStyleColumn::CalcDifference(const nsStyleColumn& aNewData) const
 {
   if ((mColumnWidth.GetUnit() == eStyleUnit_Auto)
-      != (aOther.mColumnWidth.GetUnit() == eStyleUnit_Auto) ||
-      mColumnCount != aOther.mColumnCount)
+      != (aNewData.mColumnWidth.GetUnit() == eStyleUnit_Auto) ||
+      mColumnCount != aNewData.mColumnCount)
     // We force column count changes to do a reframe, because it's tricky to handle
     // some edge cases where the column count gets smaller and content overflows.
     // XXX not ideal
     return NS_STYLE_HINT_FRAMECHANGE;
 
-  if (mColumnWidth != aOther.mColumnWidth ||
-      mColumnGap != aOther.mColumnGap ||
-      mColumnFill != aOther.mColumnFill)
+  if (mColumnWidth != aNewData.mColumnWidth ||
+      mColumnGap != aNewData.mColumnGap ||
+      mColumnFill != aNewData.mColumnFill)
     return NS_STYLE_HINT_REFLOW;
 
-  if (GetComputedColumnRuleWidth() != aOther.GetComputedColumnRuleWidth() ||
-      mColumnRuleStyle != aOther.mColumnRuleStyle ||
-      mColumnRuleColor != aOther.mColumnRuleColor ||
-      mColumnRuleColorIsForeground != aOther.mColumnRuleColorIsForeground)
+  if (GetComputedColumnRuleWidth() != aNewData.GetComputedColumnRuleWidth() ||
+      mColumnRuleStyle != aNewData.mColumnRuleStyle ||
+      mColumnRuleColor != aNewData.mColumnRuleColor ||
+      mColumnRuleColorIsForeground != aNewData.mColumnRuleColorIsForeground)
     return NS_STYLE_HINT_VISUAL;
 
   // XXX Is it right that we never check mTwipsPerPixel to return a
   // non-nsChangeHint_NeutralChange hint?
-  if (mColumnRuleWidth != aOther.mColumnRuleWidth ||
-      mTwipsPerPixel != aOther.mTwipsPerPixel) {
+  if (mColumnRuleWidth != aNewData.mColumnRuleWidth ||
+      mTwipsPerPixel != aNewData.mTwipsPerPixel) {
     return nsChangeHint_NeutralChange;
   }
 
   return NS_STYLE_HINT_NONE;
 }
 
 // --------------------
 // nsStyleSVG
@@ -886,83 +886,83 @@ PaintURIChanged(const nsStyleSVGPaint& a
     return aPaint1.mType == eStyleSVGPaintType_Server ||
            aPaint2.mType == eStyleSVGPaintType_Server;
   }
   return aPaint1.mType == eStyleSVGPaintType_Server &&
     !EqualURIs(aPaint1.mPaint.mPaintServer, aPaint2.mPaint.mPaintServer);
 }
 
 nsChangeHint
-nsStyleSVG::CalcDifference(const nsStyleSVG& aOther) const
+nsStyleSVG::CalcDifference(const nsStyleSVG& aNewData) const
 {
   nsChangeHint hint = nsChangeHint(0);
 
-  if (!EqualURIs(mMarkerEnd, aOther.mMarkerEnd) ||
-      !EqualURIs(mMarkerMid, aOther.mMarkerMid) ||
-      !EqualURIs(mMarkerStart, aOther.mMarkerStart)) {
+  if (!EqualURIs(mMarkerEnd, aNewData.mMarkerEnd) ||
+      !EqualURIs(mMarkerMid, aNewData.mMarkerMid) ||
+      !EqualURIs(mMarkerStart, aNewData.mMarkerStart)) {
     // Markers currently contribute to nsSVGPathGeometryFrame::mRect,
     // so we need a reflow as well as a repaint. No intrinsic sizes need
     // to change, so nsChangeHint_NeedReflow is sufficient.
     return nsChangeHint_UpdateEffects |
            nsChangeHint_NeedReflow |
            nsChangeHint_NeedDirtyReflow | // XXX remove me: bug 876085
            nsChangeHint_RepaintFrame;
   }
 
-  if (mFill != aOther.mFill ||
-      mStroke != aOther.mStroke ||
-      mFillOpacity != aOther.mFillOpacity ||
-      mStrokeOpacity != aOther.mStrokeOpacity) {
+  if (mFill != aNewData.mFill ||
+      mStroke != aNewData.mStroke ||
+      mFillOpacity != aNewData.mFillOpacity ||
+      mStrokeOpacity != aNewData.mStrokeOpacity) {
     hint |= nsChangeHint_RepaintFrame;
-    if (HasStroke() != aOther.HasStroke() ||
-        (!HasStroke() && HasFill() != aOther.HasFill())) {
+    if (HasStroke() != aNewData.HasStroke() ||
+        (!HasStroke() && HasFill() != aNewData.HasFill())) {
       // Frame bounds and overflow rects depend on whether we "have" fill or
       // stroke. Whether we have stroke or not just changed, or else we have no
       // stroke (in which case whether we have fill or not is significant to frame
       // bounds) and whether we have fill or not just changed. In either case we
       // need to reflow so the frame rect is updated.
       // XXXperf this is a waste on non nsSVGPathGeometryFrames.
       hint |= nsChangeHint_NeedReflow |
               nsChangeHint_NeedDirtyReflow; // XXX remove me: bug 876085
     }
-    if (PaintURIChanged(mFill, aOther.mFill) ||
-        PaintURIChanged(mStroke, aOther.mStroke)) {
+    if (PaintURIChanged(mFill, aNewData.mFill) ||
+        PaintURIChanged(mStroke, aNewData.mStroke)) {
       hint |= nsChangeHint_UpdateEffects;
     }
   }
 
   // Stroke currently contributes to nsSVGPathGeometryFrame::mRect, so
   // we need a reflow here. No intrinsic sizes need to change, so
   // nsChangeHint_NeedReflow is sufficient.
   // Note that stroke-dashoffset does not affect nsSVGPathGeometryFrame::mRect.
   // text-anchor changes also require a reflow since it changes frames' rects.
-  if (mStrokeWidth           != aOther.mStrokeWidth           ||
-      mStrokeMiterlimit      != aOther.mStrokeMiterlimit      ||
-      mStrokeLinecap         != aOther.mStrokeLinecap         ||
-      mStrokeLinejoin        != aOther.mStrokeLinejoin        ||
-      mTextAnchor            != aOther.mTextAnchor) {
+  if (mStrokeWidth           != aNewData.mStrokeWidth           ||
+      mStrokeMiterlimit      != aNewData.mStrokeMiterlimit      ||
+      mStrokeLinecap         != aNewData.mStrokeLinecap         ||
+      mStrokeLinejoin        != aNewData.mStrokeLinejoin        ||
+      mTextAnchor            != aNewData.mTextAnchor) {
     return hint |
            nsChangeHint_NeedReflow |
            nsChangeHint_NeedDirtyReflow | // XXX remove me: bug 876085
            nsChangeHint_RepaintFrame;
   }
 
   if (hint & nsChangeHint_RepaintFrame) {
     return hint; // we don't add anything else below
   }
 
-  if ( mStrokeDashoffset      != aOther.mStrokeDashoffset      ||
-       mClipRule              != aOther.mClipRule              ||
-       mColorInterpolation    != aOther.mColorInterpolation    ||
-       mColorInterpolationFilters != aOther.mColorInterpolationFilters ||
-       mFillRule              != aOther.mFillRule              ||
-       mPaintOrder            != aOther.mPaintOrder            ||
-       mShapeRendering        != aOther.mShapeRendering        ||
-       mStrokeDasharray       != aOther.mStrokeDasharray       ||
-       mContextFlags          != aOther.mContextFlags) {
+  if ( mStrokeDashoffset      != aNewData.mStrokeDashoffset      ||
+       mClipRule              != aNewData.mClipRule              ||
+       mColorInterpolation    != aNewData.mColorInterpolation    ||
+       mColorInterpolationFilters != aNewData.mColorInterpolationFilters ||
+       mFillRule              != aNewData.mFillRule              ||
+       mPaintOrder            != aNewData.mPaintOrder            ||
+       mShapeRendering        != aNewData.mShapeRendering        ||
+       mStrokeDasharray       != aNewData.mStrokeDasharray       ||
+       mContextFlags          != aNewData.mContextFlags) {
     return hint | nsChangeHint_RepaintFrame;
   }
 
   return hint;
 }
 
 // --------------------
 // nsStyleBasicShape
@@ -1250,50 +1250,50 @@ nsStyleSVGReset::Destroy(nsPresContext* 
   mMask.UntrackImages(aContext);
 
   this->~nsStyleSVGReset();
   aContext->PresShell()->
     FreeByObjectID(mozilla::eArenaObjectID_nsStyleSVGReset, this);
 }
 
 nsChangeHint
-nsStyleSVGReset::CalcDifference(const nsStyleSVGReset& aOther) const
+nsStyleSVGReset::CalcDifference(const nsStyleSVGReset& aNewData) const
 {
   nsChangeHint hint = nsChangeHint(0);
 
-  if (mClipPath != aOther.mClipPath) {
+  if (mClipPath != aNewData.mClipPath) {
     hint |= nsChangeHint_UpdateEffects |
             nsChangeHint_RepaintFrame;
     // clip-path changes require that we update the PreEffectsBBoxProperty,
     // which is done during overflow computation.
     hint |= nsChangeHint_UpdateOverflow;
   }
 
-  if (mDominantBaseline != aOther.mDominantBaseline) {
+  if (mDominantBaseline != aNewData.mDominantBaseline) {
     // XXXjwatt: why NS_STYLE_HINT_REFLOW? Isn't that excessive?
     hint |= NS_STYLE_HINT_REFLOW;
-  } else if (mVectorEffect  != aOther.mVectorEffect) {
+  } else if (mVectorEffect  != aNewData.mVectorEffect) {
     // Stroke currently affects nsSVGPathGeometryFrame::mRect, and
     // vector-effect affect stroke. As a result we need to reflow if
     // vector-effect changes in order to have nsSVGPathGeometryFrame::
     // ReflowSVG called to update its mRect. No intrinsic sizes need
     // to change so nsChangeHint_NeedReflow is sufficient.
     hint |= nsChangeHint_NeedReflow |
             nsChangeHint_NeedDirtyReflow | // XXX remove me: bug 876085
             nsChangeHint_RepaintFrame;
-  } else if (mStopColor     != aOther.mStopColor     ||
-             mFloodColor    != aOther.mFloodColor    ||
-             mLightingColor != aOther.mLightingColor ||
-             mStopOpacity   != aOther.mStopOpacity   ||
-             mFloodOpacity  != aOther.mFloodOpacity  ||
-             mMaskType      != aOther.mMaskType) {
+  } else if (mStopColor     != aNewData.mStopColor     ||
+             mFloodColor    != aNewData.mFloodColor    ||
+             mLightingColor != aNewData.mLightingColor ||
+             mStopOpacity   != aNewData.mStopOpacity   ||
+             mFloodOpacity  != aNewData.mFloodOpacity  ||
+             mMaskType      != aNewData.mMaskType) {
     hint |= nsChangeHint_RepaintFrame;
   }
 
-  hint |= mMask.CalcDifference(aOther.mMask, nsChangeHint_RepaintFrame);
+  hint |= mMask.CalcDifference(aNewData.mMask, nsChangeHint_RepaintFrame);
 
   return hint;
 }
 
 // nsStyleSVGPaint implementation
 nsStyleSVGPaint::nsStyleSVGPaint(nsStyleSVGPaintType aType)
   : mType(nsStyleSVGPaintType(0))
   , mFallbackColor(NS_RGB(0, 0, 0))
@@ -1478,124 +1478,124 @@ IsAutonessEqual(const nsStyleSides& aSid
         (aSides2.GetUnit(side) == eStyleUnit_Auto)) {
       return false;
     }
   }
   return true;
 }
 
 nsChangeHint
-nsStylePosition::CalcDifference(const nsStylePosition& aOther,
+nsStylePosition::CalcDifference(const nsStylePosition& aNewData,
                                 const nsStyleVisibility* aOldStyleVisibility) const
 {
   nsChangeHint hint = nsChangeHint(0);
 
   // Changes to "z-index" require a repaint.
-  if (mZIndex != aOther.mZIndex) {
+  if (mZIndex != aNewData.mZIndex) {
     hint |= nsChangeHint_RepaintFrame;
   }
 
   // Changes to "object-fit" & "object-position" require a repaint.  They
   // may also require a reflow, if we have a nsSubDocumentFrame, so that we
   // can adjust the size & position of the subdocument.
-  if (mObjectFit != aOther.mObjectFit ||
-      mObjectPosition != aOther.mObjectPosition) {
+  if (mObjectFit != aNewData.mObjectFit ||
+      mObjectPosition != aNewData.mObjectPosition) {
     hint |= nsChangeHint_RepaintFrame |
             nsChangeHint_NeedReflow;
   }
 
-  if (mOrder != aOther.mOrder) {
+  if (mOrder != aNewData.mOrder) {
     // "order" impacts both layout order and stacking order, so we need both a
     // reflow and a repaint when it changes.  (Technically, we only need a
     // reflow if we're in a multi-line flexbox (which we can't be sure about,
     // since that's determined by styling on our parent) -- there, "order" can
     // affect which flex line we end up on, & hence can affect our sizing by
     // changing the group of flex items we're competing with for space.)
     return hint |
            nsChangeHint_RepaintFrame |
            nsChangeHint_AllReflowHints;
   }
 
-  if (mBoxSizing != aOther.mBoxSizing) {
+  if (mBoxSizing != aNewData.mBoxSizing) {
     // Can affect both widths and heights; just a bad scene.
     return hint |
            nsChangeHint_AllReflowHints;
   }
 
   // Properties that apply to flex items:
   // XXXdholbert These should probably be more targeted (bug 819536)
-  if (mAlignSelf != aOther.mAlignSelf ||
-      mFlexBasis != aOther.mFlexBasis ||
-      mFlexGrow != aOther.mFlexGrow ||
-      mFlexShrink != aOther.mFlexShrink) {
+  if (mAlignSelf != aNewData.mAlignSelf ||
+      mFlexBasis != aNewData.mFlexBasis ||
+      mFlexGrow != aNewData.mFlexGrow ||
+      mFlexShrink != aNewData.mFlexShrink) {
     return hint |
            nsChangeHint_AllReflowHints;
   }
 
   // Properties that apply to flex containers:
   // - flex-direction can swap a flex container between vertical & horizontal.
   // - align-items can change the sizing of a flex container & the positioning
   //   of its children.
   // - flex-wrap changes whether a flex container's children are wrapped, which
   //   impacts their sizing/positioning and hence impacts the container's size.
-  if (mAlignItems != aOther.mAlignItems ||
-      mFlexDirection != aOther.mFlexDirection ||
-      mFlexWrap != aOther.mFlexWrap) {
+  if (mAlignItems != aNewData.mAlignItems ||
+      mFlexDirection != aNewData.mFlexDirection ||
+      mFlexWrap != aNewData.mFlexWrap) {
     return hint |
            nsChangeHint_AllReflowHints;
   }
 
   // Properties that apply to grid containers:
   // FIXME: only for grid containers
   // (ie. 'display: grid' or 'display: inline-grid')
-  if (mGridTemplateColumns != aOther.mGridTemplateColumns ||
-      mGridTemplateRows != aOther.mGridTemplateRows ||
-      mGridTemplateAreas != aOther.mGridTemplateAreas ||
-      mGridAutoColumnsMin != aOther.mGridAutoColumnsMin ||
-      mGridAutoColumnsMax != aOther.mGridAutoColumnsMax ||
-      mGridAutoRowsMin != aOther.mGridAutoRowsMin ||
-      mGridAutoRowsMax != aOther.mGridAutoRowsMax ||
-      mGridAutoFlow != aOther.mGridAutoFlow) {
+  if (mGridTemplateColumns != aNewData.mGridTemplateColumns ||
+      mGridTemplateRows != aNewData.mGridTemplateRows ||
+      mGridTemplateAreas != aNewData.mGridTemplateAreas ||
+      mGridAutoColumnsMin != aNewData.mGridAutoColumnsMin ||
+      mGridAutoColumnsMax != aNewData.mGridAutoColumnsMax ||
+      mGridAutoRowsMin != aNewData.mGridAutoRowsMin ||
+      mGridAutoRowsMax != aNewData.mGridAutoRowsMax ||
+      mGridAutoFlow != aNewData.mGridAutoFlow) {
     return hint |
            nsChangeHint_AllReflowHints;
   }
 
   // Properties that apply to grid items:
   // FIXME: only for grid items
   // (ie. parent frame is 'display: grid' or 'display: inline-grid')
-  if (mGridColumnStart != aOther.mGridColumnStart ||
-      mGridColumnEnd != aOther.mGridColumnEnd ||
-      mGridRowStart != aOther.mGridRowStart ||
-      mGridRowEnd != aOther.mGridRowEnd ||
-      mGridColumnGap != aOther.mGridColumnGap ||
-      mGridRowGap != aOther.mGridRowGap) {
+  if (mGridColumnStart != aNewData.mGridColumnStart ||
+      mGridColumnEnd != aNewData.mGridColumnEnd ||
+      mGridRowStart != aNewData.mGridRowStart ||
+      mGridRowEnd != aNewData.mGridRowEnd ||
+      mGridColumnGap != aNewData.mGridColumnGap ||
+      mGridRowGap != aNewData.mGridRowGap) {
     return hint |
            nsChangeHint_AllReflowHints;
   }
 
   // Changing 'justify-content/items/self' might affect the positioning,
   // but it won't affect any sizing.
-  if (mJustifyContent != aOther.mJustifyContent ||
-      mJustifyItems != aOther.mJustifyItems ||
-      mJustifySelf != aOther.mJustifySelf) {
+  if (mJustifyContent != aNewData.mJustifyContent ||
+      mJustifyItems != aNewData.mJustifyItems ||
+      mJustifySelf != aNewData.mJustifySelf) {
     hint |= nsChangeHint_NeedReflow;
   }
 
   // 'align-content' doesn't apply to a single-line flexbox but we don't know
   // if we're a flex container at this point so we can't optimize for that.
-  if (mAlignContent != aOther.mAlignContent) {
+  if (mAlignContent != aNewData.mAlignContent) {
     hint |= nsChangeHint_NeedReflow;
   }
 
-  bool widthChanged = mWidth != aOther.mWidth ||
-                      mMinWidth != aOther.mMinWidth ||
-                      mMaxWidth != aOther.mMaxWidth;
-  bool heightChanged = mHeight != aOther.mHeight ||
-                       mMinHeight != aOther.mMinHeight ||
-                       mMaxHeight != aOther.mMaxHeight;
+  bool widthChanged = mWidth != aNewData.mWidth ||
+                      mMinWidth != aNewData.mMinWidth ||
+                      mMaxWidth != aNewData.mMaxWidth;
+  bool heightChanged = mHeight != aNewData.mHeight ||
+                       mMinHeight != aNewData.mMinHeight ||
+                       mMaxHeight != aNewData.mMaxHeight;
 
   // If aOldStyleVisibility is null, we don't need to bother with any of
   // these tests, since we know that the element never had its
   // nsStyleVisibility accessed, which means it couldn't have done
   // layout.
   // Note that we pass an nsStyleVisibility here because we don't want
   // to cause a new struct to be computed during
   // nsStyleContext::CalcStyleDifference, which can lead to incorrect
@@ -1632,18 +1632,18 @@ nsStylePosition::CalcDifference(const ns
 
   // If any of the offsets have changed, then return the respective hints
   // so that we would hopefully be able to avoid reflowing.
   // Note that it is possible that we'll need to reflow when processing
   // restyles, but we don't have enough information to make a good decision
   // right now.
   // Don't try to handle changes between "auto" and non-auto efficiently;
   // that's tricky to do and will hardly ever be able to avoid a reflow.
-  if (mOffset != aOther.mOffset) {
-    if (IsAutonessEqual(mOffset, aOther.mOffset)) {
+  if (mOffset != aNewData.mOffset) {
+    if (IsAutonessEqual(mOffset, aNewData.mOffset)) {
       hint |= nsChangeHint_RecomputePosition |
               nsChangeHint_UpdateParentOverflow;
     } else {
       hint |= nsChangeHint_AllReflowHints;
     }
   }
   return hint;
 }
@@ -1722,20 +1722,21 @@ nsStyleTable::~nsStyleTable()
 
 nsStyleTable::nsStyleTable(const nsStyleTable& aSource)
   : mLayoutStrategy(aSource.mLayoutStrategy)
   , mSpan(aSource.mSpan)
 {
   MOZ_COUNT_CTOR(nsStyleTable);
 }
 
-nsChangeHint nsStyleTable::CalcDifference(const nsStyleTable& aOther) const
+nsChangeHint
+nsStyleTable::CalcDifference(const nsStyleTable& aNewData) const
 {
-  if (mSpan != aOther.mSpan ||
-      mLayoutStrategy != aOther.mLayoutStrategy)
+  if (mSpan != aNewData.mSpan ||
+      mLayoutStrategy != aNewData.mLayoutStrategy)
     return NS_STYLE_HINT_FRAMECHANGE;
   return NS_STYLE_HINT_NONE;
 }
 
 // -----------------------
 // nsStyleTableBorder
 
 nsStyleTableBorder::nsStyleTableBorder(StyleStructContext aContext)
@@ -1759,30 +1760,30 @@ nsStyleTableBorder::nsStyleTableBorder(c
   , mBorderCollapse(aSource.mBorderCollapse)
   , mCaptionSide(aSource.mCaptionSide)
   , mEmptyCells(aSource.mEmptyCells)
 {
   MOZ_COUNT_CTOR(nsStyleTableBorder);
 }
 
 nsChangeHint
-nsStyleTableBorder::CalcDifference(const nsStyleTableBorder& aOther) const
+nsStyleTableBorder::CalcDifference(const nsStyleTableBorder& aNewData) const
 {
   // Border-collapse changes need a reframe, because we use a different frame
   // class for table cells in the collapsed border model.  This is used to
   // conserve memory when using the separated border model (collapsed borders
   // require extra state to be stored).
-  if (mBorderCollapse != aOther.mBorderCollapse) {
+  if (mBorderCollapse != aNewData.mBorderCollapse) {
     return NS_STYLE_HINT_FRAMECHANGE;
   }
 
-  if ((mCaptionSide == aOther.mCaptionSide) &&
-      (mBorderSpacingCol == aOther.mBorderSpacingCol) &&
-      (mBorderSpacingRow == aOther.mBorderSpacingRow)) {
-    if (mEmptyCells == aOther.mEmptyCells)
+  if ((mCaptionSide == aNewData.mCaptionSide) &&
+      (mBorderSpacingCol == aNewData.mBorderSpacingCol) &&
+      (mBorderSpacingRow == aNewData.mBorderSpacingRow)) {
+    if (mEmptyCells == aNewData.mEmptyCells)
       return NS_STYLE_HINT_NONE;
     return NS_STYLE_HINT_VISUAL;
   }
   else
     return NS_STYLE_HINT_REFLOW;
 }
 
 // --------------------
@@ -1797,19 +1798,19 @@ nsStyleColor::nsStyleColor(StyleStructCo
 
 nsStyleColor::nsStyleColor(const nsStyleColor& aSource)
   : mColor(aSource.mColor)
 {
   MOZ_COUNT_CTOR(nsStyleColor);
 }
 
 nsChangeHint
-nsStyleColor::CalcDifference(const nsStyleColor& aOther) const
+nsStyleColor::CalcDifference(const nsStyleColor& aNewData) const
 {
-  if (mColor == aOther.mColor)
+  if (mColor == aNewData.mColor)
     return NS_STYLE_HINT_NONE;
   return nsChangeHint_RepaintFrame;
 }
 
 // --------------------
 // nsStyleGradient
 //
 bool
@@ -2298,27 +2299,27 @@ nsStyleImageLayers::nsStyleImageLayers(c
     mSizeCount = std::max(mSizeCount, count);
     mMaskModeCount = std::max(mMaskModeCount, count);
     mBlendModeCount = std::max(mBlendModeCount, count);
     mCompositeCount = std::max(mCompositeCount, count);
   }
 }
 
 nsChangeHint
-nsStyleImageLayers::CalcDifference(const nsStyleImageLayers& aOther,
+nsStyleImageLayers::CalcDifference(const nsStyleImageLayers& aNewLayers,
                                    nsChangeHint aPositionChangeHint) const
 {
   nsChangeHint hint = nsChangeHint(0);
 
   const nsStyleImageLayers& moreLayers =
-    mImageCount > aOther.mImageCount ?
-      *this : aOther;
+    mImageCount > aNewLayers.mImageCount ?
+      *this : aNewLayers;
   const nsStyleImageLayers& lessLayers =
-    mImageCount > aOther.mImageCount ?
-      aOther : *this;
+    mImageCount > aNewLayers.mImageCount ?
+      aNewLayers : *this;
 
   NS_FOR_VISIBLE_IMAGE_LAYERS_BACK_TO_FRONT(i, moreLayers) {
     if (i < lessLayers.mImageCount) {
       nsChangeHint layerDifference =
         moreLayers.mLayers[i].CalcDifference(lessLayers.mLayers[i],
                                              aPositionChangeHint);
       hint |= layerDifference;
       if (layerDifference &&
@@ -2333,26 +2334,26 @@ nsStyleImageLayers::CalcDifference(const
       }
     }
   }
 
   if (hint) {
     return hint;
   }
 
-  if (mAttachmentCount != aOther.mAttachmentCount ||
-      mBlendModeCount != aOther.mBlendModeCount ||
-      mClipCount != aOther.mClipCount ||
-      mCompositeCount != aOther.mCompositeCount ||
-      mMaskModeCount != aOther.mMaskModeCount ||
-      mOriginCount != aOther.mOriginCount ||
-      mRepeatCount != aOther.mRepeatCount ||
-      mPositionXCount != aOther.mPositionXCount ||
-      mPositionYCount != aOther.mPositionYCount ||
-      mSizeCount != aOther.mSizeCount) {
+  if (mAttachmentCount != aNewLayers.mAttachmentCount ||
+      mBlendModeCount != aNewLayers.mBlendModeCount ||
+      mClipCount != aNewLayers.mClipCount ||
+      mCompositeCount != aNewLayers.mCompositeCount ||
+      mMaskModeCount != aNewLayers.mMaskModeCount ||
+      mOriginCount != aNewLayers.mOriginCount ||
+      mRepeatCount != aNewLayers.mRepeatCount ||
+      mPositionXCount != aNewLayers.mPositionXCount ||
+      mPositionYCount != aNewLayers.mPositionYCount ||
+      mSizeCount != aNewLayers.mSizeCount) {
     hint |= nsChangeHint_NeutralChange;
   }
 
   return hint;
 }
 
 bool
 nsStyleImageLayers::HasLayerWithImage() const
@@ -2589,39 +2590,39 @@ nsStyleImageLayers::Layer::operator==(co
          mSize == aOther.mSize &&
          mImage == aOther.mImage &&
          mMaskMode == aOther.mMaskMode &&
          mComposite == aOther.mComposite &&
          EqualURIs(mSourceURI, aOther.mSourceURI);
 }
 
 nsChangeHint
-nsStyleImageLayers::Layer::CalcDifference(const nsStyleImageLayers::Layer& aOther,
+nsStyleImageLayers::Layer::CalcDifference(const nsStyleImageLayers::Layer& aNewLayer,
                                           nsChangeHint aPositionChangeHint) const
 {
   nsChangeHint hint = nsChangeHint(0);
-  if (!EqualURIs(mSourceURI, aOther.mSourceURI)) {
+  if (!EqualURIs(mSourceURI, aNewLayer.mSourceURI)) {
     hint |= nsChangeHint_UpdateEffects |
             nsChangeHint_RepaintFrame;
     // Mask changes require that we update the PreEffectsBBoxProperty,
     // which is done during overflow computation.
     hint |= nsChangeHint_UpdateOverflow;
-  } else if (mAttachment != aOther.mAttachment ||
-             mClip != aOther.mClip ||
-             mOrigin != aOther.mOrigin ||
-             mRepeat != aOther.mRepeat ||
-             mBlendMode != aOther.mBlendMode ||
-             mSize != aOther.mSize ||
-             mImage != aOther.mImage ||
-             mMaskMode != aOther.mMaskMode ||
-             mComposite != aOther.mComposite) {
+  } else if (mAttachment != aNewLayer.mAttachment ||
+             mClip != aNewLayer.mClip ||
+             mOrigin != aNewLayer.mOrigin ||
+             mRepeat != aNewLayer.mRepeat ||
+             mBlendMode != aNewLayer.mBlendMode ||
+             mSize != aNewLayer.mSize ||
+             mImage != aNewLayer.mImage ||
+             mMaskMode != aNewLayer.mMaskMode ||
+             mComposite != aNewLayer.mComposite) {
     hint |= nsChangeHint_RepaintFrame;
   }
 
-  if (mPosition != aOther.mPosition) {
+  if (mPosition != aNewLayer.mPosition) {
     hint |= aPositionChangeHint;
   }
 
   return hint;
 }
 
 // --------------------
 // nsStyleBackground
@@ -2653,24 +2654,24 @@ nsStyleBackground::Destroy(nsPresContext
   mImage.UntrackImages(aContext);
 
   this->~nsStyleBackground();
   aContext->PresShell()->
     FreeByObjectID(eArenaObjectID_nsStyleBackground, this);
 }
 
 nsChangeHint
-nsStyleBackground::CalcDifference(const nsStyleBackground& aOther) const
+nsStyleBackground::CalcDifference(const nsStyleBackground& aNewData) const
 {
   nsChangeHint hint = nsChangeHint(0);
-  if (mBackgroundColor != aOther.mBackgroundColor) {
+  if (mBackgroundColor != aNewData.mBackgroundColor) {
     hint |= nsChangeHint_RepaintFrame;
   }
 
-  hint |= mImage.CalcDifference(aOther.mImage,
+  hint |= mImage.CalcDifference(aNewData.mImage,
                                 nsChangeHint_UpdateBackgroundPosition);
 
   return hint;
 }
 
 bool
 nsStyleBackground::HasFixedBackground(nsIFrame* aFrame) const
 {
@@ -2944,95 +2945,95 @@ nsStyleDisplay::nsStyleDisplay(const nsS
   mTransformOrigin[0] = aSource.mTransformOrigin[0];
   mTransformOrigin[1] = aSource.mTransformOrigin[1];
   mTransformOrigin[2] = aSource.mTransformOrigin[2];
   mPerspectiveOrigin[0] = aSource.mPerspectiveOrigin[0];
   mPerspectiveOrigin[1] = aSource.mPerspectiveOrigin[1];
 }
 
 nsChangeHint
-nsStyleDisplay::CalcDifference(const nsStyleDisplay& aOther) const
+nsStyleDisplay::CalcDifference(const nsStyleDisplay& aNewData) const
 {
   nsChangeHint hint = nsChangeHint(0);
 
-  if (!EqualURIs(mBinding, aOther.mBinding)
-      || mPosition != aOther.mPosition
-      || mDisplay != aOther.mDisplay
-      || mContain != aOther.mContain
-      || (mFloat == NS_STYLE_FLOAT_NONE) != (aOther.mFloat == NS_STYLE_FLOAT_NONE)
-      || mOverflowX != aOther.mOverflowX
-      || mOverflowY != aOther.mOverflowY
-      || mScrollBehavior != aOther.mScrollBehavior
-      || mScrollSnapTypeX != aOther.mScrollSnapTypeX
-      || mScrollSnapTypeY != aOther.mScrollSnapTypeY
-      || mScrollSnapPointsX != aOther.mScrollSnapPointsX
-      || mScrollSnapPointsY != aOther.mScrollSnapPointsY
-      || mScrollSnapDestination != aOther.mScrollSnapDestination
-      || mTopLayer != aOther.mTopLayer
-      || mResize != aOther.mResize)
+  if (!EqualURIs(mBinding, aNewData.mBinding)
+      || mPosition != aNewData.mPosition
+      || mDisplay != aNewData.mDisplay
+      || mContain != aNewData.mContain
+      || (mFloat == NS_STYLE_FLOAT_NONE) != (aNewData.mFloat == NS_STYLE_FLOAT_NONE)
+      || mOverflowX != aNewData.mOverflowX
+      || mOverflowY != aNewData.mOverflowY
+      || mScrollBehavior != aNewData.mScrollBehavior
+      || mScrollSnapTypeX != aNewData.mScrollSnapTypeX
+      || mScrollSnapTypeY != aNewData.mScrollSnapTypeY
+      || mScrollSnapPointsX != aNewData.mScrollSnapPointsX
+      || mScrollSnapPointsY != aNewData.mScrollSnapPointsY
+      || mScrollSnapDestination != aNewData.mScrollSnapDestination
+      || mTopLayer != aNewData.mTopLayer
+      || mResize != aNewData.mResize)
     hint |= nsChangeHint_ReconstructFrame;
 
   /* Note: When mScrollBehavior, mScrollSnapTypeX, mScrollSnapTypeY,
    * mScrollSnapPointsX, mScrollSnapPointsY, or mScrollSnapDestination are
    * changed, nsChangeHint_NeutralChange is not sufficient to enter
    * nsCSSFrameConstructor::PropagateScrollToViewport. By using the same hint
    * as used when the overflow css property changes,
    * nsChangeHint_ReconstructFrame, PropagateScrollToViewport will be called.
    *
    * The scroll-behavior css property is not expected to change often (the
    * CSSOM-View DOM methods are likely to be used in those cases); however,
    * if this does become common perhaps a faster-path might be worth while.
    */
 
   if ((mAppearance == NS_THEME_TEXTFIELD &&
-       aOther.mAppearance != NS_THEME_TEXTFIELD) ||
+       aNewData.mAppearance != NS_THEME_TEXTFIELD) ||
       (mAppearance != NS_THEME_TEXTFIELD &&
-       aOther.mAppearance == NS_THEME_TEXTFIELD)) {
+       aNewData.mAppearance == NS_THEME_TEXTFIELD)) {
     // This is for <input type=number> where we allow authors to specify a
     // |-moz-appearance:textfield| to get a control without a spinner. (The
     // spinner is present for |-moz-appearance:number-input| but also other
     // values such as 'none'.) We need to reframe since we want to use
     // nsTextControlFrame instead of nsNumberControlFrame if the author
     // specifies 'textfield'.
     return nsChangeHint_ReconstructFrame;
   }
 
-  if (mFloat != aOther.mFloat) {
+  if (mFloat != aNewData.mFloat) {
     // Changing which side we float on doesn't affect descendants directly
     hint |= nsChangeHint_AllReflowHints &
             ~(nsChangeHint_ClearDescendantIntrinsics |
               nsChangeHint_NeedDirtyReflow);
   }
 
-  if (mVerticalAlign != aOther.mVerticalAlign) {
+  if (mVerticalAlign != aNewData.mVerticalAlign) {
     // XXX Can this just be AllReflowHints + RepaintFrame, and be included in
     // the block below?
     hint |= NS_STYLE_HINT_REFLOW;
   }
 
   // XXX the following is conservative, for now: changing float breaking shouldn't
   // necessarily require a repaint, reflow should suffice.
-  if (mBreakType != aOther.mBreakType
-      || mBreakInside != aOther.mBreakInside
-      || mBreakBefore != aOther.mBreakBefore
-      || mBreakAfter != aOther.mBreakAfter
-      || mAppearance != aOther.mAppearance
-      || mOrient != aOther.mOrient
-      || mOverflowClipBox != aOther.mOverflowClipBox)
+  if (mBreakType != aNewData.mBreakType
+      || mBreakInside != aNewData.mBreakInside
+      || mBreakBefore != aNewData.mBreakBefore
+      || mBreakAfter != aNewData.mBreakAfter
+      || mAppearance != aNewData.mAppearance
+      || mOrient != aNewData.mOrient
+      || mOverflowClipBox != aNewData.mOverflowClipBox)
     hint |= nsChangeHint_AllReflowHints |
             nsChangeHint_RepaintFrame;
 
-  if (mIsolation != aOther.mIsolation) {
+  if (mIsolation != aNewData.mIsolation) {
     hint |= nsChangeHint_RepaintFrame;
   }
 
   /* If we've added or removed the transform property, we need to reconstruct the frame to add
    * or remove the view object, and also to handle abs-pos and fixed-pos containers.
    */
-  if (HasTransformStyle() != aOther.HasTransformStyle()) {
+  if (HasTransformStyle() != aNewData.HasTransformStyle()) {
     // We do not need to apply nsChangeHint_UpdateTransformLayer since
     // nsChangeHint_RepaintFrame will forcibly invalidate the frame area and
     // ensure layers are rebuilt (or removed).
     hint |= nsChangeHint_UpdateContainingBlock |
             nsChangeHint_UpdateOverflow |
             nsChangeHint_RepaintFrame;
   } else {
     /* Otherwise, if we've kept the property lying around and we already had a
@@ -3042,86 +3043,86 @@ nsStyleDisplay::CalcDifference(const nsS
      * overflow rect.
      *
      * If the property isn't present in either style struct, we still do the
      * comparisons but turn all the resulting change hints into
      * nsChangeHint_NeutralChange.
      */
     nsChangeHint transformHint = nsChangeHint(0);
 
-    if (!mSpecifiedTransform != !aOther.mSpecifiedTransform ||
+    if (!mSpecifiedTransform != !aNewData.mSpecifiedTransform ||
         (mSpecifiedTransform &&
-         *mSpecifiedTransform != *aOther.mSpecifiedTransform)) {
+         *mSpecifiedTransform != *aNewData.mSpecifiedTransform)) {
       transformHint |= nsChangeHint_UpdateTransformLayer;
 
       if (mSpecifiedTransform &&
-          aOther.mSpecifiedTransform) {
+          aNewData.mSpecifiedTransform) {
         transformHint |= nsChangeHint_UpdatePostTransformOverflow;
       } else {
         transformHint |= nsChangeHint_UpdateOverflow;
       }
     }
 
     const nsChangeHint kUpdateOverflowAndRepaintHint =
       nsChangeHint_UpdateOverflow | nsChangeHint_RepaintFrame;
     for (uint8_t index = 0; index < 3; ++index)
-      if (mTransformOrigin[index] != aOther.mTransformOrigin[index]) {
+      if (mTransformOrigin[index] != aNewData.mTransformOrigin[index]) {
         transformHint |= nsChangeHint_UpdateTransformLayer |
                          nsChangeHint_UpdatePostTransformOverflow;
         break;
       }
     
     for (uint8_t index = 0; index < 2; ++index)
-      if (mPerspectiveOrigin[index] != aOther.mPerspectiveOrigin[index]) {
+      if (mPerspectiveOrigin[index] != aNewData.mPerspectiveOrigin[index]) {
         transformHint |= kUpdateOverflowAndRepaintHint;
         break;
       }
 
-    if (HasPerspectiveStyle() != aOther.HasPerspectiveStyle()) {
+    if (HasPerspectiveStyle() != aNewData.HasPerspectiveStyle()) {
       // A change from/to being a containing block for position:fixed.
       hint |= nsChangeHint_UpdateContainingBlock;
     }
 
-    if (mChildPerspective != aOther.mChildPerspective ||
-        mTransformStyle != aOther.mTransformStyle ||
-        mTransformBox != aOther.mTransformBox)
+    if (mChildPerspective != aNewData.mChildPerspective ||
+        mTransformStyle != aNewData.mTransformStyle ||
+        mTransformBox != aNewData.mTransformBox)
       transformHint |= kUpdateOverflowAndRepaintHint;
 
-    if (mBackfaceVisibility != aOther.mBackfaceVisibility)
+    if (mBackfaceVisibility != aNewData.mBackfaceVisibility)
       transformHint |= nsChangeHint_RepaintFrame;
 
     if (transformHint) {
       if (HasTransformStyle()) {
         hint |= transformHint;
       } else {
         hint |= nsChangeHint_NeutralChange;
       }
     }
   }
 
-  // Note that the HasTransformStyle() != aOther.HasTransformStyle() 
+  // Note that the HasTransformStyle() != aNewData.HasTransformStyle() 
   // test above handles relevant changes in the
   // NS_STYLE_WILL_CHANGE_TRANSFORM bit, which in turn handles frame 
   // reconstruction for changes in the containing block of 
   // fixed-positioned elements.
   uint8_t willChangeBitsChanged =
-    mWillChangeBitField ^ aOther.mWillChangeBitField;
+    mWillChangeBitField ^ aNewData.mWillChangeBitField;
   if (willChangeBitsChanged & (NS_STYLE_WILL_CHANGE_STACKING_CONTEXT |
                                NS_STYLE_WILL_CHANGE_SCROLL |
                                NS_STYLE_WILL_CHANGE_OPACITY)) {
     hint |= nsChangeHint_RepaintFrame;
   }
 
   if (willChangeBitsChanged & NS_STYLE_WILL_CHANGE_FIXPOS_CB) {
     hint |= nsChangeHint_UpdateContainingBlock;
   }
 
   // If touch-action is changed, we need to regenerate the event regions on
   // the layers and send it over to the compositor for APZ to handle.
-  if (mTouchAction != aOther.mTouchAction) {
+  if (mTouchAction != aNewData.mTouchAction) {
     hint |= nsChangeHint_RepaintFrame;
   }
 
   // Note:  Our current behavior for handling changes to the
   // transition-duration, transition-delay, and transition-timing-function
   // properties is to do nothing.  In other words, the transition
   // property that matters is what it is when the transition begins, and
   // we don't stop a transition later because the transition property
@@ -3133,34 +3134,34 @@ nsStyleDisplay::CalcDifference(const nsS
   // Note: Likewise, for animation-*, the animation manager gets
   // notified about every new style context constructed, and it uses
   // that opportunity to handle dynamic changes appropriately.
 
   // But we still need to return nsChangeHint_NeutralChange for these
   // properties, since some data did change in the style struct.
 
   if (!hint &&
-      (mOriginalDisplay != aOther.mOriginalDisplay ||
-       mOriginalFloat != aOther.mOriginalFloat ||
-       mTransitions != aOther.mTransitions ||
+      (mOriginalDisplay != aNewData.mOriginalDisplay ||
+       mOriginalFloat != aNewData.mOriginalFloat ||
+       mTransitions != aNewData.mTransitions ||
        mTransitionTimingFunctionCount !=
-         aOther.mTransitionTimingFunctionCount ||
-       mTransitionDurationCount != aOther.mTransitionDurationCount ||
-       mTransitionDelayCount != aOther.mTransitionDelayCount ||
-       mTransitionPropertyCount != aOther.mTransitionPropertyCount ||
-       mAnimations != aOther.mAnimations ||
-       mAnimationTimingFunctionCount != aOther.mAnimationTimingFunctionCount ||
-       mAnimationDurationCount != aOther.mAnimationDurationCount ||
-       mAnimationDelayCount != aOther.mAnimationDelayCount ||
-       mAnimationNameCount != aOther.mAnimationNameCount ||
-       mAnimationDirectionCount != aOther.mAnimationDirectionCount ||
-       mAnimationFillModeCount != aOther.mAnimationFillModeCount ||
-       mAnimationPlayStateCount != aOther.mAnimationPlayStateCount ||
-       mAnimationIterationCountCount != aOther.mAnimationIterationCountCount ||
-       mScrollSnapCoordinate != aOther.mScrollSnapCoordinate)) {
+         aNewData.mTransitionTimingFunctionCount ||
+       mTransitionDurationCount != aNewData.mTransitionDurationCount ||
+       mTransitionDelayCount != aNewData.mTransitionDelayCount ||
+       mTransitionPropertyCount != aNewData.mTransitionPropertyCount ||
+       mAnimations != aNewData.mAnimations ||
+       mAnimationTimingFunctionCount != aNewData.mAnimationTimingFunctionCount ||
+       mAnimationDurationCount != aNewData.mAnimationDurationCount ||
+       mAnimationDelayCount != aNewData.mAnimationDelayCount ||
+       mAnimationNameCount != aNewData.mAnimationNameCount ||
+       mAnimationDirectionCount != aNewData.mAnimationDirectionCount ||
+       mAnimationFillModeCount != aNewData.mAnimationFillModeCount ||
+       mAnimationPlayStateCount != aNewData.mAnimationPlayStateCount ||
+       mAnimationIterationCountCount != aNewData.mAnimationIterationCountCount ||
+       mScrollSnapCoordinate != aNewData.mScrollSnapCoordinate)) {
     hint |= nsChangeHint_NeutralChange;
   }
 
   return hint;
 }
 
 // --------------------
 // nsStyleVisibility
@@ -3187,45 +3188,45 @@ nsStyleVisibility::nsStyleVisibility(con
   , mWritingMode(aSource.mWritingMode)
   , mTextOrientation(aSource.mTextOrientation)
   , mColorAdjust(aSource.mColorAdjust)
 {
   MOZ_COUNT_CTOR(nsStyleVisibility);
 }
 
 nsChangeHint
-nsStyleVisibility::CalcDifference(const nsStyleVisibility& aOther) const
+nsStyleVisibility::CalcDifference(const nsStyleVisibility& aNewData) const
 {
   nsChangeHint hint = nsChangeHint(0);
 
-  if (mDirection != aOther.mDirection || mWritingMode != aOther.mWritingMode) {
+  if (mDirection != aNewData.mDirection || mWritingMode != aNewData.mWritingMode) {
     // It's important that a change in mWritingMode results in frame
     // reconstruction, because it may affect intrinsic size (see
     // nsSubDocumentFrame::GetIntrinsicISize/BSize).
     hint |= nsChangeHint_ReconstructFrame;
   } else {
-    if ((mImageOrientation != aOther.mImageOrientation)) {
+    if ((mImageOrientation != aNewData.mImageOrientation)) {
       hint |= nsChangeHint_AllReflowHints |
               nsChangeHint_RepaintFrame;
     }
-    if (mVisible != aOther.mVisible) {
+    if (mVisible != aNewData.mVisible) {
       if ((NS_STYLE_VISIBILITY_COLLAPSE == mVisible) ||
-          (NS_STYLE_VISIBILITY_COLLAPSE == aOther.mVisible)) {
+          (NS_STYLE_VISIBILITY_COLLAPSE == aNewData.mVisible)) {
         hint |= NS_STYLE_HINT_REFLOW;
       } else {
         hint |= NS_STYLE_HINT_VISUAL;
       }
     }
-    if (mTextOrientation != aOther.mTextOrientation) {
+    if (mTextOrientation != aNewData.mTextOrientation) {
       hint |= NS_STYLE_HINT_REFLOW;
     }
-    if (mImageRendering != aOther.mImageRendering) {
+    if (mImageRendering != aNewData.mImageRendering) {
       hint |= nsChangeHint_RepaintFrame;
     }
-    if (mColorAdjust != aOther.mColorAdjust) {
+    if (mColorAdjust != aNewData.mColorAdjust) {
       // color-adjust only affects media where dynamic changes can't happen.
       hint |= nsChangeHint_NeutralChange;
     }
   }
   return hint;
 }
 
 nsStyleContentData::~nsStyleContentData()
@@ -3404,60 +3405,60 @@ nsStyleContent::nsStyleContent(const nsS
       const nsStyleCounterData *data = aSource.GetCounterResetAt(index);
       mResets[index].mCounter = data->mCounter;
       mResets[index].mValue = data->mValue;
     }
   }
 }
 
 nsChangeHint
-nsStyleContent::CalcDifference(const nsStyleContent& aOther) const
+nsStyleContent::CalcDifference(const nsStyleContent& aNewData) const
 {
   // In ReResolveStyleContext we assume that if there's no existing
   // ::before or ::after and we don't have to restyle children of the
   // node then we can't end up with a ::before or ::after due to the
   // restyle of the node itself.  That's not quite true, but the only
   // exception to the above is when the 'content' property of the node
   // changes and the pseudo-element inherits the changed value.  Since
   // the code here triggers a frame change on the node in that case,
   // the optimization in ReResolveStyleContext is ok.  But if we ever
   // change this code to not reconstruct frames on changes to the
   // 'content' property, then we will need to revisit the optimization
   // in ReResolveStyleContext.
 
-  if (mContentCount != aOther.mContentCount ||
-      mIncrementCount != aOther.mIncrementCount || 
-      mResetCount != aOther.mResetCount) {
+  if (mContentCount != aNewData.mContentCount ||
+      mIncrementCount != aNewData.mIncrementCount ||
+      mResetCount != aNewData.mResetCount) {
     return NS_STYLE_HINT_FRAMECHANGE;
   }
 
   uint32_t ix = mContentCount;
   while (0 < ix--) {
-    if (mContents[ix] != aOther.mContents[ix]) {
+    if (mContents[ix] != aNewData.mContents[ix]) {
       // Unfortunately we need to reframe here; a simple reflow
       // will not pick up different text or different image URLs,
       // since we set all that up in the CSSFrameConstructor
       return NS_STYLE_HINT_FRAMECHANGE;
     }
   }
   ix = mIncrementCount;
   while (0 < ix--) {
-    if ((mIncrements[ix].mValue != aOther.mIncrements[ix].mValue) || 
-        (mIncrements[ix].mCounter != aOther.mIncrements[ix].mCounter)) {
+    if ((mIncrements[ix].mValue != aNewData.mIncrements[ix].mValue) ||
+        (mIncrements[ix].mCounter != aNewData.mIncrements[ix].mCounter)) {
       return NS_STYLE_HINT_FRAMECHANGE;
     }
   }
   ix = mResetCount;
   while (0 < ix--) {
-    if ((mResets[ix].mValue != aOther.mResets[ix].mValue) || 
-        (mResets[ix].mCounter != aOther.mResets[ix].mCounter)) {
+    if ((mResets[ix].mValue != aNewData.mResets[ix].mValue) ||
+        (mResets[ix].mCounter != aNewData.mResets[ix].mCounter)) {
       return NS_STYLE_HINT_FRAMECHANGE;
     }
   }
-  if (mMarkerOffset != aOther.mMarkerOffset) {
+  if (mMarkerOffset != aNewData.mMarkerOffset) {
     return NS_STYLE_HINT_REFLOW;
   }
   return NS_STYLE_HINT_NONE;
 }
 
 nsresult
 nsStyleContent::AllocateContents(uint32_t aCount)
 {
@@ -3499,44 +3500,44 @@ nsStyleTextReset::nsStyleTextReset(const
 }
 
 nsStyleTextReset::~nsStyleTextReset()
 {
   MOZ_COUNT_DTOR(nsStyleTextReset);
 }
 
 nsChangeHint
-nsStyleTextReset::CalcDifference(const nsStyleTextReset& aOther) const
+nsStyleTextReset::CalcDifference(const nsStyleTextReset& aNewData) const
 {
-  if (mUnicodeBidi != aOther.mUnicodeBidi) {
+  if (mUnicodeBidi != aNewData.mUnicodeBidi) {
     return NS_STYLE_HINT_REFLOW;
   }
 
   uint8_t lineStyle = GetDecorationStyle();
-  uint8_t otherLineStyle = aOther.GetDecorationStyle();
-  if (mTextDecorationLine != aOther.mTextDecorationLine ||
+  uint8_t otherLineStyle = aNewData.GetDecorationStyle();
+  if (mTextDecorationLine != aNewData.mTextDecorationLine ||
       lineStyle != otherLineStyle) {
     // Changes to our text-decoration line can impact our overflow area &
     // also our descendants' overflow areas (particularly for text-frame
     // descendants).  So, we update those areas & trigger a repaint.
     return nsChangeHint_RepaintFrame |
            nsChangeHint_UpdateSubtreeOverflow |
            nsChangeHint_SchedulePaint;
   }
 
   // Repaint for decoration color changes
   nscolor decColor, otherDecColor;
   bool isFG, otherIsFG;
   GetDecorationColor(decColor, isFG);
-  aOther.GetDecorationColor(otherDecColor, otherIsFG);
+  aNewData.GetDecorationColor(otherDecColor, otherIsFG);
   if (isFG != otherIsFG || (!isFG && decColor != otherDecColor)) {
     return nsChangeHint_RepaintFrame;
   }
 
-  if (mTextOverflow != aOther.mTextOverflow) {
+  if (mTextOverflow != aNewData.mTextOverflow) {
     return nsChangeHint_RepaintFrame;
   }
 
   return NS_STYLE_HINT_NONE;
 }
 
 // Returns true if the given shadow-arrays are equal.
 static bool
@@ -3636,98 +3637,98 @@ nsStyleText::nsStyleText(const nsStyleTe
 }
 
 nsStyleText::~nsStyleText()
 {
   MOZ_COUNT_DTOR(nsStyleText);
 }
 
 nsChangeHint
-nsStyleText::CalcDifference(const nsStyleText& aOther) const
+nsStyleText::CalcDifference(const nsStyleText& aNewData) const
 {
   if (WhiteSpaceOrNewlineIsSignificant() !=
-      aOther.WhiteSpaceOrNewlineIsSignificant()) {
+      aNewData.WhiteSpaceOrNewlineIsSignificant()) {
     // This may require construction of suppressed text frames
     return NS_STYLE_HINT_FRAMECHANGE;
   }
 
-  if (mTextCombineUpright != aOther.mTextCombineUpright ||
-      mControlCharacterVisibility != aOther.mControlCharacterVisibility) {
+  if (mTextCombineUpright != aNewData.mTextCombineUpright ||
+      mControlCharacterVisibility != aNewData.mControlCharacterVisibility) {
     return nsChangeHint_ReconstructFrame;
   }
 
-  if ((mTextAlign != aOther.mTextAlign) ||
-      (mTextAlignLast != aOther.mTextAlignLast) ||
-      (mTextAlignTrue != aOther.mTextAlignTrue) ||
-      (mTextAlignLastTrue != aOther.mTextAlignLastTrue) ||
-      (mTextTransform != aOther.mTextTransform) ||
-      (mWhiteSpace != aOther.mWhiteSpace) ||
-      (mWordBreak != aOther.mWordBreak) ||
-      (mOverflowWrap != aOther.mOverflowWrap) ||
-      (mHyphens != aOther.mHyphens) ||
-      (mRubyAlign != aOther.mRubyAlign) ||
-      (mRubyPosition != aOther.mRubyPosition) ||
-      (mTextSizeAdjust != aOther.mTextSizeAdjust) ||
-      (mLetterSpacing != aOther.mLetterSpacing) ||
-      (mLineHeight != aOther.mLineHeight) ||
-      (mTextIndent != aOther.mTextIndent) ||
-      (mWordSpacing != aOther.mWordSpacing) ||
-      (mTabSize != aOther.mTabSize))
+  if ((mTextAlign != aNewData.mTextAlign) ||
+      (mTextAlignLast != aNewData.mTextAlignLast) ||
+      (mTextAlignTrue != aNewData.mTextAlignTrue) ||
+      (mTextAlignLastTrue != aNewData.mTextAlignLastTrue) ||
+      (mTextTransform != aNewData.mTextTransform) ||
+      (mWhiteSpace != aNewData.mWhiteSpace) ||
+      (mWordBreak != aNewData.mWordBreak) ||
+      (mOverflowWrap != aNewData.mOverflowWrap) ||
+      (mHyphens != aNewData.mHyphens) ||
+      (mRubyAlign != aNewData.mRubyAlign) ||
+      (mRubyPosition != aNewData.mRubyPosition) ||
+      (mTextSizeAdjust != aNewData.mTextSizeAdjust) ||
+      (mLetterSpacing != aNewData.mLetterSpacing) ||
+      (mLineHeight != aNewData.mLineHeight) ||
+      (mTextIndent != aNewData.mTextIndent) ||
+      (mWordSpacing != aNewData.mWordSpacing) ||
+      (mTabSize != aNewData.mTabSize))
     return NS_STYLE_HINT_REFLOW;
 
-  if (HasTextEmphasis() != aOther.HasTextEmphasis() ||
+  if (HasTextEmphasis() != aNewData.HasTextEmphasis() ||
       (HasTextEmphasis() &&
-       mTextEmphasisPosition != aOther.mTextEmphasisPosition)) {
+       mTextEmphasisPosition != aNewData.mTextEmphasisPosition)) {
     // Text emphasis position change could affect line height calculation.
     return nsChangeHint_AllReflowHints |
            nsChangeHint_RepaintFrame;
   }
 
   nsChangeHint hint = nsChangeHint(0);
 
   // text-rendering changes require a reflow since they change SVG
   // frames' rects.
-  if (mTextRendering != aOther.mTextRendering) {
+  if (mTextRendering != aNewData.mTextRendering) {
     hint |= nsChangeHint_NeedReflow |
             nsChangeHint_NeedDirtyReflow | // XXX remove me: bug 876085
             nsChangeHint_RepaintFrame;
   }
 
-  if (!AreShadowArraysEqual(mTextShadow, aOther.mTextShadow) ||
-      mTextEmphasisStyle != aOther.mTextEmphasisStyle ||
-      mTextEmphasisStyleString != aOther.mTextEmphasisStyleString ||
-      mWebkitTextStrokeWidth != aOther.mWebkitTextStrokeWidth) {
+  if (!AreShadowArraysEqual(mTextShadow, aNewData.mTextShadow) ||
+      mTextEmphasisStyle != aNewData.mTextEmphasisStyle ||
+      mTextEmphasisStyleString != aNewData.mTextEmphasisStyleString ||
+      mWebkitTextStrokeWidth != aNewData.mWebkitTextStrokeWidth) {
     hint |= nsChangeHint_UpdateSubtreeOverflow |
             nsChangeHint_SchedulePaint |
             nsChangeHint_RepaintFrame;
 
     // We don't add any other hints below.
     return hint;
   }
 
   MOZ_ASSERT(!mTextEmphasisColorForeground ||
-             !aOther.mTextEmphasisColorForeground ||
-             mTextEmphasisColor == aOther.mTextEmphasisColor,
+             !aNewData.mTextEmphasisColorForeground ||
+             mTextEmphasisColor == aNewData.mTextEmphasisColor,
              "If the text-emphasis-color are both foreground color, "
              "mTextEmphasisColor should also be identical");
-  if (mTextEmphasisColorForeground != aOther.mTextEmphasisColorForeground ||
-      mTextEmphasisColor != aOther.mTextEmphasisColor ||
-      mWebkitTextFillColorForeground != aOther.mWebkitTextFillColorForeground ||
-      mWebkitTextFillColor != aOther.mWebkitTextFillColor ||
-      mWebkitTextStrokeColorForeground != aOther.mWebkitTextStrokeColorForeground ||
-      mWebkitTextStrokeColor != aOther.mWebkitTextStrokeColor) {
+  if (mTextEmphasisColorForeground != aNewData.mTextEmphasisColorForeground ||
+      mTextEmphasisColor != aNewData.mTextEmphasisColor ||
+      mWebkitTextFillColorForeground != aNewData.mWebkitTextFillColorForeground ||
+      mWebkitTextFillColor != aNewData.mWebkitTextFillColor ||
+      mWebkitTextStrokeColorForeground != aNewData.mWebkitTextStrokeColorForeground ||
+      mWebkitTextStrokeColor != aNewData.mWebkitTextStrokeColor) {
     hint |= nsChangeHint_SchedulePaint |
             nsChangeHint_RepaintFrame;
   }
 
   if (hint) {
     return hint;
   }
 
-  if (mTextEmphasisPosition != aOther.mTextEmphasisPosition) {
+  if (mTextEmphasisPosition != aNewData.mTextEmphasisPosition) {
     return nsChangeHint_NeutralChange;
   }
 
   return NS_STYLE_HINT_NONE;
 }
 
 LogicalSide
 nsStyleText::TextEmphasisSide(WritingMode aWM) const
@@ -3809,48 +3810,48 @@ nsStyleUserInterface::nsStyleUserInterfa
 
 nsStyleUserInterface::~nsStyleUserInterface()
 {
   MOZ_COUNT_DTOR(nsStyleUserInterface);
   delete [] mCursorArray;
 }
 
 nsChangeHint
-nsStyleUserInterface::CalcDifference(const nsStyleUserInterface& aOther) const
+nsStyleUserInterface::CalcDifference(const nsStyleUserInterface& aNewData) const
 {
   nsChangeHint hint = nsChangeHint(0);
-  if (mCursor != aOther.mCursor)
+  if (mCursor != aNewData.mCursor)
     hint |= nsChangeHint_UpdateCursor;
 
   // We could do better. But it wouldn't be worth it, URL-specified cursors are
   // rare.
-  if (mCursorArrayLength > 0 || aOther.mCursorArrayLength > 0)
+  if (mCursorArrayLength > 0 || aNewData.mCursorArrayLength > 0)
     hint |= nsChangeHint_UpdateCursor;
 
-  if (mPointerEvents != aOther.mPointerEvents) {
+  if (mPointerEvents != aNewData.mPointerEvents) {
     // nsSVGPathGeometryFrame's mRect depends on stroke _and_ on the value
     // of pointer-events. See nsSVGPathGeometryFrame::ReflowSVG's use of
     // GetHitTestFlags. (Only a reflow, no visual change.)
     hint |= nsChangeHint_NeedReflow |
             nsChangeHint_NeedDirtyReflow; // XXX remove me: bug 876085
   }
 
-  if (mUserModify != aOther.mUserModify)
+  if (mUserModify != aNewData.mUserModify)
     hint |= NS_STYLE_HINT_VISUAL;
   
-  if (mUserInput != aOther.mUserInput) {
+  if (mUserInput != aNewData.mUserInput) {
     if (NS_STYLE_USER_INPUT_NONE == mUserInput ||
-        NS_STYLE_USER_INPUT_NONE == aOther.mUserInput) {
+        NS_STYLE_USER_INPUT_NONE == aNewData.mUserInput) {
       hint |= NS_STYLE_HINT_FRAMECHANGE;
     } else {
       hint |= nsChangeHint_NeutralChange;
     }
   }
 
-  if (mUserFocus != aOther.mUserFocus) {
+  if (mUserFocus != aNewData.mUserFocus) {
     hint |= nsChangeHint_NeutralChange;
   }
 
   return hint;
 }
 
 void
 nsStyleUserInterface::CopyCursorArrayFrom(const nsStyleUserInterface& aSource)
@@ -3892,31 +3893,31 @@ nsStyleUIReset::nsStyleUIReset(const nsS
 }
 
 nsStyleUIReset::~nsStyleUIReset()
 {
   MOZ_COUNT_DTOR(nsStyleUIReset);
 }
 
 nsChangeHint
-nsStyleUIReset::CalcDifference(const nsStyleUIReset& aOther) const
+nsStyleUIReset::CalcDifference(const nsStyleUIReset& aNewData) const
 {
   // ignore mIMEMode
-  if (mForceBrokenImageIcon != aOther.mForceBrokenImageIcon)
+  if (mForceBrokenImageIcon != aNewData.mForceBrokenImageIcon)
     return NS_STYLE_HINT_FRAMECHANGE;
-  if (mWindowShadow != aOther.mWindowShadow) {
+  if (mWindowShadow != aNewData.mWindowShadow) {
     // We really need just an nsChangeHint_SyncFrameView, except
     // on an ancestor of the frame, so we get that by doing a
     // reflow.
     return NS_STYLE_HINT_REFLOW;
   }
-  if (mUserSelect != aOther.mUserSelect)
+  if (mUserSelect != aNewData.mUserSelect)
     return NS_STYLE_HINT_VISUAL;
 
-  if (mWindowDragging != aOther.mWindowDragging) {
+  if (mWindowDragging != aNewData.mWindowDragging) {
     return nsChangeHint_SchedulePaint;
   }
 
   return NS_STYLE_HINT_NONE;
 }
 
 //-----------------------
 // nsStyleVariables
@@ -3934,17 +3935,17 @@ nsStyleVariables::nsStyleVariables(const
 }
 
 nsStyleVariables::~nsStyleVariables()
 {
   MOZ_COUNT_DTOR(nsStyleVariables);
 }
 
 nsChangeHint
-nsStyleVariables::CalcDifference(const nsStyleVariables& aOther) const
+nsStyleVariables::CalcDifference(const nsStyleVariables& aNewData) const
 {
   return nsChangeHint(0);
 }
 
 //-----------------------
 // nsStyleEffects
 //
 
@@ -3970,71 +3971,71 @@ nsStyleEffects::nsStyleEffects(const nsS
 }
 
 nsStyleEffects::~nsStyleEffects()
 {
   MOZ_COUNT_DTOR(nsStyleEffects);
 }
 
 nsChangeHint
-nsStyleEffects::CalcDifference(const nsStyleEffects& aOther) const
+nsStyleEffects::CalcDifference(const nsStyleEffects& aNewData) const
 {
   nsChangeHint hint = nsChangeHint(0);
 
-  if (!AreShadowArraysEqual(mBoxShadow, aOther.mBoxShadow)) {
+  if (!AreShadowArraysEqual(mBoxShadow, aNewData.mBoxShadow)) {
     // Update overflow regions & trigger DLBI to be sure it's noticed.
     // Also request a repaint, since it's possible that only the color
     // of the shadow is changing (and UpdateOverflow/SchedulePaint won't
     // repaint for that, since they won't know what needs invalidating.)
     hint |= nsChangeHint_UpdateOverflow |
             nsChangeHint_SchedulePaint |
             nsChangeHint_RepaintFrame;
   }
 
-  if (mClipFlags != aOther.mClipFlags) {
+  if (mClipFlags != aNewData.mClipFlags) {
     hint |= nsChangeHint_AllReflowHints |
             nsChangeHint_RepaintFrame;
   }
 
-  if (!mClip.IsEqualInterior(aOther.mClip)) {
+  if (!mClip.IsEqualInterior(aNewData.mClip)) {
     // If the clip has changed, we just need to update overflow areas. DLBI
     // will handle the invalidation.
     hint |= nsChangeHint_UpdateOverflow |
             nsChangeHint_SchedulePaint;
   }
 
-  if (mOpacity != aOther.mOpacity) {
+  if (mOpacity != aNewData.mOpacity) {
     // If we're going from the optimized >=0.99 opacity value to 1.0 or back, then
     // repaint the frame because DLBI will not catch the invalidation.  Otherwise,
     // just update the opacity layer.
-    if ((mOpacity >= 0.99f && mOpacity < 1.0f && aOther.mOpacity == 1.0f) ||
-        (aOther.mOpacity >= 0.99f && aOther.mOpacity < 1.0f && mOpacity == 1.0f)) {
+    if ((mOpacity >= 0.99f && mOpacity < 1.0f && aNewData.mOpacity == 1.0f) ||
+        (aNewData.mOpacity >= 0.99f && aNewData.mOpacity < 1.0f && mOpacity == 1.0f)) {
       hint |= nsChangeHint_RepaintFrame;
     } else {
       hint |= nsChangeHint_UpdateOpacityLayer;
-      if ((mOpacity == 1.0f) != (aOther.mOpacity == 1.0f)) {
+      if ((mOpacity == 1.0f) != (aNewData.mOpacity == 1.0f)) {
         hint |= nsChangeHint_UpdateUsesOpacity;
       }
     }
   }
 
-  if (HasFilters() != aOther.HasFilters()) {
+  if (HasFilters() != aNewData.HasFilters()) {
     // A change from/to being a containing block for position:fixed.
     hint |= nsChangeHint_UpdateContainingBlock;
   }
 
-  if (mFilters != aOther.mFilters) {
+  if (mFilters != aNewData.mFilters) {
     hint |= nsChangeHint_UpdateEffects |
             nsChangeHint_RepaintFrame |
             nsChangeHint_UpdateOverflow;
   }
 
-  if (mMixBlendMode != aOther.mMixBlendMode) {
+  if (mMixBlendMode != aNewData.mMixBlendMode) {
     hint |= nsChangeHint_RepaintFrame;
   }
 
   if (!hint &&
-      !mClip.IsEqualEdges(aOther.mClip)) {
+      !mClip.IsEqualEdges(aNewData.mClip)) {
     hint |= nsChangeHint_NeutralChange;
   }
 
   return hint;
 }
--- a/layout/style/nsStyleStruct.h
+++ b/layout/style/nsStyleStruct.h
@@ -114,17 +114,17 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsSt
 {
   nsStyleFont(const nsFont& aFont, StyleStructContext aContext);
   nsStyleFont(const nsStyleFont& aStyleFont);
   explicit nsStyleFont(StyleStructContext aContext);
   ~nsStyleFont() {
     MOZ_COUNT_DTOR(nsStyleFont);
   }
 
-  nsChangeHint CalcDifference(const nsStyleFont& aOther) const;
+  nsChangeHint CalcDifference(const nsStyleFont& aNewData) const;
   static nsChangeHint MaxDifference() {
     return NS_STYLE_HINT_REFLOW |
            nsChangeHint_NeutralChange;
   }
   static nsChangeHint DifferenceAlwaysHandledForDescendants() {
     // CalcDifference never returns the reflow hints that are sometimes
     // handled for descendants as hints not handled for descendants.
     return nsChangeHint_NeedReflow |
@@ -382,17 +382,17 @@ private:
 struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleColor
 {
   explicit nsStyleColor(StyleStructContext aContext);
   nsStyleColor(const nsStyleColor& aOther);
   ~nsStyleColor() {
     MOZ_COUNT_DTOR(nsStyleColor);
   }
 
-  nsChangeHint CalcDifference(const nsStyleColor& aOther) const;
+  nsChangeHint CalcDifference(const nsStyleColor& aNewData) const;
   static nsChangeHint MaxDifference() {
     return nsChangeHint_RepaintFrame;
   }
   static nsChangeHint DifferenceAlwaysHandledForDescendants() {
     // CalcDifference never returns the reflow hints that are sometimes
     // handled for descendants at all.
     return nsChangeHint(0);
   }
@@ -687,17 +687,17 @@ struct nsStyleImageLayers {
     // of the background positioning area changes.  This is true for any
     // non-solid-color background whose position or size depends on
     // the size of the positioning area.  It's also true for SVG images
     // whose root <svg> node has a viewBox.
     bool RenderingMightDependOnPositioningAreaSizeChange() const;
 
     // Compute the change hint required by changes in just this layer.
     // aPositionChangeHint indicates the hint for position change.
-    nsChangeHint CalcDifference(const Layer& aOther,
+    nsChangeHint CalcDifference(const Layer& aNewLayer,
                                 nsChangeHint aPositionChangeHint) const;
 
     // An equality operator that compares the images using URL-equality
     // rather than pointer-equality.
     bool operator==(const Layer& aOther) const;
     bool operator!=(const Layer& aOther) const {
       return !(*this == aOther);
     }
@@ -736,17 +736,17 @@ struct nsStyleImageLayers {
         mLayers[i].TrackImages(aContext);
     }
   }
   void UntrackImages(nsPresContext* aContext) {
     for (uint32_t i = 0; i < mImageCount; ++i)
       mLayers[i].UntrackImages(aContext);
   }
 
-  nsChangeHint CalcDifference(const nsStyleImageLayers& aOther,
+  nsChangeHint CalcDifference(const nsStyleImageLayers& aNewLayers,
                               nsChangeHint aPositionChangeHint) const;
 
   bool HasLayerWithImage() const;
 
   static const nsCSSProperty kBackgroundLayerTable[];
   static const nsCSSProperty kMaskLayerTable[];
 
   #define NS_FOR_VISIBLE_IMAGE_LAYERS_BACK_TO_FRONT(var_, layers_) \
@@ -764,17 +764,17 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsSt
 
   void* operator new(size_t sz, nsStyleBackground* aSelf) CPP_THROW_NEW { return aSelf; }
   void* operator new(size_t sz, nsPresContext* aContext) CPP_THROW_NEW {
     return aContext->PresShell()->
       AllocateByObjectID(mozilla::eArenaObjectID_nsStyleBackground, sz);
   }
   void Destroy(nsPresContext* aContext);
 
-  nsChangeHint CalcDifference(const nsStyleBackground& aOther) const;
+  nsChangeHint CalcDifference(const nsStyleBackground& aNewData) const;
   static nsChangeHint MaxDifference() {
      return nsChangeHint_UpdateEffects |
            nsChangeHint_RepaintFrame |
            nsChangeHint_UpdateBackgroundPosition |
            nsChangeHint_NeutralChange;
   }
   static nsChangeHint DifferenceAlwaysHandledForDescendants() {
     // CalcDifference never returns the reflow hints that are sometimes
@@ -820,17 +820,17 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsSt
 
   void* operator new(size_t sz, nsStyleMargin* aSelf) CPP_THROW_NEW { return aSelf; }
   void* operator new(size_t sz, nsPresContext* aContext) CPP_THROW_NEW {
     return aContext->PresShell()->
       AllocateByObjectID(mozilla::eArenaObjectID_nsStyleMargin, sz);
   }
   void Destroy(nsPresContext* aContext);
 
-  nsChangeHint CalcDifference(const nsStyleMargin& aOther) const;
+  nsChangeHint CalcDifference(const nsStyleMargin& aNewData) const;
   static nsChangeHint MaxDifference() {
     return nsChangeHint_NeedReflow |
            nsChangeHint_ReflowChangesSizeOrPosition |
            nsChangeHint_ClearAncestorIntrinsics;
   }
   static nsChangeHint DifferenceAlwaysHandledForDescendants() {
     // CalcDifference can return all of the reflow hints sometimes not
     // handled for descendants as hints not handled for descendants.
@@ -867,17 +867,17 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsSt
 
   void* operator new(size_t sz, nsStylePadding* aSelf) CPP_THROW_NEW { return aSelf; }
   void* operator new(size_t sz, nsPresContext* aContext) CPP_THROW_NEW {
     return aContext->PresShell()->
       AllocateByObjectID(mozilla::eArenaObjectID_nsStylePadding, sz);
   }
   void Destroy(nsPresContext* aContext);
 
-  nsChangeHint CalcDifference(const nsStylePadding& aOther) const;
+  nsChangeHint CalcDifference(const nsStylePadding& aNewData) const;
   static nsChangeHint MaxDifference() {
     return NS_STYLE_HINT_REFLOW & ~nsChangeHint_ClearDescendantIntrinsics;
   }
   static nsChangeHint DifferenceAlwaysHandledForDescendants() {
     // CalcDifference can return nsChangeHint_ClearAncestorIntrinsics as
     // a hint not handled for descendants.  We could (and perhaps
     // should) return nsChangeHint_NeedReflow and
     // nsChangeHint_ReflowChangesSizeOrPosition as always handled for
@@ -1069,17 +1069,17 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsSt
 
   void* operator new(size_t sz, nsStyleBorder* aSelf) CPP_THROW_NEW { return aSelf; }
   void* operator new(size_t sz, nsPresContext* aContext) CPP_THROW_NEW {
     return aContext->PresShell()->
       AllocateByObjectID(mozilla::eArenaObjectID_nsStyleBorder, sz);
   }
   void Destroy(nsPresContext* aContext);
 
-  nsChangeHint CalcDifference(const nsStyleBorder& aOther) const;
+  nsChangeHint CalcDifference(const nsStyleBorder& aNewData) const;
   static nsChangeHint MaxDifference() {
     return NS_STYLE_HINT_REFLOW |
            nsChangeHint_UpdateOverflow |
            nsChangeHint_BorderStyleNoneChange |
            nsChangeHint_NeutralChange;
   }
   static nsChangeHint DifferenceAlwaysHandledForDescendants() {
     // CalcDifference never returns the reflow hints that are sometimes
@@ -1303,17 +1303,17 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsSt
   }
   void Destroy(nsPresContext* aContext) {
     this->~nsStyleOutline();
     aContext->PresShell()->
       FreeByObjectID(mozilla::eArenaObjectID_nsStyleOutline, this);
   }
 
   void RecalcData();
-  nsChangeHint CalcDifference(const nsStyleOutline& aOther) const;
+  nsChangeHint CalcDifference(const nsStyleOutline& aNewData) const;
   static nsChangeHint MaxDifference() {
     return nsChangeHint_UpdateOverflow |
            nsChangeHint_SchedulePaint |
            nsChangeHint_RepaintFrame |
            nsChangeHint_NeutralChange;
   }
   static nsChangeHint DifferenceAlwaysHandledForDescendants() {
     // CalcDifference never returns the reflow hints that are sometimes
@@ -1415,17 +1415,17 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsSt
       AllocateByObjectID(mozilla::eArenaObjectID_nsStyleList, sz);
   }
   void Destroy(nsPresContext* aContext) {
     this->~nsStyleList();
     aContext->PresShell()->
       FreeByObjectID(mozilla::eArenaObjectID_nsStyleList, this);
   }
 
-  nsChangeHint CalcDifference(const nsStyleList& aOther) const;
+  nsChangeHint CalcDifference(const nsStyleList& aNewData) const;
   static nsChangeHint MaxDifference() {
     return NS_STYLE_HINT_FRAMECHANGE |
            nsChangeHint_NeutralChange;
   }
   static nsChangeHint DifferenceAlwaysHandledForDescendants() {
     // CalcDifference never returns the reflow hints that are sometimes
     // handled for descendants as hints not handled for descendants.
     return nsChangeHint_NeedReflow |
@@ -1640,17 +1640,17 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsSt
       AllocateByObjectID(mozilla::eArenaObjectID_nsStylePosition, sz);
   }
   void Destroy(nsPresContext* aContext) {
     this->~nsStylePosition();
     aContext->PresShell()->
       FreeByObjectID(mozilla::eArenaObjectID_nsStylePosition, this);
   }
 
-  nsChangeHint CalcDifference(const nsStylePosition& aOther,
+  nsChangeHint CalcDifference(const nsStylePosition& aNewData,
                               const nsStyleVisibility* aOldStyleVisibility) const;
   static nsChangeHint MaxDifference() {
     return NS_STYLE_HINT_REFLOW |
            nsChangeHint_NeutralChange |
            nsChangeHint_RecomputePosition |
            nsChangeHint_UpdateParentOverflow |
            nsChangeHint_UpdateComputedBSize;
   }
@@ -1935,17 +1935,17 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsSt
   }
 
   void SetDecorationColorToForeground()
   {
     mTextDecorationStyle &= ~BORDER_COLOR_SPECIAL;
     mTextDecorationStyle |= BORDER_COLOR_FOREGROUND;
   }
 
-  nsChangeHint CalcDifference(const nsStyleTextReset& aOther) const;
+  nsChangeHint CalcDifference(const nsStyleTextReset& aNewData) const;
   static nsChangeHint MaxDifference() {
     return nsChangeHint(
         NS_STYLE_HINT_REFLOW |
         nsChangeHint_UpdateSubtreeOverflow);
   }
   static nsChangeHint DifferenceAlwaysHandledForDescendants() {
     // CalcDifference never returns the reflow hints that are sometimes
     // handled for descendants as hints not handled for descendants.
@@ -1976,17 +1976,17 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsSt
       AllocateByObjectID(mozilla::eArenaObjectID_nsStyleText, sz);
   }
   void Destroy(nsPresContext* aContext) {
     this->~nsStyleText();
     aContext->PresShell()->
       FreeByObjectID(mozilla::eArenaObjectID_nsStyleText, this);
   }
 
-  nsChangeHint CalcDifference(const nsStyleText& aOther) const;
+  nsChangeHint CalcDifference(const nsStyleText& aNewData) const;
   static nsChangeHint MaxDifference() {
     return NS_STYLE_HINT_FRAMECHANGE |
            nsChangeHint_UpdateSubtreeOverflow |
            nsChangeHint_NeutralChange;
   }
   static nsChangeHint DifferenceAlwaysHandledForDescendants() {
     // CalcDifference never returns the reflow hints that are sometimes
     // handled for descendants as hints not handled for descendants.
@@ -2195,17 +2195,17 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsSt
       AllocateByObjectID(mozilla::eArenaObjectID_nsStyleVisibility, sz);
   }
   void Destroy(nsPresContext* aContext) {
     this->~nsStyleVisibility();
     aContext->PresShell()->
       FreeByObjectID(mozilla::eArenaObjectID_nsStyleVisibility, this);
   }
 
-  nsChangeHint CalcDifference(const nsStyleVisibility& aOther) const;
+  nsChangeHint CalcDifference(const nsStyleVisibility& aNewData) const;
   static nsChangeHint MaxDifference() {
     return NS_STYLE_HINT_FRAMECHANGE |
            nsChangeHint_NeutralChange;
   }
   static nsChangeHint DifferenceAlwaysHandledForDescendants() {
     // CalcDifference never returns the reflow hints that are sometimes
     // handled for descendants as hints not handled for descendants.
     return nsChangeHint_NeedReflow |
@@ -2476,17 +2476,17 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsSt
       AllocateByObjectID(mozilla::eArenaObjectID_nsStyleDisplay, sz);
   }
   void Destroy(nsPresContext* aContext) {
     this->~nsStyleDisplay();
     aContext->PresShell()->
       FreeByObjectID(mozilla::eArenaObjectID_nsStyleDisplay, this);
   }
 
-  nsChangeHint CalcDifference(const nsStyleDisplay& aOther) const;
+  nsChangeHint CalcDifference(const nsStyleDisplay& aNewData) const;
   static nsChangeHint MaxDifference() {
     // All the parts of FRAMECHANGE are present in CalcDifference.
     return nsChangeHint(NS_STYLE_HINT_FRAMECHANGE |
                         nsChangeHint_UpdateTransformLayer |
                         nsChangeHint_UpdateOverflow |
                         nsChangeHint_UpdatePostTransformOverflow |
                         nsChangeHint_UpdateContainingBlock |
                         nsChangeHint_NeutralChange);
@@ -2748,17 +2748,17 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsSt
       AllocateByObjectID(mozilla::eArenaObjectID_nsStyleTable, sz);
   }
   void Destroy(nsPresContext* aContext) {
     this->~nsStyleTable();
     aContext->PresShell()->
       FreeByObjectID(mozilla::eArenaObjectID_nsStyleTable, this);
   }
 
-  nsChangeHint CalcDifference(const nsStyleTable& aOther) const;
+  nsChangeHint CalcDifference(const nsStyleTable& aNewData) const;
   static nsChangeHint MaxDifference() {
     return NS_STYLE_HINT_FRAMECHANGE;
   }
   static nsChangeHint DifferenceAlwaysHandledForDescendants() {
     // CalcDifference never returns the reflow hints that are sometimes
     // handled for descendants as hints not handled for descendants.
     return nsChangeHint_NeedReflow |
            nsChangeHint_ReflowChangesSizeOrPosition |
@@ -2781,17 +2781,17 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsSt
       AllocateByObjectID(mozilla::eArenaObjectID_nsStyleTableBorder, sz);
   }
   void Destroy(nsPresContext* aContext) {
     this->~nsStyleTableBorder();
     aContext->PresShell()->
       FreeByObjectID(mozilla::eArenaObjectID_nsStyleTableBorder, this);
   }
 
-  nsChangeHint CalcDifference(const nsStyleTableBorder& aOther) const;
+  nsChangeHint CalcDifference(const nsStyleTableBorder& aNewData) const;
   static nsChangeHint MaxDifference() {
     return NS_STYLE_HINT_FRAMECHANGE;
   }
   static nsChangeHint DifferenceAlwaysHandledForDescendants() {
     // CalcDifference never returns the reflow hints that are sometimes
     // handled for descendants as hints not handled for descendants.
     return nsChangeHint_NeedReflow |
            nsChangeHint_ReflowChangesSizeOrPosition |
@@ -2877,17 +2877,17 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsSt
 
   void* operator new(size_t sz, nsStyleContent* aSelf) CPP_THROW_NEW { return aSelf; }
   void* operator new(size_t sz, nsPresContext* aContext) CPP_THROW_NEW {
     return aContext->PresShell()->
       AllocateByObjectID(mozilla::eArenaObjectID_nsStyleContent, sz);
   }
   void Destroy(nsPresContext* aContext);
 
-  nsChangeHint CalcDifference(const nsStyleContent& aOther) const;
+  nsChangeHint CalcDifference(const nsStyleContent& aNewData) const;
   static nsChangeHint MaxDifference() {
     return NS_STYLE_HINT_FRAMECHANGE;
   }
   static nsChangeHint DifferenceAlwaysHandledForDescendants() {
     // CalcDifference never returns the reflow hints that are sometimes
     // handled for descendants as hints not handled for descendants.
     return nsChangeHint_NeedReflow |
            nsChangeHint_ReflowChangesSizeOrPosition |
@@ -2992,17 +2992,17 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsSt
       AllocateByObjectID(mozilla::eArenaObjectID_nsStyleUIReset, sz);
   }
   void Destroy(nsPresContext* aContext) {
     this->~nsStyleUIReset();
     aContext->PresShell()->
       FreeByObjectID(mozilla::eArenaObjectID_nsStyleUIReset, this);
   }
 
-  nsChangeHint CalcDifference(const nsStyleUIReset& aOther) const;
+  nsChangeHint CalcDifference(const nsStyleUIReset& aNewData) const;
   static nsChangeHint MaxDifference() {
     return NS_STYLE_HINT_FRAMECHANGE;
   }
   static nsChangeHint DifferenceAlwaysHandledForDescendants() {
     // CalcDifference never returns the reflow hints that are sometimes
     // handled for descendants as hints not handled for descendants.
     return nsChangeHint_NeedReflow |
            nsChangeHint_ReflowChangesSizeOrPosition |
@@ -3058,17 +3058,17 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsSt
       AllocateByObjectID(mozilla::eArenaObjectID_nsStyleUserInterface, sz);
   }
   void Destroy(nsPresContext* aContext) {
     this->~nsStyleUserInterface();
     aContext->PresShell()->
       FreeByObjectID(mozilla::eArenaObjectID_nsStyleUserInterface, this);
   }
 
-  nsChangeHint CalcDifference(const nsStyleUserInterface& aOther) const;
+  nsChangeHint CalcDifference(const nsStyleUserInterface& aNewData) const;
   static nsChangeHint MaxDifference() {
     return NS_STYLE_HINT_FRAMECHANGE |
            nsChangeHint_UpdateCursor |
            nsChangeHint_NeutralChange;
   }
   static nsChangeHint DifferenceAlwaysHandledForDescendants() {
     // CalcDifference never returns the reflow hints that are sometimes
     // handled for descendants as hints not handled for descendants.
@@ -3109,17 +3109,17 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsSt
       AllocateByObjectID(mozilla::eArenaObjectID_nsStyleXUL, sz);
   }
   void Destroy(nsPresContext* aContext) {
     this->~nsStyleXUL();
     aContext->PresShell()->
       FreeByObjectID(mozilla::eArenaObjectID_nsStyleXUL, this);
   }
 
-  nsChangeHint CalcDifference(const nsStyleXUL& aOther) const;
+  nsChangeHint CalcDifference(const nsStyleXUL& aNewData) const;
   static nsChangeHint MaxDifference() {
     return NS_STYLE_HINT_FRAMECHANGE;
   }
   static nsChangeHint DifferenceAlwaysHandledForDescendants() {
     // CalcDifference never returns the reflow hints that are sometimes
     // handled for descendants as hints not handled for descendants.
     return nsChangeHint_NeedReflow |
            nsChangeHint_ReflowChangesSizeOrPosition |
@@ -3147,17 +3147,17 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsSt
       AllocateByObjectID(mozilla::eArenaObjectID_nsStyleColumn, sz);
   }
   void Destroy(nsPresContext* aContext) {
     this->~nsStyleColumn();
     aContext->PresShell()->
       FreeByObjectID(mozilla::eArenaObjectID_nsStyleColumn, this);
   }
 
-  nsChangeHint CalcDifference(const nsStyleColumn& aOther) const;
+  nsChangeHint CalcDifference(const nsStyleColumn& aNewData) const;
   static nsChangeHint MaxDifference() {
     return NS_STYLE_HINT_FRAMECHANGE |
            nsChangeHint_NeutralChange;
   }
   static nsChangeHint DifferenceAlwaysHandledForDescendants() {
     // CalcDifference never returns the reflow hints that are sometimes
     // handled for descendants as hints not handled for descendants.
     return nsChangeHint_NeedReflow |
@@ -3244,17 +3244,17 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsSt
       AllocateByObjectID(mozilla::eArenaObjectID_nsStyleSVG, sz);
   }
   void Destroy(nsPresContext* aContext) {
     this->~nsStyleSVG();
     aContext->PresShell()->
       FreeByObjectID(mozilla::eArenaObjectID_nsStyleSVG, this);
   }
 
-  nsChangeHint CalcDifference(const nsStyleSVG& aOther) const;
+  nsChangeHint CalcDifference(const nsStyleSVG& aNewData) const;
   static nsChangeHint MaxDifference() {
     return nsChangeHint_UpdateEffects |
            nsChangeHint_NeedReflow |
            nsChangeHint_NeedDirtyReflow | // XXX remove me: bug 876085
            nsChangeHint_RepaintFrame;
   }
   static nsChangeHint DifferenceAlwaysHandledForDescendants() {
     // CalcDifference never returns nsChangeHint_NeedReflow as a hint
@@ -3572,17 +3572,17 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsSt
 
   void* operator new(size_t sz, nsStyleSVGReset* aSelf) CPP_THROW_NEW { return aSelf; }
   void* operator new(size_t sz, nsPresContext* aContext) CPP_THROW_NEW {
     return aContext->PresShell()->
       AllocateByObjectID(mozilla::eArenaObjectID_nsStyleSVGReset, sz);
   }
   void Destroy(nsPresContext* aContext);
 
-  nsChangeHint CalcDifference(const nsStyleSVGReset& aOther) const;
+  nsChangeHint CalcDifference(const nsStyleSVGReset& aNewData) const;
   static nsChangeHint MaxDifference() {
     return nsChangeHint_UpdateEffects |
            nsChangeHint_UpdateOverflow |
            nsChangeHint_NeutralChange |
            nsChangeHint_RepaintFrame |
            NS_STYLE_HINT_REFLOW;
   }
   static nsChangeHint DifferenceAlwaysHandledForDescendants() {
@@ -3627,17 +3627,17 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsSt
       AllocateByObjectID(mozilla::eArenaObjectID_nsStyleVariables, sz);
   }
   void Destroy(nsPresContext* aContext) {
     this->~nsStyleVariables();
     aContext->PresShell()->
       FreeByObjectID(mozilla::eArenaObjectID_nsStyleVariables, this);
   }
 
-  nsChangeHint CalcDifference(const nsStyleVariables& aOther) const;
+  nsChangeHint CalcDifference(const nsStyleVariables& aNewData) const;
   static nsChangeHint MaxDifference() {
     return nsChangeHint(0);
   }
   static nsChangeHint DifferenceAlwaysHandledForDescendants() {
     // CalcDifference never returns nsChangeHint_NeedReflow or
     // nsChangeHint_ClearAncestorIntrinsics at all.
     return nsChangeHint(0);
   }
@@ -3657,17 +3657,17 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsSt
       AllocateByObjectID(mozilla::eArenaObjectID_nsStyleEffects, sz);
   }
   void Destroy(nsPresContext* aContext) {
     this->~nsStyleEffects();
     aContext->PresShell()->
       FreeByObjectID(mozilla::eArenaObjectID_nsStyleEffects, this);
   }
 
-  nsChangeHint CalcDifference(const nsStyleEffects& aOther) const;
+  nsChangeHint CalcDifference(const nsStyleEffects& aNewData) const;
   static nsChangeHint MaxDifference() {
     return nsChangeHint_AllReflowHints |
            nsChangeHint_UpdateOverflow |
            nsChangeHint_SchedulePaint |
            nsChangeHint_RepaintFrame |
            nsChangeHint_UpdateOpacityLayer |
            nsChangeHint_UpdateUsesOpacity |
            nsChangeHint_UpdateContainingBlock |
--- a/media/libpng/CHANGES
+++ b/media/libpng/CHANGES
@@ -5058,17 +5058,18 @@ Version 1.6.15beta03 [November 3, 2014]
 
 Version 1.6.15beta04 [November 4, 2014]
   Removed new PNG_USE_ARM_NEON configuration flag and made a one-line
     revision to configure.ac to support ARM on aarch64 instead (John Bowler).
 
 Version 1.6.15beta05 [November 5, 2014]
   Use png_get_libpng_ver(NULL) instead of PNG_LIBPNG_VER_STRING in
     example.c, pngtest.c, and applications in the contrib directory.
-  Avoid out-of-bounds memory access in png_user_version_check().
+  Fixed an out-of-range read in png_user_version_check() (Bug report from
+    Qixue Xiao, CVE-2015-8540).
   Simplified and future-proofed png_user_version_check().
   Fixed GCC unsigned int->float warnings. Various versions of GCC
     seem to generate warnings when an unsigned value is implicitly
     converted to double. This is probably a GCC bug but this change
     avoids the issue by explicitly converting to (int) where safe.
   Free all allocated memory in pngimage. The file buffer cache was left
     allocated at the end of the program, harmless but it causes memory
     leak reports from clang.
@@ -5479,16 +5480,127 @@ Version 1.6.21rc02 [January 7, 2016]
   Relocated assert() in contrib/tools/pngfix.c, bug found by American
     Fuzzy Lop, reported by Brian Carpenter.
   Marked 'limit' UNUSED in transform_range_check().  This only affects
     release builds.
 
 Version 1.6.21 [January 15, 2016]
   Worked around a false-positive Coverity issue in pngvalid.c.
 
+Version 1.6.22beta01 [January 23, 2016]
+  Changed PNG_USE_MKSTEMP to __COVERITY__ to select alternate
+    "tmpfile()" implementation in contrib/libtests/pngstest.c
+  Fixed NO_STDIO build of pngunknown.c to skip calling png_init_io()
+    if there is no stdio.h support.
+  Added a png_image_write_to_memory() API and a number of assist macros
+    to allow an application that uses the simplified API write to bypass
+    stdio and write directly to memory.
+  Added some warnings (png.h) and some check code to detect *possible*
+    overflow in the ROW_STRIDE and simplified image SIZE macros.  This
+    disallows image width/height/format that *might* overflow.  This is
+    a quiet API change that limits in-memory image size (uncompressed) to
+    less than 4GByte and image row size (stride) to less than 2GByte.
+  Revised workaround for false-positive Coverity issue in pngvalid.c.
+
+Version 1.6.22beta02 [February 8, 2016]
+  Only use exit(77) in configure builds.
+  Corrected error in PNG_IMAGE_PNG_SIZE_MAX. This new macro underreported
+    the palette size because it failed to take into account that the memory
+    palette has to be expanded to full RGB when it is written to PNG.
+  Updated CMakeLists.txt, added supporting scripts/gen*.cmake.in
+    and test.cmake.in (Roger Leigh).
+  Relaxed limit checks on gamma values in pngrtran.c. As suggested in
+    the comments gamma values outside the range currently permitted
+    by png_set_alpha_mode are useful for HDR data encoding.  These values
+    are already permitted by png_set_gamma so it is reasonable caution to
+    extend the png_set_alpha_mode range as HDR imaging systems are starting
+    to emerge.
+
+Version 1.6.22beta03 [March 9, 2016]
+  Added a common-law trademark notice and export control information
+    to the LICENSE file, png.h, and the man page.
+  Restored "& 0xff" in png_save_uint_16() and png_save_uint_32() that
+    were accidentally removed from libpng-1.6.17. 
+  Changed PNG_INFO_cHNK and PNG_FREE_cHNK from 0xnnnn to 0xnnnnU in png.h
+    (Robert C. Seacord).
+  Removed dubious "#if INT_MAX" test from png.h that was added to
+    libpng-1.6.19beta02 (John Bowler).
+  Add ${INCLUDES} in scripts/genout.cmake.in (Bug report by Nixon Kwok).
+  Updated LICENSE to say files in the contrib directory are not
+    necessarily under the libpng license, and that some makefiles have
+    other copyright owners.
+  Added INTEL-SSE2 support (Mike Klein and Matt Sarett, Google, Inc.).
+  Made contrib/libtests/timepng more robust.  The code no longer gives
+    up/fails on invalid PNG data, it just skips it (with error messages).
+    The code no longer fails on PNG files with data beyond IEND.  Options
+    exist to use png_read_png (reading the whole image, not by row) and, in
+    that case, to apply any of the supported transforms.  This makes for
+    more realistic testing; the decoded data actually gets used in a
+    meaningful fashion (John Bowler).
+  Fixed some misleading indentation (Krishnaraj Bhat).
+
+Version 1.6.22beta04 [April 5, 2016]
+  Force GCC compilation to C89 if needed (Dagobert Michelsen).
+  SSE filter speed improvements for bpp=3:
+    memcpy-free implementations of load3() / store3().
+    call load3() only when needed at the end of a scanline.
+
+Version 1.6.22beta05 [April 27, 2016]
+  Added PNG_FAST_FILTERS macro (defined as
+    PNG_FILTER_NONE|PNG_FILTER_SUB|PNG_FILTER_UP).
+  Various fixes for contrib/libtests/timepng.c
+  Moved INTEL-SSE code from pngpriv.h into contrib/intel/intel_sse.patch.
+  Fixed typo (missing underscore) in #define PNG_READ_16_TO_8_SUPPORTED
+    (Bug report by Y.Ohashik).
+
+Version 1.6.22beta06 [May 5, 2016]
+  Rebased contrib/intel_sse.patch.
+  Quieted two Coverity issues in contrib/libtests/timepng.c.
+  Fixed issues with scripts/genout.cmake.in (David Capello, Nixon Kwok):
+    Added support to use multiple directories in ZLIBINCDIR variable,
+    Fixed CMAKE_C_FLAGS with multiple values when genout is compiled on MSVC,
+    Fixed pnglibconf.c compilation on OS X including the sysroot path.
+
+Version 1.6.22rc01 [May 14, 2016]
+  No changes.
+
+Version 1.6.22rc02 [May 16, 2016]
+  Removed contrib/timepng from default build; it does not build on platforms
+    that don't supply clock_gettime().
+
+Version 1.6.22rc03 [May 17, 2016]
+  Restored contrib/timepng to default build but check for the presence
+    of clock_gettime() in configure.ac and Makefile.am.
+
+Version 1.6.22 [May 26, 2016]
+  No changes.
+
+Version 1.6.23beta01 [May 29, 2016]
+  Stop a potential memory leak in png_set_tRNS() (Bug report by Ted Ying).
+  Fixed the progressive reader to handle empty first IDAT chunk properly
+    (patch by Timothy Nikkel).  This bug was introduced in libpng-1.6.0 and
+    only affected the libpng16 branch.
+  Added tests in pngvalid.c to check zero-length IDAT chunks in various
+    positions.  Fixed the sequential reader to handle these more robustly
+    (John Bowler).
+
+Version 1.6.23rc01 [June 2, 2016]
+  Corrected progressive read input buffer in pngvalid.c. The previous version
+    the code invariably passed just one byte at a time to libpng.  The intent
+    was to pass a random number of bytes in the range 0..511.
+  Moved sse2 prototype from pngpriv.h to contrib/intel/intel_sse.patch.
+  Added missing ")" in pngerror.c (Matt Sarrett).
+
+Version 1.6.23rc02 [June 4, 2016]
+  Fixed undefined behavior in png_push_save_buffer(). Do not call
+    memcpy() with a null source, even if count is zero (Leon Scroggins III).
+
+Version 1.6.23 [June 9, 2016]
+  Fixed bad link to RFC2083 in png.5 (Nikola Forro).
+
 Send comments/corrections/commendations to png-mng-implement at lists.sf.net
 (subscription required; visit
 https://lists.sourceforge.net/lists/listinfo/png-mng-implement
 to subscribe)
 or to glennrp at users.sourceforge.net
 
 Glenn R-P
 #endif
--- a/media/libpng/LICENSE
+++ b/media/libpng/LICENSE
@@ -9,23 +9,23 @@ If you modify libpng you may insert addi
 this sentence.
 
 pnglibconf.h and moz.build are distributed under 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/.
 
 This modified version of libpng code adds animated PNG support and is
 released under the libpng license described below. The modifications are
-Copyright (c) 2006-2007 Andrew Smith, Copyright (c) 2008-2015 Max Stepin,
+Copyright (c) 2006-2007 Andrew Smith, Copyright (c) 2008-2016 Max Stepin,
 and are delimited by "#ifdef PNG_APNG_SUPPORTED / #endif" directives
 surrounding them in the modified libpng source files.
 
 This code is released under the libpng license.
 
-libpng versions 1.0.7, July 1, 2000, through 1.6.21, January 15, 2016, are
+libpng versions 1.0.7, July 1, 2000 through 1.6.23, June 9, 2016 are
 Copyright (c) 2000-2002, 2004, 2006-2016 Glenn Randers-Pehrson, are
 derived from libpng-1.0.6, and are distributed according to the same
 disclaimer and license as libpng-1.0.6 with the following individuals
 added to the list of Contributing Authors:
 
    Simon-Pierre Cadieux
    Eric S. Raymond
    Mans Rullgard
@@ -37,16 +37,20 @@ and with the following additions to the 
 
    There is no warranty against interference with your enjoyment of the
    library or against infringement.  There is no warranty that our
    efforts or the library will fulfill any of your particular purposes
    or needs.  This library is provided with all faults, and the entire
    risk of satisfactory quality, performance, accuracy, and effort is with
    the user.
 
+Some files in the "contrib" directory and some configure-generated
+files that are distributed with libpng have other copyright owners and
+are released under other open source licenses.
+
 libpng versions 0.97, January 1998, through 1.0.6, March 20, 2000, are
 Copyright (c) 1998-2000 Glenn Randers-Pehrson, are derived from
 libpng-0.96, and are distributed according to the same disclaimer and
 license as libpng-0.96, with the following individuals added to the list
 of Contributing Authors:
 
    Tom Lane
    Glenn Randers-Pehrson
@@ -60,16 +64,19 @@ Contributing Authors:
 
    John Bowler
    Kevin Bracey
    Sam Bushell
    Magnus Holmgren
    Greg Roelofs
    Tom Tanner
 
+Some files in the "scripts" directory have other copyright owners
+but are released under this license.
+
 libpng versions 0.5, May 1995, through 0.88, January 1996, are
 Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
 
 For the purposes of this copyright and license, "Contributing Authors"
 is defined as the following set of individuals:
 
    Andreas Dilger
    Dave Martindale
@@ -100,23 +107,34 @@ to the following restrictions:
 The Contributing Authors and Group 42, Inc. specifically permit, without
 fee, and encourage the use of this source code as a component to
 supporting the PNG file format in commercial products.  If you use this
 source code in a product, acknowledgment is not required but would be
 appreciated.
 
 END OF COPYRIGHT NOTICE, DISCLAIMER, and LICENSE.
 
-A "png_get_copyright" function is available, for convenient use in "about"
-boxes and the like:
+TRADEMARK:
 
-   printf("%s", png_get_copyright(NULL));
+The name "libpng" has not been registered by the Copyright owner
+as a trademark in any jurisdiction.  However, because libpng has
+been distributed and maintained world-wide, continually since 1995,
+the Copyright owner claims "common-law trademark protection" in any
+jurisdiction where common-law trademark is recognized.
 
-Also, the PNG logo (in PNG format, of course) is supplied in the
-files "pngbar.png" and "pngbar.jpg (88x31) and "pngnow.png" (98x31).
+OSI CERTIFICATION:
 
 Libpng is OSI Certified Open Source Software.  OSI Certified Open Source is
 a certification mark of the Open Source Initiative. OSI has not addressed
 the additional disclaimers inserted at version 1.0.7.
 
+EXPORT CONTROL:
+
+The Copyright owner believes that the Export Control Classification
+Number (ECCN) for libpng is EAR99, which means not subject to export
+controls or International Traffic in Arms Regulations (ITAR) because
+it is open source, publicly available software, that does not contain
+any encryption software.  See the EAR, paragraphs 734.3(b)(3) and
+734.7(b).
+
 Glenn Randers-Pehrson
 glennrp at users.sourceforge.net
-January 15, 2016
+June 9, 2016
--- a/media/libpng/MOZCHANGES
+++ b/media/libpng/MOZCHANGES
@@ -1,11 +1,13 @@
 
 Changes made to pristine libpng source by mozilla.org developers.
 
+2016/06/09  -- Synced with libpng-1.6.23 (bug #1275901).
+
 2016/01/16  -- Synced with libpng-1.6.21 (bug #1230757).
 
 2015/11/12  -- Synced with libpng-1.6.19 (bug #1224244).
 
 2015/07/30  -- Synced with libpng-1.6.18 (bug #1186977).
 
 2015/03/27  -- Synced with libpng-1.6.17 (bug #1147909).
 
--- a/media/libpng/README
+++ b/media/libpng/README
@@ -1,9 +1,9 @@
-README for libpng version 1.6.21 - January 15, 2016 (shared library 16.0)
+README for libpng version 1.6.23 - June 9, 2016 (shared library 16.0)
 See the note about version numbers near the top of png.h
 
 See INSTALL for instructions on how to install libpng.
 
 Libpng comes in several distribution formats.  Get libpng-*.tar.gz or
 libpng-*.tar.xz or if you want UNIX-style line endings in the text files,
 or lpng*.7z or lpng*.zip if you want DOS-style line endings.
 
--- a/media/libpng/apng.patch
+++ b/media/libpng/apng.patch
@@ -3,38 +3,38 @@ Index: LICENSE
 --- LICENSE
 +++ LICENSE
 @@ -8,6 +8,12 @@
  If you modify libpng you may insert additional notices immediately following
  this sentence.
  
 +This modified version of libpng code adds animated PNG support and is
 +released under the libpng license described below. The modifications are
-+Copyright (c) 2006-2007 Andrew Smith, Copyright (c) 2008-2015 Max Stepin,
++Copyright (c) 2006-2007 Andrew Smith, Copyright (c) 2008-2016 Max Stepin,
 +and are delimited by "#ifdef PNG_APNG_SUPPORTED / #endif" directives
 +surrounding them in the modified libpng source files.
 +
  This code is released under the libpng license.
  
- libpng versions 1.0.7, July 1, 2000, through 1.6.21, January 15, 2016, are
+ libpng versions 1.0.7, July 1, 2000 through 1.6.23, June 9, 2016 are
 Index: pngread.c
 ===================================================================
 --- pngread.c
 +++ pngread.c
-@@ -158,6 +158,9 @@
+@@ -161,6 +161,9 @@
  
        else if (chunk_name == png_IDAT)
        {
 +#ifdef PNG_READ_APNG_SUPPORTED
 +         png_have_info(png_ptr, info_ptr);
 +#endif
           png_ptr->idat_size = length;
           break;
        }
-@@ -247,6 +250,17 @@
+@@ -250,6 +253,17 @@
           png_handle_iTXt(png_ptr, info_ptr, length);
  #endif
  
 +#ifdef PNG_READ_APNG_SUPPORTED
 +      else if (chunk_name == png_acTL)
 +         png_handle_acTL(png_ptr, info_ptr, length);
 +
 +      else if (chunk_name == png_fcTL)
@@ -42,17 +42,17 @@ Index: pngread.c
 +
 +      else if (chunk_name == png_fdAT)
 +         png_handle_fdAT(png_ptr, info_ptr, length);
 +#endif
 +
        else
           png_handle_unknown(png_ptr, info_ptr, length,
              PNG_HANDLE_CHUNK_AS_DEFAULT);
-@@ -254,6 +268,72 @@
+@@ -257,6 +271,72 @@
  }
  #endif /* SEQUENTIAL_READ */
  
 +#ifdef PNG_READ_APNG_SUPPORTED
 +void PNGAPI
 +png_read_frame_head(png_structp png_ptr, png_infop info_ptr)
 +{
 +    png_byte have_chunk_after_DAT; /* after IDAT or after fdAT */
@@ -294,79 +294,79 @@ Index: pngget.c
 Index: png.c
 ===================================================================
 --- png.c
 +++ png.c
 @@ -775,17 +775,21 @@
  #else
  #  ifdef __STDC__
     return PNG_STRING_NEWLINE \
--      "libpng version 1.6.21 - January 15, 2016" PNG_STRING_NEWLINE \
-+      "libpng version 1.6.21+apng - January 15, 2016" PNG_STRING_NEWLINE \
+-      "libpng version 1.6.23 - June 9, 2016" PNG_STRING_NEWLINE \
++      "libpng version 1.6.23+apng - June 9, 2016" PNG_STRING_NEWLINE \
        "Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson" \
        PNG_STRING_NEWLINE \
        "Copyright (c) 1996-1997 Andreas Dilger" PNG_STRING_NEWLINE \
        "Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc." \
 -      PNG_STRING_NEWLINE;
 +      PNG_STRING_NEWLINE \
 +      "Portions Copyright (c) 2006-2007 Andrew Smith" PNG_STRING_NEWLINE \
-+      "Portions Copyright (c) 2008-2015 Max Stepin" PNG_STRING_NEWLINE ;
++      "Portions Copyright (c) 2008-2016 Max Stepin" PNG_STRING_NEWLINE ;
  #  else
--   return "libpng version 1.6.21 - January 15, 2016\
-+   return "libpng version 1.6.21+apng - January 15, 2016\
+-   return "libpng version 1.6.23 - June 9, 2016\
++   return "libpng version 1.6.23+apng - June 9, 2016\
        Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson\
        Copyright (c) 1996-1997 Andreas Dilger\
 -      Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.";
 +      Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.\
 +      Portions Copyright (c) 2006-2007 Andrew Smith\
-+      Portions Copyright (c) 2008-2015 Max Stepin";
++      Portions Copyright (c) 2008-2016 Max Stepin";
  #  endif
  #endif
  }
 Index: png.h
 ===================================================================
 --- png.h
 +++ png.h
 @@ -23,6 +23,12 @@
   * If you modify libpng you may insert additional notices immediately following
   * this sentence.
   *
 + * This modified version of libpng code adds animated PNG support and is
 + * released under the libpng license described below. The modifications are
-+ * Copyright (c) 2006-2007 Andrew Smith, Copyright (c) 2008-2015 Max Stepin,
++ * Copyright (c) 2006-2007 Andrew Smith, Copyright (c) 2008-2016 Max Stepin,
 + * and are delimited by "#ifdef PNG_APNG_SUPPORTED / #endif" directives
 + * surrounding them in the modified libpng source files.
 + *
   * This code is released under the libpng license.
   *
-  * libpng versions 1.0.7, July 1, 2000, through 1.6.21, January 15, 2016, are
-@@ -282,9 +288,9 @@
+  * Some files in the "contrib" directory and some configure-generated
+@@ -313,9 +319,9 @@
   */
  
  /* Version information for png.h - this should match the version in png.c */
--#define PNG_LIBPNG_VER_STRING "1.6.21"
-+#define PNG_LIBPNG_VER_STRING "1.6.21+apng"
+-#define PNG_LIBPNG_VER_STRING "1.6.23"
++#define PNG_LIBPNG_VER_STRING "1.6.23+apng"
  #define PNG_HEADER_VERSION_STRING \
--     " libpng version 1.6.21 - January 15, 2016\n"
-+     " libpng version 1.6.21+apng - January 15, 2016\n"
+-     " libpng version 1.6.23 - June 9, 2016\n"
++     " libpng version 1.6.23+apng - June 9, 2016\n"
  
  #define PNG_LIBPNG_VER_SONUM   16
  #define PNG_LIBPNG_VER_DLLNUM  16
-@@ -335,6 +341,10 @@
+@@ -366,6 +372,10 @@
  #   include "pnglibconf.h"
  #endif
  
 +#define PNG_APNG_SUPPORTED
 +#define PNG_READ_APNG_SUPPORTED
 +#define PNG_WRITE_APNG_SUPPORTED
 +
  #ifndef PNG_VERSION_INFO_ONLY
     /* Machine specific configuration. */
  #  include "pngconf.h"
-@@ -430,6 +440,17 @@
+@@ -461,6 +471,17 @@
   * See pngconf.h for base types that vary by machine/system
   */
  
 +#ifdef PNG_APNG_SUPPORTED
 +/* dispose_op flags from inside fcTL */
 +#define PNG_DISPOSE_OP_NONE        0x00
 +#define PNG_DISPOSE_OP_BACKGROUND  0x01
 +#define PNG_DISPOSE_OP_PREVIOUS    0x02
@@ -374,39 +374,39 @@ Index: png.h
 +/* blend_op flags from inside fcTL */
 +#define PNG_BLEND_OP_SOURCE        0x00
 +#define PNG_BLEND_OP_OVER          0x01
 +#endif /* APNG */
 +
  /* This triggers a compiler error in png.c, if png.c and png.h
   * do not agree upon the version number.
   */
-@@ -752,6 +773,10 @@
- #if INT_MAX >= 0x8000 /* else this might break */
- #define PNG_INFO_IDAT 0x8000   /* ESR, 1.0.6 */
- #endif
+@@ -781,6 +802,10 @@
+ #define PNG_INFO_sPLT 0x2000U  /* ESR, 1.0.6 */
+ #define PNG_INFO_sCAL 0x4000U  /* ESR, 1.0.6 */
+ #define PNG_INFO_IDAT 0x8000U  /* ESR, 1.0.6 */
 +#ifdef PNG_APNG_SUPPORTED
 +#define PNG_INFO_acTL 0x10000
 +#define PNG_INFO_fcTL 0x20000
 +#endif
  
  /* This is used for the transformation routines, as some of them
   * change these values for the row.  It also should enable using
-@@ -789,6 +814,10 @@
+@@ -818,6 +843,10 @@
  #ifdef PNG_PROGRESSIVE_READ_SUPPORTED
  typedef PNG_CALLBACK(void, *png_progressive_info_ptr, (png_structp, png_infop));
  typedef PNG_CALLBACK(void, *png_progressive_end_ptr, (png_structp, png_infop));
 +#ifdef PNG_APNG_SUPPORTED
 +typedef PNG_CALLBACK(void, *png_progressive_frame_ptr, (png_structp,
 +    png_uint_32));
 +#endif
  
  /* The following callback receives png_uint_32 row_number, int pass for the
   * png_bytep data of the row.  When transforming an interlaced image the
-@@ -3110,6 +3139,75 @@
+@@ -3237,6 +3266,75 @@
   *  END OF HARDWARE AND SOFTWARE OPTIONS
   ******************************************************************************/
  
 +#ifdef PNG_APNG_SUPPORTED
 +PNG_EXPORT(245, png_uint_32, png_get_acTL, (png_structp png_ptr,
 +   png_infop info_ptr, png_uint_32 *num_frames, png_uint_32 *num_plays));
 +
 +PNG_EXPORT(246, png_uint_32, png_set_acTL, (png_structp png_ptr,
@@ -472,24 +472,24 @@ Index: png.h
 +PNG_EXPORT(264, void, png_write_frame_tail, (png_structp png_ptr,
 +   png_infop info_ptr));
 +#endif /* WRITE_APNG */
 +#endif /* APNG */
 +
  /* Maintainer: Put new public prototypes here ^, in libpng.3, in project
   * defs, and in scripts/symbols.def.
   */
-@@ -3118,7 +3216,11 @@
+@@ -3245,7 +3343,11 @@
   * one to use is one more than this.)
   */
  #ifdef PNG_EXPORT_LAST_ORDINAL
 +#ifdef PNG_APNG_SUPPORTED
-+  PNG_EXPORT_LAST_ORDINAL(264);
++  PNG_EXPORT_LAST_ORDINAL(265);
 +#else
-   PNG_EXPORT_LAST_ORDINAL(244);
+   PNG_EXPORT_LAST_ORDINAL(245);
 +#endif /* APNG */
  #endif
  
  #ifdef __cplusplus
 Index: pngpriv.h
 ===================================================================
 --- pngpriv.h
 +++ pngpriv.h
@@ -648,19 +648,19 @@ Index: pngwrite.c
 +#ifdef PNG_WRITE_APNG_SUPPORTED
 +   if (png_ptr->num_frames_written != png_ptr->num_frames_to_write)
 +      png_error(png_ptr, "Not enough frames written");
 +#endif
 +
  #ifdef PNG_WRITE_CHECK_FOR_INVALID_INDEX_SUPPORTED
     if (png_ptr->num_palette_max > png_ptr->num_palette)
        png_benign_error(png_ptr, "Wrote palette index exceeding num_palette");
-@@ -2227,4 +2236,42 @@
+@@ -2380,4 +2389,42 @@
  }
- # endif /* STDIO */
+ #endif /* SIMPLIFIED_WRITE_STDIO */
  #endif /* SIMPLIFIED_WRITE */
 +
 +#ifdef PNG_WRITE_APNG_SUPPORTED
 +void PNGAPI
 +png_write_frame_head(png_structp png_ptr, png_infop info_ptr,
 +    png_bytepp row_pointers, png_uint_32 width, png_uint_32 height,
 +    png_uint_32 x_offset, png_uint_32 y_offset,
 +    png_uint_16 delay_num, png_uint_16 delay_den, png_byte dispose_op,
@@ -785,27 +785,27 @@ Index: pngpread.c
 +
 +      return;
 +   }
 +#endif /* READ_APNG */
 +
     if (chunk_name == png_IDAT)
     {
        if ((png_ptr->mode & PNG_AFTER_IDAT) != 0)
-@@ -258,6 +341,9 @@
+@@ -260,6 +343,9 @@
  
     else if (chunk_name == png_IDAT)
     {
 +#ifdef PNG_READ_APNG_SUPPORTED
 +      png_have_info(png_ptr, info_ptr);
 +#endif
        png_ptr->idat_size = png_ptr->push_length;
        png_ptr->process_mode = PNG_READ_IDAT_MODE;
        png_push_have_info(png_ptr, info_ptr);
-@@ -404,6 +490,20 @@
+@@ -406,6 +492,20 @@
     }
  #endif
  
 +#ifdef PNG_READ_APNG_SUPPORTED
 +   else if (chunk_name == png_acTL)
 +   {
 +      PNG_PUSH_SAVE_BUFFER_IF_FULL
 +      png_handle_acTL(png_ptr, info_ptr, png_ptr->push_length);
@@ -816,29 +816,29 @@ Index: pngpread.c
 +      PNG_PUSH_SAVE_BUFFER_IF_FULL
 +      png_handle_fcTL(png_ptr, info_ptr, png_ptr->push_length);
 +   }
 +
 +#endif /* READ_APNG */
     else
     {
        PNG_PUSH_SAVE_BUFFER_IF_FULL
-@@ -533,7 +633,11 @@
+@@ -538,7 +638,11 @@
        png_byte chunk_tag[4];
  
        /* TODO: this code can be commoned up with the same code in push_read */
 +#ifdef PNG_READ_APNG_SUPPORTED
 +      PNG_PUSH_SAVE_BUFFER_IF_LT(12)
 +#else
        PNG_PUSH_SAVE_BUFFER_IF_LT(8)
 +#endif
        png_push_fill_buffer(png_ptr, chunk_length, 4);
        png_ptr->push_length = png_get_uint_31(png_ptr, chunk_length);
        png_reset_crc(png_ptr);
-@@ -541,17 +645,60 @@
+@@ -546,17 +650,60 @@
        png_ptr->chunk_name = PNG_CHUNK_FROM_STRING(chunk_tag);
        png_ptr->mode |= PNG_HAVE_CHUNK_HEADER;
  
 +#ifdef PNG_READ_APNG_SUPPORTED
 +      if (png_ptr->chunk_name != png_fdAT && png_ptr->num_frames_read > 0)
 +      {
 +          if ((png_ptr->flags & PNG_FLAG_ZSTREAM_ENDED) != 0)
 +          {
@@ -889,34 +889,34 @@ Index: pngpread.c
 +      {
 +         png_ensure_sequence_number(png_ptr, 4);
 +         png_ptr->idat_size -= 4;
 +      }
 +#endif
     }
  
     if (png_ptr->idat_size != 0 && png_ptr->save_buffer_size != 0)
-@@ -625,6 +772,16 @@
+@@ -630,6 +777,16 @@
     if (!(buffer_length > 0) || buffer == NULL)
        png_error(png_ptr, "No IDAT data (internal error)");
  
 +#ifdef PNG_READ_APNG_SUPPORTED
 +   /* If the app is not APNG-aware, decode only the first frame */
 +   if ((png_ptr->apng_flags & PNG_APNG_APP) == 0 &&
 +      png_ptr->num_frames_read > 0)
 +   {
 +      png_ptr->flags |= PNG_FLAG_ZSTREAM_ENDED;
 +      return;
 +   }
 +#endif
 +
     /* This routine must process all the data it has been given
      * before returning, calling the row callback as required to
      * handle the uncompressed results.
-@@ -1074,6 +1231,18 @@
+@@ -1079,6 +1236,18 @@
     png_set_read_fn(png_ptr, progressive_ptr, png_push_fill_buffer);
  }
  
 +#ifdef PNG_READ_APNG_SUPPORTED
 +void PNGAPI
 +png_set_progressive_frame_fn(png_structp png_ptr,
 +   png_progressive_frame_ptr frame_info_fn,
 +   png_progressive_frame_ptr frame_end_fn)
@@ -941,17 +941,17 @@ Index: pngset.c
 +
 +#ifdef PNG_APNG_SUPPORTED
 +   /* for non-animated png. this may be overwritten from an acTL chunk later */
 +   info_ptr->num_frames = 1;
 +#endif
  }
  
  #ifdef PNG_oFFs_SUPPORTED
-@@ -1094,6 +1099,146 @@
+@@ -1096,6 +1101,146 @@
  }
  #endif /* sPLT */
  
 +#ifdef PNG_APNG_SUPPORTED
 +png_uint_32 PNGAPI
 +png_set_acTL(png_structp png_ptr, png_infop info_ptr,
 +    png_uint_32 num_frames, png_uint_32 num_plays)
 +{
@@ -1598,32 +1598,32 @@ Index: pngwutil.c
 +    png_ptr->usr_width = png_ptr->width;
 +}
 +#endif /* WRITE_APNG */
  #endif /* WRITE */
 Index: scripts/symbols.def
 ===================================================================
 --- scripts/symbols.def
 +++ scripts/symbols.def
-@@ -249,3 +249,23 @@
-  png_set_check_for_invalid_index @242
+@@ -250,3 +250,23 @@
   png_get_palette_max @243
   png_set_option @244
-+ png_get_acTL @245
-+ png_set_acTL @246
-+ png_get_num_frames @247
-+ png_get_num_plays @248
-+ png_get_next_frame_fcTL @249
-+ png_set_next_frame_fcTL @250
-+ png_get_next_frame_width @251
-+ png_get_next_frame_height @252
-+ png_get_next_frame_x_offset @253
-+ png_get_next_frame_y_offset @254
-+ png_get_next_frame_delay_num @255
-+ png_get_next_frame_delay_den @256
-+ png_get_next_frame_dispose_op @257
-+ png_get_next_frame_blend_op @258
-+ png_get_first_frame_is_hidden @259
-+ png_set_first_frame_is_hidden @260
-+ png_read_frame_head @261
-+ png_set_progressive_frame_fn @262
-+ png_write_frame_head @263
-+ png_write_frame_tail @264
+  png_image_write_to_memory @245
++ png_get_acTL @246
++ png_set_acTL @247
++ png_get_num_frames @248
++ png_get_num_plays @249
++ png_get_next_frame_fcTL @250
++ png_set_next_frame_fcTL @251
++ png_get_next_frame_width @252
++ png_get_next_frame_height @253
++ png_get_next_frame_x_offset @254
++ png_get_next_frame_y_offset @255
++ png_get_next_frame_delay_num @256
++ png_get_next_frame_delay_den @257
++ png_get_next_frame_dispose_op @258
++ png_get_next_frame_blend_op @259
++ png_get_first_frame_is_hidden @260
++ png_set_first_frame_is_hidden @261
++ png_read_frame_head @262
++ png_set_progressive_frame_fn @263
++ png_write_frame_head @264
++ png_write_frame_tail @265
--- a/media/libpng/arm/arm_init.c
+++ b/media/libpng/arm/arm_init.c
@@ -1,14 +1,14 @@
 
 /* arm_init.c - NEON optimised filter functions
  *
- * Copyright (c) 2014 Glenn Randers-Pehrson
+ * Copyright (c) 2014,2016 Glenn Randers-Pehrson
  * Written by Mans Rullgard, 2011.
- * Last changed in libpng 1.6.16 [December 22, 2014]
+ * Last changed in libpng 1.6.22 [May 24, 2016]
  *
  * This code is released under the libpng license.
  * For conditions of distribution and use, see the disclaimer
  * and license in png.h
  */
 /* Below, after checking __linux__, various non-C90 POSIX 1003.1 functions are
  * called.
  */
@@ -61,16 +61,17 @@ png_init_filter_functions_neon(png_struc
     * the check is only performed if the API has not set the NEON option on
     * or off explicitly.  In this case the check controls what happens.
     *
     * If the CHECK is not compiled in and the option is UNSET the behavior prior
     * to 1.6.7 was to use the NEON code - this was a bug caused by having the
     * wrong order of the 'ON' and 'default' cases.  UNSET now defaults to OFF,
     * as documented in png.h
     */
+   png_debug(1, "in png_init_filter_functions_neon");
 #ifdef PNG_ARM_NEON_API_SUPPORTED
    switch ((pp->options >> PNG_ARM_NEON) & 3)
    {
       case PNG_OPTION_UNSET:
          /* Allow the run-time check to execute if it has been enabled -
           * thus both API and CHECK can be turned on.  If it isn't supported
           * this case will fall through to the 'default' below, which just
           * returns.
--- a/media/libpng/arm/filter_neon_intrinsics.c
+++ b/media/libpng/arm/filter_neon_intrinsics.c
@@ -1,16 +1,16 @@
 
 /* filter_neon_intrinsics.c - NEON optimised filter functions
  *
- * Copyright (c) 2014 Glenn Randers-Pehrson
+ * Copyright (c) 2014,2016 Glenn Randers-Pehrson
  * Written by James Yu <james.yu at linaro.org>, October 2013.
  * Based on filter_neon.S, written by Mans Rullgard, 2011.
  *
- * Last changed in libpng 1.6.16 [December 22, 2014]
+ * Last changed in libpng 1.6.22 [May 24, 2016]
  *
  * This code is released under the libpng license.
  * For conditions of distribution and use, see the disclaimer
  * and license in png.h
  */
 
 #include "../pngpriv.h"
 
@@ -42,16 +42,18 @@
 void
 png_read_filter_row_up_neon(png_row_infop row_info, png_bytep row,
    png_const_bytep prev_row)
 {
    png_bytep rp = row;
    png_bytep rp_stop = row + row_info->rowbytes;
    png_const_bytep pp = prev_row;
 
+   png_debug(1, "in png_read_filter_row_up_neon");
+
    for (; rp < rp_stop; rp += 16, pp += 16)
    {
       uint8x16_t qrp, qpp;
 
       qrp = vld1q_u8(rp);
       qpp = vld1q_u8(pp);
       qrp = vaddq_u8(qrp, qpp);
       vst1q_u8(rp, qrp);
@@ -67,16 +69,18 @@ png_read_filter_row_sub3_neon(png_row_in
 
    uint8x16_t vtmp = vld1q_u8(rp);
    uint8x8x2_t *vrpt = png_ptr(uint8x8x2_t, &vtmp);
    uint8x8x2_t vrp = *vrpt;
 
    uint8x8x4_t vdest;
    vdest.val[3] = vdup_n_u8(0);
 
+   png_debug(1, "in png_read_filter_row_sub3_neon");
+
    for (; rp < rp_stop;)
    {
       uint8x8_t vtmp1, vtmp2;
       uint32x2_t *temp_pointer;
 
       vtmp1 = vext_u8(vrp.val[0], vrp.val[1], 3);
       vdest.val[0] = vadd_u8(vdest.val[3], vrp.val[0]);
       vtmp2 = vext_u8(vrp.val[0], vrp.val[1], 6);
@@ -108,16 +112,18 @@ png_read_filter_row_sub4_neon(png_row_in
    png_const_bytep prev_row)
 {
    png_bytep rp = row;
    png_bytep rp_stop = row + row_info->rowbytes;
 
    uint8x8x4_t vdest;
    vdest.val[3] = vdup_n_u8(0);
 
+   png_debug(1, "in png_read_filter_row_sub4_neon");
+
    for (; rp < rp_stop; rp += 16)
    {
       uint32x2x4_t vtmp = vld4_u32(png_ptr(uint32_t,rp));
       uint8x8x4_t *vrpt = png_ptr(uint8x8x4_t,&vtmp);
       uint8x8x4_t vrp = *vrpt;
       uint32x2x4_t *temp_pointer;
 
       vdest.val[0] = vadd_u8(vdest.val[3], vrp.val[0]);
@@ -143,16 +149,18 @@ png_read_filter_row_avg3_neon(png_row_in
    uint8x8x2_t vrp;
    uint8x8x4_t vdest;
    vdest.val[3] = vdup_n_u8(0);
 
    vtmp = vld1q_u8(rp);
    vrpt = png_ptr(uint8x8x2_t,&vtmp);
    vrp = *vrpt;
 
+   png_debug(1, "in png_read_filter_row_avg3_neon");
+
    for (; rp < rp_stop; pp += 12)
    {
       uint8x8_t vtmp1, vtmp2, vtmp3;
 
       uint8x8x2_t *vppt;
       uint8x8x2_t vpp;
 
       uint32x2_t *temp_pointer;
@@ -202,16 +210,18 @@ png_read_filter_row_avg4_neon(png_row_in
 {
    png_bytep rp = row;
    png_bytep rp_stop = row + row_info->rowbytes;
    png_const_bytep pp = prev_row;
 
    uint8x8x4_t vdest;
    vdest.val[3] = vdup_n_u8(0);
 
+   png_debug(1, "in png_read_filter_row_avg4_neon");
+
    for (; rp < rp_stop; rp += 16, pp += 16)
    {
       uint32x2x4_t vtmp;
       uint8x8x4_t *vrpt, *vppt;
       uint8x8x4_t vrp, vpp;
       uint32x2x4_t *temp_pointer;
 
       vtmp = vld4_u32(png_ptr(uint32_t,rp));
@@ -275,16 +285,18 @@ png_read_filter_row_paeth3_neon(png_row_
    uint8x8_t vlast = vdup_n_u8(0);
    uint8x8x4_t vdest;
    vdest.val[3] = vdup_n_u8(0);
 
    vtmp = vld1q_u8(rp);
    vrpt = png_ptr(uint8x8x2_t,&vtmp);
    vrp = *vrpt;
 
+   png_debug(1, "in png_read_filter_row_paeth3_neon");
+
    for (; rp < rp_stop; pp += 12)
    {
       uint8x8x2_t *vppt;
       uint8x8x2_t vpp;
       uint8x8_t vtmp1, vtmp2, vtmp3;
       uint32x2_t *temp_pointer;
 
       vtmp = vld1q_u8(pp);
@@ -334,16 +346,18 @@ png_read_filter_row_paeth4_neon(png_row_
    png_bytep rp = row;
    png_bytep rp_stop = row + row_info->rowbytes;
    png_const_bytep pp = prev_row;
 
    uint8x8_t vlast = vdup_n_u8(0);
    uint8x8x4_t vdest;
    vdest.val[3] = vdup_n_u8(0);
 
+   png_debug(1, "in png_read_filter_row_paeth4_neon");
+
    for (; rp < rp_stop; rp += 16, pp += 16)
    {
       uint32x2x4_t vtmp;
       uint8x8x4_t *vrpt, *vppt;
       uint8x8x4_t vrp, vpp;
       uint32x2x4_t *temp_pointer;
 
       vtmp = vld4_u32(png_ptr(uint32_t,rp));
--- a/media/libpng/libpng-manual.txt
+++ b/media/libpng/libpng-manual.txt
@@ -1,22 +1,22 @@
 libpng-manual.txt - A description on how to use and modify libpng
 
- libpng version 1.6.21 - January 15, 2016
+ libpng version 1.6.23 - June 9, 2016
  Updated and distributed by Glenn Randers-Pehrson
  <glennrp at users.sourceforge.net>
  Copyright (c) 1998-2016 Glenn Randers-Pehrson
 
  This document is released under the libpng license.
  For conditions of distribution and use, see the disclaimer
  and license in png.h
 
  Based on:
 
- libpng versions 0.97, January 1998, through 1.6.21 - January 15, 2016
+ libpng versions 0.97, January 1998, through 1.6.23 - June 9, 2016
  Updated and distributed by Glenn Randers-Pehrson
  Copyright (c) 1998-2016 Glenn Randers-Pehrson
 
  libpng 1.0 beta 6 - version 0.96 - May 28, 1997
  Updated and distributed by Andreas Dilger
  Copyright (c) 1996, 1997 Andreas Dilger
 
  libpng 1.0 beta 2 - version 0.88 - January 26, 1996
@@ -2837,17 +2837,17 @@ filter types.
        or more PNG_FILTER_NAME masks.
      */
     png_set_filter(png_ptr, 0,
        PNG_FILTER_NONE  | PNG_FILTER_VALUE_NONE |
        PNG_FILTER_SUB   | PNG_FILTER_VALUE_SUB  |
        PNG_FILTER_UP    | PNG_FILTER_VALUE_UP   |
        PNG_FILTER_AVG   | PNG_FILTER_VALUE_AVG  |
        PNG_FILTER_PAETH | PNG_FILTER_VALUE_PAETH|
-       PNG_ALL_FILTERS);
+       PNG_ALL_FILTERS  | PNG_FAST_FILTERS);
 
 If an application wants to start and stop using particular filters during
 compression, it should start out with all of the filters (to ensure that
 the previous row of pixels will be stored in case it's needed later),
 and then add and remove them after the start of compression.
 
 If you are writing a PNG datastream that is to be embedded in a MNG
 datastream, the second parameter can be either 0 or 64.
@@ -4098,16 +4098,23 @@ be written:
    colormap_entries: set to the number of entries in the color-map (0 to 256)
 
    int png_image_write_to_file, (png_imagep image,
       const char *file, int convert_to_8bit, const void *buffer,
       png_int_32 row_stride, const void *colormap));
 
       Write the image to the named file.
 
+   int png_image_write_to_memory (png_imagep image, void *memory,
+      png_alloc_size_t * PNG_RESTRICT memory_bytes,
+      int convert_to_8_bit, const void *buffer, ptrdiff_t row_stride,
+      const void *colormap));
+
+      Write the image to memory.
+
    int png_image_write_to_stdio(png_imagep image, FILE *file,
       int convert_to_8_bit, const void *buffer,
       png_int_32 row_stride, const void *colormap)
 
       Write the image to the given (FILE*).
 
 With all write APIs if image is in one of the linear formats with
 (png_uint_16) data then setting convert_to_8_bit will cause the output to be
@@ -4375,37 +4382,45 @@ of row filters can have a significant im
 encoding speed and a somewhat lesser impact on the decoding speed
 of an image.  Filtering is enabled by default for RGB and grayscale
 images (with and without alpha), but not for paletted images nor
 for any images with bit depths less than 8 bits/pixel.
 
 The 'method' parameter sets the main filtering method, which is
 currently only '0' in the PNG 1.2 specification.  The 'filters'
 parameter sets which filter(s), if any, should be used for each
-scanline.  Possible values are PNG_ALL_FILTERS and PNG_NO_FILTERS
-to turn filtering on and off, respectively.
+scanline.  Possible values are PNG_ALL_FILTERS, PNG_NO_FILTERS,
+or PNG_FAST_FILTERS to turn filtering on and off, or to turn on
+just the fast-decoding subset of filters, respectively.
 
 Individual filter types are PNG_FILTER_NONE, PNG_FILTER_SUB,
 PNG_FILTER_UP, PNG_FILTER_AVG, PNG_FILTER_PAETH, which can be bitwise
 ORed together with '|' to specify one or more filters to use.
 These filters are described in more detail in the PNG specification.
 If you intend to change the filter type during the course of writing
 the image, you should start with flags set for all of the filters
 you intend to use so that libpng can initialize its internal
 structures appropriately for all of the filter types.  (Note that this
 means the first row must always be adaptively filtered, because libpng
 currently does not allocate the filter buffers until png_write_row()
 is called for the first time.)
 
-    filters = PNG_FILTER_NONE | PNG_FILTER_SUB
+    filters = PNG_NO_FILTERS;
+    filters = PNG_ALL_FILTERS;
+    filters = PNG_FAST_FILTERS;
+
+    or
+
+    filters = PNG_FILTER_NONE | PNG_FILTER_SUB |
               PNG_FILTER_UP | PNG_FILTER_AVG |
-              PNG_FILTER_PAETH | PNG_ALL_FILTERS;
+              PNG_FILTER_PAETH;
 
     png_set_filter(png_ptr, PNG_FILTER_TYPE_BASE,
        filters);
+
               The second parameter can also be
               PNG_INTRAPIXEL_DIFFERENCING if you are
               writing a PNG to be embedded in a MNG
               datastream.  This parameter must be the
               same as the value of filter_method used
               in png_set_IHDR().
 
 Requesting debug printout
@@ -4770,17 +4785,18 @@ the palette was not checked, or "0" if n
 does not account for any palette index used by ancillary chunks such as the
 bKGD chunk; you must check those separately to determine the maximum
 palette index actually used.
 
 There are no substantial API changes between the non-deprecated parts of
 the 1.4.5 API and the 1.5.0 API; however, the ability to directly access
 members of the main libpng control structures, png_struct and png_info,
 deprecated in earlier versions of libpng, has been completely removed from
-libpng 1.5.
+libpng 1.5, and new private "pngstruct.h", "pnginfo.h", and "pngdebug.h"
+header files were created.
 
 We no longer include zlib.h in png.h.  The include statement has been moved
 to pngstruct.h, where it is not accessible by applications. Applications that
 need access to information in zlib.h will need to add the '#include "zlib.h"'
 directive.  It does not matter whether this is placed prior to or after
 the '"#include png.h"' directive.
 
 The png_sprintf(), png_strcpy(), and png_strncpy() macros are no longer used
@@ -5010,16 +5026,17 @@ includes the following:
    read functions
      png_image_begin_read_from_file()
      png_image_begin_read_from_stdio()
      png_image_begin_read_from_memory()
      png_image_finish_read()
      png_image_free()
    write functions
      png_image_write_to_file()
+     png_image_write_to_memory()
      png_image_write_to_stdio()
 
 Starting with libpng-1.6.0, you can configure libpng to prefix all exported
 symbols, using the PNG_PREFIX macro.
 
 We no longer include string.h in png.h.  The include statement has been moved
 to pngpriv.h, where it is not accessible by applications.  Applications that
 need access to information in string.h must add an '#include <string.h>'
@@ -5323,17 +5340,17 @@ Lines do not exceed 80 characters.
 Other rules can be inferred by inspecting the libpng source.
 
 XVI. Y2K Compliance in libpng
 
 Since the PNG Development group is an ad-hoc body, we can't make
 an official declaration.
 
 This is your unofficial assurance that libpng from version 0.71 and
-upward through 1.6.21 are Y2K compliant.  It is my belief that earlier
+upward through 1.6.23 are Y2K compliant.  It is my belief that earlier
 versions were also Y2K compliant.
 
 Libpng only has two year fields.  One is a 2-byte unsigned integer
 that will hold years up to 65535.  The other, which is deprecated,
 holds the date in text format, and will hold years up to 9999.
 
 The integer is
     "png_uint_16 year" in png_time_struct.
--- a/media/libpng/png.c
+++ b/media/libpng/png.c
@@ -9,17 +9,17 @@
  * This code is released under the libpng license.
  * For conditions of distribution and use, see the disclaimer
  * and license in png.h
  */
 
 #include "pngpriv.h"
 
 /* Generate a compiler error if there is an old png.h in the search path. */
-typedef png_libpng_version_1_6_21 Your_png_h_is_not_version_1_6_21;
+typedef png_libpng_version_1_6_23 Your_png_h_is_not_version_1_6_23;
 
 /* Tells libpng that we have already handled the first "num_bytes" bytes
  * of the PNG file signature.  If the PNG data is embedded into another
  * stream we can set num_bytes = 8 so that libpng will not attempt to read
  * or write any of the magic bytes before it starts on the IHDR.
  */
 
 #ifdef PNG_READ_SUPPORTED
@@ -770,31 +770,31 @@ png_const_charp PNGAPI
 png_get_copyright(png_const_structrp png_ptr)
 {
    PNG_UNUSED(png_ptr)  /* Silence compiler warning about unused png_ptr */
 #ifdef PNG_STRING_COPYRIGHT
    return PNG_STRING_COPYRIGHT
 #else
 #  ifdef __STDC__
    return PNG_STRING_NEWLINE \
-      "libpng version 1.6.21+apng - January 15, 2016" PNG_STRING_NEWLINE \
+      "libpng version 1.6.23+apng - June 9, 2016" PNG_STRING_NEWLINE \
       "Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson" \
       PNG_STRING_NEWLINE \
       "Copyright (c) 1996-1997 Andreas Dilger" PNG_STRING_NEWLINE \
       "Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc." \
       PNG_STRING_NEWLINE \
       "Portions Copyright (c) 2006-2007 Andrew Smith" PNG_STRING_NEWLINE \
-      "Portions Copyright (c) 2008-2015 Max Stepin" PNG_STRING_NEWLINE ;
+      "Portions Copyright (c) 2008-2016 Max Stepin" PNG_STRING_NEWLINE ;
 #  else
-   return "libpng version 1.6.21+apng - January 15, 2016\
+   return "libpng version 1.6.23+apng - June 9, 2016\
       Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson\
       Copyright (c) 1996-1997 Andreas Dilger\
       Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.\
       Portions Copyright (c) 2006-2007 Andrew Smith\
-      Portions Copyright (c) 2008-2015 Max Stepin";
+      Portions Copyright (c) 2008-2016 Max Stepin";
 #  endif
 #endif
 }
 
 /* The following return the library version as a short string in the
  * format 1.0.0 through 99.99.99zz.  To get the version of *.h files
  * used with your application, print out PNG_LIBPNG_VER_STRING, which
  * is defined in png.h.
--- a/media/libpng/png.h
+++ b/media/libpng/png.h
@@ -1,42 +1,46 @@
 
 /* png.h - header file for PNG reference library
  *
- * libpng version 1.6.21, January 15, 2016
+ * libpng version 1.6.23, June 9, 2016
  *
  * Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson
  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
  *
  * This code is released under the libpng license (See LICENSE, below)
  *
  * Authors and maintainers:
  *   libpng versions 0.71, May 1995, through 0.88, January 1996: Guy Schalnat
  *   libpng versions 0.89, June 1996, through 0.96, May 1997: Andreas Dilger
- *   libpng versions 0.97, January 1998, through 1.6.21, January 15, 2016:
+ *   libpng versions 0.97, January 1998, through 1.6.23, June 9, 2016:
  *     Glenn Randers-Pehrson.
  *   See also "Contributing Authors", below.
  */
 
 /*
  * COPYRIGHT NOTICE, DISCLAIMER, and LICENSE:
  *
  * If you modify libpng you may insert additional notices immediately following
  * this sentence.
  *
  * This modified version of libpng code adds animated PNG support and is
  * released under the libpng license described below. The modifications are
- * Copyright (c) 2006-2007 Andrew Smith, Copyright (c) 2008-2015 Max Stepin,
+ * Copyright (c) 2006-2007 Andrew Smith, Copyright (c) 2008-2016 Max Stepin,
  * and are delimited by "#ifdef PNG_APNG_SUPPORTED / #endif" directives
  * surrounding them in the modified libpng source files.
  *
  * This code is released under the libpng license.
  *
- * libpng versions 1.0.7, July 1, 2000, through 1.6.21, January 15, 2016, are
+ * Some files in the "contrib" directory and some configure-generated
+ * files that are distributed with libpng have other copyright owners and
+ * are released under other open source licenses.
+ *
+ * libpng versions 1.0.7, July 1, 2000 through 1.6.23, June 9, 2016 are
  * Copyright (c) 2000-2002, 2004, 2006-2016 Glenn Randers-Pehrson, are
  * derived from libpng-1.0.6, and are distributed according to the same
  * disclaimer and license as libpng-1.0.6 with the following individuals
  * added to the list of Contributing Authors:
  *
  *    Simon-Pierre Cadieux
  *    Eric S. Raymond
  *    Mans Rullgard
@@ -48,39 +52,49 @@
  *
  *    There is no warranty against interference with your enjoyment of the
  *    library or against infringement.  There is no warranty that our
  *    efforts or the library will fulfill any of your particular purposes
  *    or needs.  This library is provided with all faults, and the entire
  *    risk of satisfactory quality, performance, accuracy, and effort is with
  *    the user.
  *
+ * Some files in the "contrib" directory have other copyright owners and
+ * are released under other open source licenses.
+ *
+ *
  * libpng versions 0.97, January 1998, through 1.0.6, March 20, 2000, are
  * Copyright (c) 1998-2000 Glenn Randers-Pehrson, are derived from
  * libpng-0.96, and are distributed according to the same disclaimer and
  * license as libpng-0.96, with the following individuals added to the list
  * of Contributing Authors:
  *
  *    Tom Lane
  *    Glenn Randers-Pehrson
  *    Willem van Schaik
  *
+ * Some files in the "scripts" directory have different copyright owners
+ * but are also released under this license.
+ *
  * libpng versions 0.89, June 1996, through 0.96, May 1997, are
  * Copyright (c) 1996-1997 Andreas Dilger, are derived from libpng-0.88,
  * and are distributed according to the same disclaimer and license as
  * libpng-0.88, with the following individuals added to the list of
  * Contributing Authors:
  *
  *    John Bowler
  *    Kevin Bracey
  *    Sam Bushell
  *    Magnus Holmgren
  *    Greg Roelofs
  *    Tom Tanner
  *
+ * Some files in the "scripts" directory have other copyright owners
+ * but are released under this license.
+ *
  * libpng versions 0.5, May 1995, through 0.88, January 1996, are
  * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
  *
  * For the purposes of this copyright and license, "Contributing Authors"
  * is defined as the following set of individuals:
  *
  *    Andreas Dilger
  *    Dave Martindale
@@ -110,35 +124,52 @@
  *
  * The Contributing Authors and Group 42, Inc. specifically permit, without
  * fee, and encourage the use of this source code as a component to
  * supporting the PNG file format in commercial products.  If you use this
  * source code in a product, acknowledgment is not required but would be
  * appreciated.
  *
  * END OF COPYRIGHT NOTICE, DISCLAIMER, and LICENSE.
+ *
+ * TRADEMARK:
+ *
+ * The name "libpng" has not been registered by the Copyright owner
+ * as a trademark in any jurisdiction.  However, because libpng has
+ * been distributed and maintained world-wide, continually since 1995,
+ * the Copyright owner claims "common-law trademark protection" in any
+ * jurisdiction where common-law trademark is recognized.
+ *
+ * OSI CERTIFICATION:
+ *
+ * Libpng is OSI Certified Open Source Software.  OSI Certified Open Source is
+ * a certification mark of the Open Source Initiative. OSI has not addressed
+ * the additional disclaimers inserted at version 1.0.7.
+ *
+ * EXPORT CONTROL:
+ *
+ * The Copyright owner believes that the Export Control Classification
+ * Number (ECCN) for libpng is EAR99, which means not subject to export
+ * controls or International Traffic in Arms Regulations (ITAR) because
+ * it is open source, publicly available software, that does not contain
+ * any encryption software.  See the EAR, paragraphs 734.3(b)(3) and
+ * 734.7(b).
  */
 
 /*
  * A "png_get_copyright" function is available, for convenient use in "about"
  * boxes and the like:
  *
  *    printf("%s", png_get_copyright(NULL));
  *
  * Also, the PNG logo (in PNG format, of course) is supplied in the
  * files "pngbar.png" and "pngbar.jpg (88x31) and "pngnow.png" (98x31).
  */
 
 /*
- * Libpng is OSI Certified Open Source Software.  OSI Certified Open Source is
- * a certification mark of the Open Source Initiative. OSI has not addressed
- * the additional disclaimers inserted at version 1.0.7.
- */
-
-/*
  * The contributing authors would like to thank all those who helped
  * with testing, bug fixes, and patience.  This wouldn't have been
  * possible without all of you.
  *
  * Thanks to Frank J. T. Wojcik for helping with the documentation.
  */
 
 /* Note about libpng version numbers:
@@ -183,21 +214,21 @@
  *    1.0.6j                        10007  2.1.0.6j (incompatible with 1.0.0)
  *    1.0.7beta11-14        DLLNUM  10007  2.1.0.7beta11-14 (binary compatible)
  *    1.0.7beta15-18           1    10007  2.1.0.7beta15-18 (binary compatible)
  *    1.0.7rc1-2               1    10007  2.1.0.7rc1-2 (binary compatible)
  *    1.0.7                    1    10007  (still compatible)
  *    ...
  *    1.0.19                  10    10019  10.so.0.19[.0]
  *    ...
- *    1.2.53                  13    10253  12.so.0.53[.0]
+ *    1.2.56                  13    10256  12.so.0.56[.0]
  *    ...
- *    1.5.23                  15    10523  15.so.15.23[.0]
+ *    1.5.27                  15    10527  15.so.15.27[.0]
  *    ...
- *    1.6.21                  16    10621  16.so.16.21[.0]
+ *    1.6.23                  16    10623  16.so.16.23[.0]
  *
  *    Henceforth the source version will match the shared-library major
  *    and minor numbers; the shared-library major version number will be
  *    used for changes in backward compatibility, as it is intended.  The
  *    PNG_LIBPNG_VER macro, which is not used within libpng but is available
  *    for applications, is an unsigned integer of the form xyyzz corresponding
  *    to the source version x.y.z (leading zeros in y and z).  Beta versions
  *    were given the previous public release number plus a letter, until
@@ -215,23 +246,23 @@
  * is available as a W3C Recommendation and as an ISO Specification,
  * <http://www.w3.org/TR/2003/REC-PNG-20031110/
  */
 
 /*
  * Y2K compliance in libpng:
  * =========================
  *
- *    January 15, 2016
+ *    June 9, 2016
  *
  *    Since the PNG Development group is an ad-hoc body, we can't make
  *    an official declaration.
  *
  *    This is your unofficial assurance that libpng from version 0.71 and
- *    upward through 1.6.21 are Y2K compliant.  It is my belief that
+ *    upward through 1.6.23 are Y2K compliant.  It is my belief that
  *    earlier versions were also Y2K compliant.
  *
  *    Libpng only has two year fields.  One is a 2-byte unsigned integer
  *    that will hold years up to 65535.  The other, which is deprecated,
  *    holds the date in text format, and will hold years up to 9999.
  *
  *    The integer is
  *        "png_uint_16 year" in png_time_struct.
@@ -283,27 +314,27 @@
  * file has been stripped from your copy of libpng, you can find it at
  * <http://www.libpng.org/pub/png/libpng-manual.txt>
  *
  * If you just need to read a PNG file and don't want to read the documentation
  * skip to the end of this file and read the section entitled 'simplified API'.
  */
 
 /* Version information for png.h - this should match the version in png.c */
-#define PNG_LIBPNG_VER_STRING "1.6.21+apng"
+#define PNG_LIBPNG_VER_STRING "1.6.23+apng"
 #define PNG_HEADER_VERSION_STRING \
-     " libpng version 1.6.21+apng - January 15, 2016\n"
+     " libpng version 1.6.23+apng - June 9, 2016\n"
 
 #define PNG_LIBPNG_VER_SONUM   16
 #define PNG_LIBPNG_VER_DLLNUM  16
 
 /* These should match the first 3 components of PNG_LIBPNG_VER_STRING: */
 #define PNG_LIBPNG_VER_MAJOR   1
 #define PNG_LIBPNG_VER_MINOR   6
-#define PNG_LIBPNG_VER_RELEASE 21
+#define PNG_LIBPNG_VER_RELEASE 23
 
 /* This should match the numeric part of the final component of
  * PNG_LIBPNG_VER_STRING, omitting any leading zero:
  */
 
 #define PNG_LIBPNG_VER_BUILD  0
 
 /* Release Status */
@@ -324,17 +355,17 @@
 #define PNG_LIBPNG_BUILD_BASE_TYPE PNG_LIBPNG_BUILD_STABLE
 
 /* Careful here.  At one time, Guy wanted to use 082, but that would be octal.
  * We must not include leading zeros.
  * Versions 0.7 through 1.0.0 were in the range 0 to 100 here (only
  * version 1.0.0 was mis-numbered 100 instead of 10000).  From
  * version 1.0.1 it's    xxyyzz, where x=major, y=minor, z=release
  */
-#define PNG_LIBPNG_VER 10621 /* 1.6.21 */
+#define PNG_LIBPNG_VER 10623 /* 1.6.23 */
 
 /* Library configuration: these options cannot be changed after
  * the library has been built.
  */
 #ifndef PNGLCONF_H
     /* If pnglibconf.h is missing, you can
      * copy scripts/pnglibconf.h.prebuilt to pnglibconf.h
      */
@@ -449,17 +480,17 @@ extern "C" {
 /* blend_op flags from inside fcTL */
 #define PNG_BLEND_OP_SOURCE        0x00
 #define PNG_BLEND_OP_OVER          0x01
 #endif /* APNG */
 
 /* This triggers a compiler error in png.c, if png.c and png.h
  * do not agree upon the version number.
  */
-typedef char* png_libpng_version_1_6_21;
+typedef char* png_libpng_version_1_6_23;
 
 /* Basic control structions.  Read libpng-manual.txt or libpng.3 for more info.
  *
  * png_struct is the cache of information used while reading or writing a single
  * PNG file.  One of these is always required, although the simplified API
  * (below) hides the creation and destruction of it.
  */
 typedef struct png_struct_def png_struct;
@@ -750,34 +781,32 @@ typedef png_unknown_chunk * * png_unknow
 /* Maximum number of entries in PLTE/sPLT/tRNS arrays */
 #define PNG_MAX_PALETTE_LENGTH    256
 
 /* These determine if an ancillary chunk's data has been successfully read
  * from the PNG header, or if the application has filled in the corresponding
  * data in the info_struct to be written into the output file.  The values
  * of the PNG_INFO_<chunk> defines should NOT be changed.
  */
-#define PNG_INFO_gAMA 0x0001
-#define PNG_INFO_sBIT 0x0002
-#define PNG_INFO_cHRM 0x0004
-#define PNG_INFO_PLTE 0x0008
-#define PNG_INFO_tRNS 0x0010
-#define PNG_INFO_bKGD 0x0020
-#define PNG_INFO_hIST 0x0040
-#define PNG_INFO_pHYs 0x0080
-#define PNG_INFO_oFFs 0x0100
-#define PNG_INFO_tIME 0x0200
-#define PNG_INFO_pCAL 0x0400
-#define PNG_INFO_sRGB 0x0800   /* GR-P, 0.96a */
-#define PNG_INFO_iCCP 0x1000   /* ESR, 1.0.6 */
-#define PNG_INFO_sPLT 0x2000   /* ESR, 1.0.6 */
-#define PNG_INFO_sCAL 0x4000   /* ESR, 1.0.6 */
-#if INT_MAX >= 0x8000 /* else this might break */
-#define PNG_INFO_IDAT 0x8000   /* ESR, 1.0.6 */
-#endif
+#define PNG_INFO_gAMA 0x0001U
+#define PNG_INFO_sBIT 0x0002U
+#define PNG_INFO_cHRM 0x0004U
+#define PNG_INFO_PLTE 0x0008U
+#define PNG_INFO_tRNS 0x0010U
+#define PNG_INFO_bKGD 0x0020U
+#define PNG_INFO_hIST 0x0040U
+#define PNG_INFO_pHYs 0x0080U
+#define PNG_INFO_oFFs 0x0100U
+#define PNG_INFO_tIME 0x0200U
+#define PNG_INFO_pCAL 0x0400U
+#define PNG_INFO_sRGB 0x0800U  /* GR-P, 0.96a */
+#define PNG_INFO_iCCP 0x1000U  /* ESR, 1.0.6 */
+#define PNG_INFO_sPLT 0x2000U  /* ESR, 1.0.6 */
+#define PNG_INFO_sCAL 0x4000U  /* ESR, 1.0.6 */
+#define PNG_INFO_IDAT 0x8000U  /* ESR, 1.0.6 */
 #ifdef PNG_APNG_SUPPORTED
 #define PNG_INFO_acTL 0x10000
 #define PNG_INFO_fcTL 0x20000
 #endif
 
 /* This is used for the transformation routines, as some of them
  * change these values for the row.  It also should enable using
  * the routines for other purposes.
@@ -1346,17 +1375,17 @@ PNG_FIXED_EXPORT(215, void, png_set_back
 #endif
 
 #ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
 /* Scale a 16-bit depth file down to 8-bit, accurately. */
 PNG_EXPORT(229, void, png_set_scale_16, (png_structrp png_ptr));
 #endif
 
 #ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED
-#define PNG_READ_16_TO_8 SUPPORTED /* Name prior to 1.5.4 */
+#define PNG_READ_16_TO_8_SUPPORTED /* Name prior to 1.5.4 */
 /* Strip the second byte of information from a 16-bit depth file. */
 PNG_EXPORT(48, void, png_set_strip_16, (png_structrp png_ptr));
 #endif
 
 #ifdef PNG_READ_QUANTIZE_SUPPORTED
 /* Turn on quantizing, and reduce the palette to the number of colors
  * available.
  */
@@ -1497,18 +1526,18 @@ PNG_EXPORT(67, void, png_set_filter, (pn
  * These values should NOT be changed.
  */
 #define PNG_NO_FILTERS     0x00
 #define PNG_FILTER_NONE    0x08
 #define PNG_FILTER_SUB     0x10
 #define PNG_FILTER_UP      0x20
 #define PNG_FILTER_AVG     0x40
 #define PNG_FILTER_PAETH   0x80
-#define PNG_ALL_FILTERS (PNG_FILTER_NONE | PNG_FILTER_SUB | PNG_FILTER_UP | \
-                         PNG_FILTER_AVG | PNG_FILTER_PAETH)
+#define PNG_FAST_FILTERS (PNG_FILTER_NONE | PNG_FILTER_SUB | PNG_FILTER_UP)
+#define PNG_ALL_FILTERS (PNG_FAST_FILTERS | PNG_FILTER_AVG | PNG_FILTER_PAETH)
 
 /* Filter values (not flags) - used in pngwrite.c, pngwutil.c for now.
  * These defines should NOT be changed.
  */
 #define PNG_FILTER_VALUE_NONE  0
 #define PNG_FILTER_VALUE_SUB   1
 #define PNG_FILTER_VALUE_UP    2
 #define PNG_FILTER_VALUE_AVG   3
@@ -1775,31 +1804,31 @@ PNG_EXPORT(98, void, png_free_data, (png
 PNG_EXPORT(99, void, png_data_freer, (png_const_structrp png_ptr,
     png_inforp info_ptr, int freer, png_uint_32 mask));
 
 /* Assignments for png_data_freer */
 #define PNG_DESTROY_WILL_FREE_DATA 1
 #define PNG_SET_WILL_FREE_DATA 1
 #define PNG_USER_WILL_FREE_DATA 2
 /* Flags for png_ptr->free_me and info_ptr->free_me */
-#define PNG_FREE_HIST 0x0008
-#define PNG_FREE_ICCP 0x0010
-#define PNG_FREE_SPLT 0x0020
-#define PNG_FREE_ROWS 0x0040
-#define PNG_FREE_PCAL 0x0080
-#define PNG_FREE_SCAL 0x0100
+#define PNG_FREE_HIST 0x0008U
+#define PNG_FREE_ICCP 0x0010U
+#define PNG_FREE_SPLT 0x0020U
+#define PNG_FREE_ROWS 0x0040U
+#define PNG_FREE_PCAL 0x0080U
+#define PNG_FREE_SCAL 0x0100U
 #ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED
-#  define PNG_FREE_UNKN 0x0200
+#  define PNG_FREE_UNKN 0x0200U
 #endif
-/*      PNG_FREE_LIST 0x0400    removed in 1.6.0 because it is ignored */
-#define PNG_FREE_PLTE 0x1000
-#define PNG_FREE_TRNS 0x2000
-#define PNG_FREE_TEXT 0x4000
-#define PNG_FREE_ALL  0x7fff
-#define PNG_FREE_MUL  0x4220 /* PNG_FREE_SPLT|PNG_FREE_TEXT|PNG_FREE_UNKN */
+/*      PNG_FREE_LIST 0x0400U   removed in 1.6.0 because it is ignored */
+#define PNG_FREE_PLTE 0x1000U
+#define PNG_FREE_TRNS 0x2000U
+#define PNG_FREE_TEXT 0x4000U
+#define PNG_FREE_ALL  0x7fffU
+#define PNG_FREE_MUL  0x4220U /* PNG_FREE_SPLT|PNG_FREE_TEXT|PNG_FREE_UNKN */
 
 #ifdef PNG_USER_MEM_SUPPORTED
 PNG_EXPORTA(100, png_voidp, png_malloc_default, (png_const_structrp png_ptr,
     png_alloc_size_t size), PNG_ALLOCATED PNG_DEPRECATED);
 PNG_EXPORTA(101, void, png_free_default, (png_const_structrp png_ptr,
     png_voidp ptr), PNG_DEPRECATED);
 #endif
 
@@ -2913,22 +2942,29 @@ typedef struct
 
 /* Information about the whole row, or whole image */
 #define PNG_IMAGE_ROW_STRIDE(image)\
    (PNG_IMAGE_PIXEL_CHANNELS((image).format) * (image).width)
    /* Return the total number of components in a single row of the image; this
     * is the minimum 'row stride', the minimum count of components between each
     * row.  For a color-mapped image this is the minimum number of bytes in a
     * row.
+    *
+    * WARNING: this macro overflows for some images with more than one component
+    * and very large image widths.  libpng will refuse to process an image where
+    * this macro would overflow.
     */
 
 #define PNG_IMAGE_BUFFER_SIZE(image, row_stride)\
    (PNG_IMAGE_PIXEL_COMPONENT_SIZE((image).format)*(image).height*(row_stride))
    /* Return the size, in bytes, of an image buffer given a png_image and a row
     * stride - the number of components to leave space for in each row.
+    *
+    * WARNING: this macro overflows a 32-bit integer for some large PNG images,
+    * libpng will refuse to process an image where such an overflow would occur.
     */
 
 #define PNG_IMAGE_SIZE(image)\
    PNG_IMAGE_BUFFER_SIZE(image, PNG_IMAGE_ROW_STRIDE(image))
    /* Return the size, in bytes, of the image in memory given just a png_image;
     * the row stride is the minimum stride required for the image.
     */
 
@@ -3039,62 +3075,153 @@ PNG_EXPORT(237, int, png_image_finish_re
 
 PNG_EXPORT(238, void, png_image_free, (png_imagep image));
    /* Free any data allocated by libpng in image->opaque, setting the pointer to
     * NULL.  May be called at any time after the structure is initialized.
     */
 #endif /* SIMPLIFIED_READ */
 
 #ifdef PNG_SIMPLIFIED_WRITE_SUPPORTED
-#ifdef PNG_STDIO_SUPPORTED
 /* WRITE APIS
  * ----------
  * For write you must initialize a png_image structure to describe the image to
  * be written.  To do this use memset to set the whole structure to 0 then
  * initialize fields describing your image.
  *
  * version: must be set to PNG_IMAGE_VERSION
  * opaque: must be initialized to NULL
  * width: image width in pixels
  * height: image height in rows
  * format: the format of the data (image and color-map) you wish to write
  * flags: set to 0 unless one of the defined flags applies; set
  *    PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB for color format images where the RGB
  *    values do not correspond to the colors in sRGB.
  * colormap_entries: set to the number of entries in the color-map (0 to 256)
  */
+#ifdef PNG_SIMPLIFIED_WRITE_STDIO_SUPPORTED
 PNG_EXPORT(239, int, png_image_write_to_file, (png_imagep image,
    const char *file, int convert_to_8bit, const void *buffer,
    png_int_32 row_stride, const void *colormap));
    /* Write the image to the named file. */
 
 PNG_EXPORT(240, int, png_image_write_to_stdio, (png_imagep image, FILE *file,
    int convert_to_8_bit, const void *buffer, png_int_32 row_stride,
    const void *colormap));
    /* Write the image to the given (FILE*). */
-
-/* With both write APIs if image is in one of the linear formats with 16-bit
+#endif /* SIMPLIFIED_WRITE_STDIO */
+
+/* With all write APIs if image is in one of the linear formats with 16-bit
  * data then setting convert_to_8_bit will cause the output to be an 8-bit PNG
  * gamma encoded according to the sRGB specification, otherwise a 16-bit linear
  * encoded PNG file is written.
  *
  * With color-mapped data formats the colormap parameter point to a color-map
  * with at least image->colormap_entries encoded in the specified format.  If
  * the format is linear the written PNG color-map will be converted to sRGB
  * regardless of the convert_to_8_bit flag.
  *
  * With all APIs row_stride is handled as in the read APIs - it is the spacing
  * from one row to the next in component sized units (1 or 2 bytes) and if
- * negative indicates a bottom-up row layout in the buffer.  If row_stride is zero,
- * libpng will calculate it for you from the image width and number of channels.
+ * negative indicates a bottom-up row layout in the buffer.  If row_stride is
+ * zero, libpng will calculate it for you from the image width and number of
+ * channels.
  *
- * Note that the write API does not support interlacing, sub-8-bit pixels, indexed
- * PNG (color_type 3) or most ancillary chunks.
+ * Note that the write API does not support interlacing, sub-8-bit pixels or
+ * most ancillary chunks.  If you need to write text chunks (e.g. for copyright
+ * notices) you need to use one of the other APIs.
  */
-#endif /* STDIO */
+
+PNG_EXPORT(245, int, png_image_write_to_memory, (png_imagep image, void *memory,
+   png_alloc_size_t * PNG_RESTRICT memory_bytes, int convert_to_8_bit,
+   const void *buffer, png_int_32 row_stride, const void *colormap));
+   /* Write the image to the given memory buffer.  The function both writes the
+    * whole PNG data stream to *memory and updates *memory_bytes with the count
+    * of bytes written.
+    *
+    * 'memory' may be NULL.  In this case *memory_bytes is not read however on
+    * success the number of bytes which would have been written will still be
+    * stored in *memory_bytes.  On failure *memory_bytes will contain 0.
+    *
+    * If 'memory' is not NULL it must point to memory[*memory_bytes] of
+    * writeable memory.
+    *
+    * If the function returns success memory[*memory_bytes] (if 'memory' is not
+    * NULL) contains the written PNG data.  *memory_bytes will always be less
+    * than or equal to the original value.
+    *
+    * If the function returns false and *memory_bytes was not changed an error
+    * occured during write.  If *memory_bytes was changed, or is not 0 if
+    * 'memory' was NULL, the write would have succeeded but for the memory
+    * buffer being too small.  *memory_bytes contains the required number of
+    * bytes and will be bigger that the original value.
+    */
+
+#define png_image_write_get_memory_size(image, size, convert_to_8_bit, buffer,\
+   row_stride, colormap)\
+   png_image_write_to_memory(&(image), 0, &(size), convert_to_8_bit, buffer,\
+         row_stride, colormap)
+   /* Return the amount of memory in 'size' required to compress this image.
+    * The png_image structure 'image' must be filled in as in the above
+    * function and must not be changed before the actual write call, the buffer
+    * and all other parameters must also be identical to that in the final
+    * write call.  The 'size' variable need not be initialized.
+    *
+    * NOTE: the macro returns true/false, if false is returned 'size' will be
+    * set to zero and the write failed and probably will fail if tried again.
+    */
+
+/* You can pre-allocate the buffer by making sure it is of sufficient size
+ * regardless of the amount of compression achieved.  The buffer size will
+ * always be bigger than the original image and it will never be filled.  The
+ * following macros are provided to assist in allocating the buffer.
+ */
+#define PNG_IMAGE_DATA_SIZE(image) (PNG_IMAGE_SIZE(image)+(image).height)
+   /* The number of uncompressed bytes in the PNG byte encoding of the image;
+    * uncompressing the PNG IDAT data will give this number of bytes.
+    *
+    * NOTE: while PNG_IMAGE_SIZE cannot overflow for an image in memory this
+    * macro can because of the extra bytes used in the PNG byte encoding.  You
+    * need to avoid this macro if your image size approaches 2^30 in width or
+    * height.  The same goes for the remainder of these macros; they all produce
+    * bigger numbers than the actual in-memory image size.
+    */
+#ifndef PNG_ZLIB_MAX_SIZE
+#  define PNG_ZLIB_MAX_SIZE(b) ((b)+(((b)+7U)>>3)+(((b)+63U)>>6)+11U)
+   /* An upper bound on the number of compressed bytes given 'b' uncompressed
+    * bytes.  This is based on deflateBounds() in zlib; different
+    * implementations of zlib compression may conceivably produce more data so
+    * if your zlib implementation is not zlib itself redefine this macro
+    * appropriately.
+    */
+#endif
+
+#define PNG_IMAGE_COMPRESSED_SIZE_MAX(image)\
+   PNG_ZLIB_MAX_SIZE((png_alloc_size_t)PNG_IMAGE_DATA_SIZE(image))
+   /* An upper bound on the size of the data in the PNG IDAT chunks. */
+
+#define PNG_IMAGE_PNG_SIZE_MAX_(image, image_size)\
+   ((8U/*sig*/+25U/*IHDR*/+16U/*gAMA*/+44U/*cHRM*/+12U/*IEND*/+\
+    (((image).format&PNG_FORMAT_FLAG_COLORMAP)?/*colormap: PLTE, tRNS*/\
+     12U+3U*(image).colormap_entries/*PLTE data*/+\
+     (((image).format&PNG_FORMAT_FLAG_ALPHA)?\
+      12U/*tRNS*/+(image).colormap_entries:0U):0U)+\
+    12U)+(12U*((image_size)/PNG_ZBUF_SIZE))/*IDAT*/+(image_size))
+   /* A helper for the following macro; if your compiler cannot handle the
+    * following macro use this one with the result of
+    * PNG_IMAGE_COMPRESSED_SIZE_MAX(image) as the second argument (most
+    * compilers should handle this just fine.)
+    */
+
+#define PNG_IMAGE_PNG_SIZE_MAX(image)\
+   PNG_IMAGE_PNG_SIZE_MAX_(image, PNG_IMAGE_COMPRESSED_SIZE_MAX(image))
+   /* An upper bound on the total length of the PNG data stream for 'image'.
+    * The result is of type png_alloc_size_t, on 32-bit systems this may
+    * overflow even though PNG_IMAGE_DATA_SIZE does not overflow; the write will
+    * run out of buffer space but return a corrected size which should work.
+    */
 #endif /* SIMPLIFIED_WRITE */
 /*******************************************************************************
  *  END OF SIMPLIFIED API
  ******************************************************************************/
 #endif /* SIMPLIFIED_{READ|WRITE} */
 
 /*******************************************************************************
  * Section 6: IMPLEMENTATION OPTIONS
@@ -3212,19 +3339,19 @@ PNG_EXPORT(264, void, png_write_frame_ta
  * defs, and in scripts/symbols.def.
  */
 
 /* The last ordinal number (this is the *last* one already used; the next
  * one to use is one more than this.)
  */
 #ifdef PNG_EXPORT_LAST_ORDINAL
 #ifdef PNG_APNG_SUPPORTED
-  PNG_EXPORT_LAST_ORDINAL(264);
+  PNG_EXPORT_LAST_ORDINAL(265);
 #else
-  PNG_EXPORT_LAST_ORDINAL(244);
+  PNG_EXPORT_LAST_ORDINAL(245);
 #endif /* APNG */
 #endif
 
 #ifdef __cplusplus
 }
 #endif
 
 #endif /* PNG_VERSION_INFO_ONLY */
--- a/media/libpng/pngconf.h
+++ b/media/libpng/pngconf.h
@@ -1,12 +1,12 @@
 
 /* pngconf.h - machine configurable file for libpng
  *
- * libpng version 1.6.21, January 15, 2016
+ * libpng version 1.6.23, June 9, 2016
  *
  * Copyright (c) 1998-2002,2004,2006-2015 Glenn Randers-Pehrson
  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
  *
  * This code is released under the libpng license.
  * For conditions of distribution and use, see the disclaimer
  * and license in png.h
--- a/media/libpng/pngerror.c
+++ b/media/libpng/pngerror.c
@@ -39,17 +39,17 @@ PNG_FUNCTION(void,PNGAPI
 png_error,(png_const_structrp png_ptr, png_const_charp error_message),
    PNG_NORETURN)
 {
 #ifdef PNG_ERROR_NUMBERS_SUPPORTED
    char msg[16];
    if (png_ptr != NULL)
    {
       if ((png_ptr->flags &
-         (PNG_FLAG_STRIP_ERROR_NUMBERS|PNG_FLAG_STRIP_ERROR_TEXT)) != 0
+         (PNG_FLAG_STRIP_ERROR_NUMBERS|PNG_FLAG_STRIP_ERROR_TEXT)) != 0)
       {
          if (*error_message == PNG_LITERAL_SHARP)
          {
             /* Strip "#nnnn " from beginning of error message. */
             int offset;
             for (offset = 1; offset<15; offset++)
                if (error_message[offset] == ' ')
                   break;
--- a/media/libpng/pngget.c
+++ b/media/libpng/pngget.c
@@ -451,21 +451,21 @@ png_get_pHYs_dpi(png_const_structrp png_
             if (res_y != NULL) *res_y = (png_uint_32)(*res_y * .0254 + .50);
          }
       }
    }
 
    return (retval);
 }
 #endif /* pHYs */
-#endif  /* INCH_CONVERSIONS */
+#endif /* INCH_CONVERSIONS */
 
 /* png_get_channels really belongs in here, too, but it's been around longer */
 
-#endif  /* EASY_ACCESS */
+#endif /* EASY_ACCESS */
 
 
 png_byte PNGAPI
 png_get_channels(png_const_structrp png_ptr, png_const_inforp info_ptr)
 {
    if (png_ptr != NULL && info_ptr != NULL)
       return(info_ptr->channels);
 
@@ -1137,29 +1137,29 @@ png_get_user_chunk_ptr(png_const_structr
 
 png_size_t PNGAPI
 png_get_compression_buffer_size(png_const_structrp png_ptr)
 {
    if (png_ptr == NULL)
       return 0;
 
 #ifdef PNG_WRITE_SUPPORTED
-      if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0)
+   if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0)
 #endif
    {
 #ifdef PNG_SEQUENTIAL_READ_SUPPORTED
-         return png_ptr->IDAT_read_size;
+      return png_ptr->IDAT_read_size;
 #else
-         return PNG_IDAT_READ_SIZE;
+      return PNG_IDAT_READ_SIZE;
 #endif
    }
 
 #ifdef PNG_WRITE_SUPPORTED
-      else
-         return png_ptr->zbuffer_size;
+   else
+      return png_ptr->zbuffer_size;
 #endif
 }
 
 #ifdef PNG_SET_USER_LIMITS_SUPPORTED
 /* These functions were added to libpng 1.2.6 and were enabled
  * by default in libpng-1.4.0 */
 png_uint_32 PNGAPI
 png_get_user_width_max (png_const_structrp png_ptr)
--- a/media/libpng/pngpread.c
+++ b/media/libpng/pngpread.c
@@ -1,13 +1,13 @@
 
 /* pngpread.c - read a png file in push mode
  *
- * Last changed in libpng 1.6.18 [July 23, 2015]
- * Copyright (c) 1998-2002,2004,2006-2015 Glenn Randers-Pehrson
+ * Last changed in libpng 1.6.23 [June 9, 2016]
+ * Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson
  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
  *
  * This code is released under the libpng license.
  * For conditions of distribution and use, see the disclaimer
  * and license in png.h
  */
 
@@ -288,22 +288,24 @@ png_push_read_chunk(png_structrp png_ptr
        */
       if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
          png_error(png_ptr, "Missing IHDR before IDAT");
 
       else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&
           (png_ptr->mode & PNG_HAVE_PLTE) == 0)
          png_error(png_ptr, "Missing PLTE before IDAT");
 
-      png_ptr->mode |= PNG_HAVE_IDAT;
       png_ptr->process_mode = PNG_READ_IDAT_MODE;
 
-      if ((png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT) == 0)
-         if (png_ptr->push_length == 0)
-            return;
+      if ((png_ptr->mode & PNG_HAVE_IDAT) != 0)
+         if ((png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT) == 0)
+            if (png_ptr->push_length == 0)
+               return;
+
+      png_ptr->mode |= PNG_HAVE_IDAT;
 
       if ((png_ptr->mode & PNG_AFTER_IDAT) != 0)
          png_benign_error(png_ptr, "Too many IDATs found");
    }
 
    if (chunk_name == png_IHDR)
    {
       if (png_ptr->push_length != 13)
@@ -594,17 +596,20 @@ png_push_save_buffer(png_structrp png_pt
           (png_size_t)new_max);
 
       if (png_ptr->save_buffer == NULL)
       {
          png_free(png_ptr, old_buffer);
          png_error(png_ptr, "Insufficient memory for save_buffer");
       }
 
-      memcpy(png_ptr->save_buffer, old_buffer, png_ptr->save_buffer_size);
+      if (old_buffer)
+         memcpy(png_ptr->save_buffer, old_buffer, png_ptr->save_buffer_size);
+      else if (png_ptr->save_buffer_size)
+         png_error(png_ptr, "save_buffer error");
       png_free(png_ptr, old_buffer);
       png_ptr->save_buffer_max = new_max;
    }
    if (png_ptr->current_buffer_size)
    {
       memcpy(png_ptr->save_buffer + png_ptr->save_buffer_size,
          png_ptr->current_buffer_ptr, png_ptr->current_buffer_size);
       png_ptr->save_buffer_size += png_ptr->current_buffer_size;
--- a/media/libpng/pngpriv.h
+++ b/media/libpng/pngpriv.h
@@ -1,13 +1,13 @@
 
 /* pngpriv.h - private declarations for use inside libpng
  *
- * Last changed in libpng 1.6.21 [January 15, 2016]
- * Copyright (c) 1998-2002,2004,2006-2015 Glenn Randers-Pehrson
+ * Last changed in libpng 1.6.22 [May 26, 2016]
+ * Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson
  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
  *
  * This code is released under the libpng license.
  * For conditions of distribution and use, see the disclaimer
  * and license in png.h
  */
 
--- a/media/libpng/pngread.c
+++ b/media/libpng/pngread.c
@@ -1,13 +1,13 @@
 
 /* pngread.c - read a PNG file
  *
- * Last changed in libpng 1.6.17 [March 26, 2015]
- * Copyright (c) 1998-2002,2004,2006-2015 Glenn Randers-Pehrson
+ * Last changed in libpng 1.6.23 [June 9, 2016]
+ * Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson
  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
  *
  * This code is released under the libpng license.
  * For conditions of distribution and use, see the disclaimer
  * and license in png.h
  *
  * This file contains routines that an application calls directly to
@@ -122,17 +122,20 @@ png_read_info(png_structrp png_ptr, png_
 
          else if ((png_ptr->mode & PNG_AFTER_IDAT) != 0)
             png_chunk_benign_error(png_ptr, "Too many IDATs found");
 
          png_ptr->mode |= PNG_HAVE_IDAT;
       }
 
       else if ((png_ptr->mode & PNG_HAVE_IDAT) != 0)
+      {
+         png_ptr->mode |= PNG_HAVE_CHUNK_AFTER_IDAT;
          png_ptr->mode |= PNG_AFTER_IDAT;
+      }
 
       /* This should be a binary subdivision search or a hash for
        * matching the chunk name rather than a linear search.
        */
       if (chunk_name == png_IHDR)
          png_handle_IHDR(png_ptr, info_ptr, length);
 
       else if (chunk_name == png_IEND)
@@ -860,47 +863,54 @@ png_read_end(png_structrp png_ptr, png_i
      png_benign_error(png_ptr, "Read palette index exceeding num_palette");
 #endif
 
    do
    {
       png_uint_32 length = png_read_chunk_header(png_ptr);
       png_uint_32 chunk_name = png_ptr->chunk_name;
 
+      if (chunk_name != png_IDAT)
+         png_ptr->mode |= PNG_HAVE_CHUNK_AFTER_IDAT;
+
       if (chunk_name == png_IEND)
          png_handle_IEND(png_ptr, info_ptr, length);
 
       else if (chunk_name == png_IHDR)
          png_handle_IHDR(png_ptr, info_ptr, length);
 
       else if (info_ptr == NULL)
          png_crc_finish(png_ptr, length);
 
 #ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
       else if ((keep = png_chunk_unknown_handling(png_ptr, chunk_name)) != 0)
       {
          if (chunk_name == png_IDAT)
          {
-            if ((length > 0) ||
-                (png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT) != 0)
-               png_benign_error(png_ptr, "Too many IDATs found");
+            if ((length > 0 && !(png_ptr->flags & PNG_FLAG_ZSTREAM_ENDED))
+                || (png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT) != 0)
+               png_benign_error(png_ptr, ".Too many IDATs found");
          }
          png_handle_unknown(png_ptr, info_ptr, length, keep);
          if (chunk_name == png_PLTE)
             png_ptr->mode |= PNG_HAVE_PLTE;
       }
 #endif
 
       else if (chunk_name == png_IDAT)
       {
          /* Zero length IDATs are legal after the last IDAT has been
-          * read, but not after other chunks have been read.
+          * read, but not after other chunks have been read.  1.6 does not
+          * always read all the deflate data; specifically it cannot be relied
+          * upon to read the Adler32 at the end.  If it doesn't ignore IDAT
+          * chunks which are longer than zero as well:
           */
-         if ((length > 0) || (png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT) != 0)
-            png_benign_error(png_ptr, "Too many IDATs found");
+         if ((length > 0 && !(png_ptr->flags & PNG_FLAG_ZSTREAM_ENDED))
+             || (png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT) != 0)
+            png_benign_error(png_ptr, "..Too many IDATs found");
 
          png_crc_finish(png_ptr, length);
       }
       else if (chunk_name == png_PLTE)
          png_handle_PLTE(png_ptr, info_ptr, length);
 
 #ifdef PNG_READ_bKGD_SUPPORTED
       else if (chunk_name == png_bKGD)
@@ -3923,26 +3933,26 @@ png_image_read_direct(png_voidp argument
             int where;
 
             if (linear != 0)
                filler = 65535;
 
             else
                filler = 255;
 
-#           ifdef PNG_FORMAT_AFIRST_SUPPORTED
-               if ((format & PNG_FORMAT_FLAG_AFIRST) != 0)
-               {
-                  where = PNG_FILLER_BEFORE;
-                  change &= ~PNG_FORMAT_FLAG_AFIRST;
-               }
-
-               else
-#           endif
-               where = PNG_FILLER_AFTER;
+#ifdef PNG_FORMAT_AFIRST_SUPPORTED
+            if ((format & PNG_FORMAT_FLAG_AFIRST) != 0)
+            {
+               where = PNG_FILLER_BEFORE;
+               change &= ~PNG_FORMAT_FLAG_AFIRST;
+            }
+
+            else
+#endif
+            where = PNG_FILLER_AFTER;
 
             png_set_add_alpha(png_ptr, filler, where);
          }
 
          /* This stops the (irrelevant) call to swap_alpha below. */
          change &= ~PNG_FORMAT_FLAG_ALPHA;
       }
 
@@ -4040,22 +4050,22 @@ png_image_read_direct(png_voidp argument
       }
 
       else if (do_local_compose != 0) /* internal error */
          png_error(png_ptr, "png_image_read: alpha channel lost");
 
       if (info_ptr->bit_depth == 16)
          info_format |= PNG_FORMAT_FLAG_LINEAR;
 
-#     ifdef PNG_FORMAT_BGR_SUPPORTED
-         if ((png_ptr->transformations & PNG_BGR) != 0)
-            info_format |= PNG_FORMAT_FLAG_BGR;
-#     endif
-
-#     ifdef PNG_FORMAT_AFIRST_SUPPORTED
+#ifdef PNG_FORMAT_BGR_SUPPORTED
+      if ((png_ptr->transformations & PNG_BGR) != 0)
+         info_format |= PNG_FORMAT_FLAG_BGR;
+#endif
+
+#ifdef PNG_FORMAT_AFIRST_SUPPORTED
          if (do_local_background == 2)
          {
             if ((format & PNG_FORMAT_FLAG_AFIRST) != 0)
                info_format |= PNG_FORMAT_FLAG_AFIRST;
          }
 
          if ((png_ptr->transformations & PNG_SWAP_ALPHA) != 0 ||
             ((png_ptr->transformations & PNG_ADD_ALPHA) != 0 &&
@@ -4146,68 +4156,94 @@ png_image_read_direct(png_voidp argument
 }
 
 int PNGAPI
 png_image_finish_read(png_imagep image, png_const_colorp background,
    void *buffer, png_int_32 row_stride, void *colormap)
 {
    if (image != NULL && image->version == PNG_IMAGE_VERSION)
    {
-      png_uint_32 check;
-
-      if (row_stride == 0)
-         row_stride = PNG_IMAGE_ROW_STRIDE(*image);
-
-      if (row_stride < 0)
-         check = -row_stride;
-
-      else
-         check = row_stride;
-
-      if (image->opaque != NULL && buffer != NULL &&
-         check >= PNG_IMAGE_ROW_STRIDE(*image))
+      /* Check for row_stride overflow.  This check is not performed on the
+       * original PNG format because it may not occur in the output PNG format
+       * and libpng deals with the issues of reading the original.
+       */
+      const unsigned int channels = PNG_IMAGE_PIXEL_CHANNELS(image->format);
+
+      if (image->width <= 0x7FFFFFFFU/channels) /* no overflow */
       {
-         if ((image->format & PNG_FORMAT_FLAG_COLORMAP) == 0 ||
-            (image->colormap_entries > 0 && colormap != NULL))
+         png_uint_32 check;
+         const png_uint_32 png_row_stride = image->width * channels;
+
+         if (row_stride == 0)
+            row_stride = (png_int_32)/*SAFE*/png_row_stride;
+
+         if (row_stride < 0)
+            check = -row_stride;
+
+         else
+            check = row_stride;
+
+         if (image->opaque != NULL && buffer != NULL && check >= png_row_stride)
          {
-            int result;
-            png_image_read_control display;
-
-            memset(&display, 0, (sizeof display));
-            display.image = image;
-            display.buffer = buffer;
-            display.row_stride = row_stride;
-            display.colormap = colormap;
-            display.background = background;
-            display.local_row = NULL;
-
-            /* Choose the correct 'end' routine; for the color-map case all the
-             * setup has already been done.
+            /* Now check for overflow of the image buffer calculation; this
+             * limits the whole image size to 32 bits for API compatibility with
+             * the current, 32-bit, PNG_IMAGE_BUFFER_SIZE macro.
              */
-            if ((image->format & PNG_FORMAT_FLAG_COLORMAP) != 0)
-               result =
-                  png_safe_execute(image, png_image_read_colormap, &display) &&
-                  png_safe_execute(image, png_image_read_colormapped, &display);
+            if (image->height <= 0xFFFFFFFF/png_row_stride)
+            {
+               if ((image->format & PNG_FORMAT_FLAG_COLORMAP) == 0 ||
+                  (image->colormap_entries > 0 && colormap != NULL))
+               {
+                  int result;
+                  png_image_read_control display;
+
+                  memset(&display, 0, (sizeof display));
+                  display.image = image;
+                  display.buffer = buffer;
+                  display.row_stride = row_stride;
+                  display.colormap = colormap;
+                  display.background = background;
+                  display.local_row = NULL;
+
+                  /* Choose the correct 'end' routine; for the color-map case
+                   * all the setup has already been done.
+                   */
+                  if ((image->format & PNG_FORMAT_FLAG_COLORMAP) != 0)
+                     result = png_safe_execute(image,
+                                    png_image_read_colormap, &display) &&
+                              png_safe_execute(image,
+                                    png_image_read_colormapped, &display);
+
+                  else
+                     result =
+                        png_safe_execute(image,
+                              png_image_read_direct, &display);
+
+                  png_image_free(image);
+                  return result;
+               }
+
+               else
+                  return png_image_error(image,
+                     "png_image_finish_read[color-map]: no color-map");
+            }
 
             else
-               result =
-                  png_safe_execute(image, png_image_read_direct, &display);
-
-            png_image_free(image);
-            return result;
+               return png_image_error(image,
+                  "png_image_finish_read: image too large");
          }
 
          else
             return png_image_error(image,
-               "png_image_finish_read[color-map]: no color-map");
+               "png_image_finish_read: invalid argument");
       }
 
       else
          return png_image_error(image,
-            "png_image_finish_read: invalid argument");
+            "png_image_finish_read: row_stride too large");
    }
 
    else if (image != NULL)
       return png_image_error(image,
          "png_image_finish_read: damaged PNG_IMAGE_VERSION");
 
    return 0;
 }
--- a/media/libpng/pngrtran.c
+++ b/media/libpng/pngrtran.c
@@ -1,13 +1,13 @@
 
 /* pngrtran.c - transforms the data in a row for PNG readers
  *
- * Last changed in libpng 1.6.19 [November 12, 2015]
- * Copyright (c) 1998-2002,2004,2006-2015 Glenn Randers-Pehrson
+ * Last changed in libpng 1.6.22 [May 26, 2016]
+ * Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson
  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
  *
  * This code is released under the libpng license.
  * For conditions of distribution and use, see the disclaimer
  * and license in png.h
  *
  * This file contains functions optionally called by an application
@@ -154,17 +154,17 @@ png_set_background_fixed(png_structrp pn
 void PNGAPI
 png_set_background(png_structrp png_ptr,
     png_const_color_16p background_color, int background_gamma_code,
     int need_expand, double background_gamma)
 {
    png_set_background_fixed(png_ptr, background_color, background_gamma_code,
       need_expand, png_fixed(png_ptr, background_gamma, "png_set_background"));
 }
-#  endif  /* FLOATING_POINT */
+#  endif /* FLOATING_POINT */
 #endif /* READ_BACKGROUND */
 
 /* Scale 16-bit depth files to 8-bit depth.  If both of these are set then the
  * one that pngrtran does first (scale) happens.  This is necessary to allow the
  * TRANSFORM and API behavior to be somewhat consistent, and it's simpler.
  */
 #ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
 void PNGAPI
@@ -284,19 +284,22 @@ png_set_alpha_mode_fixed(png_structrp pn
       return;
 
    output_gamma = translate_gamma_flags(png_ptr, output_gamma, 1/*screen*/);
 
    /* Validate the value to ensure it is in a reasonable range. The value
     * is expected to be 1 or greater, but this range test allows for some
     * viewing correction values.  The intent is to weed out users of this API
     * who use the inverse of the gamma value accidentally!  Since some of these
-    * values are reasonable this may have to be changed.
+    * values are reasonable this may have to be changed:
+    *
+    * 1.6.x: changed from 0.07..3 to 0.01..100 (to accomodate the optimal 16-bit
+    * gamma of 36, and its reciprocal.)
     */
-   if (output_gamma < 70000 || output_gamma > 300000)
+   if (output_gamma < 1000 || output_gamma > 10000000)
       png_error(png_ptr, "output gamma out of expected range");
 
    /* The default file gamma is the inverse of the output gamma; the output
     * gamma may be changed below so get the file value first:
     */
    file_gamma = png_reciprocal(output_gamma);
 
    /* There are really 8 possibilities here, composed of any combination
@@ -1907,17 +1910,17 @@ png_init_read_transformations(png_struct
          for (i=0; i<istop; ++i)
          {
             int component = png_ptr->palette[i].blue;
 
             component >>= shift;
             png_ptr->palette[i].blue = (png_byte)component;
          }
    }
-#endif  /* READ_SHIFT */
+#endif /* READ_SHIFT */
 }
 
 /* Modify the info structure to reflect the transformations.  The
  * info should be updated so a PNG file could be written with it,
  * assuming the transformations result in valid PNG data.
  */
 void /* PRIVATE */
 png_read_transform_info(png_structrp png_ptr, png_inforp info_ptr)
--- a/media/libpng/pngset.c
+++ b/media/libpng/pngset.c
@@ -1,13 +1,13 @@
 
 /* pngset.c - storage of image information into info struct
  *
- * Last changed in libpng 1.6.21 [January 15, 2016]
- * Copyright (c) 1998-2015 Glenn Randers-Pehrson
+ * Last changed in libpng 1.6.23 [June 9, 2016]
+ * Copyright (c) 1998-2016 Glenn Randers-Pehrson
  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
  *
  * This code is released under the libpng license.
  * For conditions of distribution and use, see the disclaimer
  * and license in png.h
  *
  * The functions here are used during reads to store data from the file
@@ -952,22 +952,24 @@ png_set_tRNS(png_structrp png_ptr, png_i
         *
         * 1.6.0: The above statement is incorrect; png_handle_tRNS effectively
         * relies on png_set_tRNS storing the information in png_struct
         * (otherwise it won't be there for the code in pngrtran.c).
         */
 
        png_free_data(png_ptr, info_ptr, PNG_FREE_TRNS, 0);
 
-       /* Changed from num_trans to PNG_MAX_PALETTE_LENGTH in version 1.2.1 */
-       png_ptr->trans_alpha = info_ptr->trans_alpha = png_voidcast(png_bytep,
-         png_malloc(png_ptr, PNG_MAX_PALETTE_LENGTH));
-
        if (num_trans > 0 && num_trans <= PNG_MAX_PALETTE_LENGTH)
+       {
+         /* Changed from num_trans to PNG_MAX_PALETTE_LENGTH in version 1.2.1 */
+          info_ptr->trans_alpha = png_voidcast(png_bytep,
+             png_malloc(png_ptr, PNG_MAX_PALETTE_LENGTH));
           memcpy(info_ptr->trans_alpha, trans_alpha, (png_size_t)num_trans);
+       }
+       png_ptr->trans_alpha = info_ptr->trans_alpha;
    }
 
    if (trans_color != NULL)
    {
 #ifdef PNG_WARNINGS_SUPPORTED
       if (info_ptr->bit_depth < 16)
       {
          int sample_max = (1 << info_ptr->bit_depth) - 1;
--- a/media/libpng/pngwrite.c
+++ b/media/libpng/pngwrite.c
@@ -7,19 +7,19 @@
  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
  *
  * This code is released under the libpng license.
  * For conditions of distribution and use, see the disclaimer
  * and license in png.h
  */
 
 #include "pngpriv.h"
-#if defined(PNG_SIMPLIFIED_WRITE_SUPPORTED) && defined(PNG_STDIO_SUPPORTED)
+#ifdef PNG_SIMPLIFIED_WRITE_STDIO_SUPPORTED
 #  include <errno.h>
-#endif
+#endif /* SIMPLIFIED_WRITE_STDIO */
 
 #ifdef PNG_WRITE_SUPPORTED
 
 #ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED
 /* Write out all the unknown chunks for the current given location */
 static void
 write_unknown_chunks(png_structrp png_ptr, png_const_inforp info_ptr,
    unsigned int where)
@@ -1456,17 +1456,16 @@ png_write_png(png_structrp png_ptr, png_
    png_write_end(png_ptr, info_ptr);
 
    PNG_UNUSED(params)
 }
 #endif
 
 
 #ifdef PNG_SIMPLIFIED_WRITE_SUPPORTED
-# ifdef PNG_STDIO_SUPPORTED /* currently required for png_image_write_* */
 /* Initialize the write structure - general purpose utility. */
 static int
 png_image_write_init(png_imagep image)
 {
    png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, image,
        png_safe_error, png_safe_warning);
 
    if (png_ptr != NULL)
@@ -1508,16 +1507,20 @@ typedef struct
    png_const_voidp buffer;
    png_int_32      row_stride;
    png_const_voidp colormap;
    int             convert_to_8bit;
    /* Local variables: */
    png_const_voidp first_row;
    ptrdiff_t       row_bytes;
    png_voidp       local_row;
+   /* Byte count for memory writing */
+   png_bytep        memory;
+   png_alloc_size_t memory_bytes; /* not used for STDIO */
+   png_alloc_size_t output_bytes; /* running total */
 } png_image_write_control;
 
 /* Write png_uint_16 input to a 16-bit PNG; the png_ptr has already been set to
  * do any necessary byte swapping.  The component order is defined by the
  * png_image format value.
  */
 static int
 png_write_image_16bit(png_voidp argument)
@@ -1935,19 +1938,53 @@ png_image_write_main(png_voidp argument)
    int alpha = !colormap && (format & PNG_FORMAT_FLAG_ALPHA);
    int write_16bit = linear && !colormap && (display->convert_to_8bit == 0);
 
 #   ifdef PNG_BENIGN_ERRORS_SUPPORTED
       /* Make sure we error out on any bad situation */
       png_set_benign_errors(png_ptr, 0/*error*/);
 #   endif
 
-   /* Default the 'row_stride' parameter if required. */
-   if (display->row_stride == 0)
-      display->row_stride = PNG_IMAGE_ROW_STRIDE(*image);
+   /* Default the 'row_stride' parameter if required, also check the row stride
+    * and total image size to ensure that they are within the system limits.
+    */
+   {
+      const unsigned int channels = PNG_IMAGE_PIXEL_CHANNELS(image->format);
+
+      if (image->width <= 0x7FFFFFFFU/channels) /* no overflow */
+      {
+         png_uint_32 check;
+         const png_uint_32 png_row_stride = image->width * channels;
+
+         if (display->row_stride == 0)
+            display->row_stride = (png_int_32)/*SAFE*/png_row_stride;
+
+         if (display->row_stride < 0)
+            check = -display->row_stride;
+
+         else
+            check = display->row_stride;
+
+         if (check >= png_row_stride)
+         {
+            /* Now check for overflow of the image buffer calculation; this
+             * limits the whole image size to 32 bits for API compatibility with
+             * the current, 32-bit, PNG_IMAGE_BUFFER_SIZE macro.
+             */
+            if (image->height > 0xFFFFFFFF/png_row_stride)
+               png_error(image->opaque->png_ptr, "memory image too large");
+         }
+
+         else
+            png_error(image->opaque->png_ptr, "supplied row stride too small");
+      }
+
+      else
+         png_error(image->opaque->png_ptr, "image row stride too large");
+   }
 
    /* Set the required transforms then write the rows in the correct order. */
    if ((format & PNG_FORMAT_FLAG_COLORMAP) != 0)
    {
       if (display->colormap != NULL && image->colormap_entries > 0)
       {
          png_uint_32 entries = image->colormap_entries;
 
@@ -2114,24 +2151,140 @@ png_image_write_main(png_voidp argument)
          row += row_bytes;
       }
    }
 
    png_write_end(png_ptr, info_ptr);
    return 1;
 }
 
+
+static void (PNGCBAPI
+image_memory_write)(png_structp png_ptr, png_bytep/*const*/ data,
+   png_size_t size)
+{
+   png_image_write_control *display = png_voidcast(png_image_write_control*,
+      png_ptr->io_ptr/*backdoor: png_get_io_ptr(png_ptr)*/);
+   const png_alloc_size_t ob = display->output_bytes;
+
+   /* Check for overflow; this should never happen: */
+   if (size <= ((png_alloc_size_t)-1) - ob)
+   {
+      /* I don't think libpng ever does this, but just in case: */
+      if (size > 0)
+      {
+         if (display->memory_bytes >= ob+size) /* writing */
+            memcpy(display->memory+ob, data, size);
+
+         /* Always update the size: */
+         display->output_bytes = ob+size;
+      }
+   }
+
+   else
+      png_error(png_ptr, "png_image_write_to_memory: PNG too big");
+}
+
+static void (PNGCBAPI
+image_memory_flush)(png_structp png_ptr)
+{
+   PNG_UNUSED(png_ptr)
+}
+
+static int
+png_image_write_memory(png_voidp argument)
+{
+   png_image_write_control *display = png_voidcast(png_image_write_control*,
+      argument);
+
+   /* The rest of the memory-specific init and write_main in an error protected
+    * environment.  This case needs to use callbacks for the write operations
+    * since libpng has no built in support for writing to memory.
+    */
+   png_set_write_fn(display->image->opaque->png_ptr, display/*io_ptr*/,
+         image_memory_write, image_memory_flush);
+
+   return png_image_write_main(display);
+}
+
+int PNGAPI
+png_image_write_to_memory(png_imagep image, void *memory,
+   png_alloc_size_t * PNG_RESTRICT memory_bytes, int convert_to_8bit,
+   const void *buffer, png_int_32 row_stride, const void *colormap)
+{
+   /* Write the image to the given buffer, or count the bytes if it is NULL */
+   if (image != NULL && image->version == PNG_IMAGE_VERSION)
+   {
+      if (memory_bytes != NULL && buffer != NULL)
+      {
+         /* This is to give the caller an easier error detection in the NULL
+          * case and guard against uninitialized variable problems:
+          */
+         if (memory == NULL)
+            *memory_bytes = 0;
+
+         if (png_image_write_init(image) != 0)
+         {
+            png_image_write_control display;
+            int result;
+
+            memset(&display, 0, (sizeof display));
+            display.image = image;
+            display.buffer = buffer;
+            display.row_stride = row_stride;
+            display.colormap = colormap;
+            display.convert_to_8bit = convert_to_8bit;
+            display.memory = png_voidcast(png_bytep, memory);
+            display.memory_bytes = *memory_bytes;
+            display.output_bytes = 0;
+
+            result = png_safe_execute(image, png_image_write_memory, &display);
+            png_image_free(image);
+
+            /* write_memory returns true even if we ran out of buffer. */
+            if (result)
+            {
+               /* On out-of-buffer this function returns '0' but still updates
+                * memory_bytes:
+                */
+               if (memory != NULL && display.output_bytes > *memory_bytes)
+                  result = 0;
+
+               *memory_bytes = display.output_bytes;
+            }
+
+            return result;
+         }
+
+         else
+            return 0;
+      }
+
+      else
+         return png_image_error(image,
+            "png_image_write_to_memory: invalid argument");
+   }
+
+   else if (image != NULL)
+      return png_image_error(image,
+         "png_image_write_to_memory: incorrect PNG_IMAGE_VERSION");
+
+   else
+      return 0;
+}
+
+#ifdef PNG_SIMPLIFIED_WRITE_STDIO_SUPPORTED
 int PNGAPI
 png_image_write_to_stdio(png_imagep image, FILE *file, int convert_to_8bit,
    const void *buffer, png_int_32 row_stride, const void *colormap)
 {
    /* Write the image to the given (FILE*). */
    if (image != NULL && image->version == PNG_IMAGE_VERSION)
    {
-      if (file != NULL)
+      if (file != NULL && buffer != NULL)
       {
          if (png_image_write_init(image) != 0)
          {
             png_image_write_control display;
             int result;
 
             /* This is slightly evil, but png_init_io doesn't do anything other
              * than this and we haven't changed the standard IO functions so
@@ -2171,17 +2324,17 @@ png_image_write_to_stdio(png_imagep imag
 int PNGAPI
 png_image_write_to_file(png_imagep image, const char *file_name,
    int convert_to_8bit, const void *buffer, png_int_32 row_stride,
    const void *colormap)
 {
    /* Write the image to the named file. */
    if (image != NULL && image->version == PNG_IMAGE_VERSION)
    {
-      if (file_name != NULL)
+      if (file_name != NULL && buffer != NULL)
       {
          FILE *fp = fopen(file_name, "wb");
 
          if (fp != NULL)
          {
             if (png_image_write_to_stdio(image, fp, convert_to_8bit, buffer,
                row_stride, colormap) != 0)
             {
@@ -2229,17 +2382,17 @@ png_image_write_to_file(png_imagep image
 
    else if (image != NULL)
       return png_image_error(image,
          "png_image_write_to_file: incorrect PNG_IMAGE_VERSION");
 
    else
       return 0;
 }
-# endif /* STDIO */
+#endif /* SIMPLIFIED_WRITE_STDIO */
 #endif /* SIMPLIFIED_WRITE */
 
 #ifdef PNG_WRITE_APNG_SUPPORTED
 void PNGAPI
 png_write_frame_head(png_structp png_ptr, png_infop info_ptr,
     png_bytepp row_pointers, png_uint_32 width, png_uint_32 height,
     png_uint_32 x_offset, png_uint_32 y_offset,
     png_uint_16 delay_num, png_uint_16 delay_den, png_byte dispose_op,
--- a/media/libpng/pngwutil.c
+++ b/media/libpng/pngwutil.c
@@ -1,13 +1,13 @@
 
 /* pngwutil.c - utilities to write a PNG file
  *
- * Last changed in libpng 1.6.21 [January 15, 2016]
- * Copyright (c) 1998-2002,2004,2006-2015 Glenn Randers-Pehrson
+ * Last changed in libpng 1.6.22 [May 26, 2016]
+ * Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson
  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
  *
  * This code is released under the libpng license.
  * For conditions of distribution and use, see the disclaimer
  * and license in png.h
  */
 
@@ -18,31 +18,31 @@
 #ifdef PNG_WRITE_INT_FUNCTIONS_SUPPORTED
 /* Place a 32-bit number into a buffer in PNG byte order.  We work
  * with unsigned numbers for convenience, although one supported
  * ancillary chunk uses signed (two's complement) numbers.
  */
 void PNGAPI
 png_save_uint_32(png_bytep buf, png_uint_32 i)
 {
-   buf[0] = (png_byte)(i >> 24);
-   buf[1] = (png_byte)(i >> 16);
-   buf[2] = (png_byte)(i >> 8);
-   buf[3] = (png_byte)(i     );
+   buf[0] = (png_byte)((i >> 24) & 0xffU);
+   buf[1] = (png_byte)((i >> 16) & 0xffU);
+   buf[2] = (png_byte)((i >>  8) & 0xffU);
+   buf[3] = (png_byte)( i        & 0xffU);
 }
 
 /* Place a 16-bit number into a buffer in PNG byte order.
  * The parameter is declared unsigned int, not png_uint_16,
  * just to avoid potential problems on pre-ANSI C compilers.
  */
 void PNGAPI
 png_save_uint_16(png_bytep buf, unsigned int i)
 {
-   buf[0] = (png_byte)(i >> 8);
-   buf[1] = (png_byte)(i     );
+   buf[0] = (png_byte)((i >> 8) & 0xffU);
+   buf[1] = (png_byte)( i       & 0xffU);
 }
 #endif
 
 /* Simple function to write the signature.  If we have already written
  * the magic bytes of the signature, or more likely, the PNG stream is
  * being embedded into another stream and doesn't need its own signature,
  * we should call png_set_sig_bytes() to tell libpng how many of the
  * bytes have already been written.
--- a/modules/brotli/README.mozilla
+++ b/modules/brotli/README.mozilla
@@ -9,13 +9,9 @@ Upstream code can be viewed at
 
 and cloned by
   git clone https://github.com/google/brotli
 
 The in-tree copy is updated by running
   sh update.sh
 from within the modules/brotli directory.
 
-Current version: [commit 33aa40220b96cf95ad2b9ba61dc8d7fd2f964f2c].
-
-dec/port.h was patched to fix false positive warning in Brotli and a
-corresponding change will be done upstream.
-See https://bugzilla.mozilla.org/show_bug.cgi?id=1247301
+Current version: [commit 29d31d5921b0a2b323ac24e7f7d0cdc9a3c0dd08].
--- a/modules/brotli/dec/bit_reader.c
+++ b/modules/brotli/dec/bit_reader.c
@@ -39,10 +39,10 @@ int BrotliWarmupBitReader(BrotliBitReade
       /* If we consumed all the input, we don't care about the alignment. */
       return 1;
     }
   }
   return 1;
 }
 
 #if defined(__cplusplus) || defined(c_plusplus)
-}    /* extern "C" */
+}  /* extern "C" */
 #endif
--- a/modules/brotli/dec/bit_reader.h
+++ b/modules/brotli/dec/bit_reader.h
@@ -43,37 +43,37 @@ static BROTLI_INLINE uint32_t BitMask(ui
        "Unsigned Bit Field Extract" UBFX instruction on ARM. */
     return ~((0xffffffffU) << n);
   } else {
     return kBitMask[n];
   }
 }
 
 typedef struct {
-  reg_t       val_;          /* pre-fetched bits */
-  uint32_t    bit_pos_;      /* current bit-reading position in val_ */
-  const uint8_t* next_in;    /* the byte we're reading from */
-  size_t      avail_in;
+  reg_t val_;              /* pre-fetched bits */
+  uint32_t bit_pos_;       /* current bit-reading position in val_ */
+  const uint8_t* next_in;  /* the byte we're reading from */
+  size_t avail_in;
 } BrotliBitReader;
 
 typedef struct {
-  reg_t    val_;
+  reg_t val_;
   uint32_t bit_pos_;
   const uint8_t* next_in;
-  size_t   avail_in;
+  size_t avail_in;
 } BrotliBitReaderState;
 
 /* Initializes the bitreader fields. */
-void BrotliInitBitReader(BrotliBitReader* const br);
+BROTLI_INTERNAL void BrotliInitBitReader(BrotliBitReader* const br);
 
 /* Ensures that accumulator is not empty. May consume one byte of input.
    Returns 0 if data is required but there is no input available.
-   For BROTLI_BUILD_PORTABLE this function also prepares bit reader for aligned
+   For BROTLI_ALIGNED_READ this function also prepares bit reader for aligned
    reading. */
-int BrotliWarmupBitReader(BrotliBitReader* const br);
+BROTLI_INTERNAL int BrotliWarmupBitReader(BrotliBitReader* const br);
 
 static BROTLI_INLINE void BrotliBitReaderSaveState(
     BrotliBitReader* const from, BrotliBitReaderState* to) {
   to->val_ = from->val_;
   to->bit_pos_ = from->bit_pos_;
   to->next_in = from->next_in;
   to->avail_in = from->avail_in;
 }
@@ -104,19 +104,17 @@ static BROTLI_INLINE int BrotliCheckInpu
   return br->avail_in >= num;
 }
 
 static BROTLI_INLINE uint16_t BrotliLoad16LE(const uint8_t* in) {
   if (BROTLI_LITTLE_ENDIAN) {
     return *((const uint16_t*)in);
   } else if (BROTLI_BIG_ENDIAN) {
     uint16_t value = *((const uint16_t*)in);
-    return (uint16_t)(
-        ((value & 0xFFU) << 8) |
-        ((value & 0xFF00U) >> 8));
+    return (uint16_t)(((value & 0xFFU) << 8) | ((value & 0xFF00U) >> 8));
   } else {
     return (uint16_t)(in[0] | (in[1] << 8));
   }
 }
 
 static BROTLI_INLINE uint32_t BrotliLoad32LE(const uint8_t* in) {
   if (BROTLI_LITTLE_ENDIAN) {
     return *((const uint32_t*)in);
@@ -223,19 +221,19 @@ static BROTLI_INLINE void BrotliFillBitW
 
 /* Pulls one byte of input to accumulator. */
 static BROTLI_INLINE int BrotliPullByte(BrotliBitReader* const br) {
   if (br->avail_in == 0) {
     return 0;
   }
   br->val_ >>= 8;
 #if (BROTLI_64_BITS)
-    br->val_ |= ((uint64_t)*br->next_in) << 56;
+  br->val_ |= ((uint64_t)*br->next_in) << 56;
 #else
-    br->val_ |= ((uint32_t)*br->next_in) << 24;
+  br->val_ |= ((uint32_t)*br->next_in) << 24;
 #endif
   br->bit_pos_ -= 8;
   --br->avail_in;
   ++br->next_in;
   return 1;
 }
 
 /* Returns currently available bits.
@@ -257,17 +255,17 @@ static BROTLI_INLINE uint32_t BrotliGetB
     BrotliBitReader* const br, uint32_t n_bits) {
   BrotliFillBitWindow(br, n_bits);
   return (uint32_t)BrotliGetBitsUnmasked(br) & BitMask(n_bits);
 }
 
 /* Tries to peek the specified amount of bits. Returns 0, if there is not
    enough input. */
 static BROTLI_INLINE int BrotliSafeGetBits(
-  BrotliBitReader* const br, uint32_t n_bits, uint32_t* val) {
+    BrotliBitReader* const br, uint32_t n_bits, uint32_t* val) {
   while (BrotliGetAvailableBits(br) < n_bits) {
     if (!BrotliPullByte(br)) {
       return 0;
     }
   }
   *val = (uint32_t)BrotliGetBitsUnmasked(br) & BitMask(n_bits);
   return 1;
 }
@@ -291,20 +289,18 @@ static BROTLI_INLINE void BrotliBitReade
   br->bit_pos_ += unused_bits;
 }
 
 /* Reads the specified number of bits from br and advances the bit pos.
    Precondition: accumulator MUST contain at least n_bits. */
 static BROTLI_INLINE void BrotliTakeBits(
   BrotliBitReader* const br, uint32_t n_bits, uint32_t* val) {
   *val = (uint32_t)BrotliGetBitsUnmasked(br) & BitMask(n_bits);
-#ifdef BROTLI_DECODE_DEBUG
-  printf("[BrotliReadBits]  %d %d %d val: %6x\n",
-         (int)br->avail_in, (int)br->bit_pos_, n_bits, (int)*val);
-#endif
+  BROTLI_LOG(("[BrotliReadBits]  %d %d %d val: %6x\n",
+      (int)br->avail_in, (int)br->bit_pos_, n_bits, (int)*val));
   BrotliDropBits(br, n_bits);
 }
 
 /* Reads the specified number of bits from br and advances the bit pos.
    Assumes that there is enough input to perform BrotliFillBitWindow. */
 static BROTLI_INLINE uint32_t BrotliReadBits(
     BrotliBitReader* const br, uint32_t n_bits) {
   if (BROTLI_64_BITS || (n_bits <= 16)) {
@@ -321,17 +317,17 @@ static BROTLI_INLINE uint32_t BrotliRead
     BrotliTakeBits(br, n_bits - 16, &high_val);
     return low_val | (high_val << 16);
   }
 }
 
 /* Tries to read the specified amount of bits. Returns 0, if there is not
    enough input. n_bits MUST be positive. */
 static BROTLI_INLINE int BrotliSafeReadBits(
-  BrotliBitReader* const br, uint32_t n_bits, uint32_t* val) {
+    BrotliBitReader* const br, uint32_t n_bits, uint32_t* val) {
   while (BrotliGetAvailableBits(br) < n_bits) {
     if (!BrotliPullByte(br)) {
       return 0;
     }
   }
   BrotliTakeBits(br, n_bits, val);
   return 1;
 }
@@ -376,12 +372,12 @@ static BROTLI_INLINE void BrotliCopyByte
     --num;
   }
   memcpy(dest, br->next_in, num);
   br->avail_in -= num;
   br->next_in += num;
 }
 
 #if defined(__cplusplus) || defined(c_plusplus)
-}    /* extern "C" */
+}  /* extern "C" */
 #endif
 
 #endif  /* BROTLI_DEC_BIT_READER_H_ */
--- a/modules/brotli/dec/context.h
+++ b/modules/brotli/dec/context.h
@@ -97,20 +97,20 @@
 */
 
 #ifndef BROTLI_DEC_CONTEXT_H_
 #define BROTLI_DEC_CONTEXT_H_
 
 #include "./types.h"
 
 enum ContextType {
-  CONTEXT_LSB6         = 0,
-  CONTEXT_MSB6         = 1,
-  CONTEXT_UTF8         = 2,
-  CONTEXT_SIGNED       = 3
+  CONTEXT_LSB6 = 0,
+  CONTEXT_MSB6 = 1,
+  CONTEXT_UTF8 = 2,
+  CONTEXT_SIGNED = 3
 };
 
 /* Common context lookup table for all context modes. */
 static const uint8_t kContextLookup[1792] = {
   /* CONTEXT_UTF8, last byte. */
   /* ASCII range. */
    0,  0,  0,  0,  0,  0,  0,  0,  0,  4,  4,  0,  0,  4,  0,  0,
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
--- a/modules/brotli/dec/decode.c
+++ b/modules/brotli/dec/decode.c
@@ -5,69 +5,50 @@
 */
 
 #include "./decode.h"
 
 #ifdef __ARM_NEON__
 #include <arm_neon.h>
 #endif
 
-#include <stdio.h>  /* printf (debug output) */
 #include <stdlib.h>  /* free, malloc */
 #include <string.h>  /* memcpy, memset */
 
 #include "./bit_reader.h"
 #include "./context.h"
 #include "./dictionary.h"
 #include "./huffman.h"
 #include "./port.h"
 #include "./prefix.h"
+#include "./state.h"
 #include "./transform.h"
 
 #if defined(__cplusplus) || defined(c_plusplus)
 extern "C" {
 #endif
 
-/* BROTLI_FAILURE macro unwraps to BROTLI_RESULT_ERROR in non-debug build. */
-/* In debug build it dumps file name, line and pretty function name. */
-#if defined(_MSC_VER) || !defined(BROTLI_DEBUG)
-#define BROTLI_FAILURE() BROTLI_RESULT_ERROR
-#else
-#define BROTLI_FAILURE() \
-    BrotliFailure(__FILE__, __LINE__, __PRETTY_FUNCTION__)
-static inline BrotliResult BrotliFailure(const char *f, int l, const char *fn) {
-  fprintf(stderr, "ERROR at %s:%d (%s)\n", f, l, fn);
-  fflush(stderr);
-  return BROTLI_RESULT_ERROR;
-}
-#endif
+#define BROTLI_FAILURE(CODE) (BROTLI_DUMP(), CODE)
 
-#ifdef BROTLI_DECODE_DEBUG
-#define BROTLI_LOG_UINT(name)                                    \
-  printf("[%s] %s = %lu\n", __func__, #name, (unsigned long)(name))
-#define BROTLI_LOG_ARRAY_INDEX(array_name, idx)                  \
-  printf("[%s] %s[%lu] = %lu\n", __func__, #array_name, \
-         (unsigned long)(idx), (unsigned long)array_name[idx])
-#define BROTLI_LOG(x) printf x
-#else
-#define BROTLI_LOG_UINT(name)
-#define BROTLI_LOG_ARRAY_INDEX(array_name, idx)
-#define BROTLI_LOG(x)
-#endif
+#define BROTLI_LOG_UINT(name)                                       \
+  BROTLI_LOG(("[%s] %s = %lu\n", __func__, #name, (unsigned long)(name)))
+#define BROTLI_LOG_ARRAY_INDEX(array_name, idx)                     \
+  BROTLI_LOG(("[%s] %s[%lu] = %lu\n", __func__, #array_name,        \
+         (unsigned long)(idx), (unsigned long)array_name[idx]))
 
 static const uint32_t kDefaultCodeLength = 8;
 static const uint32_t kCodeLengthRepeatCode = 16;
 static const uint32_t kNumLiteralCodes = 256;
 static const uint32_t kNumInsertAndCopyCodes = 704;
 static const uint32_t kNumBlockLengthCodes = 26;
 static const int kLiteralContextBits = 6;
 static const int kDistanceContextBits = 2;
 
-#define HUFFMAN_TABLE_BITS      8U
-#define HUFFMAN_TABLE_MASK      0xff
+#define HUFFMAN_TABLE_BITS 8U
+#define HUFFMAN_TABLE_MASK 0xff
 
 #define CODE_LENGTH_CODES 18
 static const uint8_t kCodeLengthCodeOrder[CODE_LENGTH_CODES] = {
   1, 2, 3, 4, 0, 5, 17, 6, 16, 7, 8, 9, 10, 11, 12, 13, 14, 15,
 };
 
 /* Static prefix code for the complex code length code lengths. */
 static const uint8_t kCodeLengthPrefixLength[16] = {
@@ -84,35 +65,48 @@ BrotliState* BrotliCreateState(
     brotli_alloc_func alloc_func, brotli_free_func free_func, void* opaque) {
   BrotliState* state = 0;
   if (!alloc_func && !free_func) {
     state = (BrotliState*)malloc(sizeof(BrotliState));
   } else if (alloc_func && free_func) {
     state = (BrotliState*)alloc_func(opaque, sizeof(BrotliState));
   }
   if (state == 0) {
-    (void)BROTLI_FAILURE();
+    BROTLI_DUMP();
     return 0;
   }
   BrotliStateInitWithCustomAllocators(state, alloc_func, free_func, opaque);
+  state->error_code = BROTLI_NO_ERROR;
   return state;
 }
 
 /* Deinitializes and frees BrotliState instance. */
 void BrotliDestroyState(BrotliState* state) {
   if (!state) {
     return;
   } else {
     brotli_free_func free_func = state->free_func;
     void* opaque = state->memory_manager_opaque;
     BrotliStateCleanup(state);
     free_func(opaque, state);
   }
 }
 
+/* Saves error code and converts it to BrotliResult */
+static BROTLI_NOINLINE BrotliResult SaveErrorCode(
+    BrotliState* s, BrotliErrorCode e) {
+  s->error_code = (int)e;
+  switch (e) {
+    case BROTLI_SUCCESS: return BROTLI_RESULT_SUCCESS;
+    case BROTLI_NEEDS_MORE_INPUT: return BROTLI_RESULT_NEEDS_MORE_INPUT;
+    case BROTLI_NEEDS_MORE_OUTPUT: return BROTLI_RESULT_NEEDS_MORE_OUTPUT;
+    default: return BROTLI_RESULT_ERROR;
+  }
+}
+
 /* Decodes a number in the range [9..24], by reading 1 - 7 bits.
    Precondition: bit-reader accumulator has at least 7 bits. */
 static uint32_t DecodeWindowBits(BrotliBitReader* br) {
   uint32_t n;
   BrotliTakeBits(br, 1, &n);
   if (n == 0) {
     return 16;
   }
@@ -122,184 +116,183 @@ static uint32_t DecodeWindowBits(BrotliB
   }
   BrotliTakeBits(br, 3, &n);
   if (n != 0) {
     return 8 + n;
   }
   return 17;
 }
 
-static BROTLI_INLINE void memmove16(
-    uint8_t* dst, uint8_t* src) {
+static BROTLI_INLINE void memmove16(uint8_t* dst, uint8_t* src) {
 #if defined(__ARM_NEON__)
   vst1q_u8(dst, vld1q_u8(src));
 #else
   uint32_t buffer[4];
   memcpy(buffer, src, 16);
   memcpy(dst, buffer, 16);
 #endif
 }
 
 /* Decodes a number in the range [0..255], by reading 1 - 11 bits. */
-static BROTLI_NOINLINE BrotliResult DecodeVarLenUint8(BrotliState* s,
+static BROTLI_NOINLINE BrotliErrorCode DecodeVarLenUint8(BrotliState* s,
     BrotliBitReader* br, uint32_t* value) {
   uint32_t bits;
   switch (s->substate_decode_uint8) {
     case BROTLI_STATE_DECODE_UINT8_NONE:
       if (PREDICT_FALSE(!BrotliSafeReadBits(br, 1, &bits))) {
-        return BROTLI_RESULT_NEEDS_MORE_INPUT;
+        return BROTLI_NEEDS_MORE_INPUT;
       }
       if (bits == 0) {
         *value = 0;
-        return BROTLI_RESULT_SUCCESS;
+        return BROTLI_SUCCESS;
       }
       /* No break, transit to the next state. */
 
     case BROTLI_STATE_DECODE_UINT8_SHORT:
       if (PREDICT_FALSE(!BrotliSafeReadBits(br, 3, &bits))) {
         s->substate_decode_uint8 = BROTLI_STATE_DECODE_UINT8_SHORT;
-        return BROTLI_RESULT_NEEDS_MORE_INPUT;
+        return BROTLI_NEEDS_MORE_INPUT;
       }
       if (bits == 0) {
         *value = 1;
         s->substate_decode_uint8 = BROTLI_STATE_DECODE_UINT8_NONE;
-        return BROTLI_RESULT_SUCCESS;
+        return BROTLI_SUCCESS;
       }
       /* Use output value as a temporary storage. It MUST be persisted. */
       *value = bits;
       /* No break, transit to the next state. */
 
     case BROTLI_STATE_DECODE_UINT8_LONG:
       if (PREDICT_FALSE(!BrotliSafeReadBits(br, *value, &bits))) {
         s->substate_decode_uint8 = BROTLI_STATE_DECODE_UINT8_LONG;
-        return BROTLI_RESULT_NEEDS_MORE_INPUT;
+        return BROTLI_NEEDS_MORE_INPUT;
       }
       *value = (1U << *value) + bits;
       s->substate_decode_uint8 = BROTLI_STATE_DECODE_UINT8_NONE;
-      return BROTLI_RESULT_SUCCESS;
+      return BROTLI_SUCCESS;
 
     default:
-      return BROTLI_FAILURE();
+      return BROTLI_FAILURE(BROTLI_ERROR_UNREACHABLE);
   }
 }
 
 /* Decodes a metablock length and flags by reading 2 - 31 bits. */
-static BrotliResult BROTLI_NOINLINE DecodeMetaBlockLength(BrotliState* s,
-                                                          BrotliBitReader* br) {
+static BrotliErrorCode BROTLI_NOINLINE DecodeMetaBlockLength(
+    BrotliState* s, BrotliBitReader* br) {
   uint32_t bits;
   int i;
   for (;;) {
     switch (s->substate_metablock_header) {
       case BROTLI_STATE_METABLOCK_HEADER_NONE:
         if (!BrotliSafeReadBits(br, 1, &bits)) {
-          return BROTLI_RESULT_NEEDS_MORE_INPUT;
+          return BROTLI_NEEDS_MORE_INPUT;
         }
         s->is_last_metablock = (uint8_t)bits;
         s->meta_block_remaining_len = 0;
         s->is_uncompressed = 0;
         s->is_metadata = 0;
         if (!s->is_last_metablock) {
           s->substate_metablock_header = BROTLI_STATE_METABLOCK_HEADER_NIBBLES;
           break;
         }
         s->substate_metablock_header = BROTLI_STATE_METABLOCK_HEADER_EMPTY;
         /* No break, transit to the next state. */
 
       case BROTLI_STATE_METABLOCK_HEADER_EMPTY:
         if (!BrotliSafeReadBits(br, 1, &bits)) {
-          return BROTLI_RESULT_NEEDS_MORE_INPUT;
+          return BROTLI_NEEDS_MORE_INPUT;
         }
         if (bits) {
           s->substate_metablock_header = BROTLI_STATE_METABLOCK_HEADER_NONE;
-          return BROTLI_RESULT_SUCCESS;
+          return BROTLI_SUCCESS;
         }
         s->substate_metablock_header = BROTLI_STATE_METABLOCK_HEADER_NIBBLES;
         /* No break, transit to the next state. */
 
       case BROTLI_STATE_METABLOCK_HEADER_NIBBLES:
         if (!BrotliSafeReadBits(br, 2, &bits)) {
-          return BROTLI_RESULT_NEEDS_MORE_INPUT;
+          return BROTLI_NEEDS_MORE_INPUT;
         }
         s->size_nibbles = (uint8_t)(bits + 4);
         s->loop_counter = 0;
         if (bits == 3) {
           s->is_metadata = 1;
           s->substate_metablock_header = BROTLI_STATE_METABLOCK_HEADER_RESERVED;
           break;
         }
         s->substate_metablock_header = BROTLI_STATE_METABLOCK_HEADER_SIZE;
         /* No break, transit to the next state. */
 
       case BROTLI_STATE_METABLOCK_HEADER_SIZE:
         i = s->loop_counter;
         for (; i < s->size_nibbles; ++i) {
           if (!BrotliSafeReadBits(br, 4, &bits)) {
             s->loop_counter = i;
-            return BROTLI_RESULT_NEEDS_MORE_INPUT;
+            return BROTLI_NEEDS_MORE_INPUT;
           }
           if (i + 1 == s->size_nibbles && s->size_nibbles > 4 && bits == 0) {
-            return BROTLI_FAILURE();
+            return BROTLI_FAILURE(BROTLI_ERROR_FORMAT_EXUBERANT_NIBBLE);
           }
           s->meta_block_remaining_len |= (int)(bits << (i * 4));
         }
         s->substate_metablock_header =
             BROTLI_STATE_METABLOCK_HEADER_UNCOMPRESSED;
         /* No break, transit to the next state. */
 
       case BROTLI_STATE_METABLOCK_HEADER_UNCOMPRESSED:
         if (!s->is_last_metablock) {
           if (!BrotliSafeReadBits(br, 1, &bits)) {
-            return BROTLI_RESULT_NEEDS_MORE_INPUT;
+            return BROTLI_NEEDS_MORE_INPUT;
           }
           s->is_uncompressed = (uint8_t)bits;
         }
         ++s->meta_block_remaining_len;
         s->substate_metablock_header = BROTLI_STATE_METABLOCK_HEADER_NONE;
-        return BROTLI_RESULT_SUCCESS;
+        return BROTLI_SUCCESS;
 
       case BROTLI_STATE_METABLOCK_HEADER_RESERVED:
         if (!BrotliSafeReadBits(br, 1, &bits)) {
-          return BROTLI_RESULT_NEEDS_MORE_INPUT;
+          return BROTLI_NEEDS_MORE_INPUT;
         }
         if (bits != 0) {
-          return BROTLI_FAILURE();
+          return BROTLI_FAILURE(BROTLI_ERROR_FORMAT_RESERVED);
         }
         s->substate_metablock_header = BROTLI_STATE_METABLOCK_HEADER_BYTES;
         /* No break, transit to the next state. */
 
       case BROTLI_STATE_METABLOCK_HEADER_BYTES:
         if (!BrotliSafeReadBits(br, 2, &bits)) {
-          return BROTLI_RESULT_NEEDS_MORE_INPUT;
+          return BROTLI_NEEDS_MORE_INPUT;
         }
         if (bits == 0) {
           s->substate_metablock_header = BROTLI_STATE_METABLOCK_HEADER_NONE;
-          return BROTLI_RESULT_SUCCESS;
+          return BROTLI_SUCCESS;
         }
         s->size_nibbles = (uint8_t)bits;
         s->substate_metablock_header = BROTLI_STATE_METABLOCK_HEADER_METADATA;
         /* No break, transit to the next state. */
 
       case BROTLI_STATE_METABLOCK_HEADER_METADATA:
         i = s->loop_counter;
         for (; i < s->size_nibbles; ++i) {
           if (!BrotliSafeReadBits(br, 8, &bits)) {
             s->loop_counter = i;
-            return BROTLI_RESULT_NEEDS_MORE_INPUT;
+            return BROTLI_NEEDS_MORE_INPUT;
           }
           if (i + 1 == s->size_nibbles && s->size_nibbles > 1 && bits == 0) {
-            return BROTLI_FAILURE();
+            return BROTLI_FAILURE(BROTLI_ERROR_FORMAT_EXUBERANT_META_NIBBLE);
           }
           s->meta_block_remaining_len |= (int)(bits << (i * 8));
         }
         ++s->meta_block_remaining_len;
         s->substate_metablock_header = BROTLI_STATE_METABLOCK_HEADER_NONE;
-        return BROTLI_RESULT_SUCCESS;
+        return BROTLI_SUCCESS;
 
       default:
-        return BROTLI_FAILURE();
+        return BROTLI_FAILURE(BROTLI_ERROR_UNREACHABLE);
     }
   }
 }
 
 /* Decodes the Huffman code.
    This method doesn't read data from the bit reader, BUT drops the amount of
    bits that correspond to the decoded symbol.
    bits MUST contain at least 15 (BROTLI_HUFFMAN_MAX_CODE_LENGTH) valid bits. */
@@ -372,17 +365,16 @@ static BROTLI_INLINE int SafeReadSymbol(
   uint32_t val;
   if (PREDICT_TRUE(BrotliSafeGetBits(br, 15, &val))) {
     *result = DecodeSymbol(val, table, br);
     return 1;
   }
   return SafeDecodeSymbol(table, br, result);
 }
 
-
 /* Makes a look-up in first level Huffman table. Peeks 8 bits. */
 static BROTLI_INLINE void PreloadSymbol(int safe,
                                         const HuffmanCode* table,
                                         BrotliBitReader* br,
                                         uint32_t* bits,
                                         uint32_t* value) {
   if (safe) {
     return;
@@ -422,48 +414,48 @@ static BROTLI_INLINE uint32_t Log2Floor(
   }
   return result;
 }
 
 /* Reads (s->symbol + 1) symbols.
    Totally 1..4 symbols are read, 1..10 bits each.
    The list of symbols MUST NOT contain duplicates.
  */
-static BrotliResult ReadSimpleHuffmanSymbols(uint32_t alphabet_size,
-                                             BrotliState* s) {
+static BrotliErrorCode ReadSimpleHuffmanSymbols(uint32_t alphabet_size,
+                                                BrotliState* s) {
   /* max_bits == 1..10; symbol == 0..3; 1..40 bits will be read. */
   BrotliBitReader* br = &s->br;
   uint32_t max_bits = Log2Floor(alphabet_size - 1);
   uint32_t i = s->sub_loop_counter;
   uint32_t num_symbols = s->symbol;
   while (i <= num_symbols) {
     uint32_t v;
     if (PREDICT_FALSE(!BrotliSafeReadBits(br, max_bits, &v))) {
       s->sub_loop_counter = i;
       s->substate_huffman = BROTLI_STATE_HUFFMAN_SIMPLE_READ;
-      return BROTLI_RESULT_NEEDS_MORE_INPUT;
+      return BROTLI_NEEDS_MORE_INPUT;
     }
     if (v >= alphabet_size) {
-      return BROTLI_FAILURE();
+      return BROTLI_FAILURE(BROTLI_ERROR_FORMAT_SIMPLE_HUFFMAN_ALPHABET);
     }
     s->symbols_lists_array[i] = (uint16_t)v;
     BROTLI_LOG_UINT(s->symbols_lists_array[i]);
     ++i;
   }
 
   for (i = 0; i < num_symbols; ++i) {
     uint32_t k = i + 1;
     for (; k <= num_symbols; ++k) {
       if (s->symbols_lists_array[i] == s->symbols_lists_array[k]) {
-        return BROTLI_FAILURE();
+        return BROTLI_FAILURE(BROTLI_ERROR_FORMAT_SIMPLE_HUFFMAN_SAME);
       }
     }
   }
 
-  return BROTLI_RESULT_SUCCESS;
+  return BROTLI_SUCCESS;
 }
 
 /* Process single decoded symbol code length:
     A) reset the repeat variable
     B) remember code length (if it is not 0)
     C) extend corredponding index-chain
     D) reduce the huffman space
     E) update the histogram
@@ -474,18 +466,17 @@ static BROTLI_INLINE void ProcessSingleC
     uint16_t* code_length_histo, int* next_symbol) {
   *repeat = 0;
   if (code_len != 0) { /* code_len == 1..15 */
     symbol_lists[next_symbol[code_len]] = (uint16_t)(*symbol);
     next_symbol[code_len] = (int)(*symbol);
     *prev_code_len = code_len;
     *space -= 32768U >> code_len;
     code_length_histo[code_len]++;
-    BROTLI_LOG(("[ReadHuffmanCode] code_length[%d] = %d\n",
-                *symbol, code_len));
+    BROTLI_LOG(("[ReadHuffmanCode] code_length[%d] = %d\n", *symbol, code_len));
   }
   (*symbol)++;
 }
 
 /* Process repeated symbol code length.
     A) Check if it is the extension of previous repeat sequence; if the decoded
        value is not kCodeLengthRepeatCode, then it is a new symbol-skip
     B) Update repeat variable
@@ -511,87 +502,87 @@ static BROTLI_INLINE void ProcessRepeate
   old_repeat = *repeat;
   if (*repeat > 0) {
     *repeat -= 2;
     *repeat <<= code_len - 14U;
   }
   *repeat += repeat_delta + 3U;
   repeat_delta = *repeat - old_repeat;
   if (*symbol + repeat_delta > alphabet_size) {
-    (void)BROTLI_FAILURE();
+    BROTLI_DUMP();
     *symbol = alphabet_size;
     *space = 0xFFFFF;
     return;
   }
   BROTLI_LOG(("[ReadHuffmanCode] code_length[%d..%d] = %d\n",
               *symbol, *symbol + repeat_delta - 1, *repeat_code_len));
   if (*repeat_code_len != 0) {
     unsigned last = *symbol + repeat_delta;
     int next = next_symbol[*repeat_code_len];
     do {
       symbol_lists[next] = (uint16_t)*symbol;
       next = (int)*symbol;
     } while (++(*symbol) != last);
     next_symbol[*repeat_code_len] = next;
     *space -= repeat_delta << (15 - *repeat_code_len);
-    code_length_histo[*repeat_code_len] = (uint16_t)
-        (code_length_histo[*repeat_code_len] + repeat_delta);
+    code_length_histo[*repeat_code_len] =
+        (uint16_t)(code_length_histo[*repeat_code_len] + repeat_delta);
   } else {
     *symbol += repeat_delta;
   }
 }
 
 /* Reads and decodes symbol codelengths. */
-static BrotliResult ReadSymbolCodeLengths(
+static BrotliErrorCode ReadSymbolCodeLengths(
     uint32_t alphabet_size, BrotliState* s) {
   BrotliBitReader* br = &s->br;
   uint32_t symbol = s->symbol;
   uint32_t repeat = s->repeat;
   uint32_t space = s->space;
   uint32_t prev_code_len = s->prev_code_len;
   uint32_t repeat_code_len = s->repeat_code_len;
   uint16_t* symbol_lists = s->symbol_lists;
   uint16_t* code_length_histo = s->code_length_histo;
   int* next_symbol = s->next_symbol;
   if (!BrotliWarmupBitReader(br)) {
-    return BROTLI_RESULT_NEEDS_MORE_INPUT;
+    return BROTLI_NEEDS_MORE_INPUT;
   }
   while (symbol < alphabet_size && space > 0) {
     const HuffmanCode* p = s->table;
     uint32_t code_len;
     if (!BrotliCheckInputAmount(br, BROTLI_SHORT_FILL_BIT_WINDOW_READ)) {
       s->symbol = symbol;
       s->repeat = repeat;
       s->prev_code_len = prev_code_len;
       s->repeat_code_len = repeat_code_len;
       s->space = space;
-      return BROTLI_RESULT_NEEDS_MORE_INPUT;
+      return BROTLI_NEEDS_MORE_INPUT;
     }
     BrotliFillBitWindow16(br);
     p += BrotliGetBitsUnmasked(br) &
         BitMask(BROTLI_HUFFMAN_MAX_CODE_LENGTH_CODE_LENGTH);
-    BrotliDropBits(br, p->bits); /* Use 1..5 bits */
-    code_len = p->value; /* code_len == 0..17 */
+    BrotliDropBits(br, p->bits);  /* Use 1..5 bits */
+    code_len = p->value;  /* code_len == 0..17 */
     if (code_len < kCodeLengthRepeatCode) {
       ProcessSingleCodeLength(code_len, &symbol, &repeat, &space,
           &prev_code_len, symbol_lists, code_length_histo, next_symbol);
     } else { /* code_len == 16..17, extra_bits == 2..3 */
       uint32_t repeat_delta =
           (uint32_t)BrotliGetBitsUnmasked(br) & BitMask(code_len - 14U);
       BrotliDropBits(br, code_len - 14U);
       ProcessRepeatedCodeLength(code_len, repeat_delta, alphabet_size,
           &symbol, &repeat, &space, &prev_code_len, &repeat_code_len,
           symbol_lists, code_length_histo, next_symbol);
     }
   }
   s->space = space;
-  return BROTLI_RESULT_SUCCESS;
+  return BROTLI_SUCCESS;
 }
 
-static BrotliResult SafeReadSymbolCodeLengths(
+static BrotliErrorCode SafeReadSymbolCodeLengths(
     uint32_t alphabet_size, BrotliState* s) {
   BrotliBitReader* br = &s->br;
   while (s->symbol < alphabet_size && s->space > 0) {
     const HuffmanCode* p = s->table;
     uint32_t code_len;
     uint32_t bits = 0;
     uint32_t available_bits = BrotliGetAvailableBits(br);
     if (available_bits != 0) {
@@ -614,25 +605,25 @@ static BrotliResult SafeReadSymbolCodeLe
           &s->symbol, &s->repeat, &s->space, &s->prev_code_len,
           &s->repeat_code_len, s->symbol_lists, s->code_length_histo,
           s->next_symbol);
     }
     continue;
 
 pullMoreInput:
     if (!BrotliPullByte(br)) {
-      return BROTLI_RESULT_NEEDS_MORE_INPUT;
+      return BROTLI_NEEDS_MORE_INPUT;
     }
   }
-  return BROTLI_RESULT_SUCCESS;
+  return BROTLI_SUCCESS;
 }
 
 /* Reads and decodes 15..18 codes using static prefix code.
    Each code is 2..4 bits long. In total 30..72 bits are used. */
-static BrotliResult ReadCodeLengthCodeLengths(BrotliState* s) {
+static BrotliErrorCode ReadCodeLengthCodeLengths(BrotliState* s) {
   BrotliBitReader* br = &s->br;
   uint32_t num_codes = s->repeat;
   unsigned space = s->space;
   uint32_t i = s->sub_loop_counter;
   for (; i < CODE_LENGTH_CODES; ++i) {
     const uint8_t code_len_idx = kCodeLengthCodeOrder[i];
     uint32_t ix;
     uint32_t v;
@@ -643,17 +634,17 @@ static BrotliResult ReadCodeLengthCodeLe
       } else {
         ix = 0;
       }
       if (kCodeLengthPrefixLength[ix] > available_bits) {
         s->sub_loop_counter = i;
         s->repeat = num_codes;
         s->space = space;
         s->substate_huffman = BROTLI_STATE_HUFFMAN_COMPLEX;
-        return BROTLI_RESULT_NEEDS_MORE_INPUT;
+        return BROTLI_NEEDS_MORE_INPUT;
       }
     }
     v = kCodeLengthPrefixValue[ix];
     BrotliDropBits(br, kCodeLengthPrefixLength[ix]);
     s->code_length_code_lengths[code_len_idx] = (uint8_t)v;
     BROTLI_LOG_ARRAY_INDEX(s->code_length_code_lengths, code_len_idx);
     if (v != 0) {
       space = space - (32U >> v);
@@ -661,45 +652,45 @@ static BrotliResult ReadCodeLengthCodeLe
       ++s->code_length_histo[v];
       if (space - 1U >= 32U) {
         /* space is 0 or wrapped around */
         break;
       }
     }
   }
   if (!(num_codes == 1 || space == 0)) {
-    return BROTLI_FAILURE();
+    return BROTLI_FAILURE(BROTLI_ERROR_FORMAT_CL_SPACE);
   }
-  return BROTLI_RESULT_SUCCESS;
+  return BROTLI_SUCCESS;
 }
 
 /* Decodes the Huffman tables.
    There are 2 scenarios:
     A) Huffman code contains only few symbols (1..4). Those symbols are read
        directly; their code lengths are defined by the number of symbols.
        For this scenario 4 - 45 bits will be read.
 
     B) 2-phase decoding:
     B.1) Small Huffman table is decoded; it is specified with code lengths
          encoded with predefined entropy code. 32 - 74 bits are used.
     B.2) Decoded table is used to decode code lengths of symbols in resulting
          Huffman table. In worst case 3520 bits are read.
 */
-static BrotliResult ReadHuffmanCode(uint32_t alphabet_size,
-                                    HuffmanCode* table,
-                                    uint32_t* opt_table_size,
-                                    BrotliState* s) {
+static BrotliErrorCode ReadHuffmanCode(uint32_t alphabet_size,
+                                       HuffmanCode* table,
+                                       uint32_t* opt_table_size,
+                                       BrotliState* s) {
   BrotliBitReader* br = &s->br;
   /* Unnecessary masking, but might be good for safety. */
   alphabet_size &= 0x3ff;
   /* State machine */
   switch (s->substate_huffman) {
     case BROTLI_STATE_HUFFMAN_NONE:
       if (!BrotliSafeReadBits(br, 2, &s->sub_loop_counter)) {
-        return BROTLI_RESULT_NEEDS_MORE_INPUT;
+        return BROTLI_NEEDS_MORE_INPUT;
       }
       BROTLI_LOG_UINT(s->sub_loop_counter);
       /* The value is used as follows:
          1 for simple code;
          0 for no skipping, 2 skips 2 code lengths, 3 skips 3 code lengths */
       if (s->sub_loop_counter != 1) {
         s->space = 32;
         s->repeat = 0; /* num_codes */
@@ -711,52 +702,52 @@ static BrotliResult ReadHuffmanCode(uint
         goto Complex;
       }
       /* No break, transit to the next state. */
 
     case BROTLI_STATE_HUFFMAN_SIMPLE_SIZE:
       /* Read symbols, codes & code lengths directly. */
       if (!BrotliSafeReadBits(br, 2, &s->symbol)) { /* num_symbols */
         s->substate_huffman = BROTLI_STATE_HUFFMAN_SIMPLE_SIZE;
-        return BROTLI_RESULT_NEEDS_MORE_INPUT;
+        return BROTLI_NEEDS_MORE_INPUT;
       }
       s->sub_loop_counter = 0;
       /* No break, transit to the next state. */
     case BROTLI_STATE_HUFFMAN_SIMPLE_READ: {
-      BrotliResult result = ReadSimpleHuffmanSymbols(alphabet_size, s);
-      if (result != BROTLI_RESULT_SUCCESS) {
+      BrotliErrorCode result = ReadSimpleHuffmanSymbols(alphabet_size, s);
+      if (result != BROTLI_SUCCESS) {
         return result;
       }
       /* No break, transit to the next state. */
     }
     case BROTLI_STATE_HUFFMAN_SIMPLE_BUILD: {
       uint32_t table_size;
       if (s->symbol == 3) {
         uint32_t bits;
         if (!BrotliSafeReadBits(br, 1, &bits)) {
           s->substate_huffman = BROTLI_STATE_HUFFMAN_SIMPLE_BUILD;
-          return BROTLI_RESULT_NEEDS_MORE_INPUT;
+          return BROTLI_NEEDS_MORE_INPUT;
         }
         s->symbol += bits;
       }
       BROTLI_LOG_UINT(s->symbol);
       table_size = BrotliBuildSimpleHuffmanTable(
           table, HUFFMAN_TABLE_BITS, s->symbols_lists_array, s->symbol);
       if (opt_table_size) {
         *opt_table_size = table_size;
       }
       s->substate_huffman = BROTLI_STATE_HUFFMAN_NONE;
-      return BROTLI_RESULT_SUCCESS;
+      return BROTLI_SUCCESS;
     }
 
 Complex: /* Decode Huffman-coded code lengths. */
     case BROTLI_STATE_HUFFMAN_COMPLEX: {
       uint32_t i;
-      BrotliResult result = ReadCodeLengthCodeLengths(s);
-      if (result != BROTLI_RESULT_SUCCESS) {
+      BrotliErrorCode result = ReadCodeLengthCodeLengths(s);
+      if (result != BROTLI_SUCCESS) {
         return result;
       }
       BrotliBuildCodeLengthsHuffmanTable(s->table,
                                          s->code_length_code_lengths,
                                          s->code_length_histo);
       memset(&s->code_length_histo[0], 0, sizeof(s->code_length_histo));
       for (i = 0; i <= BROTLI_HUFFMAN_MAX_CODE_LENGTH; ++i) {
         s->next_symbol[i] = (int)i - (BROTLI_HUFFMAN_MAX_CODE_LENGTH + 1);
@@ -768,39 +759,39 @@ Complex: /* Decode Huffman-coded code le
       s->repeat = 0;
       s->repeat_code_len = 0;
       s->space = 32768;
       s->substate_huffman = BROTLI_STATE_HUFFMAN_LENGTH_SYMBOLS;
       /* No break, transit to the next state. */
     }
     case BROTLI_STATE_HUFFMAN_LENGTH_SYMBOLS: {
       uint32_t table_size;
-      BrotliResult result = ReadSymbolCodeLengths(alphabet_size, s);
-      if (result == BROTLI_RESULT_NEEDS_MORE_INPUT) {
+      BrotliErrorCode result = ReadSymbolCodeLengths(alphabet_size, s);
+      if (result == BROTLI_NEEDS_MORE_INPUT) {
         result = SafeReadSymbolCodeLengths(alphabet_size, s);
       }
-      if (result != BROTLI_RESULT_SUCCESS) {
+      if (result != BROTLI_SUCCESS) {
         return result;
       }
 
       if (s->space != 0) {
         BROTLI_LOG(("[ReadHuffmanCode] space = %d\n", s->space));
-        return BROTLI_FAILURE();
+        return BROTLI_FAILURE(BROTLI_ERROR_FORMAT_HUFFMAN_SPACE);
       }
-      table_size = BrotliBuildHuffmanTable(table, HUFFMAN_TABLE_BITS,
-          s->symbol_lists, s->code_length_histo);
+      table_size = BrotliBuildHuffmanTable(
+          table, HUFFMAN_TABLE_BITS, s->symbol_lists, s->code_length_histo);
       if (opt_table_size) {
         *opt_table_size = table_size;
       }
       s->substate_huffman = BROTLI_STATE_HUFFMAN_NONE;
-      return BROTLI_RESULT_SUCCESS;
+      return BROTLI_SUCCESS;
     }
 
     default:
-      return BROTLI_FAILURE();
+      return BROTLI_FAILURE(BROTLI_ERROR_UNREACHABLE);
   }
 }
 
 /* Decodes a block length by reading 3..39 bits. */
 static BROTLI_INLINE uint32_t ReadBlockLength(const HuffmanCode* table,
                                               BrotliBitReader* br) {
   uint32_t code;
   uint32_t nbits;
@@ -852,17 +843,17 @@ static BROTLI_INLINE int SafeReadBlockLe
    Most of input values are 0 and 1. To reduce number of branches, we replace
    inner for loop with do-while.
  */
 static BROTLI_NOINLINE void InverseMoveToFrontTransform(uint8_t* v,
     uint32_t v_len, BrotliState* state) {
   /* Reinitialize elements that could have been changed. */
   uint32_t i = 4;
   uint32_t upper_bound = state->mtf_upper_bound;
-  uint8_t* mtf = state->mtf;
+  uint8_t* mtf = &state->mtf[4];  /* Make mtf[-1] addressable. */
   /* Load endian-aware constant. */
   const uint8_t b0123[4] = {0, 1, 2, 3};
   uint32_t pattern;
   memcpy(&pattern, &b0123, 4);
 
   /* Initialize list using 4 consequent values pattern. */
   *(uint32_t*)mtf = pattern;
   do {
@@ -873,122 +864,121 @@ static BROTLI_NOINLINE void InverseMoveT
 
   /* Transform the input. */
   upper_bound = 0;
   for (i = 0; i < v_len; ++i) {
     int index = v[i];
     uint8_t value = mtf[index];
     upper_bound |= v[i];
     v[i] = value;
+    mtf[-1] = value;
     do {
       index--;
       mtf[index + 1] = mtf[index];
-    } while (index > 0);
-    mtf[0] = value;
+    } while (index >= 0);
   }
   /* Remember amount of elements to be reinitialized. */
   state->mtf_upper_bound = upper_bound;
 }
 
-
 /* Decodes a series of Huffman table using ReadHuffmanCode function. */
-static BrotliResult HuffmanTreeGroupDecode(HuffmanTreeGroup* group,
-                                           BrotliState* s) {
+static BrotliErrorCode HuffmanTreeGroupDecode(HuffmanTreeGroup* group,
+                                              BrotliState* s) {
   if (s->substate_tree_group != BROTLI_STATE_TREE_GROUP_LOOP) {
     s->next = group->codes;
     s->htree_index = 0;
     s->substate_tree_group = BROTLI_STATE_TREE_GROUP_LOOP;
   }
   while (s->htree_index < group->num_htrees) {
     uint32_t table_size;
-    BrotliResult result =
+    BrotliErrorCode result =
         ReadHuffmanCode(group->alphabet_size, s->next, &table_size, s);
-    if (result != BROTLI_RESULT_SUCCESS) return result;
+    if (result != BROTLI_SUCCESS) return result;
     group->htrees[s->htree_index] = s->next;
     s->next += table_size;
     ++s->htree_index;
   }
   s->substate_tree_group = BROTLI_STATE_TREE_GROUP_NONE;
-  return BROTLI_RESULT_SUCCESS;
+  return BROTLI_SUCCESS;
 }
 
 /* Decodes a context map.
    Decoding is done in 4 phases:
     1) Read auxiliary information (6..16 bits) and allocate memory.
        In case of trivial context map, decoding is finished at this phase.
     2) Decode Huffman table using ReadHuffmanCode function.
        This table will be used for reading context map items.
     3) Read context map items; "0" values could be run-length encoded.
     4) Optionally, apply InverseMoveToFront transform to the resulting map.
  */
-static BrotliResult DecodeContextMap(uint32_t context_map_size,
-                                     uint32_t* num_htrees,
-                                     uint8_t** context_map_arg,
-                                     BrotliState* s) {
+static BrotliErrorCode DecodeContextMap(uint32_t context_map_size,
+                                        uint32_t* num_htrees,
+                                        uint8_t** context_map_arg,
+                                        BrotliState* s) {
   BrotliBitReader* br = &s->br;
-  BrotliResult result = BROTLI_RESULT_SUCCESS;
+  BrotliErrorCode result = BROTLI_SUCCESS;
 
-  switch((int)s->substate_context_map) {
+  switch ((int)s->substate_context_map) {
     case BROTLI_STATE_CONTEXT_MAP_NONE:
       result = DecodeVarLenUint8(s, br, num_htrees);
-      if (result != BROTLI_RESULT_SUCCESS) {
+      if (result != BROTLI_SUCCESS) {
         return result;
       }
       (*num_htrees)++;
       s->context_index = 0;
       BROTLI_LOG_UINT(context_map_size);
       BROTLI_LOG_UINT(*num_htrees);
       *context_map_arg = (uint8_t*)BROTLI_ALLOC(s, (size_t)context_map_size);
       if (*context_map_arg == 0) {
-        return BROTLI_FAILURE();
+        return BROTLI_FAILURE(BROTLI_ERROR_ALLOC_CONTEXT_MAP);
       }
       if (*num_htrees <= 1) {
         memset(*context_map_arg, 0, (size_t)context_map_size);
-        return BROTLI_RESULT_SUCCESS;
+        return BROTLI_SUCCESS;
       }
       s->substate_context_map = BROTLI_STATE_CONTEXT_MAP_READ_PREFIX;
       /* No break, continue to next state. */
     case BROTLI_STATE_CONTEXT_MAP_READ_PREFIX: {
       uint32_t bits;
       /* In next stage ReadHuffmanCode uses at least 4 bits, so it is safe
          to peek 4 bits ahead. */
       if (!BrotliSafeGetBits(br, 5, &bits)) {
-        return BROTLI_RESULT_NEEDS_MORE_INPUT;
+        return BROTLI_NEEDS_MORE_INPUT;
       }
       if ((bits & 1) != 0) { /* Use RLE for zeroes. */
         s->max_run_length_prefix = (bits >> 1) + 1;
         BrotliDropBits(br, 5);
       } else {
         s->max_run_length_prefix = 0;
         BrotliDropBits(br, 1);
       }
       BROTLI_LOG_UINT(s->max_run_length_prefix);
       s->substate_context_map = BROTLI_STATE_CONTEXT_MAP_HUFFMAN;
       /* No break, continue to next state. */
     }
     case BROTLI_STATE_CONTEXT_MAP_HUFFMAN:
       result = ReadHuffmanCode(*num_htrees + s->max_run_length_prefix,
                                s->context_map_table, NULL, s);
-      if (result != BROTLI_RESULT_SUCCESS) return result;
+      if (result != BROTLI_SUCCESS) return result;
       s->code = 0xFFFF;
       s->substate_context_map = BROTLI_STATE_CONTEXT_MAP_DECODE;
       /* No break, continue to next state. */
     case BROTLI_STATE_CONTEXT_MAP_DECODE: {
       uint32_t context_index = s->context_index;
       uint32_t max_run_length_prefix = s->max_run_length_prefix;
       uint8_t* context_map = *context_map_arg;
       uint32_t code = s->code;
       if (code != 0xFFFF) {
         goto rleCode;
       }
       while (context_index < context_map_size) {
         if (!SafeReadSymbol(s->context_map_table, br, &code)) {
           s->code = 0xFFFF;
           s->context_index = context_index;
-          return BROTLI_RESULT_NEEDS_MORE_INPUT;
+          return BROTLI_NEEDS_MORE_INPUT;
         }
         BROTLI_LOG_UINT(code);
 
         if (code == 0) {
           context_map[context_index++] = 0;
           continue;
         }
         if (code > max_run_length_prefix) {
@@ -997,44 +987,44 @@ static BrotliResult DecodeContextMap(uin
           continue;
         }
 rleCode:
         {
           uint32_t reps;
           if (!BrotliSafeReadBits(br, code, &reps)) {
             s->code = code;
             s->context_index = context_index;
-            return BROTLI_RESULT_NEEDS_MORE_INPUT;
+            return BROTLI_NEEDS_MORE_INPUT;
           }
           reps += 1U << code;
           BROTLI_LOG_UINT(reps);
           if (context_index + reps > context_map_size) {
-            return BROTLI_FAILURE();
+            return BROTLI_FAILURE(BROTLI_ERROR_FORMAT_CONTEXT_MAP_REPEAT);
           }
           do {
             context_map[context_index++] = 0;
           } while (--reps);
         }
       }
       /* No break, continue to next state. */
     }
     case BROTLI_STATE_CONTEXT_MAP_TRANSFORM: {
       uint32_t bits;
       if (!BrotliSafeReadBits(br, 1, &bits)) {
         s->substate_context_map = BROTLI_STATE_CONTEXT_MAP_TRANSFORM;
-        return BROTLI_RESULT_NEEDS_MORE_INPUT;
+        return BROTLI_NEEDS_MORE_INPUT;
       }
       if (bits != 0) {
         InverseMoveToFrontTransform(*context_map_arg, context_map_size, s);
       }
       s->substate_context_map = BROTLI_STATE_CONTEXT_MAP_NONE;
-      return BROTLI_RESULT_SUCCESS;
+      return BROTLI_SUCCESS;
     }
     default:
-      return BROTLI_FAILURE();
+      return BROTLI_FAILURE(BROTLI_ERROR_UNREACHABLE);
   }
 }
 
 /* Decodes a command or literal and updates block type ringbuffer.
    Reads 3..54 bits. */
 static BROTLI_INLINE int DecodeBlockTypeAndLength(int safe,
     BrotliState* s, int tree_type) {
   uint32_t max_block_type = s->num_block_types[tree_type];
@@ -1071,32 +1061,55 @@ static BROTLI_INLINE int DecodeBlockType
   if (block_type >= max_block_type) {
     block_type -= max_block_type;
   }
   ringbuffer[0] = ringbuffer[1];
   ringbuffer[1] = block_type;
   return 1;
 }
 
+static BROTLI_INLINE void DetectTrivialLiteralBlockTypes(BrotliState* s) {
+  size_t i;
+  for (i = 0; i < 8; ++i) s->trivial_literal_contexts[i] = 0;
+  for (i = 0; i < s->num_block_types[0]; i++) {
+    size_t offset = i << kLiteralContextBits;
+    size_t error = 0;
+    size_t sample = s->context_map[offset];
+    size_t j;
+    for (j = 0; j < (1u << kLiteralContextBits);) {
+      BROTLI_REPEAT(4, error |= s->context_map[offset + j++] ^ sample;)
+    }
+    if (error == 0) {
+      s->trivial_literal_contexts[i >> 5] |= 1u << (i & 31);
+    }
+  }
+}
+
+static BROTLI_INLINE void PrepareLiteralDecoding(BrotliState* s) {
+  uint8_t context_mode;
+  size_t trivial;
+  uint32_t block_type = s->block_type_rb[1];
+  uint32_t context_offset = block_type << kLiteralContextBits;
+  s->context_map_slice = s->context_map + context_offset;
+  trivial = s->trivial_literal_contexts[block_type >> 5];
+  s->trivial_literal_context = (trivial >> (block_type & 31)) & 1;
+  s->literal_htree = s->literal_hgroup.htrees[s->context_map_slice[0]];
+  context_mode = s->context_modes[block_type];
+  s->context_lookup1 = &kContextLookup[kContextLookupOffsets[context_mode]];
+  s->context_lookup2 = &kContextLookup[kContextLookupOffsets[context_mode + 1]];
+}
+
 /* Decodes the block type and updates the state for literal context.
    Reads 3..54 bits. */
 static BROTLI_INLINE int DecodeLiteralBlockSwitchInternal(int safe,
     BrotliState* s) {
-  uint8_t context_mode;
-  uint32_t context_offset;
   if (!DecodeBlockTypeAndLength(safe, s, 0)) {
     return 0;
   }
-  context_offset = s->block_type_rb[1] << kLiteralContextBits;
-  s->context_map_slice = s->context_map + context_offset;
-  s->literal_htree_index = s->context_map_slice[0];
-  s->literal_htree = s->literal_hgroup.htrees[s->literal_htree_index];
-  context_mode = s->context_modes[s->block_type_rb[1]];
-  s->context_lookup1 = &kContextLookup[kContextLookupOffsets[context_mode]];
-  s->context_lookup2 = &kContextLookup[kContextLookupOffsets[context_mode + 1]];
+  PrepareLiteralDecoding(s);
   return 1;
 }
 
 static void BROTLI_NOINLINE DecodeLiteralBlockSwitch(BrotliState* s) {
   DecodeLiteralBlockSwitchInternal(0, s);
 }
 
 static int BROTLI_NOINLINE SafeDecodeLiteralBlockSwitch(BrotliState* s) {
@@ -1137,43 +1150,47 @@ static BROTLI_INLINE int DecodeDistanceB
 static void BROTLI_NOINLINE DecodeDistanceBlockSwitch(BrotliState* s) {
   DecodeDistanceBlockSwitchInternal(0, s);
 }
 
 static int BROTLI_NOINLINE SafeDecodeDistanceBlockSwitch(BrotliState* s) {
   return DecodeDistanceBlockSwitchInternal(1, s);
 }
 
-static BrotliResult WriteRingBuffer(size_t* available_out, uint8_t** next_out,
-    size_t* total_out, BrotliState* s) {
-  size_t pos = (s->pos > s->ringbuffer_size) ?
-      (size_t)s->ringbuffer_size : (size_t)(s->pos);
-  uint8_t* start = s->ringbuffer
-      + (s->partial_pos_out & (size_t)s->ringbuffer_mask);
-  size_t partial_pos_rb =
-      (s->rb_roundtrips * (size_t)s->ringbuffer_size) + pos;
+static BrotliErrorCode BROTLI_NOINLINE WriteRingBuffer(size_t* available_out,
+    uint8_t** next_out, size_t* total_out, BrotliState* s) {
+  size_t pos = (s->pos > s->ringbuffer_size) ? (size_t)s->ringbuffer_size
+                                             : (size_t)(s->pos);
+  uint8_t* start =
+      s->ringbuffer + (s->partial_pos_out & (size_t)s->ringbuffer_mask);
+  size_t partial_pos_rb = (s->rb_roundtrips * (size_t)s->ringbuffer_size) + pos;
   size_t to_write = (partial_pos_rb - s->partial_pos_out);
   size_t num_written = *available_out;
   if (num_written > to_write) {
     num_written = to_write;
   }
   if (s->meta_block_remaining_len < 0) {
-    return BROTLI_FAILURE();
+    return BROTLI_FAILURE(BROTLI_ERROR_FORMAT_BLOCK_LENGTH_1);
   }
   memcpy(*next_out, start, num_written);
   *next_out += num_written;
   *available_out -= num_written;
   BROTLI_LOG_UINT(to_write);
   BROTLI_LOG_UINT(num_written);
   s->partial_pos_out += num_written;
-  *total_out = s->partial_pos_out;
+  if (total_out) *total_out = s->partial_pos_out;
   if (num_written < to_write) {
-    return BROTLI_RESULT_NEEDS_MORE_OUTPUT;
+    return BROTLI_NEEDS_MORE_OUTPUT;
   }
-  return BROTLI_RESULT_SUCCESS;
+
+  if (s->pos >= s->ringbuffer_size) {
+    s->pos -= s->ringbuffer_size;
+    s->rb_roundtrips++;
+  }
+  return BROTLI_SUCCESS;
 }
 
 /* Allocates ringbuffer.
 
   s->ringbuffer_size MUST be updated by BrotliCalculateRingBufferSize before
   this function is called.
 
    Last two bytes of ringbuffer are initialized to 0, so context calculation
@@ -1194,28 +1211,28 @@ static int BROTLI_NOINLINE BrotliAllocat
 
   s->ringbuffer_end = s->ringbuffer + s->ringbuffer_size;
 
   s->ringbuffer[s->ringbuffer_size - 2] = 0;
   s->ringbuffer[s->ringbuffer_size - 1] = 0;
 
   if (s->custom_dict) {
     memcpy(&s->ringbuffer[(-s->custom_dict_size) & s->ringbuffer_mask],
-                          s->custom_dict, (size_t)s->custom_dict_size);
+           s->custom_dict, (size_t)s->custom_dict_size);
   }
 
   return 1;
 }
 
-static BrotliResult BROTLI_NOINLINE CopyUncompressedBlockToOutput(
+static BrotliErrorCode BROTLI_NOINLINE CopyUncompressedBlockToOutput(
     size_t* available_out, uint8_t** next_out, size_t* total_out,
     BrotliState* s) {
   /* TODO: avoid allocation for single uncompressed block. */
   if (!s->ringbuffer && !BrotliAllocateRingBuffer(s)) {
-    return BROTLI_FAILURE();
+    return BROTLI_FAILURE(BROTLI_ERROR_ALLOC_RING_BUFFER_1);
   }
 
   /* State machine */
   for (;;) {
     switch (s->substate_uncompressed) {
       case BROTLI_STATE_UNCOMPRESSED_NONE: {
         int nbytes = (int)BrotliGetRemainingBytes(&s->br);
         if (nbytes > s->meta_block_remaining_len) {
@@ -1225,53 +1242,51 @@ static BrotliResult BROTLI_NOINLINE Copy
           nbytes = s->ringbuffer_size - s->pos;
         }
         /* Copy remaining bytes from s->br.buf_ to ringbuffer. */
         BrotliCopyBytes(&s->ringbuffer[s->pos], &s->br, (size_t)nbytes);
         s->pos += nbytes;
         s->meta_block_remaining_len -= nbytes;
         if (s->pos < s->ringbuffer_size) {
           if (s->meta_block_remaining_len == 0) {
-            return BROTLI_RESULT_SUCCESS;
+            return BROTLI_SUCCESS;
           }
-          return BROTLI_RESULT_NEEDS_MORE_INPUT;
+          return BROTLI_NEEDS_MORE_INPUT;
         }
         s->substate_uncompressed = BROTLI_STATE_UNCOMPRESSED_WRITE;
         /* No break, continue to next state */
       }
       case BROTLI_STATE_UNCOMPRESSED_WRITE: {
-        BrotliResult result = WriteRingBuffer(
-            available_out, next_out, total_out, s);
-        if (result != BROTLI_RESULT_SUCCESS) {
+        BrotliErrorCode result =
+            WriteRingBuffer(available_out, next_out, total_out, s);
+        if (result != BROTLI_SUCCESS) {
           return result;
         }
-        s->pos = 0;
-        s->rb_roundtrips++;
         s->max_distance = s->max_backward_distance;
         s->substate_uncompressed = BROTLI_STATE_UNCOMPRESSED_NONE;
         break;
       }
     }
   }
-  return BROTLI_FAILURE();
+  BROTLI_DCHECK(0);  /* Unreachable */
 }
 
 int BrotliDecompressedSize(size_t encoded_size,
                            const uint8_t* encoded_buffer,
                            size_t* decoded_size) {
   BrotliState s;
   int next_block_header;
   BrotliStateInit(&s);
   s.br.next_in = encoded_buffer;
   s.br.avail_in = encoded_size;
   if (!BrotliWarmupBitReader(&s.br)) {
     return 0;
   }
   DecodeWindowBits(&s.br);
-  if (DecodeMetaBlockLength(&s, &s.br) != BROTLI_RESULT_SUCCESS) {
+  if (DecodeMetaBlockLength(&s, &s.br) != BROTLI_SUCCESS) {
     return 0;
   }
   *decoded_size = (size_t)s.meta_block_remaining_len;
   if (s.is_last_metablock) {
     return 1;
   }
   if (!s.is_uncompressed || !BrotliJumpToByteBoundary(&s.br)) {
     return 0;
@@ -1285,61 +1300,57 @@ int BrotliDecompressedSize(size_t encode
    If we know the data size is small, do not allocate more ringbuffer
    size than needed to reduce memory usage.
 
    When this method is called, metablock size and flags MUST be decoded.
 */
 static void BROTLI_NOINLINE BrotliCalculateRingBufferSize(BrotliState* s,
     BrotliBitReader* br) {
   int is_last = s->is_last_metablock;
-  s->ringbuffer_size = 1 << s->window_bits;
+  int window_size = 1 << s->window_bits;
+  s->ringbuffer_size = window_size;
 
   if (s->is_uncompressed) {
-    int next_block_header = BrotliPeekByte(br,
-        (size_t)s->meta_block_remaining_len);
-    if (next_block_header != -1) { /* Peek succeeded */
-      if ((next_block_header & 3) == 3) { /* ISLAST and ISEMPTY */
+    int next_block_header =
+        BrotliPeekByte(br, (size_t)s->meta_block_remaining_len);
+    if (next_block_header != -1) {  /* Peek succeeded */
+      if ((next_block_header & 3) == 3) {  /* ISLAST and ISEMPTY */
         is_last = 1;
       }
     }
   }
 
   /* We need at least 2 bytes of ring buffer size to get the last two
      bytes for context from there */
   if (is_last) {
-    while (s->ringbuffer_size >= s->meta_block_remaining_len * 2
-        && s->ringbuffer_size > 32) {
+    int min_size_x2 = (s->meta_block_remaining_len + s->custom_dict_size) * 2;
+    while (s->ringbuffer_size >= min_size_x2 && s->ringbuffer_size > 32) {
       s->ringbuffer_size >>= 1;
     }
   }
 
-  /* But make it fit the custom dictionary if there is one. */
-  while (s->ringbuffer_size < s->custom_dict_size) {
-    s->ringbuffer_size <<= 1;
-  }
-
   s->ringbuffer_mask = s->ringbuffer_size - 1;
 }
 
 /* Reads 1..256 2-bit context modes. */
-static BrotliResult ReadContextModes(BrotliState* s) {
+static BrotliErrorCode ReadContextModes(BrotliState* s) {
   BrotliBitReader* br = &s->br;
   int i = s->loop_counter;
 
   while (i < (int)s->num_block_types[0]) {
     uint32_t bits;
     if (!BrotliSafeReadBits(br, 2, &bits)) {
       s->loop_counter = i;
-      return BROTLI_RESULT_NEEDS_MORE_INPUT;
+      return BROTLI_NEEDS_MORE_INPUT;
     }
     s->context_modes[i] = (uint8_t)(bits << 1);
     BROTLI_LOG_ARRAY_INDEX(s->context_modes, i);
     i++;
   }
-  return BROTLI_RESULT_SUCCESS;
+  return BROTLI_SUCCESS;
 }
 
 static BROTLI_INLINE void TakeDistanceFromRingBuffer(BrotliState* s) {
   if (s->distance_code == 0) {
     --s->dist_rb_idx;
     s->distance_code = s->dist_rb[s->dist_rb_idx & 3];
   } else {
     int distance_code = s->distance_code << 1;
@@ -1402,18 +1413,18 @@ static BROTLI_INLINE int ReadDistanceInt
   distval = s->distance_code - (int)s->num_direct_distance_codes;
   if (distval >= 0) {
     uint32_t nbits;
     int postfix;
     int offset;
     if (!safe && (s->distance_postfix_bits == 0)) {
       nbits = ((uint32_t)distval >> 1) + 1;
       offset = ((2 + (distval & 1)) << nbits) - 4;
-      s->distance_code = (int)s->num_direct_distance_codes +
-          offset + (int)BrotliReadBits(br, nbits);
+      s->distance_code = (int)s->num_direct_distance_codes + offset +
+                         (int)BrotliReadBits(br, nbits);
     } else {
       /* This branch also works well when s->distance_postfix_bits == 0 */
       uint32_t bits;
       postfix = distval & s->distance_postfix_mask;
       distval >>= s->distance_postfix_bits;
       nbits = ((uint32_t)distval >> 1) + 1;
       if (safe) {
         if (!SafeReadBits(br, nbits, &bits)) {
@@ -1493,62 +1504,63 @@ static BROTLI_INLINE int SafeReadCommand
 static BROTLI_INLINE int CheckInputAmount(int safe,
     BrotliBitReader* const br, size_t num) {
   if (safe) {
     return 1;
   }
   return BrotliCheckInputAmount(br, num);
 }
 
-#define BROTLI_SAFE(METHOD) { \
-  if (safe) { \
-    if (! Safe ## METHOD ) { \
-      result = BROTLI_RESULT_NEEDS_MORE_INPUT; \
-      goto saveStateAndReturn; \
-    } \
-  } else { \
-    METHOD ; \
-  } \
-}
+#define BROTLI_SAFE(METHOD)               \
+  {                                       \
+    if (safe) {                           \
+      if (!Safe##METHOD) {                \
+        result = BROTLI_NEEDS_MORE_INPUT; \
+        goto saveStateAndReturn;          \
+      }                                   \
+    } else {                              \
+      METHOD;                             \
+    }                                     \
+  }
 
-static BROTLI_INLINE BrotliResult ProcessCommandsInternal(int safe,
+static BROTLI_INLINE BrotliErrorCode ProcessCommandsInternal(int safe,
     BrotliState* s) {
   int pos = s->pos;
   int i = s->loop_counter;
-  BrotliResult result = BROTLI_RESULT_SUCCESS;
+  BrotliErrorCode result = BROTLI_SUCCESS;
   BrotliBitReader* br = &s->br;
 
   if (!CheckInputAmount(safe, br, 28)) {
-    result = BROTLI_RESULT_NEEDS_MORE_INPUT;
+    result = BROTLI_NEEDS_MORE_INPUT;
     goto saveStateAndReturn;
   }
   if (!safe) {
     BROTLI_UNUSED(BrotliWarmupBitReader(br));
   }
 
   /* Jump into state machine. */
   if (s->state == BROTLI_STATE_COMMAND_BEGIN) {
     goto CommandBegin;
   } else if (s->state == BROTLI_STATE_COMMAND_INNER) {
     goto CommandInner;
   } else if (s->state == BROTLI_STATE_COMMAND_POST_DECODE_LITERALS) {
     goto CommandPostDecodeLiterals;
   } else if (s->state == BROTLI_STATE_COMMAND_POST_WRAP_COPY) {
     goto CommandPostWrapCopy;
   } else {
-    return BROTLI_FAILURE();
+    return BROTLI_FAILURE(BROTLI_ERROR_UNREACHABLE);
   }
 
 CommandBegin:
   if (safe) {
     s->state = BROTLI_STATE_COMMAND_BEGIN;
   }
   if (!CheckInputAmount(safe, br, 28)) { /* 156 bits + 7 bytes */
     s->state = BROTLI_STATE_COMMAND_BEGIN;
-    result = BROTLI_RESULT_NEEDS_MORE_INPUT;
+    result = BROTLI_NEEDS_MORE_INPUT;
     goto saveStateAndReturn;
   }
   if (PREDICT_FALSE(s->block_length[1] == 0)) {
     BROTLI_SAFE(DecodeCommandBlockSwitch(s));
     goto CommandBegin;
   }
   /* Read the insert/copy length in the command */
   BROTLI_SAFE(ReadCommand(s, br, &i));
@@ -1566,68 +1578,69 @@ CommandInner:
   /* Read the literals in the command */
   if (s->trivial_literal_context) {
     uint32_t bits;
     uint32_t value;
     PreloadSymbol(safe, s->literal_htree, br, &bits, &value);
     do {
       if (!CheckInputAmount(safe, br, 28)) { /* 162 bits + 7 bytes */
         s->state = BROTLI_STATE_COMMAND_INNER;
-        result = BROTLI_RESULT_NEEDS_MORE_INPUT;
+        result = BROTLI_NEEDS_MORE_INPUT;
         goto saveStateAndReturn;
       }
       if (PREDICT_FALSE(s->block_length[0] == 0)) {
         BROTLI_SAFE(DecodeLiteralBlockSwitch(s));
         PreloadSymbol(safe, s->literal_htree, br, &bits, &value);
+        if (!s->trivial_literal_context) goto CommandInner;
       }
       if (!safe) {
-        s->ringbuffer[pos] = (uint8_t)ReadPreloadedSymbol(
-            s->literal_htree, br, &bits, &value);
+        s->ringbuffer[pos] =
+            (uint8_t)ReadPreloadedSymbol(s->literal_htree, br, &bits, &value);
       } else {
         uint32_t literal;
         if (!SafeReadSymbol(s->literal_htree, br, &literal)) {
-          result = BROTLI_RESULT_NEEDS_MORE_INPUT;
+          result = BROTLI_NEEDS_MORE_INPUT;
           goto saveStateAndReturn;
         }
         s->ringbuffer[pos] = (uint8_t)literal;
       }
       --s->block_length[0];
-      BROTLI_LOG_UINT(s->literal_htree_index);
       BROTLI_LOG_ARRAY_INDEX(s->ringbuffer, pos);
       ++pos;
       if (PREDICT_FALSE(pos == s->ringbuffer_size)) {
         s->state = BROTLI_STATE_COMMAND_INNER_WRITE;
         --i;
         goto saveStateAndReturn;
       }
     } while (--i != 0);
   } else {
     uint8_t p1 = s->ringbuffer[(pos - 1) & s->ringbuffer_mask];
     uint8_t p2 = s->ringbuffer[(pos - 2) & s->ringbuffer_mask];
     do {
       const HuffmanCode* hc;
       uint8_t context;
       if (!CheckInputAmount(safe, br, 28)) { /* 162 bits + 7 bytes */
         s->state = BROTLI_STATE_COMMAND_INNER;
-        result = BROTLI_RESULT_NEEDS_MORE_INPUT;
+        result = BROTLI_NEEDS_MORE_INPUT;
         goto saveStateAndReturn;
       }
       if (PREDICT_FALSE(s->block_length[0] == 0)) {
         BROTLI_SAFE(DecodeLiteralBlockSwitch(s));
+        if (s->trivial_literal_context) goto CommandInner;
       }
       context = s->context_lookup1[p1] | s->context_lookup2[p2];
       BROTLI_LOG_UINT(context);
       hc = s->literal_hgroup.htrees[s->context_map_slice[context]];
       p2 = p1;
       if (!safe) {
         p1 = (uint8_t)ReadSymbol(hc, br);
       } else {
         uint32_t literal;
         if (!SafeReadSymbol(hc, br, &literal)) {
-          result = BROTLI_RESULT_NEEDS_MORE_INPUT;
+          result = BROTLI_NEEDS_MORE_INPUT;
           goto saveStateAndReturn;
         }
         p1 = (uint8_t)literal;
       }
       s->ringbuffer[pos] = p1;
       --s->block_length[0];
       BROTLI_LOG_UINT(s->context_map_slice[context]);
       BROTLI_LOG_ARRAY_INDEX(s->ringbuffer, pos & s->ringbuffer_mask);
@@ -1635,17 +1648,17 @@ CommandInner:
       if (PREDICT_FALSE(pos == s->ringbuffer_size)) {
         s->state = BROTLI_STATE_COMMAND_INNER_WRITE;
         --i;
         goto saveStateAndReturn;
       }
     } while (--i != 0);
   }
   BROTLI_LOG_UINT(s->meta_block_remaining_len);
-  if (s->meta_block_remaining_len <= 0) {
+  if (PREDICT_FALSE(s->meta_block_remaining_len <= 0)) {
     s->state = BROTLI_STATE_METABLOCK_DONE;
     goto saveStateAndReturn;
   }
 
 CommandPostDecodeLiterals:
   if (safe) {
     s->state = BROTLI_STATE_COMMAND_POST_DECODE_LITERALS;
   }
@@ -1695,68 +1708,48 @@ postReadDistance:
         s->meta_block_remaining_len -= len;
         if (pos >= s->ringbuffer_size) {
           /*s->partial_pos_rb += (size_t)s->ringbuffer_size;*/
           s->state = BROTLI_STATE_COMMAND_POST_WRITE_1;
           goto saveStateAndReturn;
         }
       } else {
         BROTLI_LOG(("Invalid backward reference. pos: %d distance: %d "
-               "len: %d bytes left: %d\n",
-            pos, s->distance_code, i,
-            s->meta_block_remaining_len));
-        return BROTLI_FAILURE();
+            "len: %d bytes left: %d\n",
+            pos, s->distance_code, i, s->meta_block_remaining_len));
+        return BROTLI_FAILURE(BROTLI_ERROR_FORMAT_TRANSFORM);
       }
     } else {
       BROTLI_LOG(("Invalid backward reference. pos: %d distance: %d "
-             "len: %d bytes left: %d\n", pos, s->distance_code, i,
-             s->meta_block_remaining_len));
-      return BROTLI_FAILURE();
+          "len: %d bytes left: %d\n",
+          pos, s->distance_code, i, s->meta_block_remaining_len));
+      return BROTLI_FAILURE(BROTLI_ERROR_FORMAT_DICTIONARY);
     }
   } else {
-    const uint8_t *ringbuffer_end_minus_copy_length =
-        s->ringbuffer_end - i;
-    uint8_t* copy_src = &s->ringbuffer[
-        (pos - s->distance_code) & s->ringbuffer_mask];
+    int src_start = (pos - s->distance_code) & s->ringbuffer_mask;
     uint8_t* copy_dst = &s->ringbuffer[pos];
-    /* Check for possible underflow and clamp the pointer to 0. */
-    if (PREDICT_FALSE(s->ringbuffer_end < (const uint8_t*)0 + i)) {
-      ringbuffer_end_minus_copy_length = 0;
-    }
+    uint8_t* copy_src = &s->ringbuffer[src_start];
+    int dst_end = pos + i;
+    int src_end = src_start + i;
     /* update the recent distances cache */
     s->dist_rb[s->dist_rb_idx & 3] = s->distance_code;
     ++s->dist_rb_idx;
     s->meta_block_remaining_len -= i;
-    if (PREDICT_FALSE(s->meta_block_remaining_len < 0)) {
-      BROTLI_LOG(("Invalid backward reference. pos: %d distance: %d "
-             "len: %d bytes left: %d\n", pos, s->distance_code, i,
-             s->meta_block_remaining_len));
-      return BROTLI_FAILURE();
-    }
-    /* There is 128+ bytes of slack in the ringbuffer allocation.
+    /* There are 32+ bytes of slack in the ringbuffer allocation.
        Also, we have 16 short codes, that make these 16 bytes irrelevant
        in the ringbuffer. Let's copy over them as a first guess.
      */
     memmove16(copy_dst, copy_src);
-    /* Now check if the