Bug 1257725 part 5. Get rid of ThreadsafeAutoJSContext usage in IDBRequest::CaptureCaller. r=khuey
authorBoris Zbarsky <bzbarsky@mit.edu>
Wed, 23 Mar 2016 11:02:57 -0400
changeset 290125 30e2a55c26ee9479c2fd48c5cd04b80388a0416e
parent 290124 16ddfdbf6ff40842cca65951f0709d54980e7296
child 290126 2c3ebed966864f64b2fe2ba980c7d74cd52ae687
push id19656
push usergwagner@mozilla.com
push dateMon, 04 Apr 2016 13:43:23 +0000
treeherderb2g-inbound@e99061fde28a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskhuey
bugs1257725
milestone48.0a1
Bug 1257725 part 5. Get rid of ThreadsafeAutoJSContext usage in IDBRequest::CaptureCaller. r=khuey
dom/bindings/Bindings.conf
dom/datastore/DataStoreDB.cpp
dom/indexedDB/IDBDatabase.cpp
dom/indexedDB/IDBDatabase.h
dom/indexedDB/IDBFactory.cpp
dom/indexedDB/IDBFactory.h
dom/indexedDB/IDBIndex.cpp
dom/indexedDB/IDBObjectStore.cpp
dom/indexedDB/IDBObjectStore.h
dom/indexedDB/IDBRequest.cpp
dom/indexedDB/IDBRequest.h
dom/indexedDB/IDBTransaction.cpp
dom/indexedDB/IDBTransaction.h
--- a/dom/bindings/Bindings.conf
+++ b/dom/bindings/Bindings.conf
@@ -610,16 +610,26 @@ DOMInterfaces = {
         'direction': 'getDirection'
     }
 },
 
 'IDBCursorWithValue': {
     'nativeType': 'mozilla::dom::IDBCursor',
 },
 
