gecko-dev/dom/indexedDB/IDBCursor.cpp

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

915 строки
25 KiB
C++
Исходник Обычный вид История

/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
2012-05-21 15:12:37 +04:00
/* 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 "IDBCursor.h"
#include "IDBDatabase.h"
#include "IDBIndex.h"
#include "IDBObjectStore.h"
#include "IDBRequest.h"
#include "IDBTransaction.h"
#include "IndexedDatabaseInlines.h"
#include "mozilla/ErrorResult.h"
#include "mozilla/dom/UnionTypes.h"
#include "mozilla/dom/indexedDB/PBackgroundIDBSharedTypes.h"
#include "nsString.h"
#include "ProfilerHelpers.h"
#include "ReportInternalError.h"
// Include this last to avoid path problems on Windows.
#include "ActorsChild.h"
namespace mozilla {
namespace dom {
using namespace indexedDB;
IDBCursor::IDBCursor(Type aType, BackgroundCursorChild* aBackgroundActor,
Key aKey)
2014-11-08 03:42:53 +03:00
: mBackgroundActor(aBackgroundActor),
mRequest(aBackgroundActor->GetRequest()),
mSourceObjectStore(aBackgroundActor->GetObjectStore()),
mSourceIndex(aBackgroundActor->GetIndex()),
mTransaction(mRequest->GetTransaction()),
mCachedKey(JS::UndefinedValue()),
mCachedPrimaryKey(JS::UndefinedValue()),
mCachedValue(JS::UndefinedValue()),
mKey(std::move(aKey)),
mType(aType),
2014-11-08 03:42:53 +03:00
mDirection(aBackgroundActor->GetDirection()),
mHaveCachedKey(false),
mHaveCachedPrimaryKey(false),
mHaveCachedValue(false),
mRooted(false),
mContinueCalled(false),
mHaveValue(true) {
MOZ_ASSERT(aBackgroundActor);
2014-11-08 03:42:53 +03:00
aBackgroundActor->AssertIsOnOwningThread();
MOZ_ASSERT(mRequest);
MOZ_ASSERT_IF(aType == Type_ObjectStore || aType == Type_ObjectStoreKey,
mSourceObjectStore);
MOZ_ASSERT_IF(aType == Type_Index || aType == Type_IndexKey, mSourceIndex);
MOZ_ASSERT(mTransaction);
MOZ_ASSERT(!aKey.IsUnset());
mTransaction->RegisterCursor(this);
}
bool IDBCursor::IsLocaleAware() const {
return mSourceIndex && !mSourceIndex->Locale().IsEmpty();
}
IDBCursor::~IDBCursor() {
AssertIsOnOwningThread();
mTransaction->UnregisterCursor(this);
DropJSObjects();
if (mBackgroundActor) {
mBackgroundActor->SendDeleteMeInternal();
MOZ_ASSERT(!mBackgroundActor, "SendDeleteMeInternal should have cleared!");
}
}
// static
already_AddRefed<IDBCursor> IDBCursor::Create(
BackgroundCursorChild* aBackgroundActor, Key aKey,
StructuredCloneReadInfo&& aCloneInfo) {
MOZ_ASSERT(aBackgroundActor);
2014-11-08 03:42:53 +03:00
aBackgroundActor->AssertIsOnOwningThread();
MOZ_ASSERT(aBackgroundActor->GetObjectStore());
MOZ_ASSERT(!aBackgroundActor->GetIndex());
MOZ_ASSERT(!aKey.IsUnset());
Bug 1207245 - part 6 - rename nsRefPtr<T> to RefPtr<T>; r=ehsan; a=Tomcat The bulk of this commit was generated with a script, executed at the top level of a typical source code checkout. The only non-machine-generated part was modifying MFBT's moz.build to reflect the new naming. CLOSED TREE makes big refactorings like this a piece of cake. # The main substitution. find . -name '*.cpp' -o -name '*.cc' -o -name '*.h' -o -name '*.mm' -o -name '*.idl'| \ xargs perl -p -i -e ' s/nsRefPtr\.h/RefPtr\.h/g; # handle includes s/nsRefPtr ?</RefPtr</g; # handle declarations and variables ' # Handle a special friend declaration in gfx/layers/AtomicRefCountedWithFinalize.h. perl -p -i -e 's/::nsRefPtr;/::RefPtr;/' gfx/layers/AtomicRefCountedWithFinalize.h # Handle nsRefPtr.h itself, a couple places that define constructors # from nsRefPtr, and code generators specially. We do this here, rather # than indiscriminantly s/nsRefPtr/RefPtr/, because that would rename # things like nsRefPtrHashtable. perl -p -i -e 's/nsRefPtr/RefPtr/g' \ mfbt/nsRefPtr.h \ xpcom/glue/nsCOMPtr.h \ xpcom/base/OwningNonNull.h \ ipc/ipdl/ipdl/lower.py \ ipc/ipdl/ipdl/builtin.py \ dom/bindings/Codegen.py \ python/lldbutils/lldbutils/utils.py # In our indiscriminate substitution above, we renamed # nsRefPtrGetterAddRefs, the class behind getter_AddRefs. Fix that up. find . -name '*.cpp' -o -name '*.h' -o -name '*.idl' | \ xargs perl -p -i -e 's/nsRefPtrGetterAddRefs/RefPtrGetterAddRefs/g' if [ -d .git ]; then git mv mfbt/nsRefPtr.h mfbt/RefPtr.h else hg mv mfbt/nsRefPtr.h mfbt/RefPtr.h fi --HG-- rename : mfbt/nsRefPtr.h => mfbt/RefPtr.h
2015-10-18 08:24:48 +03:00
RefPtr<IDBCursor> cursor =
new IDBCursor(Type_ObjectStore, aBackgroundActor, std::move(aKey));
cursor->mCloneInfo = std::move(aCloneInfo);
return cursor.forget();
}
// static
already_AddRefed<IDBCursor> IDBCursor::Create(
BackgroundCursorChild* aBackgroundActor, Key aKey) {
MOZ_ASSERT(aBackgroundActor);
2014-11-08 03:42:53 +03:00
aBackgroundActor->AssertIsOnOwningThread();
MOZ_ASSERT(aBackgroundActor->GetObjectStore());
MOZ_ASSERT(!aBackgroundActor->GetIndex());
MOZ_ASSERT(!aKey.IsUnset());
Bug 1207245 - part 6 - rename nsRefPtr<T> to RefPtr<T>; r=ehsan; a=Tomcat The bulk of this commit was generated with a script, executed at the top level of a typical source code checkout. The only non-machine-generated part was modifying MFBT's moz.build to reflect the new naming. CLOSED TREE makes big refactorings like this a piece of cake. # The main substitution. find . -name '*.cpp' -o -name '*.cc' -o -name '*.h' -o -name '*.mm' -o -name '*.idl'| \ xargs perl -p -i -e ' s/nsRefPtr\.h/RefPtr\.h/g; # handle includes s/nsRefPtr ?</RefPtr</g; # handle declarations and variables ' # Handle a special friend declaration in gfx/layers/AtomicRefCountedWithFinalize.h. perl -p -i -e 's/::nsRefPtr;/::RefPtr;/' gfx/layers/AtomicRefCountedWithFinalize.h # Handle nsRefPtr.h itself, a couple places that define constructors # from nsRefPtr, and code generators specially. We do this here, rather # than indiscriminantly s/nsRefPtr/RefPtr/, because that would rename # things like nsRefPtrHashtable. perl -p -i -e 's/nsRefPtr/RefPtr/g' \ mfbt/nsRefPtr.h \ xpcom/glue/nsCOMPtr.h \ xpcom/base/OwningNonNull.h \ ipc/ipdl/ipdl/lower.py \ ipc/ipdl/ipdl/builtin.py \ dom/bindings/Codegen.py \ python/lldbutils/lldbutils/utils.py # In our indiscriminate substitution above, we renamed # nsRefPtrGetterAddRefs, the class behind getter_AddRefs. Fix that up. find . -name '*.cpp' -o -name '*.h' -o -name '*.idl' | \ xargs perl -p -i -e 's/nsRefPtrGetterAddRefs/RefPtrGetterAddRefs/g' if [ -d .git ]; then git mv mfbt/nsRefPtr.h mfbt/RefPtr.h else hg mv mfbt/nsRefPtr.h mfbt/RefPtr.h fi --HG-- rename : mfbt/nsRefPtr.h => mfbt/RefPtr.h
2015-10-18 08:24:48 +03:00
RefPtr<IDBCursor> cursor =
new IDBCursor(Type_ObjectStoreKey, aBackgroundActor, std::move(aKey));
return cursor.forget();
}
// static
already_AddRefed<IDBCursor> IDBCursor::Create(
BackgroundCursorChild* aBackgroundActor, Key aKey, Key aSortKey,
Key aPrimaryKey, StructuredCloneReadInfo&& aCloneInfo) {
MOZ_ASSERT(aBackgroundActor);
2014-11-08 03:42:53 +03:00
aBackgroundActor->AssertIsOnOwningThread();
MOZ_ASSERT(aBackgroundActor->GetIndex());
MOZ_ASSERT(!aBackgroundActor->GetObjectStore());
MOZ_ASSERT(!aKey.IsUnset());
MOZ_ASSERT(!aPrimaryKey.IsUnset());
RefPtr<IDBCursor> cursor =
new IDBCursor(Type_Index, aBackgroundActor, std::move(aKey));
cursor->mSortKey = std::move(aSortKey);
cursor->mPrimaryKey = std::move(aPrimaryKey);
cursor->mCloneInfo = std::move(aCloneInfo);
return cursor.forget();
}
// static
already_AddRefed<IDBCursor> IDBCursor::Create(
BackgroundCursorChild* aBackgroundActor, Key aKey, Key aSortKey,
Key aPrimaryKey) {
MOZ_ASSERT(aBackgroundActor);
2014-11-08 03:42:53 +03:00
aBackgroundActor->AssertIsOnOwningThread();
MOZ_ASSERT(aBackgroundActor->GetIndex());
MOZ_ASSERT(!aBackgroundActor->GetObjectStore());
MOZ_ASSERT(!aKey.IsUnset());
MOZ_ASSERT(!aPrimaryKey.IsUnset());
Bug 1207245 - part 6 - rename nsRefPtr<T> to RefPtr<T>; r=ehsan; a=Tomcat The bulk of this commit was generated with a script, executed at the top level of a typical source code checkout. The only non-machine-generated part was modifying MFBT's moz.build to reflect the new naming. CLOSED TREE makes big refactorings like this a piece of cake. # The main substitution. find . -name '*.cpp' -o -name '*.cc' -o -name '*.h' -o -name '*.mm' -o -name '*.idl'| \ xargs perl -p -i -e ' s/nsRefPtr\.h/RefPtr\.h/g; # handle includes s/nsRefPtr ?</RefPtr</g; # handle declarations and variables ' # Handle a special friend declaration in gfx/layers/AtomicRefCountedWithFinalize.h. perl -p -i -e 's/::nsRefPtr;/::RefPtr;/' gfx/layers/AtomicRefCountedWithFinalize.h # Handle nsRefPtr.h itself, a couple places that define constructors # from nsRefPtr, and code generators specially. We do this here, rather # than indiscriminantly s/nsRefPtr/RefPtr/, because that would rename # things like nsRefPtrHashtable. perl -p -i -e 's/nsRefPtr/RefPtr/g' \ mfbt/nsRefPtr.h \ xpcom/glue/nsCOMPtr.h \ xpcom/base/OwningNonNull.h \ ipc/ipdl/ipdl/lower.py \ ipc/ipdl/ipdl/builtin.py \ dom/bindings/Codegen.py \ python/lldbutils/lldbutils/utils.py # In our indiscriminate substitution above, we renamed # nsRefPtrGetterAddRefs, the class behind getter_AddRefs. Fix that up. find . -name '*.cpp' -o -name '*.h' -o -name '*.idl' | \ xargs perl -p -i -e 's/nsRefPtrGetterAddRefs/RefPtrGetterAddRefs/g' if [ -d .git ]; then git mv mfbt/nsRefPtr.h mfbt/RefPtr.h else hg mv mfbt/nsRefPtr.h mfbt/RefPtr.h fi --HG-- rename : mfbt/nsRefPtr.h => mfbt/RefPtr.h
2015-10-18 08:24:48 +03:00
RefPtr<IDBCursor> cursor =
new IDBCursor(Type_IndexKey, aBackgroundActor, std::move(aKey));
cursor->mSortKey = std::move(aSortKey);
cursor->mPrimaryKey = std::move(aPrimaryKey);
return cursor.forget();
}
// static
auto IDBCursor::ConvertDirection(IDBCursorDirection aDirection) -> Direction {
switch (aDirection) {
case mozilla::dom::IDBCursorDirection::Next:
return NEXT;
case mozilla::dom::IDBCursorDirection::Nextunique:
return NEXT_UNIQUE;
case mozilla::dom::IDBCursorDirection::Prev:
return PREV;
case mozilla::dom::IDBCursorDirection::Prevunique:
return PREV_UNIQUE;
default:
MOZ_CRASH("Unknown direction!");
}
}
#ifdef DEBUG
void IDBCursor::AssertIsOnOwningThread() const {
MOZ_ASSERT(mTransaction);
mTransaction->AssertIsOnOwningThread();
}
#endif // DEBUG
void IDBCursor::DropJSObjects() {
AssertIsOnOwningThread();
Reset();
if (!mRooted) {
return;
}
mRooted = false;
mozilla::DropJSObjects(this);
}
bool IDBCursor::IsSourceDeleted() const {
AssertIsOnOwningThread();
MOZ_ASSERT(mTransaction);
MOZ_ASSERT(mTransaction->IsOpen());
IDBObjectStore* sourceObjectStore;
if (mType == Type_Index || mType == Type_IndexKey) {
MOZ_ASSERT(mSourceIndex);
if (mSourceIndex->IsDeleted()) {
return true;
}
sourceObjectStore = mSourceIndex->ObjectStore();
MOZ_ASSERT(sourceObjectStore);
} else {
MOZ_ASSERT(mSourceObjectStore);
sourceObjectStore = mSourceObjectStore;
}
return sourceObjectStore->IsDeleted();
}
void IDBCursor::Reset() {
AssertIsOnOwningThread();
mCachedKey.setUndefined();
mCachedPrimaryKey.setUndefined();
mCachedValue.setUndefined();
IDBObjectStore::ClearCloneReadInfo(mCloneInfo);
mHaveCachedKey = false;
mHaveCachedPrimaryKey = false;
mHaveCachedValue = false;
mHaveValue = false;
mContinueCalled = false;
}
nsIGlobalObject* IDBCursor::GetParentObject() const {
AssertIsOnOwningThread();
MOZ_ASSERT(mTransaction);
return mTransaction->GetParentObject();
}
IDBCursorDirection IDBCursor::GetDirection() const {
AssertIsOnOwningThread();
switch (mDirection) {
case NEXT:
return IDBCursorDirection::Next;
case NEXT_UNIQUE:
return IDBCursorDirection::Nextunique;
case PREV:
return IDBCursorDirection::Prev;
case PREV_UNIQUE:
return IDBCursorDirection::Prevunique;
default:
MOZ_CRASH("Bad direction!");
}
}
IDBCursor::Type IDBCursor::GetType() const { return mType; }
void IDBCursor::GetSource(OwningIDBObjectStoreOrIDBIndex& aSource) const {
AssertIsOnOwningThread();
switch (mType) {
case Type_ObjectStore:
case Type_ObjectStoreKey:
MOZ_ASSERT(mSourceObjectStore);
aSource.SetAsIDBObjectStore() = mSourceObjectStore;
return;
case Type_Index:
case Type_IndexKey:
MOZ_ASSERT(mSourceIndex);
aSource.SetAsIDBIndex() = mSourceIndex;
return;
default:
MOZ_ASSERT_UNREACHABLE("Bad type!");
}
}
void IDBCursor::GetKey(JSContext* aCx, JS::MutableHandle<JS::Value> aResult,
ErrorResult& aRv) {
AssertIsOnOwningThread();
MOZ_ASSERT(!mKey.IsUnset() || !mHaveValue);
if (!mHaveValue) {
aResult.setUndefined();
return;
}
if (!mHaveCachedKey) {
if (!mRooted) {
mozilla::HoldJSObjects(this);
mRooted = true;
}
aRv = mKey.ToJSVal(aCx, mCachedKey);
if (NS_WARN_IF(aRv.Failed())) {
return;
}
mHaveCachedKey = true;
}
aResult.set(mCachedKey);
}
void IDBCursor::GetPrimaryKey(JSContext* aCx,
JS::MutableHandle<JS::Value> aResult,
ErrorResult& aRv) {
AssertIsOnOwningThread();
if (!mHaveValue) {
aResult.setUndefined();
return;
}
if (!mHaveCachedPrimaryKey) {
if (!mRooted) {
mozilla::HoldJSObjects(this);
mRooted = true;
}
const Key& key = (mType == Type_ObjectStore || mType == Type_ObjectStoreKey)
? mKey
: mPrimaryKey;
MOZ_ASSERT(!key.IsUnset());
aRv = key.ToJSVal(aCx, mCachedPrimaryKey);
if (NS_WARN_IF(aRv.Failed())) {
return;
}
mHaveCachedPrimaryKey = true;
}
aResult.set(mCachedPrimaryKey);
}
void IDBCursor::GetValue(JSContext* aCx, JS::MutableHandle<JS::Value> aResult,
ErrorResult& aRv) {
AssertIsOnOwningThread();
MOZ_ASSERT(mType == Type_ObjectStore || mType == Type_Index);
if (!mHaveValue) {
aResult.setUndefined();
return;
}
if (!mHaveCachedValue) {
if (!mRooted) {
mozilla::HoldJSObjects(this);
mRooted = true;
}
JS::Rooted<JS::Value> val(aCx);
if (NS_WARN_IF(!IDBObjectStore::DeserializeValue(aCx, mCloneInfo, &val))) {
aRv.Throw(NS_ERROR_DOM_DATA_CLONE_ERR);
return;
}
IDBObjectStore::ClearCloneReadInfo(mCloneInfo);
mCachedValue = val;
mHaveCachedValue = true;
}
aResult.set(mCachedValue);
}
void IDBCursor::Continue(JSContext* aCx, JS::Handle<JS::Value> aKey,
ErrorResult& aRv) {
AssertIsOnOwningThread();
if (!mTransaction->IsOpen()) {
aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR);
return;
}
if (IsSourceDeleted() || !mHaveValue || mContinueCalled) {
aRv.Throw(NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR);
return;
}
Key key;
auto result = key.SetFromJSVal(aCx, aKey, aRv);
if (!result.Is(Ok, aRv)) {
if (result.Is(Invalid, aRv)) {
aRv.Throw(NS_ERROR_DOM_INDEXEDDB_DATA_ERR);
}
return;
}
if (IsLocaleAware() && !key.IsUnset()) {
Key tmp;
result = key.ToLocaleAwareKey(tmp, mSourceIndex->Locale(), aRv);
if (!result.Is(Ok, aRv)) {
if (result.Is(Invalid, aRv)) {
aRv.Throw(NS_ERROR_DOM_INDEXEDDB_DATA_ERR);
}
return;
}
key = tmp;
}
const Key& sortKey = IsLocaleAware() ? mSortKey : mKey;
if (!key.IsUnset()) {
switch (mDirection) {
case NEXT:
case NEXT_UNIQUE:
if (key <= sortKey) {
aRv.Throw(NS_ERROR_DOM_INDEXEDDB_DATA_ERR);
return;
}
break;
case PREV:
case PREV_UNIQUE:
if (key >= sortKey) {
aRv.Throw(NS_ERROR_DOM_INDEXEDDB_DATA_ERR);
return;
}
break;
default:
MOZ_CRASH("Unknown direction type!");
}
}
const uint64_t requestSerialNumber = IDBRequest::NextSerialNumber();
mRequest->SetLoggingSerialNumber(requestSerialNumber);
if (mType == Type_ObjectStore || mType == Type_ObjectStoreKey) {
IDB_LOG_MARK_CHILD_TRANSACTION_REQUEST(
"database(%s).transaction(%s).objectStore(%s)."
"cursor(%s).continue(%s)",
"IDBCursor.continue()", mTransaction->LoggingSerialNumber(),
requestSerialNumber, IDB_LOG_STRINGIFY(mTransaction->Database()),
IDB_LOG_STRINGIFY(mTransaction), IDB_LOG_STRINGIFY(mSourceObjectStore),
IDB_LOG_STRINGIFY(mDirection), IDB_LOG_STRINGIFY(key));
} else {
IDB_LOG_MARK_CHILD_TRANSACTION_REQUEST(
"database(%s).transaction(%s).objectStore(%s)."
"index(%s).cursor(%s).continue(%s)",
"IDBCursor.continue()", mTransaction->LoggingSerialNumber(),
requestSerialNumber, IDB_LOG_STRINGIFY(mTransaction->Database()),
IDB_LOG_STRINGIFY(mTransaction),
IDB_LOG_STRINGIFY(mSourceIndex->ObjectStore()),
IDB_LOG_STRINGIFY(mSourceIndex), IDB_LOG_STRINGIFY(mDirection),
IDB_LOG_STRINGIFY(key));
}
mBackgroundActor->SendContinueInternal(ContinueParams(key), mKey,
mPrimaryKey);
mContinueCalled = true;
}
void IDBCursor::ContinuePrimaryKey(JSContext* aCx, JS::Handle<JS::Value> aKey,
JS::Handle<JS::Value> aPrimaryKey,
ErrorResult& aRv) {
AssertIsOnOwningThread();
if (!mTransaction->IsOpen()) {
aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR);
return;
}
if (IsSourceDeleted()) {
aRv.Throw(NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR);
return;
}
if ((mType != Type_Index && mType != Type_IndexKey) ||
(mDirection != NEXT && mDirection != PREV)) {
aRv.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR);
return;
}
if (!mHaveValue || mContinueCalled) {
aRv.Throw(NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR);
return;
}
Key key;
auto result = key.SetFromJSVal(aCx, aKey, aRv);
if (!result.Is(Ok, aRv)) {
if (result.Is(Invalid, aRv)) {
aRv.Throw(NS_ERROR_DOM_INDEXEDDB_DATA_ERR);
}
return;
}
if (IsLocaleAware() && !key.IsUnset()) {
Key tmp;
result = key.ToLocaleAwareKey(tmp, mSourceIndex->Locale(), aRv);
if (!result.Is(Ok, aRv)) {
if (result.Is(Invalid, aRv)) {
aRv.Throw(NS_ERROR_DOM_INDEXEDDB_DATA_ERR);
}
return;
}
key = tmp;
}
if (key.IsUnset()) {
aRv.Throw(NS_ERROR_DOM_INDEXEDDB_DATA_ERR);
return;
}
Key primaryKey;
result = primaryKey.SetFromJSVal(aCx, aPrimaryKey, aRv);
if (!result.Is(Ok, aRv)) {
if (result.Is(Invalid, aRv)) {
aRv.Throw(NS_ERROR_DOM_INDEXEDDB_DATA_ERR);
}
return;
}
if (primaryKey.IsUnset()) {
aRv.Throw(NS_ERROR_DOM_INDEXEDDB_DATA_ERR);
return;
}
const Key& sortKey = IsLocaleAware() ? mSortKey : mKey;
switch (mDirection) {
case NEXT:
if (key < sortKey || (key == sortKey && primaryKey <= mPrimaryKey)) {
aRv.Throw(NS_ERROR_DOM_INDEXEDDB_DATA_ERR);
return;
}
break;
case PREV:
if (key > sortKey || (key == sortKey && primaryKey >= mPrimaryKey)) {
aRv.Throw(NS_ERROR_DOM_INDEXEDDB_DATA_ERR);
return;
}
break;
default:
MOZ_CRASH("Unknown direction type!");
}
const uint64_t requestSerialNumber = IDBRequest::NextSerialNumber();
mRequest->SetLoggingSerialNumber(requestSerialNumber);
IDB_LOG_MARK_CHILD_TRANSACTION_REQUEST(
"database(%s).transaction(%s).objectStore(%s)."
"index(%s).cursor(%s).continuePrimaryKey(%s, %s)",
"IDBCursor.continuePrimaryKey()", mTransaction->LoggingSerialNumber(),
requestSerialNumber, IDB_LOG_STRINGIFY(mTransaction->Database()),
IDB_LOG_STRINGIFY(mTransaction),
IDB_LOG_STRINGIFY(mSourceIndex->ObjectStore()),
IDB_LOG_STRINGIFY(mSourceIndex), IDB_LOG_STRINGIFY(mDirection),
IDB_LOG_STRINGIFY(key), IDB_LOG_STRINGIFY(primaryKey));
mBackgroundActor->SendContinueInternal(
ContinuePrimaryKeyParams(key, primaryKey), mKey, mPrimaryKey);
mContinueCalled = true;
}
void IDBCursor::Advance(uint32_t aCount, ErrorResult& aRv) {
AssertIsOnOwningThread();
if (!aCount) {
aRv.ThrowTypeError(u"0 (Zero) is not a valid advance count.");
return;
}
if (!mTransaction->IsOpen()) {
aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR);
return;
}
if (IsSourceDeleted() || !mHaveValue || mContinueCalled) {
aRv.Throw(NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR);
return;
}
const uint64_t requestSerialNumber = IDBRequest::NextSerialNumber();
mRequest->SetLoggingSerialNumber(requestSerialNumber);
if (mType == Type_ObjectStore || mType == Type_ObjectStoreKey) {
IDB_LOG_MARK_CHILD_TRANSACTION_REQUEST(
"database(%s).transaction(%s).objectStore(%s)."
"cursor(%s).advance(%ld)",
"IDBCursor.advance()", mTransaction->LoggingSerialNumber(),
requestSerialNumber, IDB_LOG_STRINGIFY(mTransaction->Database()),
IDB_LOG_STRINGIFY(mTransaction), IDB_LOG_STRINGIFY(mSourceObjectStore),
IDB_LOG_STRINGIFY(mDirection), aCount);
} else {
IDB_LOG_MARK_CHILD_TRANSACTION_REQUEST(
"database(%s).transaction(%s).objectStore(%s)."
"index(%s).cursor(%s).advance(%ld)",
"IDBCursor.advance()", mTransaction->LoggingSerialNumber(),
requestSerialNumber, IDB_LOG_STRINGIFY(mTransaction->Database()),
IDB_LOG_STRINGIFY(mTransaction),
IDB_LOG_STRINGIFY(mSourceIndex->ObjectStore()),
IDB_LOG_STRINGIFY(mSourceIndex), IDB_LOG_STRINGIFY(mDirection), aCount);
}
mBackgroundActor->SendContinueInternal(AdvanceParams(aCount), mKey,
mPrimaryKey);
mContinueCalled = true;
}
already_AddRefed<IDBRequest> IDBCursor::Update(JSContext* aCx,
JS::Handle<JS::Value> aValue,
ErrorResult& aRv) {
AssertIsOnOwningThread();
if (!mTransaction->IsOpen()) {
aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR);
return nullptr;
}
if (!mTransaction->IsWriteAllowed()) {
aRv.Throw(NS_ERROR_DOM_INDEXEDDB_READ_ONLY_ERR);
return nullptr;
}
if (mTransaction->GetMode() == IDBTransaction::CLEANUP || IsSourceDeleted() ||
!mHaveValue || mType == Type_ObjectStoreKey || mType == Type_IndexKey ||
mContinueCalled) {
aRv.Throw(NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR);
return nullptr;
}
MOZ_ASSERT(mType == Type_ObjectStore || mType == Type_Index);
MOZ_ASSERT(!mKey.IsUnset());
MOZ_ASSERT_IF(mType == Type_Index, !mPrimaryKey.IsUnset());
mTransaction->InvalidateCursorCaches();
IDBObjectStore* objectStore;
if (mType == Type_ObjectStore) {
objectStore = mSourceObjectStore;
} else {
objectStore = mSourceIndex->ObjectStore();
}
MOZ_ASSERT(objectStore);
IDBObjectStore::ValueWrapper valueWrapper(aCx, aValue);
const Key& primaryKey = (mType == Type_ObjectStore) ? mKey : mPrimaryKey;
Bug 1207245 - part 6 - rename nsRefPtr<T> to RefPtr<T>; r=ehsan; a=Tomcat The bulk of this commit was generated with a script, executed at the top level of a typical source code checkout. The only non-machine-generated part was modifying MFBT's moz.build to reflect the new naming. CLOSED TREE makes big refactorings like this a piece of cake. # The main substitution. find . -name '*.cpp' -o -name '*.cc' -o -name '*.h' -o -name '*.mm' -o -name '*.idl'| \ xargs perl -p -i -e ' s/nsRefPtr\.h/RefPtr\.h/g; # handle includes s/nsRefPtr ?</RefPtr</g; # handle declarations and variables ' # Handle a special friend declaration in gfx/layers/AtomicRefCountedWithFinalize.h. perl -p -i -e 's/::nsRefPtr;/::RefPtr;/' gfx/layers/AtomicRefCountedWithFinalize.h # Handle nsRefPtr.h itself, a couple places that define constructors # from nsRefPtr, and code generators specially. We do this here, rather # than indiscriminantly s/nsRefPtr/RefPtr/, because that would rename # things like nsRefPtrHashtable. perl -p -i -e 's/nsRefPtr/RefPtr/g' \ mfbt/nsRefPtr.h \ xpcom/glue/nsCOMPtr.h \ xpcom/base/OwningNonNull.h \ ipc/ipdl/ipdl/lower.py \ ipc/ipdl/ipdl/builtin.py \ dom/bindings/Codegen.py \ python/lldbutils/lldbutils/utils.py # In our indiscriminate substitution above, we renamed # nsRefPtrGetterAddRefs, the class behind getter_AddRefs. Fix that up. find . -name '*.cpp' -o -name '*.h' -o -name '*.idl' | \ xargs perl -p -i -e 's/nsRefPtrGetterAddRefs/RefPtrGetterAddRefs/g' if [ -d .git ]; then git mv mfbt/nsRefPtr.h mfbt/RefPtr.h else hg mv mfbt/nsRefPtr.h mfbt/RefPtr.h fi --HG-- rename : mfbt/nsRefPtr.h => mfbt/RefPtr.h
2015-10-18 08:24:48 +03:00
RefPtr<IDBRequest> request;
if (objectStore->HasValidKeyPath()) {
if (!valueWrapper.Clone(aCx)) {
aRv.Throw(NS_ERROR_DOM_DATA_CLONE_ERR);
return nullptr;
}
// Make sure the object given has the correct keyPath value set on it.
const KeyPath& keyPath = objectStore->GetKeyPath();
Key key;
aRv = keyPath.ExtractKey(aCx, valueWrapper.Value(), key);
if (aRv.Failed()) {
return nullptr;
}
if (key != primaryKey) {
aRv.Throw(NS_ERROR_DOM_INDEXEDDB_DATA_ERR);
return nullptr;
}
request = objectStore->AddOrPut(aCx, valueWrapper,
/* aKey */ JS::UndefinedHandleValue,
/* aOverwrite */ true,
/* aFromCursor */ true, aRv);
if (aRv.Failed()) {
return nullptr;
}
} else {
JS::Rooted<JS::Value> keyVal(aCx);
aRv = primaryKey.ToJSVal(aCx, &keyVal);
if (aRv.Failed()) {
return nullptr;
}
request = objectStore->AddOrPut(aCx, valueWrapper, keyVal,
/* aOverwrite */ true,
/* aFromCursor */ true, aRv);
if (aRv.Failed()) {
return nullptr;
}
}
request->SetSource(this);
if (mType == Type_ObjectStore) {
IDB_LOG_MARK_CHILD_TRANSACTION_REQUEST(
" %s: Child Transaction[%lld] Request[%llu]: "
"database(%s).transaction(%s).objectStore(%s)."
"cursor(%s).update(%s)",
"IDBCursor.update()", mTransaction->LoggingSerialNumber(),
request->LoggingSerialNumber(),
IDB_LOG_STRINGIFY(mTransaction->Database()),
IDB_LOG_STRINGIFY(mTransaction), IDB_LOG_STRINGIFY(objectStore),
IDB_LOG_STRINGIFY(mDirection),
IDB_LOG_STRINGIFY(objectStore, primaryKey));
} else {
IDB_LOG_MARK_CHILD_TRANSACTION_REQUEST(
"database(%s).transaction(%s).objectStore(%s)."
"index(%s).cursor(%s).update(%s)",
"IDBCursor.update()", mTransaction->LoggingSerialNumber(),
request->LoggingSerialNumber(),
IDB_LOG_STRINGIFY(mTransaction->Database()),
IDB_LOG_STRINGIFY(mTransaction), IDB_LOG_STRINGIFY(objectStore),
IDB_LOG_STRINGIFY(mSourceIndex), IDB_LOG_STRINGIFY(mDirection),
IDB_LOG_STRINGIFY(objectStore, primaryKey));
}
return request.forget();
}
already_AddRefed<IDBRequest> IDBCursor::Delete(JSContext* aCx,
ErrorResult& aRv) {
AssertIsOnOwningThread();
if (!mTransaction->IsOpen()) {
aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR);
return nullptr;
}
if (!mTransaction->IsWriteAllowed()) {
aRv.Throw(NS_ERROR_DOM_INDEXEDDB_READ_ONLY_ERR);
return nullptr;
}
if (IsSourceDeleted() || !mHaveValue || mType == Type_ObjectStoreKey ||
mType == Type_IndexKey || mContinueCalled) {
aRv.Throw(NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR);
return nullptr;
}
MOZ_ASSERT(mType == Type_ObjectStore || mType == Type_Index);
MOZ_ASSERT(!mKey.IsUnset());
mTransaction->InvalidateCursorCaches();
IDBObjectStore* const objectStore = mType == Type_ObjectStore
? mSourceObjectStore.get()
: mSourceIndex->ObjectStore();
MOZ_ASSERT(objectStore);
const Key& primaryKey = (mType == Type_ObjectStore) ? mKey : mPrimaryKey;
JS::Rooted<JS::Value> key(aCx);
aRv = primaryKey.ToJSVal(aCx, &key);
if (NS_WARN_IF(aRv.Failed())) {
return nullptr;
}
Bug 1207245 - part 6 - rename nsRefPtr<T> to RefPtr<T>; r=ehsan; a=Tomcat The bulk of this commit was generated with a script, executed at the top level of a typical source code checkout. The only non-machine-generated part was modifying MFBT's moz.build to reflect the new naming. CLOSED TREE makes big refactorings like this a piece of cake. # The main substitution. find . -name '*.cpp' -o -name '*.cc' -o -name '*.h' -o -name '*.mm' -o -name '*.idl'| \ xargs perl -p -i -e ' s/nsRefPtr\.h/RefPtr\.h/g; # handle includes s/nsRefPtr ?</RefPtr</g; # handle declarations and variables ' # Handle a special friend declaration in gfx/layers/AtomicRefCountedWithFinalize.h. perl -p -i -e 's/::nsRefPtr;/::RefPtr;/' gfx/layers/AtomicRefCountedWithFinalize.h # Handle nsRefPtr.h itself, a couple places that define constructors # from nsRefPtr, and code generators specially. We do this here, rather # than indiscriminantly s/nsRefPtr/RefPtr/, because that would rename # things like nsRefPtrHashtable. perl -p -i -e 's/nsRefPtr/RefPtr/g' \ mfbt/nsRefPtr.h \ xpcom/glue/nsCOMPtr.h \ xpcom/base/OwningNonNull.h \ ipc/ipdl/ipdl/lower.py \ ipc/ipdl/ipdl/builtin.py \ dom/bindings/Codegen.py \ python/lldbutils/lldbutils/utils.py # In our indiscriminate substitution above, we renamed # nsRefPtrGetterAddRefs, the class behind getter_AddRefs. Fix that up. find . -name '*.cpp' -o -name '*.h' -o -name '*.idl' | \ xargs perl -p -i -e 's/nsRefPtrGetterAddRefs/RefPtrGetterAddRefs/g' if [ -d .git ]; then git mv mfbt/nsRefPtr.h mfbt/RefPtr.h else hg mv mfbt/nsRefPtr.h mfbt/RefPtr.h fi --HG-- rename : mfbt/nsRefPtr.h => mfbt/RefPtr.h
2015-10-18 08:24:48 +03:00
RefPtr<IDBRequest> request =
objectStore->DeleteInternal(aCx, key, /* aFromCursor */ true, aRv);
if (aRv.Failed()) {
return nullptr;
}
request->SetSource(this);
if (mType == Type_ObjectStore) {
IDB_LOG_MARK_CHILD_TRANSACTION_REQUEST(
"database(%s).transaction(%s).objectStore(%s)."
"cursor(%s).delete(%s)",
"IDBCursor.delete()", mTransaction->LoggingSerialNumber(),
request->LoggingSerialNumber(),
IDB_LOG_STRINGIFY(mTransaction->Database()),
IDB_LOG_STRINGIFY(mTransaction), IDB_LOG_STRINGIFY(objectStore),
IDB_LOG_STRINGIFY(mDirection),
IDB_LOG_STRINGIFY(objectStore, primaryKey));
} else {
IDB_LOG_MARK_CHILD_TRANSACTION_REQUEST(
"database(%s).transaction(%s).objectStore(%s)."
"index(%s).cursor(%s).delete(%s)",
"IDBCursor.delete()", mTransaction->LoggingSerialNumber(),
request->LoggingSerialNumber(),
IDB_LOG_STRINGIFY(mTransaction->Database()),
IDB_LOG_STRINGIFY(mTransaction), IDB_LOG_STRINGIFY(objectStore),
IDB_LOG_STRINGIFY(mSourceIndex), IDB_LOG_STRINGIFY(mDirection),
IDB_LOG_STRINGIFY(objectStore, primaryKey));
}
return request.forget();
}
void IDBCursor::Reset(Key&& aKey, StructuredCloneReadInfo&& aValue) {
AssertIsOnOwningThread();
MOZ_ASSERT(mType == Type_ObjectStore);
Reset();
mKey = std::move(aKey);
mCloneInfo = std::move(aValue);
mHaveValue = !mKey.IsUnset();
}
void IDBCursor::Reset(Key&& aKey) {
AssertIsOnOwningThread();
MOZ_ASSERT(mType == Type_ObjectStoreKey);
Reset();
mKey = std::move(aKey);
mHaveValue = !mKey.IsUnset();
}
void IDBCursor::Reset(Key&& aKey, Key&& aSortKey, Key&& aPrimaryKey,
StructuredCloneReadInfo&& aValue) {
AssertIsOnOwningThread();
MOZ_ASSERT(mType == Type_Index);
Reset();
mKey = std::move(aKey);
mSortKey = std::move(aSortKey);
mPrimaryKey = std::move(aPrimaryKey);
mCloneInfo = std::move(aValue);
2010-09-10 08:54:25 +04:00
mHaveValue = !mKey.IsUnset();
}
void IDBCursor::Reset(Key&& aKey, Key&& aSortKey, Key&& aPrimaryKey) {
AssertIsOnOwningThread();
MOZ_ASSERT(mType == Type_IndexKey);
Reset();
mKey = std::move(aKey);
mSortKey = std::move(aSortKey);
mPrimaryKey = std::move(aPrimaryKey);
mHaveValue = !mKey.IsUnset();
}
void IDBCursor::InvalidateCachedResponses() {
AssertIsOnOwningThread();
// TODO: In what case would mBackgroundActor be nullptr?
if (mBackgroundActor) {
mBackgroundActor->InvalidateCachedResponses();
}
}
NS_IMPL_CYCLE_COLLECTING_ADDREF(IDBCursor)
NS_IMPL_CYCLE_COLLECTING_RELEASE(IDBCursor)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(IDBCursor)
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_INTERFACE_MAP_END
NS_IMPL_CYCLE_COLLECTION_CLASS(IDBCursor)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(IDBCursor)
2014-11-08 03:42:53 +03:00
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mRequest)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSourceObjectStore)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSourceIndex)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(IDBCursor)
MOZ_ASSERT_IF(!tmp->mHaveCachedKey, tmp->mCachedKey.isUndefined());
MOZ_ASSERT_IF(!tmp->mHaveCachedPrimaryKey,
tmp->mCachedPrimaryKey.isUndefined());
MOZ_ASSERT_IF(!tmp->mHaveCachedValue, tmp->mCachedValue.isUndefined());
NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mCachedKey)
NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mCachedPrimaryKey)
NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mCachedValue)
NS_IMPL_CYCLE_COLLECTION_TRACE_END
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(IDBCursor)
2014-11-08 03:42:53 +03:00
// Don't unlink mRequest, mSourceObjectStore, or mSourceIndex!
NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
tmp->DropJSObjects();
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
Bug 1117172 part 3. Change the wrappercached WrapObject methods to allow passing in aGivenProto. r=peterv The only manual changes here are to BindingUtils.h, BindingUtils.cpp, Codegen.py, Element.cpp, IDBFileRequest.cpp, IDBObjectStore.cpp, dom/workers/Navigator.cpp, WorkerPrivate.cpp, DeviceStorageRequestChild.cpp, Notification.cpp, nsGlobalWindow.cpp, MessagePort.cpp, nsJSEnvironment.cpp, Sandbox.cpp, XPCConvert.cpp, ExportHelpers.cpp, and DataStoreService.cpp. The rest of this diff was generated by running the following commands: find . -name "*.h" -o -name "*.cpp" | xargs perl -pi -e 'BEGIN { $/ = undef } s/(WrapObjectInternal\(JSContext *\* *(?:aCx|cx|aContext|aCtx|js))\)/\1, JS::Handle<JSObject*> aGivenProto)/g' find . -name "*.h" -o -name "*.cpp" | xargs perl -pi -e 'BEGIN { $/ = undef } s/(WrapObjectInternal\((?:aCx|cx|aContext|aCtx|js))\)/\1, aGivenProto)/g' find . -name "*.h" -o -name "*.cpp" | xargs perl -pi -e 'BEGIN { $/ = undef } s/(WrapNode\(JSContext *\* *(?:aCx|cx|aContext|aCtx|js))\)/\1, JS::Handle<JSObject*> aGivenProto)/g' find . -name "*.h" -o -name "*.cpp" | xargs perl -pi -e 'BEGIN { $/ = undef } s/(WrapNode\((?:aCx|cx|aContext|aCtx|js))\)/\1, aGivenProto)/g' find . -name "*.h" -o -name "*.cpp" | xargs perl -pi -e 'BEGIN { $/ = undef } s/(WrapObject\(JSContext *\* *(?:aCx|cx|aContext|aCtx|js))\)/\1, JS::Handle<JSObject*> aGivenProto)/g' find . -name "*.h" -o -name "*.cpp" | xargs perl -pi -e 'BEGIN { $/ = undef } s/(Binding(?:_workers)?::Wrap\((?:aCx|cx|aContext|aCtx|js), [^,)]+)\)/\1, aGivenProto)/g'
2015-03-19 17:13:33 +03:00
JSObject* IDBCursor::WrapObject(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto) {
AssertIsOnOwningThread();
switch (mType) {
case Type_ObjectStore:
case Type_Index:
return IDBCursorWithValue_Binding::Wrap(aCx, this, aGivenProto);
case Type_ObjectStoreKey:
case Type_IndexKey:
return IDBCursor_Binding::Wrap(aCx, this, aGivenProto);
default:
MOZ_CRASH("Bad type!");
}
}
} // namespace dom
} // namespace mozilla