Bug 1800470, make it possible to extend WritableStream with another cycle collectable class, r=saschanaz

Differential Revision: https://phabricator.services.mozilla.com/D162287
This commit is contained in:
Olli Pettay 2022-11-24 13:58:39 +00:00
Родитель b1055977ce
Коммит 73ed00444f
6 изменённых файлов: 73 добавлений и 14 удалений

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

@ -116,7 +116,7 @@ FileSystemWritableFileStream::FileSystemWritableFileStream(
RefPtr<FileSystemWritableFileStreamChild> aActor,
const ::mozilla::ipc::FileDescriptor& aFileDescriptor,
const fs::FileSystemEntryMetadata& aMetadata)
: WritableStream(aGlobal),
: WritableStream(aGlobal, HoldDropJSObjectsCaller::Explicit),
mManager(aManager),
mActor(std::move(aActor)),
mFileDesc(nullptr),
@ -125,12 +125,16 @@ FileSystemWritableFileStream::FileSystemWritableFileStream(
auto rawFD = aFileDescriptor.ClonePlatformHandle();
mFileDesc = PR_ImportFile(PROsfd(rawFD.release()));
mozilla::HoldJSObjects(this);
LOG(("Created WritableFileStream %p for fd %p", this, mFileDesc));
}
FileSystemWritableFileStream::~FileSystemWritableFileStream() {
MOZ_ASSERT(!mActor);
MOZ_ASSERT(mClosed);
mozilla::DropJSObjects(this);
}
// https://streams.spec.whatwg.org/#writablestream-set-up

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

@ -0,0 +1,28 @@
<!DOCTYPE html>
<html class="reftest-wait">
<head>
<script id="worker1" type="javascript/worker">
self.onmessage = async function (e) {
const directory = await navigator.storage.getDirectory();
const file = await directory.getFileHandle("500014c3-f683-4551-bb26-08025c9be332", {
create: true,
});
const stream = await file.createWritable({});
const regex = new RegExp(".*");
await stream.abort(regex);
self.postMessage("done");
self.close();
}
</script>
<script>
var worker;
document.addEventListener('DOMContentLoaded', () => {
const buffer = new ArrayBuffer(1);
const blob = new Blob([document.querySelector('#worker1').textContent], { type: 'text/javascript' });
worker = new Worker(window.URL.createObjectURL(blob));
worker.postMessage([buffer], [buffer]);
worker.onmessage = function() {document.documentElement.removeAttribute("class"); }
});
</script>
</head>
</html>

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

@ -1,3 +1,5 @@
defaults pref(dom.fs.enabled,true)
# StorageManager isn't enabled on Android
defaults skip-if(Android) pref(dom.fs.enabled,true)
load 1798773.html
load 1800470.html

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

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

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

@ -49,16 +49,28 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(WritableStream)
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_INTERFACE_MAP_END
WritableStream::WritableStream(nsIGlobalObject* aGlobal) : mGlobal(aGlobal) {
mozilla::HoldJSObjects(this);
WritableStream::WritableStream(nsIGlobalObject* aGlobal,
HoldDropJSObjectsCaller aHoldDropCaller)
: mGlobal(aGlobal), mHoldDropCaller(aHoldDropCaller) {
if (mHoldDropCaller == HoldDropJSObjectsCaller::Implicit) {
mozilla::HoldJSObjects(this);
}
}
WritableStream::WritableStream(const GlobalObject& aGlobal)
: mGlobal(do_QueryInterface(aGlobal.GetAsSupports())) {
mozilla::HoldJSObjects(this);
WritableStream::WritableStream(const GlobalObject& aGlobal,
HoldDropJSObjectsCaller aHoldDropCaller)
: mGlobal(do_QueryInterface(aGlobal.GetAsSupports())),
mHoldDropCaller(aHoldDropCaller) {
if (mHoldDropCaller == HoldDropJSObjectsCaller::Implicit) {
mozilla::HoldJSObjects(this);
}
}
WritableStream::~WritableStream() { mozilla::DropJSObjects(this); }
WritableStream::~WritableStream() {
if (mHoldDropCaller == HoldDropJSObjectsCaller::Implicit) {
mozilla::DropJSObjects(this);
}
}
JSObject* WritableStream::WrapObject(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto) {
@ -458,7 +470,8 @@ already_AddRefed<WritableStream> WritableStream::Constructor(
}
// Step 4. Perform ! InitializeWritableStream(this).
RefPtr<WritableStream> writableStream = new WritableStream(aGlobal);
RefPtr<WritableStream> writableStream =
new WritableStream(aGlobal, HoldDropJSObjectsCaller::Implicit);
// Step 5. Let sizeAlgorithm be ! ExtractSizeAlgorithm(strategy).
//
@ -693,7 +706,8 @@ already_AddRefed<WritableStream> CreateWritableStream(
// Step 2: Let stream be a new WritableStream.
// Step 3: Perform ! InitializeWritableStream(stream).
auto stream = MakeRefPtr<WritableStream>(aGlobal);
auto stream = MakeRefPtr<WritableStream>(
aGlobal, WritableStream::HoldDropJSObjectsCaller::Implicit);
// Step 4: Let controller be a new WritableStreamDefaultController.
auto controller =

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

@ -39,8 +39,16 @@ class WritableStream : public nsISupports, public nsWrapperCache {
virtual void LastRelease() {}
public:
explicit WritableStream(const GlobalObject& aGlobal);
explicit WritableStream(nsIGlobalObject* aGlobal);
// If one extends WritableStream 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 WriteableStream 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 WritableStream(const GlobalObject& aGlobal,
HoldDropJSObjectsCaller aHoldDropCaller);
explicit WritableStream(nsIGlobalObject* aGlobal,
HoldDropJSObjectsCaller aHoldDropCaller);
enum class WriterState { Writable, Closed, Erroring, Errored };
@ -188,6 +196,7 @@ class WritableStream : public nsISupports, public nsWrapperCache {
nsTArray<RefPtr<Promise>> mWriteRequests;
nsCOMPtr<nsIGlobalObject> mGlobal;
HoldDropJSObjectsCaller mHoldDropCaller;
};
MOZ_CAN_RUN_SCRIPT already_AddRefed<WritableStream> CreateWritableStream(