Bug 1297558 - Remove explicit calls to Expose*ToActiveJS r=mccr8
authorJon Coppeard <jcoppeard@mozilla.com>
Tue, 18 Oct 2016 17:58:19 +0100
changeset 318400 1538850bba0fa58be8bddea4670e9f1c2f88f8f0
parent 318399 dac69b2b8d26fff4e56703c494889e64b464b088
child 318401 b89b2c0f03deb04d76809a5bbfdb74dc19d54176
push id82919
push userjcoppeard@mozilla.com
push dateTue, 18 Oct 2016 17:04:29 +0000
treeherdermozilla-inbound@b89b2c0f03de [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmccr8
bugs1297558
milestone52.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 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));