|
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/. */ |
|
5 |
|
6 #ifndef mozilla_dom_DOMJSClass_h |
|
7 #define mozilla_dom_DOMJSClass_h |
|
8 |
|
9 #include "jsfriendapi.h" |
|
10 #include "mozilla/Assertions.h" |
|
11 |
|
12 #include "mozilla/dom/PrototypeList.h" // auto-generated |
|
13 |
|
14 #include "mozilla/dom/JSSlots.h" |
|
15 |
|
16 class nsCycleCollectionParticipant; |
|
17 |
|
18 // All DOM globals must have a slot at DOM_PROTOTYPE_SLOT. |
|
19 #define DOM_PROTOTYPE_SLOT JSCLASS_GLOBAL_SLOT_COUNT |
|
20 |
|
21 // Keep this count up to date with any extra global slots added above. |
|
22 #define DOM_GLOBAL_SLOTS 1 |
|
23 |
|
24 // We use these flag bits for the new bindings. |
|
25 #define JSCLASS_DOM_GLOBAL JSCLASS_USERBIT1 |
|
26 #define JSCLASS_IS_DOMIFACEANDPROTOJSCLASS JSCLASS_USERBIT2 |
|
27 |
|
28 namespace mozilla { |
|
29 namespace dom { |
|
30 |
|
31 typedef bool |
|
32 (* ResolveOwnProperty)(JSContext* cx, JS::Handle<JSObject*> wrapper, |
|
33 JS::Handle<JSObject*> obj, JS::Handle<jsid> id, |
|
34 JS::MutableHandle<JSPropertyDescriptor> desc); |
|
35 |
|
36 typedef bool |
|
37 (* EnumerateOwnProperties)(JSContext* cx, JS::Handle<JSObject*> wrapper, |
|
38 JS::Handle<JSObject*> obj, |
|
39 JS::AutoIdVector& props); |
|
40 |
|
41 struct ConstantSpec |
|
42 { |
|
43 const char* name; |
|
44 JS::Value value; |
|
45 }; |
|
46 |
|
47 typedef bool (*PropertyEnabled)(JSContext* cx, JSObject* global); |
|
48 |
|
49 template<typename T> |
|
50 struct Prefable { |
|
51 inline bool isEnabled(JSContext* cx, JSObject* obj) const { |
|
52 if (!enabled) { |
|
53 return false; |
|
54 } |
|
55 if (!enabledFunc && !availableFunc) { |
|
56 return true; |
|
57 } |
|
58 // Just go ahead and root obj, in case enabledFunc GCs |
|
59 JS::Rooted<JSObject*> rootedObj(cx, obj); |
|
60 if (enabledFunc && |
|
61 !enabledFunc(cx, js::GetGlobalForObjectCrossCompartment(rootedObj))) { |
|
62 return false; |
|
63 } |
|
64 if (availableFunc && |
|
65 !availableFunc(cx, js::GetGlobalForObjectCrossCompartment(rootedObj))) { |
|
66 return false; |
|
67 } |
|
68 return true; |
|
69 } |
|
70 |
|
71 // A boolean indicating whether this set of specs is enabled |
|
72 bool enabled; |
|
73 // A function pointer to a function that can say the property is disabled |
|
74 // even if "enabled" is set to true. If the pointer is null the value of |
|
75 // "enabled" is used as-is unless availableFunc overrides. |
|
76 PropertyEnabled enabledFunc; |
|
77 // A function pointer to a function that can be used to disable a |
|
78 // property even if "enabled" is true and enabledFunc allowed. This |
|
79 // is basically a hack to avoid having to codegen PropertyEnabled |
|
80 // implementations in case when we need to do two separate checks. |
|
81 PropertyEnabled availableFunc; |
|
82 // Array of specs, terminated in whatever way is customary for T. |
|
83 // Null to indicate a end-of-array for Prefable, when such an |
|
84 // indicator is needed. |
|
85 const T* specs; |
|
86 }; |
|
87 |
|
88 struct NativeProperties |
|
89 { |
|
90 const Prefable<const JSFunctionSpec>* staticMethods; |
|
91 jsid* staticMethodIds; |
|
92 const JSFunctionSpec* staticMethodsSpecs; |
|
93 const Prefable<const JSPropertySpec>* staticAttributes; |
|
94 jsid* staticAttributeIds; |
|
95 const JSPropertySpec* staticAttributeSpecs; |
|
96 const Prefable<const JSFunctionSpec>* methods; |
|
97 jsid* methodIds; |
|
98 const JSFunctionSpec* methodsSpecs; |
|
99 const Prefable<const JSPropertySpec>* attributes; |
|
100 jsid* attributeIds; |
|
101 const JSPropertySpec* attributeSpecs; |
|
102 const Prefable<const JSPropertySpec>* unforgeableAttributes; |
|
103 jsid* unforgeableAttributeIds; |
|
104 const JSPropertySpec* unforgeableAttributeSpecs; |
|
105 const Prefable<const ConstantSpec>* constants; |
|
106 jsid* constantIds; |
|
107 const ConstantSpec* constantSpecs; |
|
108 }; |
|
109 |
|
110 struct NativePropertiesHolder |
|
111 { |
|
112 const NativeProperties* regular; |
|
113 const NativeProperties* chromeOnly; |
|
114 }; |
|
115 |
|
116 // Helper structure for Xrays for DOM binding objects. The same instance is used |
|
117 // for instances, interface objects and interface prototype objects of a |
|
118 // specific interface. |
|
119 struct NativePropertyHooks |
|
120 { |
|
121 // The hook to call for resolving indexed or named properties. May be null if |
|
122 // there can't be any. |
|
123 ResolveOwnProperty mResolveOwnProperty; |
|
124 // The hook to call for enumerating indexed or named properties. May be null |
|
125 // if there can't be any. |
|
126 EnumerateOwnProperties mEnumerateOwnProperties; |
|
127 |
|
128 // The property arrays for this interface. |
|
129 NativePropertiesHolder mNativeProperties; |
|
130 |
|
131 // This will be set to the ID of the interface prototype object for the |
|
132 // interface, if it has one. If it doesn't have one it will be set to |
|
133 // prototypes::id::_ID_Count. |
|
134 prototypes::ID mPrototypeID; |
|
135 |
|
136 // This will be set to the ID of the interface object for the interface, if it |
|
137 // has one. If it doesn't have one it will be set to |
|
138 // constructors::id::_ID_Count. |
|
139 constructors::ID mConstructorID; |
|
140 |
|
141 // The NativePropertyHooks instance for the parent interface. |
|
142 const NativePropertyHooks* mProtoHooks; |
|
143 }; |
|
144 |
|
145 enum DOMObjectType { |
|
146 eInstance, |
|
147 eInterface, |
|
148 eInterfacePrototype |
|
149 }; |
|
150 |
|
151 typedef JSObject* (*ParentGetter)(JSContext* aCx, JS::Handle<JSObject*> aObj); |
|
152 /** |
|
153 * Returns a handle to the relevent WebIDL prototype object for the given global |
|
154 * (which may be a handle to null on out of memory). Once allocated, the |
|
155 * prototype object is guaranteed to exist as long as the global does, since the |
|
156 * global traces its array of WebIDL prototypes and constructors. |
|
157 */ |
|
158 typedef JS::Handle<JSObject*> (*ProtoGetter)(JSContext* aCx, |
|
159 JS::Handle<JSObject*> aGlobal); |
|
160 |
|
161 struct DOMClass |
|
162 { |
|
163 // A list of interfaces that this object implements, in order of decreasing |
|
164 // derivedness. |
|
165 const prototypes::ID mInterfaceChain[MAX_PROTOTYPE_CHAIN_LENGTH]; |
|
166 |
|
167 // We store the DOM object in reserved slot with index DOM_OBJECT_SLOT or in |
|
168 // the proxy private if we use a proxy object. |
|
169 // Sometimes it's an nsISupports and sometimes it's not; this class tells |
|
170 // us which it is. |
|
171 const bool mDOMObjectIsISupports; |
|
172 |
|
173 const NativePropertyHooks* mNativeHooks; |
|
174 |
|
175 ParentGetter mGetParent; |
|
176 ProtoGetter mGetProto; |
|
177 |
|
178 // This stores the CC participant for the native, null if this class is for a |
|
179 // worker or for a native inheriting from nsISupports (we can get the CC |
|
180 // participant by QI'ing in that case). |
|
181 nsCycleCollectionParticipant* mParticipant; |
|
182 }; |
|
183 |
|
184 // Special JSClass for reflected DOM objects. |
|
185 struct DOMJSClass |
|
186 { |
|
187 // It would be nice to just inherit from JSClass, but that precludes pure |
|
188 // compile-time initialization of the form |DOMJSClass = {...};|, since C++ |
|
189 // only allows brace initialization for aggregate/POD types. |
|
190 const js::Class mBase; |
|
191 |
|
192 const DOMClass mClass; |
|
193 |
|
194 static const DOMJSClass* FromJSClass(const JSClass* base) { |
|
195 MOZ_ASSERT(base->flags & JSCLASS_IS_DOMJSCLASS); |
|
196 return reinterpret_cast<const DOMJSClass*>(base); |
|
197 } |
|
198 |
|
199 static const DOMJSClass* FromJSClass(const js::Class* base) { |
|
200 return FromJSClass(Jsvalify(base)); |
|
201 } |
|
202 |
|
203 const JSClass* ToJSClass() const { return Jsvalify(&mBase); } |
|
204 }; |
|
205 |
|
206 // Special JSClass for DOM interface and interface prototype objects. |
|
207 struct DOMIfaceAndProtoJSClass |
|
208 { |
|
209 // It would be nice to just inherit from JSClass, but that precludes pure |
|
210 // compile-time initialization of the form |
|
211 // |DOMJSInterfaceAndPrototypeClass = {...};|, since C++ only allows brace |
|
212 // initialization for aggregate/POD types. |
|
213 const JSClass mBase; |
|
214 |
|
215 // Either eInterface or eInterfacePrototype |
|
216 DOMObjectType mType; |
|
217 |
|
218 const NativePropertyHooks* mNativeHooks; |
|
219 |
|
220 // The value to return for toString() on this interface or interface prototype |
|
221 // object. |
|
222 const char* mToString; |
|
223 |
|
224 const prototypes::ID mPrototypeID; |
|
225 const uint32_t mDepth; |
|
226 |
|
227 static const DOMIfaceAndProtoJSClass* FromJSClass(const JSClass* base) { |
|
228 MOZ_ASSERT(base->flags & JSCLASS_IS_DOMIFACEANDPROTOJSCLASS); |
|
229 return reinterpret_cast<const DOMIfaceAndProtoJSClass*>(base); |
|
230 } |
|
231 static const DOMIfaceAndProtoJSClass* FromJSClass(const js::Class* base) { |
|
232 return FromJSClass(Jsvalify(base)); |
|
233 } |
|
234 |
|
235 const JSClass* ToJSClass() const { return &mBase; } |
|
236 }; |
|
237 |
|
238 class ProtoAndIfaceCache; |
|
239 |
|
240 inline bool |
|
241 HasProtoAndIfaceCache(JSObject* global) |
|
242 { |
|
243 MOZ_ASSERT(js::GetObjectClass(global)->flags & JSCLASS_DOM_GLOBAL); |
|
244 // This can be undefined if we GC while creating the global |
|
245 return !js::GetReservedSlot(global, DOM_PROTOTYPE_SLOT).isUndefined(); |
|
246 } |
|
247 |
|
248 inline ProtoAndIfaceCache* |
|
249 GetProtoAndIfaceCache(JSObject* global) |
|
250 { |
|
251 MOZ_ASSERT(js::GetObjectClass(global)->flags & JSCLASS_DOM_GLOBAL); |
|
252 return static_cast<ProtoAndIfaceCache*>( |
|
253 js::GetReservedSlot(global, DOM_PROTOTYPE_SLOT).toPrivate()); |
|
254 } |
|
255 |
|
256 } // namespace dom |
|
257 } // namespace mozilla |
|
258 |
|
259 #endif /* mozilla_dom_DOMJSClass_h */ |