michael@0: /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- michael@0: * vim: set ts=8 sts=4 et sw=4 tw=99: michael@0: * This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #ifndef vm_ProxyObject_h michael@0: #define vm_ProxyObject_h michael@0: michael@0: #include "jsobj.h" michael@0: #include "jsproxy.h" michael@0: michael@0: namespace js { michael@0: michael@0: // This is the base class for the various kinds of proxy objects. It's never michael@0: // instantiated. michael@0: class ProxyObject : public JSObject michael@0: { michael@0: // These are just local renamings of the slot constants that are part of michael@0: // the API in jsproxy.h. michael@0: static const uint32_t PRIVATE_SLOT = PROXY_PRIVATE_SLOT; michael@0: static const uint32_t HANDLER_SLOT = PROXY_HANDLER_SLOT; michael@0: static const uint32_t EXTRA_SLOT = PROXY_EXTRA_SLOT; michael@0: michael@0: public: michael@0: static ProxyObject *New(JSContext *cx, BaseProxyHandler *handler, HandleValue priv, michael@0: TaggedProto proto_, JSObject *parent_, michael@0: const ProxyOptions &options); michael@0: michael@0: const Value &private_() { michael@0: return GetReservedSlot(this, PRIVATE_SLOT); michael@0: } michael@0: michael@0: void initCrossCompartmentPrivate(HandleValue priv); michael@0: michael@0: HeapSlot *slotOfPrivate() { michael@0: return &getReservedSlotRef(PRIVATE_SLOT); michael@0: } michael@0: michael@0: JSObject *target() const { michael@0: return const_cast(this)->private_().toObjectOrNull(); michael@0: } michael@0: michael@0: BaseProxyHandler *handler() { michael@0: return static_cast(GetReservedSlot(this, HANDLER_SLOT).toPrivate()); michael@0: } michael@0: michael@0: void initHandler(BaseProxyHandler *handler); michael@0: michael@0: void setHandler(BaseProxyHandler *handler) { michael@0: SetReservedSlot(this, HANDLER_SLOT, PrivateValue(handler)); michael@0: } michael@0: michael@0: static size_t offsetOfHandler() { michael@0: return getFixedSlotOffset(HANDLER_SLOT); michael@0: } michael@0: michael@0: const Value &extra(size_t n) const { michael@0: JS_ASSERT(n == 0 || n == 1); michael@0: return GetReservedSlot(const_cast(this), EXTRA_SLOT + n); michael@0: } michael@0: michael@0: void setExtra(size_t n, const Value &extra) { michael@0: JS_ASSERT(n == 0 || n == 1); michael@0: SetReservedSlot(this, EXTRA_SLOT + n, extra); michael@0: } michael@0: michael@0: private: michael@0: HeapSlot *slotOfExtra(size_t n) { michael@0: JS_ASSERT(n == 0 || n == 1); michael@0: return &getReservedSlotRef(EXTRA_SLOT + n); michael@0: } michael@0: michael@0: HeapSlot *slotOfClassSpecific(size_t n) { michael@0: JS_ASSERT(n >= PROXY_MINIMUM_SLOTS); michael@0: JS_ASSERT(n < JSCLASS_RESERVED_SLOTS(getClass())); michael@0: return &getReservedSlotRef(n); michael@0: } michael@0: michael@0: static bool isValidProxyClass(const Class *clasp) { michael@0: // Since we can take classes from the outside, make sure that they michael@0: // are "sane". They have to quack enough like proxies for us to belive michael@0: // they should be treated as such. michael@0: michael@0: // proxy_Trace is just a trivial wrapper around ProxyObject::trace for michael@0: // friend api exposure. michael@0: return clasp->isProxy() && michael@0: (clasp->flags & JSCLASS_IMPLEMENTS_BARRIERS) && michael@0: clasp->trace == proxy_Trace && michael@0: JSCLASS_RESERVED_SLOTS(clasp) >= PROXY_MINIMUM_SLOTS; michael@0: } michael@0: michael@0: public: michael@0: static unsigned grayLinkSlot(JSObject *obj); michael@0: michael@0: void renew(JSContext *cx, BaseProxyHandler *handler, Value priv); michael@0: michael@0: static void trace(JSTracer *trc, JSObject *obj); michael@0: michael@0: void nuke(BaseProxyHandler *handler); michael@0: michael@0: static const Class callableClass_; michael@0: static const Class uncallableClass_; michael@0: }; michael@0: michael@0: } // namespace js michael@0: michael@0: // Note: the following |JSObject::is| methods are implemented in terms of michael@0: // the Is*Proxy() friend API functions to ensure the implementations are tied michael@0: // together. The exception is |JSObject::is() michael@0: // const|, which uses the standard template definition, because there is no michael@0: // IsOuterWindowProxy() function in the friend API. michael@0: michael@0: template<> michael@0: inline bool michael@0: JSObject::is() const michael@0: { michael@0: return js::IsProxy(const_cast(this)); michael@0: } michael@0: michael@0: #endif /* vm_ProxyObject_h */