Bug 1297558 - Remove explicit calls to Expose*ToActiveJS r=mccr8
authorJon Coppeard <jcoppeard@mozilla.com>
Tue, 18 Oct 2016 17:58:19 +0100
changeset 318502 1538850bba0fa58be8bddea4670e9f1c2f88f8f0
parent 318501 dac69b2b8d26fff4e56703c494889e64b464b088
child 318503 b89b2c0f03deb04d76809a5bbfdb74dc19d54176
push id20725
push userphilringnalda@gmail.com
push dateThu, 20 Oct 2016 01:36:01 +0000
treeherderfx-team@998ad5a74da8 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmccr8
bugs1297558
milestone52.0a1
Bug 1297558 - Remove explicit calls to Expose*ToActiveJS r=mccr8
dom/base/DOMRequest.h
dom/base/nsFrameMessageManager.cpp
dom/base/nsGlobalWindow.cpp
dom/base/nsGlobalWindow.h
dom/base/nsIScriptContext.h
dom/base/nsJSEnvironment.cpp
dom/base/nsJSEnvironment.h
dom/base/nsScriptLoader.cpp
dom/bindings/CallbackObject.h
dom/bindings/Exceptions.cpp
dom/bluetooth/common/webapi/BluetoothGattAttributeEvent.cpp
dom/bluetooth/common/webapi/BluetoothLeDeviceEvent.cpp
dom/canvas/ImageData.h
dom/events/MessageEvent.cpp
dom/html/nsIHTMLDocument.h
dom/indexedDB/IDBCursor.cpp
dom/indexedDB/IDBIndex.cpp
dom/indexedDB/IDBKeyRange.cpp
dom/indexedDB/IDBObjectStore.cpp
dom/indexedDB/IDBRequest.cpp
dom/media/eme/MediaEncryptedEvent.cpp
dom/media/eme/MediaKeyMessageEvent.cpp
dom/media/webaudio/AudioBuffer.cpp
dom/media/webaudio/WaveShaperNode.h
dom/nfc/MozNDEFRecord.h
dom/notification/Notification.cpp
dom/promise/Promise.cpp
dom/promise/Promise.h
dom/promise/PromiseCallback.cpp
dom/promise/PromiseDebugging.cpp
dom/push/PushSubscriptionOptions.cpp
dom/vr/VRDisplay.cpp
dom/workers/ServiceWorkerEvents.cpp
dom/workers/ServiceWorkerMessageEvent.cpp
dom/xhr/XMLHttpRequestMainThread.cpp
dom/xhr/XMLHttpRequestWorker.cpp
js/public/RootingAPI.h
js/xpconnect/src/XPCWrappedJS.cpp
js/xpconnect/src/xpcprivate.h
js/xpconnect/wrappers/WrapperFactory.cpp
--- a/dom/base/DOMRequest.h
+++ b/dom/base/DOMRequest.h
@@ -55,17 +55,16 @@ public:
     return mDone ? DOMRequestReadyState::Done
                  : DOMRequestReadyState::Pending;
   }
 
   void GetResult(JSContext*, JS::MutableHandle<JS::Value> aRetval) const
   {
     NS_ASSERTION(mDone || mResult.isUndefined(),
                  "Result should be undefined when pending");
-    JS::ExposeValueToActiveJS(mResult);
     aRetval.set(mResult);
   }
 
   DOMError* GetError() const
   {
     NS_ASSERTION(mDone || !mError,
                  "Error should be null when pending");
     return mError;
--- a/dom/base/nsFrameMessageManager.cpp
+++ b/dom/base/nsFrameMessageManager.cpp
@@ -1900,20 +1900,17 @@ nsMessageManagerScriptExecutor::InitChil
   DidCreateGlobal();
   return true;
 }
 
 void
 nsMessageManagerScriptExecutor::MarkScopesForCC()
 {
   for (uint32_t i = 0; i < mAnonymousGlobalScopes.Length(); ++i) {
-    JSObject* obj = mAnonymousGlobalScopes[i];
-    if (obj) {
-      JS::ExposeObjectToActiveJS(obj);
-    }
+    mAnonymousGlobalScopes[i].exposeToActiveJS();
   }
 }
 
 NS_IMPL_ISUPPORTS(nsScriptCacheCleaner, nsIObserver)
 
 nsFrameMessageManager* nsFrameMessageManager::sChildProcessManager = nullptr;
 nsFrameMessageManager* nsFrameMessageManager::sParentProcessManager = nullptr;
 nsFrameMessageManager* nsFrameMessageManager::sSameProcessParentManager = nullptr;
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -1814,17 +1814,17 @@ NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_BEGIN(
     if (nsCCUncollectableMarker::InGeneration(tmp->mCanSkipCCGeneration)) {
       return true;
     }
     tmp->mCanSkipCCGeneration = nsCCUncollectableMarker::sGeneration;
     if (tmp->mCachedXBLPrototypeHandlers) {
       for (auto iter = tmp->mCachedXBLPrototypeHandlers->Iter();
            !iter.Done();
            iter.Next()) {
-        JS::ExposeObjectToActiveJS(iter.Data());
+        iter.Data().exposeToActiveJS();
       }
     }
     if (EventListenerManager* elm = tmp->GetExistingListenerManager()) {
       elm->MarkForCC();
     }
     tmp->UnmarkGrayTimers();
     return true;
   }
