Bug 850293 - Remove nsScriptObjectHolder; r=mccr8,bholly sr=smaug
authorTerrence Cole <terrence@mozilla.com>
Wed, 20 Mar 2013 13:09:09 -0700
changeset 136085 a0aa85db5d171936feabb3cd48912d2fc31332d0
parent 136084 8052545133904ee1632ccff90bb8d93260fb3d73
child 136086 c87a88a0591d6ee2a75a45d8f581413ce1a01b03
push id2452
push userlsblakk@mozilla.com
push dateMon, 13 May 2013 16:59:38 +0000
treeherdermozilla-beta@d4b152d29d8d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmccr8, bholly, smaug
bugs850293
milestone22.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 850293 - Remove nsScriptObjectHolder; r=mccr8,bholly sr=smaug nsScriptObjectHolder is not needed with either conservative or exact rooting.
content/events/src/nsEventListenerManager.cpp
content/xbl/src/nsXBLPrototypeHandler.cpp
content/xbl/src/nsXBLPrototypeHandler.h
content/xbl/src/nsXBLSerialize.cpp
content/xul/content/src/nsXULElement.cpp
content/xul/content/src/nsXULElement.h
dom/base/Makefile.in
dom/base/nsDOMScriptObjectHolder.h
dom/base/nsGlobalWindow.cpp
dom/base/nsGlobalWindow.h
dom/base/nsIScriptContext.h
dom/base/nsJSEnvironment.cpp
dom/base/nsJSEnvironment.h
dom/base/nsPIDOMWindow.h
dom/src/events/nsJSEventListener.cpp
--- a/content/events/src/nsEventListenerManager.cpp
+++ b/content/events/src/nsEventListenerManager.cpp
@@ -40,17 +40,16 @@
 #include "nsDOMCID.h"
 #include "nsFocusManager.h"
 #include "nsIDOMElement.h"
 #include "nsContentUtils.h"
 #include "nsJSUtils.h"
 #include "nsContentCID.h"
 #include "nsEventDispatcher.h"
 #include "nsDOMJSUtils.h"
-#include "nsDOMScriptObjectHolder.h"
 #include "nsDataHashtable.h"
 #include "nsCOMArray.h"
 #include "nsEventListenerService.h"
 #include "nsIContentSecurityPolicy.h"
 #include "nsJSEnvironment.h"
 #include "xpcpublic.h"
 #include "nsSandboxFlags.h"
 #include "mozilla/dom/time/TimeChangeObserver.h"
@@ -753,17 +752,17 @@ nsEventListenerManager::CompileEventHand
   nsresult result = NS_OK;
 
   nsIJSEventListener *listener = aListenerStruct->GetJSListener();
   NS_ASSERTION(!listener->GetHandler().HasEventHandler(),
                "What is there to compile?");
 
   nsIScriptContext *context = listener->GetEventContext();
   JSContext *cx = context->GetNativeContext();
-  nsScriptObjectHolder<JSObject> handler(context);
+  JS::Rooted<JSObject*> handler(cx);
 
   nsCOMPtr<nsPIDOMWindow> win; // Will end up non-null if mTarget is a window
 
   nsCxPusher pusher;
   if (aNeedsCxPush) {
     pusher.Push(cx);
   }
 
@@ -849,53 +848,53 @@ nsEventListenerManager::CompileEventHand
            .setVersion(SCRIPTVERSION_DEFAULT);
 
     JS::RootedObject rootedNull(cx, nullptr); // See bug 781070.
     JSObject *handlerFun = nullptr;
     result = nsJSUtils::CompileFunction(cx, rootedNull, options,
                                         nsAtomCString(aListenerStruct->mTypeAtom),
                                         argCount, argNames, *body, &handlerFun);
     NS_ENSURE_SUCCESS(result, result);
-    handler.set(handlerFun);
+    handler = handlerFun;
     NS_ENSURE_TRUE(handler, NS_ERROR_FAILURE);
   }
 
   if (handler) {
     // Bind it
-    nsScriptObjectHolder<JSObject> boundHandler(context);
+    JS::Rooted<JSObject*> boundHandler(cx);
     context->BindCompiledEventHandler(mTarget, listener->GetEventScope(),
-                                      handler.get(), boundHandler);
+                                      handler, &boundHandler);
     if (listener->EventName() == nsGkAtoms::onerror && win) {
       bool ok;
       JSAutoRequest ar(cx);
       nsRefPtr<OnErrorEventHandlerNonNull> handlerCallback =
         new OnErrorEventHandlerNonNull(cx, listener->GetEventScope(),
-                                       boundHandler.get(), &ok);
+                                       boundHandler, &ok);
       if (!ok) {
         // JS_WrapObject failed, which means OOM allocating the JSObject.
         return NS_ERROR_OUT_OF_MEMORY;
       }
       listener->SetHandler(handlerCallback);
     } else if (listener->EventName() == nsGkAtoms::onbeforeunload && win) {
       bool ok;
       JSAutoRequest ar(cx);
       nsRefPtr<BeforeUnloadEventHandlerNonNull> handlerCallback =
         new BeforeUnloadEventHandlerNonNull(cx, listener->GetEventScope(),
-                                            boundHandler.get(), &ok);
+                                            boundHandler, &ok);
       if (!ok) {
         // JS_WrapObject failed, which means OOM allocating the JSObject.
         return NS_ERROR_OUT_OF_MEMORY;
       }
       listener->SetHandler(handlerCallback);
     } else {
       bool ok;
       JSAutoRequest ar(cx);
       nsRefPtr<EventHandlerNonNull> handlerCallback =
         new EventHandlerNonNull(cx, listener->GetEventScope(),
-                                boundHandler.get(), &ok);
+                                boundHandler, &ok);
       if (!ok) {
         // JS_WrapObject failed, which means OOM allocating the JSObject.
         return NS_ERROR_OUT_OF_MEMORY;
       }
       listener->SetHandler(handlerCallback);
     }
   }
 
--- a/content/xbl/src/nsXBLPrototypeHandler.cpp
+++ b/content/xbl/src/nsXBLPrototypeHandler.cpp
@@ -267,72 +267,73 @@ nsXBLPrototypeHandler::ExecuteHandler(ns
 
   if (!boundGlobal)
     return NS_OK;
 
   nsIScriptContext *boundContext = boundGlobal->GetScriptContext();
   if (!boundContext)
     return NS_OK;
 
-  nsScriptObjectHolder<JSObject> handler(boundContext);
   nsISupports *scriptTarget;
 
   if (winRoot) {
     scriptTarget = boundGlobal;
   } else {
     scriptTarget = aTarget;
   }
 
   // We're about to create a new nsJSEventListener, which means that we're
   // responsible for pushing the context of the event target. See the similar
   // comment in nsEventManagerListener.cpp.
   nsCxPusher pusher;
   NS_ENSURE_STATE(pusher.Push(aTarget));
 
-  rv = EnsureEventHandler(boundGlobal, boundContext, onEventAtom, handler);
+  AutoPushJSContext cx(boundContext->GetNativeContext());
+  JS::Rooted<JSObject*> handler(cx);
+
+  rv = EnsureEventHandler(boundGlobal, boundContext, onEventAtom, &handler);
   NS_ENSURE_SUCCESS(rv, rv);
 
-  AutoPushJSContext cx(boundContext->GetNativeContext());
   JSAutoRequest ar(cx);
-  JSObject* globalObject = boundGlobal->GetGlobalJSObject();
-  JSObject* scopeObject = xpc::GetXBLScope(cx, globalObject);
+  JS::Rooted<JSObject*> globalObject(cx, boundGlobal->GetGlobalJSObject());
+  JS::Rooted<JSObject*> scopeObject(cx, xpc::GetXBLScope(cx, globalObject));
 
   // Bind it to the bound element. Note that if we're using a separate XBL scope,
   // we'll actually be binding the event handler to a cross-compartment wrapper
   // to the bound element's reflector.
 
   // First, enter our XBL scope. This is where the generic handler should have
   // been compiled, above.
   JSAutoCompartment ac(cx, scopeObject);
-  JSObject* genericHandler = handler.get();
-  bool ok = JS_WrapObject(cx, &genericHandler);
+  JS::Rooted<JSObject*> genericHandler(cx, handler.get());
+  bool ok = JS_WrapObject(cx, genericHandler.address());
   NS_ENSURE_TRUE(ok, NS_ERROR_OUT_OF_MEMORY);
   MOZ_ASSERT(!js::IsCrossCompartmentWrapper(genericHandler));
 
   // Wrap the native into the XBL scope. This creates a reflector in the document
   // scope if one doesn't already exist, and potentially wraps it cross-
   // compartment into our scope (via aAllowWrapping=true).
-  JS::Value targetV = JS::UndefinedValue();
-  rv = nsContentUtils::WrapNative(cx, scopeObject, scriptTarget, &targetV, nullptr,
+  JS::Rooted<JS::Value> targetV(cx, JS::UndefinedValue());
+  rv = nsContentUtils::WrapNative(cx, scopeObject, scriptTarget, targetV.address(), nullptr,
                                   /* aAllowWrapping = */ true);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Next, clone the generic handler to be parented to the target.
-  JSObject* bound = JS_CloneFunctionObject(cx, genericHandler, &targetV.toObject());
+  JS::Rooted<JSObject*> bound(cx, JS_CloneFunctionObject(cx, genericHandler, &targetV.toObject()));
   NS_ENSURE_TRUE(bound, NS_ERROR_FAILURE);
 
   // Now, wrap the bound handler into the content compartment and use it.
   JSAutoCompartment ac2(cx, globalObject);
-  if (!JS_WrapObject(cx, &bound)) {
+  if (!JS_WrapObject(cx, bound.address())) {
     return NS_ERROR_FAILURE;
   }
-  nsScriptObjectHolder<JSObject> boundHandler(boundContext, bound);
+  JS::Rooted<JSObject*> boundHandler(cx, bound);
 
   nsRefPtr<EventHandlerNonNull> handlerCallback =
-    new EventHandlerNonNull(cx, globalObject, boundHandler.get(), &ok);
+    new EventHandlerNonNull(cx, globalObject, boundHandler, &ok);
   if (!ok) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
   nsEventHandler eventHandler(handlerCallback);
 
   // Execute it.
   nsCOMPtr<nsIJSEventListener> eventListener;
@@ -347,37 +348,38 @@ nsXBLPrototypeHandler::ExecuteHandler(ns
   eventListener->Disconnect();
   return NS_OK;
 }
 
 nsresult
 nsXBLPrototypeHandler::EnsureEventHandler(nsIScriptGlobalObject* aGlobal,
                                           nsIScriptContext *aBoundContext,
                                           nsIAtom *aName,
-                                          nsScriptObjectHolder<JSObject>& aHandler)
+                                          JS::MutableHandle<JSObject*> aHandler)
 {
+  AutoPushJSContext cx(aBoundContext->GetNativeContext());
+
   // Check to see if we've already compiled this
   nsCOMPtr<nsPIDOMWindow> pWindow = do_QueryInterface(aGlobal);
   if (pWindow) {
-    JSObject* cachedHandler = pWindow->GetCachedXBLPrototypeHandler(this);
+    JS::Rooted<JSObject*> cachedHandler(cx, pWindow->GetCachedXBLPrototypeHandler(this));
     if (cachedHandler) {
       xpc_UnmarkGrayObject(cachedHandler);
       aHandler.set(cachedHandler);
       NS_ENSURE_TRUE(aHandler, NS_ERROR_FAILURE);
       return NS_OK;
     }
   }
 
   // Ensure that we have something to compile
   nsDependentString handlerText(mHandlerText);
   NS_ENSURE_TRUE(!handlerText.IsEmpty(), NS_ERROR_FAILURE);
 
-  AutoPushJSContext cx(aBoundContext->GetNativeContext());
-  JSObject* globalObject = aGlobal->GetGlobalJSObject();
-  JSObject* scopeObject = xpc::GetXBLScope(cx, globalObject);
+  JS::Rooted<JSObject*> globalObject(cx, aGlobal->GetGlobalJSObject());
+  JS::Rooted<JSObject*> scopeObject(cx, xpc::GetXBLScope(cx, globalObject));
 
   nsAutoCString bindingURI;
   mPrototypeBinding->DocURI()->GetSpec(bindingURI);
 
   uint32_t argCount;
   const char **argNames;
   nsContentUtils::GetEventArgNames(kNameSpaceID_XBL, aName, &argCount,
                                    &argNames);
@@ -385,28 +387,28 @@ nsXBLPrototypeHandler::EnsureEventHandle
   // Compile the event handler in the xbl scope.
   JSAutoRequest ar(cx);
   JSAutoCompartment ac(cx, scopeObject);
   JS::CompileOptions options(cx);
   options.setFileAndLine(bindingURI.get(), mLineNumber)
          .setVersion(JSVERSION_LATEST)
          .setUserBit(true); // Flag us as XBL
 
-  JS::RootedObject rootedNull(cx, nullptr); // See bug 781070.
-  JSObject* handlerFun = nullptr;
+  JS::Rooted<JSObject*> rootedNull(cx); // See bug 781070.
+  JS::Rooted<JSObject*> handlerFun(cx);
   nsresult rv = nsJSUtils::CompileFunction(cx, rootedNull, options,
                                            nsAtomCString(aName), argCount,
-                                           argNames, handlerText, &handlerFun);
+                                           argNames, handlerText, handlerFun.address());
   NS_ENSURE_SUCCESS(rv, rv);
   NS_ENSURE_TRUE(handlerFun, NS_ERROR_FAILURE);
 
   // Wrap the handler into the content scope, since we're about to stash it
   // on the DOM window and such.
   JSAutoCompartment ac2(cx, globalObject);
-  bool ok = JS_WrapObject(cx, &handlerFun);
+  bool ok = JS_WrapObject(cx, handlerFun.address());
   NS_ENSURE_TRUE(ok, NS_ERROR_OUT_OF_MEMORY);
   aHandler.set(handlerFun);
   NS_ENSURE_TRUE(aHandler, NS_ERROR_FAILURE);
 
   if (pWindow) {
     pWindow->CacheXBLPrototypeHandler(this, aHandler);
   }
 
--- a/content/xbl/src/nsXBLPrototypeHandler.h
+++ b/content/xbl/src/nsXBLPrototypeHandler.h
@@ -9,25 +9,29 @@
 #include "nsIAtom.h"
 #include "nsString.h"
 #include "nsCOMPtr.h"
 #include "nsIController.h"
 #include "nsAutoPtr.h"
 #include "nsXBLEventHandler.h"
 #include "nsIWeakReference.h"
 #include "nsIScriptGlobalObject.h"
-#include "nsDOMScriptObjectHolder.h"
 #include "nsCycleCollectionParticipant.h"
 
+#include "js/RootingAPI.h"
+
+class JSObject;
 class nsIDOMEvent;
 class nsIContent;
 class nsIDOMUIEvent;
 class nsIDOMKeyEvent;
 class nsIDOMMouseEvent;
 class nsIDOMEventTarget;
+class nsIObjectInputStream;
+class nsIObjectOutputStream;
 class nsXBLPrototypeBinding;
 
 #define NS_HANDLER_TYPE_XBL_JS              (1 << 0)
 #define NS_HANDLER_TYPE_XBL_COMMAND         (1 << 1)
 #define NS_HANDLER_TYPE_XUL                 (1 << 2)
 #define NS_HANDLER_HAS_ALLOW_UNTRUSTED_ATTR (1 << 4)
 #define NS_HANDLER_ALLOW_UNTRUSTED          (1 << 5)
 #define NS_HANDLER_TYPE_SYSTEM              (1 << 6)
@@ -156,17 +160,17 @@ protected:
   void ReportKeyConflict(const PRUnichar* aKey, const PRUnichar* aModifiers, nsIContent* aElement, const char *aMessageName);
   void GetEventType(nsAString& type);
   bool ModifiersMatchMask(nsIDOMUIEvent* aEvent,
                             bool aIgnoreShiftKey = false);
   nsresult DispatchXBLCommand(nsIDOMEventTarget* aTarget, nsIDOMEvent* aEvent);
   nsresult DispatchXULKeyCommand(nsIDOMEvent* aEvent);
   nsresult EnsureEventHandler(nsIScriptGlobalObject* aGlobal,
                               nsIScriptContext *aBoundContext, nsIAtom *aName,
-                              nsScriptObjectHolder<JSObject>& aHandler);
+                              JS::MutableHandle<JSObject*> aHandler);
   static int32_t KeyToMask(int32_t key);
   
   static int32_t kAccelKey;
   static int32_t kMenuAccessKey;
   static void InitAccessKeys();
 
   static const int32_t cShift;
   static const int32_t cAlt;
--- a/content/xbl/src/nsXBLSerialize.cpp
+++ b/content/xbl/src/nsXBLSerialize.cpp
@@ -1,15 +1,15 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsXBLSerialize.h"
-#include "nsDOMScriptObjectHolder.h"
+#include "nsIXPConnect.h"
 #include "nsContentUtils.h"
 #include "jsdbgapi.h"
 
 using namespace mozilla;
 
 nsresult
 XBL_SerializeFunction(nsIScriptContext* aContext,
                       nsIObjectOutputStream* aStream,
--- a/content/xul/content/src/nsXULElement.cpp
+++ b/content/xul/content/src/nsXULElement.cpp
@@ -2462,18 +2462,18 @@ nsXULPrototypeScript::Deserialize(nsIObj
 
     // Read basic prototype data
     aStream->Read32(&mLineNo);
     aStream->Read32(&mLangVersion);
 
     nsIScriptContext *context = aGlobal->GetScriptContext();
     NS_ASSERTION(context != nullptr, "Have no context for deserialization");
     NS_ENSURE_TRUE(context, NS_ERROR_UNEXPECTED);
-    nsScriptObjectHolder<JSScript> newScriptObject(context);
-    rv = context->Deserialize(aStream, newScriptObject);
+    JS::Rooted<JSScript*> newScriptObject(context->GetNativeContext());
+    rv = context->Deserialize(aStream, &newScriptObject);
     if (NS_FAILED(rv)) {
         NS_WARNING("Language deseralization failed");
         return rv;
     }
     Set(newScriptObject);
     return NS_OK;
 }
 
@@ -2582,17 +2582,17 @@ nsXULPrototypeScript::Compile(const PRUn
             return NS_ERROR_UNEXPECTED;
     }
 
     nsAutoCString urlspec;
     nsContentUtils::GetWrapperSafeScriptFilename(aDocument, aURI, urlspec);
 
     // Ok, compile it to create a prototype script object!
 
-    nsScriptObjectHolder<JSScript> newScriptObject(context);
+    JS::Rooted<JSScript*> newScriptObject(context->GetNativeContext());
 
     // If the script was inline, tell the JS parser to save source for
     // Function.prototype.toSource(). If it's out of line, we retrieve the
     // source from the files on demand.
     bool saveSource = !mOutOfLine;
 
     rv = context->CompileScript(aText,
                                 aTextLength,
@@ -2601,17 +2601,17 @@ nsXULPrototypeScript::Compile(const PRUn
                                 // protodoc's?
                                 // If we start using the protodoc's, make sure
                                 // the DowngradePrincipalIfNeeded stuff in
                                 // nsXULDocument::OnStreamComplete still works!
                                 aDocument->NodePrincipal(),
                                 urlspec.get(),
                                 aLineNo,
                                 mLangVersion,
-                                newScriptObject,
+                                &newScriptObject,
                                 saveSource);
     if (NS_FAILED(rv))
         return rv;
 
     Set(newScriptObject);
     return rv;
 }
 
--- a/content/xul/content/src/nsXULElement.h
+++ b/content/xul/content/src/nsXULElement.h
@@ -29,17 +29,16 @@
 #include "nsIURI.h"
 #include "nsIXULTemplateBuilder.h"
 #include "nsIBoxObject.h"
 #include "nsLayoutCID.h"
 #include "nsAttrAndChildArray.h"
 #include "nsGkAtoms.h"
 #include "nsAutoPtr.h"
 #include "nsStyledElement.h"
-#include "nsDOMScriptObjectHolder.h"
 #include "nsIFrameLoader.h"
 #include "jspubtd.h"
 #include "nsFrameLoader.h"
 
 class nsIDocument;
 class nsString;
 class nsIDocShell;
 
@@ -228,20 +227,16 @@ public:
 
     nsresult Compile(const PRUnichar* aText, int32_t aTextLength,
                      nsIURI* aURI, uint32_t aLineNo,
                      nsIDocument* aDocument,
                      nsIScriptGlobalObjectOwner* aGlobalOwner);
 
     void UnlinkJSObjects();
 
-    void Set(nsScriptObjectHolder<JSScript>& aHolder)
-    {
-        Set(aHolder.get());
-    }
     void Set(JSScript* aObject);
 
     JSScript *GetScriptObject()
     {
         return mScriptObject;
     }
 
     nsCOMPtr<nsIURI>         mSrcURI;
--- a/dom/base/Makefile.in
+++ b/dom/base/Makefile.in
@@ -32,17 +32,16 @@ EXTRA_JS_MODULES += \
   ObjectWrapper.jsm \
   $(NULL)
 
 EXPORTS = \
   nsDOMCID.h \
   nsDOMClassInfoClasses.h \
   nsDOMClassInfoID.h \
   nsDOMJSUtils.h \
-  nsDOMScriptObjectHolder.h \
   nsDOMString.h \
   nsIDOMClassInfo.h \
   nsIDOMScriptObjectFactory.h \
   nsIJSEventListener.h \
   nsIJSNativeInitializer.h \
   nsIScriptContext.h	\
   nsIScriptExternalNameSet.h \
   nsIScriptGlobalObject.h \
deleted file mode 100644
--- a/dom/base/nsDOMScriptObjectHolder.h
+++ /dev/null
@@ -1,93 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef nsDOMScriptObjectHolder_h__
-#define nsDOMScriptObjectHolder_h__
-
-#include "nsIScriptContext.h"
-#include "nsIDOMScriptObjectFactory.h"
-
-#include "jspubtd.h"
-
-// A thin class used to help with script object memory management.  No virtual
-// functions and a fully inline implementation should keep the cost down.
-// [Note that a fully inline implementation is necessary for use by other
-// languages, which do not link against the layout component module]
-template<class T>
-class NS_STACK_CLASS nsScriptObjectHolder {
-public:
-  // A constructor that will cause a reference to |ctx| to be stored in
-  // the object.  Only use for short-lived object holders.
-  nsScriptObjectHolder<T>(nsIScriptContext *ctx, T* aObject = nullptr) :
-      mObject(aObject), mContext(ctx) {
-    NS_ASSERTION(ctx, "Must provide a valid context");
-  }
-
-  // copy constructor
-  nsScriptObjectHolder<T>(const nsScriptObjectHolder<T>& other) :
-      mObject(other.mObject),
-      mContext(other.mContext)
-  {
-    // New hold the script object and new reference on the script context.
-    if (mObject)
-      mContext->HoldScriptObject(mObject);
-  }
-
-  ~nsScriptObjectHolder<T>() {
-    if (mObject)
-      mContext->DropScriptObject(mObject);
-  }
-
-  // misc operators
-  nsScriptObjectHolder<T> &operator=(const nsScriptObjectHolder<T> &other) {
-    set(other);
-    return *this;
-  }
-  bool operator!() const {
-    return !mObject;
-  }
-  operator bool() const {
-    return !!mObject;
-  }
-  T* get() const {
-    return mObject;
-  }
-
-  // Drop the script object - but *not* the nsIScriptContext.
-  nsresult drop() {
-    nsresult rv = NS_OK;
-    if (mObject) {
-      rv = mContext->DropScriptObject(mObject);
-      mObject = nullptr;
-    }
-    return rv;
-  }
-
-  nsresult set(T* object) {
-    nsresult rv = drop();
-    if (NS_FAILED(rv))
-      return rv;
-    if (object) {
-      rv = mContext->HoldScriptObject(object);
-      // don't store the pointer if we failed to lock it.
-      if (NS_SUCCEEDED(rv)) {
-        mObject = object;
-      }
-    }
-    return rv;
-  }
-  nsresult set(const nsScriptObjectHolder<T> &other) {
-    nsresult rv = drop();
-    if (NS_FAILED(rv))
-      return rv;
-    return set(other.mObject);
-  }
-
-protected:
-  T* mObject;
-  nsCOMPtr<nsIScriptContext> mContext;
-};
-
-#endif // nsDOMScriptObjectHolder_h__
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -7298,17 +7298,17 @@ nsGlobalWindow::GetCachedXBLPrototypeHan
   if (mCachedXBLPrototypeHandlers.IsInitialized()) {
     mCachedXBLPrototypeHandlers.Get(aKey, &handler);
   }
   return handler;
 }
 
 void
 nsGlobalWindow::CacheXBLPrototypeHandler(nsXBLPrototypeHandler* aKey,
-                                         nsScriptObjectHolder<JSObject>& aHandler)
+                                         JS::Handle<JSObject*> aHandler)
 {
   if (!mCachedXBLPrototypeHandlers.IsInitialized()) {
     mCachedXBLPrototypeHandlers.Init();
   }
 
   if (!mCachedXBLPrototypeHandlers.Count()) {
     // Can't use macros to get the participant because nsGlobalChromeWindow also
     // runs through this code. Use QueryInterface to get the correct objects.
@@ -7320,17 +7320,17 @@ nsGlobalWindow::CacheXBLPrototypeHandler
     nsISupports* thisSupports;
     QueryInterface(NS_GET_IID(nsCycleCollectionISupports),
                    reinterpret_cast<void**>(&thisSupports));
     NS_ASSERTION(thisSupports, "Failed to QI to nsCycleCollectionISupports!");
 
     nsContentUtils::HoldJSObjects(thisSupports, participant);
   }
 
-  mCachedXBLPrototypeHandlers.Put(aKey, aHandler.get());
+  mCachedXBLPrototypeHandlers.Put(aKey, aHandler);
 }
 
 /**
  * GetScriptableFrameElement is called when script reads
  * nsIGlobalWindow::frameElement.
  *
  * In contrast to GetRealFrameElement, GetScriptableFrameElement says that the
  * window contained by an <iframe mozbrowser> or <iframe mozapp> has no frame
--- a/dom/base/nsGlobalWindow.h
+++ b/dom/base/nsGlobalWindow.h
@@ -11,17 +11,16 @@
 
 // Local Includes
 // Helper Classes
 #include "nsCOMPtr.h"
 #include "nsAutoPtr.h"
 #include "nsWeakReference.h"
 #include "nsDataHashtable.h"
 #include "nsCycleCollectionParticipant.h"
-#include "nsDOMScriptObjectHolder.h"
 
 // Interfaces Needed
 #include "nsDOMWindowList.h"
 #include "nsIBaseWindow.h"
 #include "nsIBrowserDOMWindow.h"
 #include "nsIDocShellTreeOwner.h"
 #include "nsIDocShellTreeItem.h"
 #include "nsIDOMEventTarget.h"
@@ -527,17 +526,17 @@ public:
   NS_DECL_CYCLE_COLLECTION_SKIPPABLE_SCRIPT_HOLDER_CLASS_AMBIGUOUS(nsGlobalWindow,
                                                                    nsIDOMEventTarget)
 
   virtual NS_HIDDEN_(JSObject*)
     GetCachedXBLPrototypeHandler(nsXBLPrototypeHandler* aKey);
 
   virtual NS_HIDDEN_(void)
     CacheXBLPrototypeHandler(nsXBLPrototypeHandler* aKey,
-                             nsScriptObjectHolder<JSObject>& aHandler);
+                             JS::Handle<JSObject*> aHandler);
 
   virtual bool TakeFocus(bool aFocus, uint32_t aFocusMethod);
   virtual void SetReadyForFocus();
   virtual void PageHidden();
   virtual nsresult DispatchAsyncHashchange(nsIURI *aOldURI, nsIURI *aNewURI);
   virtual nsresult DispatchSyncPopState();
 
   virtual void EnableDeviceSensor(uint32_t aType);
--- a/dom/base/nsIScriptContext.h
+++ b/dom/base/nsIScriptContext.h
@@ -18,17 +18,16 @@
 class nsIScriptGlobalObject;
 class nsIScriptSecurityManager;
 class nsIPrincipal;
 class nsIAtom;
 class nsIArray;
 class nsIVariant;
 class nsIObjectInputStream;
 class nsIObjectOutputStream;
-template<class> class nsScriptObjectHolder;
 class nsIScriptObjectPrincipal;
 class nsIDOMWindow;
 class nsIURI;
 
 typedef void (*nsScriptTerminationFunc)(nsISupports* aRef);
 
 #define NS_ISCRIPTCONTEXTPRINCIPAL_IID \
   { 0xd012cdb3, 0x8f1e, 0x4440, \
@@ -41,18 +40,18 @@ public:
 
   virtual nsIScriptObjectPrincipal* GetObjectPrincipal() = 0;
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsIScriptContextPrincipal,
                               NS_ISCRIPTCONTEXTPRINCIPAL_IID)
 
 #define NS_ISCRIPTCONTEXT_IID \
-{ 0xa2210341, 0x3123, 0x4477, \
-    { 0xb5, 0xa9, 0x91, 0x95, 0xbd, 0x77, 0xb1, 0xe6 } }
+{ 0xf5af1c3c, 0xebad, 0x4d00, \
+  { 0xa2, 0xa4, 0x12, 0x2e, 0x27, 0x16, 0x59, 0x01 } }
 
 /* This MUST match JSVERSION_DEFAULT.  This version stuff if we don't
    know what language we have is a little silly... */
 #define SCRIPTVERSION_DEFAULT JSVERSION_DEFAULT
 
 /**
  * It is used by the application to initialize a runtime and run scripts.
  * A script runtime would implement this interface.
@@ -99,17 +98,17 @@ public:
    *
    **/
   virtual nsresult CompileScript(const PRUnichar* aText,
                                  int32_t aTextLength,
                                  nsIPrincipal* aPrincipal,
                                  const char* aURL,
                                  uint32_t aLineNo,
                                  uint32_t aVersion,
-                                 nsScriptObjectHolder<JSScript>& aScriptObject,
+                                 JS::MutableHandle<JSScript*> aScriptObject,
                                  bool aSaveSource = false) = 0;
 
   /**
    * Execute a precompiled script object.
    *
    * @param aScriptObject an object representing the script to be executed
    * @param aScopeObject an object telling the scope in which to execute,
    *                     or nullptr to use a default scope
@@ -159,17 +158,17 @@ public:
    * @param aHandler the function object to bind, created by an earlier call to
    *        CompileEventHandler
    * @param aBoundHandler [out] the result of the bind operation.
    * @return NS_OK if the function was successfully bound
    */
   virtual nsresult BindCompiledEventHandler(nsISupports* aTarget,
                                             JSObject* aScope,
                                             JSObject* aHandler,
-                                            nsScriptObjectHolder<JSObject>& aBoundHandler) = 0;
+                                            JS::MutableHandle<JSObject*> aBoundHandler) = 0;
 
   /**
    * Return the global object.
    *
    **/
   virtual nsIScriptGlobalObject *GetGlobalObject() = 0;
 
   /**
@@ -221,17 +220,17 @@ public:
   virtual void ScriptEvaluated(bool aTerminated) = 0;
 
   virtual nsresult Serialize(nsIObjectOutputStream* aStream,
                              JSScript* aScriptObject) = 0;
   
   /* Deserialize a script from a stream.
    */
   virtual nsresult Deserialize(nsIObjectInputStream* aStream,
-                               nsScriptObjectHolder<JSScript>& aResult) = 0;
+                               JS::MutableHandle<JSScript*> aResult) = 0;
 
   /**
    * JS only - this function need not be implemented by languages other
    * than JS (ie, this should be moved to a private interface!)
    * Called to specify a function that should be called when the current
    * script (if there is one) terminates. Generally used if breakdown
    * of script state needs to happen, but should be deferred till
    * the end of script evaluation.
@@ -280,17 +279,16 @@ public:
    */
   virtual void DidInitializeContext() = 0;
 
   /* Memory managment for script objects.  Used by the implementation of
    * nsScriptObjectHolder to manage the lifetimes of the held script objects.
    *
    * See also nsIScriptRuntime, which has identical methods and is useful
    * in situations when you do not have an nsIScriptContext.
-   * 
    */
   virtual nsresult DropScriptObject(void *object) = 0;
   virtual nsresult HoldScriptObject(void *object) = 0;
 
   virtual void EnterModalState() = 0;
   virtual void LeaveModalState() = 0;
 };
 
