1 : /* -*- Mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*- */
2 : /* ***** BEGIN LICENSE BLOCK *****
3 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 : *
5 : * The contents of this file are subject to the Mozilla Public License Version
6 : * 1.1 (the "License"); you may not use this file except in compliance with
7 : * the License. You may obtain a copy of the License at
8 : * http://www.mozilla.org/MPL/
9 : *
10 : * Software distributed under the License is distributed on an "AS IS" basis,
11 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 : * for the specific language governing rights and limitations under the
13 : * License.
14 : *
15 : * The Original Code is worker threads.
16 : *
17 : * The Initial Developer of the Original Code is
18 : * Mozilla Corporation.
19 : * Portions created by the Initial Developer are Copyright (C) 2008
20 : * the Initial Developer. All Rights Reserved.
21 : *
22 : * Contributor(s):
23 : * Ben Turner <bent.mozilla@gmail.com> (Original Author)
24 : * Ben Newman <b{enjamn,newman}@mozilla.com>
25 : *
26 : * Alternatively, the contents of this file may be used under the terms of
27 : * either the GNU General Public License Version 2 or later (the "GPL"), or
28 : * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29 : * in which case the provisions of the GPL or the LGPL are applicable instead
30 : * of those above. If you wish to allow use of your version of this file only
31 : * under the terms of either the GPL or the LGPL, and not to allow others to
32 : * use your version of this file under the terms of the MPL, indicate your
33 : * decision by deleting the provisions above and replace them with the notice
34 : * and other provisions required by the GPL or the LGPL. If you do not delete
35 : * the provisions above, a recipient may use your version of this file under
36 : * the terms of any one of the MPL, the GPL or the LGPL.
37 : *
38 : * ***** END LICENSE BLOCK ***** */
39 :
40 : #ifndef __NSAUTOJSVALHOLDER_H__
41 : #define __NSAUTOJSVALHOLDER_H__
42 :
43 : #include "jsapi.h"
44 :
45 : #include "nsDebug.h"
46 :
47 : /**
48 : * Simple class that looks and acts like a jsval except that it unroots
49 : * itself automatically if Root() is ever called. Designed to be rooted on the
50 : * context or runtime (but not both!).
51 : */
52 : class nsAutoJSValHolder
53 : {
54 : public:
55 45911 : nsAutoJSValHolder() : mVal(JSVAL_NULL), mRt(nsnull)
56 : {
57 : // nothing to do
58 45911 : }
59 :
60 : /**
61 : * Always release on destruction.
62 : */
63 45911 : virtual ~nsAutoJSValHolder() {
64 45911 : Release();
65 91822 : }
66 :
67 : nsAutoJSValHolder(const nsAutoJSValHolder& aOther) {
68 : *this = aOther;
69 : }
70 :
71 : nsAutoJSValHolder& operator=(const nsAutoJSValHolder& aOther) {
72 : if (this != &aOther) {
73 : if (aOther.IsHeld()) {
74 : // XXX No error handling here...
75 : this->Hold(aOther.mRt);
76 : }
77 : else {
78 : this->Release();
79 : }
80 : *this = static_cast<jsval>(aOther);
81 : }
82 : return *this;
83 : }
84 :
85 : /**
86 : * Hold by rooting on the context's runtime.
87 : */
88 6371 : bool Hold(JSContext* aCx) {
89 6371 : return Hold(JS_GetRuntime(aCx));
90 : }
91 :
92 : /**
93 : * Hold by rooting on the runtime.
94 : * Note that mVal may be JSVAL_NULL, which is not a problem.
95 : */
96 6371 : bool Hold(JSRuntime* aRt) {
97 : // Do we really care about different runtimes?
98 6371 : if (mRt && aRt != mRt) {
99 0 : js_RemoveRoot(mRt, &mVal);
100 0 : mRt = nsnull;
101 : }
102 :
103 6371 : if (!mRt && js_AddRootRT(aRt, &mVal, "nsAutoJSValHolder")) {
104 6371 : mRt = aRt;
105 : }
106 :
107 6371 : return !!mRt;
108 : }
109 :
110 : /**
111 : * Manually release, nullifying mVal, and mRt, but returning
112 : * the original jsval.
113 : */
114 45911 : jsval Release() {
115 45911 : jsval oldval = mVal;
116 :
117 45911 : if (mRt) {
118 6371 : js_RemoveRoot(mRt, &mVal); // infallible
119 6371 : mRt = nsnull;
120 : }
121 :
122 45911 : mVal = JSVAL_NULL;
123 :
124 : return oldval;
125 : }
126 :
127 : /**
128 : * Determine if Hold has been called.
129 : */
130 80 : bool IsHeld() const {
131 80 : return !!mRt;
132 : }
133 :
134 : /**
135 : * Explicit JSObject* conversion.
136 : */
137 0 : JSObject* ToJSObject() const {
138 0 : return JSVAL_IS_OBJECT(mVal)
139 : ? JSVAL_TO_OBJECT(mVal)
140 0 : : nsnull;
141 : }
142 :
143 0 : jsval* ToJSValPtr() {
144 0 : return &mVal;
145 : }
146 :
147 : /**
148 : * Pretend to be a jsval.
149 : */
150 0 : operator jsval() const { return mVal; }
151 :
152 0 : nsAutoJSValHolder &operator=(JSObject* aOther) {
153 0 : return *this = OBJECT_TO_JSVAL(aOther);
154 : }
155 :
156 6371 : nsAutoJSValHolder &operator=(jsval aOther) {
157 : #ifdef DEBUG
158 6371 : if (JSVAL_IS_GCTHING(aOther) && !JSVAL_IS_NULL(aOther)) {
159 80 : NS_ASSERTION(IsHeld(), "Not rooted!");
160 : }
161 : #endif
162 6371 : mVal = aOther;
163 6371 : return *this;
164 : }
165 :
166 : private:
167 : jsval mVal;
168 : JSRuntime* mRt;
169 : };
170 :
171 : #endif /* __NSAUTOJSVALHOLDER_H__ */
|