@@ -2019,18 +2019,17 @@ nsGlobalWindow::RiskyUnlink()
 }
 #endif
 
 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsGlobalWindow)
   if (tmp->mCachedXBLPrototypeHandlers) {
     for (auto iter = tmp->mCachedXBLPrototypeHandlers->Iter();
          !iter.Done();
          iter.Next()) {
-      JS::Heap<JSObject*>& data = iter.Data();
-      aCallbacks.Trace(&data, "Cached XBL prototype handler", aClosure);
+      aCallbacks.Trace(&iter.Data(), "Cached XBL prototype handler", aClosure);
     }
   }
   NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
 NS_IMPL_CYCLE_COLLECTION_TRACE_END
 
 bool
 nsGlobalWindow::IsBlackForCC(bool aTracingNeeded)
 {
@@ -2643,18 +2642,17 @@ nsGlobalWindow::SetNewDocument(nsIDocume
 
     if (aDocument != oldDoc) {
       JS::ExposeObjectToActiveJS(newInnerGlobal);
     }
 
     // We're reusing the inner window, but this still counts as a navigation,
     // so all expandos and such defined on the outer window should go away. Force
     // all Xray wrappers to be recomputed.
-    JS::Rooted<JSObject*> rootedObject(cx, GetWrapperPreserveColor());
-    JS::ExposeObjectToActiveJS(rootedObject);
+    JS::Rooted<JSObject*> rootedObject(cx, GetWrapper());
     if (!JS_RefreshCrossCompartmentWrappers(cx, rootedObject)) {
       return NS_ERROR_FAILURE;
     }
 
     // Inner windows are only reused for same-origin principals, but the principals
     // don't necessarily match exactly. Update the principal on the compartment to
     // match the new document.
     // NB: We don't just call currentInner->RefreshCompartmentPrincipals() here
@@ -9033,17 +9031,17 @@ nsGlobalWindow::GetCachedXBLPrototypeHan
   return handler;
 }
 
 void
 nsGlobalWindow::CacheXBLPrototypeHandler(nsXBLPrototypeHandler* aKey,
                                          JS::Handle<JSObject*> aHandler)
 {
   if (!mCachedXBLPrototypeHandlers) {
-    mCachedXBLPrototypeHandlers = new nsJSThingHashtable<nsPtrHashKey<nsXBLPrototypeHandler>, JSObject*>();
+    mCachedXBLPrototypeHandlers = new XBLPrototypeHandlerTable();
     PreserveWrapper(ToSupports(this));
   }
 
   mCachedXBLPrototypeHandlers->Put(aKey, aHandler);
 }
 
 Element*
 nsGlobalWindow::GetFrameElementOuter(nsIPrincipal& aSubjectPrincipal)
--- a/dom/base/nsGlobalWindow.h
+++ b/dom/base/nsGlobalWindow.h
@@ -1912,17 +1912,18 @@ protected:
   bool mNetworkUploadObserverEnabled;
   bool mNetworkDownloadObserverEnabled;
 #endif // MOZ_B2G
 
   bool mCleanedUp;
 
   nsCOMPtr<nsIDOMOfflineResourceList> mApplicationCache;
 
-  nsAutoPtr<nsJSThingHashtable<nsPtrHashKey<nsXBLPrototypeHandler>, JSObject*> > mCachedXBLPrototypeHandlers;
+  using XBLPrototypeHandlerTable = nsJSThingHashtable<nsPtrHashKey<nsXBLPrototypeHandler>, JSObject*>;
+  nsAutoPtr<XBLPrototypeHandlerTable> mCachedXBLPrototypeHandlers;
 
   // mSuspendedDoc is only set on outer windows. It's useful when we get matched
   // EnterModalState/LeaveModalState calls, in which case the outer window is
   // responsible for unsuspending events on the document. If we don't (for
   // example, if the outer window is closed before the LeaveModalState call),
   // then the inner window whose mDoc is our mSuspendedDoc is responsible for
   // unsuspending it.
   nsCOMPtr<nsIDocument> mSuspendedDoc;
--- a/dom/base/nsIScriptContext.h
+++ b/dom/base/nsIScriptContext.h
@@ -80,17 +80,16 @@ public:
    */
   virtual void DidInitializeContext() = 0;
 
   /**
    * Access the Window Proxy. The setter should only be called by nsGlobalWindow.
    */
   virtual void SetWindowProxy(JS::Handle<JSObject*> aWindowProxy) = 0;
   virtual JSObject* GetWindowProxy() = 0;
-  virtual JSObject* GetWindowProxyPreserveColor() = 0;
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsIScriptContext, NS_ISCRIPTCONTEXT_IID)
 
 #define NS_IOFFTHREADSCRIPTRECEIVER_IID \
 {0x3a980010, 0x878d, 0x46a9,            \
   {0x93, 0xad, 0xbc, 0xfd, 0xd3, 0x8e, 0xa0, 0xc2}}
 
--- a/dom/base/nsJSEnvironment.cpp
+++ b/dom/base/nsJSEnvironment.cpp
@@ -2214,27 +2214,16 @@ void
 nsJSContext::SetWindowProxy(JS::Handle<JSObject*> aWindowProxy)
 {
   mWindowProxy = aWindowProxy;
 }
 
 JSObject*
 nsJSContext::GetWindowProxy()
 {
-  JSObject* windowProxy = GetWindowProxyPreserveColor();
-  if (windowProxy) {
-    JS::ExposeObjectToActiveJS(windowProxy);
-  }
-
-  return windowProxy;
-}
-
-JSObject*
-nsJSContext::GetWindowProxyPreserveColor()
-{
   return mWindowProxy;
 }
 
 void
 nsJSContext::LikelyShortLivingObjectCreated()
 {
   ++sLikelyShortLivingObjectsNeedingGC;
 }
--- a/dom/base/nsJSEnvironment.h
+++ b/dom/base/nsJSEnvironment.h
@@ -58,17 +58,16 @@ public:
 
   virtual nsresult InitClasses(JS::Handle<JSObject*> aGlobalObj) override;
 
   virtual void WillInitializeContext() override;
   virtual void DidInitializeContext() override;
 
   virtual void SetWindowProxy(JS::Handle<JSObject*> aWindowProxy) override;
   virtual JSObject* GetWindowProxy() override;
-  virtual JSObject* GetWindowProxyPreserveColor() override;
 
   static void LoadStart();
   static void LoadEnd();
 
   enum IsShrinking {
     ShrinkingGC,
     NonShrinkingGC
   };
--- a/dom/base/nsScriptLoader.cpp
+++ b/dom/base/nsScriptLoader.cpp
@@ -309,28 +309,18 @@ public:
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(nsModuleScript)
 
   nsModuleScript(nsScriptLoader* aLoader,
                  nsIURI* aBaseURL,
                  JS::Handle<JSObject*> aModuleRecord);
 
   nsScriptLoader* Loader() const { return mLoader; }
