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/. */
10 #include "mozilla/Maybe.h"
12 #include "jsfriendapi.h"
14 #include "js/CallNonGenericMethod.h"
19 using JS::AutoIdVector
;
22 using JS::HandleObject
;
23 using JS::HandleValue
;
24 using JS::IsAcceptableThis
;
25 using JS::MutableHandle
;
26 using JS::MutableHandleObject
;
27 using JS::MutableHandleValue
;
29 using JS::PrivateValue
;
33 class JS_FRIEND_API(Wrapper
);
36 * A proxy is a JSObject that implements generic behavior by providing custom
37 * implementations for each object trap. The implementation for each trap is
38 * provided by a C++ object stored on the proxy, known as its handler.
40 * A major use case for proxies is to forward each trap to another object,
41 * known as its target. The target can be an arbitrary C++ object. Not every
42 * proxy has the notion of a target, however.
44 * Proxy traps are grouped into fundamental and derived traps. Every proxy has
45 * to at least provide implementations for the fundamental traps, but the
46 * derived traps can be implemented in terms of the fundamental ones
47 * BaseProxyHandler provides implementations of the derived traps in terms of
48 * the (pure virtual) fundamental traps.
50 * In addition to the normal traps, there are two models for proxy prototype
51 * chains. First, proxies may opt to use the standard prototype mechanism used
52 * throughout the engine. To do so, simply pass a prototype to NewProxyObject()
53 * at creation time. All prototype accesses will then "just work" to treat the
54 * proxy as a "normal" object. Alternatively, if instead the proxy wishes to
55 * implement more complicated prototype semantics (if, for example, it wants to
56 * delegate the prototype lookup to a wrapped object), it may pass Proxy::LazyProto
57 * as the prototype at create time and opt in to the trapped prototype system,
58 * which guarantees that their trap will be called on any and every prototype
59 * chain access of the object.
61 * This system is implemented with two traps: {get,set}PrototypeOf. The default
62 * implementation of setPrototypeOf throws a TypeError. Since it is not possible
63 * to create an object without a sense of prototype chain, handler implementors
64 * must provide a getPrototypeOf trap if opting in to the dynamic prototype system.
66 * To minimize code duplication, a set of abstract proxy handler classes is
67 * provided, from which other handlers may inherit. These abstract classes
68 * are organized in the following hierarchy:
78 * BaseProxyHandler is the most generic kind of proxy handler. It does not make
79 * any assumptions about the target. Consequently, it does not provide any
80 * default implementation for the fundamental traps. It does, however, implement
81 * the derived traps in terms of the fundamental ones. This allows consumers of
82 * this class to define any custom behavior they want.
84 * Important: If you add a trap here, you should probably also add a Proxy::foo
85 * entry point with an AutoEnterPolicy. If you don't, you need an explicit
86 * override for the trap in SecurityWrapper. See bug 945826 comment 0.
88 class JS_FRIEND_API(BaseProxyHandler
)
91 * Sometimes it's desirable to designate groups of proxy handlers as "similar".
92 * For this, we use the notion of a "family": A consumer-provided opaque pointer
93 * that designates the larger group to which this proxy belongs.
95 * If it will never be important to differentiate this proxy from others as
96 * part of a distinct group, nullptr may be used instead.
101 * Proxy handlers can use mHasPrototype to request the following special
102 * treatment from the JS engine:
104 * - When mHasPrototype is true, the engine never calls these methods:
105 * getPropertyDescriptor, has, set, enumerate, iterate. Instead, for
106 * these operations, it calls the "own" traps like
107 * getOwnPropertyDescriptor, hasOwn, defineProperty, keys, etc., and
108 * consults the prototype chain if needed.
110 * - When mHasPrototype is true, the engine calls handler->get() only if
111 * handler->hasOwn() says an own property exists on the proxy. If not,
112 * it consults the prototype chain.
114 * This is useful because it frees the ProxyHandler from having to implement
115 * any behavior having to do with the prototype chain.
120 * All proxies indicate whether they have any sort of interesting security
121 * policy that might prevent the caller from doing something it wants to
122 * the object. In the case of wrappers, this distinction is used to
123 * determine whether the caller may strip off the wrapper if it so desires.
125 bool mHasSecurityPolicy
;
128 explicit MOZ_CONSTEXPR
BaseProxyHandler(const void *aFamily
, bool aHasPrototype
= false,
129 bool aHasSecurityPolicy
= false)
131 mHasPrototype(aHasPrototype
),
132 mHasSecurityPolicy(aHasSecurityPolicy
)
135 bool hasPrototype() const {
136 return mHasPrototype
;
139 bool hasSecurityPolicy() const {
140 return mHasSecurityPolicy
;
143 inline const void *family() const {
146 static size_t offsetOfFamily() {
147 return offsetof(BaseProxyHandler
, mFamily
);
150 virtual bool finalizeInBackground(Value priv
) const {
152 * Called on creation of a proxy to determine whether its finalize
153 * method can be finalized on the background thread.
158 /* Policy enforcement traps.
160 * enter() allows the policy to specify whether the caller may perform |act|
161 * on the proxy's |id| property. In the case when |act| is CALL, |id| is
162 * generally JSID_VOID.
164 * The |act| parameter to enter() specifies the action being performed.
165 * If |bp| is false, the trap suggests that the caller throw (though it
166 * may still decide to squelch the error).
168 * We make these OR-able so that assertEnteredPolicy can pass a union of them.
169 * For example, get{,Own}PropertyDescriptor is invoked by calls to ::get()
170 * ::set(), in addition to being invoked on its own, so there are several
171 * valid Actions that could have been entered.
173 typedef uint32_t Action
;
180 GET_PROPERTY_DESCRIPTOR
= 0x10
183 virtual bool enter(JSContext
*cx
, HandleObject wrapper
, HandleId id
, Action act
,
186 /* ES5 Harmony fundamental proxy traps. */
187 virtual bool preventExtensions(JSContext
*cx
, HandleObject proxy
) const = 0;
188 virtual bool getPropertyDescriptor(JSContext
*cx
, HandleObject proxy
, HandleId id
,
189 MutableHandle
<JSPropertyDescriptor
> desc
) const = 0;
190 virtual bool getOwnPropertyDescriptor(JSContext
*cx
, HandleObject proxy
,
191 HandleId id
, MutableHandle
<JSPropertyDescriptor
> desc
) const = 0;
192 virtual bool defineProperty(JSContext
*cx
, HandleObject proxy
, HandleId id
,
193 MutableHandle
<JSPropertyDescriptor
> desc
) const = 0;
194 virtual bool getOwnPropertyNames(JSContext
*cx
, HandleObject proxy
,
195 AutoIdVector
&props
) const = 0;
196 virtual bool delete_(JSContext
*cx
, HandleObject proxy
, HandleId id
, bool *bp
) const = 0;
197 virtual bool enumerate(JSContext
*cx
, HandleObject proxy
, AutoIdVector
&props
) const = 0;
199 /* ES5 Harmony derived proxy traps. */
200 virtual bool has(JSContext
*cx
, HandleObject proxy
, HandleId id
, bool *bp
) const;
201 virtual bool hasOwn(JSContext
*cx
, HandleObject proxy
, HandleId id
, bool *bp
) const;
202 virtual bool get(JSContext
*cx
, HandleObject proxy
, HandleObject receiver
,
203 HandleId id
, MutableHandleValue vp
) const;
204 virtual bool set(JSContext
*cx
, HandleObject proxy
, HandleObject receiver
,
205 HandleId id
, bool strict
, MutableHandleValue vp
) const;
206 virtual bool keys(JSContext
*cx
, HandleObject proxy
, AutoIdVector
&props
) const;
207 virtual bool iterate(JSContext
*cx
, HandleObject proxy
, unsigned flags
,
208 MutableHandleValue vp
) const;
210 /* Spidermonkey extensions. */
211 virtual bool isExtensible(JSContext
*cx
, HandleObject proxy
, bool *extensible
) const = 0;
212 virtual bool call(JSContext
*cx
, HandleObject proxy
, const CallArgs
&args
) const;
213 virtual bool construct(JSContext
*cx
, HandleObject proxy
, const CallArgs
&args
) const;
214 virtual bool nativeCall(JSContext
*cx
, IsAcceptableThis test
, NativeImpl impl
, CallArgs args
) const;
215 virtual bool hasInstance(JSContext
*cx
, HandleObject proxy
, MutableHandleValue v
, bool *bp
) const;
216 virtual bool objectClassIs(HandleObject obj
, ESClassValue classValue
, JSContext
*cx
) const;
217 virtual const char *className(JSContext
*cx
, HandleObject proxy
) const;
218 virtual JSString
*fun_toString(JSContext
*cx
, HandleObject proxy
, unsigned indent
) const;
219 virtual bool regexp_toShared(JSContext
*cx
, HandleObject proxy
, RegExpGuard
*g
) const;
220 virtual bool boxedValue_unbox(JSContext
*cx
, HandleObject proxy
, MutableHandleValue vp
) const;
221 virtual bool defaultValue(JSContext
*cx
, HandleObject obj
, JSType hint
, MutableHandleValue vp
) const;
222 virtual void finalize(JSFreeOp
*fop
, JSObject
*proxy
) const;
223 virtual bool getPrototypeOf(JSContext
*cx
, HandleObject proxy
, MutableHandleObject protop
) const;
224 virtual bool setPrototypeOf(JSContext
*cx
, HandleObject proxy
, HandleObject proto
, bool *bp
) const;
226 // These two hooks must be overridden, or not overridden, in tandem -- no
227 // overriding just one!
228 virtual bool watch(JSContext
*cx
, JS::HandleObject proxy
, JS::HandleId id
,
229 JS::HandleObject callable
) const;
230 virtual bool unwatch(JSContext
*cx
, JS::HandleObject proxy
, JS::HandleId id
) const;
232 virtual bool slice(JSContext
*cx
, HandleObject proxy
, uint32_t begin
, uint32_t end
,
233 HandleObject result
) const;
235 /* See comment for weakmapKeyDelegateOp in js/Class.h. */
236 virtual JSObject
*weakmapKeyDelegate(JSObject
*proxy
) const;
237 virtual bool isScripted() const { return false; }
241 * DirectProxyHandler includes a notion of a target object. All traps are
242 * reimplemented such that they forward their behavior to the target. This
243 * allows consumers of this class to forward to another object as transparently
244 * and efficiently as possible.
246 * Important: If you add a trap implementation here, you probably also need to
247 * add an override in CrossCompartmentWrapper. If you don't, you risk
248 * compartment mismatches. See bug 945826 comment 0.
250 class JS_PUBLIC_API(DirectProxyHandler
) : public BaseProxyHandler
253 explicit MOZ_CONSTEXPR
DirectProxyHandler(const void *aFamily
, bool aHasPrototype
= false,
254 bool aHasSecurityPolicy
= false)
255 : BaseProxyHandler(aFamily
, aHasPrototype
, aHasSecurityPolicy
)
258 /* ES5 Harmony fundamental proxy traps. */
259 virtual bool preventExtensions(JSContext
*cx
, HandleObject proxy
) const MOZ_OVERRIDE
;
260 virtual bool getPropertyDescriptor(JSContext
*cx
, HandleObject proxy
, HandleId id
,
261 MutableHandle
<JSPropertyDescriptor
> desc
) const MOZ_OVERRIDE
;
262 virtual bool getOwnPropertyDescriptor(JSContext
*cx
, HandleObject proxy
, HandleId id
,
263 MutableHandle
<JSPropertyDescriptor
> desc
) const MOZ_OVERRIDE
;
264 virtual bool defineProperty(JSContext
*cx
, HandleObject proxy
, HandleId id
,
265 MutableHandle
<JSPropertyDescriptor
> desc
) const MOZ_OVERRIDE
;
266 virtual bool getOwnPropertyNames(JSContext
*cx
, HandleObject proxy
,
267 AutoIdVector
&props
) const MOZ_OVERRIDE
;
268 virtual bool delete_(JSContext
*cx
, HandleObject proxy
, HandleId id
,
269 bool *bp
) const MOZ_OVERRIDE
;
270 virtual bool enumerate(JSContext
*cx
, HandleObject proxy
,
271 AutoIdVector
&props
) const MOZ_OVERRIDE
;
273 /* ES5 Harmony derived proxy traps. */
274 virtual bool has(JSContext
*cx
, HandleObject proxy
, HandleId id
,
275 bool *bp
) const MOZ_OVERRIDE
;
276 virtual bool hasOwn(JSContext
*cx
, HandleObject proxy
, HandleId id
,
277 bool *bp
) const MOZ_OVERRIDE
;
278 virtual bool get(JSContext
*cx
, HandleObject proxy
, HandleObject receiver
,
279 HandleId id
, MutableHandleValue vp
) const MOZ_OVERRIDE
;
280 virtual bool set(JSContext
*cx
, HandleObject proxy
, HandleObject receiver
,
281 HandleId id
, bool strict
, MutableHandleValue vp
) const MOZ_OVERRIDE
;
282 virtual bool keys(JSContext
*cx
, HandleObject proxy
,
283 AutoIdVector
&props
) const MOZ_OVERRIDE
;
284 virtual bool iterate(JSContext
*cx
, HandleObject proxy
, unsigned flags
,
285 MutableHandleValue vp
) const MOZ_OVERRIDE
;
287 /* Spidermonkey extensions. */
288 virtual bool isExtensible(JSContext
*cx
, HandleObject proxy
, bool *extensible
) const MOZ_OVERRIDE
;
289 virtual bool call(JSContext
*cx
, HandleObject proxy
, const CallArgs
&args
) const MOZ_OVERRIDE
;
290 virtual bool construct(JSContext
*cx
, HandleObject proxy
, const CallArgs
&args
) const MOZ_OVERRIDE
;
291 virtual bool nativeCall(JSContext
*cx
, IsAcceptableThis test
, NativeImpl impl
,
292 CallArgs args
) const MOZ_OVERRIDE
;
293 virtual bool hasInstance(JSContext
*cx
, HandleObject proxy
, MutableHandleValue v
,
294 bool *bp
) const MOZ_OVERRIDE
;
295 virtual bool getPrototypeOf(JSContext
*cx
, HandleObject proxy
,
296 MutableHandleObject protop
) const MOZ_OVERRIDE
;
297 virtual bool setPrototypeOf(JSContext
*cx
, HandleObject proxy
, HandleObject proto
,
298 bool *bp
) const MOZ_OVERRIDE
;
299 virtual bool objectClassIs(HandleObject obj
, ESClassValue classValue
,
300 JSContext
*cx
) const MOZ_OVERRIDE
;
301 virtual const char *className(JSContext
*cx
, HandleObject proxy
) const MOZ_OVERRIDE
;
302 virtual JSString
*fun_toString(JSContext
*cx
, HandleObject proxy
,
303 unsigned indent
) const MOZ_OVERRIDE
;
304 virtual bool regexp_toShared(JSContext
*cx
, HandleObject proxy
,
305 RegExpGuard
*g
) const MOZ_OVERRIDE
;
306 virtual bool boxedValue_unbox(JSContext
*cx
, HandleObject proxy
, MutableHandleValue vp
) const;
307 virtual JSObject
*weakmapKeyDelegate(JSObject
*proxy
) const MOZ_OVERRIDE
;
311 * Dispatch point for handlers that executes the appropriate C++ or scripted traps.
313 * Important: All proxy traps need either (a) an AutoEnterPolicy in their
314 * Proxy::foo entry point below or (b) an override in SecurityWrapper. See bug
320 /* ES5 Harmony fundamental proxy traps. */
321 static bool preventExtensions(JSContext
*cx
, HandleObject proxy
);
322 static bool getPropertyDescriptor(JSContext
*cx
, HandleObject proxy
, HandleId id
,
323 MutableHandle
<JSPropertyDescriptor
> desc
);
324 static bool getPropertyDescriptor(JSContext
*cx
, HandleObject proxy
, HandleId id
,
325 MutableHandleValue vp
);
326 static bool getOwnPropertyDescriptor(JSContext
*cx
, HandleObject proxy
, HandleId id
,
327 MutableHandle
<JSPropertyDescriptor
> desc
);
328 static bool getOwnPropertyDescriptor(JSContext
*cx
, HandleObject proxy
, HandleId id
,
329 MutableHandleValue vp
);
330 static bool defineProperty(JSContext
*cx
, HandleObject proxy
, HandleId id
,
331 MutableHandle
<JSPropertyDescriptor
> desc
);
332 static bool getOwnPropertyNames(JSContext
*cx
, HandleObject proxy
, AutoIdVector
&props
);
333 static bool delete_(JSContext
*cx
, HandleObject proxy
, HandleId id
, bool *bp
);
334 static bool enumerate(JSContext
*cx
, HandleObject proxy
, AutoIdVector
&props
);
336 /* ES5 Harmony derived proxy traps. */
337 static bool has(JSContext
*cx
, HandleObject proxy
, HandleId id
, bool *bp
);
338 static bool hasOwn(JSContext
*cx
, HandleObject proxy
, HandleId id
, bool *bp
);
339 static bool get(JSContext
*cx
, HandleObject proxy
, HandleObject receiver
, HandleId id
,
340 MutableHandleValue vp
);
341 static bool set(JSContext
*cx
, HandleObject proxy
, HandleObject receiver
, HandleId id
,
342 bool strict
, MutableHandleValue vp
);
343 static bool keys(JSContext
*cx
, HandleObject proxy
, AutoIdVector
&props
);
344 static bool iterate(JSContext
*cx
, HandleObject proxy
, unsigned flags
, MutableHandleValue vp
);
346 /* Spidermonkey extensions. */
347 static bool isExtensible(JSContext
*cx
, HandleObject proxy
, bool *extensible
);
348 static bool call(JSContext
*cx
, HandleObject proxy
, const CallArgs
&args
);
349 static bool construct(JSContext
*cx
, HandleObject proxy
, const CallArgs
&args
);
350 static bool nativeCall(JSContext
*cx
, IsAcceptableThis test
, NativeImpl impl
, CallArgs args
);
351 static bool hasInstance(JSContext
*cx
, HandleObject proxy
, MutableHandleValue v
, bool *bp
);
352 static bool objectClassIs(HandleObject obj
, ESClassValue classValue
, JSContext
*cx
);
353 static const char *className(JSContext
*cx
, HandleObject proxy
);
354 static JSString
*fun_toString(JSContext
*cx
, HandleObject proxy
, unsigned indent
);
355 static bool regexp_toShared(JSContext
*cx
, HandleObject proxy
, RegExpGuard
*g
);
356 static bool boxedValue_unbox(JSContext
*cx
, HandleObject proxy
, MutableHandleValue vp
);
357 static bool defaultValue(JSContext
*cx
, HandleObject obj
, JSType hint
, MutableHandleValue vp
);
358 static bool getPrototypeOf(JSContext
*cx
, HandleObject proxy
, MutableHandleObject protop
);
359 static bool setPrototypeOf(JSContext
*cx
, HandleObject proxy
, HandleObject proto
, bool *bp
);
361 static bool watch(JSContext
*cx
, HandleObject proxy
, HandleId id
, HandleObject callable
);
362 static bool unwatch(JSContext
*cx
, HandleObject proxy
, HandleId id
);
364 static bool slice(JSContext
*cx
, HandleObject obj
, uint32_t begin
, uint32_t end
,
365 HandleObject result
);
367 /* IC entry path for handling __noSuchMethod__ on access. */
368 static bool callProp(JSContext
*cx
, HandleObject proxy
, HandleObject reveiver
, HandleId id
,
369 MutableHandleValue vp
);
372 // Use these in places where you don't want to #include vm/ProxyObject.h.
373 extern JS_FRIEND_DATA(const js::Class
* const) CallableProxyClassPtr
;
374 extern JS_FRIEND_DATA(const js::Class
* const) UncallableProxyClassPtr
;
376 inline bool IsProxy(JSObject
*obj
)
378 return GetObjectClass(obj
)->isProxy();
382 * These are part of the API.
384 * NOTE: PROXY_PRIVATE_SLOT is 0 because that way slot 0 is usable by API
385 * clients for both proxy and non-proxy objects. So an API client that only
386 * needs to store one slot's worth of data doesn't need to branch on what sort
389 const uint32_t PROXY_PRIVATE_SLOT
= 0;
390 const uint32_t PROXY_HANDLER_SLOT
= 1;
391 const uint32_t PROXY_EXTRA_SLOT
= 2;
392 const uint32_t PROXY_MINIMUM_SLOTS
= 4;
394 inline const BaseProxyHandler
*
395 GetProxyHandler(JSObject
*obj
)
397 JS_ASSERT(IsProxy(obj
));
398 return (const BaseProxyHandler
*) GetReservedSlot(obj
, PROXY_HANDLER_SLOT
).toPrivate();
402 GetProxyPrivate(JSObject
*obj
)
404 JS_ASSERT(IsProxy(obj
));
405 return GetReservedSlot(obj
, PROXY_PRIVATE_SLOT
);
409 GetProxyTargetObject(JSObject
*obj
)
411 JS_ASSERT(IsProxy(obj
));
412 return GetProxyPrivate(obj
).toObjectOrNull();
416 GetProxyExtra(JSObject
*obj
, size_t n
)
418 JS_ASSERT(IsProxy(obj
));
419 return GetReservedSlot(obj
, PROXY_EXTRA_SLOT
+ n
);
423 SetProxyHandler(JSObject
*obj
, BaseProxyHandler
*handler
)
425 JS_ASSERT(IsProxy(obj
));
426 SetReservedSlot(obj
, PROXY_HANDLER_SLOT
, PrivateValue(handler
));
430 SetProxyExtra(JSObject
*obj
, size_t n
, const Value
&extra
)
432 JS_ASSERT(IsProxy(obj
));
434 SetReservedSlot(obj
, PROXY_EXTRA_SLOT
+ n
, extra
);
438 IsScriptedProxy(JSObject
*obj
)
440 return IsProxy(obj
) && GetProxyHandler(obj
)->isScripted();
443 class MOZ_STACK_CLASS ProxyOptions
{
445 /* protected constructor for subclass */
446 ProxyOptions(bool singletonArg
, const Class
*claspArg
)
447 : singleton_(singletonArg
),
452 ProxyOptions() : singleton_(false),
453 clasp_(UncallableProxyClassPtr
)
456 bool singleton() const { return singleton_
; }
457 ProxyOptions
&setSingleton(bool flag
) {
462 const Class
*clasp() const {
465 ProxyOptions
&setClass(const Class
*claspArg
) {
469 ProxyOptions
&selectDefaultClass(bool callable
) {
470 const Class
*classp
= callable
? CallableProxyClassPtr
:
471 UncallableProxyClassPtr
;
472 return setClass(classp
);
480 JS_FRIEND_API(JSObject
*)
481 NewProxyObject(JSContext
*cx
, const BaseProxyHandler
*handler
, HandleValue priv
,
482 JSObject
*proto
, JSObject
*parent
, const ProxyOptions
&options
= ProxyOptions());
485 RenewProxyObject(JSContext
*cx
, JSObject
*obj
, BaseProxyHandler
*handler
, Value priv
);
487 class JS_FRIEND_API(AutoEnterPolicy
)
490 typedef BaseProxyHandler::Action Action
;
491 AutoEnterPolicy(JSContext
*cx
, const BaseProxyHandler
*handler
,
492 HandleObject wrapper
, HandleId id
, Action act
, bool mayThrow
)
497 allow
= handler
->hasSecurityPolicy() ? handler
->enter(cx
, wrapper
, id
, act
, &rv
)
499 recordEnter(cx
, wrapper
, id
, act
);
500 // We want to throw an exception if all of the following are true:
501 // * The policy disallowed access.
502 // * The policy set rv to false, indicating that we should throw.
503 // * The caller did not instruct us to ignore exceptions.
504 // * The policy did not throw itself.
505 if (!allow
&& !rv
&& mayThrow
)
506 reportErrorIfExceptionIsNotPending(cx
, id
);
509 virtual ~AutoEnterPolicy() { recordLeave(); }
510 inline bool allowed() { return allow
; }
511 inline bool returnValue() { JS_ASSERT(!allowed()); return rv
; }
514 // no-op constructor for subclass
518 , enteredAction(BaseProxyHandler::NONE
)
521 void reportErrorIfExceptionIsNotPending(JSContext
*cx
, jsid id
);
527 mozilla::Maybe
<HandleObject
> enteredProxy
;
528 mozilla::Maybe
<HandleId
> enteredId
;
529 Action enteredAction
;
531 // NB: We explicitly don't track the entered action here, because sometimes
532 // SET traps do an implicit GET during their implementation, leading to
533 // spurious assertions.
534 AutoEnterPolicy
*prev
;
535 void recordEnter(JSContext
*cx
, HandleObject proxy
, HandleId id
, Action act
);
538 friend JS_FRIEND_API(void) assertEnteredPolicy(JSContext
*cx
, JSObject
*proxy
, jsid id
, Action act
);
540 inline void recordEnter(JSContext
*cx
, JSObject
*proxy
, jsid id
, Action act
) {}
541 inline void recordLeave() {}
547 class JS_FRIEND_API(AutoWaivePolicy
) : public AutoEnterPolicy
{
549 AutoWaivePolicy(JSContext
*cx
, HandleObject proxy
, HandleId id
,
550 BaseProxyHandler::Action act
)
553 recordEnter(cx
, proxy
, id
, act
);
557 class JS_FRIEND_API(AutoWaivePolicy
) {
559 AutoWaivePolicy(JSContext
*cx
, HandleObject proxy
, HandleId id
,
560 BaseProxyHandler::Action act
)
566 extern JS_FRIEND_API(void)
567 assertEnteredPolicy(JSContext
*cx
, JSObject
*obj
, jsid id
,
568 BaseProxyHandler::Action act
);
570 inline void assertEnteredPolicy(JSContext
*cx
, JSObject
*obj
, jsid id
,
571 BaseProxyHandler::Action act
)
577 extern JS_FRIEND_API(JSObject
*)
578 js_InitProxyClass(JSContext
*cx
, JS::HandleObject obj
);
580 #endif /* jsproxy_h */