OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <sstream> | 5 #include <sstream> |
6 | 6 |
7 #include "src/v8.h" | 7 #include "src/v8.h" |
8 | 8 |
9 #include "src/accessors.h" | 9 #include "src/accessors.h" |
10 #include "src/allocation-site-scopes.h" | 10 #include "src/allocation-site-scopes.h" |
(...skipping 3979 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3990 UNREACHABLE(); | 3990 UNREACHABLE(); |
3991 | 3991 |
3992 case LookupIterator::ACCESS_CHECK: | 3992 case LookupIterator::ACCESS_CHECK: |
3993 if (!it.isolate()->MayNamedAccess(object, name, v8::ACCESS_SET)) { | 3993 if (!it.isolate()->MayNamedAccess(object, name, v8::ACCESS_SET)) { |
3994 return SetPropertyWithFailedAccessCheck(&it, value, SLOPPY); | 3994 return SetPropertyWithFailedAccessCheck(&it, value, SLOPPY); |
3995 } | 3995 } |
3996 break; | 3996 break; |
3997 | 3997 |
3998 case LookupIterator::ACCESSOR: { | 3998 case LookupIterator::ACCESSOR: { |
3999 PropertyDetails details = it.property_details(); | 3999 PropertyDetails details = it.property_details(); |
4000 Handle<Object> old_value = it.isolate()->factory()->the_hole_value(); | |
4001 // Ensure the context isn't changed after calling into accessors. | 4000 // Ensure the context isn't changed after calling into accessors. |
4002 AssertNoContextChange ncc(it.isolate()); | 4001 AssertNoContextChange ncc(it.isolate()); |
4003 | 4002 |
4004 Handle<Object> accessors = it.GetAccessors(); | 4003 Handle<Object> accessors = it.GetAccessors(); |
4005 | 4004 |
4006 if (is_observed && accessors->IsAccessorInfo()) { | |
4007 ASSIGN_RETURN_ON_EXCEPTION( | |
4008 it.isolate(), old_value, | |
4009 GetPropertyWithAccessor(it.GetReceiver(), it.name(), | |
4010 it.GetHolder<JSObject>(), accessors), | |
4011 Object); | |
4012 } | |
4013 | |
4014 // Special handling for ExecutableAccessorInfo, which behaves like a | 4005 // Special handling for ExecutableAccessorInfo, which behaves like a |
4015 // data property. | 4006 // data property. |
4016 if (handling == DONT_FORCE_FIELD && | 4007 if (handling == DONT_FORCE_FIELD && |
4017 accessors->IsExecutableAccessorInfo()) { | 4008 accessors->IsExecutableAccessorInfo()) { |
4018 Handle<Object> result; | 4009 Handle<Object> result; |
4019 ASSIGN_RETURN_ON_EXCEPTION( | 4010 ASSIGN_RETURN_ON_EXCEPTION( |
4020 it.isolate(), result, | 4011 it.isolate(), result, |
4021 JSObject::SetPropertyWithAccessor(it.GetReceiver(), it.name(), | 4012 JSObject::SetPropertyWithAccessor(it.GetReceiver(), it.name(), |
4022 value, it.GetHolder<JSObject>(), | 4013 value, it.GetHolder<JSObject>(), |
4023 accessors, STRICT), | 4014 accessors, STRICT), |
4024 Object); | 4015 Object); |
4025 DCHECK(result->SameValue(*value)); | 4016 DCHECK(result->SameValue(*value)); |
4026 | 4017 |
4027 if (details.attributes() == attributes) { | 4018 if (details.attributes() == attributes) { |
4028 // Regular property update if the attributes match. | |
4029 if (is_observed && !old_value->SameValue(*value)) { | |
4030 // If we are setting the prototype of a function and are | |
4031 // observed, don't send change records because the prototype | |
4032 // handles that itself. | |
4033 if (!object->IsJSFunction() || | |
4034 !Name::Equals(it.isolate()->factory()->prototype_string(), | |
4035 name) || | |
4036 !Handle<JSFunction>::cast(object)->should_have_prototype()) { | |
4037 RETURN_ON_EXCEPTION( | |
4038 it.isolate(), | |
4039 EnqueueChangeRecord(object, "update", name, old_value), | |
4040 Object); | |
4041 } | |
4042 } | |
4043 return value; | 4019 return value; |
4044 } | 4020 } |
4045 | 4021 |
4046 // Reconfigure the accessor if attributes mismatch. | 4022 // Reconfigure the accessor if attributes mismatch. |
4047 Handle<ExecutableAccessorInfo> new_data = Accessors::CloneAccessor( | 4023 Handle<ExecutableAccessorInfo> new_data = Accessors::CloneAccessor( |
4048 it.isolate(), Handle<ExecutableAccessorInfo>::cast(accessors)); | 4024 it.isolate(), Handle<ExecutableAccessorInfo>::cast(accessors)); |
4049 new_data->set_property_attributes(attributes); | 4025 new_data->set_property_attributes(attributes); |
4050 // By clearing the setter we don't have to introduce a lookup to | 4026 // By clearing the setter we don't have to introduce a lookup to |
4051 // the setter, simply make it unavailable to reflect the | 4027 // the setter, simply make it unavailable to reflect the |
4052 // attributes. | 4028 // attributes. |
4053 if (attributes & READ_ONLY) new_data->clear_setter(); | 4029 if (attributes & READ_ONLY) new_data->clear_setter(); |
4054 SetPropertyCallback(object, name, new_data, attributes); | 4030 SetPropertyCallback(object, name, new_data, attributes); |
4055 if (is_observed) { | 4031 if (is_observed) { |
4056 if (old_value->SameValue(*value)) { | |
4057 old_value = it.isolate()->factory()->the_hole_value(); | |
4058 } | |
4059 RETURN_ON_EXCEPTION( | 4032 RETURN_ON_EXCEPTION( |
4060 it.isolate(), | 4033 it.isolate(), |
4061 EnqueueChangeRecord(object, "reconfigure", name, old_value), | 4034 EnqueueChangeRecord(object, "reconfigure", name, |
| 4035 it.isolate()->factory()->the_hole_value()), |
4062 Object); | 4036 Object); |
4063 } | 4037 } |
4064 return value; | 4038 return value; |
4065 } | 4039 } |
4066 | 4040 |
4067 it.ReconfigureDataProperty(value, attributes); | 4041 it.ReconfigureDataProperty(value, attributes); |
4068 it.PrepareForDataProperty(value); | 4042 it.PrepareForDataProperty(value); |
4069 it.WriteDataValue(value); | 4043 it.WriteDataValue(value); |
4070 | 4044 |
4071 if (is_observed) { | 4045 if (is_observed) { |
4072 if (old_value->SameValue(*value)) { | |
4073 old_value = it.isolate()->factory()->the_hole_value(); | |
4074 } | |
4075 RETURN_ON_EXCEPTION( | 4046 RETURN_ON_EXCEPTION( |
4076 it.isolate(), | 4047 it.isolate(), |
4077 EnqueueChangeRecord(object, "reconfigure", name, old_value), | 4048 EnqueueChangeRecord(object, "reconfigure", name, |
| 4049 it.isolate()->factory()->the_hole_value()), |
4078 Object); | 4050 Object); |
4079 } | 4051 } |
4080 | 4052 |
4081 return value; | 4053 return value; |
4082 } | 4054 } |
4083 | 4055 |
4084 case LookupIterator::DATA: { | 4056 case LookupIterator::DATA: { |
4085 PropertyDetails details = it.property_details(); | 4057 PropertyDetails details = it.property_details(); |
4086 Handle<Object> old_value = it.isolate()->factory()->the_hole_value(); | 4058 Handle<Object> old_value = it.isolate()->factory()->the_hole_value(); |
4087 // Regular property update if the attributes match. | 4059 // Regular property update if the attributes match. |
(...skipping 12843 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
16931 Handle<DependentCode> codes = | 16903 Handle<DependentCode> codes = |
16932 DependentCode::Insert(handle(cell->dependent_code(), info->isolate()), | 16904 DependentCode::Insert(handle(cell->dependent_code(), info->isolate()), |
16933 DependentCode::kPropertyCellChangedGroup, | 16905 DependentCode::kPropertyCellChangedGroup, |
16934 info->object_wrapper()); | 16906 info->object_wrapper()); |
16935 if (*codes != cell->dependent_code()) cell->set_dependent_code(*codes); | 16907 if (*codes != cell->dependent_code()) cell->set_dependent_code(*codes); |
16936 info->dependencies(DependentCode::kPropertyCellChangedGroup)->Add( | 16908 info->dependencies(DependentCode::kPropertyCellChangedGroup)->Add( |
16937 cell, info->zone()); | 16909 cell, info->zone()); |
16938 } | 16910 } |
16939 | 16911 |
16940 } } // namespace v8::internal | 16912 } } // namespace v8::internal |
OLD | NEW |