-  JSObject* ModuleRecord() const
-  {
-    if (mModuleRecord) {
-      JS::ExposeObjectToActiveJS(mModuleRecord);
-    }
-    return mModuleRecord;
-  }
-  JS::Value Exception() const
-  {
-    JS::ExposeValueToActiveJS(mException);
-    return mException;
-  }
+  JSObject* ModuleRecord() const { return mModuleRecord; }
+  JS::Value Exception() const { return mException; }
   nsIURI* BaseURL() const { return mBaseURL; }
 
   void SetInstantiationResult(JS::Handle<JS::Value> aMaybeException);
   bool IsUninstantiated() const {
     return mInstantiationState == Uninstantiated;
   }
   bool IsInstantiated() const {
     return mInstantiationState == Instantiated;
--- a/dom/bindings/CallbackObject.h
+++ b/dom/bindings/CallbackObject.h
@@ -76,37 +76,29 @@ public:
                           JS::Handle<JSObject*> aAsyncStack,
                           nsIGlobalObject* aIncumbentGlobal)
   {
     Init(aCallback, aAsyncStack, aIncumbentGlobal);
   }
 
   JS::Handle<JSObject*> Callback() const
   {
-    JS::ExposeObjectToActiveJS(mCallback);
+    mCallback.exposeToActiveJS();
     return CallbackPreserveColor();
   }
 
   JSObject* GetCreationStack() const
   {
-    JSObject* result = mCreationStack;
-    if (result) {
-      JS::ExposeObjectToActiveJS(result);
-    }
-    return result;
+    return mCreationStack;
   }
 
   void MarkForCC()
   {
-    if (mCallback) {
-      JS::ExposeObjectToActiveJS(mCallback);
-    }
-    if (mCreationStack) {
-      JS::ExposeObjectToActiveJS(mCreationStack);
-    }
+    mCallback.exposeToActiveJS();
+    mCreationStack.exposeToActiveJS();
   }
 
   /*
    * This getter does not change the color of the JSObject meaning that the
    * object returned is not guaranteed to be kept alive past the next CC.
    *
    * This should only be called if you are certain that the return value won't
    * be passed into a JS API function and that it won't be stored without being
--- a/dom/bindings/Exceptions.cpp
+++ b/dom/bindings/Exceptions.cpp
@@ -340,17 +340,17 @@ NS_IMETHODIMP JSStackFrame::GetLanguageN
 // @argument aPropGetter the getter function to call.
 // @argument aIsCached whether we've cached this property's value before.
 //
 // @argument [out] aCanCache whether the value can get cached.
 // @argument [out] aUseCachedValue if true, just use the cached value.
 // @argument [out] aValue the value we got from the stack.
 template<typename ReturnType, typename GetterOutParamType>
 static void
-GetValueIfNotCached(JSContext* aCx, JSObject* aStack,
+GetValueIfNotCached(JSContext* aCx, const JS::Heap<JSObject*>& aStack,
                     JS::SavedFrameResult (*aPropGetter)(JSContext*,
                                                         JS::Handle<JSObject*>,
                                                         GetterOutParamType,
                                                         JS::SavedFrameSelfHosted),
                     bool aIsCached, bool* aCanCache, bool* aUseCachedValue,
                     ReturnType aValue)
 {
   MOZ_ASSERT(aStack);
@@ -360,17 +360,16 @@ GetValueIfNotCached(JSContext* aCx, JSOb
   // slow path.
   *aCanCache = js::GetContextCompartment(aCx) == js::GetObjectCompartment(stack);
   if (*aCanCache && aIsCached) {
     *aUseCachedValue = true;
     return;
   }
 
   *aUseCachedValue = false;
-  JS::ExposeObjectToActiveJS(stack);
 
   aPropGetter(aCx, stack, aValue, JS::SavedFrameSelfHosted::Exclude);
 }
 
 NS_IMETHODIMP JSStackFrame::GetFilename(JSContext* aCx, nsAString& aFilename)
 {
   if (!mStack) {
     aFilename.Truncate();
@@ -623,17 +622,16 @@ NS_IMETHODIMP JSStackFrame::GetFormatted
   // slow path.
   bool canCache =
     js::GetContextCompartment(aCx) == js::GetObjectCompartment(mStack);
   if (canCache && mFormattedStackInitialized) {
     aStack = mFormattedStack;
     return NS_OK;
   }
 
-  JS::ExposeObjectToActiveJS(mStack);
   JS::Rooted<JSObject*> stack(aCx, mStack);
 
   JS::Rooted<JSString*> formattedStack(aCx);
   if (!JS::BuildStackString(aCx, stack, &formattedStack)) {
     JS_ClearPendingException(aCx);
     aStack.Truncate();
     return NS_OK;
   }
@@ -652,19 +650,16 @@ NS_IMETHODIMP JSStackFrame::GetFormatted
     mFormattedStackInitialized = true;
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP JSStackFrame::GetNativeSavedFrame(JS::MutableHandle<JS::Value> aSavedFrame)
 {
-  if (mStack) {
-    JS::ExposeObjectToActiveJS(mStack);
-  }
   aSavedFrame.setObjectOrNull(mStack);
   return NS_OK;
 }
 
 NS_IMETHODIMP JSStackFrame::ToString(JSContext* aCx, nsACString& _retval)
 {
   _retval.Truncate();
 
--- a/dom/bluetooth/common/webapi/BluetoothGattAttributeEvent.cpp
+++ b/dom/bluetooth/common/webapi/BluetoothGattAttributeEvent.cpp
@@ -163,17 +163,16 @@ BluetoothGattAttributeEvent::GetValue(
     if (!mValue) {
       aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
       return;
     }
 
     mRawValue.Clear();
   }
 
-  JS::ExposeObjectToActiveJS(mValue);
   aValue.set(mValue);
 
   return;
 }
 
 bool
 BluetoothGattAttributeEvent::NeedResponse() const
 {
--- a/dom/bluetooth/common/webapi/BluetoothLeDeviceEvent.cpp
+++ b/dom/bluetooth/common/webapi/BluetoothLeDeviceEvent.cpp
@@ -135,13 +135,12 @@ BluetoothLeDeviceEvent::GetScanRecord(
                                       mRawScanRecord.Length(),
                                       mRawScanRecord.Elements());
     if (!mScanRecord) {
       aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
       return;
     }
     mRawScanRecord.Clear();
   }
-  JS::ExposeObjectToActiveJS(mScanRecord);
   aScanRecord.set(mScanRecord);
 
   return;
 }
--- a/dom/canvas/ImageData.h
+++ b/dom/canvas/ImageData.h
@@ -64,17 +64,16 @@ public:
     return mHeight;
   }
   void GetData(JSContext* cx, JS::MutableHandle<JSObject*> aData) const
   {
     aData.set(GetDataObject());
   }
   JSObject* GetDataObject() const
   {
-    JS::ExposeObjectToActiveJS(mData);
     return mData;
   }
 
   bool WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto, JS::MutableHandle<JSObject*> aReflector);
 
 private:
   void HoldData();
   void DropData();
--- a/dom/events/MessageEvent.cpp
+++ b/dom/events/MessageEvent.cpp
@@ -60,17 +60,16 @@ MessageEvent::WrapObjectInternal(JSConte
 {
   return mozilla::dom::MessageEventBinding::Wrap(aCx, this, aGivenProto);
 }
 
 void
 MessageEvent::GetData(JSContext* aCx, JS::MutableHandle<JS::Value> aData,
                       ErrorResult& aRv)
 {
-  JS::ExposeValueToActiveJS(mData);
   aData.set(mData);
   if (!JS_WrapValue(aCx, aData)) {
     aRv.Throw(NS_ERROR_FAILURE);
   }
 }
 
 void
 MessageEvent::GetOrigin(nsAString& aOrigin) const
--- a/dom/html/nsIHTMLDocument.h
+++ b/dom/html/nsIHTMLDocument.h
@@ -43,17 +43,17 @@ public:
   virtual void RemovedForm() = 0;
   /**
    * Called to get a better count of forms than document.forms can provide
    * without calling FlushPendingNotifications (bug 138892).
    */
   // XXXbz is this still needed now that we can flush just content,
   // not the rest?
   virtual int32_t GetNumFormsSynchronous() = 0;
