diff --git a/Makefile.in b/Makefile.in index 74106621332c..4c8baebb9f5a 100644 --- a/Makefile.in +++ b/Makefile.in @@ -237,6 +237,9 @@ endif # 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 diff --git a/accessible/base/EventTree.cpp b/accessible/base/EventTree.cpp index a2fcedf7b352..232f17eef957 100644 --- a/accessible/base/EventTree.cpp +++ b/accessible/base/EventTree.cpp @@ -36,52 +36,10 @@ TreeMutation::TreeMutation(Accessible* aParent, bool aNoEvents) : 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(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(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(this)); } - logging::MsgEnd(); } #endif @@ -173,6 +131,22 @@ TreeMutation::Done() #endif } +#ifdef A11Y_LOG +const char* +TreeMutation::PrefixLog(void* aData, Accessible* aAcc) +{ + TreeMutation* thisObj = reinterpret_cast(aData); + if (thisObj->mParent == aAcc) { + return "_X_"; + } + const EventTree& ret = thisObj->Controller()->RootEventTree(); + if (ret.Find(aAcc)) { + return "_с_"; + } + return ""; +} +#endif + //////////////////////////////////////////////////////////////////////////////// // EventTree diff --git a/accessible/base/EventTree.h b/accessible/base/EventTree.h index e2d5ef24bc5b..eab6d37a2672 100644 --- a/accessible/base/EventTree.h +++ b/accessible/base/EventTree.h @@ -39,6 +39,10 @@ private: static EventTree* const kNoEventTree; +#ifdef A11Y_LOG + static const char* PrefixLog(void* aData, Accessible*); +#endif + Accessible* mParent; uint32_t mStartIdx; uint32_t mStateFlagsCopy; diff --git a/accessible/base/Logging.cpp b/accessible/base/Logging.cpp index 5b10fc1a914e..39be6d5cdc38 100644 --- a/accessible/base/Logging.cpp +++ b/accessible/base/Logging.cpp @@ -673,6 +673,47 @@ logging::TreeInfo(const char* aMsg, uint32_t aExtraFlags, Accessible* aParent) } } +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(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(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, ...) { diff --git a/accessible/base/Logging.h b/accessible/base/Logging.h index 12d4749e6685..c6b8ce538589 100644 --- a/accessible/base/Logging.h +++ b/accessible/base/Logging.h @@ -139,6 +139,13 @@ void TreeInfo(const char* aMsg, uint32_t aExtraFlags, 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 diff --git a/accessible/generic/Accessible.h b/accessible/generic/Accessible.h index 91427ff09baf..2e11a2cfba71 100644 --- a/accessible/generic/Accessible.h +++ b/accessible/generic/Accessible.h @@ -50,6 +50,14 @@ 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. */ @@ -1120,6 +1128,12 @@ protected: 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; diff --git a/accessible/interfaces/moz.build b/accessible/interfaces/moz.build index baa23f9774ea..e4a28f8e454a 100644 --- a/accessible/interfaces/moz.build +++ b/accessible/interfaces/moz.build @@ -4,7 +4,7 @@ # 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 += [ diff --git a/addon-sdk/source/lib/toolkit/loader.js b/addon-sdk/source/lib/toolkit/loader.js index 26df1d803093..a07ff3b2fd33 100644 --- a/addon-sdk/source/lib/toolkit/loader.js +++ b/addon-sdk/source/lib/toolkit/loader.js @@ -181,7 +181,7 @@ function readURI(uri) { 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' diff --git a/build/autoconf/compiler-opts.m4 b/build/autoconf/compiler-opts.m4 index 94fb7f86f005..eaa4a0c67010 100644 --- a/build/autoconf/compiler-opts.m4 +++ b/build/autoconf/compiler-opts.m4 @@ -95,30 +95,6 @@ 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 @@ -156,31 +132,6 @@ 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. diff --git a/build/moz.configure/old.configure b/build/moz.configure/old.configure index c01246c8fe35..964960c8f377 100644 --- a/build/moz.configure/old.configure +++ b/build/moz.configure/old.configure @@ -172,9 +172,7 @@ def old_configure_options(*options): '--enable-ctypes', '--enable-dbm', '--enable-dbus', - '--enable-debug', '--enable-debug-js-modules', - '--enable-debug-symbols', '--enable-directshow', '--enable-dtrace', '--enable-dump-painting', diff --git a/build/moz.configure/toolchain.configure b/build/moz.configure/toolchain.configure index da05ad3c7635..78e84eaf7ad5 100644 --- a/build/moz.configure/toolchain.configure +++ b/build/moz.configure/toolchain.configure @@ -604,3 +604,39 @@ 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) diff --git a/config/baseconfig.mk b/config/baseconfig.mk index a125466abf78..47a12b16e4ee 100644 --- a/config/baseconfig.mk +++ b/config/baseconfig.mk @@ -45,7 +45,7 @@ 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. diff --git a/docshell/shistory/nsSHistory.cpp b/docshell/shistory/nsSHistory.cpp index 4ecf3117c564..03a2944cb606 100644 --- a/docshell/shistory/nsSHistory.cpp +++ b/docshell/shistory/nsSHistory.cpp @@ -1696,7 +1696,7 @@ nsSHistory::CompareFrames(nsISHEntry* aPrevEntry, nsISHEntry* aNextEntry, aParent->GetChildAt(i, getter_AddRefs(treeItem)); nsCOMPtr shell = do_QueryInterface(treeItem); if (shell) { - docshells.AppendObject(shell); + docshells.AppendElement(shell.forget()); } } diff --git a/dom/base/ScriptSettings.cpp b/dom/base/ScriptSettings.cpp index 02d6f6af3620..4cfcde3a63a7 100644 --- a/dom/base/ScriptSettings.cpp +++ b/dom/base/ScriptSettings.cpp @@ -268,29 +268,6 @@ GetWebIDLCallerPrincipal() } AutoEntryScript* aes = static_cast(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; } @@ -755,9 +732,9 @@ danger::AutoCxPusher::AutoCxPusher(JSContext* cx, bool allowNull) 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 @@ -781,11 +758,11 @@ danger::AutoCxPusher::~AutoCxPusher() // pop is the same as it was right after we pushed. MOZ_ASSERT_IF(mPushedContext, mCompartmentDepthOnEntry == js::GetEnterCompartmentDepth(mPushedContext)); - DebugOnly stackTop; MOZ_ASSERT(mPushedContext == nsXPConnect::XPConnect()->GetCurrentJSContext()); XPCJSRuntime::Get()->GetJSContextStack()->Pop(); } +#ifdef DEBUG bool danger::AutoCxPusher::IsStackTop() const { @@ -793,6 +770,7 @@ danger::AutoCxPusher::IsStackTop() const MOZ_ASSERT(currentDepth >= mStackDepthAfterPush); return currentDepth == mStackDepthAfterPush; } +#endif } // namespace dom diff --git a/dom/base/ScriptSettings.h b/dom/base/ScriptSettings.h index 082e0859144e..ada1ac862c31 100644 --- a/dom/base/ScriptSettings.h +++ b/dom/base/ScriptSettings.h @@ -46,8 +46,8 @@ public: private: mozilla::Maybe mAutoRequest; - uint32_t mStackDepthAfterPush; #ifdef DEBUG + uint32_t mStackDepthAfterPush; JSContext* mPushedContext; unsigned mCompartmentDepthOnEntry; #endif @@ -262,7 +262,9 @@ public: return mCx; } +#ifdef DEBUG bool CxPusherIsStackTop() const { return mCxPusher->IsStackTop(); } +#endif // If HasException, report it. Otherwise, a no-op. void ReportException(); diff --git a/dom/base/nsDOMWindowUtils.cpp b/dom/base/nsDOMWindowUtils.cpp index cbe4f68e42b6..4f834d412004 100644 --- a/dom/base/nsDOMWindowUtils.cpp +++ b/dom/base/nsDOMWindowUtils.cpp @@ -123,6 +123,51 @@ using namespace mozilla::gfx; class gfxContext; +class OldWindowSize : public LinkedListElement +{ +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 sList; + nsWeakPtr mWindowRef; + nsSize mSize; +}; + +LinkedList OldWindowSize::sList; + NS_INTERFACE_MAP_BEGIN(nsDOMWindowUtils) NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMWindowUtils) NS_INTERFACE_MAP_ENTRY(nsIDOMWindowUtils) @@ -141,6 +186,7 @@ nsDOMWindowUtils::nsDOMWindowUtils(nsGlobalWindow *aWindow) nsDOMWindowUtils::~nsDOMWindowUtils() { + OldWindowSize::GetAndRemove(mWindow); } nsIPresShell* @@ -3104,62 +3150,6 @@ PrepareForFullscreenChange(nsIPresShell* aPresShell, const nsSize& aSize, } } -class OldWindowSize : public LinkedListElement -{ -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&& aWindow, - const nsSize& aSize) - : mWindow(Move(aWindow)), mSize(aSize) { } - ~OldWindowSize() { }; - - static OldWindowSize* GetItem(nsPIDOMWindowOuter* aWindow) - { - OldWindowSize* item = sList.getFirst(); - while (item) { - nsCOMPtr 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 sList; - nsWeakPtr mWindow; - nsSize mSize; -}; - -LinkedList OldWindowSize::sList; - NS_IMETHODIMP nsDOMWindowUtils::HandleFullscreenRequests(bool* aRetVal) { @@ -3177,7 +3167,7 @@ nsDOMWindowUtils::HandleFullscreenRequests(bool* aRetVal) } nsSize oldSize; PrepareForFullscreenChange(GetPresShell(), screenRect.Size(), &oldSize); - OldWindowSize::Set(doc->GetWindow(), oldSize); + OldWindowSize::Set(mWindow, oldSize); *aRetVal = nsIDocument::HandlePendingFullscreenRequests(doc); return NS_OK; @@ -3192,7 +3182,7 @@ nsDOMWindowUtils::ExitFullscreen() // 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; } diff --git a/dom/base/nsScriptLoader.cpp b/dom/base/nsScriptLoader.cpp index 32d16537e3b0..ad69542114df 100644 --- a/dom/base/nsScriptLoader.cpp +++ b/dom/base/nsScriptLoader.cpp @@ -898,7 +898,7 @@ ResolveRequestedModules(nsModuleLoadRequest* aRequest, nsCOMArray &aUrls nsresult rv = RequestedModuleIsInAncestorList(aRequest, uri, &isAncestor); NS_ENSURE_SUCCESS(rv, rv); if (!isAncestor) { - aUrls.AppendElement(uri); + aUrls.AppendElement(uri.forget()); } } diff --git a/dom/events/EventListenerManager.cpp b/dom/events/EventListenerManager.cpp index 486544f5410c..92b7c4097ee0 100644 --- a/dom/events/EventListenerManager.cpp +++ b/dom/events/EventListenerManager.cpp @@ -1559,7 +1559,7 @@ EventListenerManager::GetListenerInfo(nsCOMArray* aList) listener.mFlags.mCapture, listener.mFlags.mAllowUntrustedEvents, listener.mFlags.mInSystemGroup); - aList->AppendObject(info); + aList->AppendElement(info.forget()); } return NS_OK; } diff --git a/dom/ipc/ContentChild.cpp b/dom/ipc/ContentChild.cpp index d205bc370947..6dd6ce6b2304 100644 --- a/dom/ipc/ContentChild.cpp +++ b/dom/ipc/ContentChild.cpp @@ -2525,13 +2525,11 @@ ContentChild::RecvAddPermission(const IPC::Permission& permission) 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 uri; nsresult rv = NS_NewURI(getter_AddRefs(uri), originNoSuffix); diff --git a/dom/ipc/TabChild.cpp b/dom/ipc/TabChild.cpp index 31713dd60a60..4af68bebf8c1 100644 --- a/dom/ipc/TabChild.cpp +++ b/dom/ipc/TabChild.cpp @@ -1921,8 +1921,13 @@ 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 document(GetDocument()); APZCCallbackHelper::SendSetTargetAPZCNotification( mPuppetWidget, document, aEvent, aGuid, aInputBlockId); @@ -1937,8 +1942,7 @@ TabChild::RecvRealMouseButtonEvent(const WidgetMouseEvent& aEvent, mPuppetWidget->GetDefaultScale()); APZCCallbackHelper::DispatchWidgetEvent(localEvent); - if (aInputBlockId) { - MOZ_ASSERT(aEvent.mFlags.mHandledByAPZ); + if (aInputBlockId && aEvent.mFlags.mHandledByAPZ) { mAPZEventState->ProcessMouseEvent(aEvent, aGuid, aInputBlockId); } return true; @@ -1949,8 +1953,7 @@ 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 document(GetDocument()); APZCCallbackHelper::SendSetTargetAPZCNotification( mPuppetWidget, document, aEvent, aGuid, aInputBlockId); @@ -1966,8 +1969,7 @@ TabChild::RecvMouseWheelEvent(const WidgetWheelEvent& aEvent, SendRespondStartSwipeEvent(aInputBlockId, localEvent.TriggersSwipe()); } - if (aInputBlockId) { - MOZ_ASSERT(aEvent.mFlags.mHandledByAPZ); + if (aInputBlockId && aEvent.mFlags.mHandledByAPZ) { mAPZEventState->ProcessWheelEvent(localEvent, aGuid, aInputBlockId); } return true; diff --git a/dom/media/tests/mochitest/head.js b/dom/media/tests/mochitest/head.js index 09564e69c832..e0d248c8feee 100644 --- a/dom/media/tests/mochitest/head.js +++ b/dom/media/tests/mochitest/head.js @@ -312,7 +312,8 @@ function setupEnvironment() { 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] ); } diff --git a/dom/plugins/base/nsPluginHost.cpp b/dom/plugins/base/nsPluginHost.cpp index ad0815d4edd8..914d47739156 100644 --- a/dom/plugins/base/nsPluginHost.cpp +++ b/dom/plugins/base/nsPluginHost.cpp @@ -2016,7 +2016,7 @@ GetExtensionDirectories(nsCOMArray& dirs) nsCOMPtr file = do_QueryInterface(next); if (file) { file->Normalize(); - dirs.AppendElement(file); + dirs.AppendElement(file.forget()); } } } diff --git a/extensions/cookie/nsPermissionManager.cpp b/extensions/cookie/nsPermissionManager.cpp index eda52b5ec559..1979fe696afe 100644 --- a/extensions/cookie/nsPermissionManager.cpp +++ b/extensions/cookie/nsPermissionManager.cpp @@ -122,6 +122,9 @@ GetOriginFromPrincipal(nsIPrincipal* aPrincipal, nsACString& aOrigin) // 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; diff --git a/gfx/gl/SharedSurfaceANGLE.h b/gfx/gl/SharedSurfaceANGLE.h index 85c7d9a06e53..b0d03fee7388 100644 --- a/gfx/gl/SharedSurfaceANGLE.h +++ b/gfx/gl/SharedSurfaceANGLE.h @@ -40,9 +40,6 @@ public: const HANDLE mShareHandle; protected: RefPtr mKeyedMutex; - RefPtr mConsumerKeyedMutex; - RefPtr mConsumerTexture; - const GLuint mFence; SharedSurface_ANGLEShareHandle(GLContext* gl, @@ -67,10 +64,6 @@ public: virtual void ProducerReadAcquireImpl() override; virtual void ProducerReadReleaseImpl() override; - const RefPtr& GetConsumerTexture() const { - return mConsumerTexture; - } - virtual bool ToSurfaceDescriptor(layers::SurfaceDescriptor* const out_descriptor) override; virtual bool ReadbackBySharedHandle(gfx::DataSourceSurface* out_surface) override; diff --git a/gfx/gl/SharedSurfaceD3D11Interop.h b/gfx/gl/SharedSurfaceD3D11Interop.h index bfe583090c11..d8f64709e655 100644 --- a/gfx/gl/SharedSurfaceD3D11Interop.h +++ b/gfx/gl/SharedSurfaceD3D11Interop.h @@ -32,9 +32,6 @@ public: protected: RefPtr mKeyedMutex; - RefPtr mConsumerKeyedMutex; - RefPtr mConsumerTexture; - bool mLockedForGL; public: diff --git a/gfx/layers/LayersLogging.h b/gfx/layers/LayersLogging.h index b1ed6ab04c5a..cb123a245043 100644 --- a/gfx/layers/LayersLogging.h +++ b/gfx/layers/LayersLogging.h @@ -9,6 +9,7 @@ #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" @@ -110,6 +111,18 @@ AppendToString(std::stringstream& aStream, const mozilla::gfx::IntRegionTyped +void +AppendToString(std::stringstream& aStream, const mozilla::gfx::TiledRegion& 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=""); diff --git a/gfx/layers/client/ClientLayerManager.cpp b/gfx/layers/client/ClientLayerManager.cpp index eb98e5afebdf..90c0d7854a05 100644 --- a/gfx/layers/client/ClientLayerManager.cpp +++ b/gfx/layers/client/ClientLayerManager.cpp @@ -526,8 +526,13 @@ ClientLayerManager::MakeSnapshotIfRequired() 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 surf = GetSurfaceForDescriptor(inSnapshot); + RefPtr surf = GetSurfaceForDescriptor(outSnapshot); DrawTarget* dt = mShadowTarget->GetDrawTarget(); Rect dstRect(bounds.x, bounds.y, bounds.width, bounds.height); @@ -544,7 +549,7 @@ ClientLayerManager::MakeSnapshotIfRequired() DrawOptions(1.0f, CompositionOp::OP_OVER)); dt->SetTransform(oldMatrix); } - mForwarder->DestroySurfaceDescriptor(&inSnapshot); + mForwarder->DestroySurfaceDescriptor(&outSnapshot); } } } diff --git a/gfx/layers/ipc/ImageBridgeChild.cpp b/gfx/layers/ipc/ImageBridgeChild.cpp index 2627a949e245..6cd9dbd84461 100644 --- a/gfx/layers/ipc/ImageBridgeChild.cpp +++ b/gfx/layers/ipc/ImageBridgeChild.cpp @@ -343,10 +343,11 @@ ImageBridgeChild::NotifyNotUsedToNonRecycle(uint64_t aTextureId, uint64_t aTrans mTexturesWaitingFenceHandle.Remove(aTextureId); // Release TextureClient on allocator's message loop. - TextureClientReleaseTask* task = new TextureClientReleaseTask(client); + RefPtr task = + MakeAndAddRef(client); RefPtr allocator = client->GetAllocator(); client = nullptr; - allocator->AsClientAllocator()->GetMessageLoop()->PostTask(FROM_HERE, task); + allocator->AsClientAllocator()->GetMessageLoop()->PostTask(task.forget()); #else NS_RUNTIMEABORT("not reached"); #endif diff --git a/gfx/src/TiledRegion.cpp b/gfx/src/TiledRegion.cpp index fb14012fa7d3..412344d6ef35 100644 --- a/gfx/src/TiledRegion.cpp +++ b/gfx/src/TiledRegion.cpp @@ -14,6 +14,7 @@ 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 @@ -282,7 +283,8 @@ TiledRegionImpl::AddRect(const pixman_box32_t& aRect) // existing rectangle to include the intersection of aRect with the tile. return ProcessIntersectedTiles(aRect, mRects, [&aRect](nsTArray& 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(); diff --git a/gfx/src/TiledRegion.h b/gfx/src/TiledRegion.h index 10e884494463..a79d0054a7cb 100644 --- a/gfx/src/TiledRegion.h +++ b/gfx/src/TiledRegion.h @@ -94,10 +94,6 @@ public: if (mCoversBounds) { return; } - if (ExceedsMaximumSize()) { - FallBackToBounds(); - return; - } if (!mImpl.AddRect(RectToBox(aRect))) { FallBackToBounds(); @@ -111,10 +107,6 @@ public: if (mCoversBounds) { return; } - if (ExceedsMaximumSize()) { - FallBackToBounds(); - return; - } for (auto iter = aRegion.RectIter(); !iter.Done(); iter.Next()) { RectT r = iter.Get(); @@ -136,6 +128,7 @@ public: } RectT GetBounds() const { return mBounds; } + bool CoversBounds() const { return mCoversBounds; } bool Intersects(const RectT& aRect) const { @@ -162,12 +155,6 @@ public: 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; diff --git a/image/decoders/nsGIFDecoder2.cpp b/image/decoders/nsGIFDecoder2.cpp index 06916a1cf387..64ba2ffe06a2 100644 --- a/image/decoders/nsGIFDecoder2.cpp +++ b/image/decoders/nsGIFDecoder2.cpp @@ -495,6 +495,8 @@ nsGIFDecoder2::WriteInternal(const char* aBuffer, uint32_t aCount) 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: @@ -987,8 +989,9 @@ nsGIFDecoder2::ReadImageDataSubBlock(const char* aData) } 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. @@ -996,7 +999,10 @@ nsGIFDecoder2::ReadImageDataSubBlock(const char* aData) 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 diff --git a/image/decoders/nsGIFDecoder2.h b/image/decoders/nsGIFDecoder2.h index 72e5191b98d1..9a9f7191821a 100644 --- a/image/decoders/nsGIFDecoder2.h +++ b/image/decoders/nsGIFDecoder2.h @@ -90,6 +90,7 @@ private: IMAGE_DATA_BLOCK, IMAGE_DATA_SUB_BLOCK, LZW_DATA, + SKIP_LZW_DATA, FINISHED_LZW_DATA, SKIP_SUB_BLOCKS, SKIP_DATA_THEN_SKIP_SUB_BLOCKS, diff --git a/image/imgFrame.cpp b/image/imgFrame.cpp index b80b3308ec13..c9797cd968ca 100644 --- a/image/imgFrame.cpp +++ b/image/imgFrame.cpp @@ -15,8 +15,6 @@ #include "gfxUtils.h" #include "gfxAlphaRecovery.h" -static bool gDisableOptimize = false; - #include "GeckoProfiler.h" #include "mozilla/Likely.h" #include "MainThreadUtils.h" @@ -149,13 +147,6 @@ imgFrame::imgFrame() , mSinglePixel(false) , mCompositingFailed(false) { - static bool hasCheckedOptimize = false; - if (!hasCheckedOptimize) { - if (PR_GetEnv("MOZ_DISABLE_IMAGE_OPTIMIZE")) { - gDisableOptimize = true; - } - hasCheckedOptimize = true; - } } imgFrame::~imgFrame() @@ -339,6 +330,16 @@ imgFrame::Optimize() 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; diff --git a/image/test/gtest/Common.cpp b/image/test/gtest/Common.cpp index 85de52daeaeb..2d6f59e31d48 100644 --- a/image/test/gtest/Common.cpp +++ b/image/test/gtest/Common.cpp @@ -533,6 +533,14 @@ ImageTestCase NoFrameDelayGIFTestCase() 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 diff --git a/image/test/gtest/Common.h b/image/test/gtest/Common.h index 70627f2c2e6d..aa571d29cd4d 100644 --- a/image/test/gtest/Common.h +++ b/image/test/gtest/Common.h @@ -332,6 +332,7 @@ ImageTestCase TransparentPNGTestCase(); ImageTestCase TransparentGIFTestCase(); ImageTestCase FirstFramePaddingGIFTestCase(); ImageTestCase NoFrameDelayGIFTestCase(); +ImageTestCase ExtraImageSubBlocksAnimatedGIFTestCase(); ImageTestCase TransparentBMPWhenBMPAlphaEnabledTestCase(); ImageTestCase RLE4BMPTestCase(); diff --git a/image/test/gtest/TestDecoders.cpp b/image/test/gtest/TestDecoders.cpp index 59fac0b8eee6..49628c593267 100644 --- a/image/test/gtest/TestDecoders.cpp +++ b/image/test/gtest/TestDecoders.cpp @@ -349,3 +349,72 @@ 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 = + ImageFactory::CreateAnonymousImage(nsDependentCString(testCase.mMimeType)); + ASSERT_TRUE(!image->HasError()); + + nsCOMPtr 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(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 tracker = image->GetProgressTracker(); + tracker->SyncNotifyProgress(FLAG_LOAD_COMPLETE); + + // Use GetFrame() to force a sync decode of the image. + RefPtr 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()); +} diff --git a/image/test/gtest/animated-with-extra-image-sub-blocks.gif b/image/test/gtest/animated-with-extra-image-sub-blocks.gif new file mode 100644 index 000000000000..a145c814a684 Binary files /dev/null and b/image/test/gtest/animated-with-extra-image-sub-blocks.gif differ diff --git a/image/test/gtest/moz.build b/image/test/gtest/moz.build index 8b065e4d3e9c..f8d6303966ca 100644 --- a/image/test/gtest/moz.build +++ b/image/test/gtest/moz.build @@ -30,6 +30,7 @@ SOURCES += [ ] TEST_HARNESS_FILES.gtest += [ + 'animated-with-extra-image-sub-blocks.gif', 'corrupt.jpg', 'downscaled.bmp', 'downscaled.gif', diff --git a/js/public/RootingAPI.h b/js/public/RootingAPI.h index b1c2ae5a4a63..d3ac40cb10e0 100644 --- a/js/public/RootingAPI.h +++ b/js/public/RootingAPI.h @@ -586,7 +586,7 @@ 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) diff --git a/js/public/UbiNode.h b/js/public/UbiNode.h index 28e58db6ae67..f97e302a88d5 100644 --- a/js/public/UbiNode.h +++ b/js/public/UbiNode.h @@ -183,6 +183,9 @@ using mozilla::Move; using mozilla::RangedPtr; using mozilla::Variant; +template +using Vector = mozilla::Vector; + /*** ubi::StackFrame ******************************************************************************/ // Concrete JS::ubi::StackFrame instances backed by a live SavedFrame object diff --git a/js/public/UbiNodeDominatorTree.h b/js/public/UbiNodeDominatorTree.h index 8a5bfc2a7419..9231e8ca8c02 100644 --- a/js/public/UbiNodeDominatorTree.h +++ b/js/public/UbiNodeDominatorTree.h @@ -94,10 +94,10 @@ class JS_PUBLIC_API(DominatorTree) { friend class DominatedSetRange; - const mozilla::Vector& postOrder; + const JS::ubi::Vector& postOrder; const uint32_t* ptr; - DominatedNodePtr(const mozilla::Vector& postOrder, const uint32_t* ptr) + DominatedNodePtr(const JS::ubi::Vector& postOrder, const uint32_t* ptr) : postOrder(postOrder) , ptr(ptr) { } @@ -118,11 +118,11 @@ class JS_PUBLIC_API(DominatorTree) { friend class DominatedSets; - const mozilla::Vector& postOrder; + const JS::ubi::Vector& postOrder; const uint32_t* beginPtr; const uint32_t* endPtr; - DominatedSetRange(mozilla::Vector& postOrder, const uint32_t* begin, const uint32_t* end) + DominatedSetRange(JS::ubi::Vector& postOrder, const uint32_t* begin, const uint32_t* end) : postOrder(postOrder) , beginPtr(begin) , endPtr(end) @@ -179,10 +179,10 @@ class JS_PUBLIC_API(DominatorTree) */ class DominatedSets { - mozilla::Vector dominated; - mozilla::Vector indices; + JS::ubi::Vector dominated; + JS::ubi::Vector indices; - DominatedSets(mozilla::Vector&& dominated, mozilla::Vector&& indices) + DominatedSets(JS::ubi::Vector&& dominated, JS::ubi::Vector&& indices) : dominated(mozilla::Move(dominated)) , indices(mozilla::Move(indices)) { } @@ -210,7 +210,7 @@ class JS_PUBLIC_API(DominatorTree) * immediate dominator. Returns `Some` on success, `Nothing` on OOM * failure. */ - static mozilla::Maybe Create(const mozilla::Vector& doms) { + static mozilla::Maybe Create(const JS::ubi::Vector& doms) { auto length = doms.length(); MOZ_ASSERT(length < UINT32_MAX); @@ -235,8 +235,8 @@ class JS_PUBLIC_API(DominatorTree) // filled in. After having filled in all of a bucket's entries, // the index points to the start of the bucket. - mozilla::Vector dominated; - mozilla::Vector indices; + JS::ubi::Vector dominated; + JS::ubi::Vector indices; if (!dominated.growBy(length) || !indices.growBy(length)) return mozilla::Nothing(); @@ -278,7 +278,7 @@ class JS_PUBLIC_API(DominatorTree) * Get the set of nodes immediately dominated by the node at * `postOrder[nodeIndex]`. */ - DominatedSetRange dominatedSet(mozilla::Vector& postOrder, uint32_t nodeIndex) const { + DominatedSetRange dominatedSet(JS::ubi::Vector& postOrder, uint32_t nodeIndex) const { MOZ_ASSERT(postOrder.length() == indices.length()); MOZ_ASSERT(nodeIndex < indices.length()); auto end = nodeIndex == indices.length() - 1 @@ -290,11 +290,11 @@ class JS_PUBLIC_API(DominatorTree) private: // Data members. - mozilla::Vector postOrder; + JS::ubi::Vector postOrder; NodeToIndexMap nodeToPostOrderIndex; - mozilla::Vector doms; + JS::ubi::Vector doms; DominatedSets dominatedSets; - mozilla::Maybe> retainedSizes; + mozilla::Maybe> retainedSizes; private: // We use `UNDEFINED` as a sentinel value in the `doms` vector to signal @@ -302,8 +302,8 @@ class JS_PUBLIC_API(DominatorTree) // index in `postOrder` yet. static const uint32_t UNDEFINED = UINT32_MAX; - DominatorTree(mozilla::Vector&& postOrder, NodeToIndexMap&& nodeToPostOrderIndex, - mozilla::Vector&& doms, DominatedSets&& dominatedSets) + DominatorTree(JS::ubi::Vector&& postOrder, NodeToIndexMap&& nodeToPostOrderIndex, + JS::ubi::Vector&& doms, DominatedSets&& dominatedSets) : postOrder(mozilla::Move(postOrder)) , nodeToPostOrderIndex(mozilla::Move(nodeToPostOrderIndex)) , doms(mozilla::Move(doms)) @@ -311,7 +311,7 @@ class JS_PUBLIC_API(DominatorTree) , retainedSizes(mozilla::Nothing()) { } - static uint32_t intersect(mozilla::Vector& doms, uint32_t finger1, uint32_t finger2) { + static uint32_t intersect(JS::ubi::Vector& doms, uint32_t finger1, uint32_t finger2) { while (finger1 != finger2) { if (finger1 < finger2) finger1 = doms[finger1]; @@ -324,7 +324,7 @@ class JS_PUBLIC_API(DominatorTree) // 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& postOrder, + JS::ubi::Vector& postOrder, PredecessorSets& predecessorSets) { uint32_t nodeCount = 0; auto onNode = [&](const Node& node) { @@ -357,7 +357,7 @@ class JS_PUBLIC_API(DominatorTree) // Populates the given `map` with an entry for each node to its index in // `postOrder`. - static MOZ_MUST_USE bool mapNodesToTheirIndices(mozilla::Vector& postOrder, + static MOZ_MUST_USE bool mapNodesToTheirIndices(JS::ubi::Vector& postOrder, NodeToIndexMap& map) { MOZ_ASSERT(!map.initialized()); MOZ_ASSERT(postOrder.length() < UINT32_MAX); @@ -373,10 +373,10 @@ class JS_PUBLIC_API(DominatorTree) // form. static MOZ_MUST_USE bool convertPredecessorSetsToVectors( const Node& root, - mozilla::Vector& postOrder, + JS::ubi::Vector& postOrder, PredecessorSets& predecessorSets, NodeToIndexMap& nodeToPostOrderIndex, - mozilla::Vector>& predecessorVectors) + JS::ubi::Vector>& predecessorVectors) { MOZ_ASSERT(postOrder.length() < UINT32_MAX); uint32_t length = postOrder.length(); @@ -410,7 +410,7 @@ class JS_PUBLIC_API(DominatorTree) // 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& doms, + static MOZ_MUST_USE bool initializeDominators(JS::ubi::Vector& doms, uint32_t length) { MOZ_ASSERT(doms.length() == 0); if (!doms.growByUninitialized(length)) @@ -514,7 +514,7 @@ class JS_PUBLIC_API(DominatorTree) */ static mozilla::Maybe Create(JSRuntime* rt, AutoCheckCannotGC& noGC, const Node& root) { - mozilla::Vector postOrder; + JS::ubi::Vector postOrder; PredecessorSets predecessorSets; if (!predecessorSets.init() || !doTraversal(rt, noGC, root, postOrder, predecessorSets)) return mozilla::Nothing(); @@ -533,12 +533,12 @@ class JS_PUBLIC_API(DominatorTree) if (!mapNodesToTheirIndices(postOrder, nodeToPostOrderIndex)) return mozilla::Nothing(); - mozilla::Vector> predecessorVectors; + JS::ubi::Vector> predecessorVectors; if (!convertPredecessorSetsToVectors(root, postOrder, predecessorSets, nodeToPostOrderIndex, predecessorVectors)) return mozilla::Nothing(); - mozilla::Vector doms; + JS::ubi::Vector doms; if (!initializeDominators(doms, length)) return mozilla::Nothing(); diff --git a/js/public/UbiNodeShortestPaths.h b/js/public/UbiNodeShortestPaths.h index 9a46b013044a..1e554c8a6e24 100644 --- a/js/public/UbiNodeShortestPaths.h +++ b/js/public/UbiNodeShortestPaths.h @@ -69,7 +69,7 @@ struct JS_PUBLIC_API(BackEdge) /** * A path is a series of back edges from which we discovered a target node. */ -using Path = mozilla::Vector; +using Path = JS::ubi::Vector; /** * The `JS::ubi::ShortestPaths` type represents a collection of up to N shortest @@ -81,7 +81,7 @@ struct JS_PUBLIC_API(ShortestPaths) private: // Types, type aliases, and data members. - using BackEdgeVector = mozilla::Vector; + using BackEdgeVector = JS::ubi::Vector; using NodeToBackEdgeVectorMap = js::HashMap, js::SystemAllocPolicy>; diff --git a/js/src/builtin/TestingFunctions.cpp b/js/src/builtin/TestingFunctions.cpp index fb03b7db9ed4..9b28db277c02 100644 --- a/js/src/builtin/TestingFunctions.cpp +++ b/js/src/builtin/TestingFunctions.cpp @@ -2662,11 +2662,16 @@ FindPath(JSContext* cx, unsigned argc, Value* vp) 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. @@ -3349,6 +3354,11 @@ SetGCCallback(JSContext* cx, unsigned argc, Value* vp) if (strcmp(action.ptr(), "minorGC") == 0) { auto info = js_new(); + if (!info) { + ReportOutOfMemory(cx); + return false; + } + info->phases = phases; info->active = true; JS_SetGCCallback(cx->runtime(), gcCallback::minorGC, info); @@ -3366,6 +3376,11 @@ SetGCCallback(JSContext* cx, unsigned argc, Value* vp) } auto info = js_new(); + if (!info) { + ReportOutOfMemory(cx); + return false; + } + info->phases = phases; info->depth = depth; JS_SetGCCallback(cx->runtime(), gcCallback::majorGC, info); diff --git a/js/src/ds/LifoAlloc.h b/js/src/ds/LifoAlloc.h index fd9f6b5fa640..b3aac5deea5b 100644 --- a/js/src/ds/LifoAlloc.h +++ b/js/src/ds/LifoAlloc.h @@ -162,6 +162,9 @@ class LifoAlloc 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; @@ -231,6 +234,9 @@ class LifoAlloc public: explicit LifoAlloc(size_t defaultChunkSize) : peakSize_(0) +#if defined(DEBUG) || defined(JS_OOM_BREAKPOINT) + , fallibleScope_(true) +#endif { reset(defaultChunkSize); } @@ -270,19 +276,17 @@ class LifoAlloc 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; @@ -290,16 +294,12 @@ class LifoAlloc 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(); @@ -314,6 +314,36 @@ class LifoAlloc 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 T* newArray(size_t count) { static_assert(mozilla::IsPod::value, @@ -499,6 +529,7 @@ class MOZ_NON_TEMPORARY_CLASS LifoAllocScope { LifoAlloc* lifoAlloc; LifoAlloc::Mark mark; + LifoAlloc::AutoFallibleScope fallibleScope; bool shouldRelease; MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER @@ -507,6 +538,7 @@ class MOZ_NON_TEMPORARY_CLASS LifoAllocScope MOZ_GUARD_OBJECT_NOTIFIER_PARAM) : lifoAlloc(lifoAlloc), mark(lifoAlloc->mark()), + fallibleScope(lifoAlloc), shouldRelease(true) { MOZ_GUARD_OBJECT_NOTIFIER_INIT; diff --git a/js/src/frontend/Parser.cpp b/js/src/frontend/Parser.cpp index 1361b6a96ec0..090d3a029eee 100644 --- a/js/src/frontend/Parser.cpp +++ b/js/src/frontend/Parser.cpp @@ -9352,7 +9352,12 @@ Parser::objectLiteral(YieldHandling yieldHandling, PossibleError* 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(); diff --git a/js/src/gc/Statistics.cpp b/js/src/gc/Statistics.cpp index 2952e1cbcc7b..ad8a34f2eb6a 100644 --- a/js/src/gc/Statistics.cpp +++ b/js/src/gc/Statistics.cpp @@ -194,13 +194,13 @@ 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 dagDescendants[Statistics::NumTimingArrays]; +static mozilla::Vector dagDescendants[Statistics::NumTimingArrays]; struct AllPhaseIterator { int current; int baseLevel; size_t activeSlot; - mozilla::Vector::Range descendants; + mozilla::Vector::Range descendants; explicit AllPhaseIterator(const Statistics::PhaseTimeTable table) : current(0) @@ -829,7 +829,7 @@ Statistics::initialize() // Fill in the depth of each node in the tree. Multi-parented nodes // have depth 0. - mozilla::Vector stack; + mozilla::Vector 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++) { diff --git a/js/src/irregexp/RegExpEngine.cpp b/js/src/irregexp/RegExpEngine.cpp index ac02c047e33d..27ed71f9893d 100644 --- a/js/src/irregexp/RegExpEngine.cpp +++ b/js/src/irregexp/RegExpEngine.cpp @@ -1720,6 +1720,12 @@ RegExpCompiler::Assemble(JSContext* cx, 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; diff --git a/js/src/jit-test/tests/gc/bug-1280588.js b/js/src/jit-test/tests/gc/bug-1280588.js new file mode 100644 index 000000000000..c12aed2c217c --- /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" })); diff --git a/js/src/jit-test/tests/gc/oomInByteSize.js b/js/src/jit-test/tests/gc/oomInByteSize.js new file mode 100644 index 000000000000..51c856e479ca --- /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)); diff --git a/js/src/jit-test/tests/gc/oomInFindPath.js b/js/src/jit-test/tests/gc/oomInFindPath.js new file mode 100644 index 000000000000..5495791b9736 --- /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)); diff --git a/js/src/jit-test/tests/ion/bug1264948-1.js b/js/src/jit-test/tests/ion/bug1264948-1.js new file mode 100644 index 000000000000..1070275dce1d --- /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)); +} diff --git a/js/src/jit-test/tests/ion/bug1264948.js b/js/src/jit-test/tests/ion/bug1264948.js new file mode 100644 index 000000000000..833188aaab54 --- /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)); +} diff --git a/js/src/jit-test/tests/ion/bug1269756.js b/js/src/jit-test/tests/ion/bug1269756.js new file mode 100644 index 000000000000..5555e5f14d68 --- /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(); +}) diff --git a/js/src/jit/IonBuilder.cpp b/js/src/jit/IonBuilder.cpp index 934fa7fca90f..bec4c1e7ec33 100644 --- a/js/src/jit/IonBuilder.cpp +++ b/js/src/jit/IonBuilder.cpp @@ -766,7 +766,13 @@ IonBuilder::pushLoop(CFGState::State initial, jsbytecode* stopAt, MBasicBlock* e 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_) { @@ -1408,6 +1414,9 @@ IonBuilder::maybeAddOsrTypeBarriers() 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(); diff --git a/js/src/jit/JitAllocPolicy.h b/js/src/jit/JitAllocPolicy.h index 5e2c1027c691..880246313d47 100644 --- a/js/src/jit/JitAllocPolicy.h +++ b/js/src/jit/JitAllocPolicy.h @@ -34,15 +34,18 @@ class TempAllocator 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; @@ -50,8 +53,9 @@ class TempAllocator } template - T* allocateArray(size_t n) + MOZ_MUST_USE T* allocateArray(size_t n) { + LifoAlloc::AutoFallibleScope fallibleAllocator(lifoAlloc()); size_t bytes; if (MOZ_UNLIKELY(!CalculateAllocSize(n, &bytes))) return nullptr; @@ -65,12 +69,12 @@ class TempAllocator 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); } }; @@ -150,7 +154,7 @@ class AutoJitContextAlloc 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) { diff --git a/js/src/jit/MCallOptimize.cpp b/js/src/jit/MCallOptimize.cpp index 8f706029abd2..43eddecfbc50 100644 --- a/js/src/jit/MCallOptimize.cpp +++ b/js/src/jit/MCallOptimize.cpp @@ -526,6 +526,8 @@ IonBuilder::inlineArray(CallInfo& callInfo) 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; diff --git a/js/src/jit/MIR.h b/js/src/jit/MIR.h index 559f8352cc66..8ac4e553eca0 100644 --- a/js/src/jit/MIR.h +++ b/js/src/jit/MIR.h @@ -7156,6 +7156,9 @@ class MPhi final 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(); diff --git a/js/src/jit/MIRGraph.cpp b/js/src/jit/MIRGraph.cpp index 76d95e53c174..cb13a2aaa55e 100644 --- a/js/src/jit/MIRGraph.cpp +++ b/js/src/jit/MIRGraph.cpp @@ -558,7 +558,9 @@ MBasicBlock::inherit(TempAllocator& alloc, BytecodeAnalysis* analysis, MBasicBlo 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); @@ -578,7 +580,9 @@ MBasicBlock::inherit(TempAllocator& alloc, BytecodeAnalysis* analysis, MBasicBlo } 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); @@ -1193,9 +1197,11 @@ MBasicBlock::addPredecessorPopN(TempAllocator& alloc, MBasicBlock* pred, uint32_ // 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 diff --git a/js/src/jit/mips32/Assembler-mips32.cpp b/js/src/jit/mips32/Assembler-mips32.cpp index ba75583f1bc4..81fc8c97f93b 100644 --- a/js/src/jit/mips32/Assembler-mips32.cpp +++ b/js/src/jit/mips32/Assembler-mips32.cpp @@ -456,5 +456,5 @@ Assembler::UpdateBoundsCheck(uint8_t* patchAt, uint32_t heapLength) InstImm* i1 = (InstImm*) i0->next(); // Replace with new value - Assembler::UpdateLuiOriValue(i0, i1, heapSize); + Assembler::UpdateLuiOriValue(i0, i1, heapLength); } diff --git a/js/src/jit/mips64/Architecture-mips64.h b/js/src/jit/mips64/Architecture-mips64.h index 21e7efd1dff6..6606f6d9dd57 100644 --- a/js/src/jit/mips64/Architecture-mips64.h +++ b/js/src/jit/mips64/Architecture-mips64.h @@ -59,6 +59,7 @@ class FloatRegisters : public FloatRegistersMIPSShared 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 = diff --git a/js/src/jsapi-tests/testThreadingThread.cpp b/js/src/jsapi-tests/testThreadingThread.cpp index 1de02c91e99f..000a1b6bd85c 100644 --- a/js/src/jsapi-tests/testThreadingThread.cpp +++ b/js/src/jsapi-tests/testThreadingThread.cpp @@ -9,6 +9,9 @@ #include "mozilla/IntegerRange.h" #include "mozilla/Move.h" #include "mozilla/Vector.h" + +#include "jsalloc.h" + #include "jsapi-tests/tests.h" #include "threading/Thread.h" @@ -62,7 +65,7 @@ BEGIN_TEST(testThreadingThreadVectorMoveConstruct) { const static size_t N = 10; mozilla::Atomic count(0); - mozilla::Vector v; + mozilla::Vector v; for (auto i : mozilla::MakeRange(N)) { CHECK(v.emplaceBack([](mozilla::Atomic* countp){(*countp)++;}, &count)); CHECK(v.length() == i + 1); diff --git a/js/src/jsapi.h b/js/src/jsapi.h index dfca8526ac84..c461d62f895c 100644 --- a/js/src/jsapi.h +++ b/js/src/jsapi.h @@ -6150,6 +6150,8 @@ struct PerformanceGroup { uint64_t refCount_; }; +using PerformanceGroupVector = mozilla::Vector, 0, SystemAllocPolicy>; + /** * Commit any Performance Monitoring data. * @@ -6208,12 +6210,12 @@ extern JS_PUBLIC_API(bool) SetStopwatchStartCallback(JSRuntime*, StopwatchStartCallback, void*); typedef bool -(*StopwatchCommitCallback)(uint64_t, mozilla::Vector>&, void*); +(*StopwatchCommitCallback)(uint64_t, PerformanceGroupVector&, void*); extern JS_PUBLIC_API(bool) SetStopwatchCommitCallback(JSRuntime*, StopwatchCommitCallback, void*); typedef bool -(*GetGroupsCallback)(JSContext*, mozilla::Vector>&, void*); +(*GetGroupsCallback)(JSContext*, PerformanceGroupVector&, void*); extern JS_PUBLIC_API(bool) SetGetPerformanceGroupsCallback(JSRuntime*, GetGroupsCallback, void*); diff --git a/js/src/jsgc.cpp b/js/src/jsgc.cpp index 2ac106f8a52c..138a7b6532b7 100644 --- a/js/src/jsgc.cpp +++ b/js/src/jsgc.cpp @@ -972,7 +972,7 @@ GCRuntime::parseAndSetZeal(const char* str) { int frequency = -1; bool foundFrequency = false; - mozilla::Vector zeals; + mozilla::Vector zeals; static const struct { const char* const zealMode; @@ -2643,8 +2643,9 @@ GCRuntime::releaseHeldRelocatedArenas() { #ifdef DEBUG unprotectHeldRelocatedArenas(); - releaseRelocatedArenas(relocatedArenasToRelease); + Arena* arenas = relocatedArenasToRelease; relocatedArenasToRelease = nullptr; + releaseRelocatedArenas(arenas); #endif } @@ -3134,7 +3135,7 @@ GCRuntime::decommitArenas(AutoLockGC& lock) // 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 toDecommit; + mozilla::Vector toDecommit; MOZ_ASSERT(availableChunks(lock).verify()); for (ChunkPool::Iter iter(availableChunks(lock)); !iter.done(); iter.next()) { if (!toDecommit.append(iter.get())) { diff --git a/js/src/old-configure.in b/js/src/old-configure.in index 581cd7c0a96c..b413de302fd5 100644 --- a/js/src/old-configure.in +++ b/js/src/old-configure.in @@ -2432,7 +2432,6 @@ 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) diff --git a/js/src/shell/js.cpp b/js/src/shell/js.cpp index 418c79ed5999..2d9c545b314d 100644 --- a/js/src/shell/js.cpp +++ b/js/src/shell/js.cpp @@ -5222,8 +5222,8 @@ WasmLoop(JSContext* cx, unsigned argc, Value* vp) return false; Rooted typedArray(cx, &ret->as()); - 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(); } diff --git a/js/src/tests/ecma_6/Object/destructuring-shorthand-defaults.js b/js/src/tests/ecma_6/Object/destructuring-shorthand-defaults.js index 09adc7719977..879ff33f2954 100644 --- a/js/src/tests/ecma_6/Object/destructuring-shorthand-defaults.js +++ b/js/src/tests/ecma_6/Object/destructuring-shorthand-defaults.js @@ -123,5 +123,14 @@ assertEq((({a = 0} = {}) => a)({a: 1}), 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); diff --git a/js/src/vm/Stopwatch.cpp b/js/src/vm/Stopwatch.cpp index 989a08b0554a..19bea239ccd1 100644 --- a/js/src/vm/Stopwatch.cpp +++ b/js/src/vm/Stopwatch.cpp @@ -152,7 +152,7 @@ PerformanceMonitoring::commit() return true; } - GroupVector recentGroups; + PerformanceGroupVector recentGroups; recentGroups_.swap(recentGroups); bool success = true; @@ -200,7 +200,7 @@ PerformanceGroupHolder::unlink() groups_.clear(); } -const GroupVector* +const PerformanceGroupVector* PerformanceGroupHolder::getGroups(JSContext* cx) { if (initialized_) @@ -233,7 +233,7 @@ AutoStopwatch::AutoStopwatch(JSContext* cx MOZ_GUARD_OBJECT_NOTIFIER_PARAM_IN_IM 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 diff --git a/js/src/vm/Stopwatch.h b/js/src/vm/Stopwatch.h index ad8322b32647..a1b8bbbcb3db 100644 --- a/js/src/vm/Stopwatch.h +++ b/js/src/vm/Stopwatch.h @@ -19,8 +19,6 @@ namespace js { -typedef mozilla::Vector> GroupVector; - /** * A container for performance groups. * @@ -43,7 +41,7 @@ struct PerformanceGroupHolder { * 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) @@ -59,7 +57,7 @@ struct PerformanceGroupHolder { // The groups to which this compartment belongs. Filled if and only // if `initialized_` is `true`. - GroupVector groups_; + PerformanceGroupVector groups_; }; /** @@ -292,7 +290,7 @@ struct PerformanceMonitoring { /** * Groups used in the current iteration. */ - GroupVector recentGroups_; + PerformanceGroupVector recentGroups_; /** * The highest value of the timestamp counter encountered @@ -344,7 +342,7 @@ class AutoStopwatch final { // if `isMonitoringJank_` is `true`. cpuid_t cpuStart_; - mozilla::Vector> groups_; + PerformanceGroupVector groups_; public: // If the stopwatch is active, constructing an instance of diff --git a/js/src/vm/UbiNodeCensus.cpp b/js/src/vm/UbiNodeCensus.cpp index 781f7f786a78..af6a18ed8a6c 100644 --- a/js/src/vm/UbiNodeCensus.cpp +++ b/js/src/vm/UbiNodeCensus.cpp @@ -127,7 +127,7 @@ SimpleCount::report(JSContext* cx, CountBase& countBase, MutableHandleValue repo class BucketCount : public CountType { struct Count : CountBase { - mozilla::Vector ids_; + JS::ubi::Vector ids_; explicit Count(BucketCount& count) : CountBase(count), @@ -349,7 +349,7 @@ countMapToObject(JSContext* cx, Map& map, GetName getName) { // that to build the result object. This makes the ordering of entries // more interesting, and a little less non-deterministic. - mozilla::Vector entries; + JS::ubi::Vector entries; if (!entries.reserve(map.count())) { ReportOutOfMemory(cx); return nullptr; @@ -570,7 +570,7 @@ ByUbinodeType::report(JSContext* cx, CountBase& countBase, MutableHandleValue re // 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 entries; + JS::ubi::Vector entries; if (!entries.reserve(count.table.count())) return false; for (Table::Range r = count.table.all(); !r.empty(); r.popFront()) @@ -736,7 +736,7 @@ ByAllocationStack::report(JSContext* cx, CountBase& countBase, MutableHandleValu // 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 entries; + JS::ubi::Vector entries; if (!entries.reserve(count.table.count())) return false; for (Table::Range r = count.table.all(); !r.empty(); r.popFront()) diff --git a/layout/base/nsCSSRenderingBorders.cpp b/layout/base/nsCSSRenderingBorders.cpp index cc60c4fcff58..513fc5004a07 100644 --- a/layout/base/nsCSSRenderingBorders.cpp +++ b/layout/base/nsCSSRenderingBorders.cpp @@ -32,6 +32,8 @@ using namespace mozilla; using namespace mozilla::gfx; +#define MAX_COMPOSITE_BORDER_WIDTH LayoutDeviceIntCoord(10000) + /** * nsCSSRendering::PaintBorder * nsCSSRendering::PaintOutline @@ -1373,9 +1375,16 @@ nsCSSBorderRenderer::DrawBorderSides(int aSides) // 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 diff --git a/layout/base/nsRefreshDriver.cpp b/layout/base/nsRefreshDriver.cpp index a45c4d0062da..29b97cd34f8e 100644 --- a/layout/base/nsRefreshDriver.cpp +++ b/layout/base/nsRefreshDriver.cpp @@ -1876,7 +1876,7 @@ nsRefreshDriver::Tick(int64_t aNowEpoch, TimeStamp aNowTime) MOZ_ASSERT(req, "Unable to retrieve the image request"); nsCOMPtr image; if (NS_SUCCEEDED(req->GetImage(getter_AddRefs(image)))) { - imagesToRefresh.AppendElement(image); + imagesToRefresh.AppendElement(image.forget()); } } diff --git a/layout/generic/nsGridContainerFrame.cpp b/layout/generic/nsGridContainerFrame.cpp index c5541fca582e..de371cb6bcda 100644 --- a/layout/generic/nsGridContainerFrame.cpp +++ b/layout/generic/nsGridContainerFrame.cpp @@ -1081,6 +1081,7 @@ 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; @@ -1482,8 +1483,9 @@ struct nsGridContainerFrame::Tracks * 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 { @@ -1554,6 +1556,15 @@ struct nsGridContainerFrame::Tracks } } + 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 { @@ -1574,6 +1585,8 @@ struct nsGridContainerFrame::Tracks // 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; }; /** @@ -1815,6 +1828,8 @@ private: } }; +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. @@ -2199,6 +2214,9 @@ nsGridContainerFrame::GridReflowState::CalculateTrackSizes( 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, @@ -3394,7 +3412,7 @@ MeasuringReflow(nsIFrame* aChild, */ static nscoord ContentContribution(const GridItemInfo& aGridItem, - const nsHTMLReflowState* aReflowState, + const GridReflowState& aState, nsRenderingContext* aRC, WritingMode aCBWM, LogicalAxis aAxis, @@ -3408,8 +3426,19 @@ ContentContribution(const GridItemInfo& aGridItem, 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); @@ -3424,33 +3453,33 @@ ContentContribution(const GridItemInfo& aGridItem, } 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)); @@ -3477,7 +3506,7 @@ MinSize(const GridItemInfo& aGridItem, 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)); } @@ -3552,26 +3581,25 @@ nsGridContainerFrame::Tracks::ResolveIntrinsicSizeStep1( // 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) { @@ -3582,7 +3610,7 @@ nsGridContainerFrame::Tracks::ResolveIntrinsicSizeStep1( } 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) { @@ -3924,18 +3952,18 @@ nsGridContainerFrame::Tracks::ResolveIntrinsicSize( 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( @@ -4189,7 +4217,6 @@ nsGridContainerFrame::Tracks::FindUsedFlexFraction( } 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 @@ -4197,7 +4224,7 @@ nsGridContainerFrame::Tracks::FindUsedFlexFraction( 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; } @@ -4253,7 +4280,8 @@ nsGridContainerFrame::Tracks::StretchFlexibleTracks( void nsGridContainerFrame::Tracks::AlignJustifyContent( - const nsHTMLReflowState& aReflowState, + const nsStylePosition* aStyle, + WritingMode aWM, const LogicalSize& aContainerSize) { if (mSizes.IsEmpty()) { @@ -4261,12 +4289,10 @@ nsGridContainerFrame::Tracks::AlignJustifyContent( } 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, @@ -4286,13 +4312,13 @@ nsGridContainerFrame::Tracks::AlignJustifyContent( ++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; @@ -5543,8 +5569,8 @@ nsGridContainerFrame::Reflow(nsPresContext* aPresContext, 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); diff --git a/layout/generic/nsGridContainerFrame.h b/layout/generic/nsGridContainerFrame.h index 88c2e62df384..d0cdbe905d07 100644 --- a/layout/generic/nsGridContainerFrame.h +++ b/layout/generic/nsGridContainerFrame.h @@ -107,6 +107,7 @@ public: struct TrackSize; struct GridItemInfo; + struct GridReflowState; protected: static const uint32_t kAutoLine; // The maximum line number, in the zero-based translated grid. @@ -121,7 +122,6 @@ protected: struct Grid; struct GridArea; class GridItemCSSOrderIterator; - struct GridReflowState; class LineNameMap; struct LineRange; struct SharedGridData; diff --git a/layout/generic/nsTextFrame.cpp b/layout/generic/nsTextFrame.cpp index fac9db55bb3a..1791f8711ebf 100644 --- a/layout/generic/nsTextFrame.cpp +++ b/layout/generic/nsTextFrame.cpp @@ -5518,9 +5518,7 @@ nsTextFrame::DrawSelectionDecorations(gfxContext* aContext, 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; @@ -5533,34 +5531,42 @@ nsTextFrame::DrawSelectionDecorations(gfxContext* aContext, aFontMetrics); float relativeSize; - int32_t index = - nsTextPaintStyle::GetUnderlineStyleIndexForSelectionType(aSelectionType); - bool weDefineSelectionUnderline = - aTextPaintStyle.GetSelectionUnderlineForPaint(index, ¶ms.color, - &relativeSize, ¶ms.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, ¶ms.color, + &relativeSize, + ¶ms.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) { @@ -5600,10 +5606,6 @@ nsTextFrame::DrawSelectionDecorations(gfxContext* aContext, } break; } - case SelectionType::eSpellCheck: - if (!weDefineSelectionUnderline) - return; - break; case SelectionType::eURLStrikeout: { nscoord inflationMinFontSize = nsLayoutUtils::InflationMinFontSizeFor(this); @@ -5613,6 +5615,9 @@ nsTextFrame::DrawSelectionDecorations(gfxContext* aContext, GetFirstFontMetrics(GetFontGroupForFrame(this, inflation), aVertical); relativeSize = 2.0f; + aTextPaintStyle.GetURLSecondaryColor(¶ms.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; @@ -7076,7 +7081,9 @@ nsTextFrame::CombineSelectionUnderlineRect(nsPresContext* aPresContext, 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; } diff --git a/layout/inspector/inDOMView.cpp b/layout/inspector/inDOMView.cpp index eee24ed6d933..6755b31b5832 100644 --- a/layout/inspector/inDOMView.cpp +++ b/layout/inspector/inDOMView.cpp @@ -1262,7 +1262,7 @@ inDOMView::AppendKidsToArray(nsIDOMNodeList* aKids, } } - aArray.AppendObject(kid); + aArray.AppendElement(kid.forget()); } } @@ -1278,7 +1278,7 @@ inDOMView::AppendAttrsToArray(nsIDOMMozNamedAttrMap* aAttributes, nsCOMPtr 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; } diff --git a/layout/style/nsStyleContext.cpp b/layout/style/nsStyleContext.cpp index f91f72e1c3d2..6d267aa8d445 100644 --- a/layout/style/nsStyleContext.cpp +++ b/layout/style/nsStyleContext.cpp @@ -896,7 +896,7 @@ nsStyleContext::ApplyStyleFixups(bool aSkipParentDisplayBasedStyleFixup) } nsChangeHint -nsStyleContext::CalcStyleDifference(nsStyleContext* aOther, +nsStyleContext::CalcStyleDifference(nsStyleContext* aNewContext, nsChangeHint aParentHintsNotHandledForDescendants, uint32_t* aEqualStructs, uint32_t* aSamePointerStructs) @@ -914,7 +914,7 @@ nsStyleContext::CalcStyleDifference(nsStyleContext* aOther, *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 @@ -937,7 +937,7 @@ nsStyleContext::CalcStyleDifference(nsStyleContext* aOther, // (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 structsFound = 0; @@ -947,7 +947,7 @@ nsStyleContext::CalcStyleDifference(nsStyleContext* aOther, 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 { @@ -964,7 +964,7 @@ nsStyleContext::CalcStyleDifference(nsStyleContext* aOther, 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(); \ @@ -1065,7 +1065,7 @@ nsStyleContext::CalcStyleDifference(nsStyleContext* aOther, #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_); \ } \ } @@ -1073,7 +1073,7 @@ nsStyleContext::CalcStyleDifference(nsStyleContext* aOther, #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 @@ -1089,7 +1089,7 @@ nsStyleContext::CalcStyleDifference(nsStyleContext* aOther, // 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. diff --git a/layout/style/nsStyleContext.h b/layout/style/nsStyleContext.h index 1788816da22b..bd2b2d2fea0a 100644 --- a/layout/style/nsStyleContext.h +++ b/layout/style/nsStyleContext.h @@ -376,7 +376,7 @@ public: /** * 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.) * @@ -393,7 +393,7 @@ public: * 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); diff --git a/layout/style/nsStyleStruct.cpp b/layout/style/nsStyleStruct.cpp index 106d85a10407..ed23b6edddba 100644 --- a/layout/style/nsStyleStruct.cpp +++ b/layout/style/nsStyleStruct.cpp @@ -184,26 +184,26 @@ nsStyleFont::EnableZoom(nsPresContext* aContext, bool aEnable) } 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; } @@ -280,9 +280,9 @@ nsStyleMargin::Destroy(nsPresContext* aContext) { } 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 @@ -315,9 +315,9 @@ nsStylePadding::Destroy(nsPresContext* aContext) { } 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 @@ -451,15 +451,15 @@ nsStyleBorder::Destroy(nsPresContext* aContext) { } 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) { @@ -468,7 +468,7 @@ nsStyleBorder::CalcDifference(const nsStyleBorder& aOther) const // 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; } @@ -480,32 +480,32 @@ nsStyleBorder::CalcDifference(const nsStyleBorder& aOther) const // 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; } } @@ -513,7 +513,7 @@ nsStyleBorder::CalcDifference(const nsStyleBorder& aOther) const // 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; } @@ -568,27 +568,27 @@ nsStyleOutline::RecalcData() } 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; } @@ -673,24 +673,24 @@ nsStyleList::GetQuotePairs() const } 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; @@ -736,17 +736,17 @@ nsStyleXUL::nsStyleXUL(const nsStyleXUL& aSource) } 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; } @@ -791,31 +791,31 @@ nsStyleColumn::nsStyleColumn(const nsStyleColumn& aSource) } 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; } @@ -891,13 +891,13 @@ PaintURIChanged(const nsStyleSVGPaint& aPaint1, const nsStyleSVGPaint& aPaint2) } 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. @@ -907,13 +907,13 @@ nsStyleSVG::CalcDifference(const nsStyleSVG& aOther) const 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 @@ -923,8 +923,8 @@ nsStyleSVG::CalcDifference(const nsStyleSVG& aOther) const 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; } } @@ -934,11 +934,11 @@ nsStyleSVG::CalcDifference(const nsStyleSVG& aOther) const // 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 @@ -949,15 +949,15 @@ nsStyleSVG::CalcDifference(const nsStyleSVG& aOther) const 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; } @@ -1255,11 +1255,11 @@ nsStyleSVGReset::Destroy(nsPresContext* aContext) } 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, @@ -1267,10 +1267,10 @@ nsStyleSVGReset::CalcDifference(const nsStyleSVGReset& aOther) const 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:: @@ -1279,16 +1279,16 @@ nsStyleSVGReset::CalcDifference(const nsStyleSVGReset& aOther) const 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; } @@ -1483,26 +1483,26 @@ IsAutonessEqual(const nsStyleSides& aSides1, const nsStyleSides& aSides2) } 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, @@ -1514,7 +1514,7 @@ nsStylePosition::CalcDifference(const nsStylePosition& aOther, nsChangeHint_AllReflowHints; } - if (mBoxSizing != aOther.mBoxSizing) { + if (mBoxSizing != aNewData.mBoxSizing) { // Can affect both widths and heights; just a bad scene. return hint | nsChangeHint_AllReflowHints; @@ -1522,10 +1522,10 @@ nsStylePosition::CalcDifference(const nsStylePosition& aOther, // 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; } @@ -1536,9 +1536,9 @@ nsStylePosition::CalcDifference(const nsStylePosition& aOther, // 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; } @@ -1546,14 +1546,14 @@ nsStylePosition::CalcDifference(const nsStylePosition& aOther, // 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; } @@ -1561,36 +1561,36 @@ nsStylePosition::CalcDifference(const nsStylePosition& aOther, // 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 @@ -1637,8 +1637,8 @@ nsStylePosition::CalcDifference(const nsStylePosition& aOther, // 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 { @@ -1727,10 +1727,11 @@ nsStyleTable::nsStyleTable(const nsStyleTable& aSource) 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; } @@ -1764,20 +1765,20 @@ nsStyleTableBorder::nsStyleTableBorder(const nsStyleTableBorder& aSource) } 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; } @@ -1802,9 +1803,9 @@ nsStyleColor::nsStyleColor(const nsStyleColor& aSource) } 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; } @@ -2303,17 +2304,17 @@ nsStyleImageLayers::nsStyleImageLayers(const nsStyleImageLayers &aSource) } 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) { @@ -2338,16 +2339,16 @@ nsStyleImageLayers::CalcDifference(const nsStyleImageLayers& aOther, 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; } @@ -2594,29 +2595,29 @@ nsStyleImageLayers::Layer::operator==(const Layer& aOther) const } 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; } @@ -2658,14 +2659,14 @@ nsStyleBackground::Destroy(nsPresContext* aContext) } 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; @@ -2949,25 +2950,25 @@ nsStyleDisplay::nsStyleDisplay(const nsStyleDisplay& aSource) } 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, @@ -2983,9 +2984,9 @@ nsStyleDisplay::CalcDifference(const nsStyleDisplay& aOther) const */ 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 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 @@ -2995,14 +2996,14 @@ nsStyleDisplay::CalcDifference(const nsStyleDisplay& aOther) const 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; @@ -3010,24 +3011,24 @@ nsStyleDisplay::CalcDifference(const nsStyleDisplay& aOther) const // 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). @@ -3047,13 +3048,13 @@ nsStyleDisplay::CalcDifference(const nsStyleDisplay& aOther) const */ 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; @@ -3063,29 +3064,29 @@ nsStyleDisplay::CalcDifference(const nsStyleDisplay& aOther) const 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) { @@ -3097,13 +3098,13 @@ nsStyleDisplay::CalcDifference(const nsStyleDisplay& aOther) const } } - // 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)) { @@ -3116,7 +3117,7 @@ nsStyleDisplay::CalcDifference(const nsStyleDisplay& aOther) const // 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; } @@ -3138,24 +3139,24 @@ nsStyleDisplay::CalcDifference(const nsStyleDisplay& aOther) const // 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; } @@ -3192,35 +3193,35 @@ nsStyleVisibility::nsStyleVisibility(const nsStyleVisibility& aSource) } 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; } @@ -3409,7 +3410,7 @@ nsStyleContent::nsStyleContent(const nsStyleContent& aSource) } 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 @@ -3423,15 +3424,15 @@ nsStyleContent::CalcDifference(const nsStyleContent& aOther) const // '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 @@ -3440,19 +3441,19 @@ nsStyleContent::CalcDifference(const nsStyleContent& aOther) const } 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; @@ -3504,15 +3505,15 @@ nsStyleTextReset::~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 @@ -3526,12 +3527,12 @@ nsStyleTextReset::CalcDifference(const nsStyleTextReset& aOther) const 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; } @@ -3641,41 +3642,41 @@ nsStyleText::~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; @@ -3685,16 +3686,16 @@ nsStyleText::CalcDifference(const nsStyleText& aOther) const // 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; @@ -3704,16 +3705,16 @@ nsStyleText::CalcDifference(const nsStyleText& aOther) const } 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; } @@ -3722,7 +3723,7 @@ nsStyleText::CalcDifference(const nsStyleText& aOther) const return hint; } - if (mTextEmphasisPosition != aOther.mTextEmphasisPosition) { + if (mTextEmphasisPosition != aNewData.mTextEmphasisPosition) { return nsChangeHint_NeutralChange; } @@ -3814,18 +3815,18 @@ nsStyleUserInterface::~nsStyleUserInterface() } 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.) @@ -3833,19 +3834,19 @@ nsStyleUserInterface::CalcDifference(const nsStyleUserInterface& aOther) const 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; } @@ -3897,21 +3898,21 @@ nsStyleUIReset::~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; } @@ -3939,7 +3940,7 @@ nsStyleVariables::~nsStyleVariables() } nsChangeHint -nsStyleVariables::CalcDifference(const nsStyleVariables& aOther) const +nsStyleVariables::CalcDifference(const nsStyleVariables& aNewData) const { return nsChangeHint(0); } @@ -3975,11 +3976,11 @@ nsStyleEffects::~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 @@ -3989,50 +3990,50 @@ nsStyleEffects::CalcDifference(const nsStyleEffects& aOther) const 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; } diff --git a/layout/style/nsStyleStruct.h b/layout/style/nsStyleStruct.h index 36b96d25a0a0..37badd6a9c2e 100644 --- a/layout/style/nsStyleStruct.h +++ b/layout/style/nsStyleStruct.h @@ -119,7 +119,7 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS 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; @@ -387,7 +387,7 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleColor MOZ_COUNT_DTOR(nsStyleColor); } - nsChangeHint CalcDifference(const nsStyleColor& aOther) const; + nsChangeHint CalcDifference(const nsStyleColor& aNewData) const; static nsChangeHint MaxDifference() { return nsChangeHint_RepaintFrame; } @@ -692,7 +692,7 @@ struct nsStyleImageLayers { // 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 @@ -741,7 +741,7 @@ struct nsStyleImageLayers { mLayers[i].UntrackImages(aContext); } - nsChangeHint CalcDifference(const nsStyleImageLayers& aOther, + nsChangeHint CalcDifference(const nsStyleImageLayers& aNewLayers, nsChangeHint aPositionChangeHint) const; bool HasLayerWithImage() const; @@ -769,7 +769,7 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleBackground { } void Destroy(nsPresContext* aContext); - nsChangeHint CalcDifference(const nsStyleBackground& aOther) const; + nsChangeHint CalcDifference(const nsStyleBackground& aNewData) const; static nsChangeHint MaxDifference() { return nsChangeHint_UpdateEffects | nsChangeHint_RepaintFrame | @@ -825,7 +825,7 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleMargin } void Destroy(nsPresContext* aContext); - nsChangeHint CalcDifference(const nsStyleMargin& aOther) const; + nsChangeHint CalcDifference(const nsStyleMargin& aNewData) const; static nsChangeHint MaxDifference() { return nsChangeHint_NeedReflow | nsChangeHint_ReflowChangesSizeOrPosition | @@ -872,7 +872,7 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStylePadding } 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; } @@ -1074,7 +1074,7 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleBorder } 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 | @@ -1308,7 +1308,7 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleOutline } void RecalcData(); - nsChangeHint CalcDifference(const nsStyleOutline& aOther) const; + nsChangeHint CalcDifference(const nsStyleOutline& aNewData) const; static nsChangeHint MaxDifference() { return nsChangeHint_UpdateOverflow | nsChangeHint_SchedulePaint | @@ -1420,7 +1420,7 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleList 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; @@ -1645,7 +1645,7 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStylePosition 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 | @@ -1940,7 +1940,7 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleTextReset 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 | @@ -1981,7 +1981,7 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleText 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 | @@ -2200,7 +2200,7 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleVisibility 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; @@ -2481,7 +2481,7 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleDisplay 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 | @@ -2753,7 +2753,7 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleTable 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; } @@ -2786,7 +2786,7 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleTableBorder 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; } @@ -2882,7 +2882,7 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleContent } void Destroy(nsPresContext* aContext); - nsChangeHint CalcDifference(const nsStyleContent& aOther) const; + nsChangeHint CalcDifference(const nsStyleContent& aNewData) const; static nsChangeHint MaxDifference() { return NS_STYLE_HINT_FRAMECHANGE; } @@ -2997,7 +2997,7 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleUIReset 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; } @@ -3063,7 +3063,7 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleUserInterface 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 | @@ -3114,7 +3114,7 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleXUL 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; } @@ -3152,7 +3152,7 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleColumn 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; @@ -3249,7 +3249,7 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleSVG 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 | @@ -3577,7 +3577,7 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleSVGReset } void Destroy(nsPresContext* aContext); - nsChangeHint CalcDifference(const nsStyleSVGReset& aOther) const; + nsChangeHint CalcDifference(const nsStyleSVGReset& aNewData) const; static nsChangeHint MaxDifference() { return nsChangeHint_UpdateEffects | nsChangeHint_UpdateOverflow | @@ -3632,7 +3632,7 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleVariables FreeByObjectID(mozilla::eArenaObjectID_nsStyleVariables, this); } - nsChangeHint CalcDifference(const nsStyleVariables& aOther) const; + nsChangeHint CalcDifference(const nsStyleVariables& aNewData) const; static nsChangeHint MaxDifference() { return nsChangeHint(0); } @@ -3662,7 +3662,7 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleEffects 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 | diff --git a/media/libpng/CHANGES b/media/libpng/CHANGES index 8e589f64c5f3..0d6180ffad1d 100644 --- a/media/libpng/CHANGES +++ b/media/libpng/CHANGES @@ -5063,7 +5063,8 @@ Version 1.6.15beta04 [November 4, 2014] 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 @@ -5484,6 +5485,117 @@ Version 1.6.21rc02 [January 7, 2016] 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 diff --git a/media/libpng/LICENSE b/media/libpng/LICENSE index c8c835b8b880..b146475ad2c1 100644 --- a/media/libpng/LICENSE +++ b/media/libpng/LICENSE @@ -14,13 +14,13 @@ 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 @@ -42,6 +42,10 @@ and with the following additions to the disclaimer: 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 @@ -65,6 +69,9 @@ Contributing Authors: 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. @@ -105,18 +112,29 @@ 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 diff --git a/media/libpng/MOZCHANGES b/media/libpng/MOZCHANGES index cf3b0f26a527..43ab6350069f 100644 --- a/media/libpng/MOZCHANGES +++ b/media/libpng/MOZCHANGES @@ -1,6 +1,8 @@ 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). diff --git a/media/libpng/README b/media/libpng/README index 176928fbc986..38e9a14f5c96 100644 --- a/media/libpng/README +++ b/media/libpng/README @@ -1,4 +1,4 @@ -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. diff --git a/media/libpng/apng.patch b/media/libpng/apng.patch index a71d32eddfcc..c3dcf8f1074b 100644 --- a/media/libpng/apng.patch +++ b/media/libpng/apng.patch @@ -8,18 +8,18 @@ Index: LICENSE +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) { @@ -29,7 +29,7 @@ Index: pngread.c png_ptr->idat_size = length; break; } -@@ -247,6 +250,17 @@ +@@ -250,6 +253,17 @@ png_handle_iTXt(png_ptr, info_ptr, length); #endif @@ -47,7 +47,7 @@ Index: pngread.c 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 */ @@ -299,8 +299,8 @@ Index: png.c #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 \ @@ -308,16 +308,16 @@ Index: png.c - 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 } @@ -331,26 +331,26 @@ Index: png.h * + * 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 @@ -361,7 +361,7 @@ Index: png.h #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 */ @@ -379,10 +379,10 @@ Index: png.h /* 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 @@ -390,7 +390,7 @@ Index: png.h /* 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)); @@ -401,7 +401,7 @@ Index: png.h /* 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 ******************************************************************************/ @@ -477,14 +477,14 @@ Index: png.h /* 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 @@ -653,9 +653,9 @@ Index: pngwrite.c #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 @@ -790,7 +790,7 @@ Index: pngpread.c 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) { @@ -800,7 +800,7 @@ Index: pngpread.c 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 @@ -821,7 +821,7 @@ Index: pngpread.c 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 */ @@ -833,7 +833,7 @@ Index: pngpread.c 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; @@ -894,7 +894,7 @@ Index: pngpread.c } 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)"); @@ -911,7 +911,7 @@ Index: pngpread.c /* 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); } @@ -946,7 +946,7 @@ Index: pngset.c } #ifdef PNG_oFFs_SUPPORTED -@@ -1094,6 +1099,146 @@ +@@ -1096,6 +1101,146 @@ } #endif /* sPLT */ @@ -1603,27 +1603,27 @@ 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 diff --git a/media/libpng/arm/arm_init.c b/media/libpng/arm/arm_init.c index 3800f18e0ef1..5cf1abb529ea 100644 --- a/media/libpng/arm/arm_init.c +++ b/media/libpng/arm/arm_init.c @@ -1,9 +1,9 @@ /* 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 @@ -66,6 +66,7 @@ png_init_filter_functions_neon(png_structp pp, unsigned int bpp) * 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) { diff --git a/media/libpng/arm/filter_neon_intrinsics.c b/media/libpng/arm/filter_neon_intrinsics.c index d42c78890911..05c2a08aa0df 100644 --- a/media/libpng/arm/filter_neon_intrinsics.c +++ b/media/libpng/arm/filter_neon_intrinsics.c @@ -1,11 +1,11 @@ /* 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 , 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 @@ -47,6 +47,8 @@ png_read_filter_row_up_neon(png_row_infop row_info, png_bytep 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; @@ -72,6 +74,8 @@ png_read_filter_row_sub3_neon(png_row_infop row_info, png_bytep row, 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; @@ -113,6 +117,8 @@ png_read_filter_row_sub4_neon(png_row_infop row_info, png_bytep row, 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)); @@ -148,6 +154,8 @@ png_read_filter_row_avg3_neon(png_row_infop row_info, png_bytep row, 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; @@ -207,6 +215,8 @@ png_read_filter_row_avg4_neon(png_row_infop row_info, png_bytep 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; @@ -280,6 +290,8 @@ png_read_filter_row_paeth3_neon(png_row_infop row_info, png_bytep row, 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; @@ -339,6 +351,8 @@ png_read_filter_row_paeth4_neon(png_row_infop row_info, png_bytep row, 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; diff --git a/media/libpng/libpng-manual.txt b/media/libpng/libpng-manual.txt index 1e838bd7722f..541a264302a1 100644 --- a/media/libpng/libpng-manual.txt +++ b/media/libpng/libpng-manual.txt @@ -1,6 +1,6 @@ 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 Copyright (c) 1998-2016 Glenn Randers-Pehrson @@ -11,7 +11,7 @@ libpng-manual.txt - A description on how to use and modify libpng 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 @@ -2842,7 +2842,7 @@ filter types. 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 @@ -4103,6 +4103,13 @@ be written: 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) @@ -4380,8 +4387,9 @@ 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 @@ -4395,12 +4403,19 @@ 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 @@ -4775,7 +4790,8 @@ 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 @@ -5015,6 +5031,7 @@ includes the following: 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 @@ -5328,7 +5345,7 @@ 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 diff --git a/media/libpng/png.c b/media/libpng/png.c index 91df6f4c8ac4..2da592111857 100644 --- a/media/libpng/png.c +++ b/media/libpng/png.c @@ -14,7 +14,7 @@ #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 @@ -775,21 +775,21 @@ png_get_copyright(png_const_structrp png_ptr) #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 } diff --git a/media/libpng/png.h b/media/libpng/png.h index 9fa276778a34..1b96098a3596 100644 --- a/media/libpng/png.h +++ b/media/libpng/png.h @@ -1,7 +1,7 @@ /* 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) @@ -12,7 +12,7 @@ * 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. */ @@ -25,13 +25,17 @@ * * 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 @@ -53,6 +57,10 @@ * 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 @@ -63,6 +71,9 @@ * 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 @@ -76,6 +87,9 @@ * 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. * @@ -115,6 +129,29 @@ * 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). */ /* @@ -127,12 +164,6 @@ * 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 @@ -188,11 +219,11 @@ * ... * 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 @@ -220,13 +251,13 @@ * 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 @@ -288,9 +319,9 @@ */ /* 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 @@ -298,7 +329,7 @@ /* 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: @@ -329,7 +360,7 @@ * 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. @@ -454,7 +485,7 @@ extern "C" { /* 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. * @@ -755,24 +786,22 @@ typedef png_unknown_chunk * * png_unknown_chunkpp; * data in the info_struct to be written into the output file. The values * of the PNG_INFO_ 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 @@ -1351,7 +1380,7 @@ 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 @@ -1502,8 +1531,8 @@ PNG_EXPORT(67, void, png_set_filter, (png_structrp png_ptr, int method, #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. @@ -1780,21 +1809,21 @@ PNG_EXPORT(99, void, png_data_freer, (png_const_structrp png_ptr, #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, @@ -2918,12 +2947,19 @@ typedef struct * 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)\ @@ -3044,7 +3080,6 @@ PNG_EXPORT(238, void, png_image_free, (png_imagep image)); #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 @@ -3061,6 +3096,7 @@ PNG_EXPORT(238, void, png_image_free, (png_imagep image)); * 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)); @@ -3070,8 +3106,9 @@ 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*). */ +#endif /* SIMPLIFIED_WRITE_STDIO */ -/* With both write APIs if image is in one of the linear formats with 16-bit +/* 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. @@ -3083,13 +3120,103 @@ PNG_EXPORT(240, int, png_image_write_to_stdio, (png_imagep image, FILE *file, * * 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 @@ -3217,9 +3344,9 @@ PNG_EXPORT(264, void, png_write_frame_tail, (png_structp png_ptr, */ #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 diff --git a/media/libpng/pngconf.h b/media/libpng/pngconf.h index 934465455273..b0ccc8c25ee2 100644 --- a/media/libpng/pngconf.h +++ b/media/libpng/pngconf.h @@ -1,7 +1,7 @@ /* 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) diff --git a/media/libpng/pngerror.c b/media/libpng/pngerror.c index 6904bea1a23e..3fc8092fa6d8 100644 --- a/media/libpng/pngerror.c +++ b/media/libpng/pngerror.c @@ -44,7 +44,7 @@ png_error,(png_const_structrp png_ptr, png_const_charp error_message), 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) { diff --git a/media/libpng/pngget.c b/media/libpng/pngget.c index 95b2b3b2e107..1d1750b872b1 100644 --- a/media/libpng/pngget.c +++ b/media/libpng/pngget.c @@ -456,11 +456,11 @@ png_get_pHYs_dpi(png_const_structrp png_ptr, png_const_inforp info_ptr, 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 @@ -1142,19 +1142,19 @@ png_get_compression_buffer_size(png_const_structrp png_ptr) 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 } diff --git a/media/libpng/pngpread.c b/media/libpng/pngpread.c index b11b3f72c4a6..fd55eab2ca77 100644 --- a/media/libpng/pngpread.c +++ b/media/libpng/pngpread.c @@ -1,8 +1,8 @@ /* 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.) * @@ -293,12 +293,14 @@ png_push_read_chunk(png_structrp png_ptr, png_inforp info_ptr) (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"); @@ -599,7 +601,10 @@ png_push_save_buffer(png_structrp png_ptr) 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; } diff --git a/media/libpng/pngpriv.h b/media/libpng/pngpriv.h index 6ead7805539c..f39b788e4416 100644 --- a/media/libpng/pngpriv.h +++ b/media/libpng/pngpriv.h @@ -1,8 +1,8 @@ /* 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.) * diff --git a/media/libpng/pngread.c b/media/libpng/pngread.c index a6b4f67c40ca..da5e61efd198 100644 --- a/media/libpng/pngread.c +++ b/media/libpng/pngread.c @@ -1,8 +1,8 @@ /* 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.) * @@ -127,7 +127,10 @@ png_read_info(png_structrp png_ptr, png_inforp info_ptr) } 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. @@ -865,6 +868,9 @@ png_read_end(png_structrp png_ptr, png_inforp info_ptr) 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); @@ -879,9 +885,9 @@ png_read_end(png_structrp png_ptr, png_inforp info_ptr) { 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) @@ -892,10 +898,14 @@ png_read_end(png_structrp png_ptr, png_inforp info_ptr) 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); } @@ -3928,16 +3938,16 @@ png_image_read_direct(png_voidp argument) else filler = 255; -# ifdef PNG_FORMAT_AFIRST_SUPPORTED - if ((format & PNG_FORMAT_FLAG_AFIRST) != 0) - { - where = PNG_FILLER_BEFORE; - change &= ~PNG_FORMAT_FLAG_AFIRST; - } +#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; + else +#endif + where = PNG_FILLER_AFTER; png_set_add_alpha(png_ptr, filler, where); } @@ -4045,12 +4055,12 @@ png_image_read_direct(png_voidp argument) 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_BGR_SUPPORTED + if ((png_ptr->transformations & PNG_BGR) != 0) + info_format |= PNG_FORMAT_FLAG_BGR; +#endif -# ifdef PNG_FORMAT_AFIRST_SUPPORTED +#ifdef PNG_FORMAT_AFIRST_SUPPORTED if (do_local_background == 2) { if ((format & PNG_FORMAT_FLAG_AFIRST) != 0) @@ -4151,58 +4161,84 @@ png_image_finish_read(png_imagep image, png_const_colorp background, { if (image != NULL && image->version == PNG_IMAGE_VERSION) { - png_uint_32 check; + /* 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 (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)) + 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) diff --git a/media/libpng/pngrtran.c b/media/libpng/pngrtran.c index e23317886395..3138147aff9f 100644 --- a/media/libpng/pngrtran.c +++ b/media/libpng/pngrtran.c @@ -1,8 +1,8 @@ /* 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.) * @@ -159,7 +159,7 @@ png_set_background(png_structrp png_ptr, 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 @@ -289,9 +289,12 @@ png_set_alpha_mode_fixed(png_structrp png_ptr, int mode, * 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 @@ -1912,7 +1915,7 @@ png_init_read_transformations(png_structrp png_ptr) png_ptr->palette[i].blue = (png_byte)component; } } -#endif /* READ_SHIFT */ +#endif /* READ_SHIFT */ } /* Modify the info structure to reflect the transformations. The diff --git a/media/libpng/pngset.c b/media/libpng/pngset.c index 4d4351716382..65a67216ca16 100644 --- a/media/libpng/pngset.c +++ b/media/libpng/pngset.c @@ -1,8 +1,8 @@ /* 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.) * @@ -957,12 +957,14 @@ png_set_tRNS(png_structrp png_ptr, png_inforp info_ptr, 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) diff --git a/media/libpng/pngwrite.c b/media/libpng/pngwrite.c index 33e10eb58990..a658bdbe6734 100644 --- a/media/libpng/pngwrite.c +++ b/media/libpng/pngwrite.c @@ -12,9 +12,9 @@ */ #include "pngpriv.h" -#if defined(PNG_SIMPLIFIED_WRITE_SUPPORTED) && defined(PNG_STDIO_SUPPORTED) +#ifdef PNG_SIMPLIFIED_WRITE_STDIO_SUPPORTED # include -#endif +#endif /* SIMPLIFIED_WRITE_STDIO */ #ifdef PNG_WRITE_SUPPORTED @@ -1461,7 +1461,6 @@ png_write_png(png_structrp png_ptr, png_inforp info_ptr, #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) @@ -1513,6 +1512,10 @@ typedef struct 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 @@ -1940,9 +1943,43 @@ png_image_write_main(png_voidp argument) 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) @@ -2119,6 +2156,122 @@ png_image_write_main(png_voidp argument) 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) @@ -2126,7 +2279,7 @@ png_image_write_to_stdio(png_imagep image, FILE *file, int convert_to_8bit, /* 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) { @@ -2176,7 +2329,7 @@ png_image_write_to_file(png_imagep image, const char *file_name, /* 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"); @@ -2234,7 +2387,7 @@ png_image_write_to_file(png_imagep image, const char *file_name, else return 0; } -# endif /* STDIO */ +#endif /* SIMPLIFIED_WRITE_STDIO */ #endif /* SIMPLIFIED_WRITE */ #ifdef PNG_WRITE_APNG_SUPPORTED diff --git a/media/libpng/pngwutil.c b/media/libpng/pngwutil.c index ca15fddf8d2c..bd69be573a4b 100644 --- a/media/libpng/pngwutil.c +++ b/media/libpng/pngwutil.c @@ -1,8 +1,8 @@ /* 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.) * @@ -23,10 +23,10 @@ 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. @@ -36,8 +36,8 @@ png_save_uint_32(png_bytep buf, png_uint_32 i) 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 diff --git a/modules/brotli/README.mozilla b/modules/brotli/README.mozilla index b5ec992204a1..474afa2e4011 100644 --- a/modules/brotli/README.mozilla +++ b/modules/brotli/README.mozilla @@ -14,8 +14,4 @@ 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]. diff --git a/modules/brotli/dec/bit_reader.c b/modules/brotli/dec/bit_reader.c index 72509a237682..cde90af56e4f 100644 --- a/modules/brotli/dec/bit_reader.c +++ b/modules/brotli/dec/bit_reader.c @@ -44,5 +44,5 @@ int BrotliWarmupBitReader(BrotliBitReader* const br) { } #if defined(__cplusplus) || defined(c_plusplus) -} /* extern "C" */ +} /* extern "C" */ #endif diff --git a/modules/brotli/dec/bit_reader.h b/modules/brotli/dec/bit_reader.h index 58a3f8453750..7096afaa3f77 100644 --- a/modules/brotli/dec/bit_reader.h +++ b/modules/brotli/dec/bit_reader.h @@ -48,27 +48,27 @@ static BROTLI_INLINE uint32_t BitMask(uint32_t 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) { @@ -109,9 +109,7 @@ static BROTLI_INLINE uint16_t BrotliLoad16LE(const uint8_t* in) { 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)); } @@ -228,9 +226,9 @@ static BROTLI_INLINE int BrotliPullByte(BrotliBitReader* const br) { } 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; @@ -262,7 +260,7 @@ static BROTLI_INLINE uint32_t BrotliGetBits( /* 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; @@ -296,10 +294,8 @@ static BROTLI_INLINE void BrotliBitReaderUnload(BrotliBitReader* br) { 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); } @@ -326,7 +322,7 @@ static BROTLI_INLINE uint32_t BrotliReadBits( /* 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; @@ -381,7 +377,7 @@ static BROTLI_INLINE void BrotliCopyBytes(uint8_t* dest, } #if defined(__cplusplus) || defined(c_plusplus) -} /* extern "C" */ +} /* extern "C" */ #endif #endif /* BROTLI_DEC_BIT_READER_H_ */ diff --git a/modules/brotli/dec/context.h b/modules/brotli/dec/context.h index b71f9a3e0384..37ebe6aebc3c 100644 --- a/modules/brotli/dec/context.h +++ b/modules/brotli/dec/context.h @@ -102,10 +102,10 @@ #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. */ diff --git a/modules/brotli/dec/decode.c b/modules/brotli/dec/decode.c index a614c559dc3f..d184f24cba5b 100644 --- a/modules/brotli/dec/decode.c +++ b/modules/brotli/dec/decode.c @@ -10,7 +10,6 @@ #include #endif -#include /* printf (debug output) */ #include /* free, malloc */ #include /* memcpy, memset */ @@ -20,38 +19,20 @@ #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; @@ -61,8 +42,8 @@ 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] = { @@ -89,10 +70,11 @@ BrotliState* BrotliCreateState( 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; } @@ -108,6 +90,18 @@ void BrotliDestroyState(BrotliState* 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) { @@ -127,8 +121,7 @@ static uint32_t DecodeWindowBits(BrotliBitReader* br) { 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 @@ -139,29 +132,29 @@ static BROTLI_INLINE void memmove16( } /* 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; @@ -170,27 +163,27 @@ static BROTLI_NOINLINE BrotliResult DecodeVarLenUint8(BrotliState* s, 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; @@ -205,18 +198,18 @@ static BrotliResult BROTLI_NOINLINE DecodeMetaBlockLength(BrotliState* s, 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; @@ -233,10 +226,10 @@ static BrotliResult BROTLI_NOINLINE DecodeMetaBlockLength(BrotliState* s, 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)); } @@ -247,31 +240,31 @@ static BrotliResult BROTLI_NOINLINE DecodeMetaBlockLength(BrotliState* s, 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; @@ -282,19 +275,19 @@ static BrotliResult BROTLI_NOINLINE DecodeMetaBlockLength(BrotliState* s, 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); } } } @@ -377,7 +370,6 @@ static BROTLI_INLINE int SafeReadSymbol(const HuffmanCode* table, 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, @@ -427,8 +419,8 @@ static BROTLI_INLINE uint32_t Log2Floor(uint32_t x) { 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); @@ -439,10 +431,10 @@ static BrotliResult ReadSimpleHuffmanSymbols(uint32_t alphabet_size, 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]); @@ -453,12 +445,12 @@ static BrotliResult ReadSimpleHuffmanSymbols(uint32_t alphabet_size, 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: @@ -479,8 +471,7 @@ static BROTLI_INLINE void ProcessSingleCodeLength(uint32_t code_len, *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)++; } @@ -516,7 +507,7 @@ static BROTLI_INLINE void ProcessRepeatedCodeLength(uint32_t code_len, *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; @@ -532,15 +523,15 @@ static BROTLI_INLINE void ProcessRepeatedCodeLength(uint32_t code_len, } 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; @@ -552,7 +543,7 @@ static BrotliResult ReadSymbolCodeLengths( 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; @@ -563,13 +554,13 @@ static BrotliResult ReadSymbolCodeLengths( 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); @@ -583,10 +574,10 @@ static BrotliResult ReadSymbolCodeLengths( } } 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) { @@ -619,15 +610,15 @@ static BrotliResult SafeReadSymbolCodeLengths( 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; @@ -648,7 +639,7 @@ static BrotliResult ReadCodeLengthCodeLengths(BrotliState* s) { 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]; @@ -666,9 +657,9 @@ static BrotliResult ReadCodeLengthCodeLengths(BrotliState* s) { } } 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. @@ -683,10 +674,10 @@ static BrotliResult ReadCodeLengthCodeLengths(BrotliState* s) { 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; @@ -694,7 +685,7 @@ static BrotliResult ReadHuffmanCode(uint32_t alphabet_size, 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: @@ -716,13 +707,13 @@ static BrotliResult ReadHuffmanCode(uint32_t alphabet_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. */ @@ -733,7 +724,7 @@ static BrotliResult ReadHuffmanCode(uint32_t alphabet_size, 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; } @@ -744,14 +735,14 @@ static BrotliResult ReadHuffmanCode(uint32_t alphabet_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, @@ -773,29 +764,29 @@ Complex: /* Decode Huffman-coded code lengths. */ } 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); } } @@ -857,7 +848,7 @@ static BROTLI_NOINLINE void InverseMoveToFrontTransform(uint8_t* v, /* 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; @@ -878,20 +869,19 @@ static BROTLI_NOINLINE void InverseMoveToFrontTransform(uint8_t* v, 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; @@ -899,15 +889,15 @@ static BrotliResult HuffmanTreeGroupDecode(HuffmanTreeGroup* group, } 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. @@ -919,17 +909,17 @@ static BrotliResult HuffmanTreeGroupDecode(HuffmanTreeGroup* group, 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)++; @@ -938,11 +928,11 @@ static BrotliResult DecodeContextMap(uint32_t 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. */ @@ -951,7 +941,7 @@ static BrotliResult DecodeContextMap(uint32_t context_map_size, /* 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; @@ -967,7 +957,7 @@ static BrotliResult DecodeContextMap(uint32_t context_map_size, 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. */ @@ -983,7 +973,7 @@ static BrotliResult DecodeContextMap(uint32_t 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); @@ -1002,12 +992,12 @@ rleCode: 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; @@ -1020,16 +1010,16 @@ rleCode: 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); } } @@ -1076,22 +1066,45 @@ static BROTLI_INLINE int DecodeBlockTypeAndLength(int safe, 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; } @@ -1142,21 +1155,20 @@ 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; @@ -1164,11 +1176,16 @@ static BrotliResult WriteRingBuffer(size_t* available_out, uint8_t** next_out, 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. @@ -1199,18 +1216,18 @@ static int BROTLI_NOINLINE BrotliAllocateRingBuffer(BrotliState* s) { 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 */ @@ -1230,28 +1247,26 @@ static BrotliResult BROTLI_NOINLINE CopyUncompressedBlockToOutput( 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, @@ -1266,7 +1281,7 @@ int BrotliDecompressedSize(size_t encoded_size, 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; @@ -1290,13 +1305,14 @@ int BrotliDecompressedSize(size_t encoded_size, 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; } } @@ -1305,22 +1321,17 @@ static void BROTLI_NOINLINE BrotliCalculateRingBufferSize(BrotliState* s, /* 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; @@ -1328,13 +1339,13 @@ static BrotliResult ReadContextModes(BrotliState* s) { 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) { @@ -1407,8 +1418,8 @@ static BROTLI_INLINE int ReadDistanceInternal(int safe, 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; @@ -1498,26 +1509,27 @@ static BROTLI_INLINE int CheckInputAmount(int safe, 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) { @@ -1534,7 +1546,7 @@ static BROTLI_INLINE BrotliResult ProcessCommandsInternal(int safe, } else if (s->state == BROTLI_STATE_COMMAND_POST_WRAP_COPY) { goto CommandPostWrapCopy; } else { - return BROTLI_FAILURE(); + return BROTLI_FAILURE(BROTLI_ERROR_UNREACHABLE); } CommandBegin: @@ -1543,7 +1555,7 @@ CommandBegin: } 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)) { @@ -1571,26 +1583,26 @@ CommandInner: 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)) { @@ -1607,11 +1619,12 @@ CommandInner: 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); @@ -1622,7 +1635,7 @@ CommandInner: } 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; @@ -1640,7 +1653,7 @@ CommandInner: } 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; } @@ -1700,58 +1713,38 @@ postReadDistance: } } 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 copy extends over the ringbuffer end, - or if the copy overlaps with itself, if yes, do wrap-copy. */ - if (copy_src < copy_dst) { - if (copy_dst >= ringbuffer_end_minus_copy_length) { - goto CommandPostWrapCopy; - } - if (copy_src + i > copy_dst) { - goto postSelfintersecting; - } - } else { - if (copy_src >= ringbuffer_end_minus_copy_length) { - goto CommandPostWrapCopy; - } - if (copy_dst + i > copy_src) { - goto postSelfintersecting; - } + if (src_end > pos && dst_end > src_start) { + /* Regions intersect. */ + goto CommandPostWrapCopy; + } + if (dst_end >= s->ringbuffer_size || src_end >= s->ringbuffer_size) { + /* At least one region wraps. */ + goto CommandPostWrapCopy; } pos += i; if (i > 16) { @@ -1772,30 +1765,17 @@ postReadDistance: } else { goto CommandBegin; } -postSelfintersecting: - while (--i >= 0) { - s->ringbuffer[pos] = - s->ringbuffer[(pos - s->distance_code) & s->ringbuffer_mask]; - ++pos; - } - if (s->meta_block_remaining_len <= 0) { - /* Next metablock, if any */ - s->state = BROTLI_STATE_METABLOCK_DONE; - goto saveStateAndReturn; - } else { - goto CommandBegin; - } - CommandPostWrapCopy: - s->state = BROTLI_STATE_COMMAND_POST_WRAP_COPY; - while (--i >= 0) { - s->ringbuffer[pos] = - s->ringbuffer[(pos - s->distance_code) & s->ringbuffer_mask]; - ++pos; - if (pos == s->ringbuffer_size) { - /*s->partial_pos_rb += (size_t)s->ringbuffer_size;*/ - s->state = BROTLI_STATE_COMMAND_POST_WRITE_2; - goto saveStateAndReturn; + { + int wrap_guard = s->ringbuffer_size - pos; + while (--i >= 0) { + s->ringbuffer[pos] = + s->ringbuffer[(pos - s->distance_code) & s->ringbuffer_mask]; + ++pos; + if (PREDICT_FALSE(--wrap_guard == 0)) { + s->state = BROTLI_STATE_COMMAND_POST_WRITE_2; + goto saveStateAndReturn; + } } } if (s->meta_block_remaining_len <= 0) { @@ -1814,11 +1794,11 @@ saveStateAndReturn: #undef BROTLI_SAFE -static BROTLI_NOINLINE BrotliResult ProcessCommands(BrotliState* s) { +static BROTLI_NOINLINE BrotliErrorCode ProcessCommands(BrotliState* s) { return ProcessCommandsInternal(0, s); } -static BROTLI_NOINLINE BrotliResult SafeProcessCommands(BrotliState* s) { +static BROTLI_NOINLINE BrotliErrorCode SafeProcessCommands(BrotliState* s) { return ProcessCommandsInternal(1, s); } @@ -1859,7 +1839,7 @@ BrotliResult BrotliDecompressBuffer(size_t encoded_size, BrotliResult BrotliDecompressStream(size_t* available_in, const uint8_t** next_in, size_t* available_out, uint8_t** next_out, size_t* total_out, BrotliState* s) { - BrotliResult result = BROTLI_RESULT_SUCCESS; + BrotliErrorCode result = BROTLI_SUCCESS; BrotliBitReader* br = &s->br; if (s->buffer_length == 0) { /* Just connect bit reader to input stream. */ br->avail_in = *available_in; @@ -1868,13 +1848,13 @@ BrotliResult BrotliDecompressStream(size_t* available_in, /* At least one byte of input is required. More than one byte of input may be required to complete the transaction -> reading more data must be done in a loop -> do it in a main loop. */ - result = BROTLI_RESULT_NEEDS_MORE_INPUT; + result = BROTLI_NEEDS_MORE_INPUT; br->next_in = &s->buffer.u8[0]; } /* State machine */ for (;;) { - if (result != BROTLI_RESULT_SUCCESS) { /* Error | needs more input/output */ - if (result == BROTLI_RESULT_NEEDS_MORE_INPUT) { + if (result != BROTLI_SUCCESS) { /* Error | needs more input/output */ + if (result == BROTLI_NEEDS_MORE_INPUT) { if (s->ringbuffer != 0) { /* Proactively push output. */ WriteRingBuffer(available_out, next_out, total_out, s); } @@ -1884,14 +1864,14 @@ BrotliResult BrotliDecompressStream(size_t* available_in, is expanded byte-by-byte until it is enough to complete read. */ s->buffer_length = 0; /* Switch to input stream and restart. */ - result = BROTLI_RESULT_SUCCESS; + result = BROTLI_SUCCESS; br->avail_in = *available_in; br->next_in = *next_in; continue; } else if (*available_in != 0) { /* Not enough data in buffer, but can take one more byte from input stream. */ - result = BROTLI_RESULT_SUCCESS; + result = BROTLI_SUCCESS; s->buffer.u8[s->buffer_length] = **next_in; s->buffer_length++; br->avail_in = s->buffer_length; @@ -1937,7 +1917,7 @@ BrotliResult BrotliDecompressStream(size_t* available_in, case BROTLI_STATE_UNINITED: /* Prepare to the first read. */ if (!BrotliWarmupBitReader(br)) { - result = BROTLI_RESULT_NEEDS_MORE_INPUT; + result = BROTLI_NEEDS_MORE_INPUT; break; } /* Decode window size. */ @@ -1945,10 +1925,16 @@ BrotliResult BrotliDecompressStream(size_t* available_in, BROTLI_LOG_UINT(s->window_bits); if (s->window_bits == 9) { /* Value 9 is reserved for future use. */ - result = BROTLI_FAILURE(); + result = BROTLI_FAILURE(BROTLI_ERROR_FORMAT_WINDOW_BITS); break; } + /* Maximum distance, see section 9.1. of the spec. */ s->max_backward_distance = (1 << s->window_bits) - 16; + /* Limit custom dictionary size. */ + if (s->custom_dict_size >= s->max_backward_distance) { + s->custom_dict += s->custom_dict_size - s->max_backward_distance; + s->custom_dict_size = s->max_backward_distance; + } s->max_backward_distance_minus_custom_dict_size = s->max_backward_distance - s->custom_dict_size; @@ -1957,11 +1943,11 @@ BrotliResult BrotliDecompressStream(size_t* available_in, sizeof(HuffmanCode) * 3 * (BROTLI_HUFFMAN_MAX_SIZE_258 + BROTLI_HUFFMAN_MAX_SIZE_26)); if (s->block_type_trees == 0) { - result = BROTLI_FAILURE(); + result = BROTLI_FAILURE(BROTLI_ERROR_ALLOC_BLOCK_TYPE_TREES); break; } - s->block_len_trees = s->block_type_trees + - 3 * BROTLI_HUFFMAN_MAX_SIZE_258; + s->block_len_trees = + s->block_type_trees + 3 * BROTLI_HUFFMAN_MAX_SIZE_258; s->state = BROTLI_STATE_METABLOCK_BEGIN; /* No break, continue to next state */ @@ -1972,7 +1958,7 @@ BrotliResult BrotliDecompressStream(size_t* available_in, /* No break, continue to next state */ case BROTLI_STATE_METABLOCK_HEADER: result = DecodeMetaBlockLength(s, br); /* Reads 2 - 31 bits. */ - if (result != BROTLI_RESULT_SUCCESS) { + if (result != BROTLI_SUCCESS) { break; } BROTLI_LOG_UINT(s->is_last_metablock); @@ -1981,7 +1967,7 @@ BrotliResult BrotliDecompressStream(size_t* available_in, BROTLI_LOG_UINT(s->is_uncompressed); if (s->is_metadata || s->is_uncompressed) { if (!BrotliJumpToByteBoundary(br)) { - result = BROTLI_FAILURE(); + result = BROTLI_FAILURE(BROTLI_ERROR_FORMAT_PADDING_1); break; } } @@ -2008,7 +1994,7 @@ BrotliResult BrotliDecompressStream(size_t* available_in, result = CopyUncompressedBlockToOutput( available_out, next_out, total_out, s); bytes_copied -= s->meta_block_remaining_len; - if (result != BROTLI_RESULT_SUCCESS) { + if (result != BROTLI_SUCCESS) { break; } s->state = BROTLI_STATE_METABLOCK_DONE; @@ -2019,11 +2005,11 @@ BrotliResult BrotliDecompressStream(size_t* available_in, uint32_t bits; /* Read one byte and ignore it. */ if (!BrotliSafeReadBits(br, 8, &bits)) { - result = BROTLI_RESULT_NEEDS_MORE_INPUT; + result = BROTLI_NEEDS_MORE_INPUT; break; } } - if (result == BROTLI_RESULT_SUCCESS) { + if (result == BROTLI_SUCCESS) { s->state = BROTLI_STATE_METABLOCK_DONE; } break; @@ -2034,7 +2020,7 @@ BrotliResult BrotliDecompressStream(size_t* available_in, } /* Reads 1..11 bits. */ result = DecodeVarLenUint8(s, br, &s->num_block_types[s->loop_counter]); - if (result != BROTLI_RESULT_SUCCESS) { + if (result != BROTLI_SUCCESS) { break; } s->num_block_types[s->loop_counter]++; @@ -2049,7 +2035,7 @@ BrotliResult BrotliDecompressStream(size_t* available_in, int tree_offset = s->loop_counter * BROTLI_HUFFMAN_MAX_SIZE_258; result = ReadHuffmanCode(s->num_block_types[s->loop_counter] + 2, &s->block_type_trees[tree_offset], NULL, s); - if (result != BROTLI_RESULT_SUCCESS) break; + if (result != BROTLI_SUCCESS) break; s->state = BROTLI_STATE_HUFFMAN_CODE_2; /* No break, continue to next state */ } @@ -2057,7 +2043,7 @@ BrotliResult BrotliDecompressStream(size_t* available_in, int tree_offset = s->loop_counter * BROTLI_HUFFMAN_MAX_SIZE_26; result = ReadHuffmanCode(kNumBlockLengthCodes, &s->block_len_trees[tree_offset], NULL, s); - if (result != BROTLI_RESULT_SUCCESS) break; + if (result != BROTLI_SUCCESS) break; s->state = BROTLI_STATE_HUFFMAN_CODE_3; /* No break, continue to next state */ } @@ -2065,7 +2051,7 @@ BrotliResult BrotliDecompressStream(size_t* available_in, int tree_offset = s->loop_counter * BROTLI_HUFFMAN_MAX_SIZE_26; if (!SafeReadBlockLength(s, &s->block_length[s->loop_counter], &s->block_len_trees[tree_offset], br)) { - result = BROTLI_RESULT_NEEDS_MORE_INPUT; + result = BROTLI_NEEDS_MORE_INPUT; break; } BROTLI_LOG_UINT(s->block_length[s->loop_counter]); @@ -2076,20 +2062,20 @@ BrotliResult BrotliDecompressStream(size_t* available_in, case BROTLI_STATE_METABLOCK_HEADER_2: { uint32_t bits; if (!BrotliSafeReadBits(br, 6, &bits)) { - result = BROTLI_RESULT_NEEDS_MORE_INPUT; + result = BROTLI_NEEDS_MORE_INPUT; break; } s->distance_postfix_bits = bits & BitMask(2); bits >>= 2; - s->num_direct_distance_codes = NUM_DISTANCE_SHORT_CODES + - (bits << s->distance_postfix_bits); + s->num_direct_distance_codes = + NUM_DISTANCE_SHORT_CODES + (bits << s->distance_postfix_bits); BROTLI_LOG_UINT(s->num_direct_distance_codes); BROTLI_LOG_UINT(s->distance_postfix_bits); s->distance_postfix_mask = (int)BitMask(s->distance_postfix_bits); s->context_modes = (uint8_t*)BROTLI_ALLOC(s, (size_t)s->num_block_types[0]); if (s->context_modes == 0) { - result = BROTLI_FAILURE(); + result = BROTLI_FAILURE(BROTLI_ERROR_ALLOC_CONTEXT_MODES); break; } s->loop_counter = 0; @@ -2098,28 +2084,21 @@ BrotliResult BrotliDecompressStream(size_t* available_in, } case BROTLI_STATE_CONTEXT_MODES: result = ReadContextModes(s); - if (result != BROTLI_RESULT_SUCCESS) { + if (result != BROTLI_SUCCESS) { break; } s->state = BROTLI_STATE_CONTEXT_MAP_1; /* No break, continue to next state */ - case BROTLI_STATE_CONTEXT_MAP_1: { - uint32_t j; - result = DecodeContextMap(s->num_block_types[0] << kLiteralContextBits, - &s->num_literal_htrees, &s->context_map, s); - if (result != BROTLI_RESULT_SUCCESS) { + case BROTLI_STATE_CONTEXT_MAP_1: + result = DecodeContextMap( + s->num_block_types[0] << kLiteralContextBits, + &s->num_literal_htrees, &s->context_map, s); + if (result != BROTLI_SUCCESS) { break; } - s->trivial_literal_context = 1; - for (j = 0; j < s->num_block_types[0] << kLiteralContextBits; j++) { - if (s->context_map[j] != j >> kLiteralContextBits) { - s->trivial_literal_context = 0; - break; - } - } + DetectTrivialLiteralBlockTypes(s); s->state = BROTLI_STATE_CONTEXT_MAP_2; /* No break, continue to next state */ - } case BROTLI_STATE_CONTEXT_MAP_2: { uint32_t num_distance_codes = @@ -2127,7 +2106,7 @@ BrotliResult BrotliDecompressStream(size_t* available_in, result = DecodeContextMap( s->num_block_types[2] << kDistanceContextBits, &s->num_dist_htrees, &s->dist_context_map, s); - if (result != BROTLI_RESULT_SUCCESS) { + if (result != BROTLI_SUCCESS) { break; } BrotliHuffmanTreeGroupInit(s, &s->literal_hgroup, kNumLiteralCodes, @@ -2140,7 +2119,8 @@ BrotliResult BrotliDecompressStream(size_t* available_in, if (s->literal_hgroup.codes == 0 || s->insert_copy_hgroup.codes == 0 || s->distance_hgroup.codes == 0) { - return BROTLI_FAILURE(); + return SaveErrorCode(s, + BROTLI_FAILURE(BROTLI_ERROR_ALLOC_TREE_GROUPS)); } } s->loop_counter = 0; @@ -2159,23 +2139,20 @@ BrotliResult BrotliDecompressStream(size_t* available_in, case 2: hgroup = &s->distance_hgroup; break; + default: + return SaveErrorCode(s, + BROTLI_FAILURE(BROTLI_ERROR_UNREACHABLE)); } result = HuffmanTreeGroupDecode(hgroup, s); } - if (result != BROTLI_RESULT_SUCCESS) break; + if (result != BROTLI_SUCCESS) break; s->loop_counter++; if (s->loop_counter >= 3) { - uint8_t context_mode = s->context_modes[s->block_type_rb[1]]; - s->context_map_slice = s->context_map; + PrepareLiteralDecoding(s); s->dist_context_map_slice = s->dist_context_map; - s->context_lookup1 = - &kContextLookup[kContextLookupOffsets[context_mode]]; - s->context_lookup2 = - &kContextLookup[kContextLookupOffsets[context_mode + 1]]; s->htree_command = s->insert_copy_hgroup.htrees[0]; - s->literal_htree = s->literal_hgroup.htrees[s->literal_htree_index]; if (!s->ringbuffer && !BrotliAllocateRingBuffer(s)) { - result = BROTLI_FAILURE(); + result = BROTLI_FAILURE(BROTLI_ERROR_ALLOC_RING_BUFFER_2); break; } s->state = BROTLI_STATE_COMMAND_BEGIN; @@ -2186,7 +2163,7 @@ BrotliResult BrotliDecompressStream(size_t* available_in, case BROTLI_STATE_COMMAND_POST_DECODE_LITERALS: case BROTLI_STATE_COMMAND_POST_WRAP_COPY: result = ProcessCommands(s); - if (result == BROTLI_RESULT_NEEDS_MORE_INPUT) { + if (result == BROTLI_NEEDS_MORE_INPUT) { result = SafeProcessCommands(s); } break; @@ -2194,11 +2171,9 @@ BrotliResult BrotliDecompressStream(size_t* available_in, case BROTLI_STATE_COMMAND_POST_WRITE_1: case BROTLI_STATE_COMMAND_POST_WRITE_2: result = WriteRingBuffer(available_out, next_out, total_out, s); - if (result != BROTLI_RESULT_SUCCESS) { + if (result != BROTLI_SUCCESS) { break; } - s->pos -= s->ringbuffer_size; - s->rb_roundtrips++; s->max_distance = s->max_backward_distance; if (s->state == BROTLI_STATE_COMMAND_POST_WRITE_1) { memcpy(s->ringbuffer, s->ringbuffer_end, (size_t)s->pos); @@ -2224,13 +2199,18 @@ BrotliResult BrotliDecompressStream(size_t* available_in, } break; case BROTLI_STATE_METABLOCK_DONE: + if (s->meta_block_remaining_len < 0) { + result = BROTLI_FAILURE(BROTLI_ERROR_FORMAT_BLOCK_LENGTH_2); + break; + } BrotliStateCleanupAfterMetablock(s); if (!s->is_last_metablock) { s->state = BROTLI_STATE_METABLOCK_BEGIN; break; } if (!BrotliJumpToByteBoundary(br)) { - result = BROTLI_FAILURE(); + result = BROTLI_FAILURE(BROTLI_ERROR_FORMAT_PADDING_2); + break; } if (s->buffer_length == 0) { BrotliBitReaderUnload(br); @@ -2242,23 +2222,41 @@ BrotliResult BrotliDecompressStream(size_t* available_in, case BROTLI_STATE_DONE: if (s->ringbuffer != 0) { result = WriteRingBuffer(available_out, next_out, total_out, s); - if (result != BROTLI_RESULT_SUCCESS) { + if (result != BROTLI_SUCCESS) { break; } } - return result; + return SaveErrorCode(s, result); } } - return result; + return SaveErrorCode(s, result); } void BrotliSetCustomDictionary( size_t size, const uint8_t* dict, BrotliState* s) { + if (size > (1u << 24)) { + return; + } s->custom_dict = dict; - s->custom_dict_size = (int) size; + s->custom_dict_size = (int)size; } +BrotliErrorCode BrotliGetErrorCode(const BrotliState* s) { + return (BrotliErrorCode)s->error_code; +} + +const char* BrotliErrorString(BrotliErrorCode c) { + switch (c) { +#define _BROTLI_ERROR_CODE_CASE(PREFIX, NAME, CODE) \ + case BROTLI ## PREFIX ## NAME: return #NAME; +#define _BROTLI_NOTHING + BROTLI_ERROR_CODES_LIST(_BROTLI_ERROR_CODE_CASE, _BROTLI_NOTHING) +#undef _BROTLI_ERROR_CODE_CASE +#undef _BROTLI_NOTHING + default: return "INVALID"; + } +} #if defined(__cplusplus) || defined(c_plusplus) -} /* extern "C" */ +} /* extern "C" */ #endif diff --git a/modules/brotli/dec/decode.h b/modules/brotli/dec/decode.h index 074b2f58b570..056a8b5483a0 100644 --- a/modules/brotli/dec/decode.h +++ b/modules/brotli/dec/decode.h @@ -9,13 +9,14 @@ #ifndef BROTLI_DEC_DECODE_H_ #define BROTLI_DEC_DECODE_H_ -#include "./state.h" #include "./types.h" #if defined(__cplusplus) || defined(c_plusplus) extern "C" { #endif +typedef struct BrotliStateStruct BrotliState; + typedef enum { /* Decoding error, e.g. corrupt input or memory allocation problem */ BROTLI_RESULT_ERROR = 0, @@ -27,6 +28,57 @@ typedef enum { BROTLI_RESULT_NEEDS_MORE_OUTPUT = 3 } BrotliResult; +#define BROTLI_ERROR_CODES_LIST(BROTLI_ERROR_CODE, SEPARATOR) \ + BROTLI_ERROR_CODE(_, NO_ERROR, 0) SEPARATOR \ + /* Same as BrotliResult values */ \ + BROTLI_ERROR_CODE(_, SUCCESS, 1) SEPARATOR \ + BROTLI_ERROR_CODE(_, NEEDS_MORE_INPUT, 2) SEPARATOR \ + BROTLI_ERROR_CODE(_, NEEDS_MORE_OUTPUT, 3) SEPARATOR \ + \ + /* Errors caused by invalid input */ \ + BROTLI_ERROR_CODE(_ERROR_FORMAT_, EXUBERANT_NIBBLE, -1) SEPARATOR \ + BROTLI_ERROR_CODE(_ERROR_FORMAT_, RESERVED, -2) SEPARATOR \ + BROTLI_ERROR_CODE(_ERROR_FORMAT_, EXUBERANT_META_NIBBLE, -3) SEPARATOR \ + BROTLI_ERROR_CODE(_ERROR_FORMAT_, SIMPLE_HUFFMAN_ALPHABET, -4) SEPARATOR \ + BROTLI_ERROR_CODE(_ERROR_FORMAT_, SIMPLE_HUFFMAN_SAME, -5) SEPARATOR \ + BROTLI_ERROR_CODE(_ERROR_FORMAT_, CL_SPACE, -6) SEPARATOR \ + BROTLI_ERROR_CODE(_ERROR_FORMAT_, HUFFMAN_SPACE, -7) SEPARATOR \ + BROTLI_ERROR_CODE(_ERROR_FORMAT_, CONTEXT_MAP_REPEAT, -8) SEPARATOR \ + BROTLI_ERROR_CODE(_ERROR_FORMAT_, BLOCK_LENGTH_1, -9) SEPARATOR \ + BROTLI_ERROR_CODE(_ERROR_FORMAT_, BLOCK_LENGTH_2, -10) SEPARATOR \ + BROTLI_ERROR_CODE(_ERROR_FORMAT_, TRANSFORM, -11) SEPARATOR \ + BROTLI_ERROR_CODE(_ERROR_FORMAT_, DICTIONARY, -12) SEPARATOR \ + BROTLI_ERROR_CODE(_ERROR_FORMAT_, WINDOW_BITS, -13) SEPARATOR \ + BROTLI_ERROR_CODE(_ERROR_FORMAT_, PADDING_1, -14) SEPARATOR \ + BROTLI_ERROR_CODE(_ERROR_FORMAT_, PADDING_2, -15) SEPARATOR \ + \ + /* -16..-20 codes are reserved */ \ + \ + /* Memory allocation problems */ \ + BROTLI_ERROR_CODE(_ERROR_ALLOC_, CONTEXT_MODES, -21) SEPARATOR \ + /* Literal, insert and distance trees together */ \ + BROTLI_ERROR_CODE(_ERROR_ALLOC_, TREE_GROUPS, -22) SEPARATOR \ + /* -23..-24 codes are reserved for distinct tree groups */ \ + BROTLI_ERROR_CODE(_ERROR_ALLOC_, CONTEXT_MAP, -25) SEPARATOR \ + BROTLI_ERROR_CODE(_ERROR_ALLOC_, RING_BUFFER_1, -26) SEPARATOR \ + BROTLI_ERROR_CODE(_ERROR_ALLOC_, RING_BUFFER_2, -27) SEPARATOR \ + /* -28..-29 codes are reserved for dynamic ringbuffer allocation */ \ + BROTLI_ERROR_CODE(_ERROR_ALLOC_, BLOCK_TYPE_TREES, -30) SEPARATOR \ + \ + /* "Impossible" states */ \ + BROTLI_ERROR_CODE(_ERROR_, UNREACHABLE, -31) + +typedef enum { +#define _BROTLI_COMMA , +#define _BROTLI_ERROR_CODE_ENUM_ITEM(PREFIX, NAME, CODE) \ + BROTLI ## PREFIX ## NAME = CODE + BROTLI_ERROR_CODES_LIST(_BROTLI_ERROR_CODE_ENUM_ITEM, _BROTLI_COMMA) +#undef _BROTLI_ERROR_CODE_ENUM_ITEM +#undef _BROTLI_COMMA +} BrotliErrorCode; + +#define BROTLI_LAST_ERROR_CODE BROTLI_ERROR_UNREACHABLE + /* Creates the instance of BrotliState and initializes it. |alloc_func| and |free_func| MUST be both zero or both non-zero. In the case they are both zero, default memory allocators are used. |opaque| is passed to |alloc_func| @@ -63,8 +115,8 @@ BrotliResult BrotliDecompressBuffer(size_t encoded_size, bytes consumed, and the |*next_in| pointer will be incremented by that amount. Similarly, |*available_out| will be decremented by the amount of output bytes written, and the |*next_out| pointer will be incremented by that - amount. |total_out| will be set to the number of bytes decompressed since - last state initialization. + amount. |total_out|, if it is not a null-pointer, will be set to the number + of bytes decompressed since the last state initialization. Input is never overconsumed, so |next_in| and |available_in| could be passed to the next consumer after decoding is complete. */ @@ -78,16 +130,30 @@ BrotliResult BrotliDecompressStream(size_t* available_in, /* Fills the new state with a dictionary for LZ77, warming up the ringbuffer, e.g. for custom static dictionaries for data formats. Not to be confused with the built-in transformable dictionary of Brotli. - The dictionary must exist in memory until decoding is done and is owned by - the caller. To use: - 1) initialize state with BrotliStateInit - 2) use BrotliSetCustomDictionary - 3) use BrotliDecompressStream - 4) clean up with BrotliStateCleanup + |size| should be less or equal to 2^24 (16MiB), otherwise the dictionary will + be ignored. The dictionary must exist in memory until decoding is done and + is owned by the caller. To use: + 1) Allocate and initialize state with BrotliCreateState + 2) Use BrotliSetCustomDictionary + 3) Use BrotliDecompressStream + 4) Clean up and free state with BrotliDestroyState */ void BrotliSetCustomDictionary( size_t size, const uint8_t* dict, BrotliState* s); +/* Returns 1, if s is in a state where we have not read any input bytes yet, + and 0 otherwise */ +int BrotliStateIsStreamStart(const BrotliState* s); + +/* Returns 1, if s is in a state where we reached the end of the input and + produced all of the output, and 0 otherwise. */ +int BrotliStateIsStreamEnd(const BrotliState* s); + +/* Returns detailed error code after BrotliDecompressStream returns + BROTLI_RESULT_ERROR. */ +BrotliErrorCode BrotliGetErrorCode(const BrotliState* s); + +const char* BrotliErrorString(BrotliErrorCode c); #if defined(__cplusplus) || defined(c_plusplus) } /* extern "C" */ diff --git a/modules/brotli/dec/dictionary.c b/modules/brotli/dec/dictionary.c index d87f2776eb34..f8f58575c0ee 100644 --- a/modules/brotli/dec/dictionary.c +++ b/modules/brotli/dec/dictionary.c @@ -9462,5 +9462,5 @@ const uint8_t kBrotliDictionary[122784] = { }; #if defined(__cplusplus) || defined(c_plusplus) -} /* extern "C" */ +} /* extern "C" */ #endif diff --git a/modules/brotli/dec/dictionary.h b/modules/brotli/dec/dictionary.h index ee3a4698f2c3..ae250c2d7f2e 100644 --- a/modules/brotli/dec/dictionary.h +++ b/modules/brotli/dec/dictionary.h @@ -18,22 +18,21 @@ extern "C" { extern const uint8_t kBrotliDictionary[122784]; static const uint32_t kBrotliDictionaryOffsetsByLength[] = { - 0, 0, 0, 0, 0, 4096, 9216, 21504, 35840, 44032, - 53248, 63488, 74752, 87040, 93696, 100864, 104704, 106752, 108928, 113536, - 115968, 118528, 119872, 121280, 122016, + 0, 0, 0, 0, 0, 4096, 9216, 21504, 35840, 44032, 53248, 63488, 74752, 87040, + 93696, 100864, 104704, 106752, 108928, 113536, 115968, 118528, 119872, 121280, + 122016 }; static const uint8_t kBrotliDictionarySizeBitsByLength[] = { - 0, 0, 0, 0, 10, 10, 11, 11, 10, 10, - 10, 10, 10, 9, 9, 8, 7, 7, 8, 7, - 7, 6, 6, 5, 5, + 0, 0, 0, 0, 10, 10, 11, 11, 10, 10, 10, 10, 10, + 9, 9, 8, 7, 7, 8, 7, 7, 6, 6, 5, 5, }; static const int kBrotliMinDictionaryWordLength = 4; static const int kBrotliMaxDictionaryWordLength = 24; #if defined(__cplusplus) || defined(c_plusplus) -} /* extern "C" */ +} /* extern "C" */ #endif #endif /* BROTLI_DEC_DICTIONARY_H_ */ diff --git a/modules/brotli/dec/huffman.c b/modules/brotli/dec/huffman.c index c980854d810b..3775ffe7e920 100644 --- a/modules/brotli/dec/huffman.c +++ b/modules/brotli/dec/huffman.c @@ -24,43 +24,43 @@ extern "C" { #else #define BROTLI_REVERSE_BITS_BASE 0 static uint8_t kReverseBits[1 << BROTLI_REVERSE_BITS_MAX] = { - 0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0, - 0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0, - 0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8, - 0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8, - 0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4, - 0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4, - 0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC, - 0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC, - 0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2, - 0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2, - 0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA, - 0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA, - 0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6, - 0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6, - 0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE, - 0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE, - 0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1, - 0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1, - 0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9, - 0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9, - 0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5, - 0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5, - 0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED, - 0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD, - 0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3, - 0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3, - 0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB, - 0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB, - 0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7, - 0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7, - 0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF, - 0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF + 0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0, + 0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0, + 0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8, + 0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8, + 0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4, + 0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4, + 0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC, + 0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC, + 0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2, + 0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2, + 0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA, + 0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA, + 0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6, + 0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6, + 0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE, + 0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE, + 0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1, + 0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1, + 0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9, + 0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9, + 0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5, + 0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5, + 0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED, + 0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD, + 0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3, + 0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3, + 0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB, + 0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB, + 0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7, + 0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7, + 0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF, + 0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF }; -#endif /* BROTLI_RBIT */ +#endif /* BROTLI_RBIT */ #define BROTLI_REVERSE_BITS_LOWEST \ - (1U << (BROTLI_REVERSE_BITS_MAX - 1 + BROTLI_REVERSE_BITS_BASE)) + (1U << (BROTLI_REVERSE_BITS_MAX - 1 + BROTLI_REVERSE_BITS_BASE)) /* Returns reverse(num >> BROTLI_REVERSE_BITS_BASE, BROTLI_REVERSE_BITS_MAX), where reverse(value, len) is the bit-wise reversal of the len least @@ -99,23 +99,22 @@ static BROTLI_INLINE int NextTableBitSize(const uint16_t* const count, return len - root_bits; } - void BrotliBuildCodeLengthsHuffmanTable(HuffmanCode* table, const uint8_t* const code_lengths, - uint16_t *count) { - HuffmanCode code; /* current table entry */ - int symbol; /* symbol index in original or sorted table */ - uint32_t key; /* prefix code */ - uint32_t key_step; /* prefix code addend */ - int step; /* step size to replicate values in current table */ - int table_size; /* size of current table */ - int sorted[18]; /* symbols sorted by code length */ + uint16_t* count) { + HuffmanCode code; /* current table entry */ + int symbol; /* symbol index in original or sorted table */ + uint32_t key; /* prefix code */ + uint32_t key_step; /* prefix code addend */ + int step; /* step size to replicate values in current table */ + int table_size; /* size of current table */ + int sorted[18]; /* symbols sorted by code length */ /* offsets in sorted table for each length */ int offset[BROTLI_HUFFMAN_MAX_CODE_LENGTH_CODE_LENGTH + 1]; int bits; int bits_count; - BROTLI_DCHECK( - BROTLI_HUFFMAN_MAX_CODE_LENGTH_CODE_LENGTH <= BROTLI_REVERSE_BITS_MAX); + BROTLI_DCHECK(BROTLI_HUFFMAN_MAX_CODE_LENGTH_CODE_LENGTH <= + BROTLI_REVERSE_BITS_MAX); /* generate offsets into sorted symbol table by code length */ symbol = -1; @@ -170,26 +169,26 @@ void BrotliBuildCodeLengthsHuffmanTable(HuffmanCode* table, uint32_t BrotliBuildHuffmanTable(HuffmanCode* root_table, int root_bits, const uint16_t* const symbol_lists, - uint16_t *count) { - HuffmanCode code; /* current table entry */ - HuffmanCode* table; /* next available space in table */ - int len; /* current code length */ - int symbol; /* symbol index in original or sorted table */ - uint32_t key; /* prefix code */ - uint32_t key_step; /* prefix code addend */ - uint32_t sub_key; /* 2nd level table prefix code */ - uint32_t sub_key_step;/* 2nd level table prefix code addend */ - int step; /* step size to replicate values in current table */ - int table_bits; /* key length of current table */ - int table_size; /* size of current table */ - int total_size; /* sum of root table size and 2nd level table sizes */ + uint16_t* count) { + HuffmanCode code; /* current table entry */ + HuffmanCode* table; /* next available space in table */ + int len; /* current code length */ + int symbol; /* symbol index in original or sorted table */ + uint32_t key; /* prefix code */ + uint32_t key_step; /* prefix code addend */ + uint32_t sub_key; /* 2nd level table prefix code */ + uint32_t sub_key_step; /* 2nd level table prefix code addend */ + int step; /* step size to replicate values in current table */ + int table_bits; /* key length of current table */ + int table_size; /* size of current table */ + int total_size; /* sum of root table size and 2nd level table sizes */ int max_length = -1; int bits; int bits_count; BROTLI_DCHECK(root_bits <= BROTLI_REVERSE_BITS_MAX); - BROTLI_DCHECK( - BROTLI_HUFFMAN_MAX_CODE_LENGTH - root_bits <= BROTLI_REVERSE_BITS_MAX); + BROTLI_DCHECK(BROTLI_HUFFMAN_MAX_CODE_LENGTH - root_bits <= + BROTLI_REVERSE_BITS_MAX); while (symbol_lists[max_length] == 0xFFFF) max_length--; max_length += BROTLI_HUFFMAN_MAX_CODE_LENGTH + 1; @@ -246,8 +245,8 @@ uint32_t BrotliBuildHuffmanTable(HuffmanCode* root_table, sub_key = BrotliReverseBits(key); key += key_step; root_table[sub_key].bits = (uint8_t)(table_bits + root_bits); - root_table[sub_key].value = (uint16_t)( - ((size_t)(table - root_table)) - sub_key); + root_table[sub_key].value = + (uint16_t)(((size_t)(table - root_table)) - sub_key); sub_key = 0; } code.bits = (uint8_t)(len - root_bits); @@ -265,7 +264,7 @@ uint32_t BrotliBuildHuffmanTable(HuffmanCode* root_table, uint32_t BrotliBuildSimpleHuffmanTable(HuffmanCode* table, int root_bits, - uint16_t *val, + uint16_t* val, uint32_t num_symbols) { uint32_t table_size = 1; const uint32_t goal_size = 1U << root_bits; @@ -302,49 +301,47 @@ uint32_t BrotliBuildSimpleHuffmanTable(HuffmanCode* table, table[3].bits = 2; table_size = 4; break; - case 3: - { - int i, k; - for (i = 0; i < 3; ++i) { - for (k = i + 1; k < 4; ++k) { - if (val[k] < val[i]) { - uint16_t t = val[k]; - val[k] = val[i]; - val[i] = t; - } + case 3: { + int i, k; + for (i = 0; i < 3; ++i) { + for (k = i + 1; k < 4; ++k) { + if (val[k] < val[i]) { + uint16_t t = val[k]; + val[k] = val[i]; + val[i] = t; } } - for (i = 0; i < 4; ++i) { - table[i].bits = 2; - } - table[0].value = val[0]; - table[2].value = val[1]; - table[1].value = val[2]; - table[3].value = val[3]; - table_size = 4; } - break; - case 4: - { - int i; - if (val[3] < val[2]) { - uint16_t t = val[3]; - val[3] = val[2]; - val[2] = t; - } - for (i = 0; i < 7; ++i) { - table[i].value = val[0]; - table[i].bits = (uint8_t)(1 + (i & 1)); - } - table[1].value = val[1]; - table[3].value = val[2]; - table[5].value = val[1]; - table[7].value = val[3]; - table[3].bits = 3; - table[7].bits = 3; - table_size = 8; + for (i = 0; i < 4; ++i) { + table[i].bits = 2; } + table[0].value = val[0]; + table[2].value = val[1]; + table[1].value = val[2]; + table[3].value = val[3]; + table_size = 4; break; + } + case 4: { + int i; + if (val[3] < val[2]) { + uint16_t t = val[3]; + val[3] = val[2]; + val[2] = t; + } + for (i = 0; i < 7; ++i) { + table[i].value = val[0]; + table[i].bits = (uint8_t)(1 + (i & 1)); + } + table[1].value = val[1]; + table[3].value = val[2]; + table[5].value = val[1]; + table[7].value = val[3]; + table[3].bits = 3; + table[7].bits = 3; + table_size = 8; + break; + } } while (table_size != goal_size) { memcpy(&table[table_size], &table[0], @@ -355,5 +352,5 @@ uint32_t BrotliBuildSimpleHuffmanTable(HuffmanCode* table, } #if defined(__cplusplus) || defined(c_plusplus) -} /* extern "C" */ +} /* extern "C" */ #endif diff --git a/modules/brotli/dec/huffman.h b/modules/brotli/dec/huffman.h index 010baedc9642..fc880810c666 100644 --- a/modules/brotli/dec/huffman.h +++ b/modules/brotli/dec/huffman.h @@ -10,6 +10,7 @@ #define BROTLI_DEC_HUFFMAN_H_ #include "./types.h" +#include "./port.h" #if defined(__cplusplus) || defined(c_plusplus) extern "C" { @@ -32,31 +33,25 @@ static const uint16_t kMaxHuffmanTableSize[] = { #define BROTLI_HUFFMAN_MAX_CODE_LENGTH_CODE_LENGTH 5 typedef struct { - uint8_t bits; /* number of bits used for this symbol */ - uint16_t value; /* symbol value or table offset */ + uint8_t bits; /* number of bits used for this symbol */ + uint16_t value; /* symbol value or table offset */ } HuffmanCode; - /* Builds Huffman lookup table assuming code lengths are in symbol order. */ -void BrotliBuildCodeLengthsHuffmanTable(HuffmanCode* root_table, - const uint8_t* const code_lengths, - uint16_t *count); +BROTLI_INTERNAL void BrotliBuildCodeLengthsHuffmanTable(HuffmanCode* root_table, + const uint8_t* const code_lengths, uint16_t* count); /* Builds Huffman lookup table assuming code lengths are in symbol order. */ /* Returns size of resulting table. */ -uint32_t BrotliBuildHuffmanTable(HuffmanCode* root_table, - int root_bits, - const uint16_t* const symbol_lists, - uint16_t *count_arg); +BROTLI_INTERNAL uint32_t BrotliBuildHuffmanTable(HuffmanCode* root_table, + int root_bits, const uint16_t* const symbol_lists, uint16_t* count_arg); /* Builds a simple Huffman table. The num_symbols parameter is to be */ /* interpreted as follows: 0 means 1 symbol, 1 means 2 symbols, 2 means 3 */ /* symbols, 3 means 4 symbols with lengths 2,2,2,2, 4 means 4 symbols with */ /* lengths 1,2,3,3. */ -uint32_t BrotliBuildSimpleHuffmanTable(HuffmanCode* table, - int root_bits, - uint16_t *symbols, - uint32_t num_symbols); +BROTLI_INTERNAL uint32_t BrotliBuildSimpleHuffmanTable(HuffmanCode* table, + int root_bits, uint16_t* symbols, uint32_t num_symbols); /* Contains a collection of Huffman trees with the same alphabet size. */ typedef struct { @@ -67,7 +62,7 @@ typedef struct { } HuffmanTreeGroup; #if defined(__cplusplus) || defined(c_plusplus) -} /* extern "C" */ +} /* extern "C" */ #endif #endif /* BROTLI_DEC_HUFFMAN_H_ */ diff --git a/modules/brotli/dec/port.h b/modules/brotli/dec/port.h index 392d0b17bd24..19b457c75b77 100644 --- a/modules/brotli/dec/port.h +++ b/modules/brotli/dec/port.h @@ -18,13 +18,16 @@ read and overlapping memcpy; this reduces decompression speed by 5% * BROTLI_DEBUG dumps file name and line number when decoder detects stream or memory error - * BROTLI_DECODE_DEBUG enables asserts and dumps various state information + * BROTLI_ENABLE_LOG enables asserts and dumps various state information */ #ifndef BROTLI_DEC_PORT_H_ #define BROTLI_DEC_PORT_H_ -#include +#if defined(BROTLI_ENABLE_LOG) || defined(BROTLI_DEBUG) +#include +#include +#endif /* Compatibility with non-clang compilers. */ #ifndef __has_builtin @@ -39,10 +42,6 @@ #define __has_feature(x) 0 #endif -#if defined(__sparc) -#define BROTLI_TARGET_SPARC -#endif - #if defined(__arm__) || defined(__thumb__) || \ defined(_M_ARM) || defined(_M_ARMT) #define BROTLI_TARGET_ARM @@ -55,6 +54,10 @@ #endif /* ARMv8 */ #endif /* ARM */ +#if defined(__i386) || defined(_M_IX86) +#define BROTLI_TARGET_X86 +#endif + #if defined(__x86_64__) || defined(_M_X64) #define BROTLI_TARGET_X64 #endif @@ -83,19 +86,14 @@ #define BROTLI_MODERN_COMPILER 0 #endif -/* SPARC and ARMv6 don't support unaligned read. - Choose portable build for them. */ -#if !defined(BROTLI_BUILD_PORTABLE) -#if defined(BROTLI_TARGET_SPARC) || \ - (defined(BROTLI_TARGET_ARM) && !defined(BROTLI_TARGET_ARMV7)) -#define BROTLI_BUILD_PORTABLE -#endif /* SPARK or ARMv6 */ -#endif /* portable build */ - #ifdef BROTLI_BUILD_PORTABLE -#define BROTLI_ALIGNED_READ 1 +#define BROTLI_ALIGNED_READ (!!1) +#elif defined(BROTLI_TARGET_X86) || defined(BROTLI_TARGET_X64) || \ + defined(BROTLI_TARGET_ARMV7) || defined(BROTLI_TARGET_ARMV8) +/* Allow unaligned read only for whitelisted CPUs. */ +#define BROTLI_ALIGNED_READ (!!0) #else -#define BROTLI_ALIGNED_READ 0 +#define BROTLI_ALIGNED_READ (!!1) #endif /* Define "PREDICT_TRUE" and "PREDICT_FALSE" macros for capable compilers. @@ -136,9 +134,21 @@ OR: #define ATTRIBUTE_ALWAYS_INLINE #endif +#if defined(_WIN32) || defined(__CYGWIN__) +#define ATTRIBUTE_VISIBILITY_HIDDEN +#elif BROTLI_MODERN_COMPILER || __has_attribute(visibility) +#define ATTRIBUTE_VISIBILITY_HIDDEN __attribute__ ((visibility ("hidden"))) +#else +#define ATTRIBUTE_VISIBILITY_HIDDEN +#endif + +#ifndef BROTLI_INTERNAL +#define BROTLI_INTERNAL ATTRIBUTE_VISIBILITY_HIDDEN +#endif + #ifndef _MSC_VER -#if defined(__cplusplus) || !defined(__STRICT_ANSI__) \ - || __STDC_VERSION__ >= 199901L +#if defined(__cplusplus) || !defined(__STRICT_ANSI__) || \ + __STDC_VERSION__ >= 199901L #define BROTLI_INLINE inline ATTRIBUTE_ALWAYS_INLINE #else #define BROTLI_INLINE @@ -147,10 +157,22 @@ OR: #define BROTLI_INLINE __forceinline #endif /* _MSC_VER */ -#ifdef BROTLI_DECODE_DEBUG +#ifdef BROTLI_ENABLE_LOG #define BROTLI_DCHECK(x) assert(x) +#define BROTLI_LOG(x) printf x #else #define BROTLI_DCHECK(x) +#define BROTLI_LOG(x) +#endif + +#if defined(BROTLI_DEBUG) || defined(BROTLI_ENABLE_LOG) +static inline void BrotliDump(const char* f, int l, const char* fn) { + fprintf(stderr, "%s:%d (%s)\n", f, l, fn); + fflush(stderr); +} +#define BROTLI_DUMP() BrotliDump(__FILE__, __LINE__, __FUNCTION__) +#else +#define BROTLI_DUMP() (void)(0) #endif #if defined(BROTLI_BUILD_64_BIT) @@ -190,14 +212,14 @@ OR: #endif #if BROTLI_MODERN_COMPILER || __has_attribute(noinline) -#define BROTLI_NOINLINE __attribute__ ((noinline)) +#define BROTLI_NOINLINE __attribute__((noinline)) #else #define BROTLI_NOINLINE #endif -#define BROTLI_REPEAT(N, X) { \ - if ((N & 1) != 0) {X;} \ - if ((N & 2) != 0) {X; X;} \ +#define BROTLI_REPEAT(N, X) { \ + if ((N & 1) != 0) {X;} \ + if ((N & 2) != 0) {X; X;} \ if ((N & 4) != 0) {X; X; X; X;} \ } @@ -220,9 +242,9 @@ static BROTLI_INLINE unsigned BrotliRBit(unsigned input) { #define BROTLI_ALLOC(S, L) S->alloc_func(S->memory_manager_opaque, L) -#define BROTLI_FREE(S, X) { \ +#define BROTLI_FREE(S, X) { \ S->free_func(S->memory_manager_opaque, X); \ - X = NULL; \ + X = NULL; \ } #define BROTLI_UNUSED(X) (void)(X) diff --git a/modules/brotli/dec/state.c b/modules/brotli/dec/state.c index d48e55d296e5..358e08d3d615 100644 --- a/modules/brotli/dec/state.c +++ b/modules/brotli/dec/state.c @@ -15,6 +15,10 @@ extern "C" { #endif +/* Declared in decode.h */ +int BrotliStateIsStreamStart(const BrotliState* s); +int BrotliStateIsStreamEnd(const BrotliState* s); + static void* DefaultAllocFunc(void* opaque, size_t size) { BROTLI_UNUSED(opaque); return malloc(size); @@ -76,7 +80,6 @@ void BrotliStateInitWithCustomAllocators(BrotliState* s, s->distance_hgroup.codes = NULL; s->distance_hgroup.htrees = NULL; - s->custom_dict = NULL; s->custom_dict_size = 0; @@ -115,7 +118,6 @@ void BrotliStateMetablockBegin(BrotliState* s) { s->context_modes = NULL; s->dist_context_map = NULL; s->context_map_slice = NULL; - s->literal_htree_index = 0; s->literal_htree = NULL; s->dist_context_map_slice = NULL; s->dist_htree_index = 0; @@ -161,7 +163,7 @@ void BrotliHuffmanTreeGroupInit(BrotliState* s, HuffmanTreeGroup* group, const size_t max_table_size = kMaxHuffmanTableSize[(alphabet_size + 31) >> 5]; const size_t code_size = sizeof(HuffmanCode) * ntrees * max_table_size; const size_t htree_size = sizeof(HuffmanCode*) * ntrees; - char *p = (char*)BROTLI_ALLOC(s, code_size + htree_size); + char* p = (char*)BROTLI_ALLOC(s, code_size + htree_size); group->alphabet_size = (uint16_t)alphabet_size; group->num_htrees = (uint16_t)ntrees; group->codes = (HuffmanCode*)p; @@ -174,5 +176,5 @@ void BrotliHuffmanTreeGroupRelease(BrotliState* s, HuffmanTreeGroup* group) { } #if defined(__cplusplus) || defined(c_plusplus) -} /* extern "C" */ +} /* extern "C" */ #endif diff --git a/modules/brotli/dec/state.h b/modules/brotli/dec/state.h index 026fc4fc12b9..63647ef2bcb9 100644 --- a/modules/brotli/dec/state.h +++ b/modules/brotli/dec/state.h @@ -12,6 +12,7 @@ #include "./bit_reader.h" #include "./huffman.h" #include "./types.h" +#include "./port.h" #if defined(__cplusplus) || defined(c_plusplus) extern "C" { @@ -119,6 +120,8 @@ struct BrotliStateStruct { int ringbuffer_mask; int dist_rb_idx; int dist_rb[4]; + int error_code; + uint32_t sub_loop_counter; uint8_t* ringbuffer; uint8_t* ringbuffer_end; HuffmanCode* htree_command; @@ -127,8 +130,6 @@ struct BrotliStateStruct { uint8_t* context_map_slice; uint8_t* dist_context_map_slice; - uint32_t sub_loop_counter; - /* This ring buffer holds a few past copy distances that will be used by */ /* some special distance codes. */ HuffmanTreeGroup literal_hgroup; @@ -150,13 +151,11 @@ struct BrotliStateStruct { int distance_postfix_mask; uint32_t num_dist_htrees; uint8_t* dist_context_map; - HuffmanCode *literal_htree; - uint8_t literal_htree_index; + HuffmanCode* literal_htree; uint8_t dist_htree_index; uint32_t repeat_code_len; uint32_t prev_code_len; - int copy_length; int distance_code; @@ -174,7 +173,7 @@ struct BrotliStateStruct { uint16_t* symbol_lists; /* Storage from symbol_lists. */ uint16_t symbols_lists_array[BROTLI_HUFFMAN_MAX_CODE_LENGTH + 1 + - BROTLI_HUFFMAN_MAX_CODE_LENGTHS_SIZE]; + BROTLI_HUFFMAN_MAX_CODE_LENGTHS_SIZE]; /* Tails of symbol chains. */ int next_symbol[32]; uint8_t code_length_code_lengths[18]; @@ -193,7 +192,7 @@ struct BrotliStateStruct { /* For InverseMoveToFrontTransform */ uint32_t mtf_upper_bound; - uint8_t mtf[256]; + uint8_t mtf[256 + 4]; /* For custom dictionaries */ const uint8_t* custom_dict; @@ -218,33 +217,26 @@ struct BrotliStateStruct { uint32_t num_literal_htrees; uint8_t* context_map; uint8_t* context_modes; + + uint32_t trivial_literal_contexts[8]; /* 256 bits */ }; -typedef struct BrotliStateStruct BrotliState; - -void BrotliStateInit(BrotliState* s); -void BrotliStateInitWithCustomAllocators(BrotliState* s, - brotli_alloc_func alloc_func, - brotli_free_func free_func, - void* opaque); -void BrotliStateCleanup(BrotliState* s); -void BrotliStateMetablockBegin(BrotliState* s); -void BrotliStateCleanupAfterMetablock(BrotliState* s); -void BrotliHuffmanTreeGroupInit(BrotliState* s, HuffmanTreeGroup* group, - uint32_t alphabet_size, uint32_t ntrees); -void BrotliHuffmanTreeGroupRelease(BrotliState* s, HuffmanTreeGroup* group); - -/* Returns 1, if s is in a state where we have not read any input bytes yet, - and 0 otherwise */ -int BrotliStateIsStreamStart(const BrotliState* s); - -/* Returns 1, if s is in a state where we reached the end of the input and - produced all of the output, and 0 otherwise. */ -int BrotliStateIsStreamEnd(const BrotliState* s); +typedef struct BrotliStateStruct BrotliStateInternal; +#define BrotliState BrotliStateInternal +BROTLI_INTERNAL void BrotliStateInit(BrotliState* s); +BROTLI_INTERNAL void BrotliStateInitWithCustomAllocators(BrotliState* s, + brotli_alloc_func alloc_func, brotli_free_func free_func, void* opaque); +BROTLI_INTERNAL void BrotliStateCleanup(BrotliState* s); +BROTLI_INTERNAL void BrotliStateMetablockBegin(BrotliState* s); +BROTLI_INTERNAL void BrotliStateCleanupAfterMetablock(BrotliState* s); +BROTLI_INTERNAL void BrotliHuffmanTreeGroupInit(BrotliState* s, + HuffmanTreeGroup* group, uint32_t alphabet_size, uint32_t ntrees); +BROTLI_INTERNAL void BrotliHuffmanTreeGroupRelease(BrotliState* s, + HuffmanTreeGroup* group); #if defined(__cplusplus) || defined(c_plusplus) -} /* extern "C" */ +} /* extern "C" */ #endif #endif /* BROTLI_DEC_STATE_H_ */ diff --git a/modules/brotli/dec/streams.c b/modules/brotli/dec/streams.c deleted file mode 100644 index 0c781a70351e..000000000000 --- a/modules/brotli/dec/streams.c +++ /dev/null @@ -1,102 +0,0 @@ -/* Copyright 2013 Google Inc. All Rights Reserved. - - Distributed under MIT license. - See file LICENSE for detail or copy at https://opensource.org/licenses/MIT -*/ - -/* Functions for streaming input and output. */ - -#include -#ifndef _WIN32 -#include -#endif -#include "./streams.h" - -#if defined(__cplusplus) || defined(c_plusplus) -extern "C" { -#endif - -int BrotliMemInputFunction(void* data, uint8_t* buf, size_t count) { - BrotliMemInput* input = (BrotliMemInput*)data; - if (input->pos > input->length) { - return -1; - } - if (input->pos + count > input->length) { - count = input->length - input->pos; - } - memcpy(buf, input->buffer + input->pos, count); - input->pos += count; - return (int)count; -} - -BrotliInput BrotliInitMemInput(const uint8_t* buffer, size_t length, - BrotliMemInput* mem_input) { - BrotliInput input; - mem_input->buffer = buffer; - mem_input->length = length; - mem_input->pos = 0; - input.cb_ = &BrotliMemInputFunction; - input.data_ = mem_input; - return input; -} - -int BrotliMemOutputFunction(void* data, const uint8_t* buf, size_t count) { - BrotliMemOutput* output = (BrotliMemOutput*)data; - size_t limit = output->length - output->pos; - if (count > limit) { - count = limit; - } - memcpy(output->buffer + output->pos, buf, count); - output->pos += count; - return (int)count; -} - -BrotliOutput BrotliInitMemOutput(uint8_t* buffer, size_t length, - BrotliMemOutput* mem_output) { - BrotliOutput output; - mem_output->buffer = buffer; - mem_output->length = length; - mem_output->pos = 0; - output.cb_ = &BrotliMemOutputFunction; - output.data_ = mem_output; - return output; -} - -int BrotliFileInputFunction(void* data, uint8_t* buf, size_t count) { - return (int)fread(buf, 1, count, (FILE*)data); -} - -BrotliInput BrotliFileInput(FILE* f) { - BrotliInput in; - in.cb_ = BrotliFileInputFunction; - in.data_ = f; - return in; -} - -int BrotliFileOutputFunction(void* data, const uint8_t* buf, size_t count) { - return (int)fwrite(buf, 1, count, (FILE*)data); -} - -BrotliOutput BrotliFileOutput(FILE* f) { - BrotliOutput out; - out.cb_ = BrotliFileOutputFunction; - out.data_ = f; - return out; -} - -int BrotliNullOutputFunction(void* data , const uint8_t* buf, size_t count) { - BROTLI_UNUSED(data); - BROTLI_UNUSED(buf); - return (int)count; -} - -BrotliOutput BrotliNullOutput(void) { - BrotliOutput out; - out.cb_ = BrotliNullOutputFunction; - out.data_ = NULL; - return out; -} - -#if defined(__cplusplus) || defined(c_plusplus) -} /* extern "C" */ -#endif diff --git a/modules/brotli/dec/streams.h b/modules/brotli/dec/streams.h deleted file mode 100644 index a849432749b6..000000000000 --- a/modules/brotli/dec/streams.h +++ /dev/null @@ -1,95 +0,0 @@ -/* Copyright 2013 Google Inc. All Rights Reserved. - - Distributed under MIT license. - See file LICENSE for detail or copy at https://opensource.org/licenses/MIT -*/ - -/* Functions for streaming input and output. */ - -#ifndef BROTLI_DEC_STREAMS_H_ -#define BROTLI_DEC_STREAMS_H_ - -#include -#include "./port.h" -#include "./types.h" - -#if defined(__cplusplus) || defined(c_plusplus) -extern "C" { -#endif - -/* Function pointer type used to read len bytes into buf. Returns the */ -/* number of bytes read or -1 on error. */ -typedef int (*BrotliInputFunction)(void* data, uint8_t* buf, size_t len); - -/* Input callback function with associated data. */ -typedef struct { - BrotliInputFunction cb_; - void* data_; -} BrotliInput; - -/* Reads len bytes into buf, using the in callback. */ -static BROTLI_INLINE int BrotliRead(BrotliInput in, uint8_t* buf, size_t len) { - return in.cb_(in.data_, buf, len); -} - -/* Function pointer type used to write len bytes into buf. Returns the */ -/* number of bytes written or -1 on error. */ -typedef int (*BrotliOutputFunction)(void* data, const uint8_t* buf, size_t len); - -/* Output callback function with associated data. */ -typedef struct { - BrotliOutputFunction cb_; - void* data_; -} BrotliOutput; - -/* Writes len bytes into buf, using the out callback. */ -static BROTLI_INLINE int BrotliWrite(BrotliOutput out, - const uint8_t* buf, size_t len) { - return out.cb_(out.data_, buf, len); -} - -/* Memory region with position. */ -typedef struct { - const uint8_t* buffer; - size_t length; - size_t pos; -} BrotliMemInput; - -/* Input callback where *data is a BrotliMemInput struct. */ -int BrotliMemInputFunction(void* data, uint8_t* buf, size_t count); - -/* Returns an input callback that wraps the given memory region. */ -BrotliInput BrotliInitMemInput(const uint8_t* buffer, size_t length, - BrotliMemInput* mem_input); - -/* Output buffer with position. */ -typedef struct { - uint8_t* buffer; - size_t length; - size_t pos; -} BrotliMemOutput; - -/* Output callback where *data is a BrotliMemOutput struct. */ -int BrotliMemOutputFunction(void* data, const uint8_t* buf, size_t count); - -/* Returns an output callback that wraps the given memory region. */ -BrotliOutput BrotliInitMemOutput(uint8_t* buffer, size_t length, - BrotliMemOutput* mem_output); - -/* Input callback that reads from a file. */ -int BrotliFileInputFunction(void* data, uint8_t* buf, size_t count); -BrotliInput BrotliFileInput(FILE* f); - -/* Output callback that writes to a file. */ -int BrotliFileOutputFunction(void* data, const uint8_t* buf, size_t count); -BrotliOutput BrotliFileOutput(FILE* f); - -/* Output callback that does nothing, always consumes the whole input. */ -int BrotliNullOutputFunction(void* data, const uint8_t* buf, size_t count); -BrotliOutput BrotliNullOutput(void); - -#if defined(__cplusplus) || defined(c_plusplus) -} /* extern "C" */ -#endif - -#endif /* BROTLI_DEC_STREAMS_H_ */ diff --git a/modules/brotli/dec/transform.h b/modules/brotli/dec/transform.h index 03aa2b94f884..8c08f3fc0b93 100644 --- a/modules/brotli/dec/transform.h +++ b/modules/brotli/dec/transform.h @@ -17,27 +17,27 @@ extern "C" { #endif enum WordTransformType { - kIdentity = 0, - kOmitLast1 = 1, - kOmitLast2 = 2, - kOmitLast3 = 3, - kOmitLast4 = 4, - kOmitLast5 = 5, - kOmitLast6 = 6, - kOmitLast7 = 7, - kOmitLast8 = 8, - kOmitLast9 = 9, + kIdentity = 0, + kOmitLast1 = 1, + kOmitLast2 = 2, + kOmitLast3 = 3, + kOmitLast4 = 4, + kOmitLast5 = 5, + kOmitLast6 = 6, + kOmitLast7 = 7, + kOmitLast8 = 8, + kOmitLast9 = 9, kUppercaseFirst = 10, - kUppercaseAll = 11, - kOmitFirst1 = 12, - kOmitFirst2 = 13, - kOmitFirst3 = 14, - kOmitFirst4 = 15, - kOmitFirst5 = 16, - kOmitFirst6 = 17, - kOmitFirst7 = 18, - kOmitFirst8 = 19, - kOmitFirst9 = 20 + kUppercaseAll = 11, + kOmitFirst1 = 12, + kOmitFirst2 = 13, + kOmitFirst3 = 14, + kOmitFirst4 = 15, + kOmitFirst5 = 16, + kOmitFirst6 = 17, + kOmitFirst7 = 18, + kOmitFirst8 = 19, + kOmitFirst9 = 20 }; typedef struct { @@ -66,15 +66,15 @@ enum { kPFix_SP = 1, kPFix_COMMASP = 3, kPFix_SPofSPtheSP = 6, - kPFix_SPtheSP = 9, + kPFix_SPtheSP = 9, kPFix_eSP = 12, - kPFix_SPofSP = 15, + kPFix_SPofSP = 15, kPFix_sSP = 20, kPFix_DOT = 23, kPFix_SPandSP = 25, kPFix_SPinSP = 31, kPFix_DQUOT = 36, - kPFix_SPtoSP = 38, + kPFix_SPtoSP = 38, kPFix_DQUOTGT = 43, kPFix_NEWLINE = 46, kPFix_DOTSP = 48, @@ -84,20 +84,20 @@ enum { kPFix_SPthatSP = 63, kPFix_SQUOT = 70, kPFix_SPwithSP = 72, - kPFix_SPfromSP = 79, - kPFix_SPbySP = 86, + kPFix_SPfromSP = 79, + kPFix_SPbySP = 86, kPFix_OPEN = 91, kPFix_DOTSPTheSP = 93, - kPFix_SPonSP = 100, - kPFix_SPasSP = 105, - kPFix_SPisSP = 110, + kPFix_SPonSP = 100, + kPFix_SPasSP = 105, + kPFix_SPisSP = 110, kPFix_ingSP = 115, kPFix_NEWLINETAB = 120, kPFix_COLON = 123, kPFix_edSP = 125, kPFix_EQDQUOT = 129, kPFix_SPatSP = 132, - kPFix_lySP = 137, + kPFix_lySP = 137, kPFix_COMMA = 141, kPFix_EQSQUOT = 143, kPFix_DOTcomSLASH = 146, @@ -114,7 +114,6 @@ enum { kPFix_ousSP = 203 }; - static const Transform kTransforms[] = { { kPFix_EMPTY, kIdentity, kPFix_EMPTY }, { kPFix_EMPTY, kIdentity, kPFix_SP }, @@ -241,7 +240,7 @@ static const Transform kTransforms[] = { static const int kNumTransforms = sizeof(kTransforms) / sizeof(kTransforms[0]); -static int ToUpperCase(uint8_t *p) { +static int ToUpperCase(uint8_t* p) { if (p[0] < 0xc0) { if (p[0] >= 'a' && p[0] <= 'z') { p[0] ^= 32; @@ -295,7 +294,7 @@ static BROTLI_NOINLINE int TransformDictionaryWord( } #if defined(__cplusplus) || defined(c_plusplus) -} /* extern "C" */ +} /* extern "C" */ #endif #endif /* BROTLI_DEC_TRANSFORM_H_ */ diff --git a/modules/brotli/dec/types.h b/modules/brotli/dec/types.h index 56fde60b3312..0f7a0216a044 100644 --- a/modules/brotli/dec/types.h +++ b/modules/brotli/dec/types.h @@ -29,10 +29,10 @@ typedef __int64 int64_t; size length. Neither items nor size are allowed to be 0. opaque argument is a pointer provided by client and could be used to bind function to specific object (memory pool). */ -typedef void* (*brotli_alloc_func) (void* opaque, size_t size); +typedef void* (*brotli_alloc_func)(void* opaque, size_t size); /* Deallocating function pointer. Function SHOULD be no-op in the case the address is 0. */ -typedef void (*brotli_free_func) (void* opaque, void* address); +typedef void (*brotli_free_func)(void* opaque, void* address); #endif /* BROTLI_DEC_TYPES_H_ */ diff --git a/modules/woff2/README.mozilla b/modules/woff2/README.mozilla index e1de8362f4ea..5a3a57499055 100644 --- a/modules/woff2/README.mozilla +++ b/modules/woff2/README.mozilla @@ -16,3 +16,6 @@ Current version: [commit 643c7b45891cbeb5dc1f7599a4c9b53fbe82a08f]. redefine-unique_ptr.patch redefines the class std::unique_ptr to workaround a build issue with missing C++11 features. See https://bugzilla.mozilla.org/show_bug.cgi?id=1227058 + +missing-assert-header.patch contains the upstream change from commit +07cd303dd2959cbf69a6840706c0896e49e42677 adding the missing assert.h header. diff --git a/modules/woff2/missing-assert-header.patch b/modules/woff2/missing-assert-header.patch new file mode 100644 index 000000000000..aac015b75a0d --- /dev/null +++ b/modules/woff2/missing-assert-header.patch @@ -0,0 +1,22 @@ +diff --git a/modules/woff2/src/port.h b/modules/woff2/src/port.h +--- a/modules/woff2/src/port.h ++++ b/modules/woff2/src/port.h +@@ -12,16 +12,18 @@ + // See the License for the specific language governing permissions and + // limitations under the License. + // + // Helper function for bit twiddling and macros for branch prediction. + + #ifndef WOFF2_PORT_H_ + #define WOFF2_PORT_H_ + ++#include ++ + namespace woff2 { + + typedef unsigned int uint32; + + inline int Log2Floor(uint32 n) { + #if defined(__GNUC__) + return n == 0 ? -1 : 31 ^ __builtin_clz(n); + #else diff --git a/modules/woff2/src/port.h b/modules/woff2/src/port.h index 4906fbcc4665..bac47a93a612 100644 --- a/modules/woff2/src/port.h +++ b/modules/woff2/src/port.h @@ -17,6 +17,8 @@ #ifndef WOFF2_PORT_H_ #define WOFF2_PORT_H_ +#include + namespace woff2 { typedef unsigned int uint32; diff --git a/modules/woff2/update.sh b/modules/woff2/update.sh index 6933accd934c..863fe2b235f2 100755 --- a/modules/woff2/update.sh +++ b/modules/woff2/update.sh @@ -13,6 +13,7 @@ perl -p -i -e "s/\[commit [0-9a-f]{40}\]/[${COMMIT}]/" README.mozilla; rm -rf src mv ${MY_TEMP_DIR}/woff2/src src patch -p3 < redefine-unique_ptr.patch +patch -p3 < missing-assert-header.patch rm -rf ${MY_TEMP_DIR} hg add src diff --git a/moz.configure b/moz.configure index 735611cd3727..426bb763fef9 100644 --- a/moz.configure +++ b/moz.configure @@ -85,6 +85,14 @@ set_define('GTEST_USE_OWN_TR1_TUPLE', set_define('GTEST_HAS_CLONE', delayed_getattr(linux_gtest_defines, 'has_clone')) +js_option('--enable-debug', + nargs='?', + help='Enable building with developer debug info ' + '(using the given compiler flags).') + +add_old_configure_assignment('MOZ_DEBUG', + depends_if('--enable-debug')(lambda _: True)) + @depends('--disable-compile-environment', '--help') def toolchain_include(compile_env, help): if compile_env: diff --git a/netwerk/base/nsIOService.cpp b/netwerk/base/nsIOService.cpp index 440837fd5d4f..a0170c5b7053 100644 --- a/netwerk/base/nsIOService.cpp +++ b/netwerk/base/nsIOService.cpp @@ -736,28 +736,6 @@ nsIOService::NewChannelFromURIWithProxyFlagsInternal(nsIURI* aURI, if (NS_FAILED(rv)) return rv; - if (sTelemetryEnabled) { - nsAutoCString path; - aURI->GetPath(path); - - bool endsInExcl = StringEndsWith(path, NS_LITERAL_CSTRING("!")); - int32_t bangSlashPos = path.Find("!/"); - - bool hasBangSlash = bangSlashPos != kNotFound; - bool hasBangDoubleSlash = false; - - if (bangSlashPos != kNotFound) { - nsDependentCSubstring substr(path, bangSlashPos); - hasBangDoubleSlash = StringBeginsWith(substr, NS_LITERAL_CSTRING("!//")); - } - - Telemetry::Accumulate(Telemetry::URL_PATH_ENDS_IN_EXCLAMATION, endsInExcl); - Telemetry::Accumulate(Telemetry::URL_PATH_CONTAINS_EXCLAMATION_SLASH, - hasBangSlash); - Telemetry::Accumulate(Telemetry::URL_PATH_CONTAINS_EXCLAMATION_DOUBLE_SLASH, - hasBangDoubleSlash); - } - nsCOMPtr handler; rv = GetProtocolHandler(scheme.get(), getter_AddRefs(handler)); if (NS_FAILED(rv)) diff --git a/old-configure.in b/old-configure.in index e3f5b622d8cd..fc0b345969e5 100644 --- a/old-configure.in +++ b/old-configure.in @@ -47,7 +47,7 @@ _SUBDIR_CONFIG_ARGS="$ac_configure_args" dnl Set the version number of the libs included with mozilla dnl ======================================================== MOZJPEG=62 -MOZPNG=10621 +MOZPNG=10623 NSPR_VERSION=4 NSPR_MINVER=4.12 NSS_VERSION=3 @@ -6477,7 +6477,6 @@ AC_SUBST(BIN_FLAGS) AC_SUBST(MOZ_AUTH_EXTENSION) AC_SUBST(MOZ_PREF_EXTENSIONS) AC_SUBST(MOZ_DEBUG) -AC_SUBST(MOZ_DEBUG_SYMBOLS) AC_SUBST(MOZ_DEBUG_LDFLAGS) AC_SUBST(WARNINGS_AS_ERRORS) AC_SUBST_SET(MOZ_EXTENSIONS) diff --git a/python/mozbuild/mozbuild/config_status.py b/python/mozbuild/mozbuild/config_status.py index 07b3a2c28016..4fb7b0e3c1ad 100644 --- a/python/mozbuild/mozbuild/config_status.py +++ b/python/mozbuild/mozbuild/config_status.py @@ -178,13 +178,3 @@ def config_status(topobjdir='.', topsrcdir='.', defines=None, if MachCommandConditions.is_android(env): if 'AndroidEclipse' not in options.backend: print(ANDROID_IDE_ADVERTISEMENT) - - if env.substs.get('MOZ_ARTIFACT_BUILDS', False): - # Execute |mach artifact install| from the top source directory. - os.chdir(topsrcdir) - return subprocess.check_call([ - sys.executable, - os.path.join(topsrcdir, 'mach'), - '--log-no-times', - 'artifact', - 'install']) diff --git a/python/mozbuild/mozbuild/mach_commands.py b/python/mozbuild/mozbuild/mach_commands.py index eedeeff904e7..714a9ad20f91 100644 --- a/python/mozbuild/mozbuild/mach_commands.py +++ b/python/mozbuild/mozbuild/mach_commands.py @@ -399,9 +399,6 @@ class Build(MachCommandBase): line_handler=output.on_line, log=False, print_directory=False) - if self.substs.get('MOZ_ARTIFACT_BUILDS', False): - self._run_mach_artifact_install() - # Build target pairs. for make_dir, make_target in target_pairs: # We don't display build status messages during partial @@ -416,19 +413,6 @@ class Build(MachCommandBase): if status != 0: break else: - try: - if self.substs.get('MOZ_ARTIFACT_BUILDS', False): - self._run_mach_artifact_install() - except BuildEnvironmentNotFoundException: - # Can't read self.substs from config.status? That means we - # need to run configure. The client.mk invocation below - # will configure, which will run config.status, which will - # invoke |mach artifact install| itself before continuing - # the build. Therefore, we needn't install artifacts - # ourselves. - self.log(logging.DEBUG, 'artifact', - {}, "Not running |mach artifact install| -- it will be run by client.mk.") - status = self._run_make(srcdir=True, filename='client.mk', line_handler=output.on_line, log=False, print_directory=False, allow_parallel=False, ensure_exit_code=False, num_jobs=jobs, @@ -660,18 +644,6 @@ class Build(MachCommandBase): return self._run_command_in_objdir(args=args, pass_thru=True, ensure_exit_code=False) - def _run_mach_artifact_install(self): - # We'd like to launch artifact using - # self._mach_context.commands.dispatch. However, artifact activates - # the virtualenv, which plays badly with the rest of this code. - # Therefore, we run |mach artifact install| in a new process (and - # throw an exception if it fails). - self.log(logging.INFO, 'artifact', - {}, "Running |mach artifact install|.") - args = [os.path.join(self.topsrcdir, 'mach'), 'artifact', 'install'] - self._run_command_in_srcdir(args=args, require_unix_environment=True, - pass_thru=True, ensure_exit_code=True) - @CommandProvider class Doctor(MachCommandBase): """Provide commands for diagnosing common build environment problems""" diff --git a/security/nss/TAG-INFO b/security/nss/TAG-INFO index 8a8d9ac0e483..170942fd05a9 100644 --- a/security/nss/TAG-INFO +++ b/security/nss/TAG-INFO @@ -1 +1 @@ -NSS_3_25_RC0 +NSS_3_25_RC1 diff --git a/security/nss/coreconf/coreconf.dep b/security/nss/coreconf/coreconf.dep index 590d1bfaeee3..5182f75552c8 100644 --- a/security/nss/coreconf/coreconf.dep +++ b/security/nss/coreconf/coreconf.dep @@ -10,4 +10,3 @@ */ #error "Do not include this header file." - diff --git a/security/nss/lib/freebl/Makefile b/security/nss/lib/freebl/Makefile index 57a865d45e7a..0df95c7cad55 100644 --- a/security/nss/lib/freebl/Makefile +++ b/security/nss/lib/freebl/Makefile @@ -522,7 +522,18 @@ ifndef NSS_DISABLE_CHACHAPOLY else EXTRA_SRCS += poly1305.c endif - EXTRA_SRCS += chacha20_vec.c + + ifeq ($(OS_TARGET),SunOS) + ifndef NS_USE_GCC + CHACHA_NO_SSE2 = 1 + endif + endif + + ifdef CHACHA_NO_SSE2 + EXTRA_SRCS += chacha20.c + else + EXTRA_SRCS += chacha20_vec.c + endif else EXTRA_SRCS += poly1305.c EXTRA_SRCS += chacha20.c diff --git a/security/nss/lib/ssl/ssl3con.c b/security/nss/lib/ssl/ssl3con.c index c2eda2e1061d..892bb1c46cdd 100644 --- a/security/nss/lib/ssl/ssl3con.c +++ b/security/nss/lib/ssl/ssl3con.c @@ -4018,12 +4018,16 @@ static CK_MECHANISM_TYPE ssl3_GetHashMechanismByHashType(SSLHashType hashType) { switch (hashType) { + case ssl_hash_sha512: + return CKM_SHA512; case ssl_hash_sha384: return CKM_SHA384; case ssl_hash_sha256: case ssl_hash_none: /* ssl_hash_none is for pre-1.2 suites, which use SHA-256. */ return CKM_SHA256; + case ssl_hash_sha1: + return CKM_SHA_1; default: PORT_Assert(0); } diff --git a/taskcluster/ci/legacy/tasks/branches/base_job_flags.yml b/taskcluster/ci/legacy/tasks/branches/base_job_flags.yml index 293527f87b2a..eb6682a60058 100644 --- a/taskcluster/ci/legacy/tasks/branches/base_job_flags.yml +++ b/taskcluster/ci/legacy/tasks/branches/base_job_flags.yml @@ -18,7 +18,9 @@ flags: - android-api-15-frontend - android-partner-sample1 - linux + - linux-l10n # Desktop l10n - linux64 + - linux64-l10n # Desktop l10n - linux64-st-an - linux64-artifact - linux64-asan diff --git a/taskcluster/ci/legacy/tasks/branches/base_jobs.yml b/taskcluster/ci/legacy/tasks/branches/base_jobs.yml index d99ba2fb8ab0..3a354ef00bce 100644 --- a/taskcluster/ci/legacy/tasks/branches/base_jobs.yml +++ b/taskcluster/ci/legacy/tasks/branches/base_jobs.yml @@ -15,6 +15,8 @@ builds: linux: platforms: - Linux + extra-builds: # see RIDEALONG_BUILDS in `mach taskgraph` + - linux-l10n types: opt: task: tasks/builds/opt_linux32.yml @@ -24,6 +26,7 @@ builds: platforms: - Linux64 extra-builds: # see RIDEALONG_BUILDS in `mach taskgraph` + - linux64-l10n - sm-plain - sm-nonunified - sm-arm-sim diff --git a/taskcluster/ci/legacy/tasks/branches/mozilla-central/job_flags.yml b/taskcluster/ci/legacy/tasks/branches/mozilla-central/job_flags.yml index 0e1259ad9c7b..4649db570bad 100644 --- a/taskcluster/ci/legacy/tasks/branches/mozilla-central/job_flags.yml +++ b/taskcluster/ci/legacy/tasks/branches/mozilla-central/job_flags.yml @@ -17,6 +17,8 @@ builds: types: opt: task: tasks/builds/android_api_15.yml + debug: + task: tasks/builds/android_api_15_debug.yml aries: platforms: - b2g diff --git a/taskcluster/ci/legacy/tasks/branches/try/job_flags.yml b/taskcluster/ci/legacy/tasks/branches/try/job_flags.yml index 53ef14c331bc..821a79ad7ce0 100644 --- a/taskcluster/ci/legacy/tasks/branches/try/job_flags.yml +++ b/taskcluster/ci/legacy/tasks/branches/try/job_flags.yml @@ -17,6 +17,8 @@ builds: types: opt: task: tasks/builds/android_api_15.yml + debug: + task: tasks/builds/android_api_15_debug.yml android-partner-sample1: platforms: - Android @@ -31,6 +33,21 @@ builds: task: tasks/builds/opt_linux32.yml debug: task: tasks/builds/dbg_linux32.yml + linux-l10n: + platforms: + - Linux64 + types: + opt: + task: tasks/builds/firefox_l10n_linux32.yml + when: + file_patterns: + - browser/locales/all-locales + - python/compare-locales/** + - testing/mozharness/configs/single_locale/** + - testing/mozharness/mozharness/mozilla/l10n/locales.py + - testing/mozharness/scripts/desktop_l10n.py + - toolkit/locales/** + - toolkit/mozapps/installer/** linux64: platforms: - Linux64 @@ -39,6 +56,21 @@ builds: task: tasks/builds/opt_linux64.yml debug: task: tasks/builds/dbg_linux64.yml + linux64-l10n: + platforms: + - Linux64 + types: + opt: + task: tasks/builds/firefox_l10n_linux64.yml + when: + file_patterns: + - browser/locales/all-locales + - python/compare-locales/** + - testing/mozharness/configs/single_locale/** + - testing/mozharness/mozharness/mozilla/l10n/locales.py + - testing/mozharness/scripts/desktop_l10n.py + - toolkit/locales/** + - toolkit/mozapps/installer/** linux64-st-an: platforms: - Linux64 Static Analysis diff --git a/taskcluster/ci/legacy/tasks/builds/android_api_15.yml b/taskcluster/ci/legacy/tasks/builds/android_api_15.yml index 85da59e4f668..5218d5e62e2e 100644 --- a/taskcluster/ci/legacy/tasks/builds/android_api_15.yml +++ b/taskcluster/ci/legacy/tasks/builds/android_api_15.yml @@ -51,6 +51,10 @@ task: machine: # see https://github.com/mozilla/treeherder/blob/master/ui/js/values.js platform: android-4-0-armv7-api15 + groupSymbol: tc + groupName: Submitted by taskcluster + symbol: B + tier: 2 # Rather then enforcing particular conventions we require that all build # tasks provide the "build" extra field to specify where the build and tests # files are located. diff --git a/taskcluster/ci/legacy/tasks/builds/android_api_15_debug.yml b/taskcluster/ci/legacy/tasks/builds/android_api_15_debug.yml new file mode 100644 index 000000000000..db45da5c8ea7 --- /dev/null +++ b/taskcluster/ci/legacy/tasks/builds/android_api_15_debug.yml @@ -0,0 +1,66 @@ +$inherits: + from: 'tasks/builds/mobile_base.yml' + variables: + build_name: 'android' + build_type: 'debug' +task: + metadata: + name: '[TC] Android armv7 API 15+ Dbg' + description: 'Android armv7 API 15+ Dbg' + + workerType: android-api-15 + + routes: + - 'index.buildbot.branches.{{project}}.android-api-15-dbg' + - 'index.buildbot.revisions.{{head_rev}}.{{project}}.android-api-15-dbg' + + scopes: + - 'docker-worker:cache:level-{{level}}-{{project}}-build-android-api-15-dbg-workspace' + - 'docker-worker:cache:tooltool-cache' + - 'docker-worker:relengapi-proxy:tooltool.download.internal' + - 'docker-worker:relengapi-proxy:tooltool.download.public' + + payload: + cache: + level-{{level}}-{{project}}-build-android-api-15-dbg-workspace: '/home/worker/workspace' + tooltool-cache: '/home/worker/tooltool-cache' + + features: + relengAPIProxy: true + + env: + # inputs to mozharness + MOZHARNESS_SCRIPT: 'mozharness/scripts/fx_desktop_build.py' + # TODO: make these additional configuration files go away + MOZHARNESS_CONFIG: > + builds/releng_base_android_64_builds.py + disable_signing.py + platform_supports_post_upload_to_latest.py + MOZHARNESS_ACTIONS: "get-secrets build multi-l10n update" + MH_CUSTOM_BUILD_VARIANT_CFG: api-15-debug + MH_BRANCH: {{project}} + MH_BUILD_POOL: taskcluster + + command: ["/bin/bash", "bin/build.sh"] + + extra: + treeherderEnv: + - production + - staging + treeherder: + machine: + # see https://github.com/mozilla/treeherder/blob/master/ui/js/values.js + platform: android-4-0-armv7-api15 + groupSymbol: tc + groupName: Submitted by taskcluster + symbol: B + tier: 2 + collection: + debug: true + # Rather then enforcing particular conventions we require that all build + # tasks provide the "build" extra field to specify where the build and tests + # files are located. + locations: + build: 'public/build/target.apk' + mozharness: 'public/build/mozharness.zip' + test_packages: 'public/build/target.test_packages.json' diff --git a/taskcluster/ci/legacy/tasks/builds/firefox_l10n_base.yml b/taskcluster/ci/legacy/tasks/builds/firefox_l10n_base.yml new file mode 100644 index 000000000000..c278f5c4ec58 --- /dev/null +++ b/taskcluster/ci/legacy/tasks/builds/firefox_l10n_base.yml @@ -0,0 +1,51 @@ +$inherits: + from: 'tasks/l10n.yml' + variables: + platform: 'linux64' + build_name: 'linux64-l10n' + build_product: 'firefox' + build_type: 'opt' +docker-image: desktop-build +task: + scopes: + - 'docker-worker:cache:tooltool-cache' + - 'docker-worker:relengapi-proxy:tooltool.download.public' + - 'docker-worker:cache:level-{{level}}-{{project}}-{{build_name}}-workspace' + + payload: + image: + type: 'task-image' + path: 'public/image.tar' + taskId: + task-reference: "" + cache: + tooltool-cache: '/home/worker/tooltool-cache' + level-{{level}}-{{project}}-l10n-{{build_name}}-workspace: '/home/worker/workspace' + + features: + relengAPIProxy: true + + env: + MOZHARNESS_SCRIPT: 'mozharness/scripts/desktop_l10n.py' + MOZHARNESS_CONFIG: 'single_locale/tc_{{platform}}.py' + MOZHARNESS_ACTIONS: 'clone-locales list-locales setup repack summary' + MOZHARNESS_OPTIONS: 'environment-config=single_locale/production.py branch-config=single_locale/{{project}}.py platform-config=single_locale/{{platform}}.py total-chunks=1 this-chunk=1' + JOB_SCRIPT: 'taskcluster/scripts/builder/build-l10n.sh' + MH_BRANCH: {{project}} + MH_BUILD_POOL: taskcluster + # image paths + TOOLTOOL_CACHE: '/home/worker/tooltool-cache' + NEED_XVFB: true + + maxRunTime: 36000 + + command: ["/bin/bash", "bin/build.sh"] + + extra: + treeherderEnv: + - production + - staging + treeherder: + machine: + # see https://github.com/mozilla/treeherder/blob/master/ui/js/values.js + platform: {{platform}} diff --git a/taskcluster/ci/legacy/tasks/builds/firefox_l10n_linux32.yml b/taskcluster/ci/legacy/tasks/builds/firefox_l10n_linux32.yml new file mode 100644 index 000000000000..ee9bb18a448d --- /dev/null +++ b/taskcluster/ci/legacy/tasks/builds/firefox_l10n_linux32.yml @@ -0,0 +1,19 @@ +$inherits: + from: 'tasks/builds/firefox_l10n_base.yml' + variables: + build_name: 'linux32-l10n' + platform: 'linux32' +task: + metadata: + name: '[TC] Linux32 L10n' + description: 'Linux32 L10n' + + workerType: opt-linux32 + + extra: + treeherder: + groupSymbol: tc + groupName: Submitted by taskcluster + tier: 2 + symbol: L10n + diff --git a/taskcluster/ci/legacy/tasks/builds/firefox_l10n_linux64.yml b/taskcluster/ci/legacy/tasks/builds/firefox_l10n_linux64.yml new file mode 100644 index 000000000000..433e8e37bc77 --- /dev/null +++ b/taskcluster/ci/legacy/tasks/builds/firefox_l10n_linux64.yml @@ -0,0 +1,19 @@ +$inherits: + from: 'tasks/builds/firefox_l10n_base.yml' + variables: + build_name: 'linux64-l10n' + platform: 'linux64' +task: + metadata: + name: '[TC] Linux64 L10n' + description: 'Linux64 L10n' + + workerType: opt-linux64 + + extra: + treeherder: + groupSymbol: tc + groupName: Submitted by taskcluster + tier: 2 + symbol: L10n + diff --git a/taskcluster/ci/legacy/tasks/decision/periodic_alder.yml b/taskcluster/ci/legacy/tasks/decision/periodic_alder.yml deleted file mode 100644 index 09db42776573..000000000000 --- a/taskcluster/ci/legacy/tasks/decision/periodic_alder.yml +++ /dev/null @@ -1,43 +0,0 @@ -taskId: '{{ "decision task" | as-slugid }}' -task: - created: '{{now}}' - deadline: '{{ "1 day" | from-now }}' - metadata: - source: '{{source}}' - owner: '{{owner}}' - name: 'Taskcluster decision task for {{project}}' - description: | - Decision task for testing purposes for alder. - - workerType: gecko-decision - provisionerId: aws-provisioner-v1 - - scopes: - - 'docker-worker:cache:level-{{level}}-{{project}}-tc-vcs-public-sources' - - payload: - cache: - # The taskcluster-vcs tooling stores the large clone caches in this - # directory and will reuse them for new requests this saves about 20s~ and - # is the most generic cache possible. - level-{{level}}-{{project}}-tc-vcs-public-sources: '/home/worker/.tc-vcs/' - - # Note: This task is built server side without the context or tooling that - # exist in tree so we must hard code the version - image: 'quay.io/mozilla/decision:0.0.3' - - # Virtually no network or other potentially risky operations happen as part - # of the task timeout aside from the initial clone. We intentionally have - # set this to a lower value _all_ decision tasks should use a root - # repository which is cached. - maxRunTime: 1800 - - command: - - /bin/bash - - -c - - echo "test: {{comment}} ({{revision}}) for {{owner}}" - graphs: - - /home/worker/graph.json - extra: - treeherder: - symbol: D diff --git a/taskcluster/ci/legacy/tasks/l10n.yml b/taskcluster/ci/legacy/tasks/l10n.yml new file mode 100644 index 000000000000..ffd4ec5f789c --- /dev/null +++ b/taskcluster/ci/legacy/tasks/l10n.yml @@ -0,0 +1,65 @@ +# This is the "base" task which contains the common values all builds must +# provide. +--- +taskId: {{build_slugid}} + +task: + created: '{{now}}' + deadline: '{{#from_now}}24 hours{{/from_now}}' + metadata: + source: '{{source}}' + owner: mozilla-taskcluster-maintenance@mozilla.com + + tags: + createdForUser: {{owner}} + + workerType: b2gbuild + provisionerId: aws-provisioner-v1 + schedulerId: task-graph-scheduler + + scopes: + # Nearly all of our build tasks use tc-vcs so just include the scope across + # the board. + - 'docker-worker:cache:level-{{level}}-{{project}}-tc-vcs' + + payload: + # Two hours is long but covers edge cases (and matches bb based infra) + maxRunTime: 7200 + + cache: + level-{{level}}-{{project}}-tc-vcs: '/home/worker/.tc-vcs' + + # All builds share a common artifact directory for ease of uploading. + artifacts: + 'public/build': + type: directory + path: '/home/worker/workspace/build/upload/' + expires: '{{#from_now}}1 year{{/from_now}}' + + + env: + # Common environment variables for checking out gecko + GECKO_BASE_REPOSITORY: '{{base_repository}}' + GECKO_HEAD_REPOSITORY: '{{head_repository}}' + GECKO_HEAD_REV: '{{head_rev}}' + GECKO_HEAD_REF: '{{head_ref}}' + TOOLTOOL_REPO: 'https://git.mozilla.org/build/tooltool.git' + TOOLTOOL_REV: 'master' + MOZ_BUILD_DATE: '{{pushdate}}' + MOZ_SCM_LEVEL: '{{level}}' + + extra: + # Don't set locations yet + locations: + build: null + tests: null + build_product: '{{build_product}}' + build_name: '{{build_name}}' + build_type: '{{build_type}}' + index: + rank: {{pushlog_id}} + treeherder: + groupSymbol: tc + groupName: Submitted by taskcluster + tier: 2 + symbol: L10n diff --git a/taskcluster/docs/taskgraph.rst b/taskcluster/docs/taskgraph.rst index 88cf9b9f4814..eec93d6bdef9 100644 --- a/taskcluster/docs/taskgraph.rst +++ b/taskcluster/docs/taskgraph.rst @@ -63,11 +63,10 @@ Decision Task The decision task is the first task created when a new graph begins. It is responsible for creating the rest of the task graph. -The decision task for pushes is defined in-tree, currently at -``testing/taskcluster/tasks/decision``. The task description invokes ``mach -taskcluster decision`` with some metadata about the push. That mach command -determines the optimized task graph, then calls the TaskCluster API to create -the tasks. +The decision task for pushes is defined in-tree, in ``.taskcluster.yml``. The +task description invokes ``mach taskcluster decision`` with some metadata about +the push. That mach command determines the optimized task graph, then calls +the TaskCluster API to create the tasks. Graph Generation ---------------- diff --git a/taskcluster/taskgraph/kind/legacy.py b/taskcluster/taskgraph/kind/legacy.py index a774864e1e2d..6282d5e02416 100644 --- a/taskcluster/taskgraph/kind/legacy.py +++ b/taskcluster/taskgraph/kind/legacy.py @@ -116,8 +116,9 @@ def configure_dependent_task(task_path, parameters, taskid, templates, build_tre treeherder_config['build'] = \ build_treeherder_config.get('build', {}) - treeherder_config['machine'] = \ - build_treeherder_config.get('machine', {}) + if 'machine' not in treeherder_config: + treeherder_config['machine'] = \ + build_treeherder_config.get('machine', {}) if 'routes' not in task['task']: task['task']['routes'] = [] diff --git a/taskcluster/taskgraph/test/test_create.py b/taskcluster/taskgraph/test/test_create.py index 85b670dc8070..3d0f4021cb1e 100644 --- a/taskcluster/taskgraph/test/test_create.py +++ b/taskcluster/taskgraph/test/test_create.py @@ -43,6 +43,7 @@ class TestCreate(unittest.TestCase): self.created_tasks[task_id] = task_def def test_create_tasks(self): + os.environ['TASK_ID'] = 'decisiontask' kind = FakeKind() tasks = { 'tid-a': Task(kind=kind, label='a', task={'payload': 'hello world'}), @@ -58,6 +59,9 @@ class TestCreate(unittest.TestCase): self.assertEqual(task['payload'], 'hello world') # make sure the dependencies exist, at least for depid in task.get('dependencies', []): + if depid is 'decisiontask': + # Don't look for decisiontask here + continue self.assertIn(depid, self.created_tasks) def test_create_task_without_dependencies(self): diff --git a/taskcluster/taskgraph/test/test_decision.py b/taskcluster/taskgraph/test/test_decision.py index 04e625818913..19c51c617ff5 100644 --- a/taskcluster/taskgraph/test/test_decision.py +++ b/taskcluster/taskgraph/test/test_decision.py @@ -26,7 +26,7 @@ class TestDecision(unittest.TestCase): graph = Graph(nodes=set('ab'), edges={('a', 'b', 'edgelabel')}) taskgraph = TaskGraph(tasks, graph) - res = decision.taskgraph_to_json(taskgraph) + res = taskgraph.to_json() self.assertEqual(res, { 'a': { diff --git a/taskcluster/taskgraph/test/test_try_option_syntax.py b/taskcluster/taskgraph/test/test_try_option_syntax.py index cd8cd56cbba6..d9db5770bd7e 100644 --- a/taskcluster/taskgraph/test/test_try_option_syntax.py +++ b/taskcluster/taskgraph/test/test_try_option_syntax.py @@ -120,24 +120,28 @@ class TestTryOptionSyntax(unittest.TestCase): self.assertEqual(tos.platforms, None) def test_p_linux(self): - "-p linux sets platforms=['linux']" + "-p linux sets platforms=['linux', 'linux-l10n']" tos = TryOptionSyntax('try: -p linux', empty_graph) - self.assertEqual(tos.platforms, ['linux']) + self.assertEqual(tos.platforms, ['linux', 'linux-l10n']) def test_p_linux_win32(self): - "-p linux,win32 sets platforms=['linux', 'win32']" + "-p linux,win32 sets platforms=['linux', 'linux-l10n', 'win32']" tos = TryOptionSyntax('try: -p linux,win32', empty_graph) - self.assertEqual(sorted(tos.platforms), ['linux', 'win32']) + self.assertEqual(sorted(tos.platforms), ['linux', 'linux-l10n', 'win32']) def test_p_expands_ridealongs(self): "-p linux,linux64 includes the RIDEALONG_BUILDS" tos = TryOptionSyntax('try: -p linux,linux64', empty_graph) self.assertEqual(sorted(tos.platforms), [ 'linux', + 'linux-l10n', 'linux64', + 'linux64-l10n', 'sm-arm-sim', 'sm-arm64-sim', 'sm-compacting', + 'sm-nonunified', + 'sm-package', 'sm-plain', 'sm-rootanalysis', ]) diff --git a/taskcluster/taskgraph/try_option_syntax.py b/taskcluster/taskgraph/try_option_syntax.py index c6ea5e1a3d8d..6defeb2c8699 100644 --- a/taskcluster/taskgraph/try_option_syntax.py +++ b/taskcluster/taskgraph/try_option_syntax.py @@ -120,12 +120,18 @@ UNITTEST_PLATFORM_PRETTY_NAMES = { # least build-ish things. Sort of. Anyway, these other things are implemented # as different "platforms". RIDEALONG_BUILDS = { + 'linux': [ + 'linux-l10n', + ], 'linux64': [ + 'linux64-l10n', 'sm-plain', + 'sm-nonunified', 'sm-arm-sim', 'sm-arm64-sim', 'sm-compacting', 'sm-rootanalysis', + 'sm-package', ], } diff --git a/taskcluster/taskgraph/util/legacy_commit_parser.py b/taskcluster/taskgraph/util/legacy_commit_parser.py index ca6013f320e6..851ac3867319 100644 --- a/taskcluster/taskgraph/util/legacy_commit_parser.py +++ b/taskcluster/taskgraph/util/legacy_commit_parser.py @@ -339,7 +339,11 @@ def parse_commit(message, jobs): if base not in jobs['builds']: continue platforms.add(base) - platforms.update(jobs['builds'][base].get('extra-builds', [])) + for extra_build in jobs['builds'][base].get('extra-builds', []): + # Silently skip extra-builds of unknown platforms + if extra_build not in jobs['builds']: + continue + platforms.update([extra_build]) tests = normalize_test_list(aliases, jobs['flags']['tests'], args.tests) diff --git a/testing/marionette/driver.js b/testing/marionette/driver.js index c6bcb3c4e733..a041fcf5b9ee 100644 --- a/testing/marionette/driver.js +++ b/testing/marionette/driver.js @@ -1786,7 +1786,16 @@ GeckoDriver.prototype.getElementAttribute = function*(cmd, resp) { case Context.CHROME: let win = this.getCurrentWindow(); let el = this.curBrowser.seenEls.get(id, {frame: win}); - resp.body.value = atom.getElementAttribute(el, name, this.getCurrentWindow()); + + if (element.isBooleanAttribute(el, name)) { + if (el.hasAttribute(name)) { + resp.body.value = "true"; + } else { + resp.body.value = null; + } + } else { + resp.body.value = el.getAttribute(name); + } break; case Context.CONTENT: diff --git a/testing/marionette/harness/marionette/tests/unit/test_mouse_action.py b/testing/marionette/harness/marionette/tests/unit/test_mouse_action.py index 65d46aa719d2..475214375038 100644 --- a/testing/marionette/harness/marionette/tests/unit/test_mouse_action.py +++ b/testing/marionette/harness/marionette/tests/unit/test_mouse_action.py @@ -50,7 +50,7 @@ class TestMouseAction(MarionetteTestCase): def context_menu_state(): with self.marionette.using_context("chrome"): cm_el = self.marionette.find_element(By.ID, "contentAreaContextMenu") - return cm_el.get_attribute("state") + return cm_el.get_property("state") self.assertEqual("closed", context_menu_state()) self.action.context_click(click_el).perform() @@ -87,20 +87,20 @@ class TestMouseAction(MarionetteTestCase): with self.marionette.using_context("chrome"): urlbar = self.marionette.find_element(By.ID, "urlbar") - self.assertEqual("", urlbar.get_attribute("value")) + self.assertEqual("", urlbar.get_property("value")) urlbar.send_keys(test_word) - self.assertEqual(urlbar.get_attribute("value"), test_word) + self.assertEqual(urlbar.get_property("value"), test_word) (self.action.double_click(urlbar).perform() .key_down(self.mod_key) .key_down("x").perform()) - self.assertEqual(urlbar.get_attribute("value"), "") + self.assertEqual(urlbar.get_property("value"), "") def test_chrome_context_click_action(self): self.marionette.set_context("chrome") def context_menu_state(): cm_el = self.marionette.find_element(By.ID, "tabContextMenu") - return cm_el.get_attribute("state") + return cm_el.get_property("state") currtab = self.marionette.execute_script("return gBrowser.selectedTab") self.assertEqual("closed", context_menu_state()) diff --git a/testing/marionette/harness/marionette/tests/unit/test_typing.py b/testing/marionette/harness/marionette/tests/unit/test_typing.py index ecb2ff3883df..4c849665457c 100644 --- a/testing/marionette/harness/marionette/tests/unit/test_typing.py +++ b/testing/marionette/harness/marionette/tests/unit/test_typing.py @@ -83,9 +83,9 @@ class TestTyping(MarionetteTestCase): url_bar.send_keys(mod_key, "a") url_bar.send_keys(Keys.BACK_SPACE) - self.assertEqual("", url_bar.get_attribute("value")) + self.assertEqual("", url_bar.get_property("value")) url_bar.send_keys(mod_key, "v") - self.assertEqual("zyxwvutsr", url_bar.get_attribute("value")) + self.assertEqual("zyxwvutsr", url_bar.get_property("value")) def testShouldBeAbleToTypeQuoteMarks(self): test_html = self.marionette.absolute_url("javascriptPage.html") diff --git a/testing/mozbase/mozrunner/mozrunner/application.py b/testing/mozbase/mozrunner/mozrunner/application.py index 24bfa26ae3c9..19e90ca48c40 100644 --- a/testing/mozbase/mozrunner/mozrunner/application.py +++ b/testing/mozbase/mozrunner/mozrunner/application.py @@ -2,12 +2,13 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. +from abc import ABCMeta, abstractmethod from distutils.spawn import find_executable import glob import os import posixpath -from mozdevice import DeviceManagerADB, DMError +from mozdevice import DeviceManagerADB, DMError, DroidADB from mozprofile import ( Profile, FirefoxProfile, @@ -17,12 +18,14 @@ from mozprofile import ( here = os.path.abspath(os.path.dirname(__file__)) + def get_app_context(appname): context_map = { 'default': DefaultContext, 'b2g': B2GContext, 'firefox': FirefoxContext, 'thunderbird': ThunderbirdContext, - 'metro': MetroContext } + 'metro': MetroContext, + 'fennec': FennecContext} if appname not in context_map: raise KeyError("Application '%s' not supported!" % appname) return context_map[appname] @@ -32,12 +35,100 @@ class DefaultContext(object): profile_class = Profile -class B2GContext(object): - _bindir = None +class RemoteContext(object): + __metaclass__ = ABCMeta _dm = None _remote_profile = None - _remote_settings_db = None + _adb = None profile_class = Profile + dm_class = DeviceManagerADB + _bindir = None + remote_test_root = '' + remote_process = None + + @property + def bindir(self): + if self._bindir is None: + paths = [find_executable('emulator')] + paths = [p for p in paths if p is not None if os.path.isfile(p)] + if not paths: + self._bindir = '' + else: + self._bindir = os.path.dirname(paths[0]) + return self._bindir + + @property + def adb(self): + if not self._adb: + paths = [os.environ.get('ADB'), + os.environ.get('ADB_PATH'), + self.which('adb')] + paths = [p for p in paths if p is not None if os.path.isfile(p)] + if not paths: + raise OSError( + 'Could not find the adb binary, make sure it is on your' \ + 'path or set the $ADB_PATH environment variable.') + self._adb = paths[0] + return self._adb + + @property + def dm(self): + if not self._dm: + self._dm = self.dm_class(adbPath=self.adb, autoconnect=False) + return self._dm + + @property + def remote_profile(self): + if not self._remote_profile: + self._remote_profile = posixpath.join(self.remote_test_root, + 'profile') + return self._remote_profile + + def which(self, binary): + paths = os.environ.get('PATH', {}).split(os.pathsep) + if self.bindir is not None and os.path.abspath(self.bindir) not in paths: + paths.insert(0, os.path.abspath(self.bindir)) + os.environ['PATH'] = os.pathsep.join(paths) + + return find_executable(binary) + + @abstractmethod + def stop_application(self): + """ Run (device manager) command to stop application. """ + pass + + +class FennecContext(RemoteContext): + _remote_profiles_ini = None + _remote_test_root = None + + def __init__(self, app=None, adb_path=None, avd_home=None): + self._adb = adb_path + self.avd_home = avd_home + self.dm_class = DroidADB + self.remote_process = app or self.dm._packageName + + def stop_application(self): + self.dm.stopApplication(self.remote_process) + + @property + def remote_test_root(self): + if not self._remote_test_root: + self._remote_test_root = self.dm.getDeviceRoot() + return self._remote_test_root + + @property + def remote_profiles_ini(self): + if not self._remote_profiles_ini: + self._remote_profiles_ini = posixpath.join( + self.dm.getAppRoot(self.remote_process), + 'files', 'mozilla', 'profiles.ini' + ) + return self._remote_profiles_ini + + +class B2GContext(RemoteContext): + _remote_settings_db = None def __init__(self, b2g_home=None, adb_path=None): self.homedir = b2g_home or os.environ.get('B2G_HOME') @@ -76,19 +167,6 @@ class B2GContext(object): self._update_tools = os.path.join(self.homedir, 'tools', 'update-tools') return self._update_tools - @property - def adb(self): - if not self._adb: - paths = [os.environ.get('ADB'), - os.environ.get('ADB_PATH'), - self.which('adb')] - paths = [p for p in paths if p is not None if os.path.isfile(p)] - if not paths: - raise OSError('Could not find the adb binary, make sure it is on your' \ - 'path or set the $ADB_PATH environment variable.') - self._adb = paths[0] - return self._adb - @property def bindir(self): if self._bindir is None and self.homedir is not None: @@ -99,18 +177,6 @@ class B2GContext(object): self._bindir = paths[0] return self._bindir - @property - def dm(self): - if not self._dm: - self._dm = DeviceManagerADB(adbPath=self.adb, autoconnect=False, deviceRoot=self.remote_test_root) - return self._dm - - @property - def remote_profile(self): - if not self._remote_profile: - self._remote_profile = posixpath.join(self.remote_test_root, 'profile') - return self._remote_profile - @property def remote_settings_db(self): if not self._remote_settings_db: @@ -122,14 +188,6 @@ class B2GContext(object): raise DMError("Could not find settings db in '%s'!" % self.remote_idb_dir) return self._remote_settings_db - def which(self, binary): - paths = os.environ.get('PATH', {}).split(os.pathsep) - if self.bindir is not None and os.path.abspath(self.bindir) not in paths: - paths.insert(0, os.path.abspath(self.bindir)) - os.environ['PATH'] = os.pathsep.join(paths) - - return find_executable(binary) - def stop_application(self): self.dm.shellCheckOutput(['stop', 'b2g']) diff --git a/testing/mozbase/mozrunner/mozrunner/base/__init__.py b/testing/mozbase/mozrunner/mozrunner/base/__init__.py index 932d92bc956b..c154c3aafbe9 100644 --- a/testing/mozbase/mozrunner/mozrunner/base/__init__.py +++ b/testing/mozbase/mozrunner/mozrunner/base/__init__.py @@ -1,3 +1,3 @@ from .runner import BaseRunner -from .device import DeviceRunner +from .device import DeviceRunner, FennecRunner from .browser import GeckoRuntimeRunner diff --git a/testing/mozbase/mozrunner/mozrunner/base/device.py b/testing/mozbase/mozrunner/mozrunner/base/device.py index a2ad47d7ba1b..cbd9cc40282b 100644 --- a/testing/mozbase/mozrunner/mozrunner/base/device.py +++ b/testing/mozbase/mozrunner/mozrunner/base/device.py @@ -14,7 +14,7 @@ import time import mozfile from .runner import BaseRunner -from ..devices import Emulator +from ..devices import BaseEmulator class DeviceRunner(BaseRunner): """ @@ -65,7 +65,7 @@ class DeviceRunner(BaseRunner): return cmd def start(self, *args, **kwargs): - if isinstance(self.device, Emulator) and not self.device.connected: + if isinstance(self.device, BaseEmulator) and not self.device.connected: self.device.start() self.device.connect() self.device.setup_profile(self.profile) @@ -78,7 +78,7 @@ class DeviceRunner(BaseRunner): if not self.device.wait_for_net(): raise Exception("Network did not come up when starting device") - BaseRunner.start(self, *args, **kwargs) + pid = BaseRunner.start(self, *args, **kwargs) timeout = 10 # seconds starttime = datetime.datetime.now() @@ -91,6 +91,7 @@ class DeviceRunner(BaseRunner): if not self.device.wait_for_net(): raise Exception("Failed to get a network connection") + return pid def stop(self, sig=None): def _wait_for_shutdown(pid, timeout=10): @@ -142,17 +143,37 @@ class DeviceRunner(BaseRunner): def on_finish(self): self.check_for_crashes() - def check_for_crashes(self, dump_save_path=None, test_name=None): + def check_for_crashes(self, dump_save_path=None, test_name=None, **kwargs): test_name = test_name or self.last_test dump_dir = self.device.pull_minidumps() crashed = BaseRunner.check_for_crashes( self, dump_directory=dump_dir, dump_save_path=dump_save_path, - test_name=test_name) + test_name=test_name, + **kwargs) mozfile.remove(dump_dir) return crashed def cleanup(self, *args, **kwargs): BaseRunner.cleanup(self, *args, **kwargs) self.device.cleanup() + + +class FennecRunner(DeviceRunner): + + @property + def command(self): + cmd = [self.app_ctx.adb] + if self.app_ctx.dm._deviceSerial: + cmd.extend(['-s', self.app_ctx.dm._deviceSerial]) + cmd.append('shell') + app = "%s/org.mozilla.gecko.BrowserApp" % self.app_ctx.remote_process + cmd.extend(['am', 'start', '-a', 'android.activity.MAIN', '-n', app]) + params = ['-no-remote', '-profile', self.app_ctx.remote_profile] + cmd.extend(['--es', 'args', '"%s"' % ' '.join(params)]) + # Append env variables in the form "--es env0 MOZ_CRASHREPORTER=1" + for (count, (k, v)) in enumerate(self._device_env.iteritems()): + cmd.extend(["--es", "env" + str(count), k + "=" + v]) + + return cmd diff --git a/testing/mozbase/mozrunner/mozrunner/devices/__init__.py b/testing/mozbase/mozrunner/mozrunner/devices/__init__.py index ee126e1bc3c3..468e92e14072 100644 --- a/testing/mozbase/mozrunner/mozrunner/devices/__init__.py +++ b/testing/mozbase/mozrunner/mozrunner/devices/__init__.py @@ -2,7 +2,7 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this file, # You can obtain one at http://mozilla.org/MPL/2.0/. -from emulator import Emulator +from emulator import BaseEmulator, Emulator, EmulatorAVD from base import Device import emulator_battery diff --git a/testing/mozbase/mozrunner/mozrunner/devices/base.py b/testing/mozbase/mozrunner/mozrunner/devices/base.py index d35bd7f41157..d5d63c470434 100644 --- a/testing/mozbase/mozrunner/mozrunner/devices/base.py +++ b/testing/mozbase/mozrunner/mozrunner/devices/base.py @@ -18,13 +18,14 @@ from mozprocess import ProcessHandler class Device(object): connected = False + logcat_proc = None def __init__(self, app_ctx, logdir=None, serial=None, restore=True): self.app_ctx = app_ctx self.dm = self.app_ctx.dm self.restore = restore self.serial = serial - self.logdir = logdir + self.logdir = os.path.abspath(os.path.expanduser(logdir)) self.added_files = set() self.backup_files = set() diff --git a/testing/mozbase/mozrunner/mozrunner/devices/emulator.py b/testing/mozbase/mozrunner/mozrunner/devices/emulator.py index d1746af7bf9d..afc063bb9564 100644 --- a/testing/mozbase/mozrunner/mozrunner/devices/emulator.py +++ b/testing/mozbase/mozrunner/mozrunner/devices/emulator.py @@ -7,7 +7,6 @@ import datetime import os import shutil import subprocess -import sys import tempfile import time @@ -19,17 +18,25 @@ from .emulator_geo import EmulatorGeo from .emulator_screen import EmulatorScreen from ..errors import TimeoutException + class ArchContext(object): - def __init__(self, arch, context, binary=None): - kernel = os.path.join(context.homedir, 'prebuilts', 'qemu-kernel', '%s', '%s') - sysdir = os.path.join(context.homedir, 'out', 'target', 'product', '%s') + def __init__(self, arch, context, binary=None, avd=None, extra_args=None): + homedir = getattr(context,'homedir', '') + kernel = os.path.join(homedir, 'prebuilts', 'qemu-kernel', '%s', '%s') + sysdir = os.path.join(homedir, 'out', 'target', 'product', '%s') + self.extra_args = [] + self.binary = os.path.join(context.bindir or '', 'emulator') if arch == 'x86': - self.binary = os.path.join(context.bindir, 'emulator-x86') + self.binary = os.path.join(context.bindir or '', 'emulator-x86') self.kernel = kernel % ('x86', 'kernel-qemu') self.sysdir = sysdir % 'generic_x86' - self.extra_args = [] + elif avd: + self.avd = avd + self.extra_args = [ + '-show-kernel', '-debug', + 'init,console,gles,memcheck,adbserver,adbclient,adb,avd_config,socket' + ] else: - self.binary = os.path.join(context.bindir, 'emulator') self.kernel = kernel % ('arm', 'kernel-qemu-armv7') self.sysdir = sysdir % 'generic' self.extra_args = ['-cpu', 'cortex-a8'] @@ -37,27 +44,45 @@ class ArchContext(object): if binary: self.binary = binary + if extra_args: + self.extra_args.extend(extra_args) -class Emulator(Device): - logcat_proc = None + +class SDCard(object): + def __init__(self, emulator, size): + self.emulator = emulator + self.path = self.create_sdcard(size) + + def create_sdcard(self, sdcard_size): + """ + Creates an sdcard partition in the emulator. + + :param sdcard_size: Size of partition to create, e.g '10MB'. + """ + mksdcard = self.emulator.app_ctx.which('mksdcard') + path = tempfile.mktemp(prefix='sdcard', dir=self.emulator.tmpdir) + sdargs = [mksdcard, '-l', 'mySdCard', sdcard_size, path] + sd = subprocess.Popen(sdargs, stdout=subprocess.PIPE, + stderr=subprocess.STDOUT) + retcode = sd.wait() + if retcode: + raise Exception('unable to create sdcard: exit code %d: %s' + % (retcode, sd.stdout.read())) + return path + + +class BaseEmulator(Device): port = None proc = None telnet = None - def __init__(self, app_ctx, arch, resolution=None, sdcard=None, userdata=None, - no_window=None, binary=None, **kwargs): - Device.__init__(self, app_ctx, **kwargs) - - self.arch = ArchContext(arch, self.app_ctx, binary=binary) - self.resolution = resolution or '320x480' + def __init__(self, app_ctx, **kwargs): + self.arch = ArchContext(kwargs.pop('arch', 'arm'), app_ctx, + binary=kwargs.pop('binary', None), + avd=kwargs.pop('avd', None)) + super(BaseEmulator, self).__init__(app_ctx, **kwargs) self.tmpdir = tempfile.mkdtemp() - self.sdcard = None - if sdcard: - self.sdcard = self.create_sdcard(sdcard) - self.userdata = tempfile.NamedTemporaryFile(prefix='userdata-qemu', dir=self.tmpdir) - self.initdata = userdata if userdata else os.path.join(self.arch.sysdir, 'userdata.img') - self.no_window = no_window - + # These rely on telnet self.battery = EmulatorBattery(self) self.geo = EmulatorGeo(self) self.screen = EmulatorScreen(self) @@ -67,23 +92,7 @@ class Emulator(Device): """ Arguments to pass into the emulator binary. """ - qemu_args = [self.arch.binary, - '-kernel', self.arch.kernel, - '-sysdir', self.arch.sysdir, - '-data', self.userdata.name, - '-initdata', self.initdata, - '-wipe-data'] - if self.no_window: - qemu_args.append('-no-window') - if self.sdcard: - qemu_args.extend(['-sdcard', self.sdcard]) - qemu_args.extend(['-memory', '512', - '-partition-size', '512', - '-verbose', - '-skin', self.resolution, - '-gpu', 'on', - '-qemu'] + self.arch.extra_args) - return qemu_args + return [self.arch.binary] def start(self): """ @@ -118,15 +127,18 @@ class Emulator(Device): time.sleep(1) # Sometimes it takes more than 60s to launch emulator, so we # increase timeout value to 180s. Please see bug 1143380. - if datetime.datetime.now() - now > datetime.timedelta(seconds=180): - raise TimeoutException('timed out waiting for emulator to start') + if datetime.datetime.now() - now > datetime.timedelta( + seconds=180): + raise TimeoutException( + 'timed out waiting for emulator to start') devices = set(self._get_online_devices()) devices = devices - original_devices self.serial = devices.pop() self.connect() def _get_online_devices(self): - return set([d[0] for d in self.dm.devices() if d[1] != 'offline' if d[0].startswith('emulator')]) + return [d[0] for d in self.dm.devices() if d[1] != 'offline' if + d[0].startswith('emulator')] def connect(self): """ @@ -136,47 +148,25 @@ class Emulator(Device): if self.connected: return - Device.connect(self) - - self.port = int(self.serial[self.serial.rindex('-')+1:]) - self.geo.set_default_location() - self.screen.initialize() - - # setup DNS fix for networking - self.app_ctx.dm.shellCheckOutput(['setprop', 'net.dns1', '10.0.2.3']) - - def create_sdcard(self, sdcard_size): - """ - Creates an sdcard partition in the emulator. - - :param sdcard_size: Size of partition to create, e.g '10MB'. - """ - mksdcard = self.app_ctx.which('mksdcard') - path = tempfile.mktemp(prefix='sdcard', dir=self.tmpdir) - sdargs = [mksdcard, '-l', 'mySdCard', sdcard_size, path] - sd = subprocess.Popen(sdargs, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) - retcode = sd.wait() - if retcode: - raise Exception('unable to create sdcard: exit code %d: %s' - % (retcode, sd.stdout.read())) - return path + super(BaseEmulator, self).connect() + serial = self.serial or self.dm._deviceSerial + self.port = int(serial[serial.rindex('-') + 1:]) def cleanup(self): """ - Cleans up and kills the emulator. + Cleans up and kills the emulator, if it was started by mozrunner. """ - Device.cleanup(self) + super(BaseEmulator, self).cleanup() if self.proc: self.proc.kill() self.proc = None # Remove temporary files - self.userdata.close() shutil.rmtree(self.tmpdir) def _get_telnet_response(self, command=None): output = [] - assert(self.telnet) + assert self.telnet if command is not None: self.telnet.write('%s\n' % command) while True: @@ -197,3 +187,96 @@ class Emulator(Device): if self.telnet: self.telnet.write('exit\n') self.telnet.read_all() + + +class Emulator(BaseEmulator): + def __init__(self, app_ctx, arch, resolution=None, sdcard=None, userdata=None, + no_window=None, binary=None, **kwargs): + super(Emulator, self).__init__(app_ctx, arch=arch, binary=binary, **kwargs) + + # emulator args + self.resolution = resolution or '320x480' + self._sdcard_size = sdcard + self._sdcard = None + self.userdata = tempfile.NamedTemporaryFile(prefix='userdata-qemu', dir=self.tmpdir) + self.initdata = userdata if userdata else os.path.join(self.arch.sysdir, 'userdata.img') + self.no_window = no_window + + @property + def sdcard(self): + if self._sdcard_size and not self._sdcard: + self._sdcard = SDCard(self, self._sdcard_size).path + else: + return self._sdcard + + @property + def args(self): + """ + Arguments to pass into the emulator binary. + """ + qemu_args = super(Emulator, self).args + qemu_args.extend([ + '-kernel', self.arch.kernel, + '-sysdir', self.arch.sysdir, + '-data', self.userdata.name, + '-initdata', self.initdata, + '-wipe-data']) + if self.no_window: + qemu_args.append('-no-window') + if self.sdcard: + qemu_args.extend(['-sdcard', self.sdcard]) + qemu_args.extend(['-memory', '512', + '-partition-size', '512', + '-verbose', + '-skin', self.resolution, + '-gpu', 'on', + '-qemu'] + self.arch.extra_args) + return qemu_args + + def connect(self): + """ + Connects to a running device. If no serial was specified in the + constructor, defaults to the first entry in `adb devices`. + """ + if self.connected: + return + + super(Emulator, self).connect() + self.geo.set_default_location() + self.screen.initialize() + + # setup DNS fix for networking + self.app_ctx.dm.shellCheckOutput(['setprop', 'net.dns1', '10.0.2.3']) + + def cleanup(self): + """ + Cleans up and kills the emulator, if it was started by mozrunner. + """ + super(Emulator, self).cleanup() + # Remove temporary files + self.userdata.close() + +class EmulatorAVD(BaseEmulator): + def __init__(self, app_ctx, binary, avd, port=5554, **kwargs): + super(EmulatorAVD, self).__init__(app_ctx, binary=binary, avd=avd, **kwargs) + self.port = port + + @property + def args(self): + """ + Arguments to pass into the emulator binary. + """ + qemu_args = super(EmulatorAVD, self).args + qemu_args.extend(['-avd', self.arch.avd, + '-port', str(self.port)]) + qemu_args.extend(self.arch.extra_args) + return qemu_args + + def start(self): + if self.proc: + return + + env = os.environ + env['ANDROID_AVD_HOME'] = self.app_ctx.avd_home + + super(EmulatorAVD, self).start() diff --git a/testing/mozbase/mozrunner/mozrunner/runners.py b/testing/mozbase/mozrunner/mozrunner/runners.py index bbd65f8ee458..235bee652dc6 100644 --- a/testing/mozbase/mozrunner/mozrunner/runners.py +++ b/testing/mozbase/mozrunner/mozrunner/runners.py @@ -8,8 +8,8 @@ used Mozilla applications, such as Firefox or B2G emulator. """ from .application import get_app_context -from .base import DeviceRunner, GeckoRuntimeRunner -from .devices import Emulator, Device +from .base import DeviceRunner, GeckoRuntimeRunner, FennecRunner +from .devices import Emulator, EmulatorAVD, Device def Runner(*args, **kwargs): @@ -92,6 +92,43 @@ def B2GDesktopRunner(*args, **kwargs): return Runner(*args, **kwargs) +def FennecEmulatorRunner(avd='mozemulator-4.3', + adb_path=None, + avd_home=None, + logdir=None, + serial=None, + binary=None, + app='org.mozilla.fennec', + **kwargs): + """ + Create a Fennec emulator runner. This can either start a new emulator + (which will use an avd), or connect to an already-running emulator. + + :param avd: name of an AVD available in your environment. + Typically obtained via tooltool: either 'mozemulator-4.3' or 'mozemulator-x86'. Defaults to 'mozemulator-4.3' + :param avd_home: Path to avd parent directory + :param logdir: Path to save logfiles such as logcat and qemu output. + :param serial: Serial of emulator to connect to as seen in `adb devices`. + Defaults to the first entry in `adb devices`. + :param binary: Path to emulator binary. + Defaults to None, which causes the device_class to guess based on PATH. + :param app: Name of Fennec app (often org.mozilla.fennec_$USER) + Defaults to 'org.mozilla.fennec' + :returns: A DeviceRunner for Android emulators. + """ + kwargs['app_ctx'] = get_app_context('fennec')(app, adb_path=adb_path, + avd_home=avd_home) + device_args = { 'app_ctx': kwargs['app_ctx'], + 'avd': avd, + 'binary': binary, + 'serial': serial, + 'logdir': logdir + } + return FennecRunner(device_class=EmulatorAVD, + device_args=device_args, + **kwargs) + + def B2GEmulatorRunner(arch='arm', b2g_home=None, adb_path=None, @@ -168,5 +205,6 @@ runners = { 'b2g_device': B2GDeviceRunner, 'firefox': FirefoxRunner, 'thunderbird': ThunderbirdRunner, + 'fennec': FennecEmulatorRunner } diff --git a/testing/mozharness/configs/android/androidarm_4_3.py b/testing/mozharness/configs/android/androidarm_4_3.py index 3a16251d09dc..1bd24ef9100d 100644 --- a/testing/mozharness/configs/android/androidarm_4_3.py +++ b/testing/mozharness/configs/android/androidarm_4_3.py @@ -2,7 +2,7 @@ import os config = { "buildbot_json_path": "buildprops.json", - "host_utils_url": "http://talos-remote.pvt.build.mozilla.org/tegra/tegra-host-utils.Linux.1109310.2.zip", + "hostutils_manifest_path": "testing/config/tooltool-manifests/linux64/hostutils.manifest", "robocop_package_name": "org.mozilla.roboexample.test", "tooltool_manifest_path": "testing/config/tooltool-manifests/androidarm_4_3/releng.manifest", "tooltool_cache": "/builds/tooltool_cache", diff --git a/testing/mozharness/configs/android/androidx86.py b/testing/mozharness/configs/android/androidx86.py index b6f06e2d46a4..835d38a5c668 100644 --- a/testing/mozharness/configs/android/androidx86.py +++ b/testing/mozharness/configs/android/androidx86.py @@ -2,7 +2,7 @@ import os config = { "buildbot_json_path": "buildprops.json", - "host_utils_url": "http://talos-remote.pvt.build.mozilla.org/tegra/tegra-host-utils.Linux.1109310.2.zip", + "hostutils_manifest_path": "testing/config/tooltool-manifests/linux64/hostutils.manifest", "robocop_package_name": "org.mozilla.roboexample.test", "device_ip": "127.0.0.1", "tooltool_manifest_path": "testing/config/tooltool-manifests/androidx86/releng.manifest", diff --git a/testing/mozharness/configs/single_locale/linux32.py b/testing/mozharness/configs/single_locale/linux32.py new file mode 120000 index 000000000000..e9866bbbfa9f --- /dev/null +++ b/testing/mozharness/configs/single_locale/linux32.py @@ -0,0 +1 @@ +linux.py \ No newline at end of file diff --git a/testing/mozharness/configs/single_locale/tc_linux32.py b/testing/mozharness/configs/single_locale/tc_linux32.py new file mode 100644 index 000000000000..0fa0294b26a8 --- /dev/null +++ b/testing/mozharness/configs/single_locale/tc_linux32.py @@ -0,0 +1,24 @@ +import os + +config = { + "locales_file": "src/browser/locales/all-locales", + "tools_repo": "https://hg.mozilla.org/build/tools", + "mozconfig": "src/browser/config/mozconfigs/linux64/l10n-mozconfig", + "bootstrap_env": { + "NO_MERCURIAL_SETUP_CHECK": "1", + "MOZ_OBJDIR": "obj-l10n", + "EN_US_BINARY_URL": "%(en_us_binary_url)s", + "LOCALE_MERGEDIR": "%(abs_merge_dir)s/", + "MOZ_UPDATE_CHANNEL": "%(update_channel)s", + "DIST": "%(abs_objdir)s", + "LOCALE_MERGEDIR": "%(abs_merge_dir)s/", + "L10NBASEDIR": "../../l10n", + "MOZ_MAKE_COMPLETE_MAR": "1", + 'TOOLTOOL_CACHE': os.environ.get('TOOLTOOL_CACHE'), + }, + "upload_env": { + 'UPLOAD_HOST': 'localhost', + 'UPLOAD_PATH': '/home/worker/workspace/build/upload/', + }, + "mozilla_dir": "src/", +} diff --git a/testing/mozharness/scripts/android_emulator_unittest.py b/testing/mozharness/scripts/android_emulator_unittest.py index 6010774077b2..54c227902dd3 100644 --- a/testing/mozharness/scripts/android_emulator_unittest.py +++ b/testing/mozharness/scripts/android_emulator_unittest.py @@ -7,6 +7,7 @@ import copy import datetime +import glob import os import sys import signal @@ -32,13 +33,6 @@ from mozharness.mozilla.testing.unittest import EmulatorMixin class AndroidEmulatorTest(BlobUploadMixin, TestingMixin, EmulatorMixin, VCSMixin, BaseScript, MozbaseMixin): config_options = [[ - ["--host-utils-url"], - {"action": "store", - "dest": "xre_url", - "default": None, - "help": "URL to the host utils zip", - } - ], [ ["--test-suite"], {"action": "store", "dest": "test_suite", @@ -104,12 +98,12 @@ class AndroidEmulatorTest(BlobUploadMixin, TestingMixin, EmulatorMixin, VCSMixin self.test_url = c.get('test_url') self.test_manifest = c.get('test_manifest') self.robocop_path = os.path.join(abs_dirs['abs_work_dir'], "robocop.apk") - self.host_utils_url = c.get('host_utils_url') self.minidump_stackwalk_path = c.get("minidump_stackwalk_path") self.emulator = c.get('emulator') self.test_suite_definitions = c['test_suite_definitions'] self.test_suite = c.get('test_suite') self.sdk_level = None + self.xre_path = None assert self.test_suite in self.test_suite_definitions def _query_tests_dir(self): @@ -408,7 +402,7 @@ class AndroidEmulatorTest(BlobUploadMixin, TestingMixin, EmulatorMixin, VCSMixin Save a screenshot of the entire screen to the blob upload directory. """ dirs = self.query_abs_dirs() - utility = os.path.join(dirs['abs_xre_dir'], "bin", "screentopng") + utility = os.path.join(self.xre_path, "screentopng") if not os.path.exists(utility): self.warning("Unable to take screenshot: %s does not exist" % utility) return @@ -462,8 +456,8 @@ class AndroidEmulatorTest(BlobUploadMixin, TestingMixin, EmulatorMixin, VCSMixin str_format_values = { 'app': self._query_package_name(), 'remote_webserver': c['remote_webserver'], - 'xre_path': os.path.join(dirs['abs_xre_dir'], 'xre'), - 'utility_path': os.path.join(dirs['abs_xre_dir'], 'bin'), + 'xre_path': self.xre_path, + 'utility_path': self.xre_path, 'http_port': self.emulator['http_port'], 'ssl_port': self.emulator['ssl_port'], 'certs_path': os.path.join(dirs['abs_work_dir'], 'tests/certs'), @@ -500,22 +494,21 @@ class AndroidEmulatorTest(BlobUploadMixin, TestingMixin, EmulatorMixin, VCSMixin return cmd - def _tooltool_fetch(self, url): + def _tooltool_fetch(self, url, dir): c = self.config - dirs = self.query_abs_dirs() manifest_path = self.download_file( url, file_name='releng.manifest', - parent_dir=dirs['abs_avds_dir'] + parent_dir=dir ) if not os.path.exists(manifest_path): - self.fatal("Could not retrieve manifest needed to retrieve avds " + self.fatal("Could not retrieve manifest needed to retrieve " "artifacts from %s" % manifest_path) self.tooltool_fetch(manifest_path, - output_dir=dirs['abs_avds_dir'], + output_dir=dir, cache=c.get("tooltool_cache", None)) ########################################## @@ -540,13 +533,13 @@ class AndroidEmulatorTest(BlobUploadMixin, TestingMixin, EmulatorMixin, VCSMixin # XXX until we figure out how to determine the repo_path, revision url = 'https://hg.mozilla.org/%s/raw-file/%s/%s' % ( "try", "default", c["tooltool_manifest_path"]) - self._tooltool_fetch(url) + self._tooltool_fetch(url, dirs['abs_avds_dir']) elif self.buildbot_config and 'properties' in self.buildbot_config: url = 'https://hg.mozilla.org/%s/raw-file/%s/%s' % ( self.buildbot_config['properties']['repo_path'], self.buildbot_config['properties']['revision'], c["tooltool_manifest_path"]) - self._tooltool_fetch(url) + self._tooltool_fetch(url, dirs['abs_avds_dir']) else: self.fatal("properties in self.buildbot_config are required to " "retrieve tooltool manifest to be used for avds setup") @@ -634,7 +627,19 @@ class AndroidEmulatorTest(BlobUploadMixin, TestingMixin, EmulatorMixin, VCSMixin robocop_url = self.installer_url[:self.installer_url.rfind('/')] + '/robocop.apk' self.info("Downloading robocop...") self.download_file(robocop_url, 'robocop.apk', dirs['abs_work_dir'], error_level=FATAL) - self.download_unzip(self.host_utils_url, dirs['abs_xre_dir']) + self.rmtree(dirs['abs_xre_dir']) + self.mkdir_p(dirs['abs_xre_dir']) + if self.config["hostutils_manifest_path"]: + url = 'https://hg.mozilla.org/%s/raw-file/%s/%s' % ( + "try", "default", self.config["hostutils_manifest_path"]) + self._tooltool_fetch(url, dirs['abs_xre_dir']) + for p in glob.glob(os.path.join(dirs['abs_xre_dir'], 'host-utils-*')): + if os.path.isdir(p) and os.path.isfile(os.path.join(p, 'xpcshell')): + self.xre_path = p + if not self.xre_path: + self.fatal("xre path not found in %s" % dirs['abs_xre_dir']) + else: + self.fatal("configure hostutils_manifest_path!") def install(self): """ diff --git a/testing/mozharness/scripts/androidx86_emulator_unittest.py b/testing/mozharness/scripts/androidx86_emulator_unittest.py index 461149a0c69d..774e5318a3ed 100644 --- a/testing/mozharness/scripts/androidx86_emulator_unittest.py +++ b/testing/mozharness/scripts/androidx86_emulator_unittest.py @@ -6,6 +6,7 @@ # ***** END LICENSE BLOCK ***** import copy +import glob import os import sys import signal @@ -38,13 +39,6 @@ class AndroidEmulatorTest(BlobUploadMixin, TestingMixin, EmulatorMixin, VCSMixin "default": None, "help": "URL to the robocop apk", } - ], [ - ["--host-utils-url"], - {"action": "store", - "dest": "xre_url", - "default": None, - "help": "URL to the host utils zip", - } ], [ ["--test-suite"], {"action": "append", @@ -110,13 +104,13 @@ class AndroidEmulatorTest(BlobUploadMixin, TestingMixin, EmulatorMixin, VCSMixin self.test_manifest = c.get('test_manifest') self.robocop_url = c.get('robocop_url') self.robocop_path = os.path.join(abs_dirs['abs_work_dir'], "robocop.apk") - self.host_utils_url = c.get('host_utils_url') self.minidump_stackwalk_path = c.get("minidump_stackwalk_path") self.emulators = c.get('emulators') self.test_suite_definitions = c['test_suite_definitions'] self.test_suites = c.get('test_suites') for suite in self.test_suites: assert suite in self.test_suite_definitions + self.xre_path = None def _query_tests_dir(self, suite_name): dirs = self.query_abs_dirs() @@ -430,8 +424,8 @@ class AndroidEmulatorTest(BlobUploadMixin, TestingMixin, EmulatorMixin, VCSMixin str_format_values = { 'app': self._query_package_name(), 'remote_webserver': c['remote_webserver'], - 'xre_path': os.path.join(dirs['abs_xre_dir'], 'xre'), - 'utility_path': os.path.join(dirs['abs_xre_dir'], 'bin'), + 'xre_path': self.xre_path, + 'utility_path': self.xre_path, 'http_port': emulator['http_port'], 'ssl_port': emulator['ssl_port'], 'certs_path': os.path.join(dirs['abs_work_dir'], 'tests/certs'), @@ -509,22 +503,21 @@ class AndroidEmulatorTest(BlobUploadMixin, TestingMixin, EmulatorMixin, VCSMixin "emulator_index": emulator_index } - def _tooltool_fetch(self, url): + def _tooltool_fetch(self, url, dir): c = self.config - dirs = self.query_abs_dirs() manifest_path = self.download_file( url, file_name='releng.manifest', - parent_dir=dirs['abs_avds_dir'] + parent_dir=dir ) if not os.path.exists(manifest_path): - self.fatal("Could not retrieve manifest needed to retrieve avds " + self.fatal("Could not retrieve manifest needed to retrieve " "artifacts from %s" % manifest_path) self.tooltool_fetch(manifest_path, - output_dir=dirs['abs_avds_dir'], + output_dir=dir, cache=c.get("tooltool_cache", None)) ########################################## @@ -549,13 +542,13 @@ class AndroidEmulatorTest(BlobUploadMixin, TestingMixin, EmulatorMixin, VCSMixin # XXX until we figure out how to determine the repo_path, revision url = 'https://hg.mozilla.org/%s/raw-file/%s/%s' % ( "try", "default", c["tooltool_manifest_path"]) - self._tooltool_fetch(url) + self._tooltool_fetch(url, dirs['abs_avds_dir']) elif self.buildbot_config and 'properties' in self.buildbot_config: url = 'https://hg.mozilla.org/%s/raw-file/%s/%s' % ( self.buildbot_config['properties']['repo_path'], self.buildbot_config['properties']['revision'], c["tooltool_manifest_path"]) - self._tooltool_fetch(url) + self._tooltool_fetch(url, dirs['abs_avds_dir']) else: self.fatal("properties in self.buildbot_config are required to " "retrieve tooltool manifest to be used for avds setup") @@ -686,7 +679,19 @@ class AndroidEmulatorTest(BlobUploadMixin, TestingMixin, EmulatorMixin, VCSMixin self._download_robocop_apk() break - self.download_unzip(self.host_utils_url, dirs['abs_xre_dir']) + self.rmtree(dirs['abs_xre_dir']) + self.mkdir_p(dirs['abs_xre_dir']) + if self.config["hostutils_manifest_path"]: + url = 'https://hg.mozilla.org/%s/raw-file/%s/%s' % ( + "try", "default", self.config["hostutils_manifest_path"]) + self._tooltool_fetch(url, dirs['abs_xre_dir']) + for p in glob.glob(os.path.join(dirs['abs_xre_dir'], 'host-utils-*')): + if os.path.isdir(p) and os.path.isfile(os.path.join(p, 'xpcshell')): + self.xre_path = p + if not self.xre_path: + self.fatal("xre path not found in %s" % dirs['abs_xre_dir']) + else: + self.fatal("configure hostutils_manifest_path!") def install(self): assert self.installer_path is not None, \ diff --git a/toolkit/components/perfmonitoring/nsPerformanceStats.cpp b/toolkit/components/perfmonitoring/nsPerformanceStats.cpp index a5e47c964ab0..c16425c0b15a 100644 --- a/toolkit/components/perfmonitoring/nsPerformanceStats.cpp +++ b/toolkit/components/perfmonitoring/nsPerformanceStats.cpp @@ -1027,13 +1027,18 @@ nsPerformanceStatsService::GetNextId() { } /* static*/ bool -nsPerformanceStatsService::GetPerformanceGroupsCallback(JSContext* cx, JSGroupVector& out, void* closure) { +nsPerformanceStatsService::GetPerformanceGroupsCallback(JSContext* cx, + js::PerformanceGroupVector& out, + void* closure) +{ RefPtr self = reinterpret_cast(closure); return self->GetPerformanceGroups(cx, out); } bool -nsPerformanceStatsService::GetPerformanceGroups(JSContext* cx, JSGroupVector& out) { +nsPerformanceStatsService::GetPerformanceGroups(JSContext* cx, + js::PerformanceGroupVector& out) +{ JS::RootedObject global(cx, JS::CurrentGlobalOrNull(cx)); if (!global) { // While it is possible for a compartment to have no global @@ -1136,13 +1141,17 @@ nsPerformanceStatsService::StopwatchStart(uint64_t iteration) { } /*static*/ bool -nsPerformanceStatsService::StopwatchCommitCallback(uint64_t iteration, JSGroupVector& recentGroups, void* closure) { +nsPerformanceStatsService::StopwatchCommitCallback(uint64_t iteration, + js::PerformanceGroupVector& recentGroups, + void* closure) +{ RefPtr self = reinterpret_cast(closure); return self->StopwatchCommit(iteration, recentGroups); } bool -nsPerformanceStatsService::StopwatchCommit(uint64_t iteration, JSGroupVector& recentGroups) +nsPerformanceStatsService::StopwatchCommit(uint64_t iteration, + js::PerformanceGroupVector& recentGroups) { MOZ_ASSERT(iteration == mIteration); MOZ_ASSERT(!recentGroups.empty()); diff --git a/toolkit/components/perfmonitoring/nsPerformanceStats.h b/toolkit/components/perfmonitoring/nsPerformanceStats.h index 5b899786e812..989c9ccf4e0b 100644 --- a/toolkit/components/perfmonitoring/nsPerformanceStats.h +++ b/toolkit/components/perfmonitoring/nsPerformanceStats.h @@ -19,7 +19,6 @@ class nsPerformanceGroup; class nsPerformanceGroupDetails; -typedef mozilla::Vector> JSGroupVector; typedef mozilla::Vector> GroupVector; /** @@ -192,8 +191,8 @@ protected: * calling it more than once may not return the same instances of * performance groups. */ - bool GetPerformanceGroups(JSContext* cx, JSGroupVector&); - static bool GetPerformanceGroupsCallback(JSContext* cx, JSGroupVector&, void* closure); + bool GetPerformanceGroups(JSContext* cx, js::PerformanceGroupVector&); + static bool GetPerformanceGroupsCallback(JSContext* cx, js::PerformanceGroupVector&, void* closure); @@ -329,8 +328,10 @@ protected: * @param recentGroups The groups that have seen activity during this * event. */ - static bool StopwatchCommitCallback(uint64_t iteration, JSGroupVector& recentGroups, void* closure); - bool StopwatchCommit(uint64_t iteration, JSGroupVector& recentGroups); + static bool StopwatchCommitCallback(uint64_t iteration, + js::PerformanceGroupVector& recentGroups, + void* closure); + bool StopwatchCommit(uint64_t iteration, js::PerformanceGroupVector& recentGroups); /** * The number of times we have started executing JavaScript code. diff --git a/toolkit/components/places/nsNavHistory.cpp b/toolkit/components/places/nsNavHistory.cpp index b954c6d31e51..a1db473763c2 100644 --- a/toolkit/components/places/nsNavHistory.cpp +++ b/toolkit/components/places/nsNavHistory.cpp @@ -1236,7 +1236,7 @@ nsNavHistory::ExecuteQueries(nsINavHistoryQuery** aQueries, uint32_t aQueryCount for (uint32_t i = 0; i < aQueryCount; i ++) { nsCOMPtr query = do_QueryInterface(aQueries[i], &rv); NS_ENSURE_SUCCESS(rv, rv); - queries.AppendObject(query); + queries.AppendElement(query.forget()); } // Create the root node. @@ -2465,7 +2465,7 @@ nsNavHistory::CleanupPlacesOnVisitsDelete(const nsCString& aPlaceIdsQueryString) filteredPlaceIds.Append(','); } filteredPlaceIds.AppendInt(placeId); - URIs.AppendObject(uri); + URIs.AppendElement(uri.forget()); GUIDs.AppendElement(guid); } else { @@ -3003,7 +3003,7 @@ nsNavHistory::AsyncExecuteLegacyQueries(nsINavHistoryQuery** aQueries, for (uint32_t i = 0; i < aQueryCount; i ++) { nsCOMPtr query = do_QueryInterface(aQueries[i]); NS_ENSURE_STATE(query); - queries.AppendObject(query); + queries.AppendElement(query.forget()); } NS_ENSURE_ARG_MIN(queries.Count(), 1); @@ -3617,7 +3617,7 @@ nsNavHistory::ResultsAsList(mozIStorageStatement* statement, RefPtr result; rv = RowToResult(row, aOptions, getter_AddRefs(result)); NS_ENSURE_SUCCESS(rv, rv); - aResults->AppendObject(result); + aResults->AppendElement(result.forget()); } return NS_OK; } diff --git a/toolkit/components/telemetry/Histograms.json b/toolkit/components/telemetry/Histograms.json index 7399da185b19..40184e9936c2 100644 --- a/toolkit/components/telemetry/Histograms.json +++ b/toolkit/components/telemetry/Histograms.json @@ -1064,7 +1064,7 @@ "description": "2D canvas used" }, "CANVAS_WEBGL_ACCL_FAILURE_ID": { - "alert_emails": ["bgirard@mozilla.com"], + "alert_emails": ["gfx-telemetry-alerts@mozilla.com","bgirard@mozilla.com","msreckovic@mozilla.com"], "expires_in_version": "never", "kind": "count", "keyed": true, @@ -1072,7 +1072,7 @@ "bug_numbers": [1272808] }, "CANVAS_WEBGL_FAILURE_ID": { - "alert_emails": ["bgirard@mozilla.com"], + "alert_emails": ["gfx-telemetry-alerts@mozilla.com","bgirard@mozilla.com","msreckovic@mozilla.com"], "expires_in_version": "never", "kind": "count", "keyed": true, @@ -2885,21 +2885,6 @@ "n_values": 4, "description": "Count the number of 0) successful connections to an ipv4 address, 1) failed connection an ipv4 address, 2) successful connection to an ipv6 address and 3) failed connections to an ipv6 address." }, - "URL_PATH_ENDS_IN_EXCLAMATION": { - "expires_in_version": "never", - "kind": "boolean", - "description": "The URL path ends in !" - }, - "URL_PATH_CONTAINS_EXCLAMATION_SLASH": { - "expires_in_version": "never", - "kind": "boolean", - "description": "The URL path contains !/" - }, - "URL_PATH_CONTAINS_EXCLAMATION_DOUBLE_SLASH": { - "expires_in_version": "never", - "kind": "boolean", - "description": "The URL path contains !//" - }, "NETWORK_SESSION_AT_900FD": { "expires_in_version": "never", "kind": "boolean", @@ -9591,7 +9576,7 @@ }, "GRAPHICS_SANITY_TEST": { "expires_in_version": "never", - "alert_emails": ["gfx-telemetry-alerts@mozilla.com"], + "alert_emails": ["gfx-telemetry-alerts@mozilla.com","msreckovic@mozilla.com"], "kind": "enumerated", "n_values": 20, "releaseChannelCollection": "opt-out", @@ -9669,7 +9654,7 @@ "description": "Whether the user has set a custom homepage." }, "GRAPHICS_DRIVER_STARTUP_TEST": { - "alert_emails": ["danderson@mozilla.com"], + "alert_emails": ["gfx-telemetry-alerts@mozilla.com","danderson@mozilla.com","msreckovic@mozilla.com"], "expires_in_version": "never", "kind": "enumerated", "n_values": 20, @@ -9677,7 +9662,7 @@ "description": "Reports whether or not graphics drivers crashed during startup." }, "GRAPHICS_SANITY_TEST_OS_SNAPSHOT": { - "alert_emails": ["danderson@mozilla.com"], + "alert_emails": ["gfx-telemetry-alerts@mozilla.com","danderson@mozilla.com","msreckovic@mozilla.com"], "expires_in_version": "never", "kind": "enumerated", "n_values": 10, @@ -9931,7 +9916,7 @@ "description": "The number of times a given type of breakdown was used for a dominator tree" }, "GRAPHICS_SANITY_TEST_REASON": { - "alert_emails": ["danderson@mozilla.com"], + "alert_emails": ["gfx-telemetry-alerts@mozilla.com","danderson@mozilla.com","msreckovic@mozilla.com"], "expires_in_version": "43", "kind": "enumerated", "n_values": 20, @@ -10499,14 +10484,14 @@ "description": "Attempt to notify ServiceWorker of push notification resubscription." }, "D3D11_SYNC_HANDLE_FAILURE": { - "alert_emails": ["bschouten@mozilla.com","danderson@mozilla.com","msreckovic@mozilla.com","ashughes@mozilla.com"], - "expires_in_version": "50", + "alert_emails": ["gfx-telemetry-alerts@mozilla.com","bschouten@mozilla.com","danderson@mozilla.com","msreckovic@mozilla.com","ashughes@mozilla.com"], + "expires_in_version": "60", "releaseChannelCollection": "opt-out", "kind": "count", "description": "Number of times the D3D11 compositor failed to get a texture sync handle." }, "GFX_CONTENT_FAILED_TO_ACQUIRE_DEVICE": { - "alert_emails": ["gfx-telemetry-alerts@mozilla.com"], + "alert_emails": ["gfx-telemetry-alerts@mozilla.com","msreckovic@mozilla.com"], "expires_in_version": "never", "kind": "enumerated", "n_values": 6, @@ -10908,7 +10893,7 @@ "description": "Counts the number of times that about:tabcrashed was unloaded without submitting." }, "ABOUTCRASHES_OPENED_COUNT": { - "alert_emails": ["bgirard@mozilla.com"], + "alert_emails": ["gfx-telemetry-alerts@mozilla.com","bgirard@mozilla.com","msreckovic@mozilla.com"], "expires_in_version": "55", "kind": "count", "bug_numbers": [1276714, 1276716], diff --git a/toolkit/components/telemetry/histogram-whitelists.json b/toolkit/components/telemetry/histogram-whitelists.json index 5c952ad9cd71..be179c2eaa5d 100644 --- a/toolkit/components/telemetry/histogram-whitelists.json +++ b/toolkit/components/telemetry/histogram-whitelists.json @@ -1006,9 +1006,6 @@ "URLCLASSIFIER_PS_FAILURE", "URLCLASSIFIER_PS_FALLOCATE_TIME", "URLCLASSIFIER_PS_FILELOAD_TIME", - "URL_PATH_CONTAINS_EXCLAMATION_DOUBLE_SLASH", - "URL_PATH_CONTAINS_EXCLAMATION_SLASH", - "URL_PATH_ENDS_IN_EXCLAMATION", "VIDEO_CANPLAYTYPE_H264_CONSTRAINT_SET_FLAG", "VIDEO_CANPLAYTYPE_H264_LEVEL", "VIDEO_CANPLAYTYPE_H264_PROFILE", @@ -2313,9 +2310,6 @@ "URLCLASSIFIER_PS_FAILURE", "URLCLASSIFIER_PS_FALLOCATE_TIME", "URLCLASSIFIER_PS_FILELOAD_TIME", - "URL_PATH_CONTAINS_EXCLAMATION_DOUBLE_SLASH", - "URL_PATH_CONTAINS_EXCLAMATION_SLASH", - "URL_PATH_ENDS_IN_EXCLAMATION", "VIDEO_ADOBE_GMP_DISAPPEARED", "VIDEO_ADOBE_GMP_MISSING_FILES", "VIDEO_CANPLAYTYPE_H264_CONSTRAINT_SET_FLAG", diff --git a/toolkit/xre/nsAppRunner.cpp b/toolkit/xre/nsAppRunner.cpp index d5e89b8619e5..a5d353d2e631 100644 --- a/toolkit/xre/nsAppRunner.cpp +++ b/toolkit/xre/nsAppRunner.cpp @@ -4835,6 +4835,7 @@ MultiprocessBlockPolicy() { } #endif // XP_WIN +#if defined(MOZ_WIDGET_GTK) /** * Avoids enabling e10s for certain locales that require bidi selection, * which currently doesn't work well with e10s. @@ -4851,6 +4852,7 @@ MultiprocessBlockPolicy() { gMultiprocessBlockPolicy = kE10sDisabledForBidi; return gMultiprocessBlockPolicy; } +#endif // MOZ_WIDGET_GTK /* * None of the blocking policies matched, so e10s is allowed to run. diff --git a/widget/android/PrefsHelper.h b/widget/android/PrefsHelper.h index 0d7d9f4d9db7..b6a040ddfae5 100644 --- a/widget/android/PrefsHelper.h +++ b/widget/android/PrefsHelper.h @@ -12,6 +12,7 @@ #include "nsCOMPtr.h" #include "nsVariant.h" +#include "mozilla/Maybe.h" #include "mozilla/Preferences.h" #include "mozilla/Services.h" #include "mozilla/UniquePtr.h" @@ -67,16 +68,19 @@ class PrefsHelper return false; } - const auto& jstrVal = type == widget::PrefsHelper::PREF_STRING ? - jni::StringParam(strVal, aPrefName.Env()) : - jni::StringParam(nullptr); + Maybe jstrVal; + jstrVal.emplace(nullptr); + if (type == widget::PrefsHelper::PREF_STRING) { + jstrVal.reset(); + jstrVal.emplace(strVal, aPrefName.Env()); + } if (aPrefHandler) { widget::PrefsHelper::CallPrefHandler( - aPrefHandler, type, aPrefName, boolVal, intVal, jstrVal); + aPrefHandler, type, aPrefName, boolVal, intVal, jstrVal.ref()); } else { widget::PrefsHelper::OnPrefChange( - aPrefName, type, boolVal, intVal, jstrVal); + aPrefName, type, boolVal, intVal, jstrVal.ref()); } return true; } @@ -189,12 +193,15 @@ public: continue; } - const auto& jstrVal = type == widget::PrefsHelper::PREF_STRING ? - jni::StringParam(strVal, aCls.Env()) : - jni::StringParam(nullptr); + Maybe jstrVal; + jstrVal.emplace(nullptr); + if (type == widget::PrefsHelper::PREF_STRING) { + jstrVal.reset(); + jstrVal.emplace(strVal, aCls.Env()); + } widget::PrefsHelper::CallPrefHandler( - aPrefHandler, type, nameStr, boolVal, intVal, jstrVal); + aPrefHandler, type, nameStr, boolVal, intVal, jstrVal.ref()); } widget::PrefsHelper::CallPrefHandler( @@ -314,11 +321,14 @@ public: return; } - const auto& jstrVal = type == widget::PrefsHelper::PREF_STRING ? - jni::StringParam(strVal) : - jni::StringParam(nullptr); + Maybe jstrVal; + jstrVal.emplace(nullptr); + if (type == widget::PrefsHelper::PREF_STRING) { + jstrVal.reset(); + jstrVal.emplace(strVal); + } - widget::PrefsHelper::OnPrefChange(name, type, boolVal, intVal, jstrVal); + widget::PrefsHelper::OnPrefChange(name, type, boolVal, intVal, jstrVal.ref()); } }; diff --git a/widget/gtk/nsDragService.cpp b/widget/gtk/nsDragService.cpp index 1b04f49b1cc0..666b6f6aa1d9 100644 --- a/widget/gtk/nsDragService.cpp +++ b/widget/gtk/nsDragService.cpp @@ -441,7 +441,7 @@ nsDragService::SetAlphaPixmap(SourceSurface *aSurface, // Make a DrawTarget wrapped around the pixmap to render on RefPtr dt = nsWindow::GetDrawTargetForGdkDrawable(GDK_DRAWABLE(pixmap), - IntRect(dragRect.width, + IntSize(dragRect.width, dragRect.height)); if (!dt) return false; diff --git a/widget/gtk/nsWindow.h b/widget/gtk/nsWindow.h index 5917e53ddc60..c38c647823c8 100644 --- a/widget/gtk/nsWindow.h +++ b/widget/gtk/nsWindow.h @@ -321,7 +321,7 @@ public: #if (MOZ_WIDGET_GTK == 2) static already_AddRefed GetDrawTargetForGdkDrawable(GdkDrawable* aDrawable, - const IntSize& aSize); + const mozilla::gfx::IntSize& aSize); #endif NS_IMETHOD ReparentNativeWidget(nsIWidget* aNewParent) override; diff --git a/widget/nsBaseWidget.cpp b/widget/nsBaseWidget.cpp index e1e52b99c747..c67b5bfd2c4c 100644 --- a/widget/nsBaseWidget.cpp +++ b/widget/nsBaseWidget.cpp @@ -242,18 +242,6 @@ WidgetShutdownObserver::Unregister() } } -#if defined(XP_WIN) || defined(XP_MACOSX) || defined(MOZ_WIDGET_GTK) -// defined in nsAppRunner.cpp -extern const char* kAccessibilityLastRunDatePref; - -static inline uint32_t -PRTimeToSeconds(PRTime t_usec) -{ - PRTime usec_per_sec = PR_USEC_PER_SEC; - return uint32_t(t_usec /= usec_per_sec); -} -#endif - void nsBaseWidget::Shutdown() { @@ -931,10 +919,20 @@ nsBaseWidget::AutoLayerManagerSetup::~AutoLayerManagerSetup() } } +bool nsBaseWidget::IsSmallPopup() const +{ + return mWindowType == eWindowType_popup && mPopupType != ePopupTypePanel; +} + bool nsBaseWidget::ComputeShouldAccelerate() { - return gfx::gfxConfig::IsEnabled(gfx::Feature::HW_COMPOSITING); + bool enabled = gfx::gfxConfig::IsEnabled(gfx::Feature::HW_COMPOSITING); +#ifdef MOZ_WIDGET_GTK + return enabled && !IsSmallPopup(); +#else + return enabled; +#endif } bool @@ -1876,6 +1874,18 @@ nsBaseWidget::ZoomToRect(const uint32_t& aPresShellId, #ifdef ACCESSIBILITY +#if defined(XP_WIN) || defined(XP_MACOSX) || defined(MOZ_WIDGET_GTK) +// defined in nsAppRunner.cpp +extern const char* kAccessibilityLastRunDatePref; + +static inline uint32_t +PRTimeToSeconds(PRTime t_usec) +{ + PRTime usec_per_sec = PR_USEC_PER_SEC; + return uint32_t(t_usec /= usec_per_sec); +} +#endif + a11y::Accessible* nsBaseWidget::GetRootAccessible() { diff --git a/widget/nsBaseWidget.h b/widget/nsBaseWidget.h index cdae75da0262..7f0e57fc1dc1 100644 --- a/widget/nsBaseWidget.h +++ b/widget/nsBaseWidget.h @@ -293,6 +293,10 @@ public: mozilla::a11y::Accessible* GetRootAccessible(); #endif + // Return true if this is a simple widget (that is typically not worth + // accelerating) + bool IsSmallPopup() const; + nsPopupLevel PopupLevel() { return mPopupLevel; } virtual LayoutDeviceIntSize diff --git a/xpcom/glue/nsCategoryCache.h b/xpcom/glue/nsCategoryCache.h index b9fe6dddd302..023aa7a75ed6 100644 --- a/xpcom/glue/nsCategoryCache.h +++ b/xpcom/glue/nsCategoryCache.h @@ -79,7 +79,7 @@ public: nsISupports* entry = iter.UserData(); nsCOMPtr service = do_QueryInterface(entry); if (service) { - aResult.AppendObject(service); + aResult.AppendElement(service.forget()); } } }