IDBIndex.cpp 18 KB

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