| Index: src/runtime.cc
|
| diff --git a/src/runtime.cc b/src/runtime.cc
|
| index dcc76181fe488a0aa27a7c734cb7a5be706df303..fff5a319b54c78970c71c346ee7a9e8914dcc613 100644
|
| --- a/src/runtime.cc
|
| +++ b/src/runtime.cc
|
| @@ -1098,8 +1098,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_ClassOf) {
|
| RUNTIME_FUNCTION(MaybeObject*, Runtime_GetPrototype) {
|
| NoHandleAllocation ha(isolate);
|
| ASSERT(args.length() == 1);
|
| - CONVERT_ARG_CHECKED(JSReceiver, input_obj, 0);
|
| - Object* obj = input_obj;
|
| + CONVERT_ARG_CHECKED(Object, obj, 0);
|
| // We don't expect access checks to be needed on JSProxy objects.
|
| ASSERT(!obj->IsAccessCheckNeeded() || obj->IsJSObject());
|
| do {
|
| @@ -1117,12 +1116,43 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetPrototype) {
|
| }
|
|
|
|
|
| +static inline Object* GetPrototypeSkipHiddenPrototypes(Isolate* isolate,
|
| + Object* receiver) {
|
| + Object* current = receiver->GetPrototype(isolate);
|
| + while (current->IsJSObject() &&
|
| + JSObject::cast(current)->map()->is_hidden_prototype()) {
|
| + current = current->GetPrototype(isolate);
|
| + }
|
| + return current;
|
| +}
|
| +
|
| +
|
| RUNTIME_FUNCTION(MaybeObject*, Runtime_SetPrototype) {
|
| NoHandleAllocation ha(isolate);
|
| ASSERT(args.length() == 2);
|
| - CONVERT_ARG_CHECKED(JSReceiver, input_obj, 0);
|
| + CONVERT_ARG_CHECKED(JSObject, obj, 0);
|
| CONVERT_ARG_CHECKED(Object, prototype, 1);
|
| - return input_obj->SetPrototype(prototype, true);
|
| + if (FLAG_harmony_observation && obj->map()->is_observed()) {
|
| + HandleScope scope(isolate);
|
| + Handle<JSObject> receiver(obj);
|
| + Handle<Object> value(prototype, isolate);
|
| + Handle<Object> old_value(
|
| + GetPrototypeSkipHiddenPrototypes(isolate, *receiver), isolate);
|
| +
|
| + MaybeObject* result = receiver->SetPrototype(*value, true);
|
| + Handle<Object> hresult;
|
| + if (!result->ToHandle(&hresult, isolate)) return result;
|
| +
|
| + Handle<Object> new_value(
|
| + GetPrototypeSkipHiddenPrototypes(isolate, *receiver), isolate);
|
| + if (!new_value->SameValue(*old_value)) {
|
| + JSObject::EnqueueChangeRecord(receiver, "prototype",
|
| + isolate->factory()->proto_string(),
|
| + old_value);
|
| + }
|
| + return *hresult;
|
| + }
|
| + return obj->SetPrototype(prototype, true);
|
| }
|
|
|
|
|
| @@ -4251,14 +4281,6 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DefineOrRedefineDataProperty) {
|
| if (callback->IsAccessorInfo()) {
|
| return isolate->heap()->undefined_value();
|
| }
|
| - // TODO(mstarzinger): The __proto__ property should actually be a real
|
| - // JavaScript accessor instead of a foreign callback. But for now we just
|
| - // avoid changing the writability and configurability attribute of this
|
| - // property.
|
| - Handle<Name> proto_string = isolate->factory()->proto_string();
|
| - if (callback->IsForeign() && proto_string->Equals(*name)) {
|
| - attr = static_cast<PropertyAttributes>(attr & ~(READ_ONLY | DONT_DELETE));
|
| - }
|
| // Avoid redefining foreign callback as data property, just use the stored
|
| // setter to update the value instead.
|
| // TODO(mstarzinger): So far this only works if property attributes don't
|
| @@ -12167,11 +12189,8 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugConstructedBy) {
|
| RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugGetPrototype) {
|
| NoHandleAllocation ha(isolate);
|
| ASSERT(args.length() == 1);
|
| -
|
| CONVERT_ARG_CHECKED(JSObject, obj, 0);
|
| -
|
| - // Use the __proto__ accessor.
|
| - return Accessors::ObjectPrototype.getter(obj, NULL);
|
| + return GetPrototypeSkipHiddenPrototypes(isolate, obj);
|
| }
|
|
|
|
|
|
|