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/. */
7 #ifndef mozilla_dom_idbcursor_h__
8 #define mozilla_dom_idbcursor_h__
10 #include "IDBCursorType.h"
11 #include "IndexedDatabase.h"
12 #include "js/RootingAPI.h"
13 #include "mozilla/Attributes.h"
14 #include "mozilla/dom/IDBCursorBinding.h"
15 #include "mozilla/dom/IDBTransaction.h"
16 #include "mozilla/dom/indexedDB/Key.h"
17 #include "mozilla/dom/quota/CheckedUnsafePtr.h"
18 #include "mozilla/InitializedOnce.h"
19 #include "nsCycleCollectionParticipant.h"
20 #include "nsWrapperCache.h"
22 class nsIGlobalObject
;
33 class OwningIDBObjectStoreOrIDBIndex
;
35 class IDBObjectStoreCursor
;
36 class IDBObjectStoreKeyCursor
;
38 class IDBIndexKeyCursor
;
41 class BackgroundCursorChildBase
;
42 template <IDBCursorType CursorType
>
43 class BackgroundCursorChild
;
44 } // namespace indexedDB
46 class IDBCursor
: public nsISupports
, public nsWrapperCache
{
48 using Key
= indexedDB::Key
;
49 using StructuredCloneReadInfoChild
= indexedDB::StructuredCloneReadInfoChild
;
51 using Direction
= IDBCursorDirection
;
52 using Type
= IDBCursorType
;
55 InitializedOnce
<const NotNull
<indexedDB::BackgroundCursorChildBase
*>>
58 // TODO: mRequest could be made const if Bug 1575173 is resolved. It is
59 // initialized in the constructor and never modified/cleared.
60 RefPtr
<IDBRequest
> mRequest
;
62 // Sub-classes' mSource will hold this alive.
63 CheckedUnsafePtr
<IDBTransaction
> mTransaction
;
66 // These are cycle-collected!
67 JS::Heap
<JS::Value
> mCachedKey
;
68 JS::Heap
<JS::Value
> mCachedPrimaryKey
;
69 JS::Heap
<JS::Value
> mCachedValue
;
71 const Direction mDirection
;
73 bool mHaveCachedKey
: 1;
74 bool mHaveCachedPrimaryKey
: 1;
75 bool mHaveCachedValue
: 1;
77 bool mContinueCalled
: 1;
81 [[nodiscard
]] static RefPtr
<IDBObjectStoreCursor
> Create(
82 indexedDB::BackgroundCursorChild
<Type::ObjectStore
>* aBackgroundActor
,
83 Key aKey
, StructuredCloneReadInfoChild
&& aCloneInfo
);
85 [[nodiscard
]] static RefPtr
<IDBObjectStoreKeyCursor
> Create(
86 indexedDB::BackgroundCursorChild
<Type::ObjectStoreKey
>* aBackgroundActor
,
89 [[nodiscard
]] static RefPtr
<IDBIndexCursor
> Create(
90 indexedDB::BackgroundCursorChild
<Type::Index
>* aBackgroundActor
, Key aKey
,
91 Key aSortKey
, Key aPrimaryKey
, StructuredCloneReadInfoChild
&& aCloneInfo
);
93 [[nodiscard
]] static RefPtr
<IDBIndexKeyCursor
> Create(
94 indexedDB::BackgroundCursorChild
<Type::IndexKey
>* aBackgroundActor
,
95 Key aKey
, Key aSortKey
, Key aPrimaryKey
);
97 void AssertIsOnOwningThread() const
105 nsIGlobalObject
* GetParentObject() const;
107 // XXX: The virtual methods that are used by the DOM binding could be removed
108 // on the base class, if we provided a non-polymorphic wrapper instead, which
109 // uses a custom dispatch to the actual implementation type. Don't know if
112 virtual void GetSource(OwningIDBObjectStoreOrIDBIndex
& aSource
) const = 0;
114 IDBCursorDirection
GetDirection() const;
116 RefPtr
<IDBRequest
> Request() const;
118 virtual void GetKey(JSContext
* aCx
, JS::MutableHandle
<JS::Value
> aResult
,
119 ErrorResult
& aRv
) = 0;
121 virtual void GetPrimaryKey(JSContext
* aCx
,
122 JS::MutableHandle
<JS::Value
> aResult
,
123 ErrorResult
& aRv
) = 0;
125 // XXX: We could move this to a sub-class, since this is only present on
126 // IDBCursorWithValue.
127 virtual void GetValue(JSContext
* aCx
, JS::MutableHandle
<JS::Value
> aResult
,
128 ErrorResult
& aRv
) = 0;
130 virtual void Continue(JSContext
* aCx
, JS::Handle
<JS::Value
> aKey
,
131 ErrorResult
& aRv
) = 0;
133 virtual void ContinuePrimaryKey(JSContext
* aCx
, JS::Handle
<JS::Value
> aKey
,
134 JS::Handle
<JS::Value
> aPrimaryKey
,
135 ErrorResult
& aRv
) = 0;
137 virtual void Advance(uint32_t aCount
, ErrorResult
& aRv
) = 0;
139 [[nodiscard
]] virtual RefPtr
<IDBRequest
> Update(JSContext
* aCx
,
140 JS::Handle
<JS::Value
> aValue
,
141 ErrorResult
& aRv
) = 0;
143 [[nodiscard
]] virtual RefPtr
<IDBRequest
> Delete(JSContext
* aCx
,
144 ErrorResult
& aRv
) = 0;
146 void ClearBackgroundActor() {
147 AssertIsOnOwningThread();
149 mBackgroundActor
.destroy();
152 virtual void InvalidateCachedResponses() = 0;
154 NS_DECL_CYCLE_COLLECTING_ISUPPORTS
155 NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(IDBCursor
)
158 IDBCursor(indexedDB::BackgroundCursorChildBase
* aBackgroundActor
);
160 // TODO: Check if we can remove virtual by changing cycle collection.
161 virtual ~IDBCursor() = default;
166 template <IDBCursor::Type CursorType
>
167 class IDBTypedCursor
: public IDBCursor
{
169 template <typename
... DataArgs
>
170 explicit IDBTypedCursor(
171 indexedDB::BackgroundCursorChild
<CursorType
>* aBackgroundActor
,
172 DataArgs
&&... aDataArgs
);
174 static constexpr Type
GetType() { return CursorType
; }
176 // Checks if this is a locale aware cursor (ie. the index's sortKey is unset)
177 bool IsLocaleAware() const;
179 void GetSource(OwningIDBObjectStoreOrIDBIndex
& aSource
) const final
;
181 void GetKey(JSContext
* aCx
, JS::MutableHandle
<JS::Value
> aResult
,
182 ErrorResult
& aRv
) final
;
184 void GetPrimaryKey(JSContext
* aCx
, JS::MutableHandle
<JS::Value
> aResult
,
185 ErrorResult
& aRv
) final
;
187 void GetValue(JSContext
* aCx
, JS::MutableHandle
<JS::Value
> aResult
,
188 ErrorResult
& aRv
) final
;
190 void Continue(JSContext
* aCx
, JS::Handle
<JS::Value
> aKey
,
191 ErrorResult
& aRv
) final
;
193 void ContinuePrimaryKey(JSContext
* aCx
, JS::Handle
<JS::Value
> aKey
,
194 JS::Handle
<JS::Value
> aPrimaryKey
,
195 ErrorResult
& aRv
) final
;
197 void Advance(uint32_t aCount
, ErrorResult
& aRv
) final
;
199 [[nodiscard
]] RefPtr
<IDBRequest
> Update(JSContext
* aCx
,
200 JS::Handle
<JS::Value
> aValue
,
201 ErrorResult
& aRv
) final
;
203 [[nodiscard
]] RefPtr
<IDBRequest
> Delete(JSContext
* aCx
,
204 ErrorResult
& aRv
) final
;
207 JSObject
* WrapObject(JSContext
* aCx
, JS::Handle
<JSObject
*> aGivenProto
) final
;
209 void InvalidateCachedResponses() final
;
213 void Reset(CursorData
<CursorType
>&& aCursorData
);
216 static constexpr bool IsObjectStoreCursor
=
217 CursorTypeTraits
<CursorType
>::IsObjectStoreCursor
;
218 static constexpr bool IsKeyOnlyCursor
=
219 CursorTypeTraits
<CursorType
>::IsKeyOnlyCursor
;
221 CursorSourceType
<CursorType
>& GetSourceRef() const {
226 IDBObjectStore
& GetSourceObjectStoreRef() const {
227 if constexpr (IsObjectStoreCursor
) {
228 return GetSourceRef();
230 MOZ_ASSERT(!GetSourceRef().IsDeleted());
232 auto res
= GetSourceRef().ObjectStore();
238 indexedDB::BackgroundCursorChild
<CursorType
>& GetTypedBackgroundActorRef()
240 // We can safely downcast to BackgroundCursorChild<CursorType>*, since we
241 // initialized that in the constructor from that type. We just want to avoid
242 // having a second typed field.
243 return *static_cast<indexedDB::BackgroundCursorChild
<CursorType
>*>(
244 mBackgroundActor
->get());
247 bool IsSourceDeleted() const;
250 virtual ~IDBTypedCursor() override
;
252 void DropJSObjects();
254 CursorData
<CursorType
> mData
;
256 // TODO: mSource could be made const if Bug 1575173 is resolved. It is
257 // initialized in the constructor and never modified/cleared.
258 RefPtr
<CursorSourceType
<CursorType
>> mSource
;
261 // The subclasses defined by this macro are only needed to be able to use the
262 // cycle collector macros, which do not support templates. If spelled out, the
263 // cycle collection could be implemented directly on IDBTypedCursor, and these
264 // classes were not needed.
265 #define CONCRETE_IDBCURSOR_SUBCLASS(_subclassName, _cursorType) \
266 class _subclassName final : public IDBTypedCursor<_cursorType> { \
268 NS_DECL_ISUPPORTS_INHERITED \
269 NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(_subclassName, IDBCursor) \
271 using IDBTypedCursor<_cursorType>::IDBTypedCursor; \
274 ~_subclassName() final = default; \
277 CONCRETE_IDBCURSOR_SUBCLASS(IDBObjectStoreCursor
, IDBCursor::Type::ObjectStore
)
278 CONCRETE_IDBCURSOR_SUBCLASS(IDBObjectStoreKeyCursor
,
279 IDBCursor::Type::ObjectStoreKey
)
280 CONCRETE_IDBCURSOR_SUBCLASS(IDBIndexCursor
, IDBCursor::Type::Index
)
281 CONCRETE_IDBCURSOR_SUBCLASS(IDBIndexKeyCursor
, IDBCursor::Type::IndexKey
)
283 template <IDBCursor::Type CursorType
>
284 using IDBCursorImpl
= typename CursorTypeTraits
<CursorType
>::Type
;
287 } // namespace mozilla
289 #endif // mozilla_dom_idbcursor_h__