-  
+
   virtual bool IsWriting() = 0;
 
   /**
    * Get the list of form elements in the document.
    */
   virtual nsContentList* GetForms() = 0;
 
   /**
--- a/dom/indexedDB/IDBCursor.cpp
+++ b/dom/indexedDB/IDBCursor.cpp
@@ -338,17 +338,16 @@ IDBCursor::GetKey(JSContext* aCx, JS::Mu
     aRv = mKey.ToJSVal(aCx, mCachedKey);
     if (NS_WARN_IF(aRv.Failed())) {
       return;
     }
 
     mHaveCachedKey = true;
   }
 
-  JS::ExposeValueToActiveJS(mCachedKey);
   aResult.set(mCachedKey);
 }
 
 void
 IDBCursor::GetPrimaryKey(JSContext* aCx, JS::MutableHandle<JS::Value> aResult,
                          ErrorResult& aRv)
 {
   AssertIsOnOwningThread();
@@ -374,17 +373,16 @@ IDBCursor::GetPrimaryKey(JSContext* aCx,
     aRv = key.ToJSVal(aCx, mCachedPrimaryKey);
     if (NS_WARN_IF(aRv.Failed())) {
       return;
     }
 
     mHaveCachedPrimaryKey = true;
   }
 
-  JS::ExposeValueToActiveJS(mCachedPrimaryKey);
   aResult.set(mCachedPrimaryKey);
 }
 
 void
 IDBCursor::GetValue(JSContext* aCx, JS::MutableHandle<JS::Value> aResult,
                     ErrorResult& aRv)
 {
   AssertIsOnOwningThread();
@@ -408,17 +406,16 @@ IDBCursor::GetValue(JSContext* aCx, JS::
     }
 
     IDBObjectStore::ClearCloneReadInfo(mCloneInfo);
 
     mCachedValue = val;
     mHaveCachedValue = true;
   }
 
-  JS::ExposeValueToActiveJS(mCachedValue);
   aResult.set(mCachedValue);
 }
 
 void
 IDBCursor::Continue(JSContext* aCx,
                     JS::Handle<JS::Value> aKey,
                     ErrorResult &aRv)
 {
--- a/dom/indexedDB/IDBIndex.cpp
+++ b/dom/indexedDB/IDBIndex.cpp
@@ -285,34 +285,32 @@ void
 IDBIndex::GetKeyPath(JSContext* aCx,
                      JS::MutableHandle<JS::Value> aResult,
                      ErrorResult& aRv)
 {
   AssertIsOnOwningThread();
 
   if (!mCachedKeyPath.isUndefined()) {
     MOZ_ASSERT(mRooted);
-    JS::ExposeValueToActiveJS(mCachedKeyPath);
     aResult.set(mCachedKeyPath);
     return;
   }
 
   MOZ_ASSERT(!mRooted);
 
   aRv = GetKeyPath().ToJSVal(aCx, mCachedKeyPath);
   if (NS_WARN_IF(aRv.Failed())) {
     return;
   }
 
   if (mCachedKeyPath.isGCThing()) {
     mozilla::HoldJSObjects(this);
     mRooted = true;
   }
 
-  JS::ExposeValueToActiveJS(mCachedKeyPath);
   aResult.set(mCachedKeyPath);
 }
 
 already_AddRefed<IDBRequest>
 IDBIndex::GetInternal(bool aKeyOnly,
                       JSContext* aCx,
                       JS::Handle<JS::Value> aKey,
                       ErrorResult& aRv)
--- a/dom/indexedDB/IDBKeyRange.cpp
+++ b/dom/indexedDB/IDBKeyRange.cpp
@@ -302,17 +302,16 @@ IDBKeyRange::GetLower(JSContext* aCx, JS
     aRv = Lower().ToJSVal(aCx, mCachedLowerVal);
     if (aRv.Failed()) {
       return;
     }
 
     mHaveCachedLowerVal = true;
   }
 
-  JS::ExposeValueToActiveJS(mCachedLowerVal);
   aResult.set(mCachedLowerVal);
 }
 
 void
 IDBKeyRange::GetUpper(JSContext* aCx, JS::MutableHandle<JS::Value> aResult,
                       ErrorResult& aRv)
 {
   AssertIsOnOwningThread();
@@ -326,17 +325,16 @@ IDBKeyRange::GetUpper(JSContext* aCx, JS
     aRv = Upper().ToJSVal(aCx, mCachedUpperVal);
     if (aRv.Failed()) {
       return;
     }
 
     mHaveCachedUpperVal = true;
   }
 
-  JS::ExposeValueToActiveJS(mCachedUpperVal);
   aResult.set(mCachedUpperVal);
 }
 
 bool
 IDBKeyRange::Includes(JSContext* aCx,
                       JS::Handle<JS::Value> aValue,
                       ErrorResult& aRv) const
 {
--- a/dom/indexedDB/IDBObjectStore.cpp
+++ b/dom/indexedDB/IDBObjectStore.cpp
@@ -1595,32 +1595,30 @@ IDBObjectStore::GetParentObject() const
 }
 
 void
 IDBObjectStore::GetKeyPath(JSContext* aCx,
                            JS::MutableHandle<JS::Value> aResult,
                            ErrorResult& aRv)
 {
   if (!mCachedKeyPath.isUndefined()) {
-    JS::ExposeValueToActiveJS(mCachedKeyPath);
     aResult.set(mCachedKeyPath);
     return;
   }
 
   aRv = GetKeyPath().ToJSVal(aCx, mCachedKeyPath);
   if (NS_WARN_IF(aRv.Failed())) {
     return;
   }
 
   if (mCachedKeyPath.isGCThing()) {
     mozilla::HoldJSObjects(this);
     mRooted = true;
   }
 
-  JS::ExposeValueToActiveJS(mCachedKeyPath);
   aResult.set(mCachedKeyPath);
 }
 
 already_AddRefed<DOMStringList>
 IDBObjectStore::IndexNames()
 {
   AssertIsOnOwningThread();
 
--- a/dom/indexedDB/IDBRequest.cpp
+++ b/dom/indexedDB/IDBRequest.cpp
@@ -336,17 +336,16 @@ IDBRequest::GetResult(JS::MutableHandle<
 {
   AssertIsOnOwningThread();
 
   if (!mHaveResultOrErrorCode) {
     aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
     return;
   }
 
-  JS::ExposeValueToActiveJS(mResultVal);
   aResult.set(mResultVal);
 }
 
 void
 IDBRequest::SetResultCallback(ResultCallback* aCallback)
 {
   AssertIsOnOwningThread();
   MOZ_ASSERT(aCallback);
@@ -362,17 +361,16 @@ IDBRequest::SetResultCallback(ResultCall
 
   AutoJSAPI autoJS;
   Maybe<JSAutoCompartment> ac;
 
   if (GetScriptOwner()) {
     // If we have a script owner we want the SafeJSContext and then to enter the
     // script owner's compartment.
     autoJS.Init();
-    JS::ExposeObjectToActiveJS(GetScriptOwner());
     ac.emplace(autoJS.cx(), GetScriptOwner());
   } else {
     // Otherwise our owner is a window and we use that to initialize.
     MOZ_ASSERT(GetOwner());
     if (!autoJS.Init(GetOwner())) {
       IDB_WARNING("Failed to initialize AutoJSAPI!");
       SetError(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
       return;
--- a/dom/media/eme/MediaEncryptedEvent.cpp
+++ b/dom/media/eme/MediaEncryptedEvent.cpp
@@ -117,16 +117,13 @@ MediaEncryptedEvent::GetInitData(JSConte
                                     mRawInitData.Length(),
                                     mRawInitData.Elements());
     if (!mInitData) {
       aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
       return;
     }
     mRawInitData.Clear();
   }
-  if (mInitData) {
-    JS::ExposeObjectToActiveJS(mInitData);
-  }
   aData.set(mInitData);
 }
 
 } // namespace dom
 } // namespace mozilla
--- a/dom/media/eme/MediaKeyMessageEvent.cpp
+++ b/dom/media/eme/MediaKeyMessageEvent.cpp
@@ -115,14 +115,13 @@ MediaKeyMessageEvent::GetMessage(JSConte
                                    mRawMessage.Length(),
                                    mRawMessage.Elements());
     if (!mMessage) {
       aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
       return;
     }
     mRawMessage.Clear();
   }
-  JS::ExposeObjectToActiveJS(mMessage);
   aMessage.set(mMessage);
 }
 
 } // namespace dom
 } // namespace mozilla
--- a/dom/media/webaudio/AudioBuffer.cpp
+++ b/dom/media/webaudio/AudioBuffer.cpp
@@ -339,19 +339,16 @@ AudioBuffer::GetChannelData(JSContext* a
     return;
   }
 
   if (!RestoreJSChannelData(aJSContext)) {
     aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
     return;
   }
 
-  if (mJSChannels[aChannel]) {
-    JS::ExposeObjectToActiveJS(mJSChannels[aChannel]);
-  }
   aRetval.set(mJSChannels[aChannel]);
 }
 
 already_AddRefed<ThreadSharedFloatArrayBufferList>
 AudioBuffer::StealJSArrayDataIntoSharedChannels(JSContext* aJSContext)
 {
   // "1. If any of the AudioBuffer's ArrayBuffer have been detached, abort
   // these steps, and return a zero-length channel data buffers to the
@@ -366,28 +363,22 @@ AudioBuffer::StealJSArrayDataIntoSharedC
 
   // "2. Detach all ArrayBuffers for arrays previously returned by
   // getChannelData on this AudioBuffer."
   // "3. Retain the underlying data buffers from those ArrayBuffers and return
   // references to them to the invoker."
   RefPtr<ThreadSharedFloatArrayBufferList> result =
     new ThreadSharedFloatArrayBufferList(mJSChannels.Length());
   for (uint32_t i = 0; i < mJSChannels.Length(); ++i) {
-    if (mJSChannels[i]) {
-      JS::ExposeObjectToActiveJS(mJSChannels[i]);
-    }
     JS::Rooted<JSObject*> arrayBufferView(aJSContext, mJSChannels[i]);
     bool isSharedMemory;
     JS::Rooted<JSObject*> arrayBuffer(aJSContext,
                                       JS_GetArrayBufferViewBuffer(aJSContext,
                                                                   arrayBufferView,
                                                                   &isSharedMemory));
-    if (arrayBuffer) {
-      JS::ExposeObjectToActiveJS(arrayBuffer);
-    }
     // The channel data arrays should all have originated in
     // RestoreJSChannelData, where they are created unshared.
     MOZ_ASSERT(!isSharedMemory);
     auto stolenData = arrayBuffer
       ? static_cast<float*>(JS_StealArrayBufferContents(aJSContext,
                                                         arrayBuffer))
       : nullptr;
     if (stolenData) {
--- a/dom/media/webaudio/WaveShaperNode.h
+++ b/dom/media/webaudio/WaveShaperNode.h
@@ -23,19 +23,16 @@ public:
 
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(WaveShaperNode, AudioNode)
 
   JSObject* WrapObject(JSContext *aCx, JS::Handle<JSObject*> aGivenProto) override;
 
   void GetCurve(JSContext* aCx, JS::MutableHandle<JSObject*> aRetval) const
   {
-    if (mCurve) {
-      JS::ExposeObjectToActiveJS(mCurve);
-    }
     aRetval.set(mCurve);
   }
   void SetCurve(const Nullable<Float32Array>& aData, ErrorResult& aRv);
 
   OverSampleType Oversample() const
   {
     return mType;
   }
--- a/dom/nfc/MozNDEFRecord.h
+++ b/dom/nfc/MozNDEFRecord.h
@@ -58,35 +58,26 @@ public:
 
   TNF Tnf() const
   {
     return mTnf;
   }
 
   void GetType(JSContext* /* unused */, JS::MutableHandle<JSObject*> aRetVal) const
   {
-    if (mType) {
-      JS::ExposeObjectToActiveJS(mType);
-    }
     aRetVal.set(mType);
   }
 
   void GetId(JSContext* /* unused */, JS::MutableHandle<JSObject*> aRetVal) const
   {
-    if (mId) {
-      JS::ExposeObjectToActiveJS(mId);
-    }
     aRetVal.set(mId);
   }
 
   void GetPayload(JSContext* /* unused */, JS::MutableHandle<JSObject*> aRetVal) const
   {
-    if (mPayload) {
-      JS::ExposeObjectToActiveJS(mPayload);
-    }
     aRetVal.set(mPayload);
   }
 
   uint32_t Size() const
   {
     return mSize;
   }
 
