Thu, 15 Jan 2015 15:55:04 +0100
Back out 97036ab72558 which inappropriately compared turds to third parties.
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #ifndef __NSAUTOJSVALHOLDER_H__
8 #define __NSAUTOJSVALHOLDER_H__
10 #include "nsDebug.h"
11 #include "jsapi.h"
13 /**
14 * Simple class that looks and acts like a JS::Value except that it unroots
15 * itself automatically if Root() is ever called. Designed to be rooted on the
16 * context or runtime (but not both!).
17 */
18 class nsAutoJSValHolder
19 {
20 public:
21 nsAutoJSValHolder()
22 : mVal(JSVAL_NULL), mRt(nullptr)
23 {
24 // nothing to do
25 }
27 /**
28 * Always release on destruction.
29 */
30 virtual ~nsAutoJSValHolder() {
31 Release();
32 }
34 nsAutoJSValHolder(const nsAutoJSValHolder& aOther)
35 : mVal(JSVAL_NULL), mRt(nullptr)
36 {
37 *this = aOther;
38 }
40 nsAutoJSValHolder& operator=(const nsAutoJSValHolder& aOther) {
41 if (this != &aOther) {
42 if (aOther.IsHeld()) {
43 // XXX No error handling here...
44 this->Hold(aOther.mRt);
45 }
46 else {
47 this->Release();
48 }
49 *this = static_cast<JS::Value>(aOther);
50 }
51 return *this;
52 }
54 /**
55 * Hold by rooting on the context's runtime.
56 */
57 bool Hold(JSContext* aCx) {
58 return Hold(JS_GetRuntime(aCx));
59 }
61 /**
62 * Hold by rooting on the runtime.
63 * Note that mVal may be JSVAL_NULL, which is not a problem.
64 */
65 bool Hold(JSRuntime* aRt) {
66 MOZ_ASSERT_IF(mRt, mRt == aRt);
68 if (!mRt && JS::AddNamedValueRootRT(aRt, &mVal, "nsAutoJSValHolder")) {
69 mRt = aRt;
70 }
72 return !!mRt;
73 }
75 /**
76 * Manually release, nullifying mVal, and mRt, but returning
77 * the original JS::Value.
78 */
79 JS::Value Release() {
80 JS::Value oldval = mVal;
82 if (mRt) {
83 JS::RemoveValueRootRT(mRt, &mVal); // infallible
84 mRt = nullptr;
85 }
87 mVal = JSVAL_NULL;
89 return oldval;
90 }
92 /**
93 * Determine if Hold has been called.
94 */
95 bool IsHeld() const {
96 return !!mRt;
97 }
99 /**
100 * Explicit JSObject* conversion.
101 */
102 JSObject* ToJSObject() const {
103 return mVal.isObject()
104 ? &mVal.toObject()
105 : nullptr;
106 }
108 /**
109 * Pretend to be a JS::Value.
110 */
111 operator JS::Value() const { return mVal; }
112 JS::Value get() const { return mVal; }
114 nsAutoJSValHolder &operator=(JSObject* aOther) {
115 return *this = OBJECT_TO_JSVAL(aOther);
116 }
118 nsAutoJSValHolder &operator=(JS::Value aOther) {
119 #ifdef DEBUG
120 if (JSVAL_IS_GCTHING(aOther) && !JSVAL_IS_NULL(aOther)) {
121 MOZ_ASSERT(IsHeld(), "Not rooted!");
122 }
123 #endif
124 mVal = aOther;
125 return *this;
126 }
128 private:
129 JS::Heap<JS::Value> mVal;
130 JSRuntime* mRt;
131 };
133 #endif /* __NSAUTOJSVALHOLDER_H__ */