From owner-svn-ports-all@freebsd.org Tue Dec 26 21:47:16 2017 Return-Path: Delivered-To: svn-ports-all@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 13E92E8504D; Tue, 26 Dec 2017 21:47:16 +0000 (UTC) (envelope-from jbeich@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id A361468CC0; Tue, 26 Dec 2017 21:47:15 +0000 (UTC) (envelope-from jbeich@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id vBQLlE6h011167; Tue, 26 Dec 2017 21:47:14 GMT (envelope-from jbeich@FreeBSD.org) Received: (from jbeich@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id vBQLlEka011157; Tue, 26 Dec 2017 21:47:14 GMT (envelope-from jbeich@FreeBSD.org) Message-Id: <201712262147.vBQLlEka011157@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: jbeich set sender to jbeich@FreeBSD.org using -f From: Jan Beich Date: Tue, 26 Dec 2017 21:47:13 +0000 (UTC) To: ports-committers@freebsd.org, svn-ports-all@freebsd.org, svn-ports-head@freebsd.org Subject: svn commit: r457317 - in head/www/waterfox: . files X-SVN-Group: ports-head X-SVN-Commit-Author: jbeich X-SVN-Commit-Paths: in head/www/waterfox: . files X-SVN-Commit-Revision: 457317 X-SVN-Commit-Repository: ports MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-ports-all@freebsd.org X-Mailman-Version: 2.1.25 Precedence: list List-Id: SVN commit messages for the ports tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 26 Dec 2017 21:47:16 -0000 Author: jbeich Date: Tue Dec 26 21:47:13 2017 New Revision: 457317 URL: https://svnweb.freebsd.org/changeset/ports/457317 Log: www/waterfox: apply some FF58 fixes Security: a891c5b4-3d7a-4de9-9c71-eef3fd698c77 Added: head/www/waterfox/files/patch-bug1224396 (contents, props changed) head/www/waterfox/files/patch-bug1399400 (contents, props changed) head/www/waterfox/files/patch-bug1399520 (contents, props changed) head/www/waterfox/files/patch-bug1408276 (contents, props changed) head/www/waterfox/files/patch-bug1409951 (contents, props changed) head/www/waterfox/files/patch-bug1410134 (contents, props changed) head/www/waterfox/files/patch-bug1412145 (contents, props changed) head/www/waterfox/files/patch-bug1413741 (contents, props changed) head/www/waterfox/files/patch-bug1414425 (contents, props changed) head/www/waterfox/files/patch-bug1414452 (contents, props changed) head/www/waterfox/files/patch-bug1414945 (contents, props changed) head/www/waterfox/files/patch-bug1415441 (contents, props changed) head/www/waterfox/files/patch-bug1415582 (contents, props changed) head/www/waterfox/files/patch-bug1415598 (contents, props changed) head/www/waterfox/files/patch-bug1417797 (contents, props changed) head/www/waterfox/files/patch-bug1418447 (contents, props changed) head/www/waterfox/files/patch-bug1418854 (contents, props changed) head/www/waterfox/files/patch-bug1419363 (contents, props changed) head/www/waterfox/files/patch-bug1422389 (contents, props changed) head/www/waterfox/files/patch-bug1423086 (contents, props changed) head/www/waterfox/files/patch-bug1423159 (contents, props changed) head/www/waterfox/files/patch-bug1424373 (contents, props changed) head/www/waterfox/files/patch-z-bug1382366 (contents, props changed) Modified: head/www/waterfox/Makefile (contents, props changed) Modified: head/www/waterfox/Makefile ============================================================================== --- head/www/waterfox/Makefile Tue Dec 26 21:32:54 2017 (r457316) +++ head/www/waterfox/Makefile Tue Dec 26 21:47:13 2017 (r457317) @@ -2,7 +2,7 @@ PORTNAME= waterfox DISTVERSION= 56.0.1.s20171212 -PORTREVISION= 1 +PORTREVISION= 2 CATEGORIES= www ipv6 MAINTAINER= jbeich@FreeBSD.org Added: head/www/waterfox/files/patch-bug1224396 ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/www/waterfox/files/patch-bug1224396 Tue Dec 26 21:47:13 2017 (r457317) @@ -0,0 +1,146 @@ +commit 94f55f3a6124 +Author: Lee Salzman +Date: Wed Nov 22 12:19:29 2017 -0500 + + Bug 1224396 - Skia path allocation cleanups. r=msreckovic a=gchang + + MozReview-Commit-ID: GAf2vC1Fucv + + --HG-- + extra : source : db4543ce21ce1e8a1c81b685a16e61f71db2f602 +--- + gfx/skia/skia/include/core/SkPathRef.h | 24 ++++++++++++++---------- + gfx/skia/skia/src/core/SkArenaAlloc.cpp | 23 ++++++++++++++++++----- + gfx/skia/skia/src/core/SkArenaAlloc.h | 5 ++++- + 3 files changed, 36 insertions(+), 16 deletions(-) + +diff --git gfx/skia/skia/include/core/SkPathRef.h gfx/skia/skia/include/core/SkPathRef.h +index 5e6fda7d85b2..24870c64fbc0 100644 +--- gfx/skia/skia/include/core/SkPathRef.h ++++ gfx/skia/skia/include/core/SkPathRef.h +@@ -16,7 +16,7 @@ + #include "SkRRect.h" + #include "SkRect.h" + #include "SkRefCnt.h" +-#include // ptrdiff_t ++#include "../private/SkTemplates.h" + + class SkRBuffer; + class SkWBuffer; +@@ -433,31 +433,35 @@ private: + */ + void makeSpace(size_t size) { + SkDEBUGCODE(this->validate();) +- ptrdiff_t growSize = size - fFreeSpace; +- if (growSize <= 0) { ++ if (size <= fFreeSpace) { + return; + } ++ size_t growSize = size - fFreeSpace; + size_t oldSize = this->currSize(); + // round to next multiple of 8 bytes + growSize = (growSize + 7) & ~static_cast(7); + // we always at least double the allocation +- if (static_cast(growSize) < oldSize) { ++ if (growSize < oldSize) { + growSize = oldSize; + } + if (growSize < kMinSize) { + growSize = kMinSize; + } +- size_t newSize = oldSize + growSize; ++ constexpr size_t maxSize = std::numeric_limits::max(); ++ size_t newSize; ++ if (growSize <= maxSize - oldSize) { ++ newSize = oldSize + growSize; ++ } else { ++ SK_ABORT("Path too big."); ++ } + // Note that realloc could memcpy more than we need. It seems to be a win anyway. TODO: + // encapsulate this. + fPoints = reinterpret_cast(sk_realloc_throw(fPoints, newSize)); + size_t oldVerbSize = fVerbCnt * sizeof(uint8_t); +- void* newVerbsDst = reinterpret_cast( +- reinterpret_cast(fPoints) + newSize - oldVerbSize); +- void* oldVerbsSrc = reinterpret_cast( +- reinterpret_cast(fPoints) + oldSize - oldVerbSize); ++ void* newVerbsDst = SkTAddOffset(fPoints, newSize - oldVerbSize); ++ void* oldVerbsSrc = SkTAddOffset(fPoints, oldSize - oldVerbSize); + memmove(newVerbsDst, oldVerbsSrc, oldVerbSize); +- fVerbs = reinterpret_cast(reinterpret_cast(fPoints) + newSize); ++ fVerbs = SkTAddOffset(fPoints, newSize); + fFreeSpace += growSize; + SkDEBUGCODE(this->validate();) + } +diff --git gfx/skia/skia/src/core/SkArenaAlloc.cpp gfx/skia/skia/src/core/SkArenaAlloc.cpp +index eca3aa97d761..57a19093d065 100644 +--- gfx/skia/skia/src/core/SkArenaAlloc.cpp ++++ gfx/skia/skia/src/core/SkArenaAlloc.cpp +@@ -8,6 +8,7 @@ + #include + #include + #include "SkArenaAlloc.h" ++#include "SkTypes.h" + + static char* end_chain(char*) { return nullptr; } + +@@ -95,19 +96,31 @@ void SkArenaAlloc::ensureSpace(uint32_t size, uint32_t alignment) { + // This must be conservative to add the right amount of extra memory to handle the alignment + // padding. + constexpr uint32_t alignof_max_align_t = 8; +- uint32_t objSizeAndOverhead = size + headerSize + sizeof(Footer); ++ constexpr uint32_t maxSize = std::numeric_limits::max(); ++ constexpr uint32_t overhead = headerSize + sizeof(Footer); ++ SkASSERT_RELEASE(size <= maxSize - overhead); ++ uint32_t objSizeAndOverhead = size + overhead; + if (alignment > alignof_max_align_t) { +- objSizeAndOverhead += alignment - 1; ++ uint32_t alignmentOverhead = alignment - 1; ++ SkASSERT_RELEASE(objSizeAndOverhead <= maxSize - alignmentOverhead); ++ objSizeAndOverhead += alignmentOverhead; + } + +- uint32_t allocationSize = std::max(objSizeAndOverhead, fExtraSize * fFib0); +- fFib0 += fFib1; +- std::swap(fFib0, fFib1); ++ uint32_t minAllocationSize; ++ if (fExtraSize <= maxSize / fFib0) { ++ minAllocationSize = fExtraSize * fFib0; ++ fFib0 += fFib1; ++ std::swap(fFib0, fFib1); ++ } else { ++ minAllocationSize = maxSize; ++ } ++ uint32_t allocationSize = std::max(objSizeAndOverhead, minAllocationSize); + + // Round up to a nice size. If > 32K align to 4K boundary else up to max_align_t. The > 32K + // heuristic is from the JEMalloc behavior. + { + uint32_t mask = allocationSize > (1 << 15) ? (1 << 12) - 1 : 16 - 1; ++ SkASSERT_RELEASE(allocationSize <= maxSize - mask); + allocationSize = (allocationSize + mask) & ~mask; + } + +diff --git gfx/skia/skia/src/core/SkArenaAlloc.h gfx/skia/skia/src/core/SkArenaAlloc.h +index 494696ce768d..05d3336684e9 100644 +--- gfx/skia/skia/src/core/SkArenaAlloc.h ++++ gfx/skia/skia/src/core/SkArenaAlloc.h +@@ -157,6 +157,7 @@ private: + template + char* commonArrayAlloc(uint32_t count) { + char* objStart; ++ SkASSERT_RELEASE(count <= std::numeric_limits::max() / sizeof(T)); + uint32_t arraySize = SkTo(count * sizeof(T)); + uint32_t alignment = SkTo(alignof(T)); + +@@ -164,7 +165,9 @@ private: + objStart = this->allocObject(arraySize, alignment); + fCursor = objStart + arraySize; + } else { +- uint32_t totalSize = arraySize + sizeof(Footer) + sizeof(uint32_t); ++ constexpr uint32_t overhead = sizeof(Footer) + sizeof(uint32_t); ++ SkASSERT_RELEASE(arraySize <= std::numeric_limits::max() - overhead); ++ uint32_t totalSize = arraySize + overhead; + objStart = this->allocObjectWithFooter(totalSize, alignment); + + // Can never be UB because max value is alignof(T). Added: head/www/waterfox/files/patch-bug1399400 ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/www/waterfox/files/patch-bug1399400 Tue Dec 26 21:47:13 2017 (r457317) @@ -0,0 +1,39 @@ +commit 7c15d03b1e83 +Author: Blake Kaplan +Date: Mon Dec 18 19:39:45 2017 -0500 + + Bug 1399400 - Use a strong reference when handling mTextField. r=bz a=jcristau + + MozReview-Commit-ID: IqzGDM4ezeW + + --HG-- + extra : rebase_source : 8f9a1f72360fcabdc6e57fec3dbdda1bd705fd03 + extra : source : 02d457ace9bb8430e25cfb3a1fb6b0303c9d01c5 +--- + layout/forms/nsNumberControlFrame.cpp | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git layout/forms/nsNumberControlFrame.cpp layout/forms/nsNumberControlFrame.cpp +index 00b4492f23f1..68819267c906 100644 +--- layout/forms/nsNumberControlFrame.cpp ++++ layout/forms/nsNumberControlFrame.cpp +@@ -592,15 +592,17 @@ nsNumberControlFrame::HandleFocusEvent(WidgetEvent* aEvent) + { + if (aEvent->mOriginalTarget != mTextField) { + // Move focus to our text field ++ RefPtr textField = HTMLInputElement::FromContent(mTextField); + IgnoredErrorResult ignored; +- HTMLInputElement::FromContent(mTextField)->Focus(ignored); ++ textField->Focus(ignored); + } + } + + void + nsNumberControlFrame::HandleSelectCall() + { +- HTMLInputElement::FromContent(mTextField)->Select(); ++ RefPtr textField = HTMLInputElement::FromContent(mTextField); ++ textField->Select(); + } + + #define STYLES_DISABLING_NATIVE_THEMING \ Added: head/www/waterfox/files/patch-bug1399520 ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/www/waterfox/files/patch-bug1399520 Tue Dec 26 21:47:13 2017 (r457317) @@ -0,0 +1,93 @@ +commit b4603106d015 +Author: Liang-Heng Chen +Date: Thu Oct 19 22:29:41 2017 -0400 + + Bug 1399520 - Avoid race condition. r=dragana + + MozReview-Commit-ID: 6Pd2HXqBgX4 +--- + modules/libjar/nsJAR.cpp | 26 ++++++++++++++++++-------- + modules/libjar/nsJAR.h | 8 +++++--- + 2 files changed, 23 insertions(+), 11 deletions(-) + +diff --git modules/libjar/nsJAR.cpp modules/libjar/nsJAR.cpp +index 80589e03f92b..b3121d99ef0a 100644 +--- modules/libjar/nsJAR.cpp ++++ modules/libjar/nsJAR.cpp +@@ -43,11 +43,27 @@ NS_IMPL_QUERY_INTERFACE(nsJAR, nsIZipReader) + NS_IMPL_ADDREF(nsJAR) + + // Custom Release method works with nsZipReaderCache... ++// Release might be called from multi-thread, we have to ++// take this function carefully to avoid delete-after-use. + MozExternalRefCountType nsJAR::Release(void) + { + nsrefcnt count; + NS_PRECONDITION(0 != mRefCnt, "dup release"); +- count = --mRefCnt; ++ ++ RefPtr cache; ++ if (mRefCnt == 2) { // don't use a lock too frequently ++ // Use a mutex here to guarantee mCache is not racing and the target instance ++ // is still valid to increase ref-count. ++ MutexAutoLock lock(mLock); ++ cache = mCache; ++ mCache = nullptr; ++ } ++ if (cache) { ++ DebugOnly rv = cache->ReleaseZip(this); ++ MOZ_ASSERT(NS_SUCCEEDED(rv), "failed to release zip file"); ++ } ++ ++ count = --mRefCnt; // don't access any member variable after this line + NS_LOG_RELEASE(this, count, "nsJAR"); + if (0 == count) { + mRefCnt = 1; /* stabilize */ +@@ -56,13 +72,7 @@ MozExternalRefCountType nsJAR::Release(void) + delete this; + return 0; + } +- if (1 == count && mCache) { +-#ifdef DEBUG +- nsresult rv = +-#endif +- mCache->ReleaseZip(this); +- NS_ASSERTION(NS_SUCCEEDED(rv), "failed to release zip file"); +- } ++ + return count; + } + +diff --git modules/libjar/nsJAR.h modules/libjar/nsJAR.h +index 7f675c93003b..4fe948680fbf 100644 +--- modules/libjar/nsJAR.h ++++ modules/libjar/nsJAR.h +@@ -12,6 +12,7 @@ + #include "mozilla/Logging.h" + #include "prinrval.h" + ++#include "mozilla/Atomics.h" + #include "mozilla/Mutex.h" + #include "nsIComponentManager.h" + #include "nsCOMPtr.h" +@@ -75,8 +76,9 @@ class nsJAR final : public nsIZipReader + mReleaseTime = PR_INTERVAL_NO_TIMEOUT; + } + +- void SetZipReaderCache(nsZipReaderCache* cache) { +- mCache = cache; ++ void SetZipReaderCache(nsZipReaderCache* aCache) { ++ mozilla::MutexAutoLock lock(mLock); ++ mCache = aCache; + } + + nsresult GetNSPRFileDesc(PRFileDesc** aNSPRFileDesc); +@@ -89,7 +91,7 @@ class nsJAR final : public nsIZipReader + RefPtr mZip; // The underlying zip archive + PRIntervalTime mReleaseTime; // used by nsZipReaderCache for flushing entries + nsZipReaderCache* mCache; // if cached, this points to the cache it's contained in +- mozilla::Mutex mLock; ++ mozilla::Mutex mLock; // protect mCache and mZip + int64_t mMtime; + bool mOpened; + bool mIsOmnijar; Added: head/www/waterfox/files/patch-bug1408276 ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/www/waterfox/files/patch-bug1408276 Tue Dec 26 21:47:13 2017 (r457317) @@ -0,0 +1,170 @@ +commit a9bc6108422a +Author: Karl Tomlinson +Date: Tue Oct 17 18:14:43 2017 +1300 + + Bug 1408276 - Move to LIFECYCLE_WAITING_FOR_MAIN_THREAD_CLEANUP at end of iteration. r=padenot, a=gchang + + MozReview-Commit-ID: GbfIOPZPuGu + + --HG-- + extra : rebase_source : acc2bcee9a36d2b8f18826f08825895de5df0c1e +--- + dom/media/GraphDriver.cpp | 27 +++++++++++++++++---------- + dom/media/MediaStreamGraph.cpp | 32 +++++++++++++++++++++----------- + dom/media/MediaStreamGraphImpl.h | 12 +++++++++++- + 3 files changed, 49 insertions(+), 22 deletions(-) + +diff --git dom/media/GraphDriver.cpp dom/media/GraphDriver.cpp +index 7f6f386fdaca..13944338e3d7 100644 +--- dom/media/GraphDriver.cpp ++++ dom/media/GraphDriver.cpp +@@ -284,8 +284,7 @@ SystemClockDriver::IsFallback() + void + ThreadedDriver::RunThread() + { +- bool stillProcessing = true; +- while (stillProcessing) { ++ while (true) { + mIterationStart = IterationEnd(); + mIterationEnd += GetIntervalForIteration(); + +@@ -324,10 +323,16 @@ ThreadedDriver::RunThread() + (long)stateComputedTime, + (long)nextStateComputedTime)); + +- stillProcessing = mGraphImpl->OneIteration(nextStateComputedTime); ++ bool stillProcessing = mGraphImpl->OneIteration(nextStateComputedTime); + ++ if (!stillProcessing) { ++ // Enter shutdown mode. The stable-state handler will detect this ++ // and complete shutdown if the graph does not get restarted. ++ mGraphImpl->SignalMainThreadCleanup(); ++ return; ++ } + MonitorAutoLock lock(GraphImpl()->GetMonitor()); +- if (NextDriver() && stillProcessing) { ++ if (NextDriver()) { + LOG(LogLevel::Debug, ("Switching to AudioCallbackDriver")); + RemoveCallback(); + NextDriver()->SetGraphTime(this, mIterationStart, mIterationEnd); +@@ -1009,13 +1014,20 @@ AudioCallbackDriver::DataCallback(const AudioDataValue* aInputBuffer, + mGraphImpl->NotifyOutputData(aOutputBuffer, static_cast(aFrames), + mSampleRate, mOutputChannels); + ++ if (!stillProcessing) { ++ // Enter shutdown mode. The stable-state handler will detect this ++ // and complete shutdown if the graph does not get restarted. ++ mGraphImpl->SignalMainThreadCleanup(); ++ return aFrames - 1; ++ } ++ + bool switching = false; + { + MonitorAutoLock mon(mGraphImpl->GetMonitor()); + switching = !!NextDriver(); + } + +- if (switching && stillProcessing) { ++ if (switching) { + // If the audio stream has not been started by the previous driver or + // the graph itself, keep it alive. + MonitorAutoLock mon(mGraphImpl->GetMonitor()); +@@ -1032,11 +1044,6 @@ AudioCallbackDriver::DataCallback(const AudioDataValue* aInputBuffer, + return aFrames - 1; + } + +- if (!stillProcessing) { +- LOG(LogLevel::Debug, +- ("Stopping audio thread for MediaStreamGraph %p", this)); +- return aFrames - 1; +- } + return aFrames; + } + +diff --git dom/media/MediaStreamGraph.cpp dom/media/MediaStreamGraph.cpp +index 3a742aafe9b2..6420e038a8fe 100644 +--- dom/media/MediaStreamGraph.cpp ++++ dom/media/MediaStreamGraph.cpp +@@ -1193,11 +1193,13 @@ MediaStreamGraphImpl::PrepareUpdatesToMainThreadState(bool aFinalUpdate) + } + } + +- // Don't send the message to the main thread if it's not going to have +- // any work to do. +- if (aFinalUpdate || +- !mUpdateRunnables.IsEmpty() || +- !mStreamUpdates.IsEmpty()) { ++ // If this is the final update, then a stable state event will soon be ++ // posted just before this thread finishes, and so there is no need to also ++ // post here. ++ if (!aFinalUpdate && ++ // Don't send the message to the main thread if it's not going to have ++ // any work to do. ++ !(mUpdateRunnables.IsEmpty() && mStreamUpdates.IsEmpty())) { + EnsureStableStateEventPosted(); + } + } +@@ -1430,12 +1432,7 @@ MediaStreamGraphImpl::UpdateMainThreadState() + (IsEmpty() && mBackMessageQueue.IsEmpty()); + PrepareUpdatesToMainThreadState(finalUpdate); + if (finalUpdate) { +- // Enter shutdown mode. The stable-state handler will detect this +- // and complete shutdown. Destroy any streams immediately. +- LOG(LogLevel::Debug, +- ("MediaStreamGraph %p waiting for main thread cleanup", this)); +- // We'll shut down this graph object if it does not get restarted. +- mLifecycleState = LIFECYCLE_WAITING_FOR_MAIN_THREAD_CLEANUP; ++ // Enter shutdown mode when this iteration is completed. + // No need to Destroy streams here. The main-thread owner of each + // stream is responsible for calling Destroy on them. + return false; +@@ -1861,6 +1858,19 @@ MediaStreamGraphImpl::EnsureStableStateEventPosted() + mAbstractMainThread->Dispatch(event.forget()); + } + ++void ++MediaStreamGraphImpl::SignalMainThreadCleanup() ++{ ++ MOZ_ASSERT(mDriver->OnThread()); ++ ++ MonitorAutoLock lock(mMonitor); ++ LOG(LogLevel::Debug, ++ ("MediaStreamGraph %p waiting for main thread cleanup", this)); ++ mLifecycleState = ++ MediaStreamGraphImpl::LIFECYCLE_WAITING_FOR_MAIN_THREAD_CLEANUP; ++ EnsureStableStateEventPosted(); ++} ++ + void + MediaStreamGraphImpl::AppendMessage(UniquePtr aMessage) + { +diff --git dom/media/MediaStreamGraphImpl.h dom/media/MediaStreamGraphImpl.h +index dfea12bca3a8..dce49da39166 100644 +--- dom/media/MediaStreamGraphImpl.h ++++ dom/media/MediaStreamGraphImpl.h +@@ -197,6 +197,14 @@ public: + */ + bool OneIteration(GraphTime aStateEnd); + ++ /** ++ * Called from the driver, when the graph thread is about to stop, to tell ++ * the main thread to attempt to begin cleanup. The main thread may either ++ * shutdown or revive the graph depending on whether it receives new ++ * messages. ++ */ ++ void SignalMainThreadCleanup(); ++ + bool Running() const + { + mMonitor.AssertCurrentThreadOwns(); +@@ -720,7 +728,9 @@ public: + LIFECYCLE_WAITING_FOR_STREAM_DESTRUCTION + }; + /** +- * Modified only on the main thread in mMonitor. ++ * Modified only in mMonitor. Transitions to ++ * LIFECYCLE_WAITING_FOR_MAIN_THREAD_CLEANUP occur on the graph thread at ++ * the end of an iteration. All other transitions occur on the main thread. + */ + LifecycleState mLifecycleState; + /** Added: head/www/waterfox/files/patch-bug1409951 ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/www/waterfox/files/patch-bug1409951 Tue Dec 26 21:47:13 2017 (r457317) @@ -0,0 +1,177 @@ +commit d5562dbcfd63 +Author: Henri Sivonen +Date: Fri Dec 1 10:45:25 2017 -0500 + + Bug 1409951 - Use a stack to end serializer contexts instead of recomputing them. r=smaug, a=gchang + + MozReview-Commit-ID: FOd8AUmtYyA + + --HG-- + extra : rebase_source : 1f02ebc32fe80591d617f27ec70094a109ead2b0 + extra : source : b0a3a621f5c85b5e9a4eb97de77fcb2558ac17c6 +--- + dom/base/nsDocumentEncoder.cpp | 56 +++++++++++++++++++------------------- + dom/base/nsPlainTextSerializer.cpp | 1 + + 2 files changed, 29 insertions(+), 28 deletions(-) + +diff --git dom/base/nsDocumentEncoder.cpp dom/base/nsDocumentEncoder.cpp +index 5912d67da86e..2fb488750366 100644 +--- dom/base/nsDocumentEncoder.cpp ++++ dom/base/nsDocumentEncoder.cpp +@@ -49,6 +49,7 @@ + #include "mozilla/dom/Element.h" + #include "mozilla/dom/ShadowRoot.h" + #include "nsLayoutUtils.h" ++#include "mozilla/ScopeExit.h" + + using namespace mozilla; + using namespace mozilla::dom; +@@ -92,8 +93,8 @@ protected: + int32_t aDepth); + nsresult SerializeRangeContextStart(const nsTArray& aAncestorArray, + nsAString& aString); +- nsresult SerializeRangeContextEnd(const nsTArray& aAncestorArray, +- nsAString& aString); ++ nsresult SerializeRangeContextEnd(nsAString& aString); ++ + virtual int32_t + GetImmediateContextCount(const nsTArray& aAncestorArray) + { +@@ -185,6 +186,7 @@ protected: + AutoTArray mStartOffsets; + AutoTArray mEndNodes; + AutoTArray mEndOffsets; ++ AutoTArray, 8> mRangeContexts; + // Whether the serializer cares about being notified to scan elements to + // keep track of whether they are preformatted. This stores the out + // argument of nsIContentSerializer::Init(). +@@ -874,6 +876,9 @@ nsDocumentEncoder::SerializeRangeContextStart(const nsTArray& aAncesto + if (mDisableContextSerialize) { + return NS_OK; + } ++ ++ AutoTArray* serializedContext = mRangeContexts.AppendElement(); ++ + int32_t i = aAncestorArray.Length(), j; + nsresult rv = NS_OK; + +@@ -889,7 +894,7 @@ nsDocumentEncoder::SerializeRangeContextStart(const nsTArray& aAncesto + // Either a general inclusion or as immediate context + if (IncludeInContext(node) || i < j) { + rv = SerializeNodeStart(node, 0, -1, aString); +- ++ serializedContext->AppendElement(node); + if (NS_FAILED(rv)) + break; + } +@@ -899,34 +904,24 @@ nsDocumentEncoder::SerializeRangeContextStart(const nsTArray& aAncesto + } + + nsresult +-nsDocumentEncoder::SerializeRangeContextEnd(const nsTArray& aAncestorArray, +- nsAString& aString) ++nsDocumentEncoder::SerializeRangeContextEnd(nsAString& aString) + { + if (mDisableContextSerialize) { + return NS_OK; + } +- int32_t i = 0, j; +- int32_t count = aAncestorArray.Length(); +- nsresult rv = NS_OK; + +- // currently only for table-related elements +- j = GetImmediateContextCount(aAncestorArray); ++ MOZ_RELEASE_ASSERT(!mRangeContexts.IsEmpty(), "Tried to end context without starting one."); ++ AutoTArray& serializedContext = mRangeContexts.LastElement(); + +- while (i < count) { +- nsINode *node = aAncestorArray.ElementAt(i++); ++ nsresult rv = NS_OK; ++ for (nsINode* node : Reversed(serializedContext)) { ++ rv = SerializeNodeEnd(node, aString); + +- if (!node) ++ if (NS_FAILED(rv)) + break; +- +- // Either a general inclusion or as immediate context +- if (IncludeInContext(node) || i - 1 < j) { +- rv = SerializeNodeEnd(node, aString); +- +- if (NS_FAILED(rv)) +- break; +- } + } + ++ mRangeContexts.RemoveElementAt(mRangeContexts.Length() - 1); + return rv; + } + +@@ -992,7 +987,7 @@ nsDocumentEncoder::SerializeRangeToString(nsRange *aRange, + rv = SerializeRangeNodes(aRange, mCommonParent, aOutputString, 0); + NS_ENSURE_SUCCESS(rv, rv); + } +- rv = SerializeRangeContextEnd(mCommonAncestors, aOutputString); ++ rv = SerializeRangeContextEnd(aOutputString); + NS_ENSURE_SUCCESS(rv, rv); + + return rv; +@@ -1029,6 +1024,11 @@ NS_IMETHODIMP + nsDocumentEncoder::EncodeToStringWithMaxLength(uint32_t aMaxLength, + nsAString& aOutputString) + { ++ MOZ_ASSERT(mRangeContexts.IsEmpty(), "Re-entrant call to nsDocumentEncoder."); ++ auto rangeContextGuard = MakeScopeExit([&] { ++ mRangeContexts.Clear(); ++ }); ++ + if (!mDocument) + return NS_ERROR_NOT_INITIALIZED; + +@@ -1112,10 +1112,8 @@ nsDocumentEncoder::EncodeToStringWithMaxLength(uint32_t aMaxLength, + prevNode = node; + } else if (prevNode) { + // Went from a to a non- +- mCommonAncestors.Clear(); +- nsContentUtils::GetAncestors(p->GetParentNode(), mCommonAncestors); + mDisableContextSerialize = false; +- rv = SerializeRangeContextEnd(mCommonAncestors, output); ++ rv = SerializeRangeContextEnd(output); + NS_ENSURE_SUCCESS(rv, rv); + prevNode = nullptr; + } +@@ -1134,10 +1132,8 @@ nsDocumentEncoder::EncodeToStringWithMaxLength(uint32_t aMaxLength, + nsCOMPtr p = do_QueryInterface(prevNode); + rv = SerializeNodeEnd(p, output); + NS_ENSURE_SUCCESS(rv, rv); +- mCommonAncestors.Clear(); +- nsContentUtils::GetAncestors(p->GetParentNode(), mCommonAncestors); + mDisableContextSerialize = false; +- rv = SerializeRangeContextEnd(mCommonAncestors, output); ++ rv = SerializeRangeContextEnd(output); + NS_ENSURE_SUCCESS(rv, rv); + } + +@@ -1196,6 +1192,10 @@ nsDocumentEncoder::EncodeToStringWithMaxLength(uint32_t aMaxLength, + NS_IMETHODIMP + nsDocumentEncoder::EncodeToStream(nsIOutputStream* aStream) + { ++ MOZ_ASSERT(mRangeContexts.IsEmpty(), "Re-entrant call to nsDocumentEncoder."); ++ auto rangeContextGuard = MakeScopeExit([&] { ++ mRangeContexts.Clear(); ++ }); + nsresult rv = NS_OK; + + if (!mDocument) +diff --git dom/base/nsPlainTextSerializer.cpp dom/base/nsPlainTextSerializer.cpp +index 189469f73bb6..d7ddb0274be5 100644 +--- dom/base/nsPlainTextSerializer.cpp ++++ dom/base/nsPlainTextSerializer.cpp +@@ -388,6 +388,7 @@ nsPlainTextSerializer::ScanElementForPreformat(Element* aElement) + NS_IMETHODIMP + nsPlainTextSerializer::ForgetElementForPreformat(Element* aElement) + { ++ MOZ_RELEASE_ASSERT(!mPreformatStack.empty(), "Tried to pop without previous push."); + mPreformatStack.pop(); + return NS_OK; + } Added: head/www/waterfox/files/patch-bug1410134 ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/www/waterfox/files/patch-bug1410134 Tue Dec 26 21:47:13 2017 (r457317) @@ -0,0 +1,52 @@ +commit 2d5001acfa08 +Author: Tim Huang +Date: Tue Nov 28 14:56:55 2017 -0500 + + Bug 1410134 - Fix the remove-while-iterating for RemoveCookiesWithOriginAttributes. r=jdm, a=gchang + + MozReview-Commit-ID: u56N4084lL + + --HG-- + extra : source : ffab26e34d92c1fc2e5103d2bad3625e180963bb +--- + netwerk/cookie/nsCookieService.cpp | 24 ++++++++++-------------- + 1 file changed, 10 insertions(+), 14 deletions(-) + +diff --git netwerk/cookie/nsCookieService.cpp netwerk/cookie/nsCookieService.cpp +index 7d939da101e2..0692b7088751 100644 +--- netwerk/cookie/nsCookieService.cpp ++++ netwerk/cookie/nsCookieService.cpp +@@ -4899,23 +4899,19 @@ nsCookieService::RemoveCookiesWithOriginAttributes( + } + + // Pattern matches. Delete all cookies within this nsCookieEntry. +- const nsCookieEntry::ArrayType& cookies = entry->GetCookies(); ++ uint32_t cookiesCount = entry->GetCookies().Length(); + +- while (!cookies.IsEmpty()) { +- nsCookie *cookie = cookies.LastElement(); +- +- nsAutoCString host; +- cookie->GetHost(host); +- +- nsAutoCString name; +- cookie->GetName(name); +- +- nsAutoCString path; +- cookie->GetPath(path); ++ for (nsCookieEntry::IndexType i = 0 ; i < cookiesCount; ++i) { ++ // Remove the first cookie from the list. ++ nsListIter iter(entry, 0); ++ RefPtr cookie = iter.Cookie(); + + // Remove the cookie. +- nsresult rv = Remove(host, entry->mOriginAttributes, name, path, false); +- NS_ENSURE_SUCCESS(rv, rv); ++ RemoveCookieFromList(iter); ++ ++ if (cookie) { ++ NotifyChanged(cookie, u"deleted"); ++ } + } + } + DebugOnly rv = transaction.Commit(); Added: head/www/waterfox/files/patch-bug1412145 ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/www/waterfox/files/patch-bug1412145 Tue Dec 26 21:47:13 2017 (r457317) @@ -0,0 +1,286 @@ +commit d83a24ce6fb3 +Author: Xidorn Quan +Date: Tue Nov 28 17:06:51 2017 -0600 + + Bug 1412145 - Drop more backpointers of CSSOM objects in dtor and unlink. r=bz, a=gchang + + MozReview-Commit-ID: Ftg3WMBBNlO +--- + layout/style/GroupRule.cpp | 7 +++++++ + layout/style/GroupRule.h | 1 + + layout/style/MediaList.h | 4 +++- + layout/style/ServoCSSRuleList.cpp | 2 ++ + layout/style/ServoKeyframeRule.cpp | 12 ++++++++++-- + layout/style/ServoKeyframesRule.cpp | 23 ++++++++++++++++------- + layout/style/ServoMediaRule.cpp | 17 +++++++++++++++-- + layout/style/ServoPageRule.cpp | 2 ++ + layout/style/ServoStyleRule.cpp | 1 + + layout/style/nsCSSRules.cpp | 31 +++++++++++++++++++++++++++---- + 10 files changed, 84 insertions(+), 16 deletions(-) + +diff --git layout/style/GroupRule.cpp layout/style/GroupRule.cpp +index 28739e1818eb..32bd8c83e43a 100644 +--- layout/style/GroupRule.cpp ++++ layout/style/GroupRule.cpp +@@ -198,6 +198,13 @@ GeckoGroupRuleRules::SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const + // ServoGroupRuleRules + // + ++ServoGroupRuleRules::~ServoGroupRuleRules() ++{ ++ if (mRuleList) { ++ mRuleList->DropReference(); ++ } ++} ++ + #ifdef DEBUG + void + ServoGroupRuleRules::List(FILE* out, int32_t aIndent) const +diff --git layout/style/GroupRule.h layout/style/GroupRule.h +index ac9e26921f0b..5c336e5c3611 100644 +--- layout/style/GroupRule.h ++++ layout/style/GroupRule.h +@@ -87,6 +87,7 @@ struct ServoGroupRuleRules + // Do we ever clone Servo rules? + MOZ_ASSERT_UNREACHABLE("stylo: Cloning GroupRule not implemented"); + } ++ ~ServoGroupRuleRules(); + + void SetParentRule(GroupRule* aParentRule) { + if (mRuleList) { +diff --git layout/style/MediaList.h layout/style/MediaList.h +index 4e8c12a2461a..b95e6ec26895 100644 +--- layout/style/MediaList.h ++++ layout/style/MediaList.h +@@ -84,7 +84,9 @@ protected: + virtual nsresult Delete(const nsAString& aOldMedium) = 0; + virtual nsresult Append(const nsAString& aNewMedium) = 0; + +- virtual ~MediaList() {} ++ virtual ~MediaList() { ++ MOZ_ASSERT(!mStyleSheet, "Backpointer should have been cleared"); ++ } + + // not refcounted; sheet will let us know when it goes away + // mStyleSheet is the sheet that needs to be dirtied when this +diff --git layout/style/ServoCSSRuleList.cpp layout/style/ServoCSSRuleList.cpp +index 37ce9be9f337..31f481899964 100644 +--- layout/style/ServoCSSRuleList.cpp ++++ layout/style/ServoCSSRuleList.cpp +@@ -234,6 +234,8 @@ ServoCSSRuleList::GetDOMCSSRuleType(uint32_t aIndex) const + + ServoCSSRuleList::~ServoCSSRuleList() + { ++ MOZ_ASSERT(!mStyleSheet, "Backpointer should have been cleared"); ++ MOZ_ASSERT(!mParentRule, "Backpointer should have been cleared"); + DropAllRules(); + } + +diff --git layout/style/ServoKeyframeRule.cpp layout/style/ServoKeyframeRule.cpp +index 1be82c3100c5..6ca8a1815f8c 100644 +--- layout/style/ServoKeyframeRule.cpp ++++ layout/style/ServoKeyframeRule.cpp +@@ -35,7 +35,10 @@ public: + return NS_OK; + } + +- void DropReference() { mRule = nullptr; } ++ void DropReference() { ++ mRule = nullptr; ++ mDecls->SetOwningRule(nullptr); ++ } + + DeclarationBlock* GetCSSDeclaration(Operation aOperation) final + { +@@ -81,7 +84,9 @@ public: + } + + private: +- virtual ~ServoKeyframeDeclaration() {} ++ virtual ~ServoKeyframeDeclaration() { ++ MOZ_ASSERT(!mRule, "Backpointer should have been cleared"); ++ } + + ServoKeyframeRule* mRule; + RefPtr mDecls; +@@ -102,6 +107,9 @@ NS_INTERFACE_MAP_END_INHERITING(nsDOMCSSDeclaration) + + ServoKeyframeRule::~ServoKeyframeRule() + { ++ if (mDeclaration) { ++ mDeclaration->DropReference(); ++ } + } + + NS_IMPL_ADDREF_INHERITED(ServoKeyframeRule, dom::CSSKeyframeRule) +diff --git layout/style/ServoKeyframesRule.cpp layout/style/ServoKeyframesRule.cpp +index 9a7252a5a639..7341b954ec60 100644 +--- layout/style/ServoKeyframesRule.cpp ++++ layout/style/ServoKeyframesRule.cpp +@@ -90,7 +90,12 @@ public: + { + mStyleSheet = nullptr; + mParentRule = nullptr; +- DropAllRules(); ++ for (css::Rule* rule : mRules) { ++ if (rule) { ++ rule->SetStyleSheet(nullptr); ++ rule->SetParentRule(nullptr); ++ } ++ } + } + + size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const +@@ -103,15 +108,16 @@ public: + } + + private: +- virtual ~ServoKeyframeList() {} ++ virtual ~ServoKeyframeList() { ++ MOZ_ASSERT(!mParentRule, "Backpointer should have been cleared"); ++ MOZ_ASSERT(!mStyleSheet, "Backpointer should have been cleared"); ++ DropAllRules(); ++ } + + void DropAllRules() + { +- for (css::Rule* rule : mRules) { +- if (rule) { +- rule->SetStyleSheet(nullptr); +- rule->SetParentRule(nullptr); +- } ++ if (mParentRule || mStyleSheet) { ++ DropReference(); + } + mRules.Clear(); + mRawRule = nullptr; +@@ -163,6 +169,9 @@ ServoKeyframesRule::ServoKeyframesRule(RefPtr aRawRule, + + ServoKeyframesRule::~ServoKeyframesRule() + { ++ if (mKeyframeList) { ++ mKeyframeList->DropReference(); ++ } + } + + NS_IMPL_ADDREF_INHERITED(ServoKeyframesRule, dom::CSSKeyframesRule) +diff --git layout/style/ServoMediaRule.cpp layout/style/ServoMediaRule.cpp +index 002ae20ffd0b..fbda581a377f 100644 +--- layout/style/ServoMediaRule.cpp ++++ layout/style/ServoMediaRule.cpp +@@ -24,6 +24,9 @@ ServoMediaRule::ServoMediaRule(RefPtr aRawRule, + + ServoMediaRule::~ServoMediaRule() + { ++ if (mMediaList) { ++ mMediaList->SetStyleSheet(nullptr); ++ } + } + + NS_IMPL_ADDREF_INHERITED(ServoMediaRule, CSSMediaRule) +@@ -33,8 +36,18 @@ NS_IMPL_RELEASE_INHERITED(ServoMediaRule, CSSMediaRule) + NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(ServoMediaRule) + NS_INTERFACE_MAP_END_INHERITING(CSSMediaRule) + +-NS_IMPL_CYCLE_COLLECTION_INHERITED(ServoMediaRule, CSSMediaRule, +- mMediaList) ++NS_IMPL_CYCLE_COLLECTION_CLASS(ServoMediaRule) ++ ++NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(ServoMediaRule, CSSMediaRule) ++ if (tmp->mMediaList) { ++ tmp->mMediaList->SetStyleSheet(nullptr); ++ tmp->mMediaList = nullptr; ++ } ++NS_IMPL_CYCLE_COLLECTION_UNLINK_END ++ ++NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(ServoMediaRule, CSSMediaRule) ++ NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMediaList) ++NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END + + /* virtual */ already_AddRefed + ServoMediaRule::Clone() const +diff --git layout/style/ServoPageRule.cpp layout/style/ServoPageRule.cpp +index 97c718ed1ba9..93e8ff334122 100644 +--- layout/style/ServoPageRule.cpp ++++ layout/style/ServoPageRule.cpp +@@ -26,6 +26,7 @@ ServoPageRuleDeclaration::ServoPageRuleDeclaration( + + ServoPageRuleDeclaration::~ServoPageRuleDeclaration() + { ++ mDecls->SetOwningRule(nullptr); + } + + // QueryInterface implementation for ServoPageRuleDeclaration +@@ -141,6 +142,7 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(ServoPageRule, CSSPageRule) + // NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER which we can't use + // directly because the wrapper is on the declaration, not on us. + tmp->mDecls.ReleaseWrapper(static_cast(p)); ++ tmp->mDecls.mDecls->SetOwningRule(nullptr); + NS_IMPL_CYCLE_COLLECTION_UNLINK_END + + NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(ServoPageRule, CSSPageRule) +diff --git layout/style/ServoStyleRule.cpp layout/style/ServoStyleRule.cpp +index 1d7470eef037..855e643515f9 100644 +--- layout/style/ServoStyleRule.cpp ++++ layout/style/ServoStyleRule.cpp +@@ -28,6 +28,7 @@ ServoStyleRuleDeclaration::ServoStyleRuleDeclaration( + + ServoStyleRuleDeclaration::~ServoStyleRuleDeclaration() + { ++ mDecls->SetOwningRule(nullptr); + } + + // QueryInterface implementation for ServoStyleRuleDeclaration +diff --git layout/style/nsCSSRules.cpp layout/style/nsCSSRules.cpp +index 5081244c6a53..0bdedc4a3b03 100644 +--- layout/style/nsCSSRules.cpp ++++ layout/style/nsCSSRules.cpp +@@ -212,12 +212,25 @@ ImportRule::~ImportRule() + NS_IMPL_ADDREF_INHERITED(ImportRule, CSSImportRule) + NS_IMPL_RELEASE_INHERITED(ImportRule, CSSImportRule) + +-NS_IMPL_CYCLE_COLLECTION_INHERITED(ImportRule, CSSImportRule, mMedia, mChildSheet) +- + // QueryInterface implementation for ImportRule + NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(ImportRule) + NS_INTERFACE_MAP_END_INHERITING(CSSImportRule) + ++NS_IMPL_CYCLE_COLLECTION_CLASS(ImportRule) ++ ++NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(ImportRule, CSSImportRule) ++ if (tmp->mChildSheet) { ++ tmp->mChildSheet->SetOwnerRule(nullptr); ++ tmp->mChildSheet = nullptr; ++ } ++ tmp->mMedia = nullptr; ++NS_IMPL_CYCLE_COLLECTION_UNLINK_END ++ ++NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(ImportRule, CSSImportRule) ++ NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMedia) ++ NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mChildSheet) ++NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END ++ + #ifdef DEBUG + /* virtual */ void + ImportRule::List(FILE* out, int32_t aIndent) const +@@ -342,8 +355,18 @@ NS_IMPL_RELEASE_INHERITED(MediaRule, CSSMediaRule) + NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(MediaRule) + NS_INTERFACE_MAP_END_INHERITING(CSSMediaRule) + +-NS_IMPL_CYCLE_COLLECTION_INHERITED(MediaRule, CSSMediaRule, +- mMedia) ++NS_IMPL_CYCLE_COLLECTION_CLASS(MediaRule) ++ ++NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(MediaRule, CSSMediaRule) ++ if (tmp->mMedia) { ++ tmp->mMedia->SetStyleSheet(nullptr); ++ tmp->mMedia = nullptr; ++ } ++NS_IMPL_CYCLE_COLLECTION_UNLINK_END ++ ++NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(MediaRule, CSSMediaRule) ++ NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMedia) ++NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END + + /* virtual */ void + MediaRule::SetStyleSheet(StyleSheet* aSheet) Added: head/www/waterfox/files/patch-bug1413741 ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/www/waterfox/files/patch-bug1413741 Tue Dec 26 21:47:13 2017 (r457317) @@ -0,0 +1,25 @@ +commit bd17df85baf4 +Author: Andrea Marchesini *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***