--- a/dom/notification/Notification.cpp
+++ b/dom/notification/Notification.cpp
@@ -2342,17 +2342,16 @@ Notification::GetData(JSContext* aCx,
     }
     mData = data;
   }
   if (mData.isNull()) {
     aRetval.setNull();
     return;
   }
 
-  JS::ExposeValueToActiveJS(mData);
   aRetval.set(mData);
 }
 
 void
 Notification::InitFromJSVal(JSContext* aCx, JS::Handle<JS::Value> aData,
                             ErrorResult& aRv)
 {
   if (!mDataAsBase64.IsEmpty() || aData.isNull()) {
--- a/dom/promise/Promise.cpp
+++ b/dom/promise/Promise.cpp
@@ -429,26 +429,20 @@ NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(Pro
 #else // SPIDERMONKEY_PROMISE
   NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mPromiseObj);
 #endif // SPIDERMONKEY_PROMISE
 NS_IMPL_CYCLE_COLLECTION_TRACE_END
 
 #ifndef SPIDERMONKEY_PROMISE
 NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_BEGIN(Promise)
   if (tmp->IsBlack()) {
-    JS::ExposeValueToActiveJS(tmp->mResult);
-    if (tmp->mAllocationStack) {
-      JS::ExposeObjectToActiveJS(tmp->mAllocationStack);
-    }
-    if (tmp->mRejectionStack) {
-      JS::ExposeObjectToActiveJS(tmp->mRejectionStack);
-    }
-    if (tmp->mFullfillmentStack) {
-      JS::ExposeObjectToActiveJS(tmp->mFullfillmentStack);
-    }
+    tmp->mResult.exposeToActiveJS();
+    tmp->mAllocationStack.exposeToActiveJS();
+    tmp->mRejectionStack.exposeToActiveJS();
+    tmp->mFullfillmentStack.exposeToActiveJS();
     return true;
   }
 NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_END
 
 NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_BEGIN(Promise)
   return tmp->IsBlackAndDoesNotNeedTracing(tmp);
 NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_END
 
@@ -511,17 +505,16 @@ Promise::~Promise()
 
 bool
 Promise::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto,
                     JS::MutableHandle<JSObject*> aWrapper)
 {
 #ifdef DEBUG
   binding_detail::AssertReflectorHasGivenProto(aCx, mPromiseObj, aGivenProto);
 #endif // DEBUG
-  JS::ExposeObjectToActiveJS(mPromiseObj);
   aWrapper.set(mPromiseObj);
   return true;
 }
 
 // static
 already_AddRefed<Promise>
 Promise::Create(nsIGlobalObject* aGlobal, ErrorResult& aRv)
 {
@@ -2616,17 +2609,16 @@ Promise::MaybeReportRejected()
   AutoJSAPI jsapi;
   // We may not have a usable global by now (if it got unlinked
   // already), so don't init with it.
   jsapi.Init();
   JSContext* cx = jsapi.cx();
   JS::Rooted<JSObject*> obj(cx, GetWrapper());
   MOZ_ASSERT(obj); // We preserve our wrapper, so should always have one here.
   JS::Rooted<JS::Value> val(cx, mResult);
-  JS::ExposeValueToActiveJS(val);
 
   JSAutoCompartment ac(cx, obj);
   if (!JS_WrapValue(cx, &val)) {
     JS_ClearPendingException(cx);
     return;
   }
 
   js::ErrorReport report(cx);
--- a/dom/promise/Promise.h
+++ b/dom/promise/Promise.h
@@ -212,19 +212,16 @@ public:
        // Xrays.
        JS::Handle<JSObject*> aCalleeGlobal,
        AnyCallback* aResolveCallback, AnyCallback* aRejectCallback,
        JS::MutableHandle<JS::Value> aRetval,
        ErrorResult& aRv);
 
   JSObject* PromiseObj() const
   {
-    if (mPromiseObj) {
-      JS::ExposeObjectToActiveJS(mPromiseObj);
-    }
     return mPromiseObj;
   }
 
 #else // SPIDERMONKEY_PROMISE
   JSObject* PromiseObj()
   {
     return GetWrapper();
   }
--- a/dom/promise/PromiseCallback.cpp
+++ b/dom/promise/PromiseCallback.cpp
@@ -76,17 +76,16 @@ ResolvePromiseCallback::~ResolvePromiseC
 }
 
 nsresult
 ResolvePromiseCallback::Call(JSContext* aCx,
                              JS::Handle<JS::Value> aValue)
 {
   // Run resolver's algorithm with value and the synchronous flag set.
 
-  JS::ExposeObjectToActiveJS(mGlobal);
   JS::ExposeValueToActiveJS(aValue);
 
   JSAutoCompartment ac(aCx, mGlobal);
   JS::Rooted<JS::Value> value(aCx, aValue);
   if (!JS_WrapValue(aCx, &value)) {
     NS_WARNING("Failed to wrap value into the right compartment.");
     return NS_ERROR_FAILURE;
   }
@@ -138,17 +137,16 @@ RejectPromiseCallback::~RejectPromiseCal
 }
 
 nsresult
 RejectPromiseCallback::Call(JSContext* aCx,
                             JS::Handle<JS::Value> aValue)
 {
   // Run resolver's algorithm with value and the synchronous flag set.
 
-  JS::ExposeObjectToActiveJS(mGlobal);
   JS::ExposeValueToActiveJS(aValue);
 
   JSAutoCompartment ac(aCx, mGlobal);
   JS::Rooted<JS::Value> value(aCx, aValue);
   if (!JS_WrapValue(aCx, &value)) {
     NS_WARNING("Failed to wrap value into the right compartment.");
     return NS_ERROR_FAILURE;
   }
@@ -205,17 +203,16 @@ InvokePromiseFuncCallback::~InvokePromis
 }
 
 nsresult
 InvokePromiseFuncCallback::Call(JSContext* aCx,
                                 JS::Handle<JS::Value> aValue)
 {
   // Run resolver's algorithm with value and the synchronous flag set.
 
-  JS::ExposeObjectToActiveJS(mGlobal);
   JS::ExposeValueToActiveJS(aValue);
 
   JSAutoCompartment ac(aCx, mGlobal);
   JS::Rooted<JS::Value> value(aCx, aValue);
   if (!JS_WrapValue(aCx, &value)) {
     NS_WARNING("Failed to wrap value into the right compartment.");
     return NS_ERROR_FAILURE;
   }
@@ -307,17 +304,16 @@ WrapperPromiseCallback::~WrapperPromiseC
 {
   DropJSObjects(this);
 }
 
 nsresult
 WrapperPromiseCallback::Call(JSContext* aCx,
                              JS::Handle<JS::Value> aValue)
 {
-  JS::ExposeObjectToActiveJS(mGlobal);
   JS::ExposeValueToActiveJS(aValue);
 
   JSAutoCompartment ac(aCx, mGlobal);
   JS::Rooted<JS::Value> value(aCx, aValue);
   if (!JS_WrapValue(aCx, &value)) {
     NS_WARNING("Failed to wrap value into the right compartment.");
     return NS_ERROR_FAILURE;
   }
--- a/dom/promise/PromiseDebugging.cpp
+++ b/dom/promise/PromiseDebugging.cpp
@@ -185,22 +185,20 @@ PromiseDebugging::GetState(GlobalObject&
     return;
   }
   switch (promise->mState) {
   case Promise::Pending:
     aState.mState = PromiseDebuggingState::Pending;
     break;
   case Promise::Resolved:
     aState.mState = PromiseDebuggingState::Fulfilled;
-    JS::ExposeValueToActiveJS(promise->mResult);
     aState.mValue = promise->mResult;
     break;
   case Promise::Rejected:
     aState.mState = PromiseDebuggingState::Rejected;
-    JS::ExposeValueToActiveJS(promise->mResult);
     aState.mReason = promise->mResult;
     break;
   }
 }
 
 #endif // SPIDERMONKEY_PROMISE
 
 /*static */ nsString
--- a/dom/push/PushSubscriptionOptions.cpp
+++ b/dom/push/PushSubscriptionOptions.cpp
@@ -66,15 +66,14 @@ PushSubscriptionOptions::GetApplicationS
   if (!mRawAppServerKey.IsEmpty() && !mAppServerKey) {
     JS::Rooted<JSObject*> appServerKey(aCx);
     PushUtil::CopyArrayToArrayBuffer(aCx, mRawAppServerKey, &appServerKey, aRv);
     if (aRv.Failed()) {
       return;
     }
     MOZ_ASSERT(appServerKey);
     mAppServerKey = appServerKey;
-    JS::ExposeObjectToActiveJS(mAppServerKey);
   }
   aKey.set(mAppServerKey);
 }
 
 } // namespace dom
 } // namespace mozilla
