Backed out 4 changesets (bug 1416724) for failing /builds/worker/workspace/build/src/dom/media/hls/HLSDemuxer.cpp:89:5 r=backout on a CLOSED TREE
authorshindli <shindli@mozilla.com>
Wed, 15 Nov 2017 09:49:04 +0200
changeset 391960 7613f8e20ad525e183b9e5a237cb5725fbe3f630
parent 391959 7e35281e0eafbc99ee94d182dfb11d4492f89120
child 391961 3aa5eb7e2ed90b56d28f2618ed1339da085028b2
push id32909
push usercbrindusan@mozilla.com
push dateWed, 15 Nov 2017 22:25:14 +0000
treeherdermozilla-central@f41930a869a8 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbackout
bugs1416724
milestone59.0a1
backs out45352aa4319debd6ad3445f2729db197ffc83eac
01d1e5263bcd56fadf19b446b48c4ab2c9de6891
bc854c315ec8c0dfde87ca0193c024d16314aaa2
35a50167485d1507d07e85b21e29f6b17c505d7d
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Backed out 4 changesets (bug 1416724) for failing /builds/worker/workspace/build/src/dom/media/hls/HLSDemuxer.cpp:89:5 r=backout on a CLOSED TREE Backed out changeset 45352aa4319d (bug 1416724) Backed out changeset 01d1e5263bcd (bug 1416724) Backed out changeset bc854c315ec8 (bug 1416724) Backed out changeset 35a50167485d (bug 1416724)
dom/file/MutableBlobStorage.cpp
dom/file/MutableBlobStorage.h
dom/media/MediaDecoder.cpp
dom/media/MediaDecoderStateMachine.cpp
dom/media/MediaDecoderStateMachine.h
dom/media/MediaEventSource.h
dom/media/MediaFormatReader.cpp
dom/media/MediaRecorder.cpp
dom/media/ReaderProxy.cpp
dom/media/encoder/MediaEncoder.cpp
dom/media/gtest/TestMP4Demuxer.cpp
dom/media/mediasource/AutoTaskQueue.h
dom/media/mediasource/MediaSourceDemuxer.cpp
dom/media/mediasource/TrackBuffersManager.cpp
dom/media/platforms/android/RemoteDataDecoder.cpp
dom/media/platforms/omx/OmxDataDecoder.cpp
dom/media/webaudio/MediaBufferDecoder.cpp
media/webrtc/signaling/src/mediapipeline/MediaPipeline.cpp
netwerk/base/nsNetUtil.cpp
xpcom/tests/gtest/TestMozPromise.cpp
xpcom/tests/gtest/TestStateWatching.cpp
xpcom/tests/gtest/TestTaskQueue.cpp
xpcom/threads/AbstractThread.cpp
xpcom/threads/AbstractThread.h
xpcom/threads/StateMirroring.h
xpcom/threads/TaskDispatcher.h
xpcom/threads/TaskQueue.cpp
xpcom/threads/TaskQueue.h
--- a/dom/file/MutableBlobStorage.cpp
+++ b/dom/file/MutableBlobStorage.cpp
@@ -359,17 +359,17 @@ MutableBlobStorage::MutableBlobStorage(M
 }
 
 MutableBlobStorage::~MutableBlobStorage()
 {
   free(mData);
 
   if (mFD) {
     RefPtr<Runnable> runnable = new CloseFileRunnable(mFD);
-    Unused << DispatchToIOThread(runnable.forget());
+    DispatchToIOThread(runnable.forget());
   }
 
   if (mTaskQueue) {
     mTaskQueue->BeginShutdown();
   }
 
   if (mActor) {
     NS_ProxyRelease("MutableBlobStorage::mActor",
@@ -403,20 +403,17 @@ MutableBlobStorage::GetBlobWhenReady(nsI
     MOZ_ASSERT(mActor);
 
     // We want to wait until all the WriteRunnable are completed. The way we do
     // this is to go to the I/O thread and then we come back: the runnables are
     // executed in order and this LastRunnable will be... the last one.
     // This Runnable will also close the FD on the I/O thread.
     RefPtr<Runnable> runnable =
       new LastRunnable(this, aParent, aContentType, aCallback);
-
-    // If the dispatching fails, we are shutting down and it's fine to do not
-    // run the callback.
-    Unused << DispatchToIOThread(runnable.forget());
+    DispatchToIOThread(runnable.forget());
     return;
   }
 
   // If we are waiting for the temporary file, it's better to wait...
   if (previousState == eWaitingForTemporaryFile) {
     mPendingParent = aParent;
     mPendingContentType = aContentType;
     mPendingCallback = aCallback;
@@ -473,20 +470,17 @@ MutableBlobStorage::Append(const void* a
     }
 
     RefPtr<WriteRunnable> runnable =
       WriteRunnable::CopyBuffer(this, aData, aLength);
     if (NS_WARN_IF(!runnable)) {
       return NS_ERROR_OUT_OF_MEMORY;
     }
 
-    nsresult rv = DispatchToIOThread(runnable.forget());
-    if (NS_WARN_IF(NS_FAILED(rv))) {
-      return rv;
-    }
+    DispatchToIOThread(runnable.forget());
 
     mDataLen += aLength;
     return NS_OK;
   }
 
   // By default, we store in memory.
 
   uint64_t offset = mDataLen;
@@ -582,20 +576,17 @@ MutableBlobStorage::TemporaryFileCreated
   MOZ_ASSERT_IF(mPendingCallback, mStorageState == eClosed);
   MOZ_ASSERT(mActor);
   MOZ_ASSERT(aFD);
 
   // If the object has been already closed and we don't need to execute a
   // callback, we need just to close the file descriptor in the correct thread.
   if (mStorageState == eClosed && !mPendingCallback) {
     RefPtr<Runnable> runnable = new CloseFileRunnable(aFD);
-
-    // If this dispatching fails, CloseFileRunnable will close the FD in the
-    // DTOR on the current thread.
-    Unused << DispatchToIOThread(runnable.forget());
+    DispatchToIOThread(runnable.forget());
 
     // Let's inform the parent that we have nothing else to do.
     mActor->SendOperationDone(false, EmptyCString());
     mActor = nullptr;
     return;
   }
 
   // If we still receiving data, we can proceed in temporary-file mode.
@@ -609,34 +600,30 @@ MutableBlobStorage::TemporaryFileCreated
   // This runnable takes the ownership of mData and it will write this buffer
   // into the temporary file.
   RefPtr<WriteRunnable> runnable =
     WriteRunnable::AdoptBuffer(this, mData, mDataLen);
   MOZ_ASSERT(runnable);
 
   mData = nullptr;
 
-  nsresult rv = DispatchToIOThread(runnable.forget());
-  if (NS_WARN_IF(NS_FAILED(rv))) {
-    // Shutting down, we cannot continue.
-    return;
-  }
+  DispatchToIOThread(runnable.forget());
 
   // If we are closed, it means that GetBlobWhenReady() has been called when we
   // were already waiting for a temporary file-descriptor. Finally we are here,
   // AdoptBuffer runnable is going to write the current buffer into this file.
   // After that, there is nothing else to write, and we dispatch LastRunnable
   // which ends up calling mPendingCallback via CreateBlobRunnable.
   if (mStorageState == eClosed) {
     MOZ_ASSERT(mPendingCallback);
 
     RefPtr<Runnable> runnable =
       new LastRunnable(this, mPendingParent, mPendingContentType,
                        mPendingCallback);
-    Unused << DispatchToIOThread(runnable.forget());
+    DispatchToIOThread(runnable.forget());
 
     mPendingParent = nullptr;
     mPendingCallback = nullptr;
   }
 }
 
 void
 MutableBlobStorage::AskForBlob(TemporaryIPCBlobChildCallback* aCallback,
@@ -659,34 +646,29 @@ MutableBlobStorage::ErrorPropagated(nsre
   mErrorResult = aRv;
 
   if (mActor) {
     mActor->SendOperationDone(false, EmptyCString());
     mActor = nullptr;
   }
 }
 
-nsresult
+void
 MutableBlobStorage::DispatchToIOThread(already_AddRefed<nsIRunnable> aRunnable)
 {
   if (!mTaskQueue) {
     nsCOMPtr<nsIEventTarget> target
       = do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID);
     MOZ_ASSERT(target);
 
     mTaskQueue = new TaskQueue(target.forget());
   }
 
   nsCOMPtr<nsIRunnable> runnable(aRunnable);
-  nsresult rv = mTaskQueue->Dispatch(runnable.forget());
-  if (NS_WARN_IF(NS_FAILED(rv))) {
-    return rv;
-  }
-
-  return NS_OK;
+  mTaskQueue->Dispatch(runnable.forget());
 }
 
 size_t
 MutableBlobStorage::SizeOfCurrentMemoryBuffer() const
 {
   MOZ_ASSERT(NS_IsMainThread());
   return mStorageState < eInTemporaryFile ? mDataLen : 0;
 }
--- a/dom/file/MutableBlobStorage.h
+++ b/dom/file/MutableBlobStorage.h
@@ -84,18 +84,17 @@ private:
   ~MutableBlobStorage();
 
   bool ExpandBufferSize(uint64_t aSize);
 
   bool ShouldBeTemporaryStorage(uint64_t aSize) const;
 
   bool MaybeCreateTemporaryFile();
 
-  MOZ_MUST_USE nsresult
-  DispatchToIOThread(already_AddRefed<nsIRunnable> aRunnable);
+  void DispatchToIOThread(already_AddRefed<nsIRunnable> aRunnable);
 
   // All these variables are touched on the main thread only.
 
   void* mData;
   uint64_t mDataLen;
   uint64_t mDataBufferLen;
 
   enum StorageState {
--- a/dom/media/MediaDecoder.cpp
+++ b/dom/media/MediaDecoder.cpp
@@ -20,17 +20,16 @@
 #include "mozilla/Preferences.h"
 #include "mozilla/StaticPtr.h"
 #include "mozilla/Telemetry.h"
 #include "mozilla/dom/AudioTrack.h"
 #include "mozilla/dom/AudioTrackList.h"
 #include "mozilla/dom/VideoTrack.h"
 #include "mozilla/dom/VideoTrackList.h"
 #include "mozilla/layers/ShadowLayers.h"
-#include "mozilla/Unused.h"
 #include "nsComponentManagerUtils.h"
 #include "nsContentUtils.h"
 #include "nsError.h"
 #include "nsIMemoryReporter.h"
 #include "nsIObserver.h"
 #include "nsPrintfCString.h"
 #include "nsTArray.h"
 #include <algorithm>
@@ -1095,17 +1094,18 @@ MediaDecoder::NotifyCompositor()
   RefPtr<KnowsCompositor> knowsCompositor = GetCompositor();
   if (knowsCompositor) {
     nsCOMPtr<nsIRunnable> r =
       NewRunnableMethod<already_AddRefed<KnowsCompositor>&&>(
         "MediaFormatReader::UpdateCompositor",
         mReader,
         &MediaFormatReader::UpdateCompositor,
         knowsCompositor.forget());
-    Unused << mReader->OwnerThread()->Dispatch(r.forget());
+    mReader->OwnerThread()->Dispatch(r.forget(),
+                                     AbstractThread::DontAssertDispatchSuccess);
   }
 }
 
 void
 MediaDecoder::SetElementVisibility(bool aIsDocumentVisible,
                                    Visibility aElementVisibility,
                                    bool aIsElementInTree)
 {
@@ -1375,23 +1375,20 @@ MediaDecoder::SizeOfAudioQueue()
   return 0;
 }
 
 void
 MediaDecoder::NotifyDataArrivedInternal()
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_DIAGNOSTIC_ASSERT(!IsShutdown());
-
-  nsresult rv =
-    mReader->OwnerThread()->Dispatch(
-      NewRunnableMethod("MediaFormatReader::NotifyDataArrived",
-                        mReader.get(),
-                        &MediaFormatReader::NotifyDataArrived));
-  MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
+  mReader->OwnerThread()->Dispatch(
+    NewRunnableMethod("MediaFormatReader::NotifyDataArrived",
+                      mReader.get(),
+                      &MediaFormatReader::NotifyDataArrived));
 }
 
 void
 MediaDecoder::NotifyDataArrived()
 {
   NotifyDataArrivedInternal();
   DownloadProgressed();
 }
--- a/dom/media/MediaDecoderStateMachine.cpp
+++ b/dom/media/MediaDecoderStateMachine.cpp
@@ -1495,18 +1495,17 @@ public:
     // then switch to the CompletedState which dispatches an "ended" event.
     // However, the ThenValue of the SeekPromise has not yet been set, so the
     // promise resolving is postponed and then the JS developer receives the
     // "ended" event before the seek promise is resolved.
     // An asynchronous seek operation helps to solve this issue since while the
     // seek is actually performed, the ThenValue of SeekPromise has already
     // been set so that it won't be postponed.
     RefPtr<Runnable> r = mAsyncSeekTask = new AysncNextFrameSeekTask(this);
-    nsresult rv = OwnerThread()->Dispatch(r.forget());
-    MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
+    OwnerThread()->Dispatch(r.forget());
   }
 
 private:
   void DoSeekInternal()
   {
     // We don't need to discard frames to the mCurrentTime here because we have
     // done it at DoSeek() and any video data received in between either
     // finishes the seek operation or be discarded, see HandleVideoDecoded().
@@ -3493,22 +3492,20 @@ void
 MediaDecoderStateMachine::ScheduleStateMachine()
 {
   MOZ_ASSERT(OnTaskQueue());
   if (mDispatchedStateMachine) {
     return;
   }
   mDispatchedStateMachine = true;
 
-  nsresult rv =
-    OwnerThread()->Dispatch(
-      NewRunnableMethod("MediaDecoderStateMachine::RunStateMachine",
-                        this,
-                        &MediaDecoderStateMachine::RunStateMachine));
-  MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
+  OwnerThread()->Dispatch(
+    NewRunnableMethod("MediaDecoderStateMachine::RunStateMachine",
+                      this,
+                      &MediaDecoderStateMachine::RunStateMachine));
 }
 
 void
 MediaDecoderStateMachine::ScheduleStateMachineIn(const TimeUnit& aTime)
 {
   MOZ_ASSERT(OnTaskQueue()); // mDelayedScheduler.Ensure() may Disconnect()
                              // the promise, which must happen on the state
                              // machine task queue.
@@ -3728,53 +3725,51 @@ MediaDecoderStateMachine::GetDebugInfo()
 }
 
 RefPtr<MediaDecoder::DebugInfoPromise>
 MediaDecoderStateMachine::RequestDebugInfo()
 {
   using PromiseType = MediaDecoder::DebugInfoPromise;
   RefPtr<PromiseType::Private> p = new PromiseType::Private(__func__);
   RefPtr<MediaDecoderStateMachine> self = this;
-  nsresult rv = OwnerThread()->Dispatch(
+  OwnerThread()->Dispatch(
     NS_NewRunnableFunction(
       "MediaDecoderStateMachine::RequestDebugInfo",
       [self, p]() { p->Resolve(self->GetDebugInfo(), __func__); }),
+    AbstractThread::AssertDispatchSuccess,
     AbstractThread::TailDispatch);
-  MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
   return p.forget();
 }
 
 void MediaDecoderStateMachine::AddOutputStream(ProcessedMediaStream* aStream,
                                                bool aFinishWhenEnded)
 {
   MOZ_ASSERT(NS_IsMainThread());
   LOG("AddOutputStream aStream=%p!", aStream);
   mOutputStreamManager->Add(aStream, aFinishWhenEnded);
   nsCOMPtr<nsIRunnable> r =
     NewRunnableMethod<bool>("MediaDecoderStateMachine::SetAudioCaptured",
                             this,
                             &MediaDecoderStateMachine::SetAudioCaptured,
                             true);
-  nsresult rv = OwnerThread()->Dispatch(r.forget());
-  MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
+  OwnerThread()->Dispatch(r.forget());
 }
 
 void MediaDecoderStateMachine::RemoveOutputStream(MediaStream* aStream)
 {
   MOZ_ASSERT(NS_IsMainThread());
   LOG("RemoveOutputStream=%p!", aStream);
   mOutputStreamManager->Remove(aStream);
   if (mOutputStreamManager->IsEmpty()) {
     nsCOMPtr<nsIRunnable> r =
       NewRunnableMethod<bool>("MediaDecoderStateMachine::SetAudioCaptured",
                               this,
                               &MediaDecoderStateMachine::SetAudioCaptured,
                               false);
-    nsresult rv = OwnerThread()->Dispatch(r.forget());
-    MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
+    OwnerThread()->Dispatch(r.forget());
   }
 }
 
 class VideoQueueMemoryFunctor : public nsDequeFunctor
 {
 public:
   VideoQueueMemoryFunctor()
     : mSize(0)
--- a/dom/media/MediaDecoderStateMachine.h
+++ b/dom/media/MediaDecoderStateMachine.h
@@ -199,18 +199,17 @@ public:
     nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction(
       "MediaDecoderStateMachine::DispatchSetFragmentEndTime",
       [self, aEndTime]() {
         // A negative number means we don't have a fragment end time at all.
         self->mFragmentEndTime = aEndTime >= media::TimeUnit::Zero()
                                    ? aEndTime
                                    : media::TimeUnit::Invalid();
       });
-    nsresult rv = OwnerThread()->Dispatch(r.forget());
-    MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
+    OwnerThread()->Dispatch(r.forget());
   }
 
   void DispatchCanPlayThrough(bool aCanPlayThrough)
   {
     RefPtr<MediaDecoderStateMachine> self = this;
     nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction(
       "MediaDecoderStateMachine::DispatchCanPlayThrough",
       [self, aCanPlayThrough]() {
--- a/dom/media/MediaEventSource.h
+++ b/dom/media/MediaEventSource.h
@@ -8,17 +8,16 @@
 #define MediaEventSource_h_
 
 #include "mozilla/AbstractThread.h"
 #include "mozilla/Atomics.h"
 #include "mozilla/IndexSequence.h"
 #include "mozilla/Mutex.h"
 #include "mozilla/Tuple.h"
 #include "mozilla/TypeTraits.h"
-#include "mozilla/Unused.h"
 
 #include "nsISupportsImpl.h"
 #include "nsTArray.h"
 #include "nsThreadUtils.h"
 
 namespace mozilla {
 
 /**
@@ -105,17 +104,17 @@ struct EventTarget<nsIEventTarget> {
     aTarget->Dispatch(Move(aTask), NS_DISPATCH_NORMAL);
   }
 };
 
 template <>
 struct EventTarget<AbstractThread> {
   static void
   Dispatch(AbstractThread* aTarget, already_AddRefed<nsIRunnable> aTask) {
-    Unused << aTarget->Dispatch(Move(aTask));
+    aTarget->Dispatch(Move(aTask), AbstractThread::DontAssertDispatchSuccess);
   }
 };
 
 /**
  * Encapsulate a raw pointer to be captured by a lambda without causing
  * static-analysis errors.
  */
 template <typename T>
--- a/dom/media/MediaFormatReader.cpp
+++ b/dom/media/MediaFormatReader.cpp
@@ -1020,21 +1020,19 @@ public:
   bool GetSamplesMayBlock() const override
   {
     return mGetSamplesMayBlock;
   }
 
   void Reset() override
   {
     RefPtr<Wrapper> self = this;
-    nsresult rv =
-      mTaskQueue->Dispatch(
-        NS_NewRunnableFunction("MediaFormatReader::DemuxerProxy::Wrapper::Reset",
-                               [self]() { self->mTrackDemuxer->Reset(); }));
-    MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
+    mTaskQueue->Dispatch(
+      NS_NewRunnableFunction("MediaFormatReader::DemuxerProxy::Wrapper::Reset",
+                             [self]() { self->mTrackDemuxer->Reset(); }));
   }
 
   nsresult GetNextRandomAccessPoint(TimeUnit* aTime) override
   {
     MutexAutoLock lock(mMutex);
     if (NS_SUCCEEDED(mNextRandomAccessPointResult)) {
       *aTime = mNextRandomAccessPoint;
     }
@@ -1081,21 +1079,19 @@ private:
   nsresult mNextRandomAccessPointResult = NS_OK;
   TimeUnit mNextRandomAccessPoint;
   TimeIntervals mBuffered;
   friend class DemuxerProxy;
 
   ~Wrapper()
   {
     RefPtr<MediaTrackDemuxer> trackDemuxer = mTrackDemuxer.forget();
-    nsresult rv =
-      mTaskQueue->Dispatch(NS_NewRunnableFunction(
-        "MediaFormatReader::DemuxerProxy::Wrapper::~Wrapper",
-        [trackDemuxer]() { trackDemuxer->BreakCycles(); }));
-    MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
+    mTaskQueue->Dispatch(NS_NewRunnableFunction(
+      "MediaFormatReader::DemuxerProxy::Wrapper::~Wrapper",
+      [trackDemuxer]() { trackDemuxer->BreakCycles(); }));
   }
 
   void UpdateRandomAccessPoint()
   {
     MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn());
     if (!mTrackDemuxer) {
       // Detached.
       return;
@@ -1993,18 +1989,17 @@ MediaFormatReader::ScheduleUpdate(TrackT
   auto& decoder = GetDecoderData(aTrack);
   if (decoder.mUpdateScheduled) {
     return;
   }
   LOGV("SchedulingUpdate(%s)", TrackTypeToStr(aTrack));
   decoder.mUpdateScheduled = true;
   RefPtr<nsIRunnable> task(NewRunnableMethod<TrackType>(
     "MediaFormatReader::Update", this, &MediaFormatReader::Update, aTrack));
-  nsresult rv = OwnerThread()->Dispatch(task.forget());
-  MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
+  OwnerThread()->Dispatch(task.forget());
 }
 
 bool
 MediaFormatReader::UpdateReceivedNewData(TrackType aTrack)
 {
   MOZ_ASSERT(OnTaskQueue());
   auto& decoder = GetDecoderData(aTrack);
 
@@ -2892,20 +2887,18 @@ MediaFormatReader::SetSeekTarget(const S
 
 void
 MediaFormatReader::ScheduleSeek()
 {
   if (mSeekScheduled) {
     return;
   }
   mSeekScheduled = true;
-  nsresult rv =
-    OwnerThread()->Dispatch(NewRunnableMethod(
-      "MediaFormatReader::AttemptSeek", this, &MediaFormatReader::AttemptSeek));
-  MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
+  OwnerThread()->Dispatch(NewRunnableMethod(
+    "MediaFormatReader::AttemptSeek", this, &MediaFormatReader::AttemptSeek));
 }
 
 void
 MediaFormatReader::AttemptSeek()
 {
   MOZ_ASSERT(OnTaskQueue());
 
   mSeekScheduled = false;
--- a/dom/media/MediaRecorder.cpp
+++ b/dom/media/MediaRecorder.cpp
@@ -957,22 +957,20 @@ private:
 
     if (!mEncoder) {
       LOG(LogLevel::Error, ("Session.InitEncoder !mEncoder %p", this));
       DoSessionEndTask(NS_ERROR_ABORT);
       return;
     }
 
     mEncoderListener = MakeAndAddRef<EncoderListener>(mEncoderThread, this);
-    nsresult rv =
-      mEncoderThread->Dispatch(
-        NewRunnableMethod<RefPtr<EncoderListener>>(
-          "mozilla::MediaEncoder::RegisterListener",
-          mEncoder, &MediaEncoder::RegisterListener, mEncoderListener));
-    MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
+    mEncoderThread->Dispatch(
+      NewRunnableMethod<RefPtr<EncoderListener>>(
+        "mozilla::MediaEncoder::RegisterListener",
+        mEncoder, &MediaEncoder::RegisterListener, mEncoderListener));
 
     if (mRecorder->mAudioNode) {
       mEncoder->ConnectAudioNode(mRecorder->mAudioNode,
                                  mRecorder->mAudioNodeOutput);
     }
 
     for (auto& track : mMediaStreamTracks) {
       mEncoder->ConnectMediaStreamTrack(track);
--- a/dom/media/ReaderProxy.cpp
+++ b/dom/media/ReaderProxy.cpp
@@ -130,31 +130,29 @@ ReaderProxy::WaitForData(MediaData::Type
 void
 ReaderProxy::ReleaseResources()
 {
   MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
   nsCOMPtr<nsIRunnable> r =
     NewRunnableMethod("MediaFormatReader::ReleaseResources",
                       mReader,
                       &MediaFormatReader::ReleaseResources);
-  nsresult rv = mReader->OwnerThread()->Dispatch(r.forget());
-  MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
+  mReader->OwnerThread()->Dispatch(r.forget());
 }
 
 void
 ReaderProxy::ResetDecode(TrackSet aTracks)
 {
   MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
   nsCOMPtr<nsIRunnable> r =
     NewRunnableMethod<TrackSet>("MediaFormatReader::ResetDecode",
                                 mReader,
                                 &MediaFormatReader::ResetDecode,
                                 aTracks);
-  nsresult rv = mReader->OwnerThread()->Dispatch(r.forget());
-  MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
+  mReader->OwnerThread()->Dispatch(r.forget());
 }
 
 RefPtr<ShutdownPromise>
 ReaderProxy::Shutdown()
 {
   MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
   mShutdown = true;
   RefPtr<ReaderProxy> self = this;
@@ -190,18 +188,17 @@ void
 ReaderProxy::SetVideoBlankDecode(bool aIsBlankDecode)
 {
   MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
   nsCOMPtr<nsIRunnable> r =
     NewRunnableMethod<bool>("MediaFormatReader::SetVideoNullDecode",
                             mReader,
                             &MediaFormatReader::SetVideoNullDecode,
                             aIsBlankDecode);
-  nsresult rv = mReader->OwnerThread()->Dispatch(r.forget());
-  MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
+  mReader->OwnerThread()->Dispatch(r.forget());
 }
 
 void
 ReaderProxy::UpdateDuration()
 {
   MOZ_ASSERT(mReader->OwnerThread()->IsCurrentThreadIn());
   mReader->UpdateDuration(mDuration.Ref().ref());
 }
@@ -213,13 +210,12 @@ ReaderProxy::SetCanonicalDuration(
   using DurationT = AbstractCanonical<media::NullableTimeUnit>;
   RefPtr<ReaderProxy> self = this;
   RefPtr<DurationT> canonical = aCanonical;
   nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction(
     "ReaderProxy::SetCanonicalDuration", [this, self, canonical]() {
       mDuration.Connect(canonical);
       mWatchManager.Watch(mDuration, &ReaderProxy::UpdateDuration);
     });
-  nsresult rv = mReader->OwnerThread()->Dispatch(r.forget());
-  MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
+  mReader->OwnerThread()->Dispatch(r.forget());
 }
 
 } // namespace mozilla
--- a/dom/media/encoder/MediaEncoder.cpp
+++ b/dom/media/encoder/MediaEncoder.cpp
@@ -16,17 +16,16 @@
 #include "mozilla/dom/MediaStreamTrack.h"
 #include "mozilla/dom/VideoStreamTrack.h"
 #include "mozilla/gfx/Point.h" // IntSize
 #include "mozilla/Logging.h"
 #include "mozilla/media/MediaUtils.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/StaticPtr.h"
 #include "mozilla/TaskQueue.h"
-#include "mozilla/Unused.h"
 #include "nsIPrincipal.h"
 #include "nsMimeTypes.h"
 #include "OggWriter.h"
 #include "OpusTrackEncoder.h"
 #include "TimeUnits.h"
 
 #ifdef MOZ_WEBM_ENCODER
 #include "VP8TrackEncoder.h"
@@ -92,47 +91,41 @@ public:
     MOZ_ASSERT(mEncoder);
     MOZ_ASSERT(mEncoderThread);
 
     if (mShutdown) {
       return;
     }
 
     if (!mInitialized) {
-      nsresult rv =
-        mEncoderThread->Dispatch(
-          NewRunnableMethod<StreamTime>(
-            "mozilla::AudioTrackEncoder::SetStartOffset",
-            mEncoder, &AudioTrackEncoder::SetStartOffset, aTrackOffset));
-      MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
+      mEncoderThread->Dispatch(
+        NewRunnableMethod<StreamTime>(
+          "mozilla::AudioTrackEncoder::SetStartOffset",
+          mEncoder, &AudioTrackEncoder::SetStartOffset, aTrackOffset));
       mInitialized = true;
     }
 
     if (mDirectConnected) {
       if (aQueuedMedia.IsNull()) {
-        nsresult rv =
-          mEncoderThread->Dispatch(
-            NewRunnableMethod<StreamTime>(
-              "mozilla::AudioTrackEncoder::AdvanceBlockedInput",
-              mEncoder, &AudioTrackEncoder::AdvanceBlockedInput,
-              aQueuedMedia.GetDuration()));
-        MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
+        mEncoderThread->Dispatch(
+          NewRunnableMethod<StreamTime>(
+            "mozilla::AudioTrackEncoder::AdvanceBlockedInput",
+            mEncoder, &AudioTrackEncoder::AdvanceBlockedInput,
+            aQueuedMedia.GetDuration()));
         return;
       }
     } else {
       NotifyRealtimeTrackData(aGraph, aTrackOffset, aQueuedMedia);
     }
 
-    nsresult rv =
-      mEncoderThread->Dispatch(
-        NewRunnableMethod<StreamTime>(
-          "mozilla::AudioTrackEncoder::AdvanceCurrentTime",
-          mEncoder, &AudioTrackEncoder::AdvanceCurrentTime,
-          aQueuedMedia.GetDuration()));
-    MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
+    mEncoderThread->Dispatch(
+      NewRunnableMethod<StreamTime>(
+        "mozilla::AudioTrackEncoder::AdvanceCurrentTime",
+        mEncoder, &AudioTrackEncoder::AdvanceCurrentTime,
+        aQueuedMedia.GetDuration()));
   }
 
   void NotifyRealtimeTrackData(MediaStreamGraph* aGraph,
                                StreamTime aTrackOffset,
                                const MediaSegment& aMedia) override
   {
     MOZ_ASSERT(mEncoder);
     MOZ_ASSERT(mEncoderThread);
@@ -141,48 +134,42 @@ public:
       return;
     }
 
     const AudioSegment& audio = static_cast<const AudioSegment&>(aMedia);
 
     AudioSegment copy;
     copy.AppendSlice(audio, 0, audio.GetDuration());
 
-    nsresult rv =
-      mEncoderThread->Dispatch(
-        NewRunnableMethod<StoreCopyPassByRRef<AudioSegment>>(
-          "mozilla::AudioTrackEncoder::AppendAudioSegment",
-          mEncoder, &AudioTrackEncoder::AppendAudioSegment, Move(copy)));
-    MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
+    mEncoderThread->Dispatch(
+      NewRunnableMethod<StoreCopyPassByRRef<AudioSegment>>(
+        "mozilla::AudioTrackEncoder::AppendAudioSegment",
+        mEncoder, &AudioTrackEncoder::AppendAudioSegment, Move(copy)));
   }
 
   void NotifyEnded() override
   {
     MOZ_ASSERT(mEncoder);
     MOZ_ASSERT(mEncoderThread);
 
     if (mShutdown) {
       return;
     }
 
-    nsresult rv =
-      mEncoderThread->Dispatch(
-        NewRunnableMethod("mozilla::AudioTrackEncoder::NotifyEndOfStream",
-                          mEncoder, &AudioTrackEncoder::NotifyEndOfStream));
-    MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
+    mEncoderThread->Dispatch(
+      NewRunnableMethod("mozilla::AudioTrackEncoder::NotifyEndOfStream",
+                        mEncoder, &AudioTrackEncoder::NotifyEndOfStream));
   }
 
   void NotifyRemoved() override
   {
     if (!mShutdown) {
-      nsresult rv =
-        mEncoderThread->Dispatch(
-          NewRunnableMethod("mozilla::AudioTrackEncoder::NotifyEndOfStream",
-                            mEncoder, &AudioTrackEncoder::NotifyEndOfStream));
-      MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
+      mEncoderThread->Dispatch(
+        NewRunnableMethod("mozilla::AudioTrackEncoder::NotifyEndOfStream",
+                          mEncoder, &AudioTrackEncoder::NotifyEndOfStream));
     }
 
     mRemoved = true;
 
     if (!mDirectConnected) {
       mEncoder = nullptr;
       mEncoderThread = nullptr;
     }
@@ -246,91 +233,79 @@ public:
     MOZ_ASSERT(mEncoder);
     MOZ_ASSERT(mEncoderThread);
 
     if (mShutdown) {
       return;
     }
 
     if (!mInitialized) {
-      nsresult rv =
-        mEncoderThread->Dispatch(
-          NewRunnableMethod<StreamTime>(
-            "mozilla::VideoTrackEncoder::SetStartOffset",
-            mEncoder, &VideoTrackEncoder::SetStartOffset, aTrackOffset));
-      MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
+      mEncoderThread->Dispatch(
+        NewRunnableMethod<StreamTime>(
+          "mozilla::VideoTrackEncoder::SetStartOffset",
+          mEncoder, &VideoTrackEncoder::SetStartOffset, aTrackOffset));
       mInitialized = true;
     }
 
     if (aQueuedMedia.IsNull()) {
-      nsresult rv =
-        mEncoderThread->Dispatch(
-          NewRunnableMethod<StreamTime>(
-            "mozilla::VideoTrackEncoder::AdvanceBlockedInput",
-            mEncoder, &VideoTrackEncoder::AdvanceBlockedInput,
-            aQueuedMedia.GetDuration()));
-      MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
+      mEncoderThread->Dispatch(
+        NewRunnableMethod<StreamTime>(
+          "mozilla::VideoTrackEncoder::AdvanceBlockedInput",
+          mEncoder, &VideoTrackEncoder::AdvanceBlockedInput,
+          aQueuedMedia.GetDuration()));
       return;
     }
 
-    nsresult rv =
-      mEncoderThread->Dispatch(
-        NewRunnableMethod<StreamTime>(
-          "mozilla::VideoTrackEncoder::AdvanceCurrentTime",
-          mEncoder, &VideoTrackEncoder::AdvanceCurrentTime,
-          aQueuedMedia.GetDuration()));
-    MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
+    mEncoderThread->Dispatch(
+      NewRunnableMethod<StreamTime>(
+        "mozilla::VideoTrackEncoder::AdvanceCurrentTime",
+        mEncoder, &VideoTrackEncoder::AdvanceCurrentTime,
+        aQueuedMedia.GetDuration()));
   }
 
   void SetCurrentFrames(const VideoSegment& aMedia) override
   {
     MOZ_ASSERT(mEncoder);
     MOZ_ASSERT(mEncoderThread);
 
     if (mShutdown) {
       return;
     }
 
     VideoSegment copy;
     copy.AppendSlice(aMedia, 0, aMedia.GetDuration());
 
-    nsresult rv =
-      mEncoderThread->Dispatch(
-        NewRunnableMethod<StoreCopyPassByRRef<VideoSegment>>(
-          "mozilla::VideoTrackEncoder::AppendVideoSegment",
-          mEncoder, &VideoTrackEncoder::AppendVideoSegment, Move(copy)));
-    MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
+    mEncoderThread->Dispatch(
+      NewRunnableMethod<StoreCopyPassByRRef<VideoSegment>>(
+        "mozilla::VideoTrackEncoder::AppendVideoSegment",
+        mEncoder, &VideoTrackEncoder::AppendVideoSegment, Move(copy)));
   }
 
   void ClearFrames() override {}
 
   void NotifyEnded() override
   {
     MOZ_ASSERT(mEncoder);
     MOZ_ASSERT(mEncoderThread);
 
     if (mShutdown) {
       return;
     }
 
-    nsresult rv =
-      mEncoderThread->Dispatch(
-        NewRunnableMethod("mozilla::VideoTrackEncoder::NotifyEndOfStream",
-                          mEncoder, &VideoTrackEncoder::NotifyEndOfStream));
-    MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
+    mEncoderThread->Dispatch(
+      NewRunnableMethod("mozilla::VideoTrackEncoder::NotifyEndOfStream",
+                        mEncoder, &VideoTrackEncoder::NotifyEndOfStream));
   }
 
   void NotifyRemoved() override
   {
     if (!mShutdown) {
-      nsresult rv =
-        mEncoderThread->Dispatch(
-          NewRunnableMethod("mozilla::VideoTrackEncoder::NotifyEndOfStream",
-                            mEncoder, &VideoTrackEncoder::NotifyEndOfStream));
-      MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
+      mEncoderThread->Dispatch(
+        NewRunnableMethod("mozilla::VideoTrackEncoder::NotifyEndOfStream",
+                          mEncoder, &VideoTrackEncoder::NotifyEndOfStream));
     }
 
     mRemoved = true;
 
     if (!mDirectConnected) {
       mEncoder = nullptr;
       mEncoderThread = nullptr;
     }
@@ -365,41 +340,37 @@ public:
   {
     MOZ_ASSERT(mEncoderThread->IsCurrentThreadIn());
     MOZ_ASSERT(aTrackEncoder->IsInitialized());
 
     if (!mEncoder) {
       return;
     }
 
-    nsresult rv =
-      mEncoderThread->Dispatch(
-        NewRunnableMethod("mozilla::MediaEncoder::NotifyInitialized",
-                          mEncoder, &MediaEncoder::NotifyInitialized));
-    MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
+    mEncoderThread->Dispatch(
+      NewRunnableMethod("mozilla::MediaEncoder::NotifyInitialized",
+                        mEncoder, &MediaEncoder::NotifyInitialized));
   }
 
   void DataAvailable(TrackEncoder* aTrackEncoder) override
   {
     MOZ_ASSERT(mEncoderThread->IsCurrentThreadIn());
     MOZ_ASSERT(aTrackEncoder->IsInitialized());
 
     if (!mEncoder) {
       return;
     }
 
     if (mPendingDataAvailable) {
       return;
     }
 
-    nsresult rv =
-      mEncoderThread->Dispatch(
-        NewRunnableMethod("mozilla::MediaEncoder::EncoderListener::DataAvailableImpl",
-                          this, &EncoderListener::DataAvailableImpl));
-    MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
+    mEncoderThread->Dispatch(
+      NewRunnableMethod("mozilla::MediaEncoder::EncoderListener::DataAvailableImpl",
+                        this, &EncoderListener::DataAvailableImpl));
 
     mPendingDataAvailable = true;
   }
 
   void DataAvailableImpl()
   {
     MOZ_ASSERT(mEncoderThread->IsCurrentThreadIn());
 
@@ -414,21 +385,19 @@ public:
   void Error(TrackEncoder* aTrackEncoder) override
   {
     MOZ_ASSERT(mEncoderThread->IsCurrentThreadIn());
 
     if (!mEncoder) {
       return;
     }
 
-    nsresult rv =
-      mEncoderThread->Dispatch(
-        NewRunnableMethod("mozilla::MediaEncoder::SetError",
-                          mEncoder, &MediaEncoder::SetError));
-    MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
+    mEncoderThread->Dispatch(
+      NewRunnableMethod("mozilla::MediaEncoder::SetError",
+                        mEncoder, &MediaEncoder::SetError));
   }
 
 protected:
   RefPtr<TaskQueue> mEncoderThread;
   RefPtr<MediaEncoder> mEncoder;
   bool mPendingDataAvailable;
 };
 
@@ -449,76 +418,66 @@ MediaEncoder::MediaEncoder(TaskQueue* aE
   , mCompleted(false)
   , mError(false)
   , mCanceled(false)
   , mShutdown(false)
 {
   if (mAudioEncoder) {
     mAudioListener =
       MakeAndAddRef<AudioTrackListener>(mAudioEncoder, mEncoderThread);
-    nsresult rv =
-      mEncoderThread->Dispatch(
-        NewRunnableMethod<RefPtr<EncoderListener>>(
-          "mozilla::AudioTrackEncoder::RegisterListener",
-          mAudioEncoder, &AudioTrackEncoder::RegisterListener,
-          mEncoderListener));
-    MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
+    mEncoderThread->Dispatch(
+      NewRunnableMethod<RefPtr<EncoderListener>>(
+        "mozilla::AudioTrackEncoder::RegisterListener",
+        mAudioEncoder, &AudioTrackEncoder::RegisterListener, mEncoderListener));
   }
   if (mVideoEncoder) {
     mVideoListener =
       MakeAndAddRef<VideoTrackListener>(mVideoEncoder, mEncoderThread);
-    nsresult rv =
-      mEncoderThread->Dispatch(
-        NewRunnableMethod<RefPtr<EncoderListener>>(
-          "mozilla::VideoTrackEncoder::RegisterListener",
-          mVideoEncoder, &VideoTrackEncoder::RegisterListener,
-          mEncoderListener));
-    MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
+    mEncoderThread->Dispatch(
+      NewRunnableMethod<RefPtr<EncoderListener>>(
+        "mozilla::VideoTrackEncoder::RegisterListener",
+        mVideoEncoder, &VideoTrackEncoder::RegisterListener, mEncoderListener));
   }
 }
 
 MediaEncoder::~MediaEncoder()
 {
   MOZ_ASSERT(mListeners.IsEmpty());
 }
 
 void
 MediaEncoder::Suspend(TimeStamp aTime)
 {
   auto& ae = mAudioEncoder;
   auto& ve = mVideoEncoder;
-  nsresult rv =
-    mEncoderThread->Dispatch(NewRunnableFrom([ae, ve, aTime]() {
-      if (ae) {
-        ae->Suspend(aTime);
-      }
-      if (ve) {
-        ve->Suspend(aTime);
-      }
-      return NS_OK;
-    }));
-  MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
+  mEncoderThread->Dispatch(NewRunnableFrom([ae, ve, aTime]() {
+    if (ae) {
+      ae->Suspend(aTime);
+    }
+    if (ve) {
+      ve->Suspend(aTime);
+    }
+    return NS_OK;
+  }));
 }
 
 void
 MediaEncoder::Resume(TimeStamp aTime)
 {
   auto& ae = mAudioEncoder;
   auto& ve = mVideoEncoder;
-  nsresult rv =
-    mEncoderThread->Dispatch(NewRunnableFrom([ae, ve, aTime]() {
-      if (ae) {
-        ae->Resume(aTime);
-      }
-      if (ve) {
-        ve->Resume(aTime);
-      }
-      return NS_OK;
-    }));
-  MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
+  mEncoderThread->Dispatch(NewRunnableFrom([ae, ve, aTime]() {
+    if (ae) {
+      ae->Resume(aTime);
+    }
+    if (ve) {
+      ve->Resume(aTime);
+    }
+    return NS_OK;
+  }));
 }
 
 void
 MediaEncoder::ConnectAudioNode(AudioNode* aNode, uint32_t aOutput)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   if (mAudioNode) {
@@ -873,21 +832,19 @@ MediaEncoder::Shutdown()
     // Shutting down after being canceled. We cannot use the encoder thread.
     return;
   }
 
   auto listeners(mListeners);
   for (auto& l : listeners) {
     // We dispatch here since this method is typically called from
     // a DataAvailable() handler.
-    nsresult rv =
-      mEncoderThread->Dispatch(
-        NewRunnableMethod("mozilla::MediaEncoderListener::Shutdown",
-                          l, &MediaEncoderListener::Shutdown));
-    MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
+    mEncoderThread->Dispatch(
+      NewRunnableMethod("mozilla::MediaEncoderListener::Shutdown",
+                        l, &MediaEncoderListener::Shutdown));
   }
 }
 
 nsresult
 MediaEncoder::WriteEncodedDataToMuxer(TrackEncoder *aTrackEncoder)
 {
   AUTO_PROFILER_LABEL("MediaEncoder::WriteEncodedDataToMuxer", OTHER);
 
@@ -955,30 +912,28 @@ MediaEncoder::IsShutdown()
 }
 
 void
 MediaEncoder::Cancel()
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   RefPtr<MediaEncoder> self = this;
-  nsresult rv =
-    mEncoderThread->Dispatch(NewRunnableFrom([self]() mutable {
-      self->mCanceled = true;
+  mEncoderThread->Dispatch(NewRunnableFrom([self]() mutable {
+    self->mCanceled = true;
 
-      if (self->mAudioEncoder) {
-        self->mAudioEncoder->Cancel();
-      }
-      if (self->mVideoEncoder) {
-        self->mVideoEncoder->Cancel();
-      }
-      self->Shutdown();
-      return NS_OK;
-    }));
-  MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
+    if (self->mAudioEncoder) {
+      self->mAudioEncoder->Cancel();
+    }
+    if (self->mVideoEncoder) {
+      self->mVideoEncoder->Cancel();
+    }
+    self->Shutdown();
+    return NS_OK;
+  }));
 }
 
 bool
 MediaEncoder::HasError()
 {
   MOZ_ASSERT(mEncoderThread->IsCurrentThreadIn());
   return mError;
 }
--- a/dom/media/gtest/TestMP4Demuxer.cpp
+++ b/dom/media/gtest/TestMP4Demuxer.cpp
@@ -5,17 +5,16 @@
 
 #include "gtest/gtest.h"
 #include "MP4Demuxer.h"
 #include "mozilla/MozPromise.h"
 #include "MediaDataDemuxer.h"
 #include "mozilla/SharedThreadPool.h"
 #include "mozilla/TaskQueue.h"
 #include "mozilla/ArrayUtils.h"
-#include "mozilla/Unused.h"
 #include "MockMediaResource.h"
 #include "VideoUtils.h"
 
 using namespace mozilla;
 using namespace mp4_demuxer;
 using media::TimeUnit;
 
 class AutoTaskQueue;
@@ -145,17 +144,17 @@ public:
 private:
 
   template<typename FunctionType>
   void
   DispatchTask(FunctionType aFun)
   {
     RefPtr<Runnable> r =
       NS_NewRunnableFunction("MP4DemuxerBinding::DispatchTask", aFun);
-    Unused << mTaskQueue->Dispatch(r.forget());
+    mTaskQueue->Dispatch(r.forget());
   }
 
   virtual ~MP4DemuxerBinding()
   {
   }
 };
 
 TEST(MP4Demuxer, Seek)
--- a/dom/media/mediasource/AutoTaskQueue.h
+++ b/dom/media/mediasource/AutoTaskQueue.h
@@ -31,21 +31,21 @@ public:
   , mTaskQueue(new TaskQueue(Move(aPool), aName, aSupportsTailDispatch))
   {}
 
   TaskDispatcher& TailDispatcher() override
   {
     return mTaskQueue->TailDispatcher();
   }
 
-  MOZ_MUST_USE nsresult
-  Dispatch(already_AddRefed<nsIRunnable> aRunnable,
-           DispatchReason aReason = NormalDispatch) override
+  nsresult Dispatch(already_AddRefed<nsIRunnable> aRunnable,
+                    DispatchFailureHandling aFailureHandling = AssertDispatchSuccess,
+                    DispatchReason aReason = NormalDispatch) override
   {
-    return mTaskQueue->Dispatch(Move(aRunnable), aReason);
+    return mTaskQueue->Dispatch(Move(aRunnable), aFailureHandling, aReason);
   }
 
   // Prevent a GCC warning about the other overload of Dispatch being hidden.
   using AbstractThread::Dispatch;
 
   // Blocks until all tasks finish executing.
   void AwaitIdle() { mTaskQueue->AwaitIdle(); }
 
--- a/dom/media/mediasource/MediaSourceDemuxer.cpp
+++ b/dom/media/mediasource/MediaSourceDemuxer.cpp
@@ -59,34 +59,32 @@ MediaSourceDemuxer::AddSizeOfResources(
   RefPtr<MediaSourceDecoder::ResourceSizes> sizes = aSizes;
   nsCOMPtr<nsIRunnable> task = NS_NewRunnableFunction(
     "MediaSourceDemuxer::AddSizeOfResources", [self, sizes]() {
       for (const RefPtr<TrackBuffersManager>& manager : self->mSourceBuffers) {
         manager->AddSizeOfResources(sizes);
       }
     });
 
-  nsresult rv = GetTaskQueue()->Dispatch(task.forget());
-  MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
+  GetTaskQueue()->Dispatch(task.forget());
 }
 
 void MediaSourceDemuxer::NotifyInitDataArrived()
 {
   RefPtr<MediaSourceDemuxer> self = this;
   nsCOMPtr<nsIRunnable> task = NS_NewRunnableFunction(
     "MediaSourceDemuxer::NotifyInitDataArrived", [self]() {
       if (self->mInitPromise.IsEmpty()) {
         return;
       }
       if (self->ScanSourceBuffersForContent()) {
         self->mInitPromise.ResolveIfExists(NS_OK, __func__);
       }
     });
-  nsresult rv = GetTaskQueue()->Dispatch(task.forget());
-  MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
+  GetTaskQueue()->Dispatch(task.forget());
 }
 
 bool
 MediaSourceDemuxer::ScanSourceBuffersForContent()
 {
   MOZ_ASSERT(OnTaskQueue());
 
   if (mSourceBuffers.IsEmpty()) {
@@ -167,18 +165,17 @@ void
 MediaSourceDemuxer::AttachSourceBuffer(
   RefPtr<TrackBuffersManager>& aSourceBuffer)
 {
   nsCOMPtr<nsIRunnable> task = NewRunnableMethod<RefPtr<TrackBuffersManager>&&>(
     "MediaSourceDemuxer::DoAttachSourceBuffer",
     this,
     &MediaSourceDemuxer::DoAttachSourceBuffer,
     aSourceBuffer);
-  nsresult rv = GetTaskQueue()->Dispatch(task.forget());
-  MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
+  GetTaskQueue()->Dispatch(task.forget());
 }
 
 void
 MediaSourceDemuxer::DoAttachSourceBuffer(
   RefPtr<mozilla::TrackBuffersManager>&& aSourceBuffer)
 {
   MOZ_ASSERT(OnTaskQueue());
   mSourceBuffers.AppendElement(Move(aSourceBuffer));
@@ -189,18 +186,17 @@ void
 MediaSourceDemuxer::DetachSourceBuffer(
   RefPtr<TrackBuffersManager>& aSourceBuffer)
 {
   nsCOMPtr<nsIRunnable> task = NewRunnableMethod<RefPtr<TrackBuffersManager>&&>(
     "MediaSourceDemuxer::DoDetachSourceBuffer",
     this,
     &MediaSourceDemuxer::DoDetachSourceBuffer,
     aSourceBuffer);
-  nsresult rv = GetTaskQueue()->Dispatch(task.forget());
-  MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
+  GetTaskQueue()->Dispatch(task.forget());
 }
 
 void
 MediaSourceDemuxer::DoDetachSourceBuffer(
   RefPtr<TrackBuffersManager>&& aSourceBuffer)
 {
   MOZ_ASSERT(OnTaskQueue());
   mSourceBuffers.RemoveElementsBy(
@@ -363,18 +359,17 @@ MediaSourceTrackDemuxer::Reset()
       MOZ_ASSERT(self->OnTaskQueue());
       self->mManager->Seek(self->mType, TimeUnit::Zero(), TimeUnit::Zero());
       {
         MonitorAutoLock mon(self->mMonitor);
         self->mNextRandomAccessPoint = self->mManager->GetNextRandomAccessPoint(
           self->mType, MediaSourceDemuxer::EOS_FUZZ);
       }
     });
-  nsresult rv = mParent->GetTaskQueue()->Dispatch(task.forget());
-  MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
+  mParent->GetTaskQueue()->Dispatch(task.forget());
 }
 
 nsresult
 MediaSourceTrackDemuxer::GetNextRandomAccessPoint(TimeUnit* aTime)
 {
   MonitorAutoLock mon(mMonitor);
   *aTime = mNextRandomAccessPoint;
   return NS_OK;
@@ -404,18 +399,17 @@ void
 MediaSourceTrackDemuxer::BreakCycles()
 {
   RefPtr<MediaSourceTrackDemuxer> self = this;
   nsCOMPtr<nsIRunnable> task =
     NS_NewRunnableFunction("MediaSourceTrackDemuxer::BreakCycles", [self]() {
       self->DetachManager();
       self->mParent = nullptr;
     });
-  nsresult rv = mParent->GetTaskQueue()->Dispatch(task.forget());
-  MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
+  mParent->GetTaskQueue()->Dispatch(task.forget());
 }
 
 RefPtr<MediaSourceTrackDemuxer::SeekPromise>
 MediaSourceTrackDemuxer::DoSeek(const TimeUnit& aTime)
 {
   if (!mManager) {
     return SeekPromise::CreateAndReject(
       MediaResult(NS_ERROR_DOM_MEDIA_FATAL_ERR,
--- a/dom/media/mediasource/TrackBuffersManager.cpp
+++ b/dom/media/mediasource/TrackBuffersManager.cpp
@@ -160,23 +160,21 @@ TrackBuffersManager::QueueTask(SourceBuf
     MOZ_ASSERT(aTask->GetType() == SourceBufferTask::Type::Detach,
                "only detach task could happen here!");
     MSE_DEBUG("Could not queue the task '%s' without task queue",
               aTask->GetTypeName());
     return;
   }
 
   if (!taskQueue->IsCurrentThreadIn()) {
-    nsresult rv =
-        taskQueue->Dispatch(NewRunnableMethod<RefPtr<SourceBufferTask>>(
-        "TrackBuffersManager::QueueTask",
-        this,
-        &TrackBuffersManager::QueueTask,
-        aTask));
-    MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
+    taskQueue->Dispatch(NewRunnableMethod<RefPtr<SourceBufferTask>>(
+      "TrackBuffersManager::QueueTask",
+      this,
+      &TrackBuffersManager::QueueTask,
+      aTask));
     return;
   }
   mQueue.Push(aTask);
   ProcessTasks();
 }
 
 void
 TrackBuffersManager::ProcessTasks()
--- a/dom/media/platforms/android/RemoteDataDecoder.cpp
+++ b/dom/media/platforms/android/RemoteDataDecoder.cpp
@@ -633,24 +633,22 @@ RemoteDataDecoder::Decode(MediaRawData* 
 
   });
 }
 
 void
 RemoteDataDecoder::UpdateInputStatus(int64_t aTimestamp, bool aProcessed)
 {
   if (!mTaskQueue->IsCurrentThreadIn()) {
-    nsresult rv =
-      mTaskQueue->Dispatch(
-        NewRunnableMethod<int64_t, bool>("RemoteDataDecoder::UpdateInputStatus",
-                                         this,
-                                         &RemoteDataDecoder::UpdateInputStatus,
-                                         aTimestamp,
-                                         aProcessed));
-    MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
+    mTaskQueue->Dispatch(
+      NewRunnableMethod<int64_t, bool>("RemoteDataDecoder::UpdateInputStatus",
+                                       this,
+                                       &RemoteDataDecoder::UpdateInputStatus,
+                                       aTimestamp,
+                                       aProcessed));
     return;
   }
   AssertOnTaskQueue();
   if (mShutdown) {
     return;
   }
 
   if (!aProcessed) {
@@ -664,23 +662,21 @@ RemoteDataDecoder::UpdateInputStatus(int
     ReturnDecodedData();
   }
 }
 
 void
 RemoteDataDecoder::UpdateOutputStatus(RefPtr<MediaData>&& aSample)
 {
   if (!mTaskQueue->IsCurrentThreadIn()) {
-    nsresult rv =
-      mTaskQueue->Dispatch(
-        NewRunnableMethod<const RefPtr<MediaData>>("RemoteDataDecoder::UpdateOutputStatus",
-                                                   this,
-                                                   &RemoteDataDecoder::UpdateOutputStatus,
-                                                   Move(aSample)));
-    MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
+    mTaskQueue->Dispatch(
+      NewRunnableMethod<const RefPtr<MediaData>>("RemoteDataDecoder::UpdateOutputStatus",
+                                                 this,
+                                                 &RemoteDataDecoder::UpdateOutputStatus,
+                                                 Move(aSample)));
     return;
   }
   AssertOnTaskQueue();
   if (mShutdown) {
     return;
   }
   if (IsUsefulData(aSample)) {
     mDecodedData.AppendElement(Move(aSample));
@@ -704,43 +700,38 @@ RemoteDataDecoder::ReturnDecodedData()
     mDecodedData.Clear();
   }
 }
 
 void
 RemoteDataDecoder::DrainComplete()
 {
   if (!mTaskQueue->IsCurrentThreadIn()) {
-    nsresult rv =
-      mTaskQueue->Dispatch(
-        NewRunnableMethod("RemoteDataDecoder::DrainComplete",
-                          this, &RemoteDataDecoder::DrainComplete));
-    MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
+    mTaskQueue->Dispatch(
+      NewRunnableMethod("RemoteDataDecoder::DrainComplete",
+                        this, &RemoteDataDecoder::DrainComplete));
     return;
   }
   AssertOnTaskQueue();
   if (mShutdown) {
     return;
   }
   mDrainStatus = DrainStatus::DRAINED;
   ReturnDecodedData();
   // Make decoder accept input again.
   mJavaDecoder->Flush();
 }
 
 void
 RemoteDataDecoder::Error(const MediaResult& aError)
 {
   if (!mTaskQueue->IsCurrentThreadIn()) {
-    nsresult rv =
-      mTaskQueue->Dispatch(
-        NewRunnableMethod<MediaResult>("RemoteDataDecoder::Error",
-                                       this, &RemoteDataDecoder::Error,
-                                       aError));
-    MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
+    mTaskQueue->Dispatch(
+      NewRunnableMethod<MediaResult>("RemoteDataDecoder::Error",
+                                     this, &RemoteDataDecoder::Error, aError));
     return;
   }
   AssertOnTaskQueue();
   if (mShutdown) {
     return;
   }
   mDecodePromise.RejectIfExists(aError, __func__);
   mDrainPromise.RejectIfExists(aError, __func__);
--- a/dom/media/platforms/omx/OmxDataDecoder.cpp
+++ b/dom/media/platforms/omx/OmxDataDecoder.cpp
@@ -391,18 +391,17 @@ OmxDataDecoder::EmptyBufferDone(BufferDa
         if (mMediaRawDatas.Length()) {
           return;
         }
 
         mDecodePromise.ResolveIfExists(mDecodedData, __func__);
         mDecodedData.Clear();
       });
 
-    nsresult rv = mOmxTaskQueue->Dispatch(r.forget());
-    MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
+    mOmxTaskQueue->Dispatch(r.forget());
   }
 }
 
 void
 OmxDataDecoder::EmptyBufferFailure(OmxBufferFailureHolder aFailureHolder)
 {
   NotifyError(aFailureHolder.mError, __func__);
 }
--- a/dom/media/webaudio/MediaBufferDecoder.cpp
+++ b/dom/media/webaudio/MediaBufferDecoder.cpp
@@ -505,18 +505,17 @@ AsyncDecodeWebAudio(const char* aContent
                            WebAudioDecodeJob::UnknownError);
     aDecodeJob.mContext->Dispatch(event.forget());
   } else {
     // If we did this without a temporary:
     //   task->Reader()->OwnerThread()->Dispatch(task.forget())
     // we might evaluate the task.forget() before calling Reader(). Enforce
     // a non-crashy order-of-operations.
     TaskQueue* taskQueue = task->Reader()->OwnerThread();
-    nsresult rv = taskQueue->Dispatch(task.forget());
-    MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
+    taskQueue->Dispatch(task.forget());
   }
 }
 
 WebAudioDecodeJob::WebAudioDecodeJob(AudioContext* aContext,
                                      Promise* aPromise,
                                      DecodeSuccessCallback* aSuccessCallback,
                                      DecodeErrorCallback* aFailureCallback)
   : mContext(aContext)
--- a/media/webrtc/signaling/src/mediapipeline/MediaPipeline.cpp
+++ b/media/webrtc/signaling/src/mediapipeline/MediaPipeline.cpp
@@ -202,18 +202,17 @@ public:
 
     ++mLength; // Atomic
 
     nsCOMPtr<nsIRunnable> runnable =
       NewRunnableMethod<StoreRefPtrPassByPtr<Image>, bool>(
         "VideoFrameConverter::ProcessVideoFrame",
         this, &VideoFrameConverter::ProcessVideoFrame,
         aChunk.mFrame.GetImage(), forceBlack);
-    nsresult rv = mTaskQueue->Dispatch(runnable.forget());
-    MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
+    mTaskQueue->Dispatch(runnable.forget());
   }
 
   void AddListener(VideoConverterListener* aListener)
   {
     MutexAutoLock lock(mMutex);
 
     MOZ_ASSERT(!mListeners.Contains(aListener));
     mListeners.AppendElement(aListener);
--- a/netwerk/base/nsNetUtil.cpp
+++ b/netwerk/base/nsNetUtil.cpp
@@ -1543,17 +1543,18 @@ private:
             return NS_ERROR_FAILURE;
         }
 
         mTaskQueue = new TaskQueue(target.forget());
 
         MonitorAutoLock lock(mMonitor);
 
         nsCOMPtr<nsIRunnable> runnable = this;
-        nsresult rv = mTaskQueue->Dispatch(runnable.forget());
+        nsresult rv = mTaskQueue->Dispatch(runnable.forget(),
+                                           AbstractThread::DontAssertDispatchSuccess);
         NS_ENSURE_SUCCESS(rv, rv);
 
         lock.Wait();
 
         return mAsyncResult;
     }
 
     // This method runs on the I/O Thread when the owning thread is blocked by
@@ -1594,17 +1595,18 @@ private:
         if (NS_SUCCEEDED(rv)) {
             mWrittenData += writtenData;
             if (mCount != -1) {
                 MOZ_ASSERT(mCount >= writtenData);
                 mCount -= writtenData;
             }
 
             nsCOMPtr<nsIRunnable> runnable = this;
-            rv = mTaskQueue->Dispatch(runnable.forget());
+            rv = mTaskQueue->Dispatch(runnable.forget(),
+                                      AbstractThread::DontAssertDispatchSuccess);
             if (NS_WARN_IF(NS_FAILED(rv))) {
                 OperationCompleted(rv);
             }
         
             return NS_OK;
         }
 
         // Async wait...
--- a/xpcom/tests/gtest/TestMozPromise.cpp
+++ b/xpcom/tests/gtest/TestMozPromise.cpp
@@ -4,17 +4,16 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "gtest/gtest.h"
 
 #include "base/message_loop.h"
 
 #include "mozilla/TaskQueue.h"
 #include "mozilla/MozPromise.h"
-#include "mozilla/Unused.h"
 
 #include "nsISupportsImpl.h"
 #include "mozilla/SharedThreadPool.h"
 #include "VideoUtils.h"
 
 using namespace mozilla;
 
 typedef MozPromise<int, double, false> TestPromise;
@@ -56,21 +55,22 @@ public:
     MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn());
     if (!mPromise) {
       // Canceled.
       return NS_OK;
     }
 
     if (--mIterations == 0) {
       mPromise->ResolveOrReject(mValue, __func__);
-      return NS_OK;
+    } else {
+      nsCOMPtr<nsIRunnable> r = this;
+      mTaskQueue->Dispatch(r.forget());
     }
 
-    nsCOMPtr<nsIRunnable> r = this;
-    return mTaskQueue->Dispatch(r.forget());
+    return NS_OK;
   }
 
   void Cancel() {
     mPromise = nullptr;
   }
 
 protected:
   ~DelayedResolveOrReject() {}
@@ -82,17 +82,17 @@ private:
   int mIterations;
 };
 
 template<typename FunctionType>
 void
 RunOnTaskQueue(TaskQueue* aQueue, FunctionType aFun)
 {
   nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction("RunOnTaskQueue", aFun);
-  Unused << aQueue->Dispatch(r.forget());
+  aQueue->Dispatch(r.forget());
 }
 
 // std::function can't come soon enough. :-(
 #define DO_FAIL []() { EXPECT_TRUE(false); return TestPromise::CreateAndReject(0, __func__); }
 
 TEST(MozPromise, BasicResolve)
 {
   AutoTaskQueue atq;
@@ -157,21 +157,21 @@ TEST(MozPromise, AsyncResolve)
     RefPtr<TestPromise::Private> p = new TestPromise::Private(__func__);
 
     // Kick off three racing tasks, and make sure we get the one that finishes earliest.
     RefPtr<DelayedResolveOrReject> a = new DelayedResolveOrReject(queue, p, RRValue::MakeResolve(32), 10);
     RefPtr<DelayedResolveOrReject> b = new DelayedResolveOrReject(queue, p, RRValue::MakeResolve(42), 5);
     RefPtr<DelayedResolveOrReject> c = new DelayedResolveOrReject(queue, p, RRValue::MakeReject(32.0), 7);
 
     nsCOMPtr<nsIRunnable> ref = a.get();
-    Unused << queue->Dispatch(ref.forget());
+    queue->Dispatch(ref.forget());
     ref = b.get();
-    Unused << queue->Dispatch(ref.forget());
+    queue->Dispatch(ref.forget());
     ref = c.get();
-    Unused << queue->Dispatch(ref.forget());
+    queue->Dispatch(ref.forget());
 
     p->Then(queue, __func__, [queue, a, b, c] (int aResolveValue) -> void {
       EXPECT_EQ(aResolveValue, 42);
       a->Cancel();
       b->Cancel();
       c->Cancel();
       queue->BeginShutdown();
     }, DO_FAIL);
@@ -192,17 +192,17 @@ TEST(MozPromise, CompletionPromises)
            [&invokedPass] (int aVal) {
              invokedPass = true;
              return TestPromise::CreateAndResolve(aVal, __func__);
            }, DO_FAIL)
     ->Then(queue, __func__,
       [queue] (int aVal) -> RefPtr<TestPromise> {
         RefPtr<TestPromise::Private> p = new TestPromise::Private(__func__);
         nsCOMPtr<nsIRunnable> resolver = new DelayedResolveOrReject(queue, p, RRValue::MakeResolve(aVal - 8), 10);
-        Unused << queue->Dispatch(resolver.forget());
+        queue->Dispatch(resolver.forget());
         return RefPtr<TestPromise>(p);
       },
       DO_FAIL)
     ->Then(queue, __func__,
       [] (int aVal) -> RefPtr<TestPromise> { return TestPromise::CreateAndReject(double(aVal - 42) + 42.0, __func__); },
       DO_FAIL)
     ->Then(queue, __func__,
       DO_FAIL,
--- a/xpcom/tests/gtest/TestStateWatching.cpp
+++ b/xpcom/tests/gtest/TestStateWatching.cpp
@@ -3,17 +3,16 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "gtest/gtest.h"
 #include "mozilla/SharedThreadPool.h"
 #include "mozilla/StateWatching.h"
 #include "mozilla/TaskQueue.h"
-#include "mozilla/Unused.h"
 #include "nsISupportsImpl.h"
 #include "VideoUtils.h"
 
 namespace TestStateWatching {
 
 using namespace mozilla;
 
 struct Foo {
@@ -28,17 +27,17 @@ TEST(WatchManager, Shutdown)
 {
   RefPtr<TaskQueue> queue = new TaskQueue(
     GetMediaThreadPool(MediaThreadType::PLAYBACK));
 
   RefPtr<Foo> p = new Foo;
   WatchManager<Foo> manager(p, queue);
   Watchable<bool> notifier(false, "notifier");
 
-  Unused << queue->Dispatch(NS_NewRunnableFunction(
+  queue->Dispatch(NS_NewRunnableFunction(
     "TestStateWatching::WatchManager_Shutdown_Test::TestBody", [&]() {
       manager.Watch(notifier, &Foo::Notify);
       notifier = true;    // Trigger the call to Foo::Notify().
       manager.Shutdown(); // Shutdown() should cancel the call.
     }));
 
   queue->BeginShutdown();
   queue->AwaitShutdownAndIdle();
--- a/xpcom/tests/gtest/TestTaskQueue.cpp
+++ b/xpcom/tests/gtest/TestTaskQueue.cpp
@@ -2,17 +2,16 @@
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "gtest/gtest.h"
 #include "mozilla/SharedThreadPool.h"
 #include "mozilla/TaskQueue.h"
-#include "mozilla/Unused.h"
 #include "VideoUtils.h"
 
 namespace TestTaskQueue {
 
 using namespace mozilla;
 
 TEST(TaskQueue, EventOrder)
 {
@@ -25,47 +24,48 @@ TEST(TaskQueue, EventOrder)
 
   bool errored = false;
   int counter = 0;
   int sync = 0;
   Monitor monitor("TaskQueue::EventOrder::monitor");
 
   // We expect task1 happens before task3.
   for (int i = 0; i < 10000; ++i) {
-    Unused << tq1->Dispatch(
+    tq1->Dispatch(
       NS_NewRunnableFunction(
         "TestTaskQueue::TaskQueue_EventOrder_Test::TestBody",
         [&]() {
-          Unused << tq2->Dispatch(NS_NewRunnableFunction(
+          tq2->Dispatch(NS_NewRunnableFunction(
             "TestTaskQueue::TaskQueue_EventOrder_Test::TestBody",
             []() { // task0
             }));
-          Unused << tq3->Dispatch(NS_NewRunnableFunction(
+          tq3->Dispatch(NS_NewRunnableFunction(
             "TestTaskQueue::TaskQueue_EventOrder_Test::TestBody",
             [&]() { // task1
               EXPECT_EQ(1, ++counter);
               errored = counter != 1;
               MonitorAutoLock mon(monitor);
               ++sync;
               mon.Notify();
             }));
-          Unused << tq2->Dispatch(NS_NewRunnableFunction(
+          tq2->Dispatch(NS_NewRunnableFunction(
             "TestTaskQueue::TaskQueue_EventOrder_Test::TestBody",
             [&]() { // task2
-              Unused << tq3->Dispatch(NS_NewRunnableFunction(
+              tq3->Dispatch(NS_NewRunnableFunction(
                 "TestTaskQueue::TaskQueue_EventOrder_Test::TestBody",
                 [&]() { // task3
                   EXPECT_EQ(0, --counter);
                   errored = counter != 0;
                   MonitorAutoLock mon(monitor);
                   ++sync;
                   mon.Notify();
                 }));
             }));
         }),
+      AbstractThread::AssertDispatchSuccess,
       AbstractThread::TailDispatch);
 
     // Ensure task1 and task3 are done before next loop.
     MonitorAutoLock mon(monitor);
     while (sync != 2) {
       mon.Wait();
     }
     sync = 0;
--- a/xpcom/threads/AbstractThread.cpp
+++ b/xpcom/threads/AbstractThread.cpp
@@ -42,25 +42,29 @@ public:
     //
     // If you need to use tail dispatch on other XPCOM threads, you'll need to
     // implement an nsIThreadObserver to fire the tail dispatcher at the
     // appropriate times. You will also need to modify this assertion.
     MOZ_ASSERT_IF(aRequireTailDispatch, NS_IsMainThread() && aTarget->IsOnCurrentThread());
   }
 
   virtual nsresult Dispatch(already_AddRefed<nsIRunnable> aRunnable,
+                            DispatchFailureHandling aFailureHandling = AssertDispatchSuccess,
                             DispatchReason aReason = NormalDispatch) override
   {
     AbstractThread* currentThread;
     if (aReason != TailDispatch && (currentThread = GetCurrent()) && RequiresTailDispatch(currentThread)) {
-      return currentThread->TailDispatcher().AddTask(this, Move(aRunnable));
+      currentThread->TailDispatcher().AddTask(this, Move(aRunnable), aFailureHandling);
+      return NS_OK;
     }
 
     RefPtr<nsIRunnable> runner(new Runner(this, Move(aRunnable), false /* already drained by TaskGroupRunnable  */));
-    return mTarget->Dispatch(runner.forget(), NS_DISPATCH_NORMAL);
+    nsresult rv = mTarget->Dispatch(runner.forget(), NS_DISPATCH_NORMAL);
+    MOZ_DIAGNOSTIC_ASSERT(aFailureHandling == DontAssertDispatchSuccess || NS_SUCCEEDED(rv));
+    return rv;
   }
 
   // Prevent a GCC warning about the other overload of Dispatch being hidden.
   using AbstractThread::Dispatch;
 
   virtual bool IsCurrentThreadIn() override
   {
     return mTarget->IsOnCurrentThread();
@@ -214,34 +218,33 @@ AbstractThread::DispatchFromScript(nsIRu
 {
   nsCOMPtr<nsIRunnable> event(aEvent);
   return Dispatch(event.forget(), aFlags);
 }
 
 NS_IMETHODIMP
 AbstractThread::Dispatch(already_AddRefed<nsIRunnable> aEvent, uint32_t aFlags)
 {
-  return Dispatch(Move(aEvent), NormalDispatch);
+  Dispatch(Move(aEvent), DontAssertDispatchSuccess, NormalDispatch);
+  return NS_OK;
 }
 
 NS_IMETHODIMP
 AbstractThread::DelayedDispatch(already_AddRefed<nsIRunnable> aEvent,
                                  uint32_t aDelayMs)
 {
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
-nsresult
+void
 AbstractThread::TailDispatchTasksFor(AbstractThread* aThread)
 {
   if (MightHaveTailTasks()) {
-    return TailDispatcher().DispatchTasksFor(aThread);
+    TailDispatcher().DispatchTasksFor(aThread);
   }
-
-  return NS_OK;
 }
 
 bool
 AbstractThread::HasTailTasksFor(AbstractThread* aThread)
 {
   if (!MightHaveTailTasks()) {
     return false;
   }
--- a/xpcom/threads/AbstractThread.h
+++ b/xpcom/threads/AbstractThread.h
@@ -62,18 +62,20 @@ public:
   // |flags| parameter from Dispatch. Otherwise, a single-argument Dispatch call
   // would be ambiguous.
   NS_IMETHOD_(bool) IsOnCurrentThreadInfallible(void) override;
   NS_IMETHOD IsOnCurrentThread(bool *_retval) override;
   NS_IMETHOD Dispatch(already_AddRefed<nsIRunnable> event, uint32_t flags) override;
   NS_IMETHOD DispatchFromScript(nsIRunnable *event, uint32_t flags) override;
   NS_IMETHOD DelayedDispatch(already_AddRefed<nsIRunnable> event, uint32_t delay) override;
 
+  enum DispatchFailureHandling { AssertDispatchSuccess, DontAssertDispatchSuccess };
   enum DispatchReason { NormalDispatch, TailDispatch };
   virtual nsresult Dispatch(already_AddRefed<nsIRunnable> aRunnable,
+                            DispatchFailureHandling aHandling = AssertDispatchSuccess,
                             DispatchReason aReason = NormalDispatch) = 0;
 
   virtual bool IsCurrentThreadIn() = 0;
 
   // Returns a TaskDispatcher that will dispatch its tasks when the currently-
   // running tasks pops off the stack.
   //
   // May only be called when running within the it is invoked up, and only on
@@ -82,17 +84,17 @@ public:
 
   // Returns true if we have tail tasks scheduled, or if this isn't known.
   // Returns false if we definitely don't have any tail tasks.
   virtual bool MightHaveTailTasks() { return true; }
 
   // Helper functions for methods on the tail TasklDispatcher. These check
   // HasTailTasks to avoid allocating a TailDispatcher if it isn't
   // needed.
-  nsresult TailDispatchTasksFor(AbstractThread* aThread);
+  void TailDispatchTasksFor(AbstractThread* aThread);
   bool HasTailTasksFor(AbstractThread* aThread);
 
   // Returns true if this supports the tail dispatcher.
   bool SupportsTailDispatch() const { return mSupportsTailDispatch; }
 
   // Returns true if this thread requires all dispatches originating from
   // aThread go through the tail dispatcher.
   bool RequiresTailDispatch(AbstractThread* aThread) const;
--- a/xpcom/threads/StateMirroring.h
+++ b/xpcom/threads/StateMirroring.h
@@ -150,17 +150,18 @@ private:
 
     void DisconnectAll()
     {
       MIRROR_LOG("%s [%p] Disconnecting all mirrors", mName, this);
       for (size_t i = 0; i < mMirrors.Length(); ++i) {
         mMirrors[i]->OwnerThread()->Dispatch(
           NewRunnableMethod("AbstractMirror::NotifyDisconnected",
                             mMirrors[i],
-                            &AbstractMirror<T>::NotifyDisconnected));
+                            &AbstractMirror<T>::NotifyDisconnected),
+          AbstractThread::DontAssertDispatchSuccess);
       }
       mMirrors.Clear();
     }
 
     operator const T&()
     {
       MOZ_ASSERT(OwnerThread()->IsCurrentThreadIn());
       return mValue;
@@ -332,17 +333,17 @@ private:
       MOZ_ASSERT(OwnerThread()->RequiresTailDispatch(aCanonical->OwnerThread()), "Can't get coherency without tail dispatch");
 
       nsCOMPtr<nsIRunnable> r =
         NewRunnableMethod<StoreRefPtrPassByPtr<AbstractMirror<T>>>(
           "AbstractCanonical::AddMirror",
           aCanonical,
           &AbstractCanonical<T>::AddMirror,
           this);
-      aCanonical->OwnerThread()->Dispatch(r.forget());
+      aCanonical->OwnerThread()->Dispatch(r.forget(), AbstractThread::DontAssertDispatchSuccess);
       mCanonical = aCanonical;
     }
   public:
 
     void DisconnectIfConnected()
     {
       MOZ_ASSERT(OwnerThread()->IsCurrentThreadIn());
       if (!IsConnected()) {
@@ -351,17 +352,17 @@ private:
 
       MIRROR_LOG("%s [%p] Disconnecting from %p", mName, this, mCanonical.get());
       nsCOMPtr<nsIRunnable> r =
         NewRunnableMethod<StoreRefPtrPassByPtr<AbstractMirror<T>>>(
           "AbstractCanonical::RemoveMirror",
           mCanonical,
           &AbstractCanonical<T>::RemoveMirror,
           this);
-      mCanonical->OwnerThread()->Dispatch(r.forget());
+      mCanonical->OwnerThread()->Dispatch(r.forget(), AbstractThread::DontAssertDispatchSuccess);
       mCanonical = nullptr;
     }
 
   protected:
     ~Impl() { MOZ_DIAGNOSTIC_ASSERT(!IsConnected()); }
 
   private:
     T mValue;
--- a/xpcom/threads/TaskDispatcher.h
+++ b/xpcom/threads/TaskDispatcher.h
@@ -49,20 +49,21 @@ public:
   // State change tasks are dispatched asynchronously always run before regular
   // tasks. They are intended to be used to update the value held by mirrors
   // before any other dispatched tasks are run on the target thread.
   virtual void AddStateChangeTask(AbstractThread* aThread,
                                   already_AddRefed<nsIRunnable> aRunnable) = 0;
 
   // Regular tasks are dispatched asynchronously, and run after state change
   // tasks.
-  virtual nsresult AddTask(AbstractThread* aThread,
-                           already_AddRefed<nsIRunnable> aRunnable) = 0;
+  virtual void AddTask(AbstractThread* aThread,
+                       already_AddRefed<nsIRunnable> aRunnable,
+                       AbstractThread::DispatchFailureHandling aFailureHandling = AbstractThread::AssertDispatchSuccess) = 0;
 
-  virtual nsresult DispatchTasksFor(AbstractThread* aThread) = 0;
+  virtual void DispatchTasksFor(AbstractThread* aThread) = 0;
   virtual bool HasTasksFor(AbstractThread* aThread) = 0;
   virtual void DrainDirectTasks() = 0;
 };
 
 /*
  * AutoTaskDispatcher is a stack-scoped TaskDispatcher implementation that fires
  * its queued tasks when it is popped off the stack.
  */
@@ -116,80 +117,74 @@ public:
   void AddStateChangeTask(AbstractThread* aThread,
                           already_AddRefed<nsIRunnable> aRunnable) override
   {
     nsCOMPtr<nsIRunnable> r = aRunnable;
     MOZ_RELEASE_ASSERT(r);
     EnsureTaskGroup(aThread).mStateChangeTasks.AppendElement(r.forget());
   }
 
-  nsresult AddTask(AbstractThread* aThread,
-                   already_AddRefed<nsIRunnable> aRunnable) override
+  void AddTask(AbstractThread* aThread,
+               already_AddRefed<nsIRunnable> aRunnable,
+               AbstractThread::DispatchFailureHandling aFailureHandling) override
   {
     nsCOMPtr<nsIRunnable> r = aRunnable;
     MOZ_RELEASE_ASSERT(r);
     // To preserve the event order, we need to append a new group if the last
     // group is not targeted for |aThread|.
     // See https://bugzilla.mozilla.org/show_bug.cgi?id=1318226&mark=0-3#c0
     // for the details of the issue.
     if (mTaskGroups.Length() == 0 || mTaskGroups.LastElement()->mThread != aThread) {
       mTaskGroups.AppendElement(new PerThreadTaskGroup(aThread));
     }
 
     PerThreadTaskGroup& group = *mTaskGroups.LastElement();
     group.mRegularTasks.AppendElement(r.forget());
 
-    return NS_OK;
+    // The task group needs to assert dispatch success if any of the runnables
+    // it's dispatching want to assert it.
+    if (aFailureHandling == AbstractThread::AssertDispatchSuccess) {
+      group.mFailureHandling = AbstractThread::AssertDispatchSuccess;
+    }
   }
 
   bool HasTasksFor(AbstractThread* aThread) override
   {
     return !!GetTaskGroup(aThread) ||
            (aThread == AbstractThread::GetCurrent() && HaveDirectTasks());
   }
 
-  nsresult DispatchTasksFor(AbstractThread* aThread) override
+  void DispatchTasksFor(AbstractThread* aThread) override
   {
-    nsresult rv = NS_OK;
-
     // Dispatch all groups that match |aThread|.
     for (size_t i = 0; i < mTaskGroups.Length(); ++i) {
       if (mTaskGroups[i]->mThread == aThread) {
-        nsresult rv2 = DispatchTaskGroup(Move(mTaskGroups[i]));
-
-        if (NS_WARN_IF(NS_FAILED(rv2)) && NS_SUCCEEDED(rv)) {
-          // We should try our best to call DispatchTaskGroup() as much as
-          // possible and return an error if any of DispatchTaskGroup() calls
-          // failed.
-          rv = rv2;
-        }
-
+        DispatchTaskGroup(Move(mTaskGroups[i]));
         mTaskGroups.RemoveElementAt(i--);
       }
     }
-
-    return rv;
   }
 
 private:
 
   struct PerThreadTaskGroup
   {
   public:
     explicit PerThreadTaskGroup(AbstractThread* aThread)
-      : mThread(aThread)
+      : mThread(aThread), mFailureHandling(AbstractThread::DontAssertDispatchSuccess)
     {
       MOZ_COUNT_CTOR(PerThreadTaskGroup);
     }
 
     ~PerThreadTaskGroup() { MOZ_COUNT_DTOR(PerThreadTaskGroup); }
 
     RefPtr<AbstractThread> mThread;
     nsTArray<nsCOMPtr<nsIRunnable>> mStateChangeTasks;
     nsTArray<nsCOMPtr<nsIRunnable>> mRegularTasks;
+    AbstractThread::DispatchFailureHandling mFailureHandling;
   };
 
   class TaskGroupRunnable : public Runnable
   {
     public:
       explicit TaskGroupRunnable(UniquePtr<PerThreadTaskGroup>&& aTasks)
         : Runnable("AutoTaskDispatcher::TaskGroupRunnable")
         , mTasks(Move(aTasks))
@@ -250,24 +245,25 @@ private:
         return mTaskGroups[i].get();
       }
     }
 
     // Not found.
     return nullptr;
   }
 
-  nsresult DispatchTaskGroup(UniquePtr<PerThreadTaskGroup> aGroup)
+  void DispatchTaskGroup(UniquePtr<PerThreadTaskGroup> aGroup)
   {
     RefPtr<AbstractThread> thread = aGroup->mThread;
 
+    AbstractThread::DispatchFailureHandling failureHandling = aGroup->mFailureHandling;
     AbstractThread::DispatchReason reason = mIsTailDispatcher ? AbstractThread::TailDispatch
                                                               : AbstractThread::NormalDispatch;
     nsCOMPtr<nsIRunnable> r = new TaskGroupRunnable(Move(aGroup));
-    return thread->Dispatch(r.forget(), reason);
+    thread->Dispatch(r.forget(), failureHandling, reason);
   }
 
   // Direct tasks. We use a Maybe<> because (a) this class is hot, (b)
   // mDirectTasks often doesn't get anything put into it, and (c) the
   // std::queue implementation in GNU libstdc++ does two largish heap
   // allocations when creating a new std::queue.
   mozilla::Maybe<std::queue<nsCOMPtr<nsIRunnable>>> mDirectTasks;
 
--- a/xpcom/threads/TaskQueue.cpp
+++ b/xpcom/threads/TaskQueue.cpp
@@ -34,16 +34,17 @@ public:
   }
 
   NS_IMETHOD
   Dispatch(already_AddRefed<nsIRunnable> aEvent, uint32_t aFlags) override
   {
     nsCOMPtr<nsIRunnable> runnable = aEvent;
     MonitorAutoLock mon(mTaskQueue->mQueueMonitor);
     return mTaskQueue->DispatchLocked(/* passed by ref */runnable,
+                                      DontAssertDispatchSuccess,
                                       NormalDispatch);
   }
 
   NS_IMETHOD
   DelayedDispatch(already_AddRefed<nsIRunnable>, uint32_t aFlags) override
   {
     return NS_ERROR_NOT_IMPLEMENTED;
   }
@@ -100,26 +101,28 @@ TaskQueue::TailDispatcher()
   MOZ_ASSERT(mTailDispatcher);
   return *mTailDispatcher;
 }
 
 // Note aRunnable is passed by ref to support conditional ownership transfer.
 // See Dispatch() in TaskQueue.h for more details.
 nsresult
 TaskQueue::DispatchLocked(nsCOMPtr<nsIRunnable>& aRunnable,
+                          DispatchFailureHandling aFailureHandling,
                           DispatchReason aReason)
 {
   mQueueMonitor.AssertCurrentThreadOwns();
   if (mIsShutdown) {
     return NS_ERROR_FAILURE;
   }
 
   AbstractThread* currentThread;
   if (aReason != TailDispatch && (currentThread = GetCurrent()) && RequiresTailDispatch(currentThread)) {
-    return currentThread->TailDispatcher().AddTask(this, aRunnable.forget());
+    currentThread->TailDispatcher().AddTask(this, aRunnable.forget(), aFailureHandling);
+    return NS_OK;
   }
 
   mTasks.push(aRunnable.forget());
   if (mIsRunning) {
     return NS_OK;
   }
   RefPtr<nsIRunnable> runner(new Runner(this));
   nsresult rv = mTarget->Dispatch(runner.forget(), NS_DISPATCH_NORMAL);
--- a/xpcom/threads/TaskQueue.h
+++ b/xpcom/threads/TaskQueue.h
@@ -56,24 +56,30 @@ public:
   TaskQueue(already_AddRefed<nsIEventTarget> aTarget,
             const char* aName,
             bool aSupportsTailDispatch = false);
 
   TaskDispatcher& TailDispatcher() override;
 
   TaskQueue* AsTaskQueue() override { return this; }
 
-  MOZ_MUST_USE nsresult
-  Dispatch(already_AddRefed<nsIRunnable> aRunnable,
-           DispatchReason aReason = NormalDispatch) override
+  nsresult Dispatch(already_AddRefed<nsIRunnable> aRunnable,
+                    DispatchFailureHandling aFailureHandling = AssertDispatchSuccess,
+                    DispatchReason aReason = NormalDispatch) override
   {
     nsCOMPtr<nsIRunnable> r = aRunnable;
     {
       MonitorAutoLock mon(mQueueMonitor);
-      return DispatchLocked(/* passed by ref */r, aReason);
+      nsresult rv = DispatchLocked(/* passed by ref */r, aFailureHandling, aReason);
+#if defined(DEBUG) || !defined(RELEASE_OR_BETA) || defined(EARLY_BETA_OR_EARLIER)
+      if (NS_FAILED(rv) && aFailureHandling == AssertDispatchSuccess) {
+        MOZ_CRASH_UNSAFE_PRINTF("%s: Dispatch failed. rv=%x", mName, uint32_t(rv));
+      }
+#endif
+      return rv;
     }
     // If the ownership of |r| is not transferred in DispatchLocked() due to
     // dispatch failure, it will be deleted here outside the lock. We do so
     // since the destructor of the runnable might access TaskQueue and result
     // in deadlocks.
   }
 
   // Prevent a GCC warning about the other overload of Dispatch being hidden.
@@ -110,16 +116,17 @@ protected:
 
 
   // Blocks until all task finish executing. Called internally by methods
   // that need to wait until the task queue is idle.
   // mQueueMonitor must be held.
   void AwaitIdleLocked();
 
   nsresult DispatchLocked(nsCOMPtr<nsIRunnable>& aRunnable,
+                          DispatchFailureHandling aFailureHandling,
                           DispatchReason aReason = NormalDispatch);
 
   void MaybeResolveShutdown()
   {
     mQueueMonitor.AssertCurrentThreadOwns();
     if (mIsShutdown && !mIsRunning) {
       mShutdownPromise.ResolveIfExists(true, __func__);
       mTarget = nullptr;