Bug 1090537, part 3 - Pass receiver argument through from JSObject::setGeneric and setElement to Proxy::set. r=efaust.

ES6 specifies [[Set]] as an operation taking both a "this" object and a "receiver" parameter. Both JSObject::setGeneric and Proxy::set support the receiver parameter, but ObjectOps::setGeneric does not; in this patch, we add a little workaround for that. The test shows how this is observable using only standard builtins.

The changes in JSObject::setElement are untestable since currently all call sites pass the same value for obj as for receiver.

(This was reviewed as "part 2" but it was necessary to switch parts 2 and 3 and add part 2b.)

--HG--
extra : rebase_source : 617decfa9be34b01a0f923a9717ad2544d913af9
This commit is contained in:
Jason Orendorff 2014-10-15 22:54:57 -05:00
Родитель 2c1490915a
Коммит 7915208511
4 изменённых файлов: 30 добавлений и 6 удалений

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

@ -0,0 +1,15 @@
// The receiver argument is passed through proxies with no "set" handler.
var hits;
var a = new Proxy({}, {
set(t, id, value, receiver) {
assertEq(id, "prop");
assertEq(value, 3);
assertEq(receiver, b);
hits++;
}
});
var b = new Proxy(a, {});
hits = 0;
b.prop = 3;
assertEq(hits, 1);

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

@ -1840,7 +1840,7 @@ js::CreateThisForFunction(JSContext *cx, HandleObject callee, NewObjectKind newK
}
/* static */ bool
JSObject::nonNativeSetProperty(JSContext *cx, HandleObject obj,
JSObject::nonNativeSetProperty(JSContext *cx, HandleObject obj, HandleObject receiver,
HandleId id, MutableHandleValue vp, bool strict)
{
if (MOZ_UNLIKELY(obj->watched())) {
@ -1848,11 +1848,13 @@ JSObject::nonNativeSetProperty(JSContext *cx, HandleObject obj,
if (wpmap && !wpmap->triggerWatchpoint(cx, obj, id, vp))
return false;
}
if (obj->is<ProxyObject>())
return Proxy::set(cx, obj, receiver, id, strict, vp);
return obj->getOps()->setGeneric(cx, obj, id, vp, strict);
}
/* static */ bool
JSObject::nonNativeSetElement(JSContext *cx, HandleObject obj,
JSObject::nonNativeSetElement(JSContext *cx, HandleObject obj, HandleObject receiver,
uint32_t index, MutableHandleValue vp, bool strict)
{
if (MOZ_UNLIKELY(obj->watched())) {
@ -1864,6 +1866,11 @@ JSObject::nonNativeSetElement(JSContext *cx, HandleObject obj,
if (wpmap && !wpmap->triggerWatchpoint(cx, obj, id, vp))
return false;
}
if (obj->is<ProxyObject>()) {
RootedId id(cx);
return IndexToId(cx, index, &id) &&
Proxy::set(cx, obj, receiver, id, strict, vp);
}
return obj->getOps()->setElement(cx, obj, index, vp, strict);
}

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

@ -655,9 +655,11 @@ class JSObject : public js::gc::Cell
uint32_t index, js::MutableHandleValue vp, bool strict);
static bool nonNativeSetProperty(JSContext *cx, js::HandleObject obj,
js::HandleId id, js::MutableHandleValue vp, bool strict);
js::HandleObject receiver, js::HandleId id,
js::MutableHandleValue vp, bool strict);
static bool nonNativeSetElement(JSContext *cx, js::HandleObject obj,
uint32_t index, js::MutableHandleValue vp, bool strict);
js::HandleObject receiver, uint32_t index,
js::MutableHandleValue vp, bool strict);
static inline bool getGenericAttributes(JSContext *cx, js::HandleObject obj,
js::HandleId id, unsigned *attrsp);

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

@ -1414,7 +1414,7 @@ JSObject::setGeneric(JSContext *cx, js::HandleObject obj, js::HandleObject recei
js::HandleId id, js::MutableHandleValue vp, bool strict)
{
if (obj->getOps()->setGeneric)
return nonNativeSetProperty(cx, obj, id, vp, strict);
return nonNativeSetProperty(cx, obj, receiver, id, vp, strict);
return js::baseops::SetPropertyHelper<js::SequentialExecution>(
cx, obj.as<js::NativeObject>(), receiver, id, js::baseops::Qualified, vp, strict);
}
@ -1424,7 +1424,7 @@ JSObject::setElement(JSContext *cx, js::HandleObject obj, js::HandleObject recei
uint32_t index, js::MutableHandleValue vp, bool strict)
{
if (obj->getOps()->setElement)
return nonNativeSetElement(cx, obj, index, vp, strict);
return nonNativeSetElement(cx, obj, receiver, index, vp, strict);
return js::baseops::SetElementHelper(cx, obj.as<js::NativeObject>(),
receiver, index, vp, strict);
}