fune/dom/fetch/FetchStreamReader.h
Nika Layzell 0e64b40e0c Bug 1538754 - Consistently watch the nsIAsyncOutputStream for closure, r=asuth,saschanaz
Before these changes, there were a number of cases where it would be
possible for the pipe to be closed or otherwise encounter an error, and
for there to be a very large or potentially indefinite delay before that
error is reported to the ReadableStream.

This patch avoids changing too much of the structure of the existing
FetchStreamReader's design, while avoiding the potential pitfalls, and
ensuring that the stream is being consistently watched.

A more polished patch in the future may be able to perform a more
efficient and direct adaptation from a `ReadableStream` or
`WritableStream` to the `nsIAsyncInputStream` and `nsIAsyncOutputStream`
types, but that was not tackled here.

Differential Revision: https://phabricator.services.mozilla.com/D168481
2023-03-30 15:14:00 +00:00

94 lines
3.3 KiB
C++

/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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/. */
#ifndef mozilla_dom_FetchStreamReader_h
#define mozilla_dom_FetchStreamReader_h
#include "js/RootingAPI.h"
#include "js/TypeDecls.h"
#include "mozilla/Attributes.h"
#include "mozilla/dom/FetchBinding.h"
#include "mozilla/dom/PromiseNativeHandler.h"
#include "nsIAsyncOutputStream.h"
#include "nsIGlobalObject.h"
namespace mozilla::dom {
class ReadableStream;
class ReadableStreamDefaultReader;
class StrongWorkerRef;
class FetchStreamReader final : public nsIOutputStreamCallback {
public:
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(
FetchStreamReader, nsIOutputStreamCallback)
NS_DECL_NSIOUTPUTSTREAMCALLBACK
// This creates a nsIInputStream able to retrieve data from the ReadableStream
// object. The reading starts when StartConsuming() is called.
static nsresult Create(JSContext* aCx, nsIGlobalObject* aGlobal,
FetchStreamReader** aStreamReader,
nsIInputStream** aInputStream);
MOZ_CAN_RUN_SCRIPT
void ChunkSteps(JSContext* aCx, JS::Handle<JS::Value> aChunk,
ErrorResult& aRv);
MOZ_CAN_RUN_SCRIPT
void CloseSteps(JSContext* aCx, ErrorResult& aRv);
MOZ_CAN_RUN_SCRIPT
void ErrorSteps(JSContext* aCx, JS::Handle<JS::Value> aError,
ErrorResult& aRv);
// Idempotently close the output stream and null out all state. If aCx is
// provided, the reader will also be canceled. aStatus must be a DOM error
// as understood by DOMException because it will be provided as the
// cancellation reason.
//
// This is a script boundary minimize annotation changes required while
// we figure out how to handle some more tricky annotation cases (for
// example, the destructor of this class. Tracking under Bug 1750656)
MOZ_CAN_RUN_SCRIPT_BOUNDARY
void CloseAndRelease(JSContext* aCx, nsresult aStatus);
void StartConsuming(JSContext* aCx, ReadableStream* aStream,
ReadableStreamDefaultReader** aReader, ErrorResult& aRv);
private:
explicit FetchStreamReader(nsIGlobalObject* aGlobal);
~FetchStreamReader();
nsresult WriteBuffer();
// Attempt to copy data from mBuffer into mPipeOut. Returns `true` if data was
// written, and AsyncWait callbacks or FetchReadRequest calls have been set up
// to write more data in the future, and `false` otherwise.
MOZ_CAN_RUN_SCRIPT
bool Process(JSContext* aCx);
void ReportErrorToConsole(JSContext* aCx, JS::Handle<JS::Value> aValue);
nsCOMPtr<nsIGlobalObject> mGlobal;
nsCOMPtr<nsIEventTarget> mOwningEventTarget;
nsCOMPtr<nsIAsyncOutputStream> mPipeOut;
RefPtr<StrongWorkerRef> mWorkerRef;
RefPtr<StrongWorkerRef> mAsyncWaitWorkerRef;
RefPtr<ReadableStreamDefaultReader> mReader;
nsTArray<uint8_t> mBuffer;
uint32_t mBufferRemaining = 0;
uint32_t mBufferOffset = 0;
bool mHasOutstandingReadRequest = false;
bool mStreamClosed = false;
};
} // namespace mozilla::dom
#endif // mozilla_dom_FetchStreamReader_h