Bug 1107639 - Replace nsAutoJSValHolder with use of PersistentRooted r=bent
authorJon Coppeard <jcoppeard@mozilla.com>
Fri, 23 Jan 2015 10:23:57 +0000
changeset 252473 de33f69c43fb5a0e9d532e98fccdd5e3ebcaa4fd
parent 252472 852a970ae0d29218bb5e92ee1d0110a7a06f1aa0
child 252474 b60af7b7317cf2004a0b4c86e634e5dec6961a2d
push id4610
push userjlund@mozilla.com
push dateMon, 30 Mar 2015 18:32:55 +0000
treeherdermozilla-beta@4df54044d9ef [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbent
bugs1107639
milestone38.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 1107639 - Replace nsAutoJSValHolder with use of PersistentRooted r=bent
ipc/testshell/TestShellParent.cpp
ipc/testshell/TestShellParent.h
ipc/testshell/XPCShellEnvironment.cpp
ipc/testshell/XPCShellEnvironment.h
js/xpconnect/public/moz.build
js/xpconnect/public/nsAutoJSValHolder.h
js/xpconnect/src/xpcprivate.h
--- a/ipc/testshell/TestShellParent.cpp
+++ b/ipc/testshell/TestShellParent.cpp
@@ -49,33 +49,35 @@ TestShellParent::CommandDone(TestShellCo
 
   return true;
 }
 
 bool
 TestShellCommandParent::SetCallback(JSContext* aCx,
                                     JS::Value aCallback)
 {
-  if (!mCallback.Hold(aCx)) {
-    return false;
+  if (!mCallback.initialized()) {
+    mCallback.init(aCx, aCallback);
+    return true;
   }
 
   mCallback = aCallback;
 
   return true;
 }
 
 bool
 TestShellCommandParent::RunCallback(const nsString& aResponse)
 {
-  NS_ENSURE_TRUE(mCallback.ToJSObject(), false);
+  NS_ENSURE_TRUE(mCallback.isObject(), false);
 
   // We're about to run script via JS_CallFunctionValue, so we need an
   // AutoEntryScript. This is just for testing and not in any spec.
-  dom::AutoEntryScript aes(xpc::NativeGlobal(js::GetGlobalForObjectCrossCompartment(mCallback.ToJSObject())));
+  dom::AutoEntryScript aes(
+      xpc::NativeGlobal(js::GetGlobalForObjectCrossCompartment(&mCallback.toObject())));
   JSContext* cx = aes.cx();
   JS::Rooted<JSObject*> global(cx, JS::CurrentGlobalOrNull(cx));
 
   JSString* str = JS_NewUCStringCopyN(cx, aResponse.get(), aResponse.Length());
   NS_ENSURE_TRUE(str, false);
 
   JS::Rooted<JS::Value> strVal(cx, JS::StringValue(str));
 
@@ -85,17 +87,17 @@ TestShellCommandParent::RunCallback(cons
   NS_ENSURE_TRUE(ok, false);
 
   return true;
 }
 
 void
 TestShellCommandParent::ReleaseCallback()
 {
-  mCallback.Release();
+  mCallback.reset();
 }
 
 bool
 TestShellCommandParent::ExecuteCallback(const nsString& aResponse)
 {
   return static_cast<TestShellParent*>(Manager())->CommandDone(
       this, aResponse);
 }
--- a/ipc/testshell/TestShellParent.h
+++ b/ipc/testshell/TestShellParent.h
@@ -7,17 +7,17 @@
 
 #ifndef ipc_testshell_TestShellParent_h
 #define ipc_testshell_TestShellParent_h 1
 
 #include "mozilla/ipc/PTestShellParent.h"
 #include "mozilla/ipc/PTestShellCommandParent.h"
 
 #include "js/TypeDecls.h"
-#include "nsAutoJSValHolder.h"
+#include "js/RootingAPI.h"
 #include "nsString.h"
 
 namespace mozilla {
 
 namespace ipc {
 
 class TestShellCommandParent;
 
@@ -53,16 +53,16 @@ protected:
 
   void ActorDestroy(ActorDestroyReason why);
 
   bool Recv__delete__(const nsString& aResponse) {
     return ExecuteCallback(aResponse);
   }
 
 private:
-  nsAutoJSValHolder mCallback;
+  JS::PersistentRooted<JS::Value> mCallback;
 };
 
 
 } /* namespace ipc */
 } /* namespace mozilla */
 
 #endif /* ipc_testshell_TestShellParent_h */
--- a/ipc/testshell/XPCShellEnvironment.cpp
+++ b/ipc/testshell/XPCShellEnvironment.cpp
@@ -464,17 +464,17 @@ XPCShellEnvironment::~XPCShellEnvironmen
 
     AutoSafeJSContext cx;
     Rooted<JSObject*> global(cx, GetGlobalObject());
     if (global) {
         {
             JSAutoCompartment ac(cx, global);
             JS_SetAllNonReservedSlotsToUndefined(cx, global);
         }
-        mGlobalHolder.Release();
+        mGlobalHolder.reset();
 
         JSRuntime *rt = JS_GetRuntime(cx);
         JS_GC(rt);
     }
 }
 
 bool
 XPCShellEnvironment::Init()
@@ -493,20 +493,17 @@ XPCShellEnvironment::Init()
     }
 
     JSRuntime *rt;
     if (NS_FAILED(rtsvc->GetRuntime(&rt)) || !rt) {
         NS_ERROR("failed to get JSRuntime from nsJSRuntimeService!");
         return false;
     }
 
-    if (!mGlobalHolder.Hold(rt)) {
-        NS_ERROR("Can't protect global object!");
-        return false;
-    }
+    mGlobalHolder.init(rt);
 
     AutoSafeJSContext cx;
 
     JS_SetContextPrivate(cx, this);
 
     nsCOMPtr<nsIXPConnect> xpc =
       do_GetService(nsIXPConnect::GetCID());
     if (!xpc) {
--- a/ipc/testshell/XPCShellEnvironment.h
+++ b/ipc/testshell/XPCShellEnvironment.h
@@ -5,22 +5,22 @@
 #ifndef _IPC_TESTSHELL_XPCSHELLENVIRONMENT_H_
 #define _IPC_TESTSHELL_XPCSHELLENVIRONMENT_H_
 
 #include "base/basictypes.h"
 
 #include <string>
 #include <stdio.h>
 
-#include "nsAutoJSValHolder.h"
 #include "nsCOMPtr.h"
 #include "nsDebug.h"
 #include "nsString.h"
 #include "nsJSPrincipals.h"
 #include "nsContentUtils.h"
+#include "js/RootingAPI.h"
 #include "js/TypeDecls.h"
 
 struct JSPrincipals;
 
 namespace mozilla {
 namespace ipc {
 
 class XPCShellEnvironment
@@ -34,32 +34,32 @@ public:
     bool EvaluateString(const nsString& aString,
                         nsString* aResult = nullptr);
 
     JSPrincipals* GetPrincipal() {
         return nsJSPrincipals::get(nsContentUtils::GetSystemPrincipal());
     }
 
     JSObject* GetGlobalObject() {
-        return mGlobalHolder.ToJSObject();
+        return mGlobalHolder;
     }
 
     void SetIsQuitting() {
         mQuitting = true;
     }
     bool IsQuitting() {
         return mQuitting;
     }
 
 protected:
     XPCShellEnvironment();
     bool Init();
 
 private:
-    nsAutoJSValHolder mGlobalHolder;
+    JS::PersistentRooted<JSObject *> mGlobalHolder;
 
     bool mQuitting;
 };
 
 } /* namespace ipc */
 } /* namespace mozilla */
 
 #endif /* _IPC_TESTSHELL_XPCSHELLENVIRONMENT_H_ */
--- a/js/xpconnect/public/moz.build
+++ b/js/xpconnect/public/moz.build
@@ -1,14 +1,13 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
 EXPORTS += [
-    'nsAutoJSValHolder.h',
     'nsAXPCNativeCallContext.h',
     'nsTArrayHelpers.h',
     'SandboxPrivate.h',
     'xpc_map_end.h',
 ]
 
deleted file mode 100644
--- a/js/xpconnect/public/nsAutoJSValHolder.h
+++ /dev/null
@@ -1,133 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* 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 __NSAUTOJSVALHOLDER_H__
-#define __NSAUTOJSVALHOLDER_H__
-
-#include "nsDebug.h"
-#include "jsapi.h"
-
-/**
- * Simple class that looks and acts like a JS::Value except that it unroots
- * itself automatically if Root() is ever called. Designed to be rooted on the
- * context or runtime (but not both!).
- */
-class nsAutoJSValHolder
-{
-public:
-  nsAutoJSValHolder()
-    : mVal(JSVAL_NULL), mRt(nullptr)
-  {
-    // nothing to do
-  }
-
-  /**
-   * Always release on destruction.
-   */
-  virtual ~nsAutoJSValHolder() {
-    Release();
-  }
-
-  nsAutoJSValHolder(const nsAutoJSValHolder& aOther)
-    : mVal(JSVAL_NULL), mRt(nullptr)
-  {
-    *this = aOther;
-  }
-
-  nsAutoJSValHolder& operator=(const nsAutoJSValHolder& aOther) {
-    if (this != &aOther) {
-      if (aOther.IsHeld()) {
-        // XXX No error handling here...
-        this->Hold(aOther.mRt);
-      }
-      else {
-        this->Release();
-      }
-      *this = static_cast<JS::Value>(aOther);
-    }
-    return *this;
-  }
-
-  /**
-   * Hold by rooting on the context's runtime.
-   */
-  bool Hold(JSContext* aCx) {
-    return Hold(JS_GetRuntime(aCx));
-  }
-
-  /**
-   * Hold by rooting on the runtime.
-   * Note that mVal may be JSVAL_NULL, which is not a problem.
-   */
-  bool Hold(JSRuntime* aRt) {
-    MOZ_ASSERT_IF(mRt, mRt == aRt);
-
-    if (!mRt && JS::AddNamedValueRootRT(aRt, &mVal, "nsAutoJSValHolder")) {
-      mRt = aRt;
-    }
-
-    return !!mRt;
-  }
-
-  /**
-   * Manually release, nullifying mVal, and mRt, but returning
-   * the original JS::Value.
-   */
-  JS::Value Release() {
-    JS::Value oldval = mVal;
-
-    if (mRt) {
-      JS::RemoveValueRootRT(mRt, &mVal); // infallible
-      mRt = nullptr;
-    }
-
-    mVal = JSVAL_NULL;
-
-    return oldval;
-  }
-
-  /**
-   * Determine if Hold has been called.
-   */
-  bool IsHeld() const {
-    return !!mRt;
-  }
-
-  /**
-   * Explicit JSObject* conversion.
-   */
-  JSObject* ToJSObject() const {
-    return mVal.isObject()
-         ? &mVal.toObject()
-         : nullptr;
-  }
-
-  /**
-   * Pretend to be a JS::Value.
-   */
-  operator JS::Value() const { return mVal; }
-  JS::Value get() const { return mVal; }
-
-  nsAutoJSValHolder &operator=(JSObject* aOther) {
-    return *this = OBJECT_TO_JSVAL(aOther);
-  }
-
-  nsAutoJSValHolder &operator=(JS::Value aOther) {
-#ifdef DEBUG
-    if (aOther.isGCThing() && !aOther.isNull()) {
-      MOZ_ASSERT(IsHeld(), "Not rooted!");
-    }
-#endif
-    mVal = aOther;
-    return *this;
-  }
-
-private:
-  JS::Heap<JS::Value> mVal;
-  JSRuntime* mRt;
-};
-
-#endif /* __NSAUTOJSVALHOLDER_H__ */
--- a/js/xpconnect/src/xpcprivate.h
+++ b/js/xpconnect/src/xpcprivate.h
@@ -124,17 +124,16 @@
 #include "xpcexception.h"
 #include "xpcjsid.h"
 #include "prenv.h"
 #include "prclist.h"
 #include "prcvar.h"
 #include "nsString.h"
 #include "nsReadableUtils.h"
 #include "nsXPIDLString.h"
-#include "nsAutoJSValHolder.h"
 
 #include "MainThreadUtils.h"
 
 #include "nsIConsoleService.h"
 #include "nsIScriptError.h"
 #include "nsIException.h"
 
 #include "nsVariant.h"