From 50fdcca1da0613733ed67c62d6142c0c5634245d Mon Sep 17 00:00:00 2001 From: "rossberg@chromium.org" Date: Tue, 29 May 2012 14:00:56 +0000 Subject: [PATCH] Proxies: Fix receiver for setters inherited from proxies. R=mstarzinger@chromium.org BUG=v8:1543 TEST= Review URL: https://chromiumcodereview.appspot.com/10451064 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@11677 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/objects.cc | 20 ++++++++++++-------- src/objects.h | 3 +++ test/mjsunit/harmony/proxies.js | 12 ++++++++++-- 3 files changed, 25 insertions(+), 10 deletions(-) diff --git a/src/objects.cc b/src/objects.cc index ba460cf..d734fbd 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(&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 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 receiver(this); + Handle receiver(receiver_raw); Handle name(name_raw); Handle 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 receiver(receiver_raw); Handle proxy(this); Handle handler(this->handler()); // Trap might morph proxy. Handle 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 get_name = isolate->factory()->LookupAsciiSymbol("get_"); @@ -9657,7 +9661,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); diff --git a/src/objects.h b/src/objects.h index e9dfe6c..e2d7185 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, diff --git a/test/mjsunit/harmony/proxies.js b/test/mjsunit/harmony/proxies.js index 8b12b38..bb1ebf2 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" }} -- 2.7.4