mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-14 12:13:22 +00:00
Bug 761695 - Unify holder creation and access. r=peterv
With this patch, all holders are created lazily. There are two common accessors, getHolder() and ensureHolder(). The former returns null if no holder exists, the latter lazily creates the holder if it doesn't exist. It does this by calling into a virtual trap on XrayTraits, which lets the appropriate Xray type do its thing.
This commit is contained in:
parent
05eeb2aa4e
commit
1a9081b1ce
@ -329,7 +329,6 @@ WrapperFactory::Rewrap(JSContext *cx, JSObject *obj, JSObject *wrappedProto, JSO
|
||||
|
||||
JSCompartment *origin = js::GetObjectCompartment(obj);
|
||||
JSCompartment *target = js::GetContextCompartment(cx);
|
||||
bool usingXray = false;
|
||||
|
||||
// By default we use the wrapped proto of the underlying object as the
|
||||
// prototype for our wrapper, but we may select something different below.
|
||||
@ -354,7 +353,6 @@ WrapperFactory::Rewrap(JSContext *cx, JSObject *obj, JSObject *wrappedProto, JSO
|
||||
wrapper = &XrayProxy::singleton;
|
||||
} else if (type == XrayForWrappedNative) {
|
||||
typedef XrayWrapper<CrossCompartmentWrapper> Xray;
|
||||
usingXray = true;
|
||||
wrapper = &Xray::singleton;
|
||||
} else {
|
||||
wrapper = &CrossCompartmentWrapper::singleton;
|
||||
@ -377,7 +375,6 @@ WrapperFactory::Rewrap(JSContext *cx, JSObject *obj, JSObject *wrappedProto, JSO
|
||||
(wn = GetWrappedNative(cx, obj)) &&
|
||||
wn->HasProto() && wn->GetProto()->ClassIsDOMObject()) {
|
||||
typedef XrayWrapper<CrossCompartmentSecurityWrapper> Xray;
|
||||
usingXray = true;
|
||||
if (IsLocationObject(obj))
|
||||
wrapper = &FilteringWrapper<Xray, LocationPolicy>::singleton;
|
||||
else
|
||||
@ -441,7 +438,6 @@ WrapperFactory::Rewrap(JSContext *cx, JSObject *obj, JSObject *wrappedProto, JSO
|
||||
OnlyIfSubjectIsSystem>::singleton;
|
||||
} else if (IsLocationObject(obj)) {
|
||||
typedef XrayWrapper<CrossCompartmentSecurityWrapper> Xray;
|
||||
usingXray = true;
|
||||
wrapper = &FilteringWrapper<Xray, LocationPolicy>::singleton;
|
||||
} else if (IsComponentsObject(obj)) {
|
||||
wrapper = &FilteringWrapper<CrossCompartmentSecurityWrapper,
|
||||
@ -455,7 +451,6 @@ WrapperFactory::Rewrap(JSContext *cx, JSObject *obj, JSObject *wrappedProto, JSO
|
||||
wrapper = &XrayProxy::singleton;
|
||||
} else {
|
||||
typedef XrayWrapper<CrossCompartmentWrapper> Xray;
|
||||
usingXray = true;
|
||||
wrapper = &Xray::singleton;
|
||||
}
|
||||
} else {
|
||||
@ -476,7 +471,6 @@ WrapperFactory::Rewrap(JSContext *cx, JSObject *obj, JSObject *wrappedProto, JSO
|
||||
CrossOriginAccessiblePropertiesOnly>::singleton;
|
||||
} else {
|
||||
typedef XrayWrapper<CrossCompartmentSecurityWrapper> Xray;
|
||||
usingXray = true;
|
||||
|
||||
// Location objects can become same origin after navigation, so we might
|
||||
// have to grant transparent access later on.
|
||||
@ -489,15 +483,7 @@ WrapperFactory::Rewrap(JSContext *cx, JSObject *obj, JSObject *wrappedProto, JSO
|
||||
}
|
||||
}
|
||||
|
||||
JSObject *wrapperObj = Wrapper::New(cx, obj, proxyProto, parent, wrapper);
|
||||
if (!wrapperObj || !usingXray)
|
||||
return wrapperObj;
|
||||
|
||||
JSObject *xrayHolder = XrayUtils::createHolder(cx, wrapperObj);
|
||||
if (!xrayHolder)
|
||||
return nullptr;
|
||||
js::SetProxyExtra(wrapperObj, 0, js::ObjectValue(*xrayHolder));
|
||||
return wrapperObj;
|
||||
return Wrapper::New(cx, obj, proxyProto, parent, wrapper);
|
||||
}
|
||||
|
||||
JSObject *
|
||||
@ -534,15 +520,7 @@ WrapperFactory::WrapLocationObject(JSContext *cx, JSObject *obj)
|
||||
JSObject *proto;
|
||||
if (!js::GetObjectProto(cx, obj, &proto))
|
||||
return nullptr;
|
||||
JSObject *wrapperObj = Wrapper::New(cx, obj, proto, js::GetObjectParent(obj),
|
||||
&LW::singleton);
|
||||
if (!wrapperObj)
|
||||
return nullptr;
|
||||
JSObject *xrayHolder = XrayUtils::createHolder(cx, wrapperObj);
|
||||
if (!xrayHolder)
|
||||
return nullptr;
|
||||
js::SetProxyExtra(wrapperObj, 0, js::ObjectValue(*xrayHolder));
|
||||
return wrapperObj;
|
||||
return Wrapper::New(cx, obj, proto, js::GetObjectParent(obj), &LW::singleton);
|
||||
}
|
||||
|
||||
// Call WaiveXrayAndWrap when you have a JS object that you don't want to be
|
||||
@ -627,19 +605,7 @@ WrapperFactory::WrapForSameCompartmentXray(JSContext *cx, JSObject *obj)
|
||||
|
||||
// Make the Xray.
|
||||
JSObject *parent = JS_GetGlobalForObject(cx, obj);
|
||||
JSObject *wrapperObj = Wrapper::New(cx, obj, NULL, parent, wrapper);
|
||||
if (!wrapperObj)
|
||||
return NULL;
|
||||
|
||||
// Make the holder. Note that this is currently for WNs only until we fix
|
||||
// bug 761704.
|
||||
if (type == XrayForWrappedNative) {
|
||||
JSObject *xrayHolder = XrayUtils::createHolder(cx, wrapperObj);
|
||||
if (!xrayHolder)
|
||||
return nullptr;
|
||||
js::SetProxyExtra(wrapperObj, 0, js::ObjectValue(*xrayHolder));
|
||||
}
|
||||
return wrapperObj;
|
||||
return Wrapper::New(cx, obj, NULL, parent, wrapper);
|
||||
}
|
||||
|
||||
|
||||
|
@ -249,20 +249,6 @@ CloneExpandoChain(JSContext *cx, JSObject *dst, JSObject *src)
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
JSObject *
|
||||
createHolder(JSContext *cx, JSObject *wrapper)
|
||||
{
|
||||
JSObject *global = JS_GetGlobalForObject(cx, wrapper);
|
||||
JSObject *holder = JS_NewObjectWithGivenProto(cx, &HolderClass, nullptr,
|
||||
global);
|
||||
if (!holder)
|
||||
return nullptr;
|
||||
|
||||
js::SetReservedSlot(holder, JSSLOT_RESOLVING, PrivateValue(NULL));
|
||||
return holder;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
using namespace XrayUtils;
|
||||
@ -346,6 +332,11 @@ public:
|
||||
{
|
||||
MOZ_NOT_REACHED("Call trap currently implemented only for XPCWNs");
|
||||
}
|
||||
|
||||
JSObject* getHolder(JSObject *wrapper);
|
||||
JSObject* ensureHolder(JSContext *cx, JSObject *wrapper);
|
||||
|
||||
virtual JSObject* createHolder(JSContext *cx, JSObject *wrapper) = 0;
|
||||
};
|
||||
|
||||
class XPCWrappedNativeXrayTraits : public XrayTraits
|
||||
@ -365,11 +356,6 @@ public:
|
||||
static bool construct(JSContext *cx, JSObject *wrapper, unsigned argc,
|
||||
Value *argv, Value *rval);
|
||||
|
||||
static JSObject* getHolderObject(JSContext *cx, JSObject *wrapper)
|
||||
{
|
||||
return getHolderObject(wrapper);
|
||||
}
|
||||
|
||||
static bool isResolving(JSContext *cx, JSObject *holder, jsid id);
|
||||
|
||||
static bool resolveDOMCollectionProperty(JSContext *cx, JSObject *wrapper, JSObject *holder,
|
||||
@ -381,13 +367,9 @@ public:
|
||||
|
||||
typedef ResolvingId ResolvingIdImpl;
|
||||
|
||||
static XPCWrappedNativeXrayTraits singleton;
|
||||
virtual JSObject* createHolder(JSContext *cx, JSObject *wrapper);
|
||||
|
||||
private:
|
||||
static JSObject* getHolderObject(JSObject *wrapper)
|
||||
{
|
||||
return &js::GetProxyExtra(wrapper, 0).toObject();
|
||||
}
|
||||
static XPCWrappedNativeXrayTraits singleton;
|
||||
};
|
||||
|
||||
class ProxyXrayTraits : public XrayTraits
|
||||
@ -403,10 +385,6 @@ public:
|
||||
static bool delete_(JSContext *cx, JSObject *wrapper, jsid id, bool *bp);
|
||||
static bool enumerateNames(JSContext *cx, JSObject *wrapper, unsigned flags,
|
||||
JS::AutoIdVector &props);
|
||||
static JSObject* getHolderObject(JSContext *cx, JSObject *wrapper)
|
||||
{
|
||||
return getHolderObject(cx, wrapper, true);
|
||||
}
|
||||
|
||||
static bool isResolving(JSContext *cx, JSObject *holder, jsid id)
|
||||
{
|
||||
@ -415,21 +393,9 @@ public:
|
||||
|
||||
typedef ResolvingIdDummy ResolvingIdImpl;
|
||||
|
||||
virtual JSObject* createHolder(JSContext *cx, JSObject *wrapper);
|
||||
|
||||
static ProxyXrayTraits singleton;
|
||||
|
||||
private:
|
||||
static JSObject* getHolderObject(JSContext *cx, JSObject *wrapper,
|
||||
bool createHolder)
|
||||
{
|
||||
if (!js::GetProxyExtra(wrapper, 0).isUndefined())
|
||||
return &js::GetProxyExtra(wrapper, 0).toObject();
|
||||
|
||||
if (!createHolder)
|
||||
return nullptr;
|
||||
|
||||
return createHolderObject(cx, wrapper);
|
||||
}
|
||||
static JSObject* createHolderObject(JSContext *cx, JSObject *wrapper);
|
||||
};
|
||||
|
||||
class DOMXrayTraits : public XrayTraits
|
||||
@ -445,10 +411,6 @@ public:
|
||||
static bool delete_(JSContext *cx, JSObject *wrapper, jsid id, bool *bp);
|
||||
static bool enumerateNames(JSContext *cx, JSObject *wrapper, unsigned flags,
|
||||
JS::AutoIdVector &props);
|
||||
static JSObject* getHolderObject(JSContext *cx, JSObject *wrapper)
|
||||
{
|
||||
return getHolderObject(cx, wrapper, true);
|
||||
}
|
||||
|
||||
static bool isResolving(JSContext *cx, JSObject *holder, jsid id)
|
||||
{
|
||||
@ -457,21 +419,9 @@ public:
|
||||
|
||||
typedef ResolvingIdDummy ResolvingIdImpl;
|
||||
|
||||
virtual JSObject* createHolder(JSContext *cx, JSObject *wrapper);
|
||||
|
||||
static DOMXrayTraits singleton;
|
||||
|
||||
private:
|
||||
static JSObject* getHolderObject(JSContext *cx, JSObject *wrapper,
|
||||
bool createHolder)
|
||||
{
|
||||
if (!js::GetProxyExtra(wrapper, 0).isUndefined())
|
||||
return &js::GetProxyExtra(wrapper, 0).toObject();
|
||||
|
||||
if (!createHolder)
|
||||
return nullptr;
|
||||
|
||||
return createHolderObject(cx, wrapper);
|
||||
}
|
||||
static JSObject* createHolderObject(JSContext *cx, JSObject *wrapper);
|
||||
};
|
||||
|
||||
XPCWrappedNativeXrayTraits XPCWrappedNativeXrayTraits::singleton;
|
||||
@ -510,6 +460,26 @@ FindWrapper(JSContext *cx, JSObject *wrapper)
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
JSObject*
|
||||
XrayTraits::getHolder(JSObject *wrapper)
|
||||
{
|
||||
MOZ_ASSERT(WrapperFactory::IsXrayWrapper(wrapper));
|
||||
js::Value v = js::GetProxyExtra(wrapper, 0);
|
||||
return v.isObject() ? &v.toObject() : nullptr;
|
||||
}
|
||||
|
||||
JSObject*
|
||||
XrayTraits::ensureHolder(JSContext *cx, JSObject *wrapper)
|
||||
{
|
||||
JSObject *holder = getHolder(wrapper);
|
||||
if (holder)
|
||||
return holder;
|
||||
holder = createHolder(cx, wrapper); // virtual trap.
|
||||
if (holder)
|
||||
js::SetProxyExtra(wrapper, 0, ObjectValue(*holder));
|
||||
return holder;
|
||||
}
|
||||
|
||||
bool
|
||||
XPCWrappedNativeXrayTraits::isResolving(JSContext *cx, JSObject *holder,
|
||||
jsid id)
|
||||
@ -1000,7 +970,7 @@ bool
|
||||
XPCWrappedNativeXrayTraits::defineProperty(JSContext *cx, JSObject *wrapper, jsid id,
|
||||
PropertyDescriptor *desc)
|
||||
{
|
||||
JSObject *holder = getHolderObject(wrapper);
|
||||
JSObject *holder = singleton.ensureHolder(cx, wrapper);
|
||||
if (isResolving(cx, holder, id)) {
|
||||
if (!(desc->attrs & (JSPROP_GETTER | JSPROP_SETTER))) {
|
||||
if (!desc->getter)
|
||||
@ -1089,6 +1059,19 @@ XPCWrappedNativeXrayTraits::enumerateNames(JSContext *cx, JSObject *wrapper, uns
|
||||
return true;
|
||||
}
|
||||
|
||||
JSObject *
|
||||
XPCWrappedNativeXrayTraits::createHolder(JSContext *cx, JSObject *wrapper)
|
||||
{
|
||||
JSObject *global = JS_GetGlobalForObject(cx, wrapper);
|
||||
JSObject *holder = JS_NewObjectWithGivenProto(cx, &HolderClass, nullptr,
|
||||
global);
|
||||
if (!holder)
|
||||
return nullptr;
|
||||
|
||||
js::SetReservedSlot(holder, JSSLOT_RESOLVING, PrivateValue(NULL));
|
||||
return holder;
|
||||
}
|
||||
|
||||
bool
|
||||
XPCWrappedNativeXrayTraits::call(JSContext *cx, JSObject *wrapper,
|
||||
unsigned argc, Value *vp)
|
||||
@ -1166,7 +1149,7 @@ bool
|
||||
ProxyXrayTraits::defineProperty(JSContext *cx, JSObject *wrapper, jsid id,
|
||||
PropertyDescriptor *desc)
|
||||
{
|
||||
JSObject *holder = getHolderObject(cx, wrapper);
|
||||
JSObject *holder = singleton.ensureHolder(cx, wrapper);
|
||||
if (!holder)
|
||||
return false;
|
||||
|
||||
@ -1182,7 +1165,7 @@ ProxyXrayTraits::delete_(JSContext *cx, JSObject *wrapper, jsid id, bool *bp)
|
||||
return false;
|
||||
|
||||
JSObject *holder;
|
||||
if (*bp && (holder = getHolderObject(cx, wrapper, false)))
|
||||
if (*bp && (holder = singleton.getHolder(wrapper)))
|
||||
JS_DeletePropertyById(cx, holder, id);
|
||||
|
||||
return true;
|
||||
@ -1203,14 +1186,10 @@ ProxyXrayTraits::enumerateNames(JSContext *cx, JSObject *wrapper, unsigned flags
|
||||
// XPCWrappedNativeXrayTraits. Instead, it's a funny hybrid of the 'expando' and
|
||||
// 'holder' properties. However, we store it in the same slot. Exercise caution.
|
||||
JSObject*
|
||||
ProxyXrayTraits::createHolderObject(JSContext *cx, JSObject *wrapper)
|
||||
ProxyXrayTraits::createHolder(JSContext *cx, JSObject *wrapper)
|
||||
{
|
||||
JSObject *obj = JS_NewObjectWithGivenProto(cx, nullptr, nullptr,
|
||||
JS_GetGlobalForObject(cx, wrapper));
|
||||
if (!obj)
|
||||
return nullptr;
|
||||
js::SetProxyExtra(wrapper, 0, ObjectValue(*obj));
|
||||
return obj;
|
||||
return JS_NewObjectWithGivenProto(cx, nullptr, nullptr,
|
||||
JS_GetGlobalForObject(cx, wrapper));
|
||||
}
|
||||
|
||||
bool
|
||||
@ -1254,7 +1233,7 @@ DOMXrayTraits::resolveOwnProperty(JSContext *cx, js::Wrapper &jsWrapper, JSObjec
|
||||
bool
|
||||
DOMXrayTraits::defineProperty(JSContext *cx, JSObject *wrapper, jsid id, PropertyDescriptor *desc)
|
||||
{
|
||||
JSObject *holder = getHolderObject(cx, wrapper);
|
||||
JSObject *holder = singleton.ensureHolder(cx, wrapper);
|
||||
if (!holder)
|
||||
return false;
|
||||
|
||||
@ -1266,7 +1245,7 @@ bool
|
||||
DOMXrayTraits::delete_(JSContext *cx, JSObject *wrapper, jsid id, bool *bp)
|
||||
{
|
||||
JSObject *holder;
|
||||
if ((holder = getHolderObject(cx, wrapper, false)))
|
||||
if ((holder = singleton.getHolder(wrapper)))
|
||||
JS_DeletePropertyById(cx, holder, id);
|
||||
|
||||
return true;
|
||||
@ -1297,14 +1276,10 @@ DOMXrayTraits::enumerateNames(JSContext *cx, JSObject *wrapper, unsigned flags,
|
||||
}
|
||||
|
||||
JSObject*
|
||||
DOMXrayTraits::createHolderObject(JSContext *cx, JSObject *wrapper)
|
||||
DOMXrayTraits::createHolder(JSContext *cx, JSObject *wrapper)
|
||||
{
|
||||
JSObject *obj = JS_NewObjectWithGivenProto(cx, nullptr, nullptr,
|
||||
JS_GetGlobalForObject(cx, wrapper));
|
||||
if (!obj)
|
||||
return nullptr;
|
||||
js::SetProxyExtra(wrapper, 0, ObjectValue(*obj));
|
||||
return obj;
|
||||
return JS_NewObjectWithGivenProto(cx, nullptr, nullptr,
|
||||
JS_GetGlobalForObject(cx, wrapper));
|
||||
}
|
||||
|
||||
template <typename Base, typename Traits>
|
||||
@ -1393,7 +1368,7 @@ bool
|
||||
XrayWrapper<Base, Traits>::getPropertyDescriptor(JSContext *cx, JSObject *wrapper, jsid id,
|
||||
bool set, js::PropertyDescriptor *desc)
|
||||
{
|
||||
JSObject *holder = Traits::getHolderObject(cx, wrapper);
|
||||
JSObject *holder = Traits::singleton.ensureHolder(cx, wrapper);
|
||||
if (Traits::isResolving(cx, holder, id)) {
|
||||
desc->obj = NULL;
|
||||
return true;
|
||||
@ -1493,7 +1468,7 @@ bool
|
||||
XrayWrapper<Base, Traits>::getOwnPropertyDescriptor(JSContext *cx, JSObject *wrapper, jsid id,
|
||||
bool set, PropertyDescriptor *desc)
|
||||
{
|
||||
JSObject *holder = Traits::getHolderObject(cx, wrapper);
|
||||
JSObject *holder = Traits::singleton.ensureHolder(cx, wrapper);
|
||||
if (Traits::isResolving(cx, holder, id)) {
|
||||
desc->obj = NULL;
|
||||
return true;
|
||||
@ -1550,7 +1525,7 @@ XrayWrapper<Base, Traits>::defineProperty(JSContext *cx, JSObject *wrapper, jsid
|
||||
// If shadowing is forbidden, see if the id corresponds to an underlying
|
||||
// native property.
|
||||
if (WrapperFactory::IsShadowingForbidden(wrapper)) {
|
||||
JSObject *holder = Traits::getHolderObject(cx, wrapper);
|
||||
JSObject *holder = Traits::singleton.ensureHolder(cx, wrapper);
|
||||
js::PropertyDescriptor nativeProp;
|
||||
if (!Traits::resolveNativeProperty(cx, wrapper, holder, id, false, &nativeProp))
|
||||
return false;
|
||||
|
@ -30,8 +30,6 @@ extern JSClass HolderClass;
|
||||
|
||||
bool CloneExpandoChain(JSContext *cx, JSObject *src, JSObject *dst);
|
||||
|
||||
JSObject *createHolder(JSContext *cx, JSObject *wrapper);
|
||||
|
||||
bool
|
||||
IsTransparent(JSContext *cx, JSObject *wrapper);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user