--- a/dom/vr/VRDisplay.cpp
+++ b/dom/vr/VRDisplay.cpp
@@ -172,17 +172,16 @@ VREyeParameters::GetOffset(JSContext* aC
   if (!mOffset) {
     // Lazily create the Float32Array
     mOffset = dom::Float32Array::Create(aCx, this, 3, mEyeTranslation.components);
     if (!mOffset) {
       aRv.NoteJSContextException(aCx);
       return;
     }
   }
-  JS::ExposeObjectToActiveJS(mOffset);
   aRetval.set(mOffset);
 }
 
 JSObject*
 VREyeParameters::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
 {
   return VREyeParametersBinding::Wrap(aCx, this, aGivenProto);
 }
@@ -239,17 +238,16 @@ VRStageParameters::GetSittingToStandingT
     // Lazily create the Float32Array
     mSittingToStandingTransformArray = dom::Float32Array::Create(aCx, this, 16,
       mSittingToStandingTransform.components);
     if (!mSittingToStandingTransformArray) {
       aRv.NoteJSContextException(aCx);
       return;
     }
   }
-  JS::ExposeObjectToActiveJS(mSittingToStandingTransformArray);
   aRetval.set(mSittingToStandingTransformArray);
 }
 
 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(VRDisplayCapabilities, mParent)
 NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(VRDisplayCapabilities, AddRef)
 NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(VRDisplayCapabilities, Release)
 
 JSObject*
