/* -*- 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_idbcursor_h__ #define mozilla_dom_idbcursor_h__ #include "IndexedDatabase.h" #include "js/RootingAPI.h" #include "mozilla/Attributes.h" #include "mozilla/dom/IDBCursorBinding.h" #include "mozilla/dom/indexedDB/Key.h" #include "nsCycleCollectionParticipant.h" #include "nsWrapperCache.h" class nsIGlobalObject; namespace mozilla { class ErrorResult; namespace dom { class IDBIndex; class IDBObjectStore; class IDBRequest; class IDBTransaction; class OwningIDBObjectStoreOrIDBIndex; namespace indexedDB { class BackgroundCursorChild; } // 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: typedef indexedDB::Key Key; typedef indexedDB::StructuredCloneReadInfo StructuredCloneReadInfo; enum Direction { NEXT = 0, NEXT_UNIQUE, PREV, PREV_UNIQUE, // Only needed for IPC serialization helper, should never be used in code. DIRECTION_INVALID }; enum Type { Type_ObjectStore, Type_ObjectStoreKey, Type_Index, Type_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 mRequest; RefPtr mSourceObjectStore; RefPtr mSourceIndex; // mSourceObjectStore or mSourceIndex will hold this alive. IDBTransaction* const mTransaction; // These are cycle-collected! JS::Heap mCachedKey; JS::Heap mCachedPrimaryKey; JS::Heap 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; bool mHaveCachedPrimaryKey : 1; bool mHaveCachedValue : 1; bool mRooted : 1; bool mContinueCalled : 1; bool mHaveValue : 1; public: static already_AddRefed Create( indexedDB::BackgroundCursorChild* aBackgroundActor, Key aKey, StructuredCloneReadInfo&& aCloneInfo); static already_AddRefed Create( indexedDB::BackgroundCursorChild* aBackgroundActor, Key aKey); static already_AddRefed Create( indexedDB::BackgroundCursorChild* aBackgroundActor, Key aKey, Key aSortKey, Key aPrimaryKey, StructuredCloneReadInfo&& aCloneInfo); static already_AddRefed Create( indexedDB::BackgroundCursorChild* aBackgroundActor, Key aKey, Key aSortKey, Key aPrimaryKey); static Direction ConvertDirection(IDBCursorDirection aDirection); void AssertIsOnOwningThread() const #ifdef DEBUG ; #else { } #endif nsIGlobalObject* GetParentObject() const; void GetSource(OwningIDBObjectStoreOrIDBIndex& aSource) const; IDBCursorDirection GetDirection() const; Type GetType() const; void GetKey(JSContext* aCx, JS::MutableHandle aResult, ErrorResult& aRv); void GetPrimaryKey(JSContext* aCx, JS::MutableHandle aResult, ErrorResult& aRv); void GetValue(JSContext* aCx, JS::MutableHandle aResult, ErrorResult& aRv); void Continue(JSContext* aCx, JS::Handle aKey, ErrorResult& aRv); void ContinuePrimaryKey(JSContext* aCx, JS::Handle aKey, JS::Handle aPrimaryKey, ErrorResult& aRv); void Advance(uint32_t aCount, ErrorResult& aRv); already_AddRefed Update(JSContext* aCx, JS::Handle aValue, ErrorResult& aRv); already_AddRefed 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 = nullptr; } void InvalidateCachedResponses(); // Checks if this is a locale aware cursor (ie. the index's sortKey is unset) bool IsLocaleAware() const; NS_DECL_CYCLE_COLLECTING_ISUPPORTS NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(IDBCursor) // nsWrapperCache virtual JSObject* WrapObject(JSContext* aCx, JS::Handle aGivenProto) override; private: IDBCursor(Type aType, indexedDB::BackgroundCursorChild* aBackgroundActor, Key aKey); ~IDBCursor(); void DropJSObjects(); bool IsSourceDeleted() const; }; } // namespace dom } // namespace mozilla #endif // mozilla_dom_idbcursor_h__