Bug 1865640 - Part 2: Grab StrongWorkerRef in StartConsuming instead of Create r=smaug

Differential Revision: https://phabricator.services.mozilla.com/D194090
This commit is contained in:
Kagami Sascha Rosylight
2023-11-23 11:34:25 +00:00
parent cefcb6d8bb
commit f45f3daa00
2 changed files with 44 additions and 31 deletions

View File

@@ -54,42 +54,47 @@ nsresult FetchStreamReader::Create(JSContext* aCx, nsIGlobalObject* aGlobal,
NS_NewPipe2(getter_AddRefs(pipeIn), getter_AddRefs(streamReader->mPipeOut),
true, true, 0, 0);
if (!NS_IsMainThread()) {
WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(aCx);
MOZ_ASSERT(workerPrivate);
RefPtr<StrongWorkerRef> workerRef = StrongWorkerRef::Create(
workerPrivate, "FetchStreamReader", [streamReader]() {
MOZ_ASSERT(streamReader);
// mAsyncWaitWorkerRef may keep the (same) StrongWorkerRef alive even
// when mWorkerRef has already been nulled out by a previous call to
// CloseAndRelease, we can just safely ignore this callback then
// (as would the CloseAndRelease do on a second call).
if (streamReader->mWorkerRef) {
streamReader->CloseAndRelease(
streamReader->mWorkerRef->Private()->GetJSContext(),
NS_ERROR_DOM_INVALID_STATE_ERR);
} else {
MOZ_DIAGNOSTIC_ASSERT(streamReader->mAsyncWaitWorkerRef);
}
});
if (NS_WARN_IF(!workerRef)) {
streamReader->mPipeOut->CloseWithStatus(NS_ERROR_DOM_INVALID_STATE_ERR);
return NS_ERROR_DOM_INVALID_STATE_ERR;
}
// These 2 objects create a ref-cycle here that is broken when the stream is
// closed or the worker shutsdown.
streamReader->mWorkerRef = std::move(workerRef);
}
pipeIn.forget(aInputStream);
streamReader.forget(aStreamReader);
return NS_OK;
}
nsresult FetchStreamReader::MaybeGrabStrongWorkerRef(JSContext* aCx) {
if (NS_IsMainThread()) {
return NS_OK;
}
WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(aCx);
MOZ_ASSERT(workerPrivate);
RefPtr<StrongWorkerRef> workerRef = StrongWorkerRef::Create(
workerPrivate, "FetchStreamReader", [streamReader = RefPtr(this)]() {
MOZ_ASSERT(streamReader);
// mAsyncWaitWorkerRef may keep the (same) StrongWorkerRef alive even
// when mWorkerRef has already been nulled out by a previous call to
// CloseAndRelease, we can just safely ignore this callback then
// (as would the CloseAndRelease do on a second call).
if (streamReader->mWorkerRef) {
streamReader->CloseAndRelease(
streamReader->mWorkerRef->Private()->GetJSContext(),
NS_ERROR_DOM_INVALID_STATE_ERR);
} else {
MOZ_DIAGNOSTIC_ASSERT(streamReader->mAsyncWaitWorkerRef);
}
});
if (NS_WARN_IF(!workerRef)) {
return NS_ERROR_DOM_INVALID_STATE_ERR;
}
// These 2 objects create a ref-cycle here that is broken when the stream is
// closed or the worker shutsdown.
mWorkerRef = std::move(workerRef);
return NS_OK;
}
FetchStreamReader::FetchStreamReader(nsIGlobalObject* aGlobal)
: mGlobal(aGlobal), mOwningEventTarget(mGlobal->SerialEventTarget()) {
MOZ_ASSERT(aGlobal);
@@ -165,6 +170,12 @@ void FetchStreamReader::StartConsuming(JSContext* aCx, ReadableStream* aStream,
MOZ_DIAGNOSTIC_ASSERT(!mReader);
MOZ_DIAGNOSTIC_ASSERT(aStream);
aRv = MaybeGrabStrongWorkerRef(aCx);
if (aRv.Failed()) {
CloseAndRelease(aCx, NS_ERROR_DOM_INVALID_STATE_ERR);
return;
}
// Step 2: Let reader be the result of getting a reader for bodys stream.
RefPtr<ReadableStreamDefaultReader> reader = aStream->GetReader(aRv);
if (aRv.Failed()) {