@@ -330,114 +328,96 @@ VRPose::GetPosition(JSContext* aCx,
   if (!mPosition && mVRState.flags & gfx::VRDisplayCapabilityFlags::Cap_Position) {
     // Lazily create the Float32Array
     mPosition = dom::Float32Array::Create(aCx, this, 3, mVRState.position);
     if (!mPosition) {
       aRv.NoteJSContextException(aCx);
       return;
     }
   }
-  if (mPosition) {
-    JS::ExposeObjectToActiveJS(mPosition);
-  }
   aRetval.set(mPosition);
 }
 
 void
 VRPose::GetLinearVelocity(JSContext* aCx,
                           JS::MutableHandle<JSObject*> aRetval,
                           ErrorResult& aRv)
 {
   if (!mLinearVelocity && mVRState.flags & gfx::VRDisplayCapabilityFlags::Cap_Position) {
     // Lazily create the Float32Array
     mLinearVelocity = dom::Float32Array::Create(aCx, this, 3, mVRState.linearVelocity);
     if (!mLinearVelocity) {
       aRv.NoteJSContextException(aCx);
       return;
     }
   }
-  if (mLinearVelocity) {
-    JS::ExposeObjectToActiveJS(mLinearVelocity);
-  }
   aRetval.set(mLinearVelocity);
 }
 
 void
 VRPose::GetLinearAcceleration(JSContext* aCx,
                               JS::MutableHandle<JSObject*> aRetval,
                               ErrorResult& aRv)
 {
   if (!mLinearAcceleration && mVRState.flags & gfx::VRDisplayCapabilityFlags::Cap_LinearAcceleration) {
     // Lazily create the Float32Array
     mLinearAcceleration = dom::Float32Array::Create(aCx, this, 3, mVRState.linearAcceleration);
     if (!mLinearAcceleration) {
       aRv.NoteJSContextException(aCx);
       return;
     }
   }
-  if (mLinearAcceleration) {
-    JS::ExposeObjectToActiveJS(mLinearAcceleration);
-  }
   aRetval.set(mLinearAcceleration);
 }
 
 void
 VRPose::GetOrientation(JSContext* aCx,
                        JS::MutableHandle<JSObject*> aRetval,
                        ErrorResult& aRv)
 {
   if (!mOrientation && mVRState.flags & gfx::VRDisplayCapabilityFlags::Cap_Orientation) {
     // Lazily create the Float32Array
     mOrientation = dom::Float32Array::Create(aCx, this, 4, mVRState.orientation);
     if (!mOrientation) {
       aRv.NoteJSContextException(aCx);
       return;
     }
   }
-  if (mOrientation) {
-    JS::ExposeObjectToActiveJS(mOrientation);
-  }
   aRetval.set(mOrientation);
 }
 
 void
 VRPose::GetAngularVelocity(JSContext* aCx,
                            JS::MutableHandle<JSObject*> aRetval,
                            ErrorResult& aRv)
 {
   if (!mAngularVelocity && mVRState.flags & gfx::VRDisplayCapabilityFlags::Cap_Orientation) {
     // Lazily create the Float32Array
     mAngularVelocity = dom::Float32Array::Create(aCx, this, 3, mVRState.angularVelocity);
     if (!mAngularVelocity) {
       aRv.NoteJSContextException(aCx);
       return;
     }
   }
-  if (mAngularVelocity) {
-    JS::ExposeObjectToActiveJS(mAngularVelocity);
-  }
   aRetval.set(mAngularVelocity);
 }
 
 void
 VRPose::GetAngularAcceleration(JSContext* aCx,
                                JS::MutableHandle<JSObject*> aRetval,
                                ErrorResult& aRv)
 {
   if (!mAngularAcceleration && mVRState.flags & gfx::VRDisplayCapabilityFlags::Cap_AngularAcceleration) {
     // Lazily create the Float32Array
     mAngularAcceleration = dom::Float32Array::Create(aCx, this, 3, mVRState.angularAcceleration);
     if (!mAngularAcceleration) {
       aRv.NoteJSContextException(aCx);
       return;
     }
   }
-  if (mAngularAcceleration) {
-    JS::ExposeObjectToActiveJS(mAngularAcceleration);
-  }
   aRetval.set(mAngularAcceleration);
 }
 
 JSObject*
 VRPose::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
 {
   return VRPoseBinding::Wrap(aCx, this, aGivenProto);
 }
--- a/dom/workers/ServiceWorkerEvents.cpp
+++ b/dom/workers/ServiceWorkerEvents.cpp
@@ -1182,17 +1182,16 @@ ExtendableMessageEvent::~ExtendableMessa
   DropJSObjects(this);
 }
 
 void
 ExtendableMessageEvent::GetData(JSContext* aCx,
                                 JS::MutableHandle<JS::Value> aData,
                                 ErrorResult& aRv)
 {
-  JS::ExposeValueToActiveJS(mData);
   aData.set(mData);
   if (!JS_WrapValue(aCx, aData)) {
     aRv.Throw(NS_ERROR_FAILURE);
   }
 }
 
 void
 ExtendableMessageEvent::GetSource(Nullable<OwningClientOrServiceWorkerOrMessagePort>& aValue) const
--- a/dom/workers/ServiceWorkerMessageEvent.cpp
+++ b/dom/workers/ServiceWorkerMessageEvent.cpp
@@ -64,17 +64,16 @@ ServiceWorkerMessageEvent::WrapObjectInt
   return mozilla::dom::ServiceWorkerMessageEventBinding::Wrap(aCx, this, aGivenProto);
 }
 
 
 void
 ServiceWorkerMessageEvent::GetData(JSContext* aCx, JS::MutableHandle<JS::Value> aData,
                                    ErrorResult& aRv) const
 {
-  JS::ExposeValueToActiveJS(mData);
   aData.set(mData);
   if (!JS_WrapValue(aCx, aData)) {
     aRv.Throw(NS_ERROR_FAILURE);
   }
 }
 
 void
 ServiceWorkerMessageEvent::GetOrigin(nsAString& aOrigin) const
