Reviewers: Michael Starzinger,
Description:
Proxies: Fix receiver for setters inherited from proxies.
[email protected]
BUG=v8:1543
TEST=
Please review this at https://chromiumcodereview.appspot.com/10451064/
SVN Base: https://v8.googlecode.com/svn/branches/bleeding_edge
Affected files:
M src/objects.h
M src/objects.cc
M test/mjsunit/harmony/proxies.js
Index: src/objects.cc
diff --git a/src/objects.cc b/src/objects.cc
index
a8970584d8b3e206d6dc0abc89084d8046b5887e..9dd222e0e9989ee57f1b5d0a32f3ab7d50cd740a
100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -248,13 +248,14 @@ MaybeObject* JSProxy::GetElementWithHandler(Object*
receiver,
}
-MaybeObject* JSProxy::SetElementWithHandler(uint32_t index,
+MaybeObject* JSProxy::SetElementWithHandler(JSReceiver* receiver,
+ uint32_t index,
Object* value,
StrictModeFlag strict_mode) {
String* name;
MaybeObject* maybe = GetHeap()->Uint32ToString(index);
if (!maybe->To<String>(&name)) return maybe;
- return SetPropertyWithHandler(name, value, NONE, strict_mode);
+ return SetPropertyWithHandler(receiver, name, value, NONE, strict_mode);
}
@@ -2085,7 +2086,7 @@ MaybeObject*
JSObject::SetElementWithCallbackSetterInPrototypes(
return maybe;
}
return JSProxy::cast(pt)->SetPropertyWithHandlerIfDefiningSetter(
- name, value, NONE, strict_mode, found);
+ this, name, value, NONE, strict_mode, found);
}
if (!JSObject::cast(pt)->HasDictionaryElements()) {
continue;
@@ -2140,7 +2141,7 @@ MaybeObject*
JSObject::SetPropertyWithCallbackSetterInPrototypes(
Handle<Object> hvalue(value);
MaybeObject* result =
accessor_result.proxy()->SetPropertyWithHandlerIfDefiningSetter(
- name, value, attributes, strict_mode, &found);
+ this, name, value, attributes, strict_mode, &found);
if (found) return result;
// The proxy does not define the property as an accessor.
// Consequently, it has no effect on setting the receiver.
@@ -2624,7 +2625,7 @@ MaybeObject* JSReceiver::SetProperty(LookupResult*
result,
StrictModeFlag strict_mode) {
if (result->IsFound() && result->type() == HANDLER) {
return result->proxy()->SetPropertyWithHandler(
- key, value, attributes, strict_mode);
+ this, key, value, attributes, strict_mode);
} else {
return JSObject::cast(this)->SetPropertyForResult(
result, key, value, attributes, strict_mode);
@@ -2648,13 +2649,14 @@ bool JSProxy::HasPropertyWithHandler(String*
name_raw) {
MUST_USE_RESULT MaybeObject* JSProxy::SetPropertyWithHandler(
+ JSReceiver* receiver_raw,
String* name_raw,
Object* value_raw,
PropertyAttributes attributes,
StrictModeFlag strict_mode) {
Isolate* isolate = GetIsolate();
HandleScope scope(isolate);
- Handle<Object> receiver(this);
+ Handle<JSReceiver> receiver(receiver_raw);
Handle<Object> name(name_raw);
Handle<Object> value(value_raw);
@@ -2667,6 +2669,7 @@ MUST_USE_RESULT MaybeObject*
JSProxy::SetPropertyWithHandler(
MUST_USE_RESULT MaybeObject*
JSProxy::SetPropertyWithHandlerIfDefiningSetter(
+ JSReceiver* receiver_raw,
String* name_raw,
Object* value_raw,
PropertyAttributes attributes,
@@ -2674,6 +2677,7 @@ MUST_USE_RESULT MaybeObject*
JSProxy::SetPropertyWithHandlerIfDefiningSetter(
bool* found) {
*found = true; // except where defined otherwise...
Isolate* isolate = GetHeap()->isolate();
+ Handle<JSReceiver> receiver(receiver_raw);
Handle<JSProxy> proxy(this);
Handle<Object> handler(this->handler()); // Trap might morph proxy.
Handle<String> name(name_raw);
@@ -2715,7 +2719,7 @@ MUST_USE_RESULT MaybeObject*
JSProxy::SetPropertyWithHandlerIfDefiningSetter(
if (!setter->IsUndefined()) {
// We have a setter -- invoke it.
// TODO(rossberg): nicer would be to cast to some JSCallable here...
- return proxy->SetPropertyWithDefinedSetter(
+ return receiver->SetPropertyWithDefinedSetter(
JSReceiver::cast(*setter), *value);
} else {
Handle<String> get_name =
isolate->factory()->LookupAsciiSymbol("get_");
@@ -9651,7 +9655,7 @@ MaybeObject* JSReceiver::SetElement(uint32_t index,
bool check_proto) {
if (IsJSProxy()) {
return JSProxy::cast(this)->SetElementWithHandler(
- index, value, strict_mode);
+ this, index, value, strict_mode);
} else {
return JSObject::cast(this)->SetElement(
index, value, attributes, strict_mode, check_proto);
Index: src/objects.h
diff --git a/src/objects.h b/src/objects.h
index
e9dfe6ca55b94b8a923137b3cdfbcd47355ae79e..e2d718534e79e34f35164f2a3e5f60aeeb541029
100644
--- a/src/objects.h
+++ b/src/objects.h
@@ -7708,11 +7708,13 @@ class JSProxy: public JSReceiver {
uint32_t index);
MUST_USE_RESULT MaybeObject* SetPropertyWithHandler(
+ JSReceiver* receiver,
String* name,
Object* value,
PropertyAttributes attributes,
StrictModeFlag strict_mode);
MUST_USE_RESULT MaybeObject* SetElementWithHandler(
+ JSReceiver* receiver,
uint32_t index,
Object* value,
StrictModeFlag strict_mode);
@@ -7720,6 +7722,7 @@ class JSProxy: public JSReceiver {
// If the handler defines an accessor property, invoke its setter
// (or throw if only a getter exists) and set *found to true. Otherwise
false.
MUST_USE_RESULT MaybeObject* SetPropertyWithHandlerIfDefiningSetter(
+ JSReceiver* receiver,
String* name,
Object* value,
PropertyAttributes attributes,
Index: test/mjsunit/harmony/proxies.js
diff --git a/test/mjsunit/harmony/proxies.js
b/test/mjsunit/harmony/proxies.js
index
8d8f83996e255832168fa0c3c5a2d3f117888cb8..35e2afb4c76ccd8273f9731a07410b1b179b3640
100644
--- a/test/mjsunit/harmony/proxies.js
+++ b/test/mjsunit/harmony/proxies.js
@@ -572,6 +572,7 @@ TestSetThrow(Proxy.create({
}))
+var rec
var key
var val
@@ -611,6 +612,7 @@ function TestSetForDerived2(create, handler) {
assertEquals(46, o.p_setter = 46)
assertEquals("p_setter", key)
+ assertSame(o, rec)
assertEquals(46, val) // written to parent
assertFalse(Object.prototype.hasOwnProperty.call(o, "p_setter"))
@@ -641,8 +643,14 @@ TestSetForDerived({
switch (k) {
case "p_writable": return {writable: true, configurable: true}
case "p_nonwritable": return {writable: false, configurable: true}
- case "p_setter":return {set: function(x) { val = x }, configurable:
true}
- case "p_nosetter": return {get: function() { return 1 },
configurable: true}
+ case "p_setter":return {
+ set: function(x) { rec = this; val = x },
+ configurable: true
+ }
+ case "p_nosetter": return {
+ get: function() { return 1 },
+ configurable: true
+ }
case "p_nonconf":return {}
case "p_throw": throw "myexn"
case "p_setterthrow": return {set: function(x) { throw "myexn" }}
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev