Bug 1105045 - Outerize the receiver passed to proxy hooks. r=efaust.

--HG--
extra : commitid : G8ZDWGn76fj
extra : rebase_source : 36759c408e28660aa958a1683743d972f2b96986
This commit is contained in:
Jason Orendorff 2015-08-07 10:23:05 -05:00
Родитель 90259502e7
Коммит 8016bfee38
3 изменённых файлов: 52 добавлений и 3 удалений

Просмотреть файл

@ -1004,7 +1004,8 @@ GetObjectClassName(JSContext* cx, HandleObject obj);
*/
/*
* If obj a WindowProxy, return its current inner Window. Otherwise return obj.
* If obj is a WindowProxy, return its current inner Window. Otherwise return
* obj. This function can't fail and never returns nullptr.
*
* GetInnerObject is called when we need a scope chain; you never want a
* WindowProxy on a scope chain.
@ -1027,6 +1028,7 @@ GetInnerObject(JSObject* obj)
/*
* If obj is a Window object, return the WindowProxy. Otherwise return obj.
* This function can't fail; it never sets an exception or returns nullptr.
*
* This must be called before passing an object to script, if the object might
* be a Window. (But usually those cases involve scope objects, and for those,

Просмотреть файл

@ -260,8 +260,18 @@ Proxy::hasOwn(JSContext* cx, HandleObject proxy, HandleId id, bool* bp)
return handler->hasOwn(cx, proxy, id, bp);
}
static Value
OuterizeValue(JSContext* cx, HandleValue v)
{
if (v.isObject()) {
RootedObject obj(cx, &v.toObject());
return ObjectValue(*GetOuterObject(cx, obj));
}
return v;
}
bool
Proxy::get(JSContext* cx, HandleObject proxy, HandleObject receiver, HandleId id,
Proxy::get(JSContext* cx, HandleObject proxy, HandleObject receiver_, HandleId id,
MutableHandleValue vp)
{
JS_CHECK_RECURSION(cx, return false);
@ -271,6 +281,10 @@ Proxy::get(JSContext* cx, HandleObject proxy, HandleObject receiver, HandleId id
if (!policy.allowed())
return policy.returnValue();
// Outerize the receiver. Proxy handlers shouldn't have to know about
// the Window/WindowProxy distinction.
RootedObject receiver(cx, GetOuterObject(cx, receiver_));
if (handler->hasPrototype()) {
bool own;
if (!handler->hasOwn(cx, proxy, id, &own))
@ -308,7 +322,7 @@ Proxy::callProp(JSContext* cx, HandleObject proxy, HandleObject receiver, Handle
}
bool
Proxy::set(JSContext* cx, HandleObject proxy, HandleId id, HandleValue v, HandleValue receiver,
Proxy::set(JSContext* cx, HandleObject proxy, HandleId id, HandleValue v, HandleValue receiver_,
ObjectOpResult& result)
{
JS_CHECK_RECURSION(cx, return false);
@ -320,6 +334,10 @@ Proxy::set(JSContext* cx, HandleObject proxy, HandleId id, HandleValue v, Handle
return result.succeed();
}
// Outerize the receiver. Proxy handlers shouldn't have to know about
// the Window/WindowProxy distinction.
RootedValue receiver(cx, OuterizeValue(cx, receiver_));
// Special case. See the comment on BaseProxyHandler::mHasPrototype.
if (handler->hasPrototype())
return handler->BaseProxyHandler::set(cx, proxy, id, v, receiver, result);

Просмотреть файл

@ -0,0 +1,29 @@
// The global object can be the receiver passed to the get and set traps of a Proxy.
var global = this;
var proto = Object.getPrototypeOf(global);
var gets = 0, sets = 0;
Object.setPrototypeOf(global, new Proxy(proto, {
has(t, id) {
return id === "bareword" || Reflect.has(t, id);
},
get(t, id, r) {
gets++;
assertEq(r, global);
return Reflect.get(t, id, r);
},
set(t, id, v, r) {
sets++;
assertEq(r, global);
return Reflect.set(t, id, v, r);
}
}));
assertEq(bareword, undefined);
assertEq(gets, 1);
bareword = 12;
assertEq(sets, 1);
assertEq(global.bareword, 12);
reportCompare(0, 0);