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_END
ReadableStream::ReadableStream(nsIGlobalObject* aGlobal)
: mGlobal(aGlobal), mReader(nullptr) {
mozilla::HoldJSObjects(this);
ReadableStream::ReadableStream(nsIGlobalObject* aGlobal,
HoldDropJSObjectsCaller aHoldDropCaller)
: mGlobal(aGlobal), mReader(nullptr), mHoldDropCaller(aHoldDropCaller) {
if (mHoldDropCaller == HoldDropJSObjectsCaller::Implicit) {
mozilla::HoldJSObjects(this);
}
}
ReadableStream::ReadableStream(const GlobalObject& aGlobal)
: mGlobal(do_QueryInterface(aGlobal.GetAsSupports())), mReader(nullptr) {
mozilla::HoldJSObjects(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() { mozilla::DropJSObjects(this); }
ReadableStream::~ReadableStream() {
if (mHoldDropCaller == HoldDropJSObjectsCaller::Implicit) {
mozilla::DropJSObjects(this);
}
}
JSObject* ReadableStream::WrapObject(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto) {
@ -167,7 +179,8 @@ already_AddRefed<ReadableStream> ReadableStream::Constructor(
}
// Step 3.
RefPtr<ReadableStream> readableStream = new ReadableStream(aGlobal);
RefPtr<ReadableStream> readableStream =
new ReadableStream(aGlobal, HoldDropJSObjectsCaller::Implicit);
// Step 4.
if (underlyingSourceDict.mType.WasPassed()) {
@ -264,7 +277,8 @@ already_AddRefed<ReadableStream> ReadableStream::CreateAbstract(
// Step 3.
MOZ_ASSERT(IsNonNegativeNumber(highWaterMark));
// Step 4.
RefPtr<ReadableStream> stream = new ReadableStream(aGlobal);
RefPtr<ReadableStream> stream =
new ReadableStream(aGlobal, HoldDropJSObjectsCaller::Implicit);
// Step 5.
InitializeReadableStream(stream);
@ -1001,7 +1015,8 @@ already_AddRefed<ReadableStream> ReadableStream::CreateByteAbstract(
JSContext* aCx, nsIGlobalObject* aGlobal,
UnderlyingSourceAlgorithmsBase* aAlgorithms, ErrorResult& aRv) {
// 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).
InitializeReadableStream(stream);
@ -1045,7 +1060,8 @@ already_AddRefed<ReadableStream> ReadableStream::CreateNative(
// ReadableStream::Constructor for details)
// 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.
auto controller = MakeRefPtr<ReadableStreamDefaultController>(aGlobal);
@ -1092,7 +1108,8 @@ already_AddRefed<ReadableStream> ReadableStream::CreateByteNative(
JSContext* aCx, nsIGlobalObject* aGlobal,
UnderlyingSourceAlgorithmsWrapper& aAlgorithms,
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);
if (aRv.Failed()) {
return nullptr;

View file

@ -53,8 +53,17 @@ class ReadableStream : public nsISupports, public nsWrapperCache {
nsCOMPtr<nsIGlobalObject> mGlobal;
explicit ReadableStream(const GlobalObject& aGlobal);
explicit ReadableStream(nsIGlobalObject* aGlobal);
// If one extends ReadableStream with another cycle collectable class,
// 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:
// Abstract algorithms
@ -229,6 +238,8 @@ class ReadableStream : public nsISupports, public nsWrapperCache {
RefPtr<ReadableStreamGenericReader> mReader;
ReaderState mState = ReaderState::Readable;
JS::Heap<JS::Value> mStoredError;
HoldDropJSObjectsCaller mHoldDropCaller;
};
namespace streams_abstract {

View file

@ -863,7 +863,8 @@ ReadableStream::ReceiveTransferImpl(JSContext* aCx, nsIGlobalObject* aGlobal,
// Step 2: Let port be deserializedRecord.[[Deserialized]].
// Step 3: Perform ! SetUpCrossRealmTransformReadable(value, port).
RefPtr<ReadableStream> readable = new ReadableStream(aGlobal);
RefPtr<ReadableStream> readable =
new ReadableStream(aGlobal, HoldDropJSObjectsCaller::Implicit);
ErrorResult rv;
SetUpCrossRealmTransformReadable(readable, &aPort, rv);
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.
RefPtr<ReadableStream> readable = new ReadableStream(mGlobal);
RefPtr<ReadableStream> readable = new ReadableStream(
mGlobal, ReadableStream::HoldDropJSObjectsCaller::Implicit);
// Step 6: Perform ! SetUpCrossRealmTransformReadable(readable, port1).
// MOZ_KnownLive because Port1 never changes before CC

View file

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