Bug 1027964 - Standardize proxy handler families. (r=jorendorff)

This commit is contained in:
Eric Faust
2014-08-27 17:09:06 -07:00
parent 80ce7025dd
commit eb76d911cb
9 changed files with 60 additions and 57 deletions

View File

@@ -29,8 +29,7 @@ DefineStaticJSVals(JSContext* cx)
return InternJSString(cx, s_length_id, "length"); return InternJSString(cx, s_length_id, "length");
} }
const char DOMProxyHandler::family = 0;
const char HandlerFamily = 0;
js::DOMProxyShadowsResult js::DOMProxyShadowsResult
DOMProxyShadows(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id) DOMProxyShadows(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id)
@@ -60,7 +59,7 @@ DOMProxyShadows(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id)
struct SetDOMProxyInformation struct SetDOMProxyInformation
{ {
SetDOMProxyInformation() { SetDOMProxyInformation() {
js::SetDOMProxyInformation((const void*) &HandlerFamily, js::SetDOMProxyInformation((const void*) &DOMProxyHandler::family,
js::PROXY_EXTRA_SLOT + JSPROXYSLOT_EXPANDO, DOMProxyShadows); js::PROXY_EXTRA_SLOT + JSPROXYSLOT_EXPANDO, DOMProxyShadows);
} }
}; };
@@ -363,5 +362,25 @@ DOMProxyHandler::setCustom(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handl
return true; 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<js::ExpandoAndGeneration*>(v.toPrivate());
v = expandoAndGeneration->expando;
return v.isUndefined() ? nullptr : &v.toObject();
}
} // namespace dom } // namespace dom
} // namespace mozilla } // namespace mozilla

View File

