mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-11-03 17:58:55 +02:00
Bug 1842007 - Part 2: Replace DomPromiseListener use with Promise method in DoubleBufferQueueImpl r=dom-storage-reviewers,janv,asuth
AddCallbacksWithCycleCollectedArgs prevents potential cycle. (I'm assuming `this` and `newPage` cannot make cycle here) Also making FileSystemDirectoryIterator::Impl as refcountable to safely capture `this`. Differential Revision: https://phabricator.services.mozilla.com/D182940
This commit is contained in:
parent
030c922baf
commit
2cc2490039
6 changed files with 43 additions and 32 deletions
|
|
@ -46,7 +46,7 @@ class FileSystemDirectoryHandle final : public FileSystemHandle {
|
||||||
FileSystemHandleKind Kind() const override;
|
FileSystemHandleKind Kind() const override;
|
||||||
|
|
||||||
struct IteratorData {
|
struct IteratorData {
|
||||||
UniquePtr<FileSystemDirectoryIterator::Impl> mImpl;
|
RefPtr<FileSystemDirectoryIterator::Impl> mImpl;
|
||||||
};
|
};
|
||||||
|
|
||||||
void InitAsyncIteratorData(IteratorData& aData,
|
void InitAsyncIteratorData(IteratorData& aData,
|
||||||
|
|
|
||||||
|
|
@ -23,8 +23,8 @@ NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(FileSystemDirectoryIterator, mGlobal);
|
||||||
|
|
||||||
FileSystemDirectoryIterator::FileSystemDirectoryIterator(
|
FileSystemDirectoryIterator::FileSystemDirectoryIterator(
|
||||||
nsIGlobalObject* aGlobal, RefPtr<FileSystemManager>& aManager,
|
nsIGlobalObject* aGlobal, RefPtr<FileSystemManager>& aManager,
|
||||||
UniquePtr<Impl> aImpl)
|
RefPtr<Impl>& aImpl)
|
||||||
: mGlobal(aGlobal), mManager(aManager), mImpl(std::move(aImpl)) {}
|
: mGlobal(aGlobal), mManager(aManager), mImpl(aImpl) {}
|
||||||
|
|
||||||
// WebIDL Boilerplate
|
// WebIDL Boilerplate
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -31,9 +31,13 @@ class FileSystemDirectoryIterator : public nsISupports, public nsWrapperCache {
|
||||||
public:
|
public:
|
||||||
class Impl {
|
class Impl {
|
||||||
public:
|
public:
|
||||||
|
NS_INLINE_DECL_REFCOUNTING(Impl)
|
||||||
|
|
||||||
virtual already_AddRefed<Promise> Next(nsIGlobalObject* aGlobal,
|
virtual already_AddRefed<Promise> Next(nsIGlobalObject* aGlobal,
|
||||||
RefPtr<FileSystemManager>& aManager,
|
RefPtr<FileSystemManager>& aManager,
|
||||||
ErrorResult& aError) = 0;
|
ErrorResult& aError) = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
virtual ~Impl() = default;
|
virtual ~Impl() = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -42,7 +46,7 @@ class FileSystemDirectoryIterator : public nsISupports, public nsWrapperCache {
|
||||||
|
|
||||||
explicit FileSystemDirectoryIterator(nsIGlobalObject* aGlobal,
|
explicit FileSystemDirectoryIterator(nsIGlobalObject* aGlobal,
|
||||||
RefPtr<FileSystemManager>& aManager,
|
RefPtr<FileSystemManager>& aManager,
|
||||||
UniquePtr<Impl> aImpl);
|
RefPtr<Impl>& aImpl);
|
||||||
|
|
||||||
// WebIDL Boilerplate
|
// WebIDL Boilerplate
|
||||||
nsIGlobalObject* GetParentObject() const;
|
nsIGlobalObject* GetParentObject() const;
|
||||||
|
|
@ -61,7 +65,7 @@ class FileSystemDirectoryIterator : public nsISupports, public nsWrapperCache {
|
||||||
RefPtr<FileSystemManager> mManager;
|
RefPtr<FileSystemManager> mManager;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
UniquePtr<Impl> mImpl;
|
RefPtr<Impl> mImpl;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace dom
|
} // namespace dom
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@
|
||||||
#include "mozilla/dom/FileSystemLog.h"
|
#include "mozilla/dom/FileSystemLog.h"
|
||||||
#include "mozilla/dom/FileSystemManager.h"
|
#include "mozilla/dom/FileSystemManager.h"
|
||||||
#include "mozilla/dom/IterableIterator.h"
|
#include "mozilla/dom/IterableIterator.h"
|
||||||
|
#include "mozilla/dom/Promise-inl.h"
|
||||||
#include "mozilla/dom/Promise.h"
|
#include "mozilla/dom/Promise.h"
|
||||||
#include "mozilla/dom/PromiseNativeHandler.h"
|
#include "mozilla/dom/PromiseNativeHandler.h"
|
||||||
|
|
||||||
|
|
@ -117,9 +118,9 @@ class DoubleBufferQueueImpl
|
||||||
return promise.forget();
|
return promise.forget();
|
||||||
}
|
}
|
||||||
|
|
||||||
~DoubleBufferQueueImpl() = default;
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
~DoubleBufferQueueImpl() override = default;
|
||||||
|
|
||||||
void next(nsIGlobalObject* aGlobal, RefPtr<FileSystemManager>& aManager,
|
void next(nsIGlobalObject* aGlobal, RefPtr<FileSystemManager>& aManager,
|
||||||
RefPtr<Promise> aResult, ErrorResult& aError) {
|
RefPtr<Promise> aResult, ErrorResult& aError) {
|
||||||
LOG_VERBOSE(("next"));
|
LOG_VERBOSE(("next"));
|
||||||
|
|
@ -138,33 +139,38 @@ class DoubleBufferQueueImpl
|
||||||
|
|
||||||
auto newPage = MakeRefPtr<FileSystemEntryMetadataArray>();
|
auto newPage = MakeRefPtr<FileSystemEntryMetadataArray>();
|
||||||
|
|
||||||
RefPtr<DomPromiseListener> listener = new DomPromiseListener(
|
promise->AddCallbacksWithCycleCollectedArgs(
|
||||||
[global = nsCOMPtr<nsIGlobalObject>(aGlobal),
|
[self = RefPtr(this), newPage](
|
||||||
manager = RefPtr<FileSystemManager>(aManager), newPage, aResult,
|
JSContext*, JS::Handle<JS::Value>, ErrorResult&,
|
||||||
this](JSContext* aCx, JS::Handle<JS::Value> aValue) mutable {
|
RefPtr<FileSystemManager>& aManager, RefPtr<Promise>& aResult) {
|
||||||
MOZ_ASSERT(0u == mWithinPageIndex);
|
MOZ_ASSERT(0u == self->mWithinPageIndex);
|
||||||
MOZ_ASSERT(newPage->Length() <= PageSize);
|
MOZ_ASSERT(newPage->Length() <= PageSize);
|
||||||
|
|
||||||
const size_t startPos = mCurrentPageIsLastPage ? 0u : PageSize;
|
const size_t startPos =
|
||||||
if (mData.Length() < 2 * PageSize) {
|
self->mCurrentPageIsLastPage ? 0u : PageSize;
|
||||||
mData.InsertElementsAt(startPos, newPage->Elements(),
|
if (self->mData.Length() < 2 * PageSize) {
|
||||||
newPage->Length());
|
self->mData.InsertElementsAt(startPos, newPage->Elements(),
|
||||||
|
newPage->Length());
|
||||||
} else {
|
} else {
|
||||||
mData.ReplaceElementsAt(startPos, newPage->Length(),
|
self->mData.ReplaceElementsAt(startPos, newPage->Length(),
|
||||||
newPage->Elements(), newPage->Length());
|
newPage->Elements(),
|
||||||
|
newPage->Length());
|
||||||
}
|
}
|
||||||
MOZ_ASSERT(mData.Length() <= 2 * PageSize);
|
MOZ_ASSERT(self->mData.Length() <= 2 * PageSize);
|
||||||
mWithinPageEnd = newPage->Length();
|
self->mWithinPageEnd = newPage->Length();
|
||||||
|
|
||||||
Maybe<DataType> value;
|
Maybe<DataType> value;
|
||||||
if (0 != newPage->Length()) {
|
if (0 != newPage->Length()) {
|
||||||
nextInternal(value);
|
self->nextInternal(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
ResolveValue(global, manager, value, aResult);
|
self->ResolveValue(aResult->GetGlobalObject(), aManager, value,
|
||||||
|
aResult);
|
||||||
},
|
},
|
||||||
[aResult](nsresult aRv) { aResult->MaybeReject(aRv); });
|
[](JSContext*, JS::Handle<JS::Value> aValue, ErrorResult&,
|
||||||
promise->AppendNativeHandler(listener);
|
RefPtr<FileSystemManager>&,
|
||||||
|
RefPtr<Promise>& aResult) { aResult->MaybeReject(aValue); },
|
||||||
|
aManager, aResult);
|
||||||
|
|
||||||
FileSystemRequestHandler{}.GetEntries(aManager, mEntryId, mPageNumber,
|
FileSystemRequestHandler{}.GetEntries(aManager, mEntryId, mPageNumber,
|
||||||
promise, newPage, aError);
|
promise, newPage, aError);
|
||||||
|
|
@ -218,20 +224,21 @@ using UnderlyingQueue = DoubleBufferQueueImpl<ValueResolver<Type>>;
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
UniquePtr<mozilla::dom::FileSystemDirectoryIterator::Impl>
|
already_AddRefed<mozilla::dom::FileSystemDirectoryIterator::Impl>
|
||||||
FileSystemDirectoryIteratorFactory::Create(
|
FileSystemDirectoryIteratorFactory::Create(
|
||||||
const FileSystemEntryMetadata& aMetadata,
|
const FileSystemEntryMetadata& aMetadata,
|
||||||
IterableIteratorBase::IteratorType aType) {
|
IterableIteratorBase::IteratorType aType) {
|
||||||
if (IterableIteratorBase::Entries == aType) {
|
if (IterableIteratorBase::Entries == aType) {
|
||||||
return MakeUnique<UnderlyingQueue<IterableIteratorBase::Entries>>(
|
return MakeAndAddRef<UnderlyingQueue<IterableIteratorBase::Entries>>(
|
||||||
aMetadata);
|
aMetadata);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IterableIteratorBase::Values == aType) {
|
if (IterableIteratorBase::Values == aType) {
|
||||||
return MakeUnique<UnderlyingQueue<IterableIteratorBase::Values>>(aMetadata);
|
return MakeAndAddRef<UnderlyingQueue<IterableIteratorBase::Values>>(
|
||||||
|
aMetadata);
|
||||||
}
|
}
|
||||||
|
|
||||||
return MakeUnique<UnderlyingQueue<IterableIteratorBase::Keys>>(aMetadata);
|
return MakeAndAddRef<UnderlyingQueue<IterableIteratorBase::Keys>>(aMetadata);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace mozilla::dom::fs
|
} // namespace mozilla::dom::fs
|
||||||
|
|
|
||||||
|
|
@ -14,9 +14,9 @@ namespace mozilla::dom::fs {
|
||||||
class FileSystemEntryMetadata;
|
class FileSystemEntryMetadata;
|
||||||
|
|
||||||
struct FileSystemDirectoryIteratorFactory {
|
struct FileSystemDirectoryIteratorFactory {
|
||||||
static UniquePtr<mozilla::dom::FileSystemDirectoryIterator::Impl> Create(
|
static already_AddRefed<mozilla::dom::FileSystemDirectoryIterator::Impl>
|
||||||
const FileSystemEntryMetadata& aMetadata,
|
Create(const FileSystemEntryMetadata& aMetadata,
|
||||||
IterableIteratorBase::IteratorType aType);
|
IterableIteratorBase::IteratorType aType);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace mozilla::dom::fs
|
} // namespace mozilla::dom::fs
|
||||||
|
|
|
||||||
|
|
@ -89,7 +89,7 @@ TEST_F(TestFileSystemDirectoryHandle, isNextPromiseReturned) {
|
||||||
|
|
||||||
ASSERT_TRUE(dirHandle);
|
ASSERT_TRUE(dirHandle);
|
||||||
|
|
||||||
auto mockIter = MakeUnique<MockFileSystemDirectoryIteratorImpl>();
|
auto mockIter = MakeRefPtr<MockFileSystemDirectoryIteratorImpl>();
|
||||||
IgnoredErrorResult error;
|
IgnoredErrorResult error;
|
||||||
EXPECT_CALL(*mockIter, Next(_, _, _))
|
EXPECT_CALL(*mockIter, Next(_, _, _))
|
||||||
.WillOnce(::testing::Return(Promise::Create(mGlobal, error)));
|
.WillOnce(::testing::Return(Promise::Create(mGlobal, error)));
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue