diff --git a/dom/base/BodyStream.cpp b/dom/base/BodyStream.cpp index a55149ef70c5..8393c257bc04 100644 --- a/dom/base/BodyStream.cpp +++ b/dom/base/BodyStream.cpp @@ -115,8 +115,8 @@ void BodyStream::Create(JSContext* aCx, BodyStreamHolder* aStreamHolder, WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(aCx); MOZ_ASSERT(workerPrivate); - RefPtr workerRef = - WeakWorkerRef::Create(workerPrivate, [stream]() { stream->Close(); }); + RefPtr workerRef = + StrongWorkerRef::Create(workerPrivate, "BodyStream", [stream]() { stream->Close(); }); if (NS_WARN_IF(!workerRef)) { aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR); @@ -215,6 +215,7 @@ already_AddRefed BodyStream::PullCallback( ErrorPropagation(aCx, lock, stream, rv); return nullptr; } + mAsyncWaitWorkerRef = mWorkerRef; // All good. return resolvedWithUndefinedPromise.forget(); @@ -272,6 +273,7 @@ void BodyStream::WriteIntoReadRequestBuffer(JSContext* aCx, ErrorPropagation(aCx, lock, aStream, rv); return; } + mAsyncWaitWorkerRef = mWorkerRef; // All good. } @@ -429,6 +431,7 @@ BodyStream::OnInputStreamReady(nsIAsyncInputStream* aStream) NO_THREAD_SAFETY_ANALYSIS { AssertIsOnOwningThread(); MOZ_DIAGNOSTIC_ASSERT(aStream); + mAsyncWaitWorkerRef = nullptr; // Acquire |mMutex| in order to safely inspect |mState| and use |mGlobal|. Maybe lock; @@ -581,7 +584,7 @@ void BodyStream::ReleaseObjects(const MutexSingleWriterAutoLock& aProofOfLock) { // Let's dispatch a WorkerControlRunnable if the owning thread is a worker. if (mWorkerRef) { RefPtr r = - new WorkerShutdown(mWorkerRef->GetUnsafePrivate(), this); + new WorkerShutdown(mWorkerRef->Private(), this); Unused << NS_WARN_IF(!r->Dispatch()); return; } diff --git a/dom/base/BodyStream.h b/dom/base/BodyStream.h index 70b75d12c830..152774088e23 100644 --- a/dom/base/BodyStream.h +++ b/dom/base/BodyStream.h @@ -30,7 +30,7 @@ class ErrorResult; namespace dom { class BodyStream; -class WeakWorkerRef; +class StrongWorkerRef; class ReadableStream; class ReadableStreamController; @@ -200,7 +200,8 @@ class BodyStream final : public nsIInputStreamCallback, nsCOMPtr mOriginalInputStream; nsCOMPtr mInputStream; - RefPtr mWorkerRef; + RefPtr mWorkerRef; + RefPtr mAsyncWaitWorkerRef; }; } // namespace dom diff --git a/dom/fetch/FetchStreamReader.cpp b/dom/fetch/FetchStreamReader.cpp index a7c0685832c2..25c60246276e 100644 --- a/dom/fetch/FetchStreamReader.cpp +++ b/dom/fetch/FetchStreamReader.cpp @@ -76,16 +76,14 @@ nsresult FetchStreamReader::Create(JSContext* aCx, nsIGlobalObject* aGlobal, WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(aCx); MOZ_ASSERT(workerPrivate); - RefPtr workerRef = - WeakWorkerRef::Create(workerPrivate, [streamReader]() { + RefPtr workerRef = StrongWorkerRef::Create( + workerPrivate, "FetchStreamReader", [streamReader]() { MOZ_ASSERT(streamReader); MOZ_ASSERT(streamReader->mWorkerRef); - WorkerPrivate* workerPrivate = streamReader->mWorkerRef->GetPrivate(); - MOZ_ASSERT(workerPrivate); - - streamReader->CloseAndRelease(workerPrivate->GetJSContext(), - NS_ERROR_DOM_INVALID_STATE_ERR); + streamReader->CloseAndRelease( + streamReader->mWorkerRef->Private()->GetJSContext(), + NS_ERROR_DOM_INVALID_STATE_ERR); }); if (NS_WARN_IF(!workerRef)) { @@ -194,6 +192,7 @@ void FetchStreamReader::StartConsuming(JSContext* aCx, ReadableStream* aStream, if (NS_WARN_IF(aRv.Failed())) { return; } + mAsyncWaitWorkerRef = mWorkerRef; } struct FetchReadRequest : public ReadRequest { @@ -236,6 +235,7 @@ MOZ_CAN_RUN_SCRIPT_BOUNDARY NS_IMETHODIMP FetchStreamReader::OnOutputStreamReady(nsIAsyncOutputStream* aStream) { NS_ASSERT_OWNINGTHREAD(FetchStreamReader); + mAsyncWaitWorkerRef = nullptr; if (mStreamClosed) { return NS_OK; } diff --git a/dom/fetch/FetchStreamReader.h b/dom/fetch/FetchStreamReader.h index 7a74b336c336..90cfb3e6ebc4 100644 --- a/dom/fetch/FetchStreamReader.h +++ b/dom/fetch/FetchStreamReader.h @@ -19,7 +19,7 @@ namespace mozilla::dom { class ReadableStream; class ReadableStreamDefaultReader; -class WeakWorkerRef; +class StrongWorkerRef; class FetchStreamReader final : public nsIOutputStreamCallback { public: @@ -66,7 +66,8 @@ class FetchStreamReader final : public nsIOutputStreamCallback { nsCOMPtr mPipeOut; - RefPtr mWorkerRef; + RefPtr mWorkerRef; + RefPtr mAsyncWaitWorkerRef; RefPtr mReader; diff --git a/dom/fetch/FetchUtil.cpp b/dom/fetch/FetchUtil.cpp index dfbb831cca83..35489b6bb636 100644 --- a/dom/fetch/FetchUtil.cpp +++ b/dom/fetch/FetchUtil.cpp @@ -295,14 +295,13 @@ class WorkerStreamOwner final { RefPtr self = new WorkerStreamOwner(aStream, std::move(target)); - self->mWorkerRef = WeakWorkerRef::Create(aWorker, [self]() { + self->mWorkerRef = StrongWorkerRef::Create(aWorker, "JSStreamConsumer", [self]() { if (self->mStream) { // If this Close() calls JSStreamConsumer::OnInputStreamReady and drops // the last reference to the JSStreamConsumer, 'this' will not be // destroyed since ~JSStreamConsumer() only enqueues a release proxy. self->mStream->Close(); self->mStream = nullptr; - self->mWorkerRef = nullptr; } }); @@ -326,7 +325,7 @@ class WorkerStreamOwner final { // Read from any thread but only set/cleared on the worker thread. The // lifecycle of WorkerStreamOwner prevents concurrent read/clear. nsCOMPtr mStream; - RefPtr mWorkerRef; + RefPtr mWorkerRef; nsCOMPtr mOwningEventTarget; }; diff --git a/dom/file/FileReader.cpp b/dom/file/FileReader.cpp index 0e96e1c7274a..ca1d55c0d8a4 100644 --- a/dom/file/FileReader.cpp +++ b/dom/file/FileReader.cpp @@ -624,15 +624,15 @@ FileReader::Notify(nsITimer* aTimer) { // InputStreamCallback NS_IMETHODIMP FileReader::OnInputStreamReady(nsIAsyncInputStream* aStream) { - if (mReadyState != LOADING || aStream != mAsyncStream) { - return NS_OK; - } - // We use this class to decrease the busy counter at the end of this method. // In theory we can do it immediatelly but, for debugging reasons, we want to // be 100% sure we have a workerRef when OnLoadEnd() is called. FileReaderDecreaseBusyCounter RAII(this); + if (mReadyState != LOADING || aStream != mAsyncStream) { + return NS_OK; + } + uint64_t count; nsresult rv = aStream->Available(&count); @@ -731,14 +731,7 @@ void FileReader::Abort() { MOZ_ASSERT(mReadyState == LOADING); - ClearProgressEventTimer(); - - if (mAsyncWaitRunnable) { - mAsyncWaitRunnable->Cancel(); - mAsyncWaitRunnable = nullptr; - } - - mReadyState = DONE; + Cleanup(); // XXX The spec doesn't say this mError = DOMException::Create(NS_ERROR_DOM_ABORT_ERR); @@ -747,30 +740,12 @@ void FileReader::Abort() { SetDOMStringToNull(mResult); mResultArrayBuffer = nullptr; - // If we have the stream and the busy-count is not 0, it means that we are - // waiting for an OnInputStreamReady() call. Let's abort the current - // AsyncWait() calling it again with a nullptr callback. See - // nsIAsyncInputStream.idl. - if (mAsyncStream && mBusyCount) { - mAsyncStream->AsyncWait(/* callback */ nullptr, - /* aFlags*/ 0, - /* aRequestedCount */ 0, mTarget); - DecreaseBusyCounter(); - MOZ_ASSERT(mBusyCount == 0); - - mAsyncStream->Close(); - } - - mAsyncStream = nullptr; mBlob = nullptr; - // Clean up memory buffer - FreeFileData(); - // Dispatch the events DispatchProgressEvent(nsLiteralString(ABORT_STR)); DispatchProgressEvent(nsLiteralString(LOADEND_STR)); -} // namespace dom +} nsresult FileReader::IncreaseBusyCounter() { if (mWeakWorkerRef && mBusyCount++ == 0) { @@ -800,7 +775,7 @@ void FileReader::DecreaseBusyCounter() { } } -void FileReader::Shutdown() { +void FileReader::Cleanup() { mReadyState = DONE; if (mAsyncWaitRunnable) { @@ -816,11 +791,12 @@ void FileReader::Shutdown() { ClearProgressEventTimer(); FreeFileData(); mResultArrayBuffer = nullptr; +} - if (mWeakWorkerRef && mBusyCount != 0) { - mStrongWorkerRef = nullptr; +void FileReader::Shutdown() { + Cleanup(); + if (mWeakWorkerRef) { mWeakWorkerRef = nullptr; - mBusyCount = 0; } } diff --git a/dom/file/FileReader.h b/dom/file/FileReader.h index 159a974ebb47..1c07b6193f2c 100644 --- a/dom/file/FileReader.h +++ b/dom/file/FileReader.h @@ -155,6 +155,7 @@ class FileReader final : public DOMEventTargetHelper, nsresult IncreaseBusyCounter(); void DecreaseBusyCounter(); + void Cleanup(); void Shutdown(); char* mFileData;