@@ -24,17 +24,6 @@ enum {
template<typename T> struct Prefable; template<typename T> 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 class BaseDOMProxyHandler : public js::BaseProxyHandler
{ {
public: public:
@@ -89,7 +78,7 @@ class DOMProxyHandler : public BaseDOMProxyHandler
{ {
public: public:
DOMProxyHandler() DOMProxyHandler()
: BaseDOMProxyHandler(ProxyFamily()) : BaseDOMProxyHandler(&family)
{ {
} }
@@ -121,29 +110,23 @@ public:
virtual bool setCustom(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id, virtual bool setCustom(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id,
JS::MutableHandle<JS::Value> vp, bool *done) const; JS::MutableHandle<JS::Value> vp, bool *done) const;
static JSObject* GetExpandoObject(JSObject* obj) 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();
}
if (v.isUndefined()) {
return nullptr;
}
js::ExpandoAndGeneration* expandoAndGeneration =
static_cast<js::ExpandoAndGeneration*>(v.toPrivate());
v = expandoAndGeneration->expando;
return v.isUndefined() ? nullptr : &v.toObject();
}
/* GetAndClearExpandoObject does not DROP or clear the preserving wrapper flag. */ /* GetAndClearExpandoObject does not DROP or clear the preserving wrapper flag. */
static JSObject* GetAndClearExpandoObject(JSObject* obj); static JSObject* GetAndClearExpandoObject(JSObject* obj);
static JSObject* EnsureExpandoObject(JSContext* cx, static JSObject* EnsureExpandoObject(JSContext* cx,
JS::Handle<JSObject*> obj); JS::Handle<JSObject*> 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* inline const DOMProxyHandler*
GetDOMProxyHandler(JSObject* obj) GetDOMProxyHandler(JSObject* obj)
{ {

View File

@@ -45,13 +45,11 @@ WrapperOwner::idOf(JSObject *obj)
return objId; return objId;
} }
int sCPOWProxyHandler;
class CPOWProxyHandler : public BaseProxyHandler class CPOWProxyHandler : public BaseProxyHandler
{ {
public: public:
CPOWProxyHandler() CPOWProxyHandler()
: BaseProxyHandler(&sCPOWProxyHandler) {} : BaseProxyHandler(&family) {}
virtual ~CPOWProxyHandler() {} virtual ~CPOWProxyHandler() {}
virtual bool finalizeInBackground(Value priv) const MOZ_OVERRIDE { 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 const char* className(JSContext *cx, HandleObject proxy) const MOZ_OVERRIDE;
virtual void finalize(JSFreeOp *fop, JSObject *proxy) const MOZ_OVERRIDE; virtual void finalize(JSFreeOp *fop, JSObject *proxy) const MOZ_OVERRIDE;
static const char family;
static const CPOWProxyHandler singleton; static const CPOWProxyHandler singleton;
}; };
const char CPOWProxyHandler::family = 0;
const CPOWProxyHandler CPOWProxyHandler::singleton; const CPOWProxyHandler CPOWProxyHandler::singleton;
#define FORWARD(call, args) \ #define FORWARD(call, args) \

View File

@@ -601,7 +601,7 @@ JS_IsDeadWrapper(JSObject *obj)
return false; return false;
} }
return obj->as<ProxyObject>().handler()->family() == &DeadObjectProxy::sDeadObjectFamily; return obj->as<ProxyObject>().handler()->family() == &DeadObjectProxy::family;
} }
void void

View File

@@ -797,6 +797,7 @@ class ScriptedIndirectProxyHandler : public BaseProxyHandler
virtual JSString *fun_toString(JSContext *cx, HandleObject proxy, unsigned indent) const MOZ_OVERRIDE; virtual JSString *fun_toString(JSContext *cx, HandleObject proxy, unsigned indent) const MOZ_OVERRIDE;
virtual bool isScripted() const MOZ_OVERRIDE { return true; } virtual bool isScripted() const MOZ_OVERRIDE { return true; }
static const char family;
static const ScriptedIndirectProxyHandler singleton; static const ScriptedIndirectProxyHandler singleton;
}; };
@@ -818,10 +819,10 @@ static const Class CallConstructHolder = {
} /* anonymous namespace */ } /* anonymous namespace */
// This variable exists solely to provide a unique address for use as an identifier. // 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() 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 construct(JSContext *cx, HandleObject proxy, const CallArgs &args) const MOZ_OVERRIDE;
virtual bool isScripted() const MOZ_OVERRIDE { return true; } virtual bool isScripted() const MOZ_OVERRIDE { return true; }
static const char family;
static const ScriptedDirectProxyHandler singleton; static const ScriptedDirectProxyHandler singleton;
// The "proxy extra" slot index in which the handler is stored. Revocable proxies need to set // 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; 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 static inline bool
IsDataDescriptor(const PropertyDescriptor &desc) IsDataDescriptor(const PropertyDescriptor &desc)
{ {
@@ -1389,7 +1388,7 @@ ArrayToIdVector(JSContext *cx, HandleObject proxy, HandleObject target, HandleVa
} }
ScriptedDirectProxyHandler::ScriptedDirectProxyHandler() ScriptedDirectProxyHandler::ScriptedDirectProxyHandler()
: DirectProxyHandler(&sScriptedDirectProxyHandlerFamily) : DirectProxyHandler(&family)
{ {
} }
@@ -2208,6 +2207,7 @@ ScriptedDirectProxyHandler::construct(JSContext *cx, HandleObject proxy, const C
return true; return true;
} }
const char ScriptedDirectProxyHandler::family = 0;
const ScriptedDirectProxyHandler ScriptedDirectProxyHandler::singleton; const ScriptedDirectProxyHandler ScriptedDirectProxyHandler::singleton;
#define INVOKE_ON_PROTOTYPE(cx, handler, proxy, protoCall) \ #define INVOKE_ON_PROTOTYPE(cx, handler, proxy, protoCall) \

View File

@@ -87,6 +87,14 @@ class JS_FRIEND_API(Wrapper);
*/ */
class JS_FRIEND_API(BaseProxyHandler) 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; const void *mFamily;
/* /*

View File

@@ -20,8 +20,6 @@
using namespace js; using namespace js;
using namespace js::gc; using namespace js::gc;
const char js::sWrapperFamily = 0;
/* /*
* Wrapper forwards this call directly to the wrapped object for efficiency * Wrapper forwards this call directly to the wrapped object for efficiency
* and transparency. In particular, the hint is needed to properly stringify * 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) Wrapper::Wrapper(unsigned flags, bool hasPrototype, bool hasSecurityPolicy)
: DirectProxyHandler(&sWrapperFamily, hasPrototype, hasSecurityPolicy), : DirectProxyHandler(&family, hasPrototype, hasSecurityPolicy),
mFlags(flags) mFlags(flags)
{ {
} }
@@ -140,6 +138,7 @@ Wrapper::~Wrapper()
{ {
} }
const char Wrapper::family = 0;
const Wrapper Wrapper::singleton((unsigned)0); const Wrapper Wrapper::singleton((unsigned)0);
const Wrapper Wrapper::singletonWithPrototype((unsigned)0, true); const Wrapper Wrapper::singletonWithPrototype((unsigned)0, true);
JSObject *Wrapper::defaultProto = TaggedProto::LazyProto; JSObject *Wrapper::defaultProto = TaggedProto::LazyProto;
@@ -748,7 +747,7 @@ template class js::SecurityWrapper<Wrapper>;
template class js::SecurityWrapper<CrossCompartmentWrapper>; template class js::SecurityWrapper<CrossCompartmentWrapper>;
DeadObjectProxy::DeadObjectProxy() DeadObjectProxy::DeadObjectProxy()
: BaseProxyHandler(&sDeadObjectFamily) : BaseProxyHandler(&family)
{ {
} }
@@ -885,8 +884,8 @@ DeadObjectProxy::getPrototypeOf(JSContext *cx, HandleObject proxy, MutableHandle
return true; return true;
} }
const char DeadObjectProxy::family = 0;
const DeadObjectProxy DeadObjectProxy::singleton; const DeadObjectProxy DeadObjectProxy::singleton;
const char DeadObjectProxy::sDeadObjectFamily = 0;
bool bool
js::IsDeadProxyObject(JSObject *obj) js::IsDeadProxyObject(JSObject *obj)

View File

@@ -87,6 +87,7 @@ class JS_FRIEND_API(Wrapper) : public DirectProxyHandler
virtual bool finalizeInBackground(Value priv) const MOZ_OVERRIDE; virtual bool finalizeInBackground(Value priv) const MOZ_OVERRIDE;
static const char family;
static const Wrapper singleton; static const Wrapper singleton;
static const Wrapper singletonWithPrototype; static const Wrapper singletonWithPrototype;
@@ -207,9 +208,6 @@ typedef SecurityWrapper<CrossCompartmentWrapper> CrossCompartmentSecurityWrapper
class JS_FRIEND_API(DeadObjectProxy) : public BaseProxyHandler class JS_FRIEND_API(DeadObjectProxy) : public BaseProxyHandler
{ {
public: public:
// This variable exists solely to provide a unique address for use as an identifier.
static const char sDeadObjectFamily;
explicit DeadObjectProxy(); explicit DeadObjectProxy();
/* ES5 Harmony fundamental wrapper traps. */ /* ES5 Harmony fundamental wrapper traps. */
@@ -243,6 +241,7 @@ class JS_FRIEND_API(DeadObjectProxy) : public BaseProxyHandler
virtual bool getPrototypeOf(JSContext *cx, HandleObject proxy, virtual bool getPrototypeOf(JSContext *cx, HandleObject proxy,
MutableHandleObject protop) const MOZ_OVERRIDE; MutableHandleObject protop) const MOZ_OVERRIDE;
static const char family;
static const DeadObjectProxy singleton; static const DeadObjectProxy singleton;
}; };
@@ -250,15 +249,10 @@ extern JSObject *
TransparentObjectWrapper(JSContext *cx, HandleObject existing, HandleObject obj, TransparentObjectWrapper(JSContext *cx, HandleObject existing, HandleObject obj,
HandleObject parent); 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 inline bool
IsWrapper(JSObject *obj) 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 // Given a JSObject, returns that object stripped of wrappers. If

View File

@@ -1323,7 +1323,7 @@ class DebugScopeProxy : public BaseProxyHandler
} }
public: public:
static int family; static const char family;
static const DebugScopeProxy singleton; static const DebugScopeProxy singleton;
DebugScopeProxy() : BaseProxyHandler(&family) {} DebugScopeProxy() : BaseProxyHandler(&family) {}
@@ -1592,7 +1592,7 @@ class DebugScopeProxy : public BaseProxyHandler
} /* anonymous namespace */ } /* anonymous namespace */
int DebugScopeProxy::family = 0; const char DebugScopeProxy::family = 0;
const DebugScopeProxy DebugScopeProxy::singleton; const DebugScopeProxy DebugScopeProxy::singleton;
/* static */ DebugScopeObject * /* static */ DebugScopeObject *