Bug 1813011 - Part 2: Return unsettled promise from BodyStream::PullCallbackImpl r=smaug

... and resolve it after successful enqueue. Note that this never rejects it since ErrorNative will do it for us.

eWaiting/eReading/eWriting is merged into eInitialized and the state assertions now use promise state.

Differential Revision: https://phabricator.services.mozilla.com/D169483
This commit is contained in:
Kagami Sascha Rosylight 2023-02-17 18:32:25 +00:00
Родитель 5106ab260f
Коммит 395a9e1fec
2 изменённых файлов: 22 добавлений и 29 удалений

Просмотреть файл

@ -191,26 +191,16 @@ already_AddRefed<Promise> BodyStream::PullCallback(
MOZ_DIAGNOSTIC_ASSERT(mOwningEventTarget->IsOnCurrentThread());
MOZ_DIAGNOSTIC_ASSERT(mState == eInitializing || mState == eWaiting ||
mState == eReading);
RefPtr<Promise> resolvedWithUndefinedPromise =
Promise::CreateResolvedWithUndefined(aController.GetParentObject(), aRv);
if (aRv.Failed()) {
return nullptr;
}
if (mState == eReading) {
// We are already reading data.
return resolvedWithUndefinedPromise.forget();
}
MOZ_DIAGNOSTIC_ASSERT(mState == eInitializing || mState == eInitialized);
MOZ_ASSERT(!mPullPromise);
mPullPromise = Promise::CreateInfallible(aController.GetParentObject());
if (mState == eInitializing) {
// The stream has been used for the first time.
mStreamHolder->MarkAsRead();
}
mState = eReading;
mState = eInitialized;
if (!mInputStream) {
// This is the first use of the stream. Let's convert the
@ -240,7 +230,7 @@ already_AddRefed<Promise> BodyStream::PullCallback(
mAsyncWaitWorkerRef = mWorkerRef;
// All good.
return resolvedWithUndefinedPromise.forget();
return do_AddRef(mPullPromise);
}
void BodyStream::WriteIntoReadRequestBuffer(JSContext* aCx,
@ -254,7 +244,9 @@ void BodyStream::WriteIntoReadRequestBuffer(JSContext* aCx,
MOZ_DIAGNOSTIC_ASSERT(mOwningEventTarget->IsOnCurrentThread());
MOZ_DIAGNOSTIC_ASSERT(mInputStream);
MOZ_DIAGNOSTIC_ASSERT(mState == eWriting);
MOZ_DIAGNOSTIC_ASSERT(mState == eInitialized);
MOZ_DIAGNOSTIC_ASSERT(mPullPromise->State() ==
Promise::PromiseState::Pending);
uint32_t written;
nsresult rv;
@ -437,7 +429,9 @@ BodyStream::OnInputStreamReady(nsIAsyncInputStream* aStream) {
AutoEntryScript aes(mGlobal, "fetch body data available");
MOZ_DIAGNOSTIC_ASSERT(mInputStream);
MOZ_DIAGNOSTIC_ASSERT(mState == eReading);
MOZ_DIAGNOSTIC_ASSERT(mState == eInitialized);
MOZ_DIAGNOSTIC_ASSERT(mPullPromise->State() ==
Promise::PromiseState::Pending);
JSContext* cx = aes.cx();
ReadableStream* stream = mStreamHolder->GetReadableStreamBody();
@ -455,8 +449,6 @@ BodyStream::OnInputStreamReady(nsIAsyncInputStream* aStream) {
return NS_OK;
}
mState = eWriting;
ErrorResult errorResult;
EnqueueChunkWithSizeIntoStream(cx, stream, size, errorResult);
errorResult.WouldReportJSException();
@ -465,7 +457,8 @@ BodyStream::OnInputStreamReady(nsIAsyncInputStream* aStream) {
return NS_OK;
}
mState = eWaiting;
mPullPromise->MaybeResolveWithUndefined();
mPullPromise = nullptr;
// The previous call can execute JS (even up to running a nested event
// loop), so |mState| can't be asserted to have any particular value, even
@ -551,6 +544,10 @@ void BodyStream::ReleaseObjects() {
mWorkerRef = nullptr;
mGlobal = nullptr;
// It's okay to leave a potentially unsettled promise as-is as this is only
// used to prevent reentrant to PullCallback. CloseNative() or ErrorNative()
// will settle the read requests for us.
mPullPromise = nullptr;
RefPtr<BodyStream> self = mStreamHolder->TakeBodyStream();
mStreamHolder->NullifyStream();

Просмотреть файл

@ -140,15 +140,8 @@ class BodyStream final : public nsIInputStreamCallback,
// This is the beginning state before any reading operation.
eInitializing,
// RequestDataCallback has not been called yet. We haven't started to read
// data from the stream yet.
eWaiting,
// We are reading data in a separate I/O thread.
eReading,
// We are ready to write something in the JS Buffer.
eWriting,
// Stream is initialized and being consumed.
eInitialized,
// Operation completed.
eClosed,
@ -161,6 +154,9 @@ class BodyStream final : public nsIInputStreamCallback,
nsCOMPtr<nsIGlobalObject> mGlobal;
RefPtr<BodyStreamHolder> mStreamHolder;
nsCOMPtr<nsIEventTarget> mOwningEventTarget;
// Same as mGlobal but set to nullptr on OnInputStreamReady (on the owning
// thread).
RefPtr<Promise> mPullPromise;
// This is the original inputStream received during the CTOR. It will be
// converted into an nsIAsyncInputStream and stored into mInputStream at the