Backed out 3 changesets (bug 1600906) for bustage on StaticAnalysisFunctions.h. CLOSED TREE

Backed out changeset aae2faf1907c (bug 1600906)
Backed out changeset d61a65e2e4ac (bug 1600906)
Backed out changeset a114b9b8e6ea (bug 1600906)
This commit is contained in:
Csoregi Natalia 2020-01-10 17:19:22 +02:00
Родитель 1c1943da7f
Коммит 8c7b4f143a
16 изменённых файлов: 1526 добавлений и 2032 удалений

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

@ -1276,48 +1276,19 @@ void DispatchFileHandleSuccessEvent(FileHandleResultHelper* aResultHelper) {
MOZ_ASSERT(fileHandle->IsOpen() || fileHandle->IsAborted());
}
auto GetKeyOperator(const IDBCursorDirection aDirection) {
auto GetKeyOperator(const IDBCursor::Direction aDirection) {
switch (aDirection) {
case IDBCursorDirection::Next:
case IDBCursorDirection::Nextunique:
case IDBCursor::Direction::Next:
case IDBCursor::Direction::NextUnique:
return &Key::operator>=;
case IDBCursorDirection::Prev:
case IDBCursorDirection::Prevunique:
case IDBCursor::Direction::Prev:
case IDBCursor::Direction::PrevUnique:
return &Key::operator<=;
default:
MOZ_CRASH("Should never get here.");
}
}
// Does not need to be threadsafe since this only runs on one thread, but
// inheriting from CancelableRunnable is easy.
template <typename T>
class DelayedActionRunnable final : public CancelableRunnable {
using ActionFunc = void (T::*)();
T* mActor;
RefPtr<IDBRequest> mRequest;
ActionFunc mActionFunc;
public:
explicit DelayedActionRunnable(T* aActor, ActionFunc aActionFunc)
: CancelableRunnable("indexedDB::DelayedActionRunnable"),
mActor(aActor),
mRequest(aActor->GetRequest()),
mActionFunc(aActionFunc) {
MOZ_ASSERT(aActor);
aActor->AssertIsOnOwningThread();
MOZ_ASSERT(mRequest);
MOZ_ASSERT(mActionFunc);
}
private:
~DelayedActionRunnable() = default;
NS_DECL_NSIRUNNABLE
nsresult Cancel() override;
};
} // namespace
/*******************************************************************************
@ -2367,7 +2338,7 @@ bool BackgroundTransactionChild::DeallocPBackgroundIDBCursorChild(
PBackgroundIDBCursorChild* aActor) {
MOZ_ASSERT(aActor);
delete aActor;
delete static_cast<BackgroundCursorChild*>(aActor);
return true;
}
@ -2485,7 +2456,7 @@ bool BackgroundVersionChangeTransactionChild::DeallocPBackgroundIDBCursorChild(
PBackgroundIDBCursorChild* aActor) {
MOZ_ASSERT(aActor);
delete aActor;
delete static_cast<BackgroundCursorChild*>(aActor);
return true;
}
@ -3207,37 +3178,102 @@ BackgroundRequestChild::PreprocessHelper::OnFileMetadataReady(
* BackgroundCursorChild
******************************************************************************/
BackgroundCursorChildBase::BackgroundCursorChildBase(IDBRequest* const aRequest,
const Direction aDirection)
BackgroundCursorChild::CachedResponse::CachedResponse(
Key aKey, StructuredCloneReadInfo&& aCloneInfo)
: mKey{std::move(aKey)}, mCloneInfo{std::move(aCloneInfo)} {}
BackgroundCursorChild::CachedResponse::CachedResponse(
Key aKey, Key aLocaleAwareKey, Key aObjectStoreKey,
StructuredCloneReadInfo&& aCloneInfo)
: mKey{std::move(aKey)},
mLocaleAwareKey{std::move(aLocaleAwareKey)},
mObjectStoreKey{std::move(aObjectStoreKey)},
mCloneInfo{std::move(aCloneInfo)} {}
BackgroundCursorChild::CachedResponse::CachedResponse(Key aKey)
: mKey{std::move(aKey)} {}
BackgroundCursorChild::CachedResponse::CachedResponse(Key aKey,
Key aLocaleAwareKey,
Key aObjectStoreKey)
: mKey{std::move(aKey)},
mLocaleAwareKey{std::move(aLocaleAwareKey)},
mObjectStoreKey{std::move(aObjectStoreKey)} {}
// Does not need to be threadsafe since this only runs on one thread, but
// inheriting from CancelableRunnable is easy.
class BackgroundCursorChild::DelayedActionRunnable final
: public CancelableRunnable {
using ActionFunc = void (BackgroundCursorChild::*)();
BackgroundCursorChild* mActor;
RefPtr<IDBRequest> mRequest;
ActionFunc mActionFunc;
public:
explicit DelayedActionRunnable(BackgroundCursorChild* aActor,
ActionFunc aActionFunc)
: CancelableRunnable(
"indexedDB::BackgroundCursorChild::DelayedActionRunnable"),
mActor(aActor),
mRequest(aActor->mRequest),
mActionFunc(aActionFunc) {
MOZ_ASSERT(aActor);
aActor->AssertIsOnOwningThread();
MOZ_ASSERT(mRequest);
MOZ_ASSERT(mActionFunc);
}
private:
~DelayedActionRunnable() = default;
NS_DECL_NSIRUNNABLE
nsresult Cancel() override;
};
BackgroundCursorChild::BackgroundCursorChild(IDBRequest* aRequest,
IDBObjectStore* aObjectStore,
Direction aDirection)
: mRequest(aRequest),
mTransaction(aRequest->GetTransaction()),
mStrongRequest(aRequest),
mDirection(aDirection) {
MOZ_ASSERT(mTransaction);
}
template <IDBCursorType CursorType>
BackgroundCursorChild<CursorType>::BackgroundCursorChild(IDBRequest* aRequest,
SourceType* aSource,
Direction aDirection)
: BackgroundCursorChildBase(aRequest, aDirection),
mSource(aSource),
mObjectStore(aObjectStore),
mIndex(nullptr),
mCursor(nullptr),
mStrongRequest(aRequest),
mDirection(aDirection),
mInFlightResponseInvalidationNeeded(false) {
aSource->AssertIsOnOwningThread();
MOZ_ASSERT(aObjectStore);
aObjectStore->AssertIsOnOwningThread();
MOZ_ASSERT(mTransaction);
MOZ_COUNT_CTOR(indexedDB::BackgroundCursorChild<CursorType>);
MOZ_COUNT_CTOR(indexedDB::BackgroundCursorChild);
}
template <IDBCursorType CursorType>
BackgroundCursorChild<CursorType>::~BackgroundCursorChild() {
MOZ_COUNT_DTOR(indexedDB::BackgroundCursorChild<CursorType>);
BackgroundCursorChild::BackgroundCursorChild(IDBRequest* aRequest,
IDBIndex* aIndex,
Direction aDirection)
: mRequest(aRequest),
mTransaction(aRequest->GetTransaction()),
mObjectStore(nullptr),
mIndex(aIndex),
mCursor(nullptr),
mStrongRequest(aRequest),
mDirection(aDirection),
mInFlightResponseInvalidationNeeded(false) {
MOZ_ASSERT(aIndex);
aIndex->AssertIsOnOwningThread();
MOZ_ASSERT(mTransaction);
MOZ_COUNT_CTOR(indexedDB::BackgroundCursorChild);
}
template <IDBCursorType CursorType>
void BackgroundCursorChild<CursorType>::SendContinueInternal(
const CursorRequestParams& aParams,
const CursorData<CursorType>& aCurrentData) {
BackgroundCursorChild::~BackgroundCursorChild() {
MOZ_COUNT_DTOR(indexedDB::BackgroundCursorChild);
}
void BackgroundCursorChild::SendContinueInternal(
const CursorRequestParams& aParams, const Key& aCurrentKey,
const Key& aCurrentObjectStoreKey) {
AssertIsOnOwningThread();
MOZ_ASSERT(mRequest);
MOZ_ASSERT(mTransaction);
@ -3248,18 +3284,14 @@ void BackgroundCursorChild<CursorType>::SendContinueInternal(
// Make sure all our DOM objects stay alive.
mStrongCursor = mCursor;
MOZ_ASSERT(GetRequest()->ReadyState() == IDBRequestReadyState::Done);
GetRequest()->Reset();
MOZ_ASSERT(mRequest->ReadyState() == IDBRequestReadyState::Done);
mRequest->Reset();
mTransaction->OnNewRequest();
CursorRequestParams params = aParams;
Key currentKey = aCurrentData.mKey;
Key currentObjectStoreKey;
// TODO: This is still not nice.
if constexpr (!CursorTypeTraits<CursorType>::IsObjectStoreCursor) {
currentObjectStoreKey = aCurrentData.mObjectStoreKey;
}
Key currentKey = aCurrentKey;
Key currentObjectStoreKey = aCurrentObjectStoreKey;
switch (params.type()) {
case CursorRequestParams::TContinueParams: {
@ -3273,14 +3305,15 @@ void BackgroundCursorChild<CursorType>::SendContinueInternal(
[&key, isLocaleAware = mCursor->IsLocaleAware(),
keyOperator = GetKeyOperator(mDirection),
transactionSerialNumber = mTransaction->LoggingSerialNumber(),
requestSerialNumber = GetRequest()->LoggingSerialNumber()](
requestSerialNumber = mRequest->LoggingSerialNumber()](
const auto& currentCachedResponse) {
// This duplicates the logic from the parent. We could avoid this
// duplication if we invalidated the cached records always for any
// continue-with-key operation, but would lose the benefits of
// preloading then.
const auto& cachedSortKey =
currentCachedResponse.GetSortKey(isLocaleAware);
isLocaleAware ? currentCachedResponse.mLocaleAwareKey
: currentCachedResponse.mKey;
const bool discard = !(cachedSortKey.*keyOperator)(key);
if (discard) {
IDB_LOG_MARK_CHILD_TRANSACTION_REQUEST(
@ -3288,7 +3321,7 @@ void BackgroundCursorChild<CursorType>::SendContinueInternal(
"Continue, discarding", transactionSerialNumber,
requestSerialNumber, key.GetBuffer().get(),
cachedSortKey.GetBuffer().get(),
currentCachedResponse.GetObjectStoreKeyForLogging());
currentCachedResponse.mObjectStoreKey.GetBuffer().get());
} else {
IDB_LOG_MARK_CHILD_TRANSACTION_REQUEST(
"PRELOAD: Continue to key %s, keeping cached key %s/%s and "
@ -3296,7 +3329,7 @@ void BackgroundCursorChild<CursorType>::SendContinueInternal(
"Continue, keeping", transactionSerialNumber,
requestSerialNumber, key.GetBuffer().get(),
cachedSortKey.GetBuffer().get(),
currentCachedResponse.GetObjectStoreKeyForLogging());
currentCachedResponse.mObjectStoreKey.GetBuffer().get());
}
return discard;
@ -3306,61 +3339,56 @@ void BackgroundCursorChild<CursorType>::SendContinueInternal(
}
case CursorRequestParams::TContinuePrimaryKeyParams: {
if constexpr (!CursorTypeTraits<CursorType>::IsObjectStoreCursor) {
const auto& key = params.get_ContinuePrimaryKeyParams().key();
const auto& primaryKey =
params.get_ContinuePrimaryKeyParams().primaryKey();
if (key.IsUnset() || primaryKey.IsUnset()) {
break;
}
// Discard cache entries before the target key.
DiscardCachedResponses([&key, &primaryKey,
isLocaleAware = mCursor->IsLocaleAware(),
keyCompareOperator = GetKeyOperator(mDirection),
transactionSerialNumber =
mTransaction->LoggingSerialNumber(),
requestSerialNumber =
GetRequest()->LoggingSerialNumber()](
const auto& currentCachedResponse) {
// This duplicates the logic from the parent. We could avoid this
// duplication if we invalidated the cached records always for any
// continue-with-key operation, but would lose the benefits of
// preloading then.
const auto& cachedSortKey =
currentCachedResponse.GetSortKey(isLocaleAware);
const auto& cachedSortPrimaryKey =
currentCachedResponse.mObjectStoreKey;
const bool discard =
(cachedSortKey == key &&
!(cachedSortPrimaryKey.*keyCompareOperator)(primaryKey)) ||
!(cachedSortKey.*keyCompareOperator)(key);
if (discard) {
IDB_LOG_MARK_CHILD_TRANSACTION_REQUEST(
"PRELOAD: Continue to key %s with primary key %s, discarding "
"cached key %s with cached primary key %s",
"Continue, discarding", transactionSerialNumber,
requestSerialNumber, key.GetBuffer().get(),
primaryKey.GetBuffer().get(), cachedSortKey.GetBuffer().get(),
cachedSortPrimaryKey.GetBuffer().get());
} else {
IDB_LOG_MARK_CHILD_TRANSACTION_REQUEST(
"PRELOAD: Continue to key %s with primary key %s, keeping "
"cached key %s with cached primary key %s and further",
"Continue, keeping", transactionSerialNumber,
requestSerialNumber, key.GetBuffer().get(),
primaryKey.GetBuffer().get(), cachedSortKey.GetBuffer().get(),
cachedSortPrimaryKey.GetBuffer().get());
}
return discard;
});
} else {
MOZ_CRASH("Shouldn't get here");
const auto& key = params.get_ContinuePrimaryKeyParams().key();
const auto& primaryKey =
params.get_ContinuePrimaryKeyParams().primaryKey();
if (key.IsUnset() || primaryKey.IsUnset()) {
break;
}
// Discard cache entries before the target key.
DiscardCachedResponses(
[&key, &primaryKey, isLocaleAware = mCursor->IsLocaleAware(),
keyCompareOperator = GetKeyOperator(mDirection),
transactionSerialNumber = mTransaction->LoggingSerialNumber(),
requestSerialNumber = mRequest->LoggingSerialNumber()](
const auto& currentCachedResponse) {
// This duplicates the logic from the parent. We could avoid this
// duplication if we invalidated the cached records always for any
// continue-with-key operation, but would lose the benefits of
// preloading then.
const auto& cachedSortKey =
isLocaleAware ? currentCachedResponse.mLocaleAwareKey
: currentCachedResponse.mKey;
const auto& cachedSortPrimaryKey =
currentCachedResponse.mObjectStoreKey;
const bool discard =
(cachedSortKey == key &&
!(cachedSortPrimaryKey.*keyCompareOperator)(primaryKey)) ||
!(cachedSortKey.*keyCompareOperator)(key);
if (discard) {
IDB_LOG_MARK_CHILD_TRANSACTION_REQUEST(
"PRELOAD: Continue to key %s with primary key %s, discarding "
"cached key %s with cached primary key %s",
"Continue, discarding", transactionSerialNumber,
requestSerialNumber, key.GetBuffer().get(),
primaryKey.GetBuffer().get(), cachedSortKey.GetBuffer().get(),
cachedSortPrimaryKey.GetBuffer().get());
} else {
IDB_LOG_MARK_CHILD_TRANSACTION_REQUEST(
"PRELOAD: Continue to key %s with primary key %s, keeping "
"cached key %s with cached primary key %s and further",
"Continue, keeping", transactionSerialNumber,
requestSerialNumber, key.GetBuffer().get(),
primaryKey.GetBuffer().get(), cachedSortKey.GetBuffer().get(),
cachedSortPrimaryKey.GetBuffer().get());
}
return discard;
});
break;
}
@ -3368,28 +3396,24 @@ void BackgroundCursorChild<CursorType>::SendContinueInternal(
uint32_t& advanceCount = params.get_AdvanceParams().count();
IDB_LOG_MARK_CHILD_TRANSACTION_REQUEST(
"PRELOAD: Advancing %" PRIu32 " records", "Advancing",
mTransaction->LoggingSerialNumber(),
GetRequest()->LoggingSerialNumber(), advanceCount);
mTransaction->LoggingSerialNumber(), mRequest->LoggingSerialNumber(),
advanceCount);
// Discard cache entries.
DiscardCachedResponses([&advanceCount, &currentKey,
&currentObjectStoreKey](
const auto& currentCachedResponse) {
const bool res = advanceCount > 1;
if (res) {
--advanceCount;
DiscardCachedResponses(
[&advanceCount, &currentKey,
&currentObjectStoreKey](const auto& currentCachedResponse) {
const bool res = advanceCount > 1;
if (res) {
--advanceCount;
// TODO: We only need to update currentKey on the last entry, the
// others are overwritten in the next iteration anyway.
currentKey = currentCachedResponse.mKey;
if constexpr (!CursorTypeTraits<CursorType>::IsObjectStoreCursor) {
currentObjectStoreKey = currentCachedResponse.mObjectStoreKey;
} else {
Unused << currentObjectStoreKey;
}
}
return res;
});
// TODO: We only need to update currentKey on the last entry, the
// others are overwritten in the next iteration anyway.
currentKey = currentCachedResponse.mKey;
currentObjectStoreKey = currentCachedResponse.mObjectStoreKey;
}
return res;
});
break;
}
@ -3409,8 +3433,8 @@ void BackgroundCursorChild<CursorType>::SendContinueInternal(
// This is accompanied by invalidating cached entries at proper locations to
// make it correct. To avoid this, further changes are necessary, see Bug
// 1580499.
MOZ_ALWAYS_SUCCEEDS(NS_DispatchToCurrentThread(
MakeAndAddRef<DelayedActionRunnable<BackgroundCursorChild<CursorType>>>(
MOZ_ALWAYS_SUCCEEDS(
NS_DispatchToCurrentThread(MakeAndAddRef<DelayedActionRunnable>(
this, &BackgroundCursorChild::CompleteContinueRequestFromCache)));
// TODO: Could we preload further entries in the background when the size of
@ -3422,44 +3446,58 @@ void BackgroundCursorChild<CursorType>::SendContinueInternal(
}
}
template <IDBCursorType CursorType>
void BackgroundCursorChild<CursorType>::CompleteContinueRequestFromCache() {
void BackgroundCursorChild::CompleteContinueRequestFromCache() {
AssertIsOnOwningThread();
MOZ_ASSERT(mTransaction);
MOZ_ASSERT(mCursor);
MOZ_ASSERT(mStrongCursor);
MOZ_ASSERT(!mDelayedResponses.empty());
MOZ_ASSERT(mCursor->GetType() == CursorType);
const RefPtr<IDBCursor> cursor = std::move(mStrongCursor);
mCursor->Reset(std::move(mDelayedResponses.front()));
auto& item = mDelayedResponses.front();
switch (mCursor->GetType()) {
case IDBCursor::Type::ObjectStore:
mCursor->Reset(std::move(item.mKey), std::move(item.mCloneInfo));
break;
case IDBCursor::Type::Index:
mCursor->Reset(std::move(item.mKey), std::move(item.mLocaleAwareKey),
std::move(item.mObjectStoreKey),
std::move(item.mCloneInfo));
break;
case IDBCursor::Type::ObjectStoreKey:
mCursor->Reset(std::move(item.mKey));
break;
case IDBCursor::Type::IndexKey:
mCursor->Reset(std::move(item.mKey), std::move(item.mLocaleAwareKey),
std::move(item.mObjectStoreKey));
break;
default:
MOZ_CRASH("Should never get here.");
}
mDelayedResponses.pop_front();
IDB_LOG_MARK_CHILD_TRANSACTION_REQUEST(
"PRELOAD: Consumed 1 cached response, %zu cached responses remaining",
"Consumed cached response", mTransaction->LoggingSerialNumber(),
GetRequest()->LoggingSerialNumber(),
mRequest->LoggingSerialNumber(),
mDelayedResponses.size() + mCachedResponses.size());
ResultHelper helper(GetRequest(), mTransaction, cursor);
ResultHelper helper(mRequest, mTransaction, cursor);
DispatchSuccessEvent(&helper);
mTransaction->OnRequestFinished(/* aRequestCompletedSuccessfully */ true);
}
template <IDBCursorType CursorType>
void BackgroundCursorChild<CursorType>::SendDeleteMeInternal() {
void BackgroundCursorChild::SendDeleteMeInternal() {
AssertIsOnOwningThread();
MOZ_ASSERT(!mStrongRequest);
MOZ_ASSERT(!mStrongCursor);
mRequest.reset();
mRequest = nullptr;
mTransaction = nullptr;
// TODO: The things until here could be pulled up to
// BackgroundCursorChildBase.
mSource.reset();
mObjectStore = nullptr;
mIndex = nullptr;
if (mCursor) {
mCursor->ClearBackgroundActor();
@ -3469,8 +3507,7 @@ void BackgroundCursorChild<CursorType>::SendDeleteMeInternal() {
}
}
template <IDBCursorType CursorType>
void BackgroundCursorChild<CursorType>::InvalidateCachedResponses() {
void BackgroundCursorChild::InvalidateCachedResponses() {
AssertIsOnOwningThread();
MOZ_ASSERT(mTransaction);
MOZ_ASSERT(mRequest);
@ -3483,7 +3520,7 @@ void BackgroundCursorChild<CursorType>::InvalidateCachedResponses() {
IDB_LOG_MARK_CHILD_TRANSACTION_REQUEST(
"PRELOAD: Invalidating all %zu cached responses", "Invalidating",
mTransaction->LoggingSerialNumber(), GetRequest()->LoggingSerialNumber(),
mTransaction->LoggingSerialNumber(), mRequest->LoggingSerialNumber(),
mCachedResponses.size());
mCachedResponses.clear();
@ -3496,16 +3533,14 @@ void BackgroundCursorChild<CursorType>::InvalidateCachedResponses() {
IDB_LOG_MARK_CHILD_TRANSACTION_REQUEST(
"PRELOAD: Setting flag to invalidate in-flight responses",
"Set flag to invalidate in-flight responses",
mTransaction->LoggingSerialNumber(),
GetRequest()->LoggingSerialNumber());
mTransaction->LoggingSerialNumber(), mRequest->LoggingSerialNumber());
mInFlightResponseInvalidationNeeded = true;
}
}
template <IDBCursorType CursorType>
template <typename Condition>
void BackgroundCursorChild<CursorType>::DiscardCachedResponses(
void BackgroundCursorChild::DiscardCachedResponses(
const Condition& aConditionFunc) {
size_t discardedCount = 0;
while (!mCachedResponses.empty() &&
@ -3515,11 +3550,11 @@ void BackgroundCursorChild<CursorType>::DiscardCachedResponses(
}
IDB_LOG_MARK_CHILD_TRANSACTION_REQUEST(
"PRELOAD: Discarded %zu cached responses, %zu remaining", "Discarded",
mTransaction->LoggingSerialNumber(), GetRequest()->LoggingSerialNumber(),
mTransaction->LoggingSerialNumber(), mRequest->LoggingSerialNumber(),
discardedCount, mCachedResponses.size());
}
void BackgroundCursorChildBase::HandleResponse(nsresult aResponse) {
void BackgroundCursorChild::HandleResponse(nsresult aResponse) {
AssertIsOnOwningThread();
MOZ_ASSERT(NS_FAILED(aResponse));
MOZ_ASSERT(NS_ERROR_GET_MODULE(aResponse) == NS_ERROR_MODULE_DOM_INDEXEDDB);
@ -3528,12 +3563,10 @@ void BackgroundCursorChildBase::HandleResponse(nsresult aResponse) {
MOZ_ASSERT(!mStrongRequest);
MOZ_ASSERT(!mStrongCursor);
DispatchErrorEvent(GetRequest(), aResponse, mTransaction);
DispatchErrorEvent(mRequest, aResponse, mTransaction);
}
template <IDBCursorType CursorType>
void BackgroundCursorChild<CursorType>::HandleResponse(
const void_t& aResponse) {
void BackgroundCursorChild::HandleResponse(const void_t& aResponse) {
AssertIsOnOwningThread();
MOZ_ASSERT(mRequest);
MOZ_ASSERT(mTransaction);
@ -3544,25 +3577,23 @@ void BackgroundCursorChild<CursorType>::HandleResponse(
mCursor->Reset();
}
ResultHelper helper(GetRequest(), mTransaction, &JS::NullHandleValue);
ResultHelper helper(mRequest, mTransaction, &JS::NullHandleValue);
DispatchSuccessEvent(&helper);
if (!mCursor) {
MOZ_ALWAYS_SUCCEEDS(this->GetActorEventTarget()->Dispatch(
MakeAndAddRef<DelayedActionRunnable<BackgroundCursorChild<CursorType>>>(
MakeAndAddRef<DelayedActionRunnable>(
this, &BackgroundCursorChild::SendDeleteMeInternal),
NS_DISPATCH_NORMAL));
}
}
template <IDBCursorType CursorType>
template <typename... Args>
RefPtr<IDBCursor>
BackgroundCursorChild<CursorType>::HandleIndividualCursorResponse(
RefPtr<IDBCursor> BackgroundCursorChild::HandleIndividualCursorResponse(
const bool aUseAsCurrentResult, Args&&... aArgs) {
if (mCursor) {
if (aUseAsCurrentResult) {
mCursor->Reset(CursorData<CursorType>{std::forward<Args>(aArgs)...});
mCursor->Reset(std::forward<Args>(aArgs)...);
} else {
mCachedResponses.emplace_back(std::forward<Args>(aArgs)...);
}
@ -3571,16 +3602,15 @@ BackgroundCursorChild<CursorType>::HandleIndividualCursorResponse(
MOZ_ASSERT(aUseAsCurrentResult);
// TODO: This still looks quite dangerous to me. Why is mCursor not a
// RefPtr?
auto newCursor = IDBCursor::Create(this, std::forward<Args>(aArgs)...);
// TODO: This still looks quite dangerous to me. Why is mCursor not a RefPtr?
RefPtr<IDBCursor> newCursor =
IDBCursor::Create(this, std::forward<Args>(aArgs)...);
mCursor = newCursor;
return newCursor;
}
template <IDBCursorType CursorType>
template <typename T, typename Func>
void BackgroundCursorChild<CursorType>::HandleMultipleCursorResponses(
void BackgroundCursorChild::HandleMultipleCursorResponses(
const nsTArray<T>& aResponses, const Func& aHandleRecord) {
AssertIsOnOwningThread();
MOZ_ASSERT(mRequest);
@ -3591,7 +3621,7 @@ void BackgroundCursorChild<CursorType>::HandleMultipleCursorResponses(
IDB_LOG_MARK_CHILD_TRANSACTION_REQUEST(
"PRELOAD: Received %zu cursor responses", "Received",
mTransaction->LoggingSerialNumber(), GetRequest()->LoggingSerialNumber(),
mTransaction->LoggingSerialNumber(), mRequest->LoggingSerialNumber(),
aResponses.Length());
MOZ_ASSERT_IF(aResponses.Length() > 1, mCachedResponses.empty());
@ -3606,14 +3636,14 @@ void BackgroundCursorChild<CursorType>::HandleMultipleCursorResponses(
for (auto& response : responses) {
IDB_LOG_MARK_CHILD_TRANSACTION_REQUEST(
"PRELOAD: Processing response for key %s", "Processing",
mTransaction->LoggingSerialNumber(),
GetRequest()->LoggingSerialNumber(), response.key().GetBuffer().get());
mTransaction->LoggingSerialNumber(), mRequest->LoggingSerialNumber(),
response.key().GetBuffer().get());
// TODO: At the moment, we only send a cursor request to the parent if
// requested by the user code. Therefore, the first result is always used
// as the current result, and the potential extra results are cached. If
// we extended this towards preloading in the background, all results
// might need to be cached.
// requested by the user code. Therefore, the first result is always used as
// the current result, and the potential extra results are cached. If we
// extended this towards preloading in the background, all results might
// need to be cached.
auto maybeNewCursor =
aHandleRecord(/* aUseAsCurrentResult */ isFirst, response);
if (maybeNewCursor) {
@ -3627,29 +3657,29 @@ void BackgroundCursorChild<CursorType>::HandleMultipleCursorResponses(
"PRELOAD: Discarding remaining responses since "
"mInFlightResponseInvalidationNeeded is set",
"Discarding responses", mTransaction->LoggingSerialNumber(),
GetRequest()->LoggingSerialNumber());
mRequest->LoggingSerialNumber());
mInFlightResponseInvalidationNeeded = false;
break;
}
}
ResultHelper helper(GetRequest(), mTransaction, mCursor);
ResultHelper helper(mRequest, mTransaction, mCursor);
DispatchSuccessEvent(&helper);
}
template <IDBCursorType CursorType>
void BackgroundCursorChild<CursorType>::HandleResponse(
void BackgroundCursorChild::HandleResponse(
const nsTArray<ObjectStoreCursorResponse>& aResponses) {
AssertIsOnOwningThread();
MOZ_ASSERT(mObjectStore);
MOZ_ASSERT(mTransaction);
HandleMultipleCursorResponses(
aResponses, [this](const bool useAsCurrentResult,
ObjectStoreCursorResponse& response) {
// TODO: Maybe move the deserialization of the clone-read-info into
// the cursor, so that it is only done for records actually accessed,
// which might not be the case for all cached records.
// TODO: Maybe move the deserialization of the clone-read-info into the
// cursor, so that it is only done for records actually accessed, which
// might not be the case for all cached records.
return HandleIndividualCursorResponse(
useAsCurrentResult, std::move(response.key()),
DeserializeStructuredCloneReadInfo(std::move(response.cloneInfo()),
@ -3657,10 +3687,10 @@ void BackgroundCursorChild<CursorType>::HandleResponse(
});
}
template <IDBCursorType CursorType>
void BackgroundCursorChild<CursorType>::HandleResponse(
void BackgroundCursorChild::HandleResponse(
const nsTArray<ObjectStoreKeyCursorResponse>& aResponses) {
AssertIsOnOwningThread();
MOZ_ASSERT(mObjectStore);
HandleMultipleCursorResponses(
aResponses, [this](const bool useAsCurrentResult,
@ -3670,10 +3700,10 @@ void BackgroundCursorChild<CursorType>::HandleResponse(
});
}
template <IDBCursorType CursorType>
void BackgroundCursorChild<CursorType>::HandleResponse(
void BackgroundCursorChild::HandleResponse(
const nsTArray<IndexCursorResponse>& aResponses) {
AssertIsOnOwningThread();
MOZ_ASSERT(mIndex);
MOZ_ASSERT(mTransaction);
HandleMultipleCursorResponses(
@ -3687,11 +3717,10 @@ void BackgroundCursorChild<CursorType>::HandleResponse(
});
}
template <IDBCursorType CursorType>
void BackgroundCursorChild<CursorType>::HandleResponse(
void BackgroundCursorChild::HandleResponse(
const nsTArray<IndexKeyCursorResponse>& aResponses) {
AssertIsOnOwningThread();
static_assert(!CursorTypeTraits<CursorType>::IsObjectStoreCursor);
MOZ_ASSERT(mIndex);
HandleMultipleCursorResponses(
aResponses,
@ -3702,8 +3731,7 @@ void BackgroundCursorChild<CursorType>::HandleResponse(
});
}
template <IDBCursorType CursorType>
void BackgroundCursorChild<CursorType>::ActorDestroy(ActorDestroyReason aWhy) {
void BackgroundCursorChild::ActorDestroy(ActorDestroyReason aWhy) {
AssertIsOnOwningThread();
MOZ_ASSERT_IF(aWhy == Deletion, !mStrongRequest);
MOZ_ASSERT_IF(aWhy == Deletion, !mStrongCursor);
@ -3723,14 +3751,14 @@ void BackgroundCursorChild<CursorType>::ActorDestroy(ActorDestroyReason aWhy) {
}
#ifdef DEBUG
mRequest.maybeReset();
mRequest = nullptr;
mTransaction = nullptr;
mSource.maybeReset();
mObjectStore = nullptr;
mIndex = nullptr;
#endif
}
template <IDBCursorType CursorType>
mozilla::ipc::IPCResult BackgroundCursorChild<CursorType>::RecvResponse(
mozilla::ipc::IPCResult BackgroundCursorChild::RecvResponse(
const CursorResponse& aResponse) {
AssertIsOnOwningThread();
MOZ_ASSERT(aResponse.type() != CursorResponse::T__None);
@ -3758,35 +3786,19 @@ mozilla::ipc::IPCResult BackgroundCursorChild<CursorType>::RecvResponse(
break;
case CursorResponse::TArrayOfObjectStoreCursorResponse:
if constexpr (CursorType == IDBCursorType::ObjectStore) {
HandleResponse(aResponse.get_ArrayOfObjectStoreCursorResponse());
} else {
MOZ_CRASH("Response type mismatch");
}
HandleResponse(aResponse.get_ArrayOfObjectStoreCursorResponse());
break;
case CursorResponse::TArrayOfObjectStoreKeyCursorResponse:
if constexpr (CursorType == IDBCursorType::ObjectStoreKey) {
HandleResponse(aResponse.get_ArrayOfObjectStoreKeyCursorResponse());
} else {
MOZ_CRASH("Response type mismatch");
}
HandleResponse(aResponse.get_ArrayOfObjectStoreKeyCursorResponse());
break;
case CursorResponse::TArrayOfIndexCursorResponse:
if constexpr (CursorType == IDBCursorType::Index) {
HandleResponse(aResponse.get_ArrayOfIndexCursorResponse());
} else {
MOZ_CRASH("Response type mismatch");
}
HandleResponse(aResponse.get_ArrayOfIndexCursorResponse());
break;
case CursorResponse::TArrayOfIndexKeyCursorResponse:
if constexpr (CursorType == IDBCursorType::IndexKey) {
HandleResponse(aResponse.get_ArrayOfIndexKeyCursorResponse());
} else {
MOZ_CRASH("Response type mismatch");
}
HandleResponse(aResponse.get_ArrayOfIndexKeyCursorResponse());
break;
default:
@ -3798,8 +3810,8 @@ mozilla::ipc::IPCResult BackgroundCursorChild<CursorType>::RecvResponse(
return IPC_OK();
}
template <typename T>
NS_IMETHODIMP DelayedActionRunnable<T>::Run() {
NS_IMETHODIMP
BackgroundCursorChild::DelayedActionRunnable::Run() {
MOZ_ASSERT(mActor);
mActor->AssertIsOnOwningThread();
MOZ_ASSERT(mRequest);
@ -3813,8 +3825,7 @@ NS_IMETHODIMP DelayedActionRunnable<T>::Run() {
return NS_OK;
}
template <typename T>
nsresult DelayedActionRunnable<T>::Cancel() {
nsresult BackgroundCursorChild::DelayedActionRunnable::Cancel() {
if (NS_WARN_IF(!mActor)) {
return NS_ERROR_UNEXPECTED;
}
@ -3869,9 +3880,8 @@ void BackgroundFileHandleChild::NoteActorDestroyed() {
mFileHandle->ClearBackgroundActor();
// Normally this would be DEBUG-only but NoteActorDestroyed is also called
// from SendDeleteMeInternal. In that case we're going to receive an
// actual ActorDestroy call later and we don't want to touch a dead
// object.
// from SendDeleteMeInternal. In that case we're going to receive an actual
// ActorDestroy call later and we don't want to touch a dead object.
mTemporaryStrongFileHandle = nullptr;
mFileHandle = nullptr;
}

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

@ -7,7 +7,6 @@
#ifndef mozilla_dom_indexeddb_actorschild_h__
#define mozilla_dom_indexeddb_actorschild_h__
#include "IDBCursorType.h"
#include "IDBTransaction.h"
#include "js/RootingAPI.h"
#include "mozilla/Attributes.h"
@ -635,32 +634,90 @@ struct CloneInfo {
UniquePtr<JSStructuredCloneData> mCloneData;
};
class BackgroundCursorChildBase : public PBackgroundIDBCursorChild {
private:
NS_DECL_OWNINGTHREAD
protected:
InitializedOnceMustBeTrue<IDBRequest* const> mRequest;
// TODO: Consider defining different subclasses for the different cursor types,
// possibly using the CRTP, which would remove the need for various case
// distinctions.
class BackgroundCursorChild final : public PBackgroundIDBCursorChild {
friend class BackgroundTransactionChild;
friend class BackgroundVersionChangeTransactionChild;
class DelayedActionRunnable;
struct CachedResponse {
CachedResponse() = delete;
CachedResponse(Key aKey, StructuredCloneReadInfo&& aCloneInfo);
CachedResponse(Key aKey, Key aLocaleAwareKey, Key aObjectStoreKey,
StructuredCloneReadInfo&& aCloneInfo);
explicit CachedResponse(Key aKey);
CachedResponse(Key aKey, Key aLocaleAwareKey, Key aObjectStoreKey);
CachedResponse(CachedResponse&& aOther) = default;
CachedResponse& operator=(CachedResponse&& aOther) = default;
CachedResponse(const CachedResponse& aOther) = delete;
CachedResponse& operator=(const CachedResponse& aOther) = delete;
Key mKey;
Key mLocaleAwareKey;
Key mObjectStoreKey;
StructuredCloneReadInfo mCloneInfo;
};
IDBRequest* mRequest;
IDBTransaction* mTransaction;
IDBObjectStore* mObjectStore;
IDBIndex* mIndex;
IDBCursor* mCursor;
// These are only set while a request is in progress.
RefPtr<IDBRequest> mStrongRequest;
RefPtr<IDBCursor> mStrongCursor;
const Direction mDirection;
Direction mDirection;
BackgroundCursorChildBase(IDBRequest* aRequest, Direction aDirection);
NS_DECL_OWNINGTHREAD
void HandleResponse(nsresult aResponse);
std::deque<CachedResponse> mCachedResponses, mDelayedResponses;
bool mInFlightResponseInvalidationNeeded;
public:
BackgroundCursorChild(IDBRequest* aRequest, IDBObjectStore* aObjectStore,
Direction aDirection);
BackgroundCursorChild(IDBRequest* aRequest, IDBIndex* aIndex,
Direction aDirection);
void AssertIsOnOwningThread() const {
NS_ASSERT_OWNINGTHREAD(BackgroundCursorChildBase);
NS_ASSERT_OWNINGTHREAD(BackgroundCursorChild);
}
void SendContinueInternal(const CursorRequestParams& aParams,
const Key& aCurrentKey,
const Key& aCurrentObjectStoreKey);
void SendDeleteMeInternal();
void InvalidateCachedResponses();
template <typename Condition>
void DiscardCachedResponses(const Condition& aConditionFunc);
IDBRequest* GetRequest() const {
AssertIsOnOwningThread();
return *mRequest;
return mRequest;
}
IDBObjectStore* GetObjectStore() const {
AssertIsOnOwningThread();
return mObjectStore;
}
IDBIndex* GetIndex() const {
AssertIsOnOwningThread();
return mIndex;
}
Direction GetDirection() const {
@ -669,44 +726,6 @@ class BackgroundCursorChildBase : public PBackgroundIDBCursorChild {
return mDirection;
}
virtual void SendDeleteMeInternal() = 0;
};
template <IDBCursorType CursorType>
class BackgroundCursorChild final : public BackgroundCursorChildBase {
public:
using SourceType = CursorSourceType<CursorType>;
private:
friend class BackgroundTransactionChild;
friend class BackgroundVersionChangeTransactionChild;
InitializedOnceMustBeTrue<SourceType* const> mSource;
IDBCursorImpl<CursorType>* mCursor;
std::deque<CursorData<CursorType>> mCachedResponses, mDelayedResponses;
bool mInFlightResponseInvalidationNeeded;
public:
BackgroundCursorChild(IDBRequest* aRequest, SourceType* aSource,
Direction aDirection);
void SendContinueInternal(const CursorRequestParams& aParams,
const CursorData<CursorType>& aCurrentData);
void InvalidateCachedResponses();
template <typename Condition>
void DiscardCachedResponses(const Condition& aConditionFunc);
SourceType* GetSource() const {
AssertIsOnOwningThread();
return *mSource;
}
void SendDeleteMeInternal() final;
private:
// Only destroyed by BackgroundTransactionChild or
// BackgroundVersionChangeTransactionChild.
@ -714,7 +733,7 @@ class BackgroundCursorChild final : public BackgroundCursorChildBase {
void CompleteContinueRequestFromCache();
using BackgroundCursorChildBase::HandleResponse;
void HandleResponse(nsresult aResponse);
void HandleResponse(const void_t& aResponse);

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Разница между файлами не показана из-за своего большого размера Загрузить разницу

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

@ -7,9 +7,7 @@
#ifndef mozilla_dom_idbcursor_h__
#define mozilla_dom_idbcursor_h__
#include "IDBCursorType.h"
#include "IndexedDatabase.h"
#include "InitializedOnce.h"
#include "js/RootingAPI.h"
#include "mozilla/Attributes.h"
#include "mozilla/dom/IDBCursorBinding.h"
@ -32,42 +30,59 @@ class IDBObjectStore;
class IDBRequest;
class OwningIDBObjectStoreOrIDBIndex;
class IDBObjectStoreCursor;
class IDBObjectStoreKeyCursor;
class IDBIndexCursor;
class IDBIndexKeyCursor;
namespace indexedDB {
class BackgroundCursorChildBase;
template <IDBCursorType CursorType>
class BackgroundCursorChild;
} // namespace indexedDB
}
class IDBCursor : public nsISupports, public nsWrapperCache {
// TODO: Consider defining different subclasses for the different cursor types,
// possibly using the CRTP, which would remove the need for various case
// distinctions.
class IDBCursor final : public nsISupports, public nsWrapperCache {
public:
using Key = indexedDB::Key;
using StructuredCloneReadInfo = indexedDB::StructuredCloneReadInfo;
using Direction = IDBCursorDirection;
using Type = IDBCursorType;
enum struct Direction {
Next = 0,
NextUnique,
Prev,
PrevUnique,
protected:
InitializedOnceMustBeTrue<indexedDB::BackgroundCursorChildBase* const>
mBackgroundActor;
// Only needed for IPC serialization helper, should never be used in code.
Invalid
};
// TODO: mRequest could be made const if Bug 1575173 is resolved. It is
// initialized in the constructor and never modified/cleared.
enum struct Type {
ObjectStore,
ObjectStoreKey,
Index,
IndexKey,
};
private:
indexedDB::BackgroundCursorChild* mBackgroundActor;
// TODO: mRequest, mSourceObjectStore and mSourceIndex could be made const if
// Bug 1575173 is resolved. They are initialized in the constructor and never
// modified/cleared.
RefPtr<IDBRequest> mRequest;
RefPtr<IDBObjectStore> mSourceObjectStore;
RefPtr<IDBIndex> mSourceIndex;
// Sub-classes' mSource will hold this alive.
// mSourceObjectStore or mSourceIndex will hold this alive.
const CheckedUnsafePtr<IDBTransaction> mTransaction;
protected:
// These are cycle-collected!
JS::Heap<JS::Value> mCachedKey;
JS::Heap<JS::Value> mCachedPrimaryKey;
JS::Heap<JS::Value> mCachedValue;
Key mKey;
Key mSortKey; ///< AKA locale aware key/position elsewhere
Key mPrimaryKey; ///< AKA object store key/position elsewhere
StructuredCloneReadInfo mCloneInfo;
const Type mType;
const Direction mDirection;
bool mHaveCachedKey : 1;
@ -78,21 +93,22 @@ class IDBCursor : public nsISupports, public nsWrapperCache {
bool mHaveValue : 1;
public:
static MOZ_MUST_USE RefPtr<IDBObjectStoreCursor> Create(
indexedDB::BackgroundCursorChild<Type::ObjectStore>* aBackgroundActor,
Key aKey, StructuredCloneReadInfo&& aCloneInfo);
static MOZ_MUST_USE RefPtr<IDBCursor> Create(
indexedDB::BackgroundCursorChild* aBackgroundActor, Key aKey,
StructuredCloneReadInfo&& aCloneInfo);
static MOZ_MUST_USE RefPtr<IDBObjectStoreKeyCursor> Create(
indexedDB::BackgroundCursorChild<Type::ObjectStoreKey>* aBackgroundActor,
Key aKey);
static MOZ_MUST_USE RefPtr<IDBCursor> Create(
indexedDB::BackgroundCursorChild* aBackgroundActor, Key aKey);
static MOZ_MUST_USE RefPtr<IDBIndexCursor> Create(
indexedDB::BackgroundCursorChild<Type::Index>* aBackgroundActor, Key aKey,
static MOZ_MUST_USE RefPtr<IDBCursor> Create(
indexedDB::BackgroundCursorChild* aBackgroundActor, Key aKey,
Key aSortKey, Key aPrimaryKey, StructuredCloneReadInfo&& aCloneInfo);
static MOZ_MUST_USE RefPtr<IDBIndexKeyCursor> Create(
indexedDB::BackgroundCursorChild<Type::IndexKey>* aBackgroundActor,
Key aKey, Key aSortKey, Key aPrimaryKey);
static MOZ_MUST_USE RefPtr<IDBCursor> Create(
indexedDB::BackgroundCursorChild* aBackgroundActor, Key aKey,
Key aSortKey, Key aPrimaryKey);
static Direction ConvertDirection(IDBCursorDirection aDirection);
void AssertIsOnOwningThread() const
#ifdef DEBUG
@ -104,183 +120,74 @@ class IDBCursor : public nsISupports, public nsWrapperCache {
nsIGlobalObject* GetParentObject() const;
// XXX: The virtual methods that are used by the DOM binding could be removed
// on the base class, if we provided a non-polymorphic wrapper instead, which
// uses a custom dispatch to the actual implementation type. Don't know if
// this is worth it.
virtual void GetSource(OwningIDBObjectStoreOrIDBIndex& aSource) const = 0;
void GetSource(OwningIDBObjectStoreOrIDBIndex& aSource) const;
IDBCursorDirection GetDirection() const;
virtual void GetKey(JSContext* aCx, JS::MutableHandle<JS::Value> aResult,
ErrorResult& aRv) = 0;
Type GetType() const;
virtual void GetPrimaryKey(JSContext* aCx,
JS::MutableHandle<JS::Value> aResult,
ErrorResult& aRv) = 0;
void GetKey(JSContext* aCx, JS::MutableHandle<JS::Value> aResult,
ErrorResult& aRv);
// XXX: We could move this to a sub-class, since this is only present on
// IDBCursorWithValue.
virtual void GetValue(JSContext* aCx, JS::MutableHandle<JS::Value> aResult,
ErrorResult& aRv) = 0;
void GetPrimaryKey(JSContext* aCx, JS::MutableHandle<JS::Value> aResult,
ErrorResult& aRv);
virtual void Continue(JSContext* aCx, JS::Handle<JS::Value> aKey,
ErrorResult& aRv) = 0;
void GetValue(JSContext* aCx, JS::MutableHandle<JS::Value> aResult,
ErrorResult& aRv);
virtual void ContinuePrimaryKey(JSContext* aCx, JS::Handle<JS::Value> aKey,
JS::Handle<JS::Value> aPrimaryKey,
ErrorResult& aRv) = 0;
void Continue(JSContext* aCx, JS::Handle<JS::Value> aKey, ErrorResult& aRv);
virtual void Advance(uint32_t aCount, ErrorResult& aRv) = 0;
void ContinuePrimaryKey(JSContext* aCx, JS::Handle<JS::Value> aKey,
JS::Handle<JS::Value> aPrimaryKey, ErrorResult& aRv);
virtual MOZ_MUST_USE RefPtr<IDBRequest> Update(JSContext* aCx,
JS::Handle<JS::Value> aValue,
ErrorResult& aRv) = 0;
void Advance(uint32_t aCount, ErrorResult& aRv);
virtual MOZ_MUST_USE RefPtr<IDBRequest> Delete(JSContext* aCx,
ErrorResult& aRv) = 0;
MOZ_MUST_USE RefPtr<IDBRequest> Update(JSContext* aCx,
JS::Handle<JS::Value> aValue,
ErrorResult& aRv);
MOZ_MUST_USE RefPtr<IDBRequest> Delete(JSContext* aCx, ErrorResult& aRv);
void Reset();
void Reset(Key&& aKey, StructuredCloneReadInfo&& aValue);
void Reset(Key&& aKey);
void Reset(Key&& aKey, Key&& aSortKey, Key&& aPrimaryKey,
StructuredCloneReadInfo&& aValue);
void Reset(Key&& aKey, Key&& aSortKey, Key&& aPrimaryKey);
void ClearBackgroundActor() {
AssertIsOnOwningThread();
mBackgroundActor.reset();
mBackgroundActor = nullptr;
}
virtual void InvalidateCachedResponses() = 0;
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(IDBCursor)
protected:
IDBCursor(indexedDB::BackgroundCursorChildBase* aBackgroundActor);
// TODO: Check if we can remove virtual by changing cycle collection.
virtual ~IDBCursor() = default;
void ResetBase();
};
template <IDBCursor::Type CursorType>
class IDBTypedCursor : public IDBCursor {
public:
template <typename... DataArgs>
explicit IDBTypedCursor(
indexedDB::BackgroundCursorChild<CursorType>* aBackgroundActor,
DataArgs&&... aDataArgs);
static constexpr Type GetType() { return CursorType; }
void InvalidateCachedResponses();
// Checks if this is a locale aware cursor (ie. the index's sortKey is unset)
bool IsLocaleAware() const;
void GetSource(OwningIDBObjectStoreOrIDBIndex& aSource) const final;
void GetKey(JSContext* aCx, JS::MutableHandle<JS::Value> aResult,
ErrorResult& aRv) final;
void GetPrimaryKey(JSContext* aCx, JS::MutableHandle<JS::Value> aResult,
ErrorResult& aRv) final;
void GetValue(JSContext* aCx, JS::MutableHandle<JS::Value> aResult,
ErrorResult& aRv) final;
void Continue(JSContext* aCx, JS::Handle<JS::Value> aKey,
ErrorResult& aRv) final;
void ContinuePrimaryKey(JSContext* aCx, JS::Handle<JS::Value> aKey,
JS::Handle<JS::Value> aPrimaryKey,
ErrorResult& aRv) final;
void Advance(uint32_t aCount, ErrorResult& aRv) final;
MOZ_MUST_USE RefPtr<IDBRequest> Update(JSContext* aCx,
JS::Handle<JS::Value> aValue,
ErrorResult& aRv) final;
MOZ_MUST_USE RefPtr<IDBRequest> Delete(JSContext* aCx,
ErrorResult& aRv) final;
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(IDBCursor)
// nsWrapperCache
JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) final;
void InvalidateCachedResponses() final;
void Reset();
void Reset(CursorData<CursorType>&& aCursorData);
virtual JSObject* WrapObject(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto) override;
private:
static constexpr bool IsObjectStoreCursor =
CursorTypeTraits<CursorType>::IsObjectStoreCursor;
static constexpr bool IsKeyOnlyCursor =
CursorTypeTraits<CursorType>::IsKeyOnlyCursor;
IDBCursor(Type aType, indexedDB::BackgroundCursorChild* aBackgroundActor,
Key aKey);
CursorSourceType<CursorType>& GetSourceRef() const {
MOZ_ASSERT(mSource);
return *mSource;
}
IDBObjectStore& GetSourceObjectStoreRef() const {
if constexpr (IsObjectStoreCursor) {
return GetSourceRef();
} else {
MOZ_ASSERT(!GetSourceRef().IsDeleted());
auto res = GetSourceRef().ObjectStore();
MOZ_ASSERT(res);
return *res;
}
}
indexedDB::BackgroundCursorChild<CursorType>& GetTypedBackgroundActorRef()
const {
// We can safely downcast to BackgroundCursorChild<CursorType>*, since we
// initialized that in the constructor from that type. We just want to avoid
// having a second typed field.
return *static_cast<indexedDB::BackgroundCursorChild<CursorType>*>(
*mBackgroundActor);
}
bool IsSourceDeleted() const;
protected:
virtual ~IDBTypedCursor() override;
~IDBCursor();
void DropJSObjects();
CursorData<CursorType> mData;
// TODO: mSource could be made const if Bug 1575173 is resolved. It is
// initialized in the constructor and never modified/cleared.
RefPtr<CursorSourceType<CursorType>> mSource;
bool IsSourceDeleted() const;
};
// The subclasses defined by this macro are only needed to be able to use the
// cycle collector macros, which do not support templates. If spelled out, the
// cycle collection could be implemented directly on IDBTypedCursor, and these
// classes were not needed.
#define CONCRETE_IDBCURSOR_SUBCLASS(_subclassName, _cursorType) \
class _subclassName final : public IDBTypedCursor<_cursorType> { \
public: \
NS_DECL_ISUPPORTS_INHERITED \
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(_subclassName, IDBCursor) \
\
using IDBTypedCursor<_cursorType>::IDBTypedCursor; \
\
private: \
~_subclassName() final = default; \
};
CONCRETE_IDBCURSOR_SUBCLASS(IDBObjectStoreCursor, IDBCursor::Type::ObjectStore)
CONCRETE_IDBCURSOR_SUBCLASS(IDBObjectStoreKeyCursor,
IDBCursor::Type::ObjectStoreKey)
CONCRETE_IDBCURSOR_SUBCLASS(IDBIndexCursor, IDBCursor::Type::Index)
CONCRETE_IDBCURSOR_SUBCLASS(IDBIndexKeyCursor, IDBCursor::Type::IndexKey)
template <IDBCursor::Type CursorType>
using IDBCursorImpl = typename CursorTypeTraits<CursorType>::Type;
} // namespace dom
} // namespace mozilla

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

@ -1,35 +0,0 @@
/* -*- 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/. */
#include "IDBCursorType.h"
namespace mozilla {
namespace dom {
CommonCursorDataBase::CommonCursorDataBase(Key aKey) : mKey{std::move(aKey)} {}
IndexCursorDataBase::IndexCursorDataBase(Key aKey, Key aLocaleAwareKey,
Key aObjectStoreKey)
: CommonCursorDataBase{std::move(aKey)},
mLocaleAwareKey{std::move(aLocaleAwareKey)},
mObjectStoreKey{std::move(aObjectStoreKey)} {}
ValueCursorDataBase::ValueCursorDataBase(StructuredCloneReadInfo&& aCloneInfo)
: mCloneInfo{std::move(aCloneInfo)} {}
CursorData<IDBCursorType::ObjectStore>::CursorData(
Key aKey, StructuredCloneReadInfo&& aCloneInfo)
: ObjectStoreCursorDataBase{std::move(aKey)},
ValueCursorDataBase{std::move(aCloneInfo)} {}
CursorData<IDBCursorType::Index>::CursorData(
Key aKey, Key aLocaleAwareKey, Key aObjectStoreKey,
StructuredCloneReadInfo&& aCloneInfo)
: IndexCursorDataBase{std::move(aKey), std::move(aLocaleAwareKey),
std::move(aObjectStoreKey)},
ValueCursorDataBase{std::move(aCloneInfo)} {}
} // namespace dom
} // namespace mozilla

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

@ -1,143 +0,0 @@
/* -*- 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_idbcursortype_h__
#define mozilla_dom_idbcursortype_h__
#include "IndexedDatabase.h"
#include "mozilla/dom/indexedDB/Key.h"
namespace mozilla {
namespace dom {
enum struct IDBCursorType {
ObjectStore,
ObjectStoreKey,
Index,
IndexKey,
};
template <IDBCursorType CursorType>
struct CursorTypeTraits;
class IDBIndex;
class IDBObjectStore;
class IDBIndexCursor;
class IDBIndexKeyCursor;
class IDBObjectStoreCursor;
class IDBObjectStoreKeyCursor;
template <>
struct CursorTypeTraits<IDBCursorType::Index> {
using Type = IDBIndexCursor;
static constexpr bool IsObjectStoreCursor = false;
static constexpr bool IsKeyOnlyCursor = false;
};
template <>
struct CursorTypeTraits<IDBCursorType::IndexKey> {
using Type = IDBIndexKeyCursor;
static constexpr bool IsObjectStoreCursor = false;
static constexpr bool IsKeyOnlyCursor = true;
};
template <>
struct CursorTypeTraits<IDBCursorType::ObjectStore> {
using Type = IDBObjectStoreCursor;
static constexpr bool IsObjectStoreCursor = true;
static constexpr bool IsKeyOnlyCursor = false;
};
template <>
struct CursorTypeTraits<IDBCursorType::ObjectStoreKey> {
using Type = IDBObjectStoreKeyCursor;
static constexpr bool IsObjectStoreCursor = true;
static constexpr bool IsKeyOnlyCursor = true;
};
template <IDBCursorType CursorType>
using CursorSourceType =
std::conditional_t<CursorTypeTraits<CursorType>::IsObjectStoreCursor,
IDBObjectStore, IDBIndex>;
using Key = indexedDB::Key;
using StructuredCloneReadInfo = indexedDB::StructuredCloneReadInfo;
struct CommonCursorDataBase {
CommonCursorDataBase() = delete;
explicit CommonCursorDataBase(Key aKey);
Key mKey; ///< The current key, i.e. the key representing the cursor's
///< position
///< (https://w3c.github.io/IndexedDB/#cursor-position).
};
template <IDBCursorType CursorType>
struct CursorData;
struct ObjectStoreCursorDataBase : CommonCursorDataBase {
using CommonCursorDataBase::CommonCursorDataBase;
const Key& GetSortKey(const bool aIsLocaleAware) const {
MOZ_ASSERT(!aIsLocaleAware);
return GetObjectStoreKey();
}
const Key& GetObjectStoreKey() const { return mKey; }
static constexpr const char* GetObjectStoreKeyForLogging() { return "NA"; }
};
struct IndexCursorDataBase : CommonCursorDataBase {
IndexCursorDataBase(Key aKey, Key aLocaleAwareKey, Key aObjectStoreKey);
const Key& GetSortKey(const bool aIsLocaleAware) const {
return aIsLocaleAware ? mLocaleAwareKey : mKey;
}
const Key& GetObjectStoreKey() const { return mObjectStoreKey; }
const char* GetObjectStoreKeyForLogging() const {
return GetObjectStoreKey().GetBuffer().get();
}
Key mLocaleAwareKey; ///< If the index's mLocale is set, this is mKey
///< converted to mLocale. Otherwise, it is unset.
Key mObjectStoreKey; ///< The key representing the cursor's object store
///< position
///< (https://w3c.github.io/IndexedDB/#cursor-object-store-position).
};
struct ValueCursorDataBase {
explicit ValueCursorDataBase(StructuredCloneReadInfo&& aCloneInfo);
StructuredCloneReadInfo mCloneInfo;
};
template <>
struct CursorData<IDBCursorType::ObjectStoreKey> : ObjectStoreCursorDataBase {
using ObjectStoreCursorDataBase::ObjectStoreCursorDataBase;
};
template <>
struct CursorData<IDBCursorType::ObjectStore> : ObjectStoreCursorDataBase,
ValueCursorDataBase {
CursorData(Key aKey, StructuredCloneReadInfo&& aCloneInfo);
};
template <>
struct CursorData<IDBCursorType::IndexKey> : IndexCursorDataBase {
using IndexCursorDataBase::IndexCursorDataBase;
};
template <>
struct CursorData<IDBCursorType::Index> : IndexCursorDataBase,
ValueCursorDataBase {
CursorData(Key aKey, Key aLocaleAwareKey, Key aObjectStoreKey,
StructuredCloneReadInfo&& aCloneInfo);
};
} // namespace dom
} // namespace mozilla
#endif

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

@ -7,7 +7,7 @@
#include "IDBIndex.h"
#include "FileInfo.h"
#include "IDBCursorType.h"
#include "IDBCursor.h"
#include "IDBEvents.h"
#include "IDBKeyRange.h"
#include "IDBObjectStore.h"
@ -489,8 +489,11 @@ RefPtr<IDBRequest> IDBIndex::OpenCursorInternal(bool aKeysOnly, JSContext* aCx,
optionalKeyRange.emplace(std::move(serializedKeyRange));
}
const IDBCursor::Direction direction =
IDBCursor::ConvertDirection(aDirection);
const CommonIndexOpenCursorParams commonIndexParams = {
{objectStoreId, std::move(optionalKeyRange), aDirection}, indexId};
{objectStoreId, std::move(optionalKeyRange), direction}, indexId};
const auto params =
aKeysOnly ? OpenCursorParams{IndexOpenKeyCursorParams{commonIndexParams}}
@ -508,7 +511,7 @@ RefPtr<IDBRequest> IDBIndex::OpenCursorInternal(bool aKeysOnly, JSContext* aCx,
IDB_LOG_STRINGIFY(transaction->Database()),
IDB_LOG_STRINGIFY(transaction), IDB_LOG_STRINGIFY(mObjectStore),
IDB_LOG_STRINGIFY(this), IDB_LOG_STRINGIFY(keyRange),
IDB_LOG_STRINGIFY(aDirection));
IDB_LOG_STRINGIFY(direction));
} else {
IDB_LOG_MARK_CHILD_TRANSACTION_REQUEST(
"database(%s).transaction(%s).objectStore(%s).index(%s)."
@ -518,15 +521,11 @@ RefPtr<IDBRequest> IDBIndex::OpenCursorInternal(bool aKeysOnly, JSContext* aCx,
IDB_LOG_STRINGIFY(transaction->Database()),
IDB_LOG_STRINGIFY(transaction), IDB_LOG_STRINGIFY(mObjectStore),
IDB_LOG_STRINGIFY(this), IDB_LOG_STRINGIFY(keyRange),
IDB_LOG_STRINGIFY(aDirection));
IDB_LOG_STRINGIFY(direction));
}
BackgroundCursorChildBase* const actor =
aKeysOnly ? static_cast<BackgroundCursorChildBase*>(
new BackgroundCursorChild<IDBCursorType::IndexKey>(
request, this, aDirection))
: new BackgroundCursorChild<IDBCursorType::Index>(request, this,
aDirection);
BackgroundCursorChild* const actor =
new BackgroundCursorChild(request, this, direction);
// TODO: This is necessary to preserve request ordering only. Proper
// sequencing of requests should be done in a more sophisticated manner that

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

@ -7,7 +7,7 @@
#include "IDBObjectStore.h"
#include "FileInfo.h"
#include "IDBCursorType.h"
#include "IDBCursor.h"
#include "IDBDatabase.h"
#include "IDBEvents.h"
#include "IDBFactory.h"
@ -2376,8 +2376,11 @@ RefPtr<IDBRequest> IDBObjectStore::OpenCursorInternal(
optionalKeyRange.emplace(std::move(serializedKeyRange));
}
const IDBCursor::Direction direction =
IDBCursor::ConvertDirection(aDirection);
const CommonOpenCursorParams commonParams = {
objectStoreId, std::move(optionalKeyRange), aDirection};
objectStoreId, std::move(optionalKeyRange), direction};
// TODO: It would be great if the IPDL generator created a constructor
// accepting a CommonOpenCursorParams by value or rvalue reference.
@ -2396,7 +2399,7 @@ RefPtr<IDBRequest> IDBObjectStore::OpenCursorInternal(
request->LoggingSerialNumber(),
IDB_LOG_STRINGIFY(mTransaction->Database()),
IDB_LOG_STRINGIFY(mTransaction), IDB_LOG_STRINGIFY(this),
IDB_LOG_STRINGIFY(keyRange), IDB_LOG_STRINGIFY(aDirection));
IDB_LOG_STRINGIFY(keyRange), IDB_LOG_STRINGIFY(direction));
} else {
IDB_LOG_MARK_CHILD_TRANSACTION_REQUEST(
"database(%s).transaction(%s).objectStore(%s)."
@ -2405,15 +2408,11 @@ RefPtr<IDBRequest> IDBObjectStore::OpenCursorInternal(
request->LoggingSerialNumber(),
IDB_LOG_STRINGIFY(mTransaction->Database()),
IDB_LOG_STRINGIFY(mTransaction), IDB_LOG_STRINGIFY(this),
IDB_LOG_STRINGIFY(keyRange), IDB_LOG_STRINGIFY(aDirection));
IDB_LOG_STRINGIFY(keyRange), IDB_LOG_STRINGIFY(direction));
}
BackgroundCursorChildBase* const actor =
aKeysOnly ? static_cast<BackgroundCursorChildBase*>(
new BackgroundCursorChild<IDBCursorType::ObjectStoreKey>(
request, this, aDirection))
: new BackgroundCursorChild<IDBCursorType::ObjectStore>(
request, this, aDirection);
BackgroundCursorChild* const actor =
new BackgroundCursorChild(request, this, direction);
// TODO: This is necessary to preserve request ordering only. Proper
// sequencing of requests should be done in a more sophisticated manner that

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

@ -7,7 +7,6 @@
#ifndef mozilla_dom_idbobjectstore_h__
#define mozilla_dom_idbobjectstore_h__
#include "IDBCursor.h"
#include "js/RootingAPI.h"
#include "mozilla/dom/IDBCursorBinding.h"
#include "mozilla/dom/IDBIndexBinding.h"
@ -28,6 +27,7 @@ class ErrorResult;
namespace dom {
class DOMStringList;
class IDBCursor;
class IDBRequest;
class IDBTransaction;
class StringOrStringSequence;
@ -50,9 +50,7 @@ class IDBObjectStore final : public nsISupports, public nsWrapperCache {
typedef indexedDB::StructuredCloneReadInfo StructuredCloneReadInfo;
// For AddOrPut() and DeleteInternal().
// TODO Consider removing this, and making the functions public?
template <IDBCursor::Type>
friend class IDBTypedCursor;
friend class IDBCursor;
static const JSClass sDummyPropJSClass;

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

@ -299,9 +299,8 @@ BackgroundRequestChild* IDBTransaction::StartRequest(
return actor;
}
void IDBTransaction::OpenCursor(
PBackgroundIDBCursorChild* const aBackgroundActor,
const OpenCursorParams& aParams) {
void IDBTransaction::OpenCursor(BackgroundCursorChild* const aBackgroundActor,
const OpenCursorParams& aParams) {
AssertIsOnOwningThread();
MOZ_ASSERT(aBackgroundActor);
MOZ_ASSERT(aParams.type() != OpenCursorParams::T__None);

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

@ -34,7 +34,7 @@ class IDBRequest;
class StrongWorkerRef;
namespace indexedDB {
class PBackgroundIDBCursorChild;
class BackgroundCursorChild;
class BackgroundRequestChild;
class BackgroundTransactionChild;
class BackgroundVersionChangeTransactionChild;
@ -48,6 +48,7 @@ class IDBTransaction final
: public DOMEventTargetHelper,
public nsIRunnable,
public SupportsCheckedUnsafePtr<CheckIf<DiagnosticAssertEnabled>> {
friend class indexedDB::BackgroundCursorChild;
friend class indexedDB::BackgroundRequestChild;
public:
@ -162,7 +163,7 @@ class IDBTransaction final
indexedDB::BackgroundRequestChild* StartRequest(
IDBRequest* aRequest, const indexedDB::RequestParams& aParams);
void OpenCursor(indexedDB::PBackgroundIDBCursorChild* aBackgroundActor,
void OpenCursor(indexedDB::BackgroundCursorChild* aBackgroundActor,
const indexedDB::OpenCursorParams& aParams);
void RefreshSpec(bool aMayDelete);
@ -365,13 +366,10 @@ class IDBTransaction final
void MaybeNoteInactiveTransaction();
// TODO consider making private again, or move to the right place
public:
void OnNewRequest();
void OnRequestFinished(bool aRequestCompletedSuccessfully);
private:
template <typename Func>
auto DoWithTransactionChild(const Func& aFunc) const;

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

@ -85,10 +85,6 @@ class InitializedOnce final {
void reset() {
MOZ_ASSERT(mMaybe.isSome());
maybeReset();
}
void maybeReset() {
mMaybe.reset();
#ifdef DEBUG
mWasReset = true;

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

@ -12,7 +12,7 @@
#include "BackgroundChildImpl.h"
#include "GeckoProfiler.h"
#include "IDBCursorType.h"
#include "IDBCursor.h"
#include "IDBDatabase.h"
#include "IDBIndex.h"
#include "IDBKeyRange.h"
@ -189,18 +189,18 @@ class MOZ_STACK_CLASS LoggingString final : public nsAutoCString {
}
}
explicit LoggingString(const IDBCursorDirection aDirection) {
explicit LoggingString(const IDBCursor::Direction aDirection) {
switch (aDirection) {
case IDBCursorDirection::Next:
case IDBCursor::Direction::Next:
AssignLiteral("\"next\"");
break;
case IDBCursorDirection::Nextunique:
case IDBCursor::Direction::NextUnique:
AssignLiteral("\"nextunique\"");
break;
case IDBCursorDirection::Prev:
case IDBCursor::Direction::Prev:
AssignLiteral("\"prev\"");
break;
case IDBCursorDirection::Prevunique:
case IDBCursor::Direction::PrevUnique:
AssignLiteral("\"prevunique\"");
break;
default:

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

@ -73,7 +73,7 @@ struct ParamTraits<mozilla::dom::IDBCursor::Direction>
: public ContiguousEnumSerializer<
mozilla::dom::IDBCursor::Direction,
mozilla::dom::IDBCursor::Direction::Next,
mozilla::dom::IDBCursor::Direction::EndGuard_> {};
mozilla::dom::IDBCursor::Direction::Invalid> {};
template <>
struct ParamTraits<mozilla::dom::IDBTransaction::Mode>

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

@ -26,7 +26,6 @@ TEST_DIRS += ['test/gtest']
EXPORTS.mozilla.dom += [
'FlippedOnce.h',
'IDBCursor.h',
'IDBCursorType.h',
'IDBDatabase.h',
'IDBEvents.h',
'IDBFactory.h',
@ -40,7 +39,6 @@ EXPORTS.mozilla.dom += [
'IDBTransaction.h',
'IndexedDatabase.h',
'IndexedDatabaseManager.h',
'InitializedOnce.h',
]
EXPORTS.mozilla.dom.indexedDB += [
@ -58,7 +56,6 @@ UNIFIED_SOURCES += [
'FileInfo.cpp',
'FileSnapshot.cpp',
'IDBCursor.cpp',
'IDBCursorType.cpp',
'IDBDatabase.cpp',
'IDBEvents.cpp',
'IDBFactory.cpp',