/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-*/ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef mozilla_dom_DOMJSClass_h #define mozilla_dom_DOMJSClass_h #include "jsapi.h" #include "jsfriendapi.h" #include "mozilla/dom/PrototypeList.h" // auto-generated class nsCycleCollectionParticipant; // We use slot 0 for holding the raw object. This is safe for both // globals and non-globals. #define DOM_OBJECT_SLOT 0 // We use slot 1 for holding the expando object. This is not safe for globals // until bug 760095 is fixed, so that bug blocks converting Window to new // bindings. #define DOM_XRAY_EXPANDO_SLOT 1 // All DOM globals must have a slot at DOM_PROTOTYPE_SLOT. #define DOM_PROTOTYPE_SLOT JSCLASS_GLOBAL_SLOT_COUNT // We use these flag bits for the new bindings. #define JSCLASS_DOM_GLOBAL JSCLASS_USERBIT1 // NOTE: This is baked into the Ion JIT as 0 in codegen for LGetDOMProperty and // LSetDOMProperty. Those constants need to be changed accordingly if this value // changes. #define DOM_PROTO_INSTANCE_CLASS_SLOT 0 namespace mozilla { namespace dom { typedef bool (* ResolveProperty)(JSContext* cx, JSObject* wrapper, jsid id, bool set, JSPropertyDescriptor* desc); typedef bool (* EnumerateProperties)(JSContext* cx, JSObject* wrapper, JS::AutoIdVector& props); struct ConstantSpec { const char* name; JS::Value value; }; template struct Prefable { // A boolean indicating whether this set of specs is enabled bool enabled; // Array of specs, terminated in whatever way is customary for T. // Null to indicate a end-of-array for Prefable, when such an // indicator is needed. T* specs; }; struct NativeProperties { Prefable* staticMethods; jsid* staticMethodIds; JSFunctionSpec* staticMethodsSpecs; Prefable* methods; jsid* methodIds; JSFunctionSpec* methodsSpecs; Prefable* attributes; jsid* attributeIds; JSPropertySpec* attributeSpecs; Prefable* unforgeableAttributes; jsid* unforgeableAttributeIds; JSPropertySpec* unforgeableAttributeSpecs; Prefable* constants; jsid* constantIds; ConstantSpec* constantSpecs; }; struct NativePropertyHooks { ResolveProperty mResolveOwnProperty; ResolveProperty mResolveProperty; EnumerateProperties mEnumerateOwnProperties; EnumerateProperties mEnumerateProperties; const NativePropertyHooks *mProtoHooks; }; struct DOMClass { // A list of interfaces that this object implements, in order of decreasing // derivedness. const prototypes::ID mInterfaceChain[prototypes::id::_ID_Count]; // We store the DOM object in reserved slot with index DOM_OBJECT_SLOT or in // the proxy private if we use a proxy object. // Sometimes it's an nsISupports and sometimes it's not; this class tells // us which it is. const bool mDOMObjectIsISupports; const NativePropertyHooks* mNativeHooks; // This stores the CC participant for the native, null if this class is for a // worker or for a native inheriting from nsISupports (we can get the CC // participant by QI'ing in that case). nsCycleCollectionParticipant* mParticipant; }; // Special JSClass for reflected DOM objects. struct DOMJSClass { // It would be nice to just inherit from JSClass, but that precludes pure // compile-time initialization of the form |DOMJSClass = {...};|, since C++ // only allows brace initialization for aggregate/POD types. JSClass mBase; DOMClass mClass; static DOMJSClass* FromJSClass(JSClass* base) { MOZ_ASSERT(base->flags & JSCLASS_IS_DOMJSCLASS); return reinterpret_cast(base); } static const DOMJSClass* FromJSClass(const JSClass* base) { MOZ_ASSERT(base->flags & JSCLASS_IS_DOMJSCLASS); return reinterpret_cast(base); } static DOMJSClass* FromJSClass(js::Class* base) { return FromJSClass(Jsvalify(base)); } static const DOMJSClass* FromJSClass(const js::Class* base) { return FromJSClass(Jsvalify(base)); } JSClass* ToJSClass() { return &mBase; } }; inline bool HasProtoAndIfaceArray(JSObject* global) { MOZ_ASSERT(js::GetObjectClass(global)->flags & JSCLASS_DOM_GLOBAL); // This can be undefined if we GC while creating the global return !js::GetReservedSlot(global, DOM_PROTOTYPE_SLOT).isUndefined(); } inline JSObject** GetProtoAndIfaceArray(JSObject* global) { MOZ_ASSERT(js::GetObjectClass(global)->flags & JSCLASS_DOM_GLOBAL); return static_cast( js::GetReservedSlot(global, DOM_PROTOTYPE_SLOT).toPrivate()); } } // namespace dom } // namespace mozilla #endif /* mozilla_dom_DOMJSClass_h */