Line data Source code
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 : #include "IDBIndex.h"
8 :
9 : #include "FileInfo.h"
10 : #include "IDBCursor.h"
11 : #include "IDBEvents.h"
12 : #include "IDBKeyRange.h"
13 : #include "IDBObjectStore.h"
14 : #include "IDBRequest.h"
15 : #include "IDBTransaction.h"
16 : #include "IndexedDatabase.h"
17 : #include "IndexedDatabaseInlines.h"
18 : #include "mozilla/ErrorResult.h"
19 : #include "mozilla/dom/indexedDB/PBackgroundIDBSharedTypes.h"
20 : #include "ProfilerHelpers.h"
21 : #include "ReportInternalError.h"
22 :
23 : // Include this last to avoid path problems on Windows.
24 : #include "ActorsChild.h"
25 :
26 : namespace mozilla {
27 : namespace dom {
28 :
29 : using namespace mozilla::dom::indexedDB;
30 :
31 : namespace {
32 :
33 : already_AddRefed<IDBRequest>
34 0 : GenerateRequest(JSContext* aCx, IDBIndex* aIndex)
35 : {
36 0 : MOZ_ASSERT(aIndex);
37 0 : aIndex->AssertIsOnOwningThread();
38 :
39 0 : IDBTransaction* transaction = aIndex->ObjectStore()->Transaction();
40 :
41 : RefPtr<IDBRequest> request =
42 0 : IDBRequest::Create(aCx, aIndex, transaction->Database(), transaction);
43 0 : MOZ_ASSERT(request);
44 :
45 0 : return request.forget();
46 : }
47 :
48 : } // namespace
49 :
50 0 : IDBIndex::IDBIndex(IDBObjectStore* aObjectStore, const IndexMetadata* aMetadata)
51 : : mObjectStore(aObjectStore)
52 0 : , mCachedKeyPath(JS::UndefinedValue())
53 : , mMetadata(aMetadata)
54 0 : , mId(aMetadata->id())
55 0 : , mRooted(false)
56 : {
57 0 : MOZ_ASSERT(aObjectStore);
58 0 : aObjectStore->AssertIsOnOwningThread();
59 0 : MOZ_ASSERT(aMetadata);
60 0 : }
61 :
62 0 : IDBIndex::~IDBIndex()
63 : {
64 0 : AssertIsOnOwningThread();
65 :
66 0 : if (mRooted) {
67 0 : mCachedKeyPath.setUndefined();
68 0 : mozilla::DropJSObjects(this);
69 : }
70 0 : }
71 :
72 : already_AddRefed<IDBIndex>
73 0 : IDBIndex::Create(IDBObjectStore* aObjectStore,
74 : const IndexMetadata& aMetadata)
75 : {
76 0 : MOZ_ASSERT(aObjectStore);
77 0 : aObjectStore->AssertIsOnOwningThread();
78 :
79 0 : RefPtr<IDBIndex> index = new IDBIndex(aObjectStore, &aMetadata);
80 :
81 0 : return index.forget();
82 : }
83 :
84 : #ifdef DEBUG
85 :
86 : void
87 0 : IDBIndex::AssertIsOnOwningThread() const
88 : {
89 0 : MOZ_ASSERT(mObjectStore);
90 0 : mObjectStore->AssertIsOnOwningThread();
91 0 : }
92 :
93 : #endif // DEBUG
94 :
95 : void
96 0 : IDBIndex::RefreshMetadata(bool aMayDelete)
97 : {
98 0 : AssertIsOnOwningThread();
99 0 : MOZ_ASSERT_IF(mDeletedMetadata, mMetadata == mDeletedMetadata);
100 :
101 0 : const nsTArray<IndexMetadata>& indexes = mObjectStore->Spec().indexes();
102 :
103 0 : bool found = false;
104 :
105 0 : for (uint32_t count = indexes.Length(), index = 0;
106 0 : index < count;
107 : index++) {
108 0 : const IndexMetadata& metadata = indexes[index];
109 :
110 0 : if (metadata.id() == Id()) {
111 0 : mMetadata = &metadata;
112 :
113 0 : found = true;
114 0 : break;
115 : }
116 : }
117 :
118 0 : MOZ_ASSERT_IF(!aMayDelete && !mDeletedMetadata, found);
119 :
120 0 : if (found) {
121 0 : MOZ_ASSERT(mMetadata != mDeletedMetadata);
122 0 : mDeletedMetadata = nullptr;
123 : } else {
124 0 : NoteDeletion();
125 : }
126 0 : }
127 :
128 : void
129 0 : IDBIndex::NoteDeletion()
130 : {
131 0 : AssertIsOnOwningThread();
132 0 : MOZ_ASSERT(mMetadata);
133 0 : MOZ_ASSERT(Id() == mMetadata->id());
134 :
135 0 : if (mDeletedMetadata) {
136 0 : MOZ_ASSERT(mMetadata == mDeletedMetadata);
137 0 : return;
138 : }
139 :
140 0 : mDeletedMetadata = new IndexMetadata(*mMetadata);
141 :
142 0 : mMetadata = mDeletedMetadata;
143 : }
144 :
145 : const nsString&
146 0 : IDBIndex::Name() const
147 : {
148 0 : AssertIsOnOwningThread();
149 0 : MOZ_ASSERT(mMetadata);
150 :
151 0 : return mMetadata->name();
152 : }
153 :
154 : void
155 0 : IDBIndex::SetName(const nsAString& aName, ErrorResult& aRv)
156 : {
157 0 : AssertIsOnOwningThread();
158 :
159 0 : IDBTransaction* transaction = mObjectStore->Transaction();
160 :
161 0 : if (transaction->GetMode() != IDBTransaction::VERSION_CHANGE ||
162 0 : mDeletedMetadata) {
163 0 : aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
164 0 : return;
165 : }
166 :
167 0 : if (!transaction->IsOpen()) {
168 0 : aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR);
169 0 : return;
170 : }
171 :
172 0 : if (aName == mMetadata->name()) {
173 0 : return;
174 : }
175 :
176 : // Cache logging string of this index before renaming.
177 0 : const LoggingString loggingOldIndex(this);
178 :
179 0 : const int64_t indexId = Id();
180 :
181 : nsresult rv =
182 0 : transaction->Database()->RenameIndex(mObjectStore->Id(),
183 : indexId,
184 0 : aName);
185 :
186 0 : if (NS_FAILED(rv)) {
187 0 : aRv.Throw(rv);
188 0 : return;
189 : }
190 :
191 : // Don't do this in the macro because we always need to increment the serial
192 : // number to keep in sync with the parent.
193 0 : const uint64_t requestSerialNumber = IDBRequest::NextSerialNumber();
194 :
195 0 : IDB_LOG_MARK("IndexedDB %s: Child Transaction[%lld] Request[%llu]: "
196 : "database(%s).transaction(%s).objectStore(%s).index(%s)."
197 : "rename(%s)",
198 : "IndexedDB %s: C T[%lld] R[%llu]: IDBIndex.rename()",
199 : IDB_LOG_ID_STRING(),
200 : transaction->LoggingSerialNumber(),
201 : requestSerialNumber,
202 : IDB_LOG_STRINGIFY(transaction->Database()),
203 : IDB_LOG_STRINGIFY(transaction),
204 : IDB_LOG_STRINGIFY(mObjectStore),
205 : loggingOldIndex.get(),
206 : IDB_LOG_STRINGIFY(this));
207 :
208 0 : transaction->RenameIndex(mObjectStore, indexId, aName);
209 : }
210 :
211 : bool
212 0 : IDBIndex::Unique() const
213 : {
214 0 : AssertIsOnOwningThread();
215 0 : MOZ_ASSERT(mMetadata);
216 :
217 0 : return mMetadata->unique();
218 : }
219 :
220 : bool
221 0 : IDBIndex::MultiEntry() const
222 : {
223 0 : AssertIsOnOwningThread();
224 0 : MOZ_ASSERT(mMetadata);
225 :
226 0 : return mMetadata->multiEntry();
227 : }
228 :
229 : bool
230 0 : IDBIndex::LocaleAware() const
231 : {
232 0 : AssertIsOnOwningThread();
233 0 : MOZ_ASSERT(mMetadata);
234 :
235 0 : return mMetadata->locale().IsEmpty();
236 : }
237 :
238 : const indexedDB::KeyPath&
239 0 : IDBIndex::GetKeyPath() const
240 : {
241 0 : AssertIsOnOwningThread();
242 0 : MOZ_ASSERT(mMetadata);
243 :
244 0 : return mMetadata->keyPath();
245 : }
246 :
247 : void
248 0 : IDBIndex::GetLocale(nsString& aLocale) const
249 : {
250 0 : AssertIsOnOwningThread();
251 0 : MOZ_ASSERT(mMetadata);
252 :
253 0 : if (mMetadata->locale().IsEmpty()) {
254 0 : SetDOMStringToNull(aLocale);
255 : } else {
256 0 : aLocale.AssignWithConversion(mMetadata->locale());
257 : }
258 0 : }
259 :
260 : const nsCString&
261 0 : IDBIndex::Locale() const
262 : {
263 0 : AssertIsOnOwningThread();
264 0 : MOZ_ASSERT(mMetadata);
265 :
266 0 : return mMetadata->locale();
267 : }
268 :
269 : bool
270 0 : IDBIndex::IsAutoLocale() const
271 : {
272 0 : AssertIsOnOwningThread();
273 0 : MOZ_ASSERT(mMetadata);
274 :
275 0 : return mMetadata->autoLocale();
276 : }
277 :
278 : nsPIDOMWindowInner*
279 0 : IDBIndex::GetParentObject() const
280 : {
281 0 : AssertIsOnOwningThread();
282 :
283 0 : return mObjectStore->GetParentObject();
284 : }
285 :
286 : void
287 0 : IDBIndex::GetKeyPath(JSContext* aCx,
288 : JS::MutableHandle<JS::Value> aResult,
289 : ErrorResult& aRv)
290 : {
291 0 : AssertIsOnOwningThread();
292 :
293 0 : if (!mCachedKeyPath.isUndefined()) {
294 0 : MOZ_ASSERT(mRooted);
295 0 : aResult.set(mCachedKeyPath);
296 0 : return;
297 : }
298 :
299 0 : MOZ_ASSERT(!mRooted);
300 :
301 0 : aRv = GetKeyPath().ToJSVal(aCx, mCachedKeyPath);
302 0 : if (NS_WARN_IF(aRv.Failed())) {
303 0 : return;
304 : }
305 :
306 0 : if (mCachedKeyPath.isGCThing()) {
307 0 : mozilla::HoldJSObjects(this);
308 0 : mRooted = true;
309 : }
310 :
311 0 : aResult.set(mCachedKeyPath);
312 : }
313 :
314 : already_AddRefed<IDBRequest>
315 0 : IDBIndex::GetInternal(bool aKeyOnly,
316 : JSContext* aCx,
317 : JS::Handle<JS::Value> aKey,
318 : ErrorResult& aRv)
319 : {
320 0 : AssertIsOnOwningThread();
321 :
322 0 : if (mDeletedMetadata) {
323 0 : aRv.Throw(NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR);
324 0 : return nullptr;
325 : }
326 :
327 0 : IDBTransaction* transaction = mObjectStore->Transaction();
328 0 : if (!transaction->IsOpen()) {
329 0 : aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR);
330 0 : return nullptr;
331 : }
332 :
333 0 : RefPtr<IDBKeyRange> keyRange;
334 0 : aRv = IDBKeyRange::FromJSVal(aCx, aKey, getter_AddRefs(keyRange));
335 0 : if (NS_WARN_IF(aRv.Failed())) {
336 0 : return nullptr;
337 : }
338 :
339 0 : if (!keyRange) {
340 : // Must specify a key or keyRange for get() and getKey().
341 0 : aRv.Throw(NS_ERROR_DOM_INDEXEDDB_DATA_ERR);
342 0 : return nullptr;
343 : }
344 :
345 0 : const int64_t objectStoreId = mObjectStore->Id();
346 0 : const int64_t indexId = Id();
347 :
348 0 : SerializedKeyRange serializedKeyRange;
349 0 : keyRange->ToSerialized(serializedKeyRange);
350 :
351 0 : RequestParams params;
352 :
353 0 : if (aKeyOnly) {
354 0 : params = IndexGetKeyParams(objectStoreId, indexId, serializedKeyRange);
355 : } else {
356 0 : params = IndexGetParams(objectStoreId, indexId, serializedKeyRange);
357 : }
358 :
359 0 : RefPtr<IDBRequest> request = GenerateRequest(aCx, this);
360 0 : MOZ_ASSERT(request);
361 :
362 0 : if (aKeyOnly) {
363 0 : IDB_LOG_MARK("IndexedDB %s: Child Transaction[%lld] Request[%llu]: "
364 : "database(%s).transaction(%s).objectStore(%s).index(%s)."
365 : "getKey(%s)",
366 : "IndexedDB %s: C T[%lld] R[%llu]: IDBIndex.getKey()",
367 : IDB_LOG_ID_STRING(),
368 : transaction->LoggingSerialNumber(),
369 : request->LoggingSerialNumber(),
370 : IDB_LOG_STRINGIFY(transaction->Database()),
371 : IDB_LOG_STRINGIFY(transaction),
372 : IDB_LOG_STRINGIFY(mObjectStore),
373 : IDB_LOG_STRINGIFY(this),
374 : IDB_LOG_STRINGIFY(keyRange));
375 : } else {
376 0 : IDB_LOG_MARK("IndexedDB %s: Child Transaction[%lld] Request[%llu]: "
377 : "database(%s).transaction(%s).objectStore(%s).index(%s)."
378 : "get(%s)",
379 : "IndexedDB %s: C T[%lld] R[%llu]: IDBIndex.get()",
380 : IDB_LOG_ID_STRING(),
381 : transaction->LoggingSerialNumber(),
382 : request->LoggingSerialNumber(),
383 : IDB_LOG_STRINGIFY(transaction->Database()),
384 : IDB_LOG_STRINGIFY(transaction),
385 : IDB_LOG_STRINGIFY(mObjectStore),
386 : IDB_LOG_STRINGIFY(this),
387 : IDB_LOG_STRINGIFY(keyRange));
388 : }
389 :
390 0 : transaction->StartRequest(request, params);
391 :
392 0 : return request.forget();
393 : }
394 :
395 : already_AddRefed<IDBRequest>
396 0 : IDBIndex::GetAllInternal(bool aKeysOnly,
397 : JSContext* aCx,
398 : JS::Handle<JS::Value> aKey,
399 : const Optional<uint32_t>& aLimit,
400 : ErrorResult& aRv)
401 : {
402 0 : AssertIsOnOwningThread();
403 :
404 0 : if (mDeletedMetadata) {
405 0 : aRv.Throw(NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR);
406 0 : return nullptr;
407 : }
408 :
409 0 : IDBTransaction* transaction = mObjectStore->Transaction();
410 0 : if (!transaction->IsOpen()) {
411 0 : aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR);
412 0 : return nullptr;
413 : }
414 :
415 0 : RefPtr<IDBKeyRange> keyRange;
416 0 : aRv = IDBKeyRange::FromJSVal(aCx, aKey, getter_AddRefs(keyRange));
417 0 : if (NS_WARN_IF(aRv.Failed())) {
418 0 : return nullptr;
419 : }
420 :
421 0 : const int64_t objectStoreId = mObjectStore->Id();
422 0 : const int64_t indexId = Id();
423 :
424 0 : OptionalKeyRange optionalKeyRange;
425 0 : if (keyRange) {
426 0 : SerializedKeyRange serializedKeyRange;
427 0 : keyRange->ToSerialized(serializedKeyRange);
428 0 : optionalKeyRange = serializedKeyRange;
429 : } else {
430 0 : optionalKeyRange = void_t();
431 : }
432 :
433 0 : const uint32_t limit = aLimit.WasPassed() ? aLimit.Value() : 0;
434 :
435 0 : RequestParams params;
436 0 : if (aKeysOnly) {
437 0 : params = IndexGetAllKeysParams(objectStoreId, indexId, optionalKeyRange,
438 0 : limit);
439 : } else {
440 0 : params = IndexGetAllParams(objectStoreId, indexId, optionalKeyRange, limit);
441 : }
442 :
443 0 : RefPtr<IDBRequest> request = GenerateRequest(aCx, this);
444 0 : MOZ_ASSERT(request);
445 :
446 0 : if (aKeysOnly) {
447 0 : IDB_LOG_MARK("IndexedDB %s: Child Transaction[%lld] Request[%llu]: "
448 : "database(%s).transaction(%s).objectStore(%s).index(%s)."
449 : "getAllKeys(%s, %s)",
450 : "IndexedDB %s: C T[%lld] R[%llu]: IDBIndex.getAllKeys()",
451 : IDB_LOG_ID_STRING(),
452 : transaction->LoggingSerialNumber(),
453 : request->LoggingSerialNumber(),
454 : IDB_LOG_STRINGIFY(transaction->Database()),
455 : IDB_LOG_STRINGIFY(transaction),
456 : IDB_LOG_STRINGIFY(mObjectStore),
457 : IDB_LOG_STRINGIFY(this),
458 : IDB_LOG_STRINGIFY(keyRange),
459 : IDB_LOG_STRINGIFY(aLimit));
460 : } else {
461 0 : IDB_LOG_MARK("IndexedDB %s: Child Transaction[%lld] Request[%llu]: "
462 : "database(%s).transaction(%s).objectStore(%s).index(%s)."
463 : "getAll(%s, %s)",
464 : "IndexedDB %s: C T[%lld] R[%llu]: IDBIndex.getAll()",
465 : IDB_LOG_ID_STRING(),
466 : transaction->LoggingSerialNumber(),
467 : request->LoggingSerialNumber(),
468 : IDB_LOG_STRINGIFY(transaction->Database()),
469 : IDB_LOG_STRINGIFY(transaction),
470 : IDB_LOG_STRINGIFY(mObjectStore),
471 : IDB_LOG_STRINGIFY(this),
472 : IDB_LOG_STRINGIFY(keyRange),
473 : IDB_LOG_STRINGIFY(aLimit));
474 : }
475 :
476 0 : transaction->StartRequest(request, params);
477 :
478 0 : return request.forget();
479 : }
480 :
481 : already_AddRefed<IDBRequest>
482 0 : IDBIndex::OpenCursorInternal(bool aKeysOnly,
483 : JSContext* aCx,
484 : JS::Handle<JS::Value> aRange,
485 : IDBCursorDirection aDirection,
486 : ErrorResult& aRv)
487 : {
488 0 : AssertIsOnOwningThread();
489 :
490 0 : if (mDeletedMetadata) {
491 0 : aRv.Throw(NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR);
492 0 : return nullptr;
493 : }
494 :
495 0 : IDBTransaction* transaction = mObjectStore->Transaction();
496 0 : if (!transaction->IsOpen()) {
497 0 : aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR);
498 0 : return nullptr;
499 : }
500 :
501 0 : RefPtr<IDBKeyRange> keyRange;
502 0 : aRv = IDBKeyRange::FromJSVal(aCx, aRange, getter_AddRefs(keyRange));
503 0 : if (NS_WARN_IF(aRv.Failed())) {
504 0 : return nullptr;
505 : }
506 :
507 0 : int64_t objectStoreId = mObjectStore->Id();
508 0 : int64_t indexId = Id();
509 :
510 0 : OptionalKeyRange optionalKeyRange;
511 :
512 0 : if (keyRange) {
513 0 : SerializedKeyRange serializedKeyRange;
514 0 : keyRange->ToSerialized(serializedKeyRange);
515 :
516 0 : optionalKeyRange = Move(serializedKeyRange);
517 : } else {
518 0 : optionalKeyRange = void_t();
519 : }
520 :
521 0 : IDBCursor::Direction direction = IDBCursor::ConvertDirection(aDirection);
522 :
523 0 : OpenCursorParams params;
524 0 : if (aKeysOnly) {
525 0 : IndexOpenKeyCursorParams openParams;
526 0 : openParams.objectStoreId() = objectStoreId;
527 0 : openParams.indexId() = indexId;
528 0 : openParams.optionalKeyRange() = Move(optionalKeyRange);
529 0 : openParams.direction() = direction;
530 :
531 0 : params = Move(openParams);
532 : } else {
533 0 : IndexOpenCursorParams openParams;
534 0 : openParams.objectStoreId() = objectStoreId;
535 0 : openParams.indexId() = indexId;
536 0 : openParams.optionalKeyRange() = Move(optionalKeyRange);
537 0 : openParams.direction() = direction;
538 :
539 0 : params = Move(openParams);
540 : }
541 :
542 0 : RefPtr<IDBRequest> request = GenerateRequest(aCx, this);
543 0 : MOZ_ASSERT(request);
544 :
545 0 : if (aKeysOnly) {
546 0 : IDB_LOG_MARK("IndexedDB %s: Child Transaction[%lld] Request[%llu]: "
547 : "database(%s).transaction(%s).objectStore(%s).index(%s)."
548 : "openKeyCursor(%s, %s)",
549 : "IndexedDB %s: C T[%lld] R[%llu]: IDBIndex.openKeyCursor()",
550 : IDB_LOG_ID_STRING(),
551 : transaction->LoggingSerialNumber(),
552 : request->LoggingSerialNumber(),
553 : IDB_LOG_STRINGIFY(transaction->Database()),
554 : IDB_LOG_STRINGIFY(transaction),
555 : IDB_LOG_STRINGIFY(mObjectStore),
556 : IDB_LOG_STRINGIFY(this),
557 : IDB_LOG_STRINGIFY(keyRange),
558 : IDB_LOG_STRINGIFY(direction));
559 : } else {
560 0 : IDB_LOG_MARK("IndexedDB %s: Child Transaction[%lld] Request[%llu]: "
561 : "database(%s).transaction(%s).objectStore(%s).index(%s)."
562 : "openCursor(%s, %s)",
563 : "IndexedDB %s: C T[%lld] R[%llu]: "
564 : "IDBObjectStore.openKeyCursor()",
565 : IDB_LOG_ID_STRING(),
566 : transaction->LoggingSerialNumber(),
567 : request->LoggingSerialNumber(),
568 : IDB_LOG_STRINGIFY(transaction->Database()),
569 : IDB_LOG_STRINGIFY(transaction),
570 : IDB_LOG_STRINGIFY(mObjectStore),
571 : IDB_LOG_STRINGIFY(this),
572 : IDB_LOG_STRINGIFY(keyRange),
573 : IDB_LOG_STRINGIFY(direction));
574 : }
575 :
576 : BackgroundCursorChild* actor =
577 0 : new BackgroundCursorChild(request, this, direction);
578 :
579 0 : mObjectStore->Transaction()->OpenCursor(actor, params);
580 :
581 0 : return request.forget();
582 : }
583 :
584 : already_AddRefed<IDBRequest>
585 0 : IDBIndex::Count(JSContext* aCx,
586 : JS::Handle<JS::Value> aKey,
587 : ErrorResult& aRv)
588 : {
589 0 : AssertIsOnOwningThread();
590 :
591 0 : if (mDeletedMetadata) {
592 0 : aRv.Throw(NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR);
593 0 : return nullptr;
594 : }
595 :
596 0 : IDBTransaction* transaction = mObjectStore->Transaction();
597 0 : if (!transaction->IsOpen()) {
598 0 : aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR);
599 0 : return nullptr;
600 : }
601 :
602 0 : RefPtr<IDBKeyRange> keyRange;
603 0 : aRv = IDBKeyRange::FromJSVal(aCx, aKey, getter_AddRefs(keyRange));
604 0 : if (aRv.Failed()) {
605 0 : return nullptr;
606 : }
607 :
608 0 : IndexCountParams params;
609 0 : params.objectStoreId() = mObjectStore->Id();
610 0 : params.indexId() = Id();
611 :
612 0 : if (keyRange) {
613 0 : SerializedKeyRange serializedKeyRange;
614 0 : keyRange->ToSerialized(serializedKeyRange);
615 0 : params.optionalKeyRange() = serializedKeyRange;
616 : } else {
617 0 : params.optionalKeyRange() = void_t();
618 : }
619 :
620 0 : RefPtr<IDBRequest> request = GenerateRequest(aCx, this);
621 0 : MOZ_ASSERT(request);
622 :
623 0 : IDB_LOG_MARK("IndexedDB %s: Child Transaction[%lld] Request[%llu]: "
624 : "database(%s).transaction(%s).objectStore(%s).index(%s)."
625 : "count(%s)",
626 : "IndexedDB %s: C T[%lld] R[%llu]: IDBObjectStore.count()",
627 : IDB_LOG_ID_STRING(),
628 : transaction->LoggingSerialNumber(),
629 : request->LoggingSerialNumber(),
630 : IDB_LOG_STRINGIFY(transaction->Database()),
631 : IDB_LOG_STRINGIFY(transaction),
632 : IDB_LOG_STRINGIFY(mObjectStore),
633 : IDB_LOG_STRINGIFY(this),
634 : IDB_LOG_STRINGIFY(keyRange));
635 :
636 0 : transaction->StartRequest(request, params);
637 :
638 0 : return request.forget();
639 : }
640 :
641 0 : NS_IMPL_CYCLE_COLLECTING_ADDREF(IDBIndex)
642 0 : NS_IMPL_CYCLE_COLLECTING_RELEASE(IDBIndex)
643 :
644 0 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(IDBIndex)
645 0 : NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
646 0 : NS_INTERFACE_MAP_ENTRY(nsISupports)
647 0 : NS_INTERFACE_MAP_END
648 :
649 : NS_IMPL_CYCLE_COLLECTION_CLASS(IDBIndex)
650 :
651 0 : NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(IDBIndex)
652 0 : NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
653 0 : NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mCachedKeyPath)
654 0 : NS_IMPL_CYCLE_COLLECTION_TRACE_END
655 :
656 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(IDBIndex)
657 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mObjectStore)
658 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
659 :
660 0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(IDBIndex)
661 0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
662 :
663 : // Don't unlink mObjectStore!
664 :
665 0 : tmp->mCachedKeyPath.setUndefined();
666 :
667 0 : if (tmp->mRooted) {
668 0 : mozilla::DropJSObjects(tmp);
669 0 : tmp->mRooted = false;
670 : }
671 0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_END
672 :
673 : JSObject*
674 0 : IDBIndex::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
675 : {
676 0 : return IDBIndexBinding::Wrap(aCx, this, aGivenProto);
677 : }
678 :
679 : } // namespace dom
680 : } // namespace mozilla
|