Tue, 06 Jan 2015 21:39:09 +0100
Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 * vim: set ts=8 sts=4 et sw=4 tw=99:
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 /*
8 * Helper classes encapsulating access to the callee, |this| value, arguments,
9 * and argument count for a function call.
10 *
11 * The intent of JS::CallArgs and JS::CallReceiver is that they be used to
12 * encapsulate access to the un-abstracted |unsigned argc, Value *vp| arguments
13 * to a function. It's possible (albeit deprecated) to manually index into
14 * |vp| to access the callee, |this|, and arguments of a function, and to set
15 * its return value. It's also possible to use the supported API of JS_CALLEE,
16 * JS_THIS, JS_ARGV, JS_RVAL and JS_SET_RVAL to the same ends. But neither API
17 * has the error-handling or moving-GC correctness of CallArgs or CallReceiver.
18 * New code should use CallArgs and CallReceiver instead whenever possible.
19 *
20 * The eventual plan is to change JSNative to take |const CallArgs&| directly,
21 * for automatic assertion of correct use and to make calling functions more
22 * efficient. Embedders should start internally switching away from using
23 * |argc| and |vp| directly, except to create a |CallArgs|. Then, when an
24 * eventual release making that change occurs, porting efforts will require
25 * changing methods' signatures but won't require invasive changes to the
26 * methods' implementations, potentially under time pressure.
27 */
29 #ifndef js_CallArgs_h
30 #define js_CallArgs_h
32 #include "mozilla/Assertions.h"
33 #include "mozilla/Attributes.h"
34 #include "mozilla/TypeTraits.h"
36 #include "jstypes.h"
38 #include "js/RootingAPI.h"
39 #include "js/Value.h"
41 /* Typedef for native functions called by the JS VM. */
42 typedef bool
43 (* JSNative)(JSContext *cx, unsigned argc, JS::Value *vp);
45 /* Typedef for native functions that may be called in parallel. */
46 typedef bool
47 (* JSParallelNative)(js::ForkJoinContext *cx, unsigned argc, JS::Value *vp);
49 /*
50 * Typedef for native functions that may be called either in parallel or
51 * sequential execution.
52 */
53 typedef bool
54 (* JSThreadSafeNative)(js::ThreadSafeContext *cx, unsigned argc, JS::Value *vp);
56 /*
57 * Convenience wrappers for passing in ThreadSafeNative to places that expect
58 * a JSNative or a JSParallelNative.
59 */
60 template <JSThreadSafeNative threadSafeNative>
61 inline bool
62 JSNativeThreadSafeWrapper(JSContext *cx, unsigned argc, JS::Value *vp);
64 template <JSThreadSafeNative threadSafeNative>
65 inline bool
66 JSParallelNativeThreadSafeWrapper(js::ForkJoinContext *cx, unsigned argc, JS::Value *vp);
68 /*
69 * Compute |this| for the |vp| inside a JSNative, either boxing primitives or
70 * replacing with the global object as necessary.
71 *
72 * This method will go away at some point: instead use |args.thisv()|. If the
73 * value is an object, no further work is required. If that value is |null| or
74 * |undefined|, use |JS_GetGlobalForObject| to compute the global object. If
75 * the value is some other primitive, use |JS_ValueToObject| to box it.
76 */
77 extern JS_PUBLIC_API(JS::Value)
78 JS_ComputeThis(JSContext *cx, JS::Value *vp);
80 namespace JS {
82 extern JS_PUBLIC_DATA(const HandleValue) UndefinedHandleValue;
84 /*
85 * JS::CallReceiver encapsulates access to the callee, |this|, and eventual
86 * return value for a function call. The principal way to create a
87 * CallReceiver is using JS::CallReceiverFromVp:
88 *
89 * static bool
90 * FunctionReturningThis(JSContext *cx, unsigned argc, JS::Value *vp)
91 * {
92 * JS::CallReceiver rec = JS::CallReceiverFromVp(vp);
93 *
94 * // Access to the callee must occur before accessing/setting
95 * // the return value.
96 * JSObject &callee = rec.callee();
97 * rec.rval().set(JS::ObjectValue(callee));
98 *
99 * // callee() and calleev() will now assert.
100 *
101 * // It's always fine to access thisv().
102 * HandleValue thisv = rec.thisv();
103 * rec.rval().set(thisv);
104 *
105 * // As the return value was last set to |this|, returns |this|.
106 * return true;
107 * }
108 *
109 * A note on JS_ComputeThis and JS_THIS_OBJECT: these methods currently aren't
110 * part of the CallReceiver interface. We will likely add them at some point.
111 * Until then, you should probably continue using |vp| directly for these two
112 * cases.
113 *
114 * CallReceiver is exposed publicly and used internally. Not all parts of its
115 * public interface are meant to be used by embedders! See inline comments to
116 * for details.
117 */
119 namespace detail {
121 #ifdef JS_DEBUG
122 extern JS_PUBLIC_API(void)
123 CheckIsValidConstructible(Value v);
124 #endif
126 enum UsedRval { IncludeUsedRval, NoUsedRval };
128 template<UsedRval WantUsedRval>
129 class MOZ_STACK_CLASS UsedRvalBase;
131 template<>
132 class MOZ_STACK_CLASS UsedRvalBase<IncludeUsedRval>
133 {
134 protected:
135 mutable bool usedRval_;
136 void setUsedRval() const { usedRval_ = true; }
137 void clearUsedRval() const { usedRval_ = false; }
138 };
140 template<>
141 class MOZ_STACK_CLASS UsedRvalBase<NoUsedRval>
142 {
143 protected:
144 void setUsedRval() const {}
145 void clearUsedRval() const {}
146 };
148 template<UsedRval WantUsedRval>
149 class MOZ_STACK_CLASS CallReceiverBase : public UsedRvalBase<
150 #ifdef JS_DEBUG
151 WantUsedRval
152 #else
153 NoUsedRval
154 #endif
155 >
156 {
157 protected:
158 Value *argv_;
160 public:
161 /*
162 * Returns the function being called, as an object. Must not be called
163 * after rval() has been used!
164 */
165 JSObject &callee() const {
166 MOZ_ASSERT(!this->usedRval_);
167 return argv_[-2].toObject();
168 }
170 /*
171 * Returns the function being called, as a value. Must not be called after
172 * rval() has been used!
173 */
174 HandleValue calleev() const {
175 MOZ_ASSERT(!this->usedRval_);
176 return HandleValue::fromMarkedLocation(&argv_[-2]);
177 }
179 /*
180 * Returns the |this| value passed to the function. This method must not
181 * be called when the function is being called as a constructor via |new|.
182 * The value may or may not be an object: it is the individual function's
183 * responsibility to box the value if needed.
184 */
185 HandleValue thisv() const {
186 // Some internal code uses thisv() in constructing cases, so don't do
187 // this yet.
188 // MOZ_ASSERT(!argv_[-1].isMagic(JS_IS_CONSTRUCTING));
189 return HandleValue::fromMarkedLocation(&argv_[-1]);
190 }
192 Value computeThis(JSContext *cx) const {
193 if (thisv().isObject())
194 return thisv();
196 return JS_ComputeThis(cx, base());
197 }
199 bool isConstructing() const {
200 #ifdef JS_DEBUG
201 if (this->usedRval_)
202 CheckIsValidConstructible(calleev());
203 #endif
204 return argv_[-1].isMagic();
205 }
207 /*
208 * Returns the currently-set return value. The initial contents of this
209 * value are unspecified. Once this method has been called, callee() and
210 * calleev() can no longer be used. (If you're compiling against a debug
211 * build of SpiderMonkey, these methods will assert to aid debugging.)
212 *
213 * If the method you're implementing succeeds by returning true, you *must*
214 * set this. (SpiderMonkey doesn't currently assert this, but it will do
215 * so eventually.) You don't need to use or change this if your method
216 * fails.
217 */
218 MutableHandleValue rval() const {
219 this->setUsedRval();
220 return MutableHandleValue::fromMarkedLocation(&argv_[-2]);
221 }
223 public:
224 // These methods are only intended for internal use. Embedders shouldn't
225 // use them!
227 Value *base() const { return argv_ - 2; }
229 Value *spAfterCall() const {
230 this->setUsedRval();
231 return argv_ - 1;
232 }
234 public:
235 // These methods are publicly exposed, but they are *not* to be used when
236 // implementing a JSNative method and encapsulating access to |vp| within
237 // it. You probably don't want to use these!
239 void setCallee(Value aCalleev) const {
240 this->clearUsedRval();
241 argv_[-2] = aCalleev;
242 }
244 void setThis(Value aThisv) const {
245 argv_[-1] = aThisv;
246 }
248 MutableHandleValue mutableThisv() const {
249 return MutableHandleValue::fromMarkedLocation(&argv_[-1]);
250 }
251 };
253 } // namespace detail
255 class MOZ_STACK_CLASS CallReceiver : public detail::CallReceiverBase<detail::IncludeUsedRval>
256 {
257 private:
258 friend CallReceiver CallReceiverFromVp(Value *vp);
259 friend CallReceiver CallReceiverFromArgv(Value *argv);
260 };
262 MOZ_ALWAYS_INLINE CallReceiver
263 CallReceiverFromArgv(Value *argv)
264 {
265 CallReceiver receiver;
266 receiver.clearUsedRval();
267 receiver.argv_ = argv;
268 return receiver;
269 }
271 MOZ_ALWAYS_INLINE CallReceiver
272 CallReceiverFromVp(Value *vp)
273 {
274 return CallReceiverFromArgv(vp + 2);
275 }
277 /*
278 * JS::CallArgs encapsulates everything JS::CallReceiver does, plus access to
279 * the function call's arguments. The principal way to create a CallArgs is
280 * like so, using JS::CallArgsFromVp:
281 *
282 * static bool
283 * FunctionReturningArgcTimesArg0(JSContext *cx, unsigned argc, JS::Value *vp)
284 * {
285 * JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
286 *
287 * // Guard against no arguments or a non-numeric arg0.
288 * if (args.length() == 0 || !args[0].isNumber()) {
289 * args.rval().setInt32(0);
290 * return true;
291 * }
292 *
293 * args.rval().set(JS::NumberValue(args.length() * args[0].toNumber()));
294 * return true;
295 * }
296 *
297 * CallArgs is exposed publicly and used internally. Not all parts of its
298 * public interface are meant to be used by embedders! See inline comments to
299 * for details.
300 */
301 namespace detail {
303 template<UsedRval WantUsedRval>
304 class MOZ_STACK_CLASS CallArgsBase :
305 public mozilla::Conditional<WantUsedRval == detail::IncludeUsedRval,
306 CallReceiver,
307 CallReceiverBase<NoUsedRval> >::Type
308 {
309 protected:
310 unsigned argc_;
312 public:
313 /* Returns the number of arguments. */
314 unsigned length() const { return argc_; }
316 /* Returns the i-th zero-indexed argument. */
317 MutableHandleValue operator[](unsigned i) const {
318 MOZ_ASSERT(i < argc_);
319 return MutableHandleValue::fromMarkedLocation(&this->argv_[i]);
320 }
322 /*
323 * Returns the i-th zero-indexed argument, or |undefined| if there's no
324 * such argument.
325 */
326 HandleValue get(unsigned i) const {
327 return i < length()
328 ? HandleValue::fromMarkedLocation(&this->argv_[i])
329 : UndefinedHandleValue;
330 }
332 /*
333 * Returns true if the i-th zero-indexed argument is present and is not
334 * |undefined|.
335 */
336 bool hasDefined(unsigned i) const {
337 return i < argc_ && !this->argv_[i].isUndefined();
338 }
340 public:
341 // These methods are publicly exposed, but we're less sure of the interface
342 // here than we'd like (because they're hackish and drop assertions). Try
343 // to avoid using these if you can.
345 Value *array() const { return this->argv_; }
346 Value *end() const { return this->argv_ + argc_; }
347 };
349 } // namespace detail
351 class MOZ_STACK_CLASS CallArgs : public detail::CallArgsBase<detail::IncludeUsedRval>
352 {
353 private:
354 friend CallArgs CallArgsFromVp(unsigned argc, Value *vp);
355 friend CallArgs CallArgsFromSp(unsigned argc, Value *sp);
357 static CallArgs create(unsigned argc, Value *argv) {
358 CallArgs args;
359 args.clearUsedRval();
360 args.argv_ = argv;
361 args.argc_ = argc;
362 return args;
363 }
365 };
367 MOZ_ALWAYS_INLINE CallArgs
368 CallArgsFromVp(unsigned argc, Value *vp)
369 {
370 return CallArgs::create(argc, vp + 2);
371 }
373 // This method is only intended for internal use in SpiderMonkey. We may
374 // eventually move it to an internal header. Embedders should use
375 // JS::CallArgsFromVp!
376 MOZ_ALWAYS_INLINE CallArgs
377 CallArgsFromSp(unsigned argc, Value *sp)
378 {
379 return CallArgs::create(argc, sp - argc);
380 }
382 } // namespace JS
384 /*
385 * Macros to hide interpreter stack layout details from a JSNative using its
386 * JS::Value *vp parameter. DO NOT USE THESE! Instead use JS::CallArgs and
387 * friends, above. These macros will be removed when we change JSNative to
388 * take a const JS::CallArgs&.
389 */
391 #define JS_THIS_OBJECT(cx,vp) (JSVAL_TO_OBJECT(JS_THIS(cx,vp)))
393 /*
394 * Note: if this method returns null, an error has occurred and must be
395 * propagated or caught.
396 */
397 MOZ_ALWAYS_INLINE JS::Value
398 JS_THIS(JSContext *cx, JS::Value *vp)
399 {
400 return JSVAL_IS_PRIMITIVE(vp[1]) ? JS_ComputeThis(cx, vp) : vp[1];
401 }
403 /*
404 * |this| is passed to functions in ES5 without change. Functions themselves
405 * do any post-processing they desire to box |this|, compute the global object,
406 * &c. This macro retrieves a function's unboxed |this| value.
407 *
408 * This macro must not be used in conjunction with JS_THIS or JS_THIS_OBJECT,
409 * or vice versa. Either use the provided this value with this macro, or
410 * compute the boxed |this| value using those. JS_THIS_VALUE must not be used
411 * if the function is being called as a constructor.
412 *
413 * But: DO NOT USE THIS! Instead use JS::CallArgs::thisv(), above.
414 *
415 */
416 #define JS_THIS_VALUE(cx,vp) ((vp)[1])
418 #endif /* js_CallArgs_h */