1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/dom/bindings/DOMJSClass.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,259 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-*/ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this file, 1.7 + * You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#ifndef mozilla_dom_DOMJSClass_h 1.10 +#define mozilla_dom_DOMJSClass_h 1.11 + 1.12 +#include "jsfriendapi.h" 1.13 +#include "mozilla/Assertions.h" 1.14 + 1.15 +#include "mozilla/dom/PrototypeList.h" // auto-generated 1.16 + 1.17 +#include "mozilla/dom/JSSlots.h" 1.18 + 1.19 +class nsCycleCollectionParticipant; 1.20 + 1.21 +// All DOM globals must have a slot at DOM_PROTOTYPE_SLOT. 1.22 +#define DOM_PROTOTYPE_SLOT JSCLASS_GLOBAL_SLOT_COUNT 1.23 + 1.24 +// Keep this count up to date with any extra global slots added above. 1.25 +#define DOM_GLOBAL_SLOTS 1 1.26 + 1.27 +// We use these flag bits for the new bindings. 1.28 +#define JSCLASS_DOM_GLOBAL JSCLASS_USERBIT1 1.29 +#define JSCLASS_IS_DOMIFACEANDPROTOJSCLASS JSCLASS_USERBIT2 1.30 + 1.31 +namespace mozilla { 1.32 +namespace dom { 1.33 + 1.34 +typedef bool 1.35 +(* ResolveOwnProperty)(JSContext* cx, JS::Handle<JSObject*> wrapper, 1.36 + JS::Handle<JSObject*> obj, JS::Handle<jsid> id, 1.37 + JS::MutableHandle<JSPropertyDescriptor> desc); 1.38 + 1.39 +typedef bool 1.40 +(* EnumerateOwnProperties)(JSContext* cx, JS::Handle<JSObject*> wrapper, 1.41 + JS::Handle<JSObject*> obj, 1.42 + JS::AutoIdVector& props); 1.43 + 1.44 +struct ConstantSpec 1.45 +{ 1.46 + const char* name; 1.47 + JS::Value value; 1.48 +}; 1.49 + 1.50 +typedef bool (*PropertyEnabled)(JSContext* cx, JSObject* global); 1.51 + 1.52 +template<typename T> 1.53 +struct Prefable { 1.54 + inline bool isEnabled(JSContext* cx, JSObject* obj) const { 1.55 + if (!enabled) { 1.56 + return false; 1.57 + } 1.58 + if (!enabledFunc && !availableFunc) { 1.59 + return true; 1.60 + } 1.61 + // Just go ahead and root obj, in case enabledFunc GCs 1.62 + JS::Rooted<JSObject*> rootedObj(cx, obj); 1.63 + if (enabledFunc && 1.64 + !enabledFunc(cx, js::GetGlobalForObjectCrossCompartment(rootedObj))) { 1.65 + return false; 1.66 + } 1.67 + if (availableFunc && 1.68 + !availableFunc(cx, js::GetGlobalForObjectCrossCompartment(rootedObj))) { 1.69 + return false; 1.70 + } 1.71 + return true; 1.72 + } 1.73 + 1.74 + // A boolean indicating whether this set of specs is enabled 1.75 + bool enabled; 1.76 + // A function pointer to a function that can say the property is disabled 1.77 + // even if "enabled" is set to true. If the pointer is null the value of 1.78 + // "enabled" is used as-is unless availableFunc overrides. 1.79 + PropertyEnabled enabledFunc; 1.80 + // A function pointer to a function that can be used to disable a 1.81 + // property even if "enabled" is true and enabledFunc allowed. This 1.82 + // is basically a hack to avoid having to codegen PropertyEnabled 1.83 + // implementations in case when we need to do two separate checks. 1.84 + PropertyEnabled availableFunc; 1.85 + // Array of specs, terminated in whatever way is customary for T. 1.86 + // Null to indicate a end-of-array for Prefable, when such an 1.87 + // indicator is needed. 1.88 + const T* specs; 1.89 +}; 1.90 + 1.91 +struct NativeProperties 1.92 +{ 1.93 + const Prefable<const JSFunctionSpec>* staticMethods; 1.94 + jsid* staticMethodIds; 1.95 + const JSFunctionSpec* staticMethodsSpecs; 1.96 + const Prefable<const JSPropertySpec>* staticAttributes; 1.97 + jsid* staticAttributeIds; 1.98 + const JSPropertySpec* staticAttributeSpecs; 1.99 + const Prefable<const JSFunctionSpec>* methods; 1.100 + jsid* methodIds; 1.101 + const JSFunctionSpec* methodsSpecs; 1.102 + const Prefable<const JSPropertySpec>* attributes; 1.103 + jsid* attributeIds; 1.104 + const JSPropertySpec* attributeSpecs; 1.105 + const Prefable<const JSPropertySpec>* unforgeableAttributes; 1.106 + jsid* unforgeableAttributeIds; 1.107 + const JSPropertySpec* unforgeableAttributeSpecs; 1.108 + const Prefable<const ConstantSpec>* constants; 1.109 + jsid* constantIds; 1.110 + const ConstantSpec* constantSpecs; 1.111 +}; 1.112 + 1.113 +struct NativePropertiesHolder 1.114 +{ 1.115 + const NativeProperties* regular; 1.116 + const NativeProperties* chromeOnly; 1.117 +}; 1.118 + 1.119 +// Helper structure for Xrays for DOM binding objects. The same instance is used 1.120 +// for instances, interface objects and interface prototype objects of a 1.121 +// specific interface. 1.122 +struct NativePropertyHooks 1.123 +{ 1.124 + // The hook to call for resolving indexed or named properties. May be null if 1.125 + // there can't be any. 1.126 + ResolveOwnProperty mResolveOwnProperty; 1.127 + // The hook to call for enumerating indexed or named properties. May be null 1.128 + // if there can't be any. 1.129 + EnumerateOwnProperties mEnumerateOwnProperties; 1.130 + 1.131 + // The property arrays for this interface. 1.132 + NativePropertiesHolder mNativeProperties; 1.133 + 1.134 + // This will be set to the ID of the interface prototype object for the 1.135 + // interface, if it has one. If it doesn't have one it will be set to 1.136 + // prototypes::id::_ID_Count. 1.137 + prototypes::ID mPrototypeID; 1.138 + 1.139 + // This will be set to the ID of the interface object for the interface, if it 1.140 + // has one. If it doesn't have one it will be set to 1.141 + // constructors::id::_ID_Count. 1.142 + constructors::ID mConstructorID; 1.143 + 1.144 + // The NativePropertyHooks instance for the parent interface. 1.145 + const NativePropertyHooks* mProtoHooks; 1.146 +}; 1.147 + 1.148 +enum DOMObjectType { 1.149 + eInstance, 1.150 + eInterface, 1.151 + eInterfacePrototype 1.152 +}; 1.153 + 1.154 +typedef JSObject* (*ParentGetter)(JSContext* aCx, JS::Handle<JSObject*> aObj); 1.155 +/** 1.156 + * Returns a handle to the relevent WebIDL prototype object for the given global 1.157 + * (which may be a handle to null on out of memory). Once allocated, the 1.158 + * prototype object is guaranteed to exist as long as the global does, since the 1.159 + * global traces its array of WebIDL prototypes and constructors. 1.160 + */ 1.161 +typedef JS::Handle<JSObject*> (*ProtoGetter)(JSContext* aCx, 1.162 + JS::Handle<JSObject*> aGlobal); 1.163 + 1.164 +struct DOMClass 1.165 +{ 1.166 + // A list of interfaces that this object implements, in order of decreasing 1.167 + // derivedness. 1.168 + const prototypes::ID mInterfaceChain[MAX_PROTOTYPE_CHAIN_LENGTH]; 1.169 + 1.170 + // We store the DOM object in reserved slot with index DOM_OBJECT_SLOT or in 1.171 + // the proxy private if we use a proxy object. 1.172 + // Sometimes it's an nsISupports and sometimes it's not; this class tells 1.173 + // us which it is. 1.174 + const bool mDOMObjectIsISupports; 1.175 + 1.176 + const NativePropertyHooks* mNativeHooks; 1.177 + 1.178 + ParentGetter mGetParent; 1.179 + ProtoGetter mGetProto; 1.180 + 1.181 + // This stores the CC participant for the native, null if this class is for a 1.182 + // worker or for a native inheriting from nsISupports (we can get the CC 1.183 + // participant by QI'ing in that case). 1.184 + nsCycleCollectionParticipant* mParticipant; 1.185 +}; 1.186 + 1.187 +// Special JSClass for reflected DOM objects. 1.188 +struct DOMJSClass 1.189 +{ 1.190 + // It would be nice to just inherit from JSClass, but that precludes pure 1.191 + // compile-time initialization of the form |DOMJSClass = {...};|, since C++ 1.192 + // only allows brace initialization for aggregate/POD types. 1.193 + const js::Class mBase; 1.194 + 1.195 + const DOMClass mClass; 1.196 + 1.197 + static const DOMJSClass* FromJSClass(const JSClass* base) { 1.198 + MOZ_ASSERT(base->flags & JSCLASS_IS_DOMJSCLASS); 1.199 + return reinterpret_cast<const DOMJSClass*>(base); 1.200 + } 1.201 + 1.202 + static const DOMJSClass* FromJSClass(const js::Class* base) { 1.203 + return FromJSClass(Jsvalify(base)); 1.204 + } 1.205 + 1.206 + const JSClass* ToJSClass() const { return Jsvalify(&mBase); } 1.207 +}; 1.208 + 1.209 +// Special JSClass for DOM interface and interface prototype objects. 1.210 +struct DOMIfaceAndProtoJSClass 1.211 +{ 1.212 + // It would be nice to just inherit from JSClass, but that precludes pure 1.213 + // compile-time initialization of the form 1.214 + // |DOMJSInterfaceAndPrototypeClass = {...};|, since C++ only allows brace 1.215 + // initialization for aggregate/POD types. 1.216 + const JSClass mBase; 1.217 + 1.218 + // Either eInterface or eInterfacePrototype 1.219 + DOMObjectType mType; 1.220 + 1.221 + const NativePropertyHooks* mNativeHooks; 1.222 + 1.223 + // The value to return for toString() on this interface or interface prototype 1.224 + // object. 1.225 + const char* mToString; 1.226 + 1.227 + const prototypes::ID mPrototypeID; 1.228 + const uint32_t mDepth; 1.229 + 1.230 + static const DOMIfaceAndProtoJSClass* FromJSClass(const JSClass* base) { 1.231 + MOZ_ASSERT(base->flags & JSCLASS_IS_DOMIFACEANDPROTOJSCLASS); 1.232 + return reinterpret_cast<const DOMIfaceAndProtoJSClass*>(base); 1.233 + } 1.234 + static const DOMIfaceAndProtoJSClass* FromJSClass(const js::Class* base) { 1.235 + return FromJSClass(Jsvalify(base)); 1.236 + } 1.237 + 1.238 + const JSClass* ToJSClass() const { return &mBase; } 1.239 +}; 1.240 + 1.241 +class ProtoAndIfaceCache; 1.242 + 1.243 +inline bool 1.244 +HasProtoAndIfaceCache(JSObject* global) 1.245 +{ 1.246 + MOZ_ASSERT(js::GetObjectClass(global)->flags & JSCLASS_DOM_GLOBAL); 1.247 + // This can be undefined if we GC while creating the global 1.248 + return !js::GetReservedSlot(global, DOM_PROTOTYPE_SLOT).isUndefined(); 1.249 +} 1.250 + 1.251 +inline ProtoAndIfaceCache* 1.252 +GetProtoAndIfaceCache(JSObject* global) 1.253 +{ 1.254 + MOZ_ASSERT(js::GetObjectClass(global)->flags & JSCLASS_DOM_GLOBAL); 1.255 + return static_cast<ProtoAndIfaceCache*>( 1.256 + js::GetReservedSlot(global, DOM_PROTOTYPE_SLOT).toPrivate()); 1.257 +} 1.258 + 1.259 +} // namespace dom 1.260 +} // namespace mozilla 1.261 + 1.262 +#endif /* mozilla_dom_DOMJSClass_h */