+'IDBDatabase': {
+    'implicitJSContext': [ 'transaction', 'createMutableFile',
+                           'mozCreateFileHandle' ],
+},
+
+'IDBFactory': {
+    'implicitJSContext': [ 'open', 'deleteDatabase', 'openForPrincipal',
+                           'deleteForPrincipal' ],
+},
+
 'IDBIndex': {
     'binaryNames': {
         'mozGetAll': 'getAll',
         'mozGetAllKeys': 'getAllKeys',
     }
 },
 
 'IDBKeyRange': {
@@ -629,17 +639,18 @@ DOMInterfaces = {
 'IDBLocaleAwareKeyRange': {
     'headerFile': 'IDBKeyRange.h',
     'wrapperCache': False,
 },
 
 'IDBObjectStore': {
     'binaryNames': {
         'mozGetAll': 'getAll'
-    }
+    },
+    'implicitJSContext': [ 'clear' ],
 },
 
 'IDBOpenDBRequest': {
     'headerFile': 'IDBRequest.h'
 },
 
 'IDBVersionChangeEvent': {
     'headerFile': 'IDBEvents.h',
--- a/dom/datastore/DataStoreDB.cpp
+++ b/dom/datastore/DataStoreDB.cpp
@@ -142,18 +142,23 @@ DataStoreDB::Open(IDBTransactionMode aMo
 {
   MOZ_ASSERT(mState == Inactive);
 
   nsresult rv = CreateFactoryIfNeeded();
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
+  // We only need a JSContext here to get a stack from, so just init our
+  // AutoJSAPI without a global.
+  AutoJSAPI jsapi;
+  jsapi.Init();
   ErrorResult error;
-  mRequest = mFactory->Open(mDatabaseName, DATASTOREDB_VERSION, error);
+  mRequest = mFactory->Open(jsapi.cx(), mDatabaseName, DATASTOREDB_VERSION,
+                            error);
   if (NS_WARN_IF(error.Failed())) {
     return error.StealNSResult();
   }
 
   rv = AddEventListeners();
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
@@ -308,18 +313,24 @@ DataStoreDB::DatabaseOpened()
   }
 
   StringOrStringSequence objectStores;
   if (!objectStores.RawSetAsStringSequence().AppendElements(mObjectStores,
                                                             fallible)) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
+  // We init with the global of our result, just for consistency.
+  AutoJSAPI jsapi;
+  if (!jsapi.Init(&result.toObject())) {
+    return NS_ERROR_UNEXPECTED;
+  }
   RefPtr<IDBTransaction> txn;
-  error = mDatabase->Transaction(objectStores,
+  error = mDatabase->Transaction(jsapi.cx(),
+                                 objectStores,
                                  mTransactionMode,
                                  getter_AddRefs(txn));
   if (NS_WARN_IF(error.Failed())) {
     return error.StealNSResult();
   }
 
   mTransaction = txn.forget();
   return NS_OK;
@@ -337,19 +348,24 @@ DataStoreDB::Delete()
 
   mTransaction = nullptr;
 
   if (mDatabase) {
     mDatabase->Close();
     mDatabase = nullptr;
   }
 
+  // We only need a JSContext here to get a stack from, so just init our
+  // AutoJSAPI without a global.
+  AutoJSAPI jsapi;
+  jsapi.Init();
   ErrorResult error;
   RefPtr<IDBOpenDBRequest> request =
-    mFactory->DeleteDatabase(mDatabaseName, IDBOpenDBOptions(), error);
+    mFactory->DeleteDatabase(jsapi.cx(), mDatabaseName, IDBOpenDBOptions(),
+                             error);
   if (NS_WARN_IF(error.Failed())) {
     return error.StealNSResult();
   }
 
   return NS_OK;
 }
 
 IDBTransaction*
--- a/dom/indexedDB/IDBDatabase.cpp
+++ b/dom/indexedDB/IDBDatabase.cpp
@@ -596,17 +596,18 @@ IDBDatabase::DeleteObjectStore(const nsA
                transaction->LoggingSerialNumber(),
                requestSerialNumber,
                IDB_LOG_STRINGIFY(this),
                IDB_LOG_STRINGIFY(transaction),
                NS_ConvertUTF16toUTF8(aName).get());
 }
 
 already_AddRefed<IDBTransaction>
-IDBDatabase::Transaction(const StringOrStringSequence& aStoreNames,
+IDBDatabase::Transaction(JSContext* aCx,
+                         const StringOrStringSequence& aStoreNames,
                          IDBTransactionMode aMode,
                          ErrorResult& aRv)
 {
   AssertIsOnOwningThread();
 
   if ((aMode == IDBTransactionMode::Readwriteflush ||
        aMode == IDBTransactionMode::Cleanup) &&
       !IndexedDatabaseManager::ExperimentalFeaturesEnabled()) {
@@ -616,26 +617,27 @@ IDBDatabase::Transaction(const StringOrS
     aRv.ThrowTypeError<MSG_INVALID_ENUM_VALUE>(
       NS_LITERAL_STRING("Argument 2 of IDBDatabase.transaction"),
       NS_LITERAL_STRING("readwriteflush"),
       NS_LITERAL_STRING("IDBTransactionMode"));
     return nullptr;
   }
 
   RefPtr<IDBTransaction> transaction;
-  aRv = Transaction(aStoreNames, aMode, getter_AddRefs(transaction));
+  aRv = Transaction(aCx, aStoreNames, aMode, getter_AddRefs(transaction));
   if (NS_WARN_IF(aRv.Failed())) {
     return nullptr;
   }
 
   return transaction.forget();
 }
 
 nsresult
-IDBDatabase::Transaction(const StringOrStringSequence& aStoreNames,
+IDBDatabase::Transaction(JSContext* aCx,
+                         const StringOrStringSequence& aStoreNames,
                          IDBTransactionMode aMode,
                          IDBTransaction** aTransaction)
 {
   AssertIsOnOwningThread();
 
   if (NS_WARN_IF((aMode == IDBTransactionMode::Readwriteflush ||
                   aMode == IDBTransactionMode::Cleanup) &&
                  !IndexedDatabaseManager::ExperimentalFeaturesEnabled())) {
@@ -721,17 +723,17 @@ IDBDatabase::Transaction(const StringOrS
     case IDBTransactionMode::Versionchange:
       return NS_ERROR_DOM_INVALID_ACCESS_ERR;
 
     default:
       MOZ_CRASH("Unknown mode!");
   }
 
   RefPtr<IDBTransaction> transaction =
-    IDBTransaction::Create(this, sortedStoreNames, mode);
+    IDBTransaction::Create(aCx, this, sortedStoreNames, mode);
   if (NS_WARN_IF(!transaction)) {
     IDB_REPORT_INTERNAL_ERR();
     return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
   }
 
   BackgroundTransactionChild* actor =
     new BackgroundTransactionChild(transaction);
 
@@ -763,17 +765,18 @@ IDBDatabase::Storage() const
 {
   AssertIsOnOwningThread();
   MOZ_ASSERT(mSpec);
 
   return PersistenceTypeToStorage(mSpec->metadata().persistenceType());
 }
 
 already_AddRefed<IDBRequest>
-IDBDatabase::CreateMutableFile(const nsAString& aName,
+IDBDatabase::CreateMutableFile(JSContext* aCx,
+                               const nsAString& aName,
                                const Optional<nsAString>& aType,
                                ErrorResult& aRv)
 {
   AssertIsOnOwningThread();
 
   if (QuotaManager::IsShuttingDown()) {
     IDB_REPORT_INTERNAL_ERR();
     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
@@ -787,17 +790,17 @@ IDBDatabase::CreateMutableFile(const nsA
 
   nsString type;
   if (aType.WasPassed()) {
     type = aType.Value();
   }
 
   CreateFileParams params(nsString(aName), type);
 
-  RefPtr<IDBRequest> request = IDBRequest::Create(this, nullptr);
+  RefPtr<IDBRequest> request = IDBRequest::Create(aCx, this, nullptr);
   MOZ_ASSERT(request);
 
   BackgroundDatabaseRequestChild* actor =
     new BackgroundDatabaseRequestChild(this, request);
 
   IDB_LOG_MARK("IndexedDB %s: Child  Request[%llu]: "
                  "database(%s).createMutableFile(%s)",
                "IndexedDB %s: C R[%llu]: IDBDatabase.createMutableFile()",
--- a/dom/indexedDB/IDBDatabase.h
+++ b/dom/indexedDB/IDBDatabase.h
@@ -220,44 +220,48 @@ public:
                     const IDBObjectStoreParameters& aOptionalParameters,
                     ErrorResult& aRv);
 
   void
   DeleteObjectStore(const nsAString& name, ErrorResult& aRv);
 
   // This will be called from the DOM.
   already_AddRefed<IDBTransaction>
-  Transaction(const StringOrStringSequence& aStoreNames,
+  Transaction(JSContext* aCx,
+              const StringOrStringSequence& aStoreNames,
               IDBTransactionMode aMode,
               ErrorResult& aRv);
 
   // This can be called from C++ to avoid JS exception.
   nsresult
-  Transaction(const StringOrStringSequence& aStoreNames,
+  Transaction(JSContext* aCx,
+              const StringOrStringSequence& aStoreNames,
               IDBTransactionMode aMode,
               IDBTransaction** aTransaction);
 
   StorageType
   Storage() const;
 
   IMPL_EVENT_HANDLER(abort)
   IMPL_EVENT_HANDLER(error)
   IMPL_EVENT_HANDLER(versionchange)
 
   already_AddRefed<IDBRequest>
-  CreateMutableFile(const nsAString& aName,
+  CreateMutableFile(JSContext* aCx,
+                    const nsAString& aName,
                     const Optional<nsAString>& aType,
                     ErrorResult& aRv);
 
   already_AddRefed<IDBRequest>
-  MozCreateFileHandle(const nsAString& aName,
+  MozCreateFileHandle(JSContext* aCx,
+                      const nsAString& aName,
                       const Optional<nsAString>& aType,
                       ErrorResult& aRv)
   {
-    return CreateMutableFile(aName, aType, aRv);
+    return CreateMutableFile(aCx, aName, aType, aRv);
   }
 
   void
   ClearBackgroundActor()
   {
     AssertIsOnOwningThread();
 
     mBackgroundActor = nullptr;
--- a/dom/indexedDB/IDBFactory.cpp
+++ b/dom/indexedDB/IDBFactory.cpp
@@ -473,47 +473,53 @@ IDBFactory::IncrementParentLoggingReques
 {
   AssertIsOnOwningThread();
   MOZ_ASSERT(mBackgroundActor);
 
   mBackgroundActor->SendIncrementLoggingRequestSerialNumber();
 }
 
 already_AddRefed<IDBOpenDBRequest>
-IDBFactory::Open(const nsAString& aName,
+IDBFactory::Open(JSContext* aCx,
+                 const nsAString& aName,
                  uint64_t aVersion,
                  ErrorResult& aRv)
 {
-  return OpenInternal(/* aPrincipal */ nullptr,
+  return OpenInternal(aCx,
+                      /* aPrincipal */ nullptr,
                       aName,
                       Optional<uint64_t>(aVersion),
                       Optional<StorageType>(),
                       /* aDeleting */ false,
                       aRv);
 }
 
 already_AddRefed<IDBOpenDBRequest>
-IDBFactory::Open(const nsAString& aName,
+IDBFactory::Open(JSContext* aCx,
+                 const nsAString& aName,
                  const IDBOpenDBOptions& aOptions,
                  ErrorResult& aRv)
 {
-  return OpenInternal(/* aPrincipal */ nullptr,
+  return OpenInternal(aCx,
+                      /* aPrincipal */ nullptr,
                       aName,
                       aOptions.mVersion,
                       aOptions.mStorage,
                       /* aDeleting */ false,
                       aRv);
 }
 
 already_AddRefed<IDBOpenDBRequest>
-IDBFactory::DeleteDatabase(const nsAString& aName,
+IDBFactory::DeleteDatabase(JSContext* aCx,
+                           const nsAString& aName,
                            const IDBOpenDBOptions& aOptions,
                            ErrorResult& aRv)
 {
-  return OpenInternal(/* aPrincipal */ nullptr,
+  return OpenInternal(aCx,
+                      /* aPrincipal */ nullptr,
                       aName,
                       Optional<uint64_t>(),
                       aOptions.mStorage,
                       /* aDeleting */ true,
                       aRv);
 }
 
 int16_t
@@ -537,77 +543,84 @@ IDBFactory::Cmp(JSContext* aCx, JS::Hand
     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_DATA_ERR);
     return 0;
   }
 
   return Key::CompareKeys(first, second);
 }
 
 already_AddRefed<IDBOpenDBRequest>
-IDBFactory::OpenForPrincipal(nsIPrincipal* aPrincipal,
+IDBFactory::OpenForPrincipal(JSContext* aCx,
+                             nsIPrincipal* aPrincipal,
                              const nsAString& aName,
                              uint64_t aVersion,
                              ErrorResult& aRv)
 {
   MOZ_ASSERT(aPrincipal);
   if (!NS_IsMainThread()) {
     MOZ_CRASH("Figure out security checks for workers!");
   }
   MOZ_ASSERT(nsContentUtils::IsCallerChrome());
 
-  return OpenInternal(aPrincipal,
+  return OpenInternal(aCx,
+                      aPrincipal,
                       aName,
                       Optional<uint64_t>(aVersion),
                       Optional<StorageType>(),
                       /* aDeleting */ false,
                       aRv);
 }
 
 already_AddRefed<IDBOpenDBRequest>
-IDBFactory::OpenForPrincipal(nsIPrincipal* aPrincipal,
+IDBFactory::OpenForPrincipal(JSContext* aCx,
+                             nsIPrincipal* aPrincipal,
                              const nsAString& aName,
                              const IDBOpenDBOptions& aOptions,
                              ErrorResult& aRv)
 {
   MOZ_ASSERT(aPrincipal);
   if (!NS_IsMainThread()) {
     MOZ_CRASH("Figure out security checks for workers!");
   }
   MOZ_ASSERT(nsContentUtils::IsCallerChrome());
 
-  return OpenInternal(aPrincipal,
+  return OpenInternal(aCx,
+                      aPrincipal,
                       aName,
                       aOptions.mVersion,
                       aOptions.mStorage,
                       /* aDeleting */ false,
                       aRv);
 }
 
 already_AddRefed<IDBOpenDBRequest>
-IDBFactory::DeleteForPrincipal(nsIPrincipal* aPrincipal,
+IDBFactory::DeleteForPrincipal(JSContext* aCx,
+                               nsIPrincipal* aPrincipal,
                                const nsAString& aName,
                                const IDBOpenDBOptions& aOptions,
                                ErrorResult& aRv)
 {
   MOZ_ASSERT(aPrincipal);
   if (!NS_IsMainThread()) {
     MOZ_CRASH("Figure out security checks for workers!");
   }
   MOZ_ASSERT(nsContentUtils::IsCallerChrome());
 
-  return OpenInternal(aPrincipal,
+  return OpenInternal(aCx,
+                      aPrincipal,
                       aName,
                       Optional<uint64_t>(),
                       aOptions.mStorage,
                       /* aDeleting */ true,
                       aRv);
 }
 
 already_AddRefed<IDBOpenDBRequest>
-IDBFactory::OpenInternal(nsIPrincipal* aPrincipal,
+IDBFactory::OpenInternal(JSContext* aCx,
+                         nsIPrincipal* aPrincipal,
                          const nsAString& aName,
                          const Optional<uint64_t>& aVersion,
                          const Optional<StorageType>& aStorageType,
                          bool aDeleting,
                          ErrorResult& aRv)
 {
   MOZ_ASSERT(mWindow || mOwningObject);
   MOZ_ASSERT_IF(!mWindow, !mPrivateBrowsingMode);
@@ -722,26 +735,25 @@ IDBFactory::OpenInternal(nsIPrincipal* a
 
       threadLocal->mIndexedDBThreadLocal = newIDBThreadLocal.forget();
     }
   }
 
   RefPtr<IDBOpenDBRequest> request;
 
   if (mWindow) {
-    JS::Rooted<JSObject*> scriptOwner(nsContentUtils::RootingCxForThread(),
+    JS::Rooted<JSObject*> scriptOwner(aCx,
                                       nsGlobalWindow::Cast(mWindow.get())->FastGetGlobalJSObject());
     MOZ_ASSERT(scriptOwner);
 
-    request = IDBOpenDBRequest::CreateForWindow(this, mWindow, scriptOwner);
+    request = IDBOpenDBRequest::CreateForWindow(aCx, this, mWindow, scriptOwner);
   } else {
-    JS::Rooted<JSObject*> scriptOwner(nsContentUtils::RootingCxForThread(),
-                                      mOwningObject);
+    JS::Rooted<JSObject*> scriptOwner(aCx, mOwningObject);
 
-    request = IDBOpenDBRequest::CreateForJS(this, scriptOwner);
+    request = IDBOpenDBRequest::CreateForJS(aCx, this, scriptOwner);
     if (!request) {
       MOZ_ASSERT(!NS_IsMainThread());
       aRv.ThrowUncatchableException();
       return nullptr;
     }
   }
 
   MOZ_ASSERT(request);
--- a/dom/indexedDB/IDBFactory.h
+++ b/dom/indexedDB/IDBFactory.h
@@ -159,50 +159,56 @@ public:
 
     return mInnerWindowID;
   }
 
   bool
   IsChrome() const;
 
   already_AddRefed<IDBOpenDBRequest>
-  Open(const nsAString& aName,
+  Open(JSContext* aCx,
+       const nsAString& aName,
        uint64_t aVersion,
        ErrorResult& aRv);
 
   already_AddRefed<IDBOpenDBRequest>
-  Open(const nsAString& aName,
+  Open(JSContext* aCx,
+       const nsAString& aName,
        const IDBOpenDBOptions& aOptions,
        ErrorResult& aRv);
 
   already_AddRefed<IDBOpenDBRequest>
-  DeleteDatabase(const nsAString& aName,
+  DeleteDatabase(JSContext* aCx,
+                 const nsAString& aName,
                  const IDBOpenDBOptions& aOptions,
                  ErrorResult& aRv);
 
   int16_t
   Cmp(JSContext* aCx,
       JS::Handle<JS::Value> aFirst,
       JS::Handle<JS::Value> aSecond,
       ErrorResult& aRv);
 
   already_AddRefed<IDBOpenDBRequest>
-  OpenForPrincipal(nsIPrincipal* aPrincipal,
+  OpenForPrincipal(JSContext* aCx,
+                   nsIPrincipal* aPrincipal,
                    const nsAString& aName,
                    uint64_t aVersion,
                    ErrorResult& aRv);
 
   already_AddRefed<IDBOpenDBRequest>
-  OpenForPrincipal(nsIPrincipal* aPrincipal,
+  OpenForPrincipal(JSContext* aCx,
+                   nsIPrincipal* aPrincipal,
                    const nsAString& aName,
                    const IDBOpenDBOptions& aOptions,
                    ErrorResult& aRv);
 
   already_AddRefed<IDBOpenDBRequest>
-  DeleteForPrincipal(nsIPrincipal* aPrincipal,
+  DeleteForPrincipal(JSContext* aCx,
+                     nsIPrincipal* aPrincipal,
                      const nsAString& aName,
                      const IDBOpenDBOptions& aOptions,
                      ErrorResult& aRv);
 
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(IDBFactory)
 
   // nsWrapperCache
@@ -226,17 +232,18 @@ private:
                       uint64_t aInnerWindowID,
                       IDBFactory** aFactory);
 
   static nsresult
   AllowedForWindowInternal(nsPIDOMWindowInner* aWindow,
                            nsIPrincipal** aPrincipal);
 
   already_AddRefed<IDBOpenDBRequest>
-  OpenInternal(nsIPrincipal* aPrincipal,
+  OpenInternal(JSContext* aCx,
+               nsIPrincipal* aPrincipal,
                const nsAString& aName,
                const Optional<uint64_t>& aVersion,
                const Optional<StorageType>& aStorageType,
                bool aDeleting,
                ErrorResult& aRv);
 
   nsresult
   BackgroundActorCreated(PBackgroundChild* aBackgroundActor,
--- a/dom/indexedDB/IDBIndex.cpp
+++ b/dom/indexedDB/IDBIndex.cpp
@@ -24,25 +24,25 @@
 #include "ActorsChild.h"
 
 namespace mozilla {
 namespace dom {
 
 namespace {
 
 already_AddRefed<IDBRequest>
-GenerateRequest(IDBIndex* aIndex)
+GenerateRequest(JSContext* aCx, IDBIndex* aIndex)
 {
   MOZ_ASSERT(aIndex);
   aIndex->AssertIsOnOwningThread();
 
   IDBTransaction* transaction = aIndex->ObjectStore()->Transaction();
 
   RefPtr<IDBRequest> request =
-    IDBRequest::Create(aIndex, transaction->Database(), transaction);
+    IDBRequest::Create(aCx, aIndex, transaction->Database(), transaction);
   MOZ_ASSERT(request);
 
   return request.forget();
 }
 
 } // namespace
 
 IDBIndex::IDBIndex(IDBObjectStore* aObjectStore, const IndexMetadata* aMetadata)
@@ -294,17 +294,17 @@ IDBIndex::GetInternal(bool aKeyOnly,
   RequestParams params;
 
   if (aKeyOnly) {
     params = IndexGetKeyParams(objectStoreId, indexId, serializedKeyRange);
   } else {
     params = IndexGetParams(objectStoreId, indexId, serializedKeyRange);
   }
 
-  RefPtr<IDBRequest> request = GenerateRequest(this);
+  RefPtr<IDBRequest> request = GenerateRequest(aCx, this);
   MOZ_ASSERT(request);
 
   if (aKeyOnly) {
     IDB_LOG_MARK("IndexedDB %s: Child  Transaction[%lld] Request[%llu]: "
                    "database(%s).transaction(%s).objectStore(%s).index(%s)."
                    "getKey(%s)",
                  "IndexedDB %s: C T[%lld] R[%llu]: IDBIndex.getKey()",
                  IDB_LOG_ID_STRING(),
@@ -378,17 +378,17 @@ IDBIndex::GetAllInternal(bool aKeysOnly,
   RequestParams params;
   if (aKeysOnly) {
     params = IndexGetAllKeysParams(objectStoreId, indexId, optionalKeyRange,
                                    limit);
   } else {
     params = IndexGetAllParams(objectStoreId, indexId, optionalKeyRange, limit);
   }
 
-  RefPtr<IDBRequest> request = GenerateRequest(this);
+  RefPtr<IDBRequest> request = GenerateRequest(aCx, this);
   MOZ_ASSERT(request);
 
   if (aKeysOnly) {
     IDB_LOG_MARK("IndexedDB %s: Child  Transaction[%lld] Request[%llu]: "
                    "database(%s).transaction(%s).objectStore(%s).index(%s)."
                    "getAllKeys(%s, %s)",
                  "IndexedDB %s: C T[%lld] R[%llu]: IDBIndex.getAllKeys()",
                  IDB_LOG_ID_STRING(),
@@ -477,17 +477,17 @@ IDBIndex::OpenCursorInternal(bool aKeysO
     openParams.objectStoreId() = objectStoreId;
     openParams.indexId() = indexId;
     openParams.optionalKeyRange() = Move(optionalKeyRange);
     openParams.direction() = direction;
 
     params = Move(openParams);
   }
 
-  RefPtr<IDBRequest> request = GenerateRequest(this);
+  RefPtr<IDBRequest> request = GenerateRequest(aCx, this);
   MOZ_ASSERT(request);
 
   if (aKeysOnly) {
     IDB_LOG_MARK("IndexedDB %s: Child  Transaction[%lld] Request[%llu]: "
                    "database(%s).transaction(%s).objectStore(%s).index(%s)."
                    "openKeyCursor(%s, %s)",
                  "IndexedDB %s: C T[%lld] R[%llu]: IDBIndex.openKeyCursor()",
                  IDB_LOG_ID_STRING(),
@@ -555,17 +555,17 @@ IDBIndex::Count(JSContext* aCx,
   if (keyRange) {
     SerializedKeyRange serializedKeyRange;
     keyRange->ToSerialized(serializedKeyRange);
     params.optionalKeyRange() = serializedKeyRange;
   } else {
     params.optionalKeyRange() = void_t();
   }
 
-  RefPtr<IDBRequest> request = GenerateRequest(this);
+  RefPtr<IDBRequest> request = GenerateRequest(aCx, this);
   MOZ_ASSERT(request);
 
   IDB_LOG_MARK("IndexedDB %s: Child  Transaction[%lld] Request[%llu]: "
                  "database(%s).transaction(%s).objectStore(%s).index(%s)."
                  "count(%s)",
                "IndexedDB %s: C T[%lld] R[%llu]: IDBObjectStore.count()",
                IDB_LOG_ID_STRING(),
                transaction->LoggingSerialNumber(),
--- a/dom/indexedDB/IDBObjectStore.cpp
+++ b/dom/indexedDB/IDBObjectStore.cpp
@@ -192,25 +192,25 @@ struct MOZ_STACK_CLASS GetAddInfoClosure
 
   ~GetAddInfoClosure()
   {
     MOZ_COUNT_DTOR(GetAddInfoClosure);
   }
 };
 
 already_AddRefed<IDBRequest>
-GenerateRequest(IDBObjectStore* aObjectStore)
+GenerateRequest(JSContext* aCx, IDBObjectStore* aObjectStore)
 {
   MOZ_ASSERT(aObjectStore);
   aObjectStore->AssertIsOnOwningThread();
 
   IDBTransaction* transaction = aObjectStore->Transaction();
 
   RefPtr<IDBRequest> request =
-    IDBRequest::Create(aObjectStore, transaction->Database(), transaction);
+    IDBRequest::Create(aCx, aObjectStore, transaction->Database(), transaction);
   MOZ_ASSERT(request);
 
   return request.forget();
 }
 
 bool
 StructuredCloneWriteCallback(JSContext* aCx,
                              JSStructuredCloneWriter* aWriter,
@@ -1392,17 +1392,17 @@ IDBObjectStore::AddOrPut(JSContext* aCx,
 
   RequestParams params;
   if (aOverwrite) {
     params = ObjectStorePutParams(commonParams);
   } else {
     params = ObjectStoreAddParams(commonParams);
   }
 
-  RefPtr<IDBRequest> request = GenerateRequest(this);
+  RefPtr<IDBRequest> request = GenerateRequest(aCx, this);
   MOZ_ASSERT(request);
 
   if (!aFromCursor) {
     if (aOverwrite) {
       IDB_LOG_MARK("IndexedDB %s: Child  Transaction[%lld] Request[%llu]: "
                      "database(%s).transaction(%s).objectStore(%s).put(%s)",
                    "IndexedDB %s: C T[%lld] R[%llu]: IDBObjectStore.put()",
                    IDB_LOG_ID_STRING(),
@@ -1471,17 +1471,17 @@ IDBObjectStore::GetAllInternal(bool aKey
 
   RequestParams params;
   if (aKeysOnly) {
     params = ObjectStoreGetAllKeysParams(id, optionalKeyRange, limit);
   } else {
     params = ObjectStoreGetAllParams(id, optionalKeyRange, limit);
   }
 
-  RefPtr<IDBRequest> request = GenerateRequest(this);
+  RefPtr<IDBRequest> request = GenerateRequest(aCx, this);
   MOZ_ASSERT(request);
 
   if (aKeysOnly) {
     IDB_LOG_MARK("IndexedDB %s: Child  Transaction[%lld] Request[%llu]: "
                    "database(%s).transaction(%s).objectStore(%s)."
                    "getAllKeys(%s, %s)",
                  "IndexedDB %s: C T[%lld] R[%llu]: IDBObjectStore.getAllKeys()",
                  IDB_LOG_ID_STRING(),
@@ -1508,17 +1508,17 @@ IDBObjectStore::GetAllInternal(bool aKey
   }
 
   mTransaction->StartRequest(request, params);
 
   return request.forget();
 }
 
 already_AddRefed<IDBRequest>
-IDBObjectStore::Clear(ErrorResult& aRv)
+IDBObjectStore::Clear(JSContext* aCx, ErrorResult& aRv)
 {
   AssertIsOnOwningThread();
 
   if (mDeletedSpec) {
     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR);
     return nullptr;
   }
 
@@ -1530,17 +1530,17 @@ IDBObjectStore::Clear(ErrorResult& aRv)
   if (!mTransaction->IsWriteAllowed()) {
     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_READ_ONLY_ERR);
     return nullptr;
   }
 
   ObjectStoreClearParams params;
   params.objectStoreId() = Id();
 
-  RefPtr<IDBRequest> request = GenerateRequest(this);
+  RefPtr<IDBRequest> request = GenerateRequest(aCx, this);
   MOZ_ASSERT(request);
 
   IDB_LOG_MARK("IndexedDB %s: Child  Transaction[%lld] Request[%llu]: "
                  "database(%s).transaction(%s).objectStore(%s).clear()",
                "IndexedDB %s: C T[%lld] R[%llu]: IDBObjectStore.clear()",
                IDB_LOG_ID_STRING(),
                mTransaction->LoggingSerialNumber(),
                request->LoggingSerialNumber(),
@@ -1729,17 +1729,17 @@ IDBObjectStore::Get(JSContext* aCx,
     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_DATA_ERR);
     return nullptr;
   }
 
   ObjectStoreGetParams params;
   params.objectStoreId() = Id();
   keyRange->ToSerialized(params.keyRange());
 
-  RefPtr<IDBRequest> request = GenerateRequest(this);
+  RefPtr<IDBRequest> request = GenerateRequest(aCx, this);
   MOZ_ASSERT(request);
 
   IDB_LOG_MARK("IndexedDB %s: Child  Transaction[%lld] Request[%llu]: "
                  "database(%s).transaction(%s).objectStore(%s).get(%s)",
                "IndexedDB %s: C T[%lld] R[%llu]: IDBObjectStore.get()",
                IDB_LOG_ID_STRING(),
                mTransaction->LoggingSerialNumber(),
                request->LoggingSerialNumber(),
@@ -1787,17 +1787,17 @@ IDBObjectStore::DeleteInternal(JSContext
     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_DATA_ERR);
     return nullptr;
   }
 
   ObjectStoreDeleteParams params;
   params.objectStoreId() = Id();
   keyRange->ToSerialized(params.keyRange());
 
-  RefPtr<IDBRequest> request = GenerateRequest(this);
+  RefPtr<IDBRequest> request = GenerateRequest(aCx, this);
   MOZ_ASSERT(request);
 
   if (!aFromCursor) {
     IDB_LOG_MARK("IndexedDB %s: Child  Transaction[%lld] Request[%llu]: "
                    "database(%s).transaction(%s).objectStore(%s).delete(%s)",
                  "IndexedDB %s: C T[%lld] R[%llu]: IDBObjectStore.delete()",
                  IDB_LOG_ID_STRING(),
                  mTransaction->LoggingSerialNumber(),
@@ -2056,17 +2056,17 @@ IDBObjectStore::Count(JSContext* aCx,
   if (keyRange) {
     SerializedKeyRange serializedKeyRange;
     keyRange->ToSerialized(serializedKeyRange);
     params.optionalKeyRange() = serializedKeyRange;
   } else {
     params.optionalKeyRange() = void_t();
   }
 
-  RefPtr<IDBRequest> request = GenerateRequest(this);
+  RefPtr<IDBRequest> request = GenerateRequest(aCx, this);
   MOZ_ASSERT(request);
 
   IDB_LOG_MARK("IndexedDB %s: Child  Transaction[%lld] Request[%llu]: "
                  "database(%s).transaction(%s).objectStore(%s).count(%s)",
                "IndexedDB %s: C T[%lld] R[%llu]: IDBObjectStore.count()",
                IDB_LOG_ID_STRING(),
                mTransaction->LoggingSerialNumber(),
                request->LoggingSerialNumber(),
@@ -2133,17 +2133,17 @@ IDBObjectStore::OpenCursorInternal(bool 
     ObjectStoreOpenCursorParams openParams;
     openParams.objectStoreId() = objectStoreId;
     openParams.optionalKeyRange() = Move(optionalKeyRange);
     openParams.direction() = direction;
 
     params = Move(openParams);
   }
 
-  RefPtr<IDBRequest> request = GenerateRequest(this);
+  RefPtr<IDBRequest> request = GenerateRequest(aCx, this);
   MOZ_ASSERT(request);
 
   if (aKeysOnly) {
     IDB_LOG_MARK("IndexedDB %s: Child  Transaction[%lld] Request[%llu]: "
                    "database(%s).transaction(%s).objectStore(%s)."
                    "openKeyCursor(%s, %s)",
                  "IndexedDB %s: C T[%lld] R[%llu]: "
                    "IDBObjectStore.openKeyCursor()",
--- a/dom/indexedDB/IDBObjectStore.h
+++ b/dom/indexedDB/IDBObjectStore.h
@@ -197,17 +197,17 @@ public:
 
     return DeleteInternal(aCx, aKey, /* aFromCursor */ false, aRv);
   }
 
   already_AddRefed<IDBRequest>
   Get(JSContext* aCx, JS::Handle<JS::Value> aKey, ErrorResult& aRv);
 
   already_AddRefed<IDBRequest>
-  Clear(ErrorResult& aRv);
+  Clear(JSContext* aCx, ErrorResult& aRv);
 
   already_AddRefed<IDBIndex>
   CreateIndex(const nsAString& aName,
               const nsAString& aKeyPath,
               const IDBIndexParameters& aOptionalParameters,
               ErrorResult& aRv);
 
   already_AddRefed<IDBIndex>
--- a/dom/indexedDB/IDBRequest.cpp
+++ b/dom/indexedDB/IDBRequest.cpp
@@ -107,57 +107,60 @@ IDBRequest::InitMembers()
   mErrorCode = NS_OK;
   mLineNo = 0;
   mColumn = 0;
   mHaveResultOrErrorCode = false;
 }
 
 // static
 already_AddRefed<IDBRequest>
-IDBRequest::Create(IDBDatabase* aDatabase,
+IDBRequest::Create(JSContext* aCx,
+                   IDBDatabase* aDatabase,
                    IDBTransaction* aTransaction)
 {
   MOZ_ASSERT(aDatabase);
   aDatabase->AssertIsOnOwningThread();
 
   RefPtr<IDBRequest> request = new IDBRequest(aDatabase);
-  CaptureCaller(request->mFilename, &request->mLineNo, &request->mColumn);
+  CaptureCaller(aCx, request->mFilename, &request->mLineNo, &request->mColumn);
 
   request->mTransaction = aTransaction;
   request->SetScriptOwner(aDatabase->GetScriptOwner());
 
   return request.forget();
 }
 
 // static
 already_AddRefed<IDBRequest>
-IDBRequest::Create(IDBObjectStore* aSourceAsObjectStore,
+IDBRequest::Create(JSContext* aCx,
+                   IDBObjectStore* aSourceAsObjectStore,
                    IDBDatabase* aDatabase,
                    IDBTransaction* aTransaction)
 {
   MOZ_ASSERT(aSourceAsObjectStore);
   aSourceAsObjectStore->AssertIsOnOwningThread();
 
-  RefPtr<IDBRequest> request = Create(aDatabase, aTransaction);
+  RefPtr<IDBRequest> request = Create(aCx, aDatabase, aTransaction);
 
   request->mSourceAsObjectStore = aSourceAsObjectStore;
 
   return request.forget();
 }
 
 // static
 already_AddRefed<IDBRequest>
-IDBRequest::Create(IDBIndex* aSourceAsIndex,
+IDBRequest::Create(JSContext* aCx,
+                   IDBIndex* aSourceAsIndex,
                    IDBDatabase* aDatabase,
                    IDBTransaction* aTransaction)
 {
   MOZ_ASSERT(aSourceAsIndex);
   aSourceAsIndex->AssertIsOnOwningThread();
 
-  RefPtr<IDBRequest> request = Create(aDatabase, aTransaction);
+  RefPtr<IDBRequest> request = Create(aCx, aDatabase, aTransaction);
 
   request->mSourceAsIndex = aSourceAsIndex;
 
   return request.forget();
 }
 
 // static
 uint64_t
@@ -178,25 +181,24 @@ IDBRequest::SetLoggingSerialNumber(uint6
 {
   AssertIsOnOwningThread();
   MOZ_ASSERT(aLoggingSerialNumber > mLoggingSerialNumber);
 
   mLoggingSerialNumber = aLoggingSerialNumber;
 }
 
 void
-IDBRequest::CaptureCaller(nsAString& aFilename, uint32_t* aLineNo,
-                          uint32_t* aColumn)
+IDBRequest::CaptureCaller(JSContext* aCx, nsAString& aFilename,
+                          uint32_t* aLineNo, uint32_t* aColumn)
 {
   MOZ_ASSERT(aFilename.IsEmpty());
   MOZ_ASSERT(aLineNo);
   MOZ_ASSERT(aColumn);
 
-  ThreadsafeAutoJSContext cx;
-  nsJSUtils::GetCallingLocation(cx, aFilename, aLineNo, aColumn);
+  nsJSUtils::GetCallingLocation(aCx, aFilename, aLineNo, aColumn);
 }
 
 void
 IDBRequest::GetSource(
              Nullable<OwningIDBObjectStoreOrIDBIndexOrIDBCursor>& aSource) const
 {
   AssertIsOnOwningThread();
 
@@ -525,50 +527,52 @@ IDBOpenDBRequest::IDBOpenDBRequest(IDBFa
 
 IDBOpenDBRequest::~IDBOpenDBRequest()
 {
   AssertIsOnOwningThread();
 }
 
 // static
 already_AddRefed<IDBOpenDBRequest>
-IDBOpenDBRequest::CreateForWindow(IDBFactory* aFactory,
+IDBOpenDBRequest::CreateForWindow(JSContext* aCx,
+                                  IDBFactory* aFactory,
                                   nsPIDOMWindowInner* aOwner,
                                   JS::Handle<JSObject*> aScriptOwner)
 {
   MOZ_ASSERT(aFactory);
   aFactory->AssertIsOnOwningThread();
   MOZ_ASSERT(aOwner);
   MOZ_ASSERT(aScriptOwner);
 
   bool fileHandleDisabled = !IndexedDatabaseManager::IsFileHandleEnabled();
 
   RefPtr<IDBOpenDBRequest> request =
     new IDBOpenDBRequest(aFactory, aOwner, fileHandleDisabled);
-  CaptureCaller(request->mFilename, &request->mLineNo, &request->mColumn);
+  CaptureCaller(aCx, request->mFilename, &request->mLineNo, &request->mColumn);
 
   request->SetScriptOwner(aScriptOwner);
 
   return request.forget();
 }
 
 // static
 already_AddRefed<IDBOpenDBRequest>
-IDBOpenDBRequest::CreateForJS(IDBFactory* aFactory,
+IDBOpenDBRequest::CreateForJS(JSContext* aCx,
+                              IDBFactory* aFactory,
                               JS::Handle<JSObject*> aScriptOwner)
 {
   MOZ_ASSERT(aFactory);
   aFactory->AssertIsOnOwningThread();
   MOZ_ASSERT(aScriptOwner);
 
   bool fileHandleDisabled = !IndexedDatabaseManager::IsFileHandleEnabled();
 
   RefPtr<IDBOpenDBRequest> request =
     new IDBOpenDBRequest(aFactory, nullptr, fileHandleDisabled);
-  CaptureCaller(request->mFilename, &request->mLineNo, &request->mColumn);
+  CaptureCaller(aCx, request->mFilename, &request->mLineNo, &request->mColumn);
 
   request->SetScriptOwner(aScriptOwner);
 
   if (!NS_IsMainThread()) {
     WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
     MOZ_ASSERT(workerPrivate);
 
     workerPrivate->AssertIsOnWorkerThread();
--- a/dom/indexedDB/IDBRequest.h
+++ b/dom/indexedDB/IDBRequest.h
@@ -62,30 +62,33 @@ protected:
   uint32_t mLineNo;
   uint32_t mColumn;
   bool mHaveResultOrErrorCode;
 
 public:
   class ResultCallback;
 
   static already_AddRefed<IDBRequest>
-  Create(IDBDatabase* aDatabase, IDBTransaction* aTransaction);
+  Create(JSContext* aCx, IDBDatabase* aDatabase, IDBTransaction* aTransaction);
 
   static already_AddRefed<IDBRequest>
-  Create(IDBObjectStore* aSource,
+  Create(JSContext* aCx,
+         IDBObjectStore* aSource,
          IDBDatabase* aDatabase,
          IDBTransaction* aTransaction);
 
   static already_AddRefed<IDBRequest>
-  Create(IDBIndex* aSource,
+  Create(JSContext* aCx,
+         IDBIndex* aSource,
          IDBDatabase* aDatabase,
          IDBTransaction* aTransaction);
 
   static void
-  CaptureCaller(nsAString& aFilename, uint32_t* aLineNo, uint32_t* aColumn);
+  CaptureCaller(JSContext* aCx, nsAString& aFilename, uint32_t* aLineNo,
+                uint32_t* aColumn);
 
   static uint64_t
   NextSerialNumber();
 
   // nsIDOMEventTarget
   virtual nsresult
   PreHandleEvent(EventChainPreVisitor& aVisitor) override;
 
@@ -229,22 +232,24 @@ class IDBOpenDBRequest final
   RefPtr<IDBFactory> mFactory;
 
   nsAutoPtr<WorkerFeature> mWorkerFeature;
 
   const bool mFileHandleDisabled;
 
 public:
   static already_AddRefed<IDBOpenDBRequest>
-  CreateForWindow(IDBFactory* aFactory,
+  CreateForWindow(JSContext* aCx,
+                  IDBFactory* aFactory,
                   nsPIDOMWindowInner* aOwner,
                   JS::Handle<JSObject*> aScriptOwner);
 
   static already_AddRefed<IDBOpenDBRequest>
-  CreateForJS(IDBFactory* aFactory,
+  CreateForJS(JSContext* aCx,
+              IDBFactory* aFactory,
               JS::Handle<JSObject*> aScriptOwner);
 
   bool
   IsFileHandleDisabled() const
   {
     return mFileHandleDisabled;
   }
 
--- a/dom/indexedDB/IDBTransaction.cpp
+++ b/dom/indexedDB/IDBTransaction.cpp
@@ -202,31 +202,31 @@ IDBTransaction::CreateVersionChange(
   aDatabase->RegisterTransaction(transaction);
   transaction->mRegistered = true;
 
   return transaction.forget();
 }
 
 // static
 already_AddRefed<IDBTransaction>
-IDBTransaction::Create(IDBDatabase* aDatabase,
+IDBTransaction::Create(JSContext* aCx, IDBDatabase* aDatabase,
                        const nsTArray<nsString>& aObjectStoreNames,
                        Mode aMode)
 {
   MOZ_ASSERT(aDatabase);
   aDatabase->AssertIsOnOwningThread();
   MOZ_ASSERT(!aObjectStoreNames.IsEmpty());
   MOZ_ASSERT(aMode == READ_ONLY ||
              aMode == READ_WRITE ||
              aMode == READ_WRITE_FLUSH ||
              aMode == CLEANUP);
 
   RefPtr<IDBTransaction> transaction =
     new IDBTransaction(aDatabase, aObjectStoreNames, aMode);
-  IDBRequest::CaptureCaller(transaction->mFilename, &transaction->mLineNo,
+  IDBRequest::CaptureCaller(aCx, transaction->mFilename, &transaction->mLineNo,
                             &transaction->mColumn);
 
   transaction->SetScriptOwner(aDatabase->GetScriptOwner());
 
   nsCOMPtr<nsIRunnable> runnable = do_QueryObject(transaction);
   nsContentUtils::RunInMetastableState(runnable.forget());
 
   transaction->mCreating = true;
--- a/dom/indexedDB/IDBTransaction.h
+++ b/dom/indexedDB/IDBTransaction.h
@@ -119,17 +119,17 @@ public:
   static already_AddRefed<IDBTransaction>
   CreateVersionChange(IDBDatabase* aDatabase,
                       indexedDB::BackgroundVersionChangeTransactionChild* aActor,
                       IDBOpenDBRequest* aOpenRequest,
                       int64_t aNextObjectStoreId,
                       int64_t aNextIndexId);
 
   static already_AddRefed<IDBTransaction>
-  Create(IDBDatabase* aDatabase,
+  Create(JSContext* aCx, IDBDatabase* aDatabase,
          const nsTArray<nsString>& aObjectStoreNames,
          Mode aMode);
 
   static IDBTransaction*
   GetCurrent();
 
   void
   AssertIsOnOwningThread() const