|
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/. */ |
|
6 |
|
7 #ifndef vm_ProxyObject_h |
|
8 #define vm_ProxyObject_h |
|
9 |
|
10 #include "jsobj.h" |
|
11 #include "jsproxy.h" |
|
12 |
|
13 namespace js { |
|
14 |
|
15 // This is the base class for the various kinds of proxy objects. It's never |
|
16 // instantiated. |
|
17 class ProxyObject : public JSObject |
|
18 { |
|
19 // These are just local renamings of the slot constants that are part of |
|
20 // the API in jsproxy.h. |
|
21 static const uint32_t PRIVATE_SLOT = PROXY_PRIVATE_SLOT; |
|
22 static const uint32_t HANDLER_SLOT = PROXY_HANDLER_SLOT; |
|
23 static const uint32_t EXTRA_SLOT = PROXY_EXTRA_SLOT; |
|
24 |
|
25 public: |
|
26 static ProxyObject *New(JSContext *cx, BaseProxyHandler *handler, HandleValue priv, |
|
27 TaggedProto proto_, JSObject *parent_, |
|
28 const ProxyOptions &options); |
|
29 |
|
30 const Value &private_() { |
|
31 return GetReservedSlot(this, PRIVATE_SLOT); |
|
32 } |
|
33 |
|
34 void initCrossCompartmentPrivate(HandleValue priv); |
|
35 |
|
36 HeapSlot *slotOfPrivate() { |
|
37 return &getReservedSlotRef(PRIVATE_SLOT); |
|
38 } |
|
39 |
|
40 JSObject *target() const { |
|
41 return const_cast<ProxyObject*>(this)->private_().toObjectOrNull(); |
|
42 } |
|
43 |
|
44 BaseProxyHandler *handler() { |
|
45 return static_cast<BaseProxyHandler*>(GetReservedSlot(this, HANDLER_SLOT).toPrivate()); |
|
46 } |
|
47 |
|
48 void initHandler(BaseProxyHandler *handler); |
|
49 |
|
50 void setHandler(BaseProxyHandler *handler) { |
|
51 SetReservedSlot(this, HANDLER_SLOT, PrivateValue(handler)); |
|
52 } |
|
53 |
|
54 static size_t offsetOfHandler() { |
|
55 return getFixedSlotOffset(HANDLER_SLOT); |
|
56 } |
|
57 |
|
58 const Value &extra(size_t n) const { |
|
59 JS_ASSERT(n == 0 || n == 1); |
|
60 return GetReservedSlot(const_cast<ProxyObject*>(this), EXTRA_SLOT + n); |
|
61 } |
|
62 |
|
63 void setExtra(size_t n, const Value &extra) { |
|
64 JS_ASSERT(n == 0 || n == 1); |
|
65 SetReservedSlot(this, EXTRA_SLOT + n, extra); |
|
66 } |
|
67 |
|
68 private: |
|
69 HeapSlot *slotOfExtra(size_t n) { |
|
70 JS_ASSERT(n == 0 || n == 1); |
|
71 return &getReservedSlotRef(EXTRA_SLOT + n); |
|
72 } |
|
73 |
|
74 HeapSlot *slotOfClassSpecific(size_t n) { |
|
75 JS_ASSERT(n >= PROXY_MINIMUM_SLOTS); |
|
76 JS_ASSERT(n < JSCLASS_RESERVED_SLOTS(getClass())); |
|
77 return &getReservedSlotRef(n); |
|
78 } |
|
79 |
|
80 static bool isValidProxyClass(const Class *clasp) { |
|
81 // Since we can take classes from the outside, make sure that they |
|
82 // are "sane". They have to quack enough like proxies for us to belive |
|
83 // they should be treated as such. |
|
84 |
|
85 // proxy_Trace is just a trivial wrapper around ProxyObject::trace for |
|
86 // friend api exposure. |
|
87 return clasp->isProxy() && |
|
88 (clasp->flags & JSCLASS_IMPLEMENTS_BARRIERS) && |
|
89 clasp->trace == proxy_Trace && |
|
90 JSCLASS_RESERVED_SLOTS(clasp) >= PROXY_MINIMUM_SLOTS; |
|
91 } |
|
92 |
|
93 public: |
|
94 static unsigned grayLinkSlot(JSObject *obj); |
|
95 |
|
96 void renew(JSContext *cx, BaseProxyHandler *handler, Value priv); |
|
97 |
|
98 static void trace(JSTracer *trc, JSObject *obj); |
|
99 |
|
100 void nuke(BaseProxyHandler *handler); |
|
101 |
|
102 static const Class callableClass_; |
|
103 static const Class uncallableClass_; |
|
104 }; |
|
105 |
|
106 } // namespace js |
|
107 |
|
108 // Note: the following |JSObject::is<T>| methods are implemented in terms of |
|
109 // the Is*Proxy() friend API functions to ensure the implementations are tied |
|
110 // together. The exception is |JSObject::is<js::OuterWindowProxyObject>() |
|
111 // const|, which uses the standard template definition, because there is no |
|
112 // IsOuterWindowProxy() function in the friend API. |
|
113 |
|
114 template<> |
|
115 inline bool |
|
116 JSObject::is<js::ProxyObject>() const |
|
117 { |
|
118 return js::IsProxy(const_cast<JSObject*>(this)); |
|
119 } |
|
120 |
|
121 #endif /* vm_ProxyObject_h */ |