Bug 1824225: Add support for Implicit/Explicit to ReadableStream r=smaug

Differential Revision: https://phabricator.services.mozilla.com/D173525
This commit is contained in:
Randell Jesup 2023-03-24 22:19:08 +00:00
parent fec735991b
commit 23660aba47
4 changed files with 47 additions and 17 deletions

View file

@ -82,17 +82,29 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ReadableStream)
NS_INTERFACE_MAP_ENTRY(nsISupports) NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_INTERFACE_MAP_END NS_INTERFACE_MAP_END
ReadableStream::ReadableStream(nsIGlobalObject* aGlobal) ReadableStream::ReadableStream(nsIGlobalObject* aGlobal,
: mGlobal(aGlobal), mReader(nullptr) { HoldDropJSObjectsCaller aHoldDropCaller)
: mGlobal(aGlobal), mReader(nullptr), mHoldDropCaller(aHoldDropCaller) {
if (mHoldDropCaller == HoldDropJSObjectsCaller::Implicit) {
mozilla::HoldJSObjects(this); mozilla::HoldJSObjects(this);
} }
ReadableStream::ReadableStream(const GlobalObject& aGlobal)
: mGlobal(do_QueryInterface(aGlobal.GetAsSupports())), mReader(nullptr) {
mozilla::HoldJSObjects(this);
} }
ReadableStream::~ReadableStream() { mozilla::DropJSObjects(this); } ReadableStream::ReadableStream(const GlobalObject& aGlobal,
HoldDropJSObjectsCaller aHoldDropCaller)
: mGlobal(do_QueryInterface(aGlobal.GetAsSupports())),
mReader(nullptr),
mHoldDropCaller(aHoldDropCaller) {
if (mHoldDropCaller == HoldDropJSObjectsCaller::Implicit) {
mozilla::HoldJSObjects(this);
}
}
ReadableStream::~ReadableStream() {
if (mHoldDropCaller == HoldDropJSObjectsCaller::Implicit) {
mozilla::DropJSObjects(this);
}
}
JSObject* ReadableStream::WrapObject(JSContext* aCx, JSObject* ReadableStream::WrapObject(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto) { JS::Handle<JSObject*> aGivenProto) {
@ -167,7 +179,8 @@ already_AddRefed<ReadableStream> ReadableStream::Constructor(
} }
// Step 3. // Step 3.
RefPtr<ReadableStream> readableStream = new ReadableStream(aGlobal); RefPtr<ReadableStream> readableStream =
new ReadableStream(aGlobal, HoldDropJSObjectsCaller::Implicit);
// Step 4. // Step 4.
if (underlyingSourceDict.mType.WasPassed()) { if (underlyingSourceDict.mType.WasPassed()) {
@ -264,7 +277,8 @@ already_AddRefed<ReadableStream> ReadableStream::CreateAbstract(
// Step 3. // Step 3.
MOZ_ASSERT(IsNonNegativeNumber(highWaterMark)); MOZ_ASSERT(IsNonNegativeNumber(highWaterMark));
// Step 4. // Step 4.
RefPtr<ReadableStream> stream = new ReadableStream(aGlobal); RefPtr<ReadableStream> stream =
new ReadableStream(aGlobal, HoldDropJSObjectsCaller::Implicit);
// Step 5. // Step 5.
InitializeReadableStream(stream); InitializeReadableStream(stream);
@ -1001,7 +1015,8 @@ already_AddRefed<ReadableStream> ReadableStream::CreateByteAbstract(
JSContext* aCx, nsIGlobalObject* aGlobal, JSContext* aCx, nsIGlobalObject* aGlobal,
UnderlyingSourceAlgorithmsBase* aAlgorithms, ErrorResult& aRv) { UnderlyingSourceAlgorithmsBase* aAlgorithms, ErrorResult& aRv) {
// Step 1. Let stream be a new ReadableStream. // Step 1. Let stream be a new ReadableStream.
RefPtr<ReadableStream> stream = new ReadableStream(aGlobal); RefPtr<ReadableStream> stream =
new ReadableStream(aGlobal, HoldDropJSObjectsCaller::Implicit);
// Step 2. Perform ! InitializeReadableStream(stream). // Step 2. Perform ! InitializeReadableStream(stream).
InitializeReadableStream(stream); InitializeReadableStream(stream);
@ -1045,7 +1060,8 @@ already_AddRefed<ReadableStream> ReadableStream::CreateNative(
// ReadableStream::Constructor for details) // ReadableStream::Constructor for details)
// Step 5: Perform ! InitializeReadableStream(stream). // Step 5: Perform ! InitializeReadableStream(stream).
RefPtr<ReadableStream> stream = new ReadableStream(aGlobal); RefPtr<ReadableStream> stream =
new ReadableStream(aGlobal, HoldDropJSObjectsCaller::Implicit);
// Step 6: Let controller be a new ReadableStreamDefaultController. // Step 6: Let controller be a new ReadableStreamDefaultController.
auto controller = MakeRefPtr<ReadableStreamDefaultController>(aGlobal); auto controller = MakeRefPtr<ReadableStreamDefaultController>(aGlobal);
@ -1092,7 +1108,8 @@ already_AddRefed<ReadableStream> ReadableStream::CreateByteNative(
JSContext* aCx, nsIGlobalObject* aGlobal, JSContext* aCx, nsIGlobalObject* aGlobal,
UnderlyingSourceAlgorithmsWrapper& aAlgorithms, UnderlyingSourceAlgorithmsWrapper& aAlgorithms,
mozilla::Maybe<double> aHighWaterMark, ErrorResult& aRv) { mozilla::Maybe<double> aHighWaterMark, ErrorResult& aRv) {
RefPtr<ReadableStream> stream = new ReadableStream(aGlobal); RefPtr<ReadableStream> stream =
new ReadableStream(aGlobal, HoldDropJSObjectsCaller::Implicit);
stream->SetUpByteNative(aCx, aAlgorithms, aHighWaterMark, aRv); stream->SetUpByteNative(aCx, aAlgorithms, aHighWaterMark, aRv);
if (aRv.Failed()) { if (aRv.Failed()) {
return nullptr; return nullptr;

View file

@ -53,8 +53,17 @@ class ReadableStream : public nsISupports, public nsWrapperCache {
nsCOMPtr<nsIGlobalObject> mGlobal; nsCOMPtr<nsIGlobalObject> mGlobal;
explicit ReadableStream(const GlobalObject& aGlobal); // If one extends ReadableStream with another cycle collectable class,
explicit ReadableStream(nsIGlobalObject* aGlobal); // calling HoldJSObjects and DropJSObjects should happen using 'this' of
// that extending class. And in that case Explicit should be passed to the
// constructor of ReadableStream so that it doesn't make those calls.
// See also https://bugzilla.mozilla.org/show_bug.cgi?id=1801214.
enum class HoldDropJSObjectsCaller { Implicit, Explicit };
explicit ReadableStream(const GlobalObject& aGlobal,
HoldDropJSObjectsCaller aHoldDropCaller);
explicit ReadableStream(nsIGlobalObject* aGlobal,
HoldDropJSObjectsCaller aHoldDropCaller);
public: public:
// Abstract algorithms // Abstract algorithms
@ -229,6 +238,8 @@ class ReadableStream : public nsISupports, public nsWrapperCache {
RefPtr<ReadableStreamGenericReader> mReader; RefPtr<ReadableStreamGenericReader> mReader;
ReaderState mState = ReaderState::Readable; ReaderState mState = ReaderState::Readable;
JS::Heap<JS::Value> mStoredError; JS::Heap<JS::Value> mStoredError;
HoldDropJSObjectsCaller mHoldDropCaller;
}; };
namespace streams_abstract { namespace streams_abstract {

View file

@ -863,7 +863,8 @@ ReadableStream::ReceiveTransferImpl(JSContext* aCx, nsIGlobalObject* aGlobal,
// Step 2: Let port be deserializedRecord.[[Deserialized]]. // Step 2: Let port be deserializedRecord.[[Deserialized]].
// Step 3: Perform ! SetUpCrossRealmTransformReadable(value, port). // Step 3: Perform ! SetUpCrossRealmTransformReadable(value, port).
RefPtr<ReadableStream> readable = new ReadableStream(aGlobal); RefPtr<ReadableStream> readable =
new ReadableStream(aGlobal, HoldDropJSObjectsCaller::Implicit);
ErrorResult rv; ErrorResult rv;
SetUpCrossRealmTransformReadable(readable, &aPort, rv); SetUpCrossRealmTransformReadable(readable, &aPort, rv);
if (rv.MaybeSetPendingException(aCx)) { if (rv.MaybeSetPendingException(aCx)) {
@ -910,7 +911,8 @@ bool WritableStream::Transfer(JSContext* aCx, UniqueMessagePortId& aPortId) {
} }
// Step 5: Let readable be a new ReadableStream in the current Realm. // Step 5: Let readable be a new ReadableStream in the current Realm.
RefPtr<ReadableStream> readable = new ReadableStream(mGlobal); RefPtr<ReadableStream> readable = new ReadableStream(
mGlobal, ReadableStream::HoldDropJSObjectsCaller::Implicit);
// Step 6: Perform ! SetUpCrossRealmTransformReadable(readable, port1). // Step 6: Perform ! SetUpCrossRealmTransformReadable(readable, port1).
// MOZ_KnownLive because Port1 never changes before CC // MOZ_KnownLive because Port1 never changes before CC

View file

@ -18,7 +18,7 @@ using namespace mozilla::ipc;
namespace mozilla::dom { namespace mozilla::dom {
WebTransportReceiveStream::WebTransportReceiveStream(nsIGlobalObject* aGlobal) WebTransportReceiveStream::WebTransportReceiveStream(nsIGlobalObject* aGlobal)
: ReadableStream(aGlobal) {} : ReadableStream(aGlobal, HoldDropJSObjectsCaller::Implicit) {}
// WebIDL Boilerplate // WebIDL Boilerplate