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 436307 7613f8e20ad525e183b9e5a237cb5725fbe3f630
parent 436306 7e35281e0eafbc99ee94d182dfb11d4492f89120
child 436308 3aa5eb7e2ed90b56d28f2618ed1339da085028b2
push id117
push userfmarier@mozilla.com
push dateTue, 28 Nov 2017 20:17:16 +0000
reviewersbackout
bugs1416724
milestone59.0a1
backs out45352aa4319debd6ad3445f2729db197ffc83eac
01d1e5263bcd56fadf19b446b48c4ab2c9de6891
bc854c315ec8c0dfde87ca0193c024d16314aaa2
35a50167485d1507d07e85b21e29f6b17c505d7d
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;