--- a/dom/xhr/XMLHttpRequestMainThread.cpp
+++ b/dom/xhr/XMLHttpRequestMainThread.cpp
@@ -796,17 +796,16 @@ XMLHttpRequestMainThread::GetResponse(JS
 
     if (!mResultArrayBuffer) {
       mResultArrayBuffer = mArrayBufferBuilder.getArrayBuffer(aCx);
       if (!mResultArrayBuffer) {
         aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
         return;
       }
     }
-    JS::ExposeObjectToActiveJS(mResultArrayBuffer);
     aResponse.setObject(*mResultArrayBuffer);
     return;
   }
   case XMLHttpRequestResponseType::Blob:
   case XMLHttpRequestResponseType::Moz_blob:
   {
     if (mState != State::done) {
       if (mResponseType != XMLHttpRequestResponseType::Moz_blob) {
@@ -851,17 +850,16 @@ XMLHttpRequestMainThread::GetResponse(JS
         // Per spec, errors aren't propagated. null is returned instead.
         aRv = NS_OK;
         // It would be nice to log the error to the console. That's hard to
         // do without calling window.onerror as a side effect, though.
         JS_ClearPendingException(aCx);
         mResultJSON.setNull();
       }
     }
-    JS::ExposeValueToActiveJS(mResultJSON);
     aResponse.set(mResultJSON);
     return;
   }
   default:
     NS_ERROR("Should not happen");
   }
 
   aResponse.setNull();
--- a/dom/xhr/XMLHttpRequestWorker.cpp
+++ b/dom/xhr/XMLHttpRequestWorker.cpp
@@ -2408,17 +2408,16 @@ XMLHttpRequestWorker::GetResponse(JSCont
         aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
         return;
       }
 
       mStateData.mResponse.setString(str);
     }
   }
 
-  JS::ExposeValueToActiveJS(mStateData.mResponse);
   aRv = mStateData.mResponseResult;
   aResponse.set(mStateData.mResponse);
 }
 
 void
 XMLHttpRequestWorker::GetResponseText(nsAString& aResponseText, ErrorResult& aRv)
 {
   aRv = mStateData.mResponseTextResult;
--- a/js/public/RootingAPI.h
+++ b/js/public/RootingAPI.h
@@ -251,18 +251,22 @@ class Heap : public js::HeapBase<T>
     ~Heap() {
         post(ptr, GCPolicy<T>::initial());
     }
 
     DECLARE_POINTER_CONSTREF_OPS(T);
     DECLARE_POINTER_ASSIGN_OPS(Heap, T);
 
     const T* address() const { return &ptr; }
+
+    void exposeToActiveJS() const {
+        js::BarrierMethods<T>::exposeToJS(ptr);
+    }
     const T& get() const {
-        js::BarrierMethods<T>::exposeToJS(ptr);
+        exposeToActiveJS();
         return ptr;
     }
     const T& unbarrieredGet() const {
         return ptr;
     }
 
     T* unsafeGet() { return &ptr; }
 
@@ -414,20 +418,22 @@ class TenuredHeap : public js::HeapBase<
     bool hasFlag(uintptr_t flag) const {
         MOZ_ASSERT((flag & ~flagsMask) == 0);
         return (bits & flag) != 0;
     }
 
     T unbarrieredGetPtr() const { return reinterpret_cast<T>(bits & ~flagsMask); }
     uintptr_t getFlags() const { return bits & flagsMask; }
 
+    void exposeToActiveJS() const {
+        js::BarrierMethods<T>::exposeToJS(unbarrieredGetPtr());
+    }
     T getPtr() const {
-        T ptr = unbarrieredGetPtr();
-        js::BarrierMethods<T>::exposeToJS(ptr);
-        return ptr;
+        exposeToActiveJS();
+        return unbarrieredGetPtr();
     }
 
     operator T() const { return getPtr(); }
     T operator->() const { return getPtr(); }
 
     explicit operator bool() const {
         return bool(js::BarrierMethods<T>::asGCThingOrNull(unbarrieredGetPtr()));
     }
--- a/js/xpconnect/src/XPCWrappedJS.cpp
+++ b/js/xpconnect/src/XPCWrappedJS.cpp
@@ -202,19 +202,17 @@ nsXPCWrappedJS::QueryInterface(REFNSIID 
     }
 
     if (!IsValid())
         return NS_ERROR_UNEXPECTED;
 
     if (aIID.Equals(NS_GET_IID(nsIXPConnectWrappedJSUnmarkGray))) {
         *aInstancePtr = nullptr;
 
-        // No need to null check mJSObj because IsValid() call above did
-        // that already.
-        JS::ExposeObjectToActiveJS(mJSObj);
+        mJSObj.exposeToActiveJS();
 
         // Just return some error value since one isn't supposed to use
         // nsIXPConnectWrappedJSUnmarkGray objects for anything.
         return NS_ERROR_FAILURE;
     }
 
     // Always check for this first so that our 'outer' can get this interface
     // from us without recurring into a call to the outer's QI!
@@ -313,19 +311,16 @@ nsXPCWrappedJS::GetWeakReference(nsIWeak
         return mRoot->GetWeakReference(aInstancePtr);
 
     return nsSupportsWeakReference::GetWeakReference(aInstancePtr);
 }
 
 JSObject*
 nsXPCWrappedJS::GetJSObject()
 {
-    if (mJSObj) {
-        JS::ExposeObjectToActiveJS(mJSObj);
-    }
     return mJSObj;
 }
 
 // static
 nsresult
 nsXPCWrappedJS::GetNewOrUsed(JS::HandleObject jsObj,
                              REFNSIID aIID,
                              nsXPCWrappedJS** wrapperResult)
--- a/js/xpconnect/src/xpcprivate.h
+++ b/js/xpconnect/src/xpcprivate.h
@@ -1590,20 +1590,17 @@ public:
 
     XPCWrappedNativeScope*
     GetScope()   const {return mScope;}
 
     XPCJSContext*
     GetContext() const {return mScope->GetContext();}
 
     JSObject*
-    GetJSProtoObject() const {
-        JS::ExposeObjectToActiveJS(mJSProtoObject);
-        return mJSProtoObject;
-    }
+    GetJSProtoObject() const { return mJSProtoObject; }
 
     nsIClassInfo*
     GetClassInfo()     const {return mClassInfo;}
 
     XPCNativeSet*
     GetSet()           const {return mSet;}
 
     XPCNativeScriptableInfo*
--- a/js/xpconnect/wrappers/WrapperFactory.cpp
+++ b/js/xpconnect/wrappers/WrapperFactory.cpp
@@ -58,21 +58,17 @@ WrapperFactory::GetXrayWaiver(HandleObje
     MOZ_ASSERT(obj == UncheckedUnwrap(obj));
     MOZ_ASSERT(!js::IsWindow(obj));
     XPCWrappedNativeScope* scope = ObjectScope(obj);
     MOZ_ASSERT(scope);
 
     if (!scope->mWaiverWrapperMap)
         return nullptr;
 
-    JSObject* xrayWaiver = scope->mWaiverWrapperMap->Find(obj);
-    if (xrayWaiver)
-        JS::ExposeObjectToActiveJS(xrayWaiver);
-
-    return xrayWaiver;
+    return scope->mWaiverWrapperMap->Find(obj);
 }
 
 JSObject*
 WrapperFactory::CreateXrayWaiver(JSContext* cx, HandleObject obj)
 {
     // The caller is required to have already done a lookup.
     // NB: This implictly performs the assertions of GetXrayWaiver.
     MOZ_ASSERT(!GetXrayWaiver(obj));