diff --git a/dom/bindings/DOMJSProxyHandler.cpp b/dom/bindings/DOMJSProxyHandler.cpp index 67d4844df323..11ec0fd4bcd7 100644 --- a/dom/bindings/DOMJSProxyHandler.cpp +++ b/dom/bindings/DOMJSProxyHandler.cpp @@ -29,8 +29,7 @@ DefineStaticJSVals(JSContext* cx) return InternJSString(cx, s_length_id, "length"); } - -const char HandlerFamily = 0; +const char DOMProxyHandler::family = 0; js::DOMProxyShadowsResult DOMProxyShadows(JSContext* cx, JS::Handle proxy, JS::Handle id) @@ -60,7 +59,7 @@ DOMProxyShadows(JSContext* cx, JS::Handle proxy, JS::Handle id) struct SetDOMProxyInformation { SetDOMProxyInformation() { - js::SetDOMProxyInformation((const void*) &HandlerFamily, + js::SetDOMProxyInformation((const void*) &DOMProxyHandler::family, js::PROXY_EXTRA_SLOT + JSPROXYSLOT_EXPANDO, DOMProxyShadows); } }; @@ -363,5 +362,25 @@ DOMProxyHandler::setCustom(JSContext* cx, JS::Handle proxy, JS::Handl return true; } +//static +JSObject * +DOMProxyHandler::GetExpandoObject(JSObject *obj) +{ + MOZ_ASSERT(IsDOMProxy(obj), "expected a DOM proxy object"); + JS::Value v = js::GetProxyExtra(obj, JSPROXYSLOT_EXPANDO); + if (v.isObject()) { + return &v.toObject(); + } + + if (v.isUndefined()) { + return nullptr; + } + + js::ExpandoAndGeneration* expandoAndGeneration = + static_cast(v.toPrivate()); + v = expandoAndGeneration->expando; + return v.isUndefined() ? nullptr : &v.toObject(); +} + } // namespace dom } // namespace mozilla diff --git a/dom/bindings/DOMJSProxyHandler.h b/dom/bindings/DOMJSProxyHandler.h index 1dd907edeeec..614a9e47083e 100644 --- a/dom/bindings/DOMJSProxyHandler.h +++ b/dom/bindings/DOMJSProxyHandler.h @@ -24,17 +24,6 @@ enum { template struct Prefable; -// This variable exists solely to provide a unique address for use as an identifier. -extern const char HandlerFamily; -inline const void* ProxyFamily() { return &HandlerFamily; } - -inline bool IsDOMProxy(JSObject *obj) -{ - const js::Class* clasp = js::GetObjectClass(obj); - return clasp->isProxy() && - js::GetProxyHandler(obj)->family() == ProxyFamily(); -} - class BaseDOMProxyHandler : public js::BaseProxyHandler { public: @@ -89,7 +78,7 @@ class DOMProxyHandler : public BaseDOMProxyHandler { public: DOMProxyHandler() - : BaseDOMProxyHandler(ProxyFamily()) + : BaseDOMProxyHandler(&family) { } @@ -121,29 +110,23 @@ public: virtual bool setCustom(JSContext* cx, JS::Handle proxy, JS::Handle id, JS::MutableHandle vp, bool *done) const; - static JSObject* GetExpandoObject(JSObject* obj) - { - MOZ_ASSERT(IsDOMProxy(obj), "expected a DOM proxy object"); - JS::Value v = js::GetProxyExtra(obj, JSPROXYSLOT_EXPANDO); - if (v.isObject()) { - return &v.toObject(); - } + static JSObject* GetExpandoObject(JSObject* obj); - if (v.isUndefined()) { - return nullptr; - } - - js::ExpandoAndGeneration* expandoAndGeneration = - static_cast(v.toPrivate()); - v = expandoAndGeneration->expando; - return v.isUndefined() ? nullptr : &v.toObject(); - } /* GetAndClearExpandoObject does not DROP or clear the preserving wrapper flag. */ static JSObject* GetAndClearExpandoObject(JSObject* obj); static JSObject* EnsureExpandoObject(JSContext* cx, JS::Handle obj); + + static const char family; }; +inline bool IsDOMProxy(JSObject *obj) +{ + const js::Class* clasp = js::GetObjectClass(obj); + return clasp->isProxy() && + js::GetProxyHandler(obj)->family() == &DOMProxyHandler::family; +} + inline const DOMProxyHandler* GetDOMProxyHandler(JSObject* obj) { diff --git a/js/ipc/WrapperOwner.cpp b/js/ipc/WrapperOwner.cpp index 863ca997ff6f..7dc2a4eaf2af 100644 --- a/js/ipc/WrapperOwner.cpp +++ b/js/ipc/WrapperOwner.cpp @@ -45,13 +45,11 @@ WrapperOwner::idOf(JSObject *obj) return objId; } -int sCPOWProxyHandler; - class CPOWProxyHandler : public BaseProxyHandler { public: CPOWProxyHandler() - : BaseProxyHandler(&sCPOWProxyHandler) {} + : BaseProxyHandler(&family) {} virtual ~CPOWProxyHandler() {} virtual bool finalizeInBackground(Value priv) const MOZ_OVERRIDE { @@ -86,9 +84,11 @@ class CPOWProxyHandler : public BaseProxyHandler virtual const char* className(JSContext *cx, HandleObject proxy) const MOZ_OVERRIDE; virtual void finalize(JSFreeOp *fop, JSObject *proxy) const MOZ_OVERRIDE; + static const char family; static const CPOWProxyHandler singleton; }; +const char CPOWProxyHandler::family = 0; const CPOWProxyHandler CPOWProxyHandler::singleton; #define FORWARD(call, args) \ diff --git a/js/src/jsfriendapi.cpp b/js/src/jsfriendapi.cpp index f1aa8426c346..e8e05cdb574e 100644 --- a/js/src/jsfriendapi.cpp +++ b/js/src/jsfriendapi.cpp @@ -601,7 +601,7 @@ JS_IsDeadWrapper(JSObject *obj) return false; } - return obj->as().handler()->family() == &DeadObjectProxy::sDeadObjectFamily; + return obj->as().handler()->family() == &DeadObjectProxy::family; } void diff --git a/js/src/jsproxy.cpp b/js/src/jsproxy.cpp index ae6429fd7be2..12889a1f9ab6 100644 --- a/js/src/jsproxy.cpp +++ b/js/src/jsproxy.cpp @@ -797,6 +797,7 @@ class ScriptedIndirectProxyHandler : public BaseProxyHandler virtual JSString *fun_toString(JSContext *cx, HandleObject proxy, unsigned indent) const MOZ_OVERRIDE; virtual bool isScripted() const MOZ_OVERRIDE { return true; } + static const char family; static const ScriptedIndirectProxyHandler singleton; }; @@ -818,10 +819,10 @@ static const Class CallConstructHolder = { } /* anonymous namespace */ // This variable exists solely to provide a unique address for use as an identifier. -static const char sScriptedIndirectProxyHandlerFamily = 0; +const char ScriptedIndirectProxyHandler::family = 0; ScriptedIndirectProxyHandler::ScriptedIndirectProxyHandler() - : BaseProxyHandler(&sScriptedIndirectProxyHandlerFamily) + : BaseProxyHandler(&family) { } @@ -1118,6 +1119,7 @@ class ScriptedDirectProxyHandler : public DirectProxyHandler { virtual bool construct(JSContext *cx, HandleObject proxy, const CallArgs &args) const MOZ_OVERRIDE; virtual bool isScripted() const MOZ_OVERRIDE { return true; } + static const char family; static const ScriptedDirectProxyHandler singleton; // The "proxy extra" slot index in which the handler is stored. Revocable proxies need to set @@ -1128,9 +1130,6 @@ class ScriptedDirectProxyHandler : public DirectProxyHandler { static const int REVOKE_SLOT = 0; }; -// This variable exists solely to provide a unique address for use as an identifier. -static const char sScriptedDirectProxyHandlerFamily = 0; - static inline bool IsDataDescriptor(const PropertyDescriptor &desc) { @@ -1389,7 +1388,7 @@ ArrayToIdVector(JSContext *cx, HandleObject proxy, HandleObject target, HandleVa } ScriptedDirectProxyHandler::ScriptedDirectProxyHandler() - : DirectProxyHandler(&sScriptedDirectProxyHandlerFamily) + : DirectProxyHandler(&family) { } @@ -2208,6 +2207,7 @@ ScriptedDirectProxyHandler::construct(JSContext *cx, HandleObject proxy, const C return true; } +const char ScriptedDirectProxyHandler::family = 0; const ScriptedDirectProxyHandler ScriptedDirectProxyHandler::singleton; #define INVOKE_ON_PROTOTYPE(cx, handler, proxy, protoCall) \ diff --git a/js/src/jsproxy.h b/js/src/jsproxy.h index dda92b6b5550..803a9dd14c88 100644 --- a/js/src/jsproxy.h +++ b/js/src/jsproxy.h @@ -87,6 +87,14 @@ class JS_FRIEND_API(Wrapper); */ class JS_FRIEND_API(BaseProxyHandler) { + /* + * Sometimes it's desirable to designate groups of proxy handlers as "similar". + * For this, we use the notion of a "family": A consumer-provided opaque pointer + * that designates the larger group to which this proxy belongs. + * + * If it will never be important to differentiate this proxy from others as + * part of a distinct group, nullptr may be used instead. + */ const void *mFamily; /* diff --git a/js/src/jswrapper.cpp b/js/src/jswrapper.cpp index 3750043d4679..dc9935190c0f 100644 --- a/js/src/jswrapper.cpp +++ b/js/src/jswrapper.cpp @@ -20,8 +20,6 @@ using namespace js; using namespace js::gc; -const char js::sWrapperFamily = 0; - /* * Wrapper forwards this call directly to the wrapped object for efficiency * and transparency. In particular, the hint is needed to properly stringify @@ -131,7 +129,7 @@ js::IsCrossCompartmentWrapper(JSObject *obj) } Wrapper::Wrapper(unsigned flags, bool hasPrototype, bool hasSecurityPolicy) - : DirectProxyHandler(&sWrapperFamily, hasPrototype, hasSecurityPolicy), + : DirectProxyHandler(&family, hasPrototype, hasSecurityPolicy), mFlags(flags) { } @@ -140,6 +138,7 @@ Wrapper::~Wrapper() { } +const char Wrapper::family = 0; const Wrapper Wrapper::singleton((unsigned)0); const Wrapper Wrapper::singletonWithPrototype((unsigned)0, true); JSObject *Wrapper::defaultProto = TaggedProto::LazyProto; @@ -748,7 +747,7 @@ template class js::SecurityWrapper; template class js::SecurityWrapper; DeadObjectProxy::DeadObjectProxy() - : BaseProxyHandler(&sDeadObjectFamily) + : BaseProxyHandler(&family) { } @@ -885,8 +884,8 @@ DeadObjectProxy::getPrototypeOf(JSContext *cx, HandleObject proxy, MutableHandle return true; } +const char DeadObjectProxy::family = 0; const DeadObjectProxy DeadObjectProxy::singleton; -const char DeadObjectProxy::sDeadObjectFamily = 0; bool js::IsDeadProxyObject(JSObject *obj) diff --git a/js/src/jswrapper.h b/js/src/jswrapper.h index 8f3676a48bc6..fef04263bdca 100644 --- a/js/src/jswrapper.h +++ b/js/src/jswrapper.h @@ -87,6 +87,7 @@ class JS_FRIEND_API(Wrapper) : public DirectProxyHandler virtual bool finalizeInBackground(Value priv) const MOZ_OVERRIDE; + static const char family; static const Wrapper singleton; static const Wrapper singletonWithPrototype; @@ -207,9 +208,6 @@ typedef SecurityWrapper CrossCompartmentSecurityWrapper class JS_FRIEND_API(DeadObjectProxy) : public BaseProxyHandler { public: - // This variable exists solely to provide a unique address for use as an identifier. - static const char sDeadObjectFamily; - explicit DeadObjectProxy(); /* ES5 Harmony fundamental wrapper traps. */ @@ -243,6 +241,7 @@ class JS_FRIEND_API(DeadObjectProxy) : public BaseProxyHandler virtual bool getPrototypeOf(JSContext *cx, HandleObject proxy, MutableHandleObject protop) const MOZ_OVERRIDE; + static const char family; static const DeadObjectProxy singleton; }; @@ -250,15 +249,10 @@ extern JSObject * TransparentObjectWrapper(JSContext *cx, HandleObject existing, HandleObject obj, HandleObject parent); -// Proxy family for wrappers. Public so that IsWrapper() can be fully inlined by -// jsfriendapi users. -// This variable exists solely to provide a unique address for use as an identifier. -extern JS_FRIEND_DATA(const char) sWrapperFamily; - inline bool IsWrapper(JSObject *obj) { - return IsProxy(obj) && GetProxyHandler(obj)->family() == &sWrapperFamily; + return IsProxy(obj) && GetProxyHandler(obj)->family() == &Wrapper::family; } // Given a JSObject, returns that object stripped of wrappers. If diff --git a/js/src/vm/ScopeObject.cpp b/js/src/vm/ScopeObject.cpp index 5fe614acb05f..06f551eb15a4 100644 --- a/js/src/vm/ScopeObject.cpp +++ b/js/src/vm/ScopeObject.cpp @@ -1323,7 +1323,7 @@ class DebugScopeProxy : public BaseProxyHandler } public: - static int family; + static const char family; static const DebugScopeProxy singleton; DebugScopeProxy() : BaseProxyHandler(&family) {} @@ -1592,7 +1592,7 @@ class DebugScopeProxy : public BaseProxyHandler } /* anonymous namespace */ -int DebugScopeProxy::family = 0; +const char DebugScopeProxy::family = 0; const DebugScopeProxy DebugScopeProxy::singleton; /* static */ DebugScopeObject *