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 290066 30e2a55c26ee9479c2fd48c5cd04b80388a0416e
parent 290065 16ddfdbf6ff40842cca65951f0709d54980e7296
child 290067 2c3ebed966864f64b2fe2ba980c7d74cd52ae687
push id30114
push usercbook@mozilla.com
push dateThu, 24 Mar 2016 15:15:54 +0000
treeherdermozilla-central@24c5fbde4488 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskhuey
bugs1257725
milestone48.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
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