Bumping manifests a=b2g-bump
[gecko.git] / dom / bindings / DOMJSProxyHandler.h
bloba17dbafd9b136c7e117824a5be93a192e1fafd0f
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-*/
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
4 * You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #ifndef mozilla_dom_DOMJSProxyHandler_h
7 #define mozilla_dom_DOMJSProxyHandler_h
9 #include "mozilla/Attributes.h"
10 #include "mozilla/Likely.h"
12 #include "jsapi.h"
13 #include "jsproxy.h"
14 #include "nsString.h"
16 #define DOM_PROXY_OBJECT_SLOT js::PROXY_PRIVATE_SLOT
18 namespace mozilla {
19 namespace dom {
21 enum {
22 /**
23 * DOM proxies have an extra slot for the expando object at index
24 * JSPROXYSLOT_EXPANDO.
26 * The expando object is a plain JSObject whose properties correspond to
27 * "expandos" (custom properties set by the script author).
29 * The exact value stored in the JSPROXYSLOT_EXPANDO slot depends on whether
30 * the interface is annotated with the [OverrideBuiltins] extended attribute.
32 * If it is, the proxy is initialized with a PrivateValue, which contains a
33 * pointer to a js::ExpandoAndGeneration object; this contains a pointer to
34 * the actual expando object as well as the "generation" of the object.
36 * If it is not, the proxy is initialized with an UndefinedValue. In
37 * EnsureExpandoObject, it is set to an ObjectValue that points to the
38 * expando object directly. (It is set back to an UndefinedValue only when
39 * the object is about to die.)
41 JSPROXYSLOT_EXPANDO = 0
44 template<typename T> struct Prefable;
46 class BaseDOMProxyHandler : public js::BaseProxyHandler
48 public:
49 explicit MOZ_CONSTEXPR BaseDOMProxyHandler(const void* aProxyFamily, bool aHasPrototype = false)
50 : js::BaseProxyHandler(aProxyFamily, aHasPrototype)
53 // Implementations of methods that can be implemented in terms of
54 // other lower-level methods.
55 bool getOwnPropertyDescriptor(JSContext* cx, JS::Handle<JSObject*> proxy,
56 JS::Handle<jsid> id,
57 JS::MutableHandle<JSPropertyDescriptor> desc) const MOZ_OVERRIDE;
58 virtual bool ownPropertyKeys(JSContext* cx, JS::Handle<JSObject*> proxy,
59 JS::AutoIdVector &props) const MOZ_OVERRIDE;
61 bool getPropertyDescriptor(JSContext* cx, JS::Handle<JSObject*> proxy,
62 JS::Handle<jsid> id,
63 JS::MutableHandle<JSPropertyDescriptor> desc) const MOZ_OVERRIDE;
65 virtual bool enumerate(JSContext *cx, JS::Handle<JSObject*> proxy,
66 JS::MutableHandle<JSObject*> objp) const MOZ_OVERRIDE;
68 // We override getOwnEnumerablePropertyKeys() and implement it directly
69 // instead of using the default implementation, which would call
70 // ownPropertyKeys and then filter out the non-enumerable ones. This avoids
71 // unnecessary work during enumeration.
72 virtual bool getOwnEnumerablePropertyKeys(JSContext* cx, JS::Handle<JSObject*> proxy,
73 JS::AutoIdVector &props) const MOZ_OVERRIDE;
75 bool watch(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id,
76 JS::Handle<JSObject*> callable) const MOZ_OVERRIDE;
77 bool unwatch(JSContext* cx, JS::Handle<JSObject*> proxy,
78 JS::Handle<jsid> id) const MOZ_OVERRIDE;
80 protected:
81 // Hook for subclasses to implement shared ownPropertyKeys()/keys()
82 // functionality. The "flags" argument is either JSITER_OWNONLY (for keys())
83 // or JSITER_OWNONLY | JSITER_HIDDEN | JSITER_SYMBOLS (for
84 // ownPropertyKeys()).
85 virtual bool ownPropNames(JSContext* cx, JS::Handle<JSObject*> proxy,
86 unsigned flags,
87 JS::AutoIdVector& props) const = 0;
89 // Hook for subclasses to allow set() to ignore named props while other things
90 // that look at property descriptors see them. This is intentionally not
91 // named getOwnPropertyDescriptor to avoid subclasses that override it hiding
92 // our public getOwnPropertyDescriptor.
93 virtual bool getOwnPropDescriptor(JSContext* cx,
94 JS::Handle<JSObject*> proxy,
95 JS::Handle<jsid> id,
96 bool ignoreNamedProps,
97 JS::MutableHandle<JSPropertyDescriptor> desc) const = 0;
100 class DOMProxyHandler : public BaseDOMProxyHandler
102 public:
103 MOZ_CONSTEXPR DOMProxyHandler()
104 : BaseDOMProxyHandler(&family)
107 bool defineProperty(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id,
108 JS::MutableHandle<JSPropertyDescriptor> desc) const MOZ_OVERRIDE
110 bool unused;
111 return defineProperty(cx, proxy, id, desc, &unused);
113 virtual bool defineProperty(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id,
114 JS::MutableHandle<JSPropertyDescriptor> desc, bool* defined)
115 const;
116 bool delete_(JSContext* cx, JS::Handle<JSObject*> proxy,
117 JS::Handle<jsid> id, bool* bp) const MOZ_OVERRIDE;
118 bool preventExtensions(JSContext *cx, JS::Handle<JSObject*> proxy,
119 bool *succeeded) const MOZ_OVERRIDE;
120 bool isExtensible(JSContext *cx, JS::Handle<JSObject*> proxy, bool *extensible)
121 const MOZ_OVERRIDE;
122 bool has(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id,
123 bool* bp) const MOZ_OVERRIDE;
124 bool set(JSContext *cx, JS::Handle<JSObject*> proxy, JS::Handle<JSObject*> receiver,
125 JS::Handle<jsid> id, bool strict, JS::MutableHandle<JS::Value> vp)
126 const MOZ_OVERRIDE;
129 * If assigning to proxy[id] hits a named setter with OverrideBuiltins or
130 * an indexed setter, call it and set *done to true on success. Otherwise, set
131 * *done to false.
133 virtual bool setCustom(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id,
134 JS::MutableHandle<JS::Value> vp, bool *done) const;
136 static JSObject* GetExpandoObject(JSObject* obj);
138 /* GetAndClearExpandoObject does not DROP or clear the preserving wrapper flag. */
139 static JSObject* GetAndClearExpandoObject(JSObject* obj);
140 static JSObject* EnsureExpandoObject(JSContext* cx,
141 JS::Handle<JSObject*> obj);
143 static const char family;
146 inline bool IsDOMProxy(JSObject *obj)
148 const js::Class* clasp = js::GetObjectClass(obj);
149 return clasp->isProxy() &&
150 js::GetProxyHandler(obj)->family() == &DOMProxyHandler::family;
153 inline const DOMProxyHandler*
154 GetDOMProxyHandler(JSObject* obj)
156 MOZ_ASSERT(IsDOMProxy(obj));
157 return static_cast<const DOMProxyHandler*>(js::GetProxyHandler(obj));
160 extern jsid s_length_id;
162 int32_t IdToInt32(JSContext* cx, JS::Handle<jsid> id);
164 // XXXbz this should really return uint32_t, with the maximum value
165 // meaning "not an index"...
166 inline int32_t
167 GetArrayIndexFromId(JSContext* cx, JS::Handle<jsid> id)
169 if (MOZ_LIKELY(JSID_IS_INT(id))) {
170 return JSID_TO_INT(id);
172 if (MOZ_LIKELY(id == s_length_id)) {
173 return -1;
175 if (MOZ_LIKELY(JSID_IS_ATOM(id))) {
176 JSAtom* atom = JSID_TO_ATOM(id);
177 char16_t s;
179 JS::AutoCheckCannotGC nogc;
180 if (js::AtomHasLatin1Chars(atom)) {
181 s = *js::GetLatin1AtomChars(nogc, atom);
182 } else {
183 s = *js::GetTwoByteAtomChars(nogc, atom);
186 if (MOZ_LIKELY((unsigned)s >= 'a' && (unsigned)s <= 'z'))
187 return -1;
189 uint32_t i;
190 JSLinearString* str = js::AtomToLinearString(JSID_TO_ATOM(id));
191 return js::StringIsArrayIndex(str, &i) ? i : -1;
193 return IdToInt32(cx, id);
196 inline bool
197 IsArrayIndex(int32_t index)
199 return index >= 0;
202 inline void
203 FillPropertyDescriptor(JS::MutableHandle<JSPropertyDescriptor> desc,
204 JSObject* obj, bool readonly, bool enumerable = true)
206 desc.object().set(obj);
207 desc.setAttributes((readonly ? JSPROP_READONLY : 0) |
208 (enumerable ? JSPROP_ENUMERATE : 0));
209 desc.setGetter(nullptr);
210 desc.setSetter(nullptr);
213 inline void
214 FillPropertyDescriptor(JS::MutableHandle<JSPropertyDescriptor> desc,
215 JSObject* obj, JS::Value v,
216 bool readonly, bool enumerable = true)
218 desc.value().set(v);
219 FillPropertyDescriptor(desc, obj, readonly, enumerable);
222 inline void
223 FillPropertyDescriptor(JS::MutableHandle<JSPropertyDescriptor> desc,
224 JSObject* obj, unsigned attributes, JS::Value v)
226 desc.object().set(obj);
227 desc.value().set(v);
228 desc.setAttributes(attributes);
229 desc.setGetter(nullptr);
230 desc.setSetter(nullptr);
233 } // namespace dom
234 } // namespace mozilla
236 #endif /* mozilla_dom_DOMProxyHandler_h */