--- a/dom/base/nsJSEnvironment.cpp
+++ b/dom/base/nsJSEnvironment.cpp
@@ -43,17 +43,16 @@
 
 #include "xpcpublic.h"
 
 #include "jsdbgapi.h"           // for JS_ClearWatchPointsForObject
 #include "jswrapper.h"
 #include "nsIArray.h"
 #include "nsIObjectInputStream.h"
 #include "nsIObjectOutputStream.h"
-#include "nsDOMScriptObjectHolder.h"
 #include "prmem.h"
 #include "WrapperFactory.h"
 #include "nsGlobalWindow.h"
 #include "nsScriptNameSpaceManager.h"
 #include "StructuredCloneTags.h"
 #include "mozilla/dom/ImageData.h"
 #include "mozilla/dom/ImageDataBinding.h"
 
@@ -1333,17 +1332,17 @@ nsJSContext::GetObjectPrincipal()
 
 nsresult
 nsJSContext::CompileScript(const PRUnichar* aText,
                            int32_t aTextLength,
                            nsIPrincipal *aPrincipal,
                            const char *aURL,
                            uint32_t aLineNo,
                            uint32_t aVersion,
-                           nsScriptObjectHolder<JSScript>& aScriptObject,
+                           JS::MutableHandle<JSScript*> aScriptObject,
                            bool aSaveSource /* = false */)
 {
   SAMPLE_LABEL_PRINTF("JS", "Compile Script", "%s", aURL ? aURL : "");
   NS_ENSURE_TRUE(mIsInitialized, NS_ERROR_NOT_INITIALIZED);
 
   NS_ENSURE_ARG_POINTER(aPrincipal);
 
   JSObject* scopeObject = ::JS_GetGlobalObject(mContext);
@@ -1351,24 +1350,24 @@ nsJSContext::CompileScript(const PRUnich
 
   bool ok = false;
 
   nsresult rv = sSecurityManager->CanExecuteScripts(mContext, aPrincipal, &ok);
   if (NS_FAILED(rv)) {
     return NS_ERROR_FAILURE;
   }
 
-  aScriptObject.drop(); // ensure old object not used on failure...
+  aScriptObject.set(nullptr); // ensure old object not used on failure...
 
   // Don't compile if SecurityManager said "not ok" or aVersion is unknown.
   // Since the caller is responsible for parsing the version strings, we just
   // check it isn't JSVERSION_UNKNOWN.
   if (!ok || JSVersion(aVersion) == JSVERSION_UNKNOWN)
     return NS_OK;
-    
+
   XPCAutoRequest ar(mContext);
 
 
   JS::CompileOptions options(mContext);
   JS::CompileOptions::SourcePolicy sp = aSaveSource ?
     JS::CompileOptions::SAVE_SOURCE :
     JS::CompileOptions::LAZY_SOURCE;
   options.setPrincipals(nsJSPrincipals::get(aPrincipal))
@@ -1379,17 +1378,18 @@ nsJSContext::CompileScript(const PRUnich
   JSScript* script = JS::Compile(mContext,
                                  rootedScope,
                                  options,
                                  static_cast<const jschar*>(aText),
                                  aTextLength);
   if (!script) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
-  return aScriptObject.set(script);
+  aScriptObject.set(script);
+  return NS_OK;
 }
 
 nsresult
 nsJSContext::ExecuteScript(JSScript* aScriptObject,
                            JSObject* aScopeObject)
 {
   NS_ENSURE_TRUE(mIsInitialized, NS_ERROR_NOT_INITIALIZED);
 
@@ -1589,17 +1589,17 @@ nsJSContext::CallEventHandler(nsISupport
   ScriptEvaluated(true);
 
   return rv;
 }
 
 nsresult
 nsJSContext::BindCompiledEventHandler(nsISupports* aTarget, JSObject* aScope,
                                       JSObject* aHandler,
-                                      nsScriptObjectHolder<JSObject>& aBoundHandler)
+                                      JS::MutableHandle<JSObject*> aBoundHandler)
 {
   NS_ENSURE_ARG(aHandler);
   NS_ENSURE_TRUE(mIsInitialized, NS_ERROR_NOT_INITIALIZED);
   NS_PRECONDITION(!aBoundHandler, "Shouldn't already have a bound handler!");
 
   xpc_UnmarkGrayObject(aScope);
   xpc_UnmarkGrayObject(aHandler);
 
@@ -1645,23 +1645,24 @@ nsJSContext::Serialize(nsIObjectOutputSt
     return NS_ERROR_FAILURE;
 
   return nsContentUtils::XPConnect()->WriteScript(aStream, mContext,
                                                   xpc_UnmarkGrayScript(aScriptObject));
 }
 
 nsresult
 nsJSContext::Deserialize(nsIObjectInputStream* aStream,
-                         nsScriptObjectHolder<JSScript>& aResult)
+                         JS::MutableHandle<JSScript*> aResult)
 {
   JSScript *script;
   nsresult rv = nsContentUtils::XPConnect()->ReadScript(aStream, mContext, &script);
   if (NS_FAILED(rv)) return rv;
-    
-  return aResult.set(script);
+
+  aResult.set(script);
+  return NS_OK;
 }
 
 nsIScriptGlobalObject *
 nsJSContext::GetGlobalObject()
 {
   JSObject *global = ::JS_GetGlobalObject(mContext);
 
   if (!global) {
--- a/dom/base/nsJSEnvironment.h
+++ b/dom/base/nsJSEnvironment.h
@@ -51,28 +51,28 @@ public:
                                   JS::Value* aRetValue);
 
   virtual nsresult CompileScript(const PRUnichar* aText,
                                  int32_t aTextLength,
                                  nsIPrincipal *principal,
                                  const char *aURL,
                                  uint32_t aLineNo,
                                  uint32_t aVersion,
-                                 nsScriptObjectHolder<JSScript>& aScriptObject,
+                                 JS::MutableHandle<JSScript*> aScriptObject,
                                  bool aSaveSource = false);
   virtual nsresult ExecuteScript(JSScript* aScriptObject,
                                  JSObject* aScopeObject);
 
   virtual nsresult CallEventHandler(nsISupports* aTarget, JSObject* aScope,
                                     JSObject* aHandler,
                                     nsIArray *argv, nsIVariant **rv);
   virtual nsresult BindCompiledEventHandler(nsISupports *aTarget,
                                             JSObject *aScope,
                                             JSObject* aHandler,
-                                            nsScriptObjectHolder<JSObject>& aBoundHandler);
+                                            JS::MutableHandle<JSObject*> aBoundHandler);
 
   virtual nsIScriptGlobalObject *GetGlobalObject();
   inline nsIScriptGlobalObject *GetGlobalObjectRef() { return mGlobalObjectRef; }
 
   virtual JSContext* GetNativeContext();
   virtual JSObject* GetNativeGlobal();
   virtual nsresult InitContext();
   virtual bool IsContextInitialized();
@@ -92,17 +92,17 @@ public:
 
   virtual nsresult InitClasses(JSObject* aGlobalObj);
 
   virtual void WillInitializeContext();
   virtual void DidInitializeContext();
 
   virtual nsresult Serialize(nsIObjectOutputStream* aStream, JSScript* aScriptObject);
   virtual nsresult Deserialize(nsIObjectInputStream* aStream,
-                               nsScriptObjectHolder<JSScript>& aResult);
+                               JS::MutableHandle<JSScript*> aResult);
 
   virtual nsresult DropScriptObject(void *object);
   virtual nsresult HoldScriptObject(void *object);
 
   virtual void EnterModalState();
   virtual void LeaveModalState();
 
   NS_DECL_NSIXPCSCRIPTNOTIFY
--- a/dom/base/nsPIDOMWindow.h
+++ b/dom/base/nsPIDOMWindow.h
@@ -15,16 +15,18 @@
 #include "nsIDOMElement.h"
 #include "nsIDOMEventTarget.h"
 #include "nsIDOMDocument.h"
 #include "nsCOMPtr.h"
 #include "nsAutoPtr.h"
 #include "nsTArray.h"
 #include "nsIURI.h"
 
+#include "js/RootingAPI.h"
+
 #define DOM_WINDOW_DESTROYED_TOPIC "dom-window-destroyed"
 #define DOM_WINDOW_FROZEN_TOPIC "dom-window-frozen"
 #define DOM_WINDOW_THAWED_TOPIC "dom-window-thawed"
 
 class nsIIdleObserver;
 class nsIPrincipal;
 class nsPerformance;
 
@@ -40,30 +42,29 @@ enum PopupControlState {
   openOverridden    // disallow window open
 };
 
 class nsIDocShell;
 class nsIContent;
 class nsIDocument;
 class nsIScriptTimeoutHandler;
 struct nsTimeout;
-template <class> class nsScriptObjectHolder;
 class nsXBLPrototypeHandler;
 class nsIArray;
 class nsPIWindowRoot;
 
 namespace mozilla {
 namespace dom {
 class AudioContext;
 }
 }
 
 #define NS_PIDOMWINDOW_IID \
-{0xf30405c2, 0x5da8, 0x4339, \
-  {0x87, 0xe2, 0xfa, 0xb2, 0x51, 0x26, 0x8a, 0xe8}}
+{ 0x287be48c, 0x3a7a, 0x48ce, \
+  { 0x80, 0x0f, 0x05, 0x39, 0x52, 0x08, 0x2e, 0xe7 } }
 
 class nsPIDOMWindow : public nsIDOMWindowInternal
 {
 public:
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_PIDOMWINDOW_IID)
 
   virtual nsPIDOMWindow* GetPrivateRoot() = 0;
 
@@ -488,17 +489,17 @@ public:
    */
   void SetHasMouseEnterLeaveEventListeners()
   {
     mMayHaveMouseEnterLeaveEventListener = true;
   }
 
   virtual JSObject* GetCachedXBLPrototypeHandler(nsXBLPrototypeHandler* aKey) = 0;
   virtual void CacheXBLPrototypeHandler(nsXBLPrototypeHandler* aKey,
-                                        nsScriptObjectHolder<JSObject>& aHandler) = 0;
+                                        JS::Handle<JSObject*> aHandler) = 0;
 
   /*
    * Get and set the currently focused element within the document. If
    * aNeedsFocus is true, then set mNeedsFocus to true to indicate that a
    * document focus event is needed.
    *
    * DO NOT CALL EITHER OF THESE METHODS DIRECTLY. USE THE FOCUS MANAGER
    * INSTEAD.
--- a/dom/src/events/nsJSEventListener.cpp
+++ b/dom/src/events/nsJSEventListener.cpp
@@ -8,17 +8,16 @@
 #include "nsIServiceManager.h"
 #include "nsIScriptSecurityManager.h"
 #include "nsIScriptContext.h"
 #include "nsIScriptGlobalObject.h"
 #include "nsIScriptRuntime.h"
 #include "nsIXPConnect.h"
 #include "nsGUIEvent.h"
 #include "nsContentUtils.h"
-#include "nsDOMScriptObjectHolder.h"
 #include "nsIMutableArray.h"
 #include "nsVariant.h"
 #include "nsIDOMBeforeUnloadEvent.h"
 #include "nsGkAtoms.h"
 #include "nsIDOMEventTarget.h"
 #include "nsIJSContextStack.h"
 #include "xpcpublic.h"
 #include "nsJSEnvironment.h"