IDBObjectStore.h (10042B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #ifndef mozilla_dom_idbobjectstore_h__ 8 #define mozilla_dom_idbobjectstore_h__ 9 10 #include "IDBCursor.h" 11 #include "js/RootingAPI.h" 12 #include "mozilla/UniquePtr.h" 13 #include "mozilla/dom/IDBCursorBinding.h" 14 #include "mozilla/dom/IDBIndexBinding.h" 15 #include "nsCycleCollectionParticipant.h" 16 #include "nsISupports.h" 17 #include "nsString.h" 18 #include "nsTArray.h" 19 #include "nsWrapperCache.h" 20 21 struct JSClass; 22 class nsIGlobalObject; 23 24 namespace mozilla { 25 26 class ErrorResult; 27 28 namespace dom { 29 30 class DOMStringList; 31 class IDBRequest; 32 class IDBTransaction; 33 class StringOrStringSequence; 34 template <typename> 35 class Sequence; 36 37 namespace indexedDB { 38 class Key; 39 class KeyPath; 40 class IndexUpdateInfo; 41 class ObjectStoreSpec; 42 struct StructuredCloneReadInfoChild; 43 } // namespace indexedDB 44 45 class IDBObjectStore final : public nsISupports, public nsWrapperCache { 46 using IndexUpdateInfo = indexedDB::IndexUpdateInfo; 47 using Key = indexedDB::Key; 48 using KeyPath = indexedDB::KeyPath; 49 using ObjectStoreSpec = indexedDB::ObjectStoreSpec; 50 using StructuredCloneReadInfoChild = indexedDB::StructuredCloneReadInfoChild; 51 using VoidOrObjectStoreKeyPathString = nsAString; 52 53 // For AddOrPut() and DeleteInternal(). 54 // TODO Consider removing this, and making the functions public? 55 template <IDBCursor::Type> 56 friend class IDBTypedCursor; 57 58 static const JSClass sDummyPropJSClass; 59 60 // TODO: This could be made const if Bug 1575173 is resolved. It is 61 // initialized in the constructor and never modified/cleared. 62 SafeRefPtr<IDBTransaction> mTransaction; 63 JS::Heap<JS::Value> mCachedKeyPath; 64 65 // This normally points to the ObjectStoreSpec owned by the parent IDBDatabase 66 // object. However, if this objectStore is part of a versionchange transaction 67 // and it gets deleted then the spec is copied into mDeletedSpec and mSpec is 68 // set to point at mDeletedSpec. 69 ObjectStoreSpec* mSpec; 70 UniquePtr<ObjectStoreSpec> mDeletedSpec; 71 72 nsTArray<RefPtr<IDBIndex>> mIndexes; 73 nsTArray<RefPtr<IDBIndex>> mDeletedIndexes; 74 75 const int64_t mId; 76 bool mRooted; 77 78 public: 79 struct StructuredCloneWriteInfo; 80 struct StructuredCloneInfo; 81 82 class MOZ_STACK_CLASS ValueWrapper final { 83 JS::Rooted<JS::Value> mValue; 84 bool mCloned; 85 86 public: 87 ValueWrapper(JSContext* aCx, JS::Handle<JS::Value> aValue) 88 : mValue(aCx, aValue), mCloned(false) { 89 MOZ_COUNT_CTOR(IDBObjectStore::ValueWrapper); 90 } 91 92 MOZ_COUNTED_DTOR_NESTED(ValueWrapper, IDBObjectStore::ValueWrapper) 93 94 const JS::Rooted<JS::Value>& Value() const { return mValue; } 95 96 bool Clone(JSContext* aCx); 97 }; 98 99 [[nodiscard]] static RefPtr<IDBObjectStore> Create( 100 SafeRefPtr<IDBTransaction> aTransaction, ObjectStoreSpec& aSpec); 101 102 static void AppendIndexUpdateInfo( 103 int64_t aIndexID, const KeyPath& aKeyPath, bool aMultiEntry, 104 const nsCString& aLocale, JSContext* aCx, JS::Handle<JS::Value> aVal, 105 nsTArray<IndexUpdateInfo>* aUpdateInfoArray, 106 const VoidOrObjectStoreKeyPathString& aAutoIncrementedObjectStoreKeyPath, 107 ErrorResult* aRv); 108 109 static void ClearCloneReadInfo( 110 indexedDB::StructuredCloneReadInfoChild& aReadInfo); 111 112 static bool DeserializeValue(JSContext* aCx, 113 StructuredCloneReadInfoChild&& aCloneReadInfo, 114 JS::MutableHandle<JS::Value> aValue); 115 116 static const JSClass* DummyPropClass() { return &sDummyPropJSClass; } 117 118 void AssertIsOnOwningThread() const 119 #ifdef DEBUG 120 ; 121 #else 122 { 123 } 124 #endif 125 126 int64_t Id() const { 127 AssertIsOnOwningThread(); 128 129 return mId; 130 } 131 132 const nsString& Name() const; 133 134 bool AutoIncrement() const; 135 136 const KeyPath& GetKeyPath() const; 137 138 bool HasValidKeyPath() const; 139 140 nsIGlobalObject* GetParentObject() const; 141 142 void GetName(nsString& aName) const { 143 AssertIsOnOwningThread(); 144 145 aName = Name(); 146 } 147 148 void SetName(const nsAString& aName, ErrorResult& aRv); 149 150 void GetKeyPath(JSContext* aCx, JS::MutableHandle<JS::Value> aResult, 151 ErrorResult& aRv); 152 153 [[nodiscard]] RefPtr<DOMStringList> IndexNames(); 154 155 const IDBTransaction& TransactionRef() const { 156 AssertIsOnOwningThread(); 157 158 return *mTransaction; 159 } 160 161 IDBTransaction& MutableTransactionRef() { 162 AssertIsOnOwningThread(); 163 164 return *mTransaction; 165 } 166 167 SafeRefPtr<IDBTransaction> AcquireTransaction() const { 168 AssertIsOnOwningThread(); 169 170 return mTransaction.clonePtr(); 171 } 172 173 RefPtr<IDBTransaction> Transaction() const { 174 AssertIsOnOwningThread(); 175 176 return AsRefPtr(mTransaction.clonePtr()); 177 } 178 179 [[nodiscard]] RefPtr<IDBRequest> Add(JSContext* aCx, 180 JS::Handle<JS::Value> aValue, 181 JS::Handle<JS::Value> aKey, 182 ErrorResult& aRv); 183 184 [[nodiscard]] RefPtr<IDBRequest> Put(JSContext* aCx, 185 JS::Handle<JS::Value> aValue, 186 JS::Handle<JS::Value> aKey, 187 ErrorResult& aRv); 188 189 [[nodiscard]] RefPtr<IDBRequest> Delete(JSContext* aCx, 190 JS::Handle<JS::Value> aKey, 191 ErrorResult& aRv); 192 193 [[nodiscard]] RefPtr<IDBRequest> Get(JSContext* aCx, 194 JS::Handle<JS::Value> aKey, 195 ErrorResult& aRv); 196 197 [[nodiscard]] RefPtr<IDBRequest> GetKey(JSContext* aCx, 198 JS::Handle<JS::Value> aKey, 199 ErrorResult& aRv); 200 201 [[nodiscard]] RefPtr<IDBRequest> Clear(JSContext* aCx, ErrorResult& aRv); 202 203 [[nodiscard]] RefPtr<IDBIndex> CreateIndex( 204 const nsAString& aName, const StringOrStringSequence& aKeyPath, 205 const IDBIndexParameters& aOptionalParameters, ErrorResult& aRv); 206 207 [[nodiscard]] RefPtr<IDBIndex> Index(const nsAString& aName, 208 ErrorResult& aRv); 209 210 void DeleteIndex(const nsAString& aName, ErrorResult& aRv); 211 212 [[nodiscard]] RefPtr<IDBRequest> Count(JSContext* aCx, 213 JS::Handle<JS::Value> aKey, 214 ErrorResult& aRv); 215 216 [[nodiscard]] RefPtr<IDBRequest> GetAll(JSContext* aCx, 217 JS::Handle<JS::Value> aKey, 218 const Optional<uint32_t>& aLimit, 219 ErrorResult& aRv); 220 221 [[nodiscard]] RefPtr<IDBRequest> GetAllKeys(JSContext* aCx, 222 JS::Handle<JS::Value> aKey, 223 const Optional<uint32_t>& aLimit, 224 ErrorResult& aRv); 225 226 [[nodiscard]] RefPtr<IDBRequest> OpenCursor(JSContext* aCx, 227 JS::Handle<JS::Value> aRange, 228 IDBCursorDirection aDirection, 229 ErrorResult& aRv); 230 231 [[nodiscard]] RefPtr<IDBRequest> OpenCursor(JSContext* aCx, 232 IDBCursorDirection aDirection, 233 ErrorResult& aRv); 234 235 [[nodiscard]] RefPtr<IDBRequest> OpenKeyCursor(JSContext* aCx, 236 JS::Handle<JS::Value> aRange, 237 IDBCursorDirection aDirection, 238 ErrorResult& aRv); 239 240 void RefreshSpec(bool aMayDelete); 241 242 const ObjectStoreSpec& Spec() const; 243 244 void NoteDeletion(); 245 246 bool IsDeleted() const { 247 AssertIsOnOwningThread(); 248 249 return !!mDeletedSpec; 250 } 251 252 NS_DECL_CYCLE_COLLECTING_ISUPPORTS 253 NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(IDBObjectStore) 254 255 // nsWrapperCache 256 virtual JSObject* WrapObject(JSContext* aCx, 257 JS::Handle<JSObject*> aGivenProto) override; 258 259 private: 260 IDBObjectStore(SafeRefPtr<IDBTransaction> aTransaction, 261 ObjectStoreSpec* aSpec); 262 263 ~IDBObjectStore(); 264 265 void GetAddInfo(JSContext* aCx, ValueWrapper& aValueWrapper, 266 JS::Handle<JS::Value> aKeyVal, 267 StructuredCloneWriteInfo& aCloneWriteInfo, Key& aKey, 268 nsTArray<IndexUpdateInfo>& aUpdateInfoArray, 269 ErrorResult& aRv); 270 271 [[nodiscard]] RefPtr<IDBRequest> AddOrPut(JSContext* aCx, 272 ValueWrapper& aValueWrapper, 273 JS::Handle<JS::Value> aKey, 274 bool aOverwrite, bool aFromCursor, 275 ErrorResult& aRv); 276 277 [[nodiscard]] RefPtr<IDBRequest> DeleteInternal(JSContext* aCx, 278 JS::Handle<JS::Value> aKey, 279 bool aFromCursor, 280 ErrorResult& aRv); 281 282 [[nodiscard]] RefPtr<IDBRequest> GetInternal(bool aKeyOnly, JSContext* aCx, 283 JS::Handle<JS::Value> aKey, 284 ErrorResult& aRv); 285 286 [[nodiscard]] RefPtr<IDBRequest> GetAllInternal( 287 bool aKeysOnly, JSContext* aCx, JS::Handle<JS::Value> aKey, 288 const Optional<uint32_t>& aLimit, ErrorResult& aRv); 289 290 [[nodiscard]] RefPtr<IDBRequest> OpenCursorInternal( 291 bool aKeysOnly, JSContext* aCx, JS::Handle<JS::Value> aRange, 292 IDBCursorDirection aDirection, ErrorResult& aRv); 293 }; 294 295 } // namespace dom 296 } // namespace mozilla 297 298 #endif // mozilla_dom_idbobjectstore_h__