/* -*- 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_idbobjectstore_h__ #define mozilla_dom_idbobjectstore_h__ #include "IDBCursor.h" #include "js/RootingAPI.h" #include "mozilla/dom/IDBCursorBinding.h" #include "mozilla/dom/IDBIndexBinding.h" #include "mozilla/UniquePtr.h" #include "nsCycleCollectionParticipant.h" #include "nsISupports.h" #include "nsString.h" #include "nsTArray.h" #include "nsWrapperCache.h" struct JSClass; class nsIGlobalObject; namespace mozilla { class ErrorResult; namespace dom { class DOMStringList; class IDBRequest; class IDBTransaction; class StringOrStringSequence; template class Sequence; namespace indexedDB { class Key; class KeyPath; class IndexUpdateInfo; class ObjectStoreSpec; struct StructuredCloneReadInfoChild; } // namespace indexedDB class IDBObjectStore final : public nsISupports, public nsWrapperCache { using IndexUpdateInfo = indexedDB::IndexUpdateInfo; using Key = indexedDB::Key; using KeyPath = indexedDB::KeyPath; using ObjectStoreSpec = indexedDB::ObjectStoreSpec; using StructuredCloneReadInfoChild = indexedDB::StructuredCloneReadInfoChild; using VoidOrObjectStoreKeyPathString = nsAString; // For AddOrPut() and DeleteInternal(). // TODO Consider removing this, and making the functions public? template friend class IDBTypedCursor; static const JSClass sDummyPropJSClass; // TODO: This could be made const if Bug 1575173 is resolved. It is // initialized in the constructor and never modified/cleared. SafeRefPtr mTransaction; JS::Heap mCachedKeyPath; // This normally points to the ObjectStoreSpec owned by the parent IDBDatabase // object. However, if this objectStore is part of a versionchange transaction // and it gets deleted then the spec is copied into mDeletedSpec and mSpec is // set to point at mDeletedSpec. ObjectStoreSpec* mSpec; UniquePtr mDeletedSpec; nsTArray> mIndexes; nsTArray> mDeletedIndexes; const int64_t mId; bool mRooted; public: struct StructuredCloneWriteInfo; struct StructuredCloneInfo; class MOZ_STACK_CLASS ValueWrapper final { JS::Rooted mValue; bool mCloned; public: ValueWrapper(JSContext* aCx, JS::Handle aValue) : mValue(aCx, aValue), mCloned(false) { MOZ_COUNT_CTOR(IDBObjectStore::ValueWrapper); } MOZ_COUNTED_DTOR_NESTED(ValueWrapper, IDBObjectStore::ValueWrapper) const JS::Rooted& Value() const { return mValue; } bool Clone(JSContext* aCx); }; [[nodiscard]] static RefPtr Create( SafeRefPtr aTransaction, ObjectStoreSpec& aSpec); static void AppendIndexUpdateInfo( int64_t aIndexID, const KeyPath& aKeyPath, bool aMultiEntry, const nsCString& aLocale, JSContext* aCx, JS::Handle aVal, nsTArray* aUpdateInfoArray, const VoidOrObjectStoreKeyPathString& aAutoIncrementedObjectStoreKeyPath, ErrorResult* aRv); static void ClearCloneReadInfo( indexedDB::StructuredCloneReadInfoChild& aReadInfo); static bool DeserializeValue(JSContext* aCx, StructuredCloneReadInfoChild&& aCloneReadInfo, JS::MutableHandle aValue); static const JSClass* DummyPropClass() { return &sDummyPropJSClass; } void AssertIsOnOwningThread() const #ifdef DEBUG ; #else { } #endif int64_t Id() const { AssertIsOnOwningThread(); return mId; } const nsString& Name() const; bool AutoIncrement() const; const KeyPath& GetKeyPath() const; bool HasValidKeyPath() const; nsIGlobalObject* GetParentObject() const; void GetName(nsString& aName) const { AssertIsOnOwningThread(); aName = Name(); } void SetName(const nsAString& aName, ErrorResult& aRv); void GetKeyPath(JSContext* aCx, JS::MutableHandle aResult, ErrorResult& aRv); [[nodiscard]] RefPtr IndexNames(); const IDBTransaction& TransactionRef() const { AssertIsOnOwningThread(); return *mTransaction; } IDBTransaction& MutableTransactionRef() { AssertIsOnOwningThread(); return *mTransaction; } SafeRefPtr AcquireTransaction() const { AssertIsOnOwningThread(); return mTransaction.clonePtr(); } RefPtr Transaction() const { AssertIsOnOwningThread(); return AsRefPtr(mTransaction.clonePtr()); } [[nodiscard]] RefPtr Add(JSContext* aCx, JS::Handle aValue, JS::Handle aKey, ErrorResult& aRv); [[nodiscard]] RefPtr Put(JSContext* aCx, JS::Handle aValue, JS::Handle aKey, ErrorResult& aRv); [[nodiscard]] RefPtr Delete(JSContext* aCx, JS::Handle aKey, ErrorResult& aRv); [[nodiscard]] RefPtr Get(JSContext* aCx, JS::Handle aKey, ErrorResult& aRv); [[nodiscard]] RefPtr GetKey(JSContext* aCx, JS::Handle aKey, ErrorResult& aRv); [[nodiscard]] RefPtr Clear(JSContext* aCx, ErrorResult& aRv); [[nodiscard]] RefPtr CreateIndex( const nsAString& aName, const StringOrStringSequence& aKeyPath, const IDBIndexParameters& aOptionalParameters, ErrorResult& aRv); [[nodiscard]] RefPtr Index(const nsAString& aName, ErrorResult& aRv); void DeleteIndex(const nsAString& aName, ErrorResult& aRv); [[nodiscard]] RefPtr Count(JSContext* aCx, JS::Handle aKey, ErrorResult& aRv); [[nodiscard]] RefPtr GetAll(JSContext* aCx, JS::Handle aKey, const Optional& aLimit, ErrorResult& aRv); [[nodiscard]] RefPtr GetAllKeys(JSContext* aCx, JS::Handle aKey, const Optional& aLimit, ErrorResult& aRv); [[nodiscard]] RefPtr OpenCursor(JSContext* aCx, JS::Handle aRange, IDBCursorDirection aDirection, ErrorResult& aRv); [[nodiscard]] RefPtr OpenCursor(JSContext* aCx, IDBCursorDirection aDirection, ErrorResult& aRv); [[nodiscard]] RefPtr OpenKeyCursor(JSContext* aCx, JS::Handle aRange, IDBCursorDirection aDirection, ErrorResult& aRv); void RefreshSpec(bool aMayDelete); const ObjectStoreSpec& Spec() const; void NoteDeletion(); bool IsDeleted() const { AssertIsOnOwningThread(); return !!mDeletedSpec; } NS_DECL_CYCLE_COLLECTING_ISUPPORTS NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(IDBObjectStore) // nsWrapperCache virtual JSObject* WrapObject(JSContext* aCx, JS::Handle aGivenProto) override; private: IDBObjectStore(SafeRefPtr aTransaction, ObjectStoreSpec* aSpec); ~IDBObjectStore(); void GetAddInfo(JSContext* aCx, ValueWrapper& aValueWrapper, JS::Handle aKeyVal, StructuredCloneWriteInfo& aCloneWriteInfo, Key& aKey, nsTArray& aUpdateInfoArray, ErrorResult& aRv); [[nodiscard]] RefPtr AddOrPut(JSContext* aCx, ValueWrapper& aValueWrapper, JS::Handle aKey, bool aOverwrite, bool aFromCursor, ErrorResult& aRv); [[nodiscard]] RefPtr DeleteInternal(JSContext* aCx, JS::Handle aKey, bool aFromCursor, ErrorResult& aRv); [[nodiscard]] RefPtr GetInternal(bool aKeyOnly, JSContext* aCx, JS::Handle aKey, ErrorResult& aRv); [[nodiscard]] RefPtr GetAllInternal( bool aKeysOnly, JSContext* aCx, JS::Handle aKey, const Optional& aLimit, ErrorResult& aRv); [[nodiscard]] RefPtr OpenCursorInternal( bool aKeysOnly, JSContext* aCx, JS::Handle aRange, IDBCursorDirection aDirection, ErrorResult& aRv); }; } // namespace dom } // namespace mozilla #endif // mozilla_dom_idbobjectstore_h__