mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
bug 580128 - Pass the XrayWrapper itself to scriptable helpers (and related cleanup) since the holder doesn't have enough smarts to do lookups, etc. r=gal
This commit is contained in:
parent
d8815d1675
commit
964c4a31ef
@ -1928,6 +1928,9 @@ nsDOMClassInfo::ObjectIsNativeWrapper(JSContext* cx, JSObject* obj)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (obj->isWrapper())
|
||||||
|
return PR_TRUE;
|
||||||
|
|
||||||
JSPropertyOp op = obj->getJSClass()->getProperty;
|
JSPropertyOp op = obj->getJSClass()->getProperty;
|
||||||
return !!op && (op == sXPCNativeWrapperGetPropertyOp ||
|
return !!op && (op == sXPCNativeWrapperGetPropertyOp ||
|
||||||
op == sXrayWrapperPropertyHolderGetPropertyOp);
|
op == sXrayWrapperPropertyHolderGetPropertyOp);
|
||||||
|
@ -2712,7 +2712,7 @@ nsXPConnect::GetPrincipal(JSObject* obj, PRBool allowShortCircuit) const
|
|||||||
NS_IMETHODIMP_(void)
|
NS_IMETHODIMP_(void)
|
||||||
nsXPConnect::GetXrayWrapperPropertyHolderGetPropertyOp(JSPropertyOp *getPropertyPtr)
|
nsXPConnect::GetXrayWrapperPropertyHolderGetPropertyOp(JSPropertyOp *getPropertyPtr)
|
||||||
{
|
{
|
||||||
*getPropertyPtr = xpc::HolderClass.getProperty;
|
*getPropertyPtr = xpc::XrayUtils::HolderClass.getProperty;
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP_(void)
|
NS_IMETHODIMP_(void)
|
||||||
|
@ -176,7 +176,7 @@ AccessCheck::isCrossOriginAccessPermitted(JSContext *cx, JSObject *wrapper, jsid
|
|||||||
|
|
||||||
const char *name;
|
const char *name;
|
||||||
js::Class *clasp = obj->getClass();
|
js::Class *clasp = obj->getClass();
|
||||||
NS_ASSERTION(Jsvalify(clasp) != &HolderClass, "shouldn't have a holder here");
|
NS_ASSERTION(Jsvalify(clasp) != &XrayUtils::HolderClass, "shouldn't have a holder here");
|
||||||
if (clasp->ext.innerObject)
|
if (clasp->ext.innerObject)
|
||||||
name = "Window";
|
name = "Window";
|
||||||
else
|
else
|
||||||
|
@ -71,7 +71,7 @@ WrapperFactory::Rewrap(JSContext *cx, JSObject *obj, JSObject *wrappedProto, JSO
|
|||||||
{
|
{
|
||||||
NS_ASSERTION(!obj->isWrapper() || obj->getClass()->ext.innerObject,
|
NS_ASSERTION(!obj->isWrapper() || obj->getClass()->ext.innerObject,
|
||||||
"wrapped object passed to rewrap");
|
"wrapped object passed to rewrap");
|
||||||
NS_ASSERTION(JS_GET_CLASS(cx, obj) != &HolderClass, "trying to wrap a holder");
|
NS_ASSERTION(JS_GET_CLASS(cx, obj) != &XrayUtils::HolderClass, "trying to wrap a holder");
|
||||||
|
|
||||||
if (IS_SLIM_WRAPPER(obj) && !MorphSlimWrapper(cx, obj))
|
if (IS_SLIM_WRAPPER(obj) && !MorphSlimWrapper(cx, obj))
|
||||||
return nsnull;
|
return nsnull;
|
||||||
@ -142,6 +142,7 @@ WrapperFactory::Rewrap(JSContext *cx, JSObject *obj, JSObject *wrappedProto, JSO
|
|||||||
if (!wrapperObj || !xrayHolder)
|
if (!wrapperObj || !xrayHolder)
|
||||||
return wrapperObj;
|
return wrapperObj;
|
||||||
wrapperObj->setProxyExtra(js::ObjectValue(*xrayHolder));
|
wrapperObj->setProxyExtra(js::ObjectValue(*xrayHolder));
|
||||||
|
xrayHolder->setSlot(XrayUtils::JSSLOT_PROXY_OBJ, js::ObjectValue(*wrapperObj));
|
||||||
return wrapperObj;
|
return wrapperObj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,6 +53,51 @@ namespace xpc {
|
|||||||
using namespace js;
|
using namespace js;
|
||||||
|
|
||||||
static const uint32 JSSLOT_WN_OBJ = JSSLOT_PRIVATE;
|
static const uint32 JSSLOT_WN_OBJ = JSSLOT_PRIVATE;
|
||||||
|
static const uint32 JSSLOT_RESOLVING = JSSLOT_PRIVATE + 1;
|
||||||
|
|
||||||
|
namespace XrayUtils {
|
||||||
|
|
||||||
|
const uint32 JSSLOT_PROXY_OBJ = JSSLOT_PRIVATE + 2;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class ResolvingId
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ResolvingId(JSObject *holder, jsid id)
|
||||||
|
: mId(id),
|
||||||
|
mPrev(getResolvingId(holder)),
|
||||||
|
mHolder(holder)
|
||||||
|
{
|
||||||
|
holder->setSlot(JSSLOT_RESOLVING, PrivateValue(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
~ResolvingId() {
|
||||||
|
NS_ASSERTION(getResolvingId(mHolder) == this, "unbalanced ResolvingIds");
|
||||||
|
mHolder->setSlot(JSSLOT_RESOLVING, PrivateValue(mPrev));
|
||||||
|
}
|
||||||
|
|
||||||
|
static ResolvingId *getResolvingId(JSObject *holder) {
|
||||||
|
return (ResolvingId *)holder->getSlot(JSSLOT_RESOLVING).toPrivate();
|
||||||
|
}
|
||||||
|
|
||||||
|
jsid mId;
|
||||||
|
ResolvingId *mPrev;
|
||||||
|
|
||||||
|
private:
|
||||||
|
JSObject *mHolder;
|
||||||
|
};
|
||||||
|
|
||||||
|
static bool
|
||||||
|
IsResolving(JSObject *holder, jsid id)
|
||||||
|
{
|
||||||
|
for (ResolvingId *cur = ResolvingId::getResolvingId(holder); cur; cur = cur->mPrev) {
|
||||||
|
if (cur->mId == id)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
static JSBool
|
static JSBool
|
||||||
holder_get(JSContext *cx, JSObject *holder, jsid id, jsval *vp);
|
holder_get(JSContext *cx, JSObject *holder, jsid id, jsval *vp);
|
||||||
@ -63,15 +108,27 @@ holder_set(JSContext *cx, JSObject *holder, jsid id, jsval *vp);
|
|||||||
static JSBool
|
static JSBool
|
||||||
holder_enumerate(JSContext *cx, JSObject *holder);
|
holder_enumerate(JSContext *cx, JSObject *holder);
|
||||||
|
|
||||||
|
namespace XrayUtils {
|
||||||
|
|
||||||
JSClass HolderClass = {
|
JSClass HolderClass = {
|
||||||
"NativePropertyHolder",
|
"NativePropertyHolder",
|
||||||
JSCLASS_HAS_RESERVED_SLOTS(1),
|
JSCLASS_HAS_RESERVED_SLOTS(3),
|
||||||
JS_PropertyStub, JS_PropertyStub, holder_get, holder_set,
|
JS_PropertyStub, JS_PropertyStub, holder_get, holder_set,
|
||||||
holder_enumerate, JS_ResolveStub, JS_ConvertStub, NULL,
|
holder_enumerate, JS_ResolveStub, JS_ConvertStub, NULL,
|
||||||
NULL, NULL, NULL, NULL,
|
NULL, NULL, NULL, NULL,
|
||||||
NULL, NULL, NULL, NULL
|
NULL, NULL, NULL, NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
using namespace XrayUtils;
|
||||||
|
|
||||||
|
static JSObject *
|
||||||
|
GetHolder(JSObject *obj)
|
||||||
|
{
|
||||||
|
return &obj->getProxyExtra().toObject();
|
||||||
|
}
|
||||||
|
|
||||||
static XPCWrappedNative *
|
static XPCWrappedNative *
|
||||||
GetWrappedNative(JSObject *obj)
|
GetWrappedNative(JSObject *obj)
|
||||||
{
|
{
|
||||||
@ -92,20 +149,19 @@ GetWrappedNativeObjectFromHolder(JSContext *cx, JSObject *holder)
|
|||||||
// getter/setter and rely on the class getter/setter. We install a
|
// getter/setter and rely on the class getter/setter. We install a
|
||||||
// class getter/setter on the holder object to trigger them.
|
// class getter/setter on the holder object to trigger them.
|
||||||
static JSBool
|
static JSBool
|
||||||
holder_get(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
|
holder_get(JSContext *cx, JSObject *wrapper, jsid id, jsval *vp)
|
||||||
{
|
{
|
||||||
if (obj->isWrapper())
|
NS_ASSERTION(wrapper->isProxy(), "bad this object in get");
|
||||||
obj = &obj->getProxyExtra().toObject();
|
JSObject *holder = GetHolder(wrapper);
|
||||||
|
|
||||||
JSObject *wnObject = GetWrappedNativeObjectFromHolder(cx, obj);
|
JSObject *wnObject = GetWrappedNativeObjectFromHolder(cx, holder);
|
||||||
XPCWrappedNative *wn = GetWrappedNative(wnObject);
|
XPCWrappedNative *wn = GetWrappedNative(wnObject);
|
||||||
if (NATIVE_HAS_FLAG(wn, WantGetProperty)) {
|
if (NATIVE_HAS_FLAG(wn, WantGetProperty)) {
|
||||||
JSBool retval = true;
|
JSBool retval = true;
|
||||||
nsresult rv = wn->GetScriptableCallback()->GetProperty(wn, cx, obj, id, vp, &retval);
|
nsresult rv = wn->GetScriptableCallback()->GetProperty(wn, cx, wrapper, id, vp, &retval);
|
||||||
if (NS_FAILED(rv)) {
|
if (NS_FAILED(rv)) {
|
||||||
if (retval) {
|
if (retval)
|
||||||
XPCThrower::Throw(rv, cx);
|
XPCThrower::Throw(rv, cx);
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -113,17 +169,19 @@ holder_get(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static JSBool
|
static JSBool
|
||||||
holder_set(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
|
holder_set(JSContext *cx, JSObject *wrapper, jsid id, jsval *vp)
|
||||||
{
|
{
|
||||||
JSObject *wnObject = GetWrappedNativeObjectFromHolder(cx, obj);
|
NS_ASSERTION(wrapper->isProxy(), "bad this object in set");
|
||||||
|
JSObject *holder = GetHolder(wrapper);
|
||||||
|
JSObject *wnObject = GetWrappedNativeObjectFromHolder(cx, holder);
|
||||||
|
|
||||||
XPCWrappedNative *wn = GetWrappedNative(wnObject);
|
XPCWrappedNative *wn = GetWrappedNative(wnObject);
|
||||||
if (NATIVE_HAS_FLAG(wn, WantSetProperty)) {
|
if (NATIVE_HAS_FLAG(wn, WantSetProperty)) {
|
||||||
JSBool retval = true;
|
JSBool retval = true;
|
||||||
nsresult rv = wn->GetScriptableCallback()->SetProperty(wn, cx, obj, id, vp, &retval);
|
nsresult rv = wn->GetScriptableCallback()->SetProperty(wn, cx, wrapper, id, vp, &retval);
|
||||||
if (NS_FAILED(rv)) {
|
if (NS_FAILED(rv)) {
|
||||||
if (retval) {
|
if (retval)
|
||||||
XPCThrower::Throw(rv, cx);
|
XPCThrower::Throw(rv, cx);
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -131,7 +189,7 @@ holder_set(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
ResolveNativeProperty(JSContext *cx, JSObject *holder, jsid id, bool set,
|
ResolveNativeProperty(JSContext *cx, JSObject *wrapper, JSObject *holder, jsid id, bool set,
|
||||||
JSPropertyDescriptor *desc)
|
JSPropertyDescriptor *desc)
|
||||||
{
|
{
|
||||||
desc->obj = NULL;
|
desc->obj = NULL;
|
||||||
@ -152,8 +210,8 @@ ResolveNativeProperty(JSContext *cx, JSObject *holder, jsid id, bool set,
|
|||||||
JSBool retval = true;
|
JSBool retval = true;
|
||||||
JSObject *pobj = NULL;
|
JSObject *pobj = NULL;
|
||||||
uintN flags = cx->resolveFlags | (set ? JSRESOLVE_ASSIGNING : 0);
|
uintN flags = cx->resolveFlags | (set ? JSRESOLVE_ASSIGNING : 0);
|
||||||
nsresult rv = wn->GetScriptableInfo()->GetCallback()->NewResolve(wn, cx, holder, id, flags,
|
nsresult rv = wn->GetScriptableInfo()->GetCallback()->NewResolve(wn, cx, wrapper, id,
|
||||||
&pobj, &retval);
|
flags, &pobj, &retval);
|
||||||
if (NS_FAILED(rv)) {
|
if (NS_FAILED(rv)) {
|
||||||
if (retval) {
|
if (retval) {
|
||||||
XPCThrower::Throw(rv, cx);
|
XPCThrower::Throw(rv, cx);
|
||||||
@ -161,9 +219,8 @@ ResolveNativeProperty(JSContext *cx, JSObject *holder, jsid id, bool set,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pobj) {
|
if (pobj)
|
||||||
return JS_GetPropertyDescriptorById(cx, pobj, id, cx->resolveFlags, desc);
|
return JS_GetPropertyDescriptorById(cx, pobj, id, cx->resolveFlags, desc);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// There are no native numeric properties, so we can shortcut here. We will not
|
// There are no native numeric properties, so we can shortcut here. We will not
|
||||||
@ -249,12 +306,14 @@ holder_enumerate(JSContext *cx, JSObject *holder)
|
|||||||
if (!ida)
|
if (!ida)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
JSObject *wrapper = &holder->getSlot(JSSLOT_PROXY_OBJ).toObject();
|
||||||
|
|
||||||
// Resolve the underlying native properties onto the holder object
|
// Resolve the underlying native properties onto the holder object
|
||||||
jsid *idp = ida->vector;
|
jsid *idp = ida->vector;
|
||||||
size_t length = ida->length;
|
size_t length = ida->length;
|
||||||
while (length-- > 0) {
|
while (length-- > 0) {
|
||||||
JSPropertyDescriptor dummy;
|
JSPropertyDescriptor dummy;
|
||||||
if (!ResolveNativeProperty(cx, holder, *idp++, false, &dummy))
|
if (!ResolveNativeProperty(cx, wrapper, holder, *idp++, false, &dummy))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@ -266,7 +325,7 @@ static JSBool
|
|||||||
wrappedJSObject_getter(JSContext *cx, JSObject *holder, jsid id, jsval *vp)
|
wrappedJSObject_getter(JSContext *cx, JSObject *holder, jsid id, jsval *vp)
|
||||||
{
|
{
|
||||||
if (holder->isWrapper())
|
if (holder->isWrapper())
|
||||||
holder = &holder->getProxyExtra().toObject();
|
holder = GetHolder(holder);
|
||||||
|
|
||||||
// If the caller intentionally waives the X-ray wrapper we usually
|
// If the caller intentionally waives the X-ray wrapper we usually
|
||||||
// apply for wrapped natives, use a special wrapper to make sure the
|
// apply for wrapped natives, use a special wrapper to make sure the
|
||||||
@ -312,17 +371,26 @@ XrayWrapper<Base, Policy>::getPropertyDescriptor(JSContext *cx, JSObject *wrappe
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
JSObject *holder = GetHolder(wrapper);
|
||||||
|
if (IsResolving(holder, id)) {
|
||||||
|
desc->obj = NULL;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
ResolvingId resolving(holder, id);
|
||||||
|
|
||||||
void *priv;
|
void *priv;
|
||||||
if (!Policy::enter(cx, wrapper, &id, set ? JSWrapper::SET : JSWrapper::GET, &priv))
|
if (!Policy::enter(cx, wrapper, &id, set ? JSWrapper::SET : JSWrapper::GET, &priv))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
JSObject *holder = &wrapper->getProxyExtra().toObject();
|
bool ok = ResolveNativeProperty(cx, wrapper, holder, id, false, desc);
|
||||||
bool ok = ResolveNativeProperty(cx, holder, id, false, desc);
|
|
||||||
|
|
||||||
// TODO expandos
|
|
||||||
|
|
||||||
Policy::leave(cx, wrapper, priv);
|
Policy::leave(cx, wrapper, priv);
|
||||||
return ok;
|
if (!ok || desc->obj)
|
||||||
|
return ok;
|
||||||
|
|
||||||
|
return JS_GetPropertyDescriptorById(cx, holder, id,
|
||||||
|
(set ? JSRESOLVE_ASSIGNING : 0) | JSRESOLVE_QUALIFIED,
|
||||||
|
desc);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Base, typename Policy>
|
template <typename Base, typename Policy>
|
||||||
@ -338,8 +406,24 @@ bool
|
|||||||
XrayWrapper<Base, Policy>::defineProperty(JSContext *cx, JSObject *wrapper, jsid id,
|
XrayWrapper<Base, Policy>::defineProperty(JSContext *cx, JSObject *wrapper, jsid id,
|
||||||
js::PropertyDescriptor *desc)
|
js::PropertyDescriptor *desc)
|
||||||
{
|
{
|
||||||
// XXX When am I called? Implement me!
|
JSObject *holder = GetHolder(wrapper);
|
||||||
return true;
|
PropertyDescriptor existing_desc;
|
||||||
|
if (!getOwnPropertyDescriptor(cx, wrapper, id, true, &existing_desc))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (existing_desc.attrs & JSPROP_PERMANENT)
|
||||||
|
return true; // XXX throw?
|
||||||
|
|
||||||
|
JSPropertyDescriptor *jsdesc = Jsvalify(desc);
|
||||||
|
if (!(jsdesc->attrs & (JSPROP_GETTER | JSPROP_SETTER))) {
|
||||||
|
if (!desc->getter)
|
||||||
|
jsdesc->getter = holder_get;
|
||||||
|
if (!desc->setter)
|
||||||
|
jsdesc->setter = holder_set;
|
||||||
|
}
|
||||||
|
|
||||||
|
return JS_DefinePropertyById(cx, holder, id, jsdesc->value, jsdesc->getter, jsdesc->setter,
|
||||||
|
jsdesc->attrs);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Base, typename Policy>
|
template <typename Base, typename Policy>
|
||||||
@ -434,6 +518,7 @@ XrayWrapper<Base, Policy>::createHolder(JSContext *cx, JSObject *wrappedNative,
|
|||||||
return nsnull;
|
return nsnull;
|
||||||
|
|
||||||
holder->setSlot(JSSLOT_WN_OBJ, ObjectValue(*wrappedNative));
|
holder->setSlot(JSSLOT_WN_OBJ, ObjectValue(*wrappedNative));
|
||||||
|
holder->setSlot(JSSLOT_RESOLVING, PrivateValue(NULL));
|
||||||
return holder;
|
return holder;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -48,7 +48,12 @@
|
|||||||
|
|
||||||
namespace xpc {
|
namespace xpc {
|
||||||
|
|
||||||
|
namespace XrayUtils {
|
||||||
|
|
||||||
extern JSClass HolderClass;
|
extern JSClass HolderClass;
|
||||||
|
extern const uint32 JSSLOT_PROXY_OBJ;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
// NB: Base *must* derive from JSProxyHandler
|
// NB: Base *must* derive from JSProxyHandler
|
||||||
template <typename Base, typename Policy>
|
template <typename Base, typename Policy>
|
||||||
|
Loading…
Reference in New Issue
Block a user