void IDBCursor::Advance(uint32_t aCount, ErrorResult &aRv) { AssertIsOnOwningThread(); if (!aCount) { aRv.ThrowTypeError<MSG_INVALID_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("IndexedDB %s: Child Transaction[%lld] Request[%llu]: " "database(%s).transaction(%s).objectStore(%s)." "cursor(%s).advance(%ld)", "IndexedDB %s: C T[%lld] R[%llu]: IDBCursor.advance()", IDB_LOG_ID_STRING(), 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("IndexedDB %s: Child Transaction[%lld] Request[%llu]: " "database(%s).transaction(%s).objectStore(%s)." "index(%s).cursor(%s).advance(%ld)", "IndexedDB %s: C T[%lld] R[%llu]: IDBCursor.advance()", IDB_LOG_ID_STRING(), 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)); mContinueCalled = true; }
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()); IDBObjectStore* objectStore; if (mType == Type_ObjectStore) { objectStore = mSourceObjectStore; } else { objectStore = 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; } 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("IndexedDB %s: Child Transaction[%lld] Request[%llu]: " "database(%s).transaction(%s).objectStore(%s)." "cursor(%s).delete(%s)", "IndexedDB %s: C T[%lld] R[%llu]: IDBCursor.delete()", IDB_LOG_ID_STRING(), 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("IndexedDB %s: Child Transaction[%lld] Request[%llu]: " "database(%s).transaction(%s).objectStore(%s)." "index(%s).cursor(%s).delete(%s)", "IndexedDB %s: C T[%lld] R[%llu]: IDBCursor.delete()", IDB_LOG_ID_STRING(), 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::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()); 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; 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("IndexedDB %s: Child Transaction[%lld] Request[%llu]: " "database(%s).transaction(%s).objectStore(%s)." "cursor(%s).update(%s)", "IndexedDB %s: C T[%lld] R[%llu]: IDBCursor.update()", IDB_LOG_ID_STRING(), 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("IndexedDB %s: Child Transaction[%lld] Request[%llu]: " "database(%s).transaction(%s).objectStore(%s)." "index(%s).cursor(%s).update(%s)", "IndexedDB %s: C T[%lld] R[%llu]: IDBCursor.update()", IDB_LOG_ID_STRING(), 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::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; aRv = key.SetFromJSVal(aCx, aKey); if (aRv.Failed()) { return; } if (IsLocaleAware() && !key.IsUnset()) { Key tmp; aRv = key.ToLocaleBasedKey(tmp, mSourceIndex->Locale()); if (aRv.Failed()) { return; } key = tmp; } const Key& sortKey = IsLocaleAware() ? mSortKey : mKey; if (key.IsUnset()) { aRv.Throw(NS_ERROR_DOM_INDEXEDDB_DATA_ERR); return; } Key primaryKey; aRv = primaryKey.SetFromJSVal(aCx, aPrimaryKey); if (aRv.Failed()) { return; } if (primaryKey.IsUnset()) { aRv.Throw(NS_ERROR_DOM_INDEXEDDB_DATA_ERR); return; } 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("IndexedDB %s: Child Transaction[%lld] Request[%llu]: " "database(%s).transaction(%s).objectStore(%s)." "index(%s).cursor(%s).continuePrimaryKey(%s, %s)", "IndexedDB %s: C T[%lld] R[%llu]: IDBCursor.continuePrimaryKey()", IDB_LOG_ID_STRING(), 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)); mContinueCalled = true; }
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; aRv = key.SetFromJSVal(aCx, aKey); if (aRv.Failed()) { return; } #ifdef ENABLE_INTL_API if (IsLocaleAware() && !key.IsUnset()) { Key tmp; aRv = key.ToLocaleBasedKey(tmp, mSourceIndex->Locale()); if (aRv.Failed()) { return; } key = tmp; } const Key& sortKey = IsLocaleAware() ? mSortKey : mKey; #else const Key& sortKey = mKey; #endif 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("IndexedDB %s: Child Transaction[%lld] Request[%llu]: " "database(%s).transaction(%s).objectStore(%s)." "cursor(%s).continue(%s)", "IndexedDB %s: C T[%lld] R[%llu]: IDBCursor.continue()", IDB_LOG_ID_STRING(), 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("IndexedDB %s: Child Transaction[%lld] Request[%llu]: " "database(%s).transaction(%s).objectStore(%s)." "index(%s).cursor(%s).continue(%s)", "IndexedDB %s: C T[%lld] R[%llu]: IDBCursor.continue()", IDB_LOG_ID_STRING(), 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)); mContinueCalled = true; }