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

This commit is contained in:
Eric Faust 2014-08-27 17:09:06 -07:00
parent d6d35eac77
commit 96d6ad8f2d
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");
}
const char HandlerFamily = 0;
const char DOMProxyHandler::family = 0;
js::DOMProxyShadowsResult
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
{
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<JSObject*> 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<js::ExpandoAndGeneration*>(v.toPrivate());
v = expandoAndGeneration->expando;
return v.isUndefined() ? nullptr : &v.toObject();
}
} // namespace dom
} // namespace mozilla

View File

@ -24,17 +24,6 @@ enum {
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
{
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<JSObject*> proxy, JS::Handle<jsid> id,
JS::MutableHandle<JS::Value> 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<js::ExpandoAndGeneration*>(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<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*
GetDOMProxyHandler(JSObject* obj)
{

View File

@ -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) \

View File

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

View File

@ -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;
/*

View File

@ -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<Wrapper>;
template class js::SecurityWrapper<CrossCompartmentWrapper>;
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)

View File

@ -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<CrossCompartmentWrapper> 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

View File

@ -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 *