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 "src/objects.h" | 5 #include "src/objects.h" |
6 | 6 |
7 #include <cmath> | 7 #include <cmath> |
8 #include <iomanip> | 8 #include <iomanip> |
9 #include <sstream> | 9 #include <sstream> |
10 | 10 |
(...skipping 6036 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6047 Isolate* isolate = it->isolate(); | 6047 Isolate* isolate = it->isolate(); |
6048 // == OrdinaryDefineOwnProperty (O, P, Desc) == | 6048 // == OrdinaryDefineOwnProperty (O, P, Desc) == |
6049 // 1. Let current be O.[[GetOwnProperty]](P). | 6049 // 1. Let current be O.[[GetOwnProperty]](P). |
6050 // 2. ReturnIfAbrupt(current). | 6050 // 2. ReturnIfAbrupt(current). |
6051 PropertyDescriptor current; | 6051 PropertyDescriptor current; |
6052 if (!GetOwnPropertyDescriptor(it, ¤t) && | 6052 if (!GetOwnPropertyDescriptor(it, ¤t) && |
6053 isolate->has_pending_exception()) { | 6053 isolate->has_pending_exception()) { |
6054 return false; | 6054 return false; |
6055 } | 6055 } |
6056 // 3. Let extensible be the value of the [[Extensible]] internal slot of O. | 6056 // 3. Let extensible be the value of the [[Extensible]] internal slot of O. |
6057 Handle<JSObject> object = Handle<JSObject>::cast(it->GetReceiver()); | 6057 Handle<JSObject> o = Handle<JSObject>::cast(it->GetReceiver()); |
6058 bool extensible = JSObject::IsExtensible(object); | 6058 bool extensible = JSObject::IsExtensible(o); |
6059 | 6059 |
6060 bool desc_is_data_descriptor = PropertyDescriptor::IsDataDescriptor(desc); | 6060 bool desc_is_data_descriptor = PropertyDescriptor::IsDataDescriptor(desc); |
6061 bool desc_is_accessor_descriptor = | 6061 bool desc_is_accessor_descriptor = |
6062 PropertyDescriptor::IsAccessorDescriptor(desc); | 6062 PropertyDescriptor::IsAccessorDescriptor(desc); |
6063 bool desc_is_generic_descriptor = | 6063 bool desc_is_generic_descriptor = |
6064 PropertyDescriptor::IsGenericDescriptor(desc); | 6064 PropertyDescriptor::IsGenericDescriptor(desc); |
6065 | 6065 |
6066 // == ValidateAndApplyPropertyDescriptor (O, P, extensible, Desc, current) == | 6066 // == ValidateAndApplyPropertyDescriptor (O, P, extensible, Desc, current) == |
6067 // 2. If current is undefined, then | 6067 // 2. If current is undefined, then |
6068 if (current.is_empty()) { | 6068 if (current.is_empty()) { |
6069 // 2a. If extensible is false, return false. | 6069 // 2a. If extensible is false, return false. |
6070 if (!extensible) { | 6070 if (!extensible) { |
6071 if (should_throw == THROW_ON_ERROR) { | 6071 if (should_throw == THROW_ON_ERROR) { |
6072 isolate->Throw(*isolate->factory()->NewTypeError( | 6072 isolate->Throw(*isolate->factory()->NewTypeError( |
6073 MessageTemplate::kDefineDisallowed, it->GetName())); | 6073 MessageTemplate::kDefineDisallowed, it->GetName())); |
6074 } | 6074 } |
6075 return false; | 6075 return false; |
6076 } | 6076 } |
6077 // We have to reset the LookupIterator to handle interceptors properly. | 6077 // We have to use a fresh LookupIterator to handle interceptors properly. |
6078 Map* map = Handle<HeapObject>::cast(object)->map(); | 6078 LookupIterator lookup_for_store = |
6079 if ((it->IsElement() && map->has_indexed_interceptor()) || | 6079 it->IsElement() ? LookupIterator(isolate, it->GetReceiver(), |
6080 (!it->IsElement() && map->has_named_interceptor())) { | 6080 it->index(), LookupIterator::HIDDEN) |
6081 it->Restart(); | 6081 : LookupIterator(it->GetReceiver(), it->name(), |
6082 } | 6082 LookupIterator::HIDDEN); |
6083 | 6083 |
6084 // 2c. If IsGenericDescriptor(Desc) or IsDataDescriptor(Desc) is true, then: | 6084 // 2c. If IsGenericDescriptor(Desc) or IsDataDescriptor(Desc) is true, then: |
6085 // (This is equivalent to !IsAccessorDescriptor(desc).) | 6085 // (This is equivalent to !IsAccessorDescriptor(desc).) |
6086 DCHECK((desc_is_generic_descriptor || desc_is_data_descriptor) == | 6086 DCHECK((desc_is_generic_descriptor || desc_is_data_descriptor) == |
6087 !desc_is_accessor_descriptor); | 6087 !desc_is_accessor_descriptor); |
6088 if (!desc_is_accessor_descriptor) { | 6088 if (!desc_is_accessor_descriptor) { |
6089 // 2c i. If O is not undefined, create an own data property named P of | 6089 // 2c i. If O is not undefined, create an own data property named P of |
6090 // object O whose [[Value]], [[Writable]], [[Enumerable]] and | 6090 // object O whose [[Value]], [[Writable]], [[Enumerable]] and |
6091 // [[Configurable]] attribute values are described by Desc. If the value | 6091 // [[Configurable]] attribute values are described by Desc. If the value |
6092 // of an attribute field of Desc is absent, the attribute of the newly | 6092 // of an attribute field of Desc is absent, the attribute of the newly |
6093 // created property is set to its default value. | 6093 // created property is set to its default value. |
6094 if (!object->IsUndefined()) { | 6094 if (!o->IsUndefined()) { |
6095 if (!desc->has_writable()) desc->set_writable(false); | 6095 if (!desc->has_writable()) desc->set_writable(false); |
6096 if (!desc->has_enumerable()) desc->set_enumerable(false); | 6096 if (!desc->has_enumerable()) desc->set_enumerable(false); |
6097 if (!desc->has_configurable()) desc->set_configurable(false); | 6097 if (!desc->has_configurable()) desc->set_configurable(false); |
6098 Handle<Object> value( | 6098 Handle<Object> value( |
6099 desc->has_value() | 6099 desc->has_value() |
6100 ? desc->value() | 6100 ? desc->value() |
6101 : Handle<Object>::cast(isolate->factory()->undefined_value())); | 6101 : Handle<Object>::cast(isolate->factory()->undefined_value())); |
6102 MaybeHandle<Object> result = | 6102 MaybeHandle<Object> result = |
6103 JSObject::DefineOwnPropertyIgnoreAttributes( | 6103 JSObject::DefineOwnPropertyIgnoreAttributes( |
6104 it, value, desc->ToAttributes(), JSObject::DONT_FORCE_FIELD); | 6104 &lookup_for_store, value, desc->ToAttributes(), |
| 6105 JSObject::DONT_FORCE_FIELD); |
6105 if (result.is_null()) return false; | 6106 if (result.is_null()) return false; |
6106 } | 6107 } |
6107 } else { | 6108 } else { |
6108 // 2d. Else Desc must be an accessor Property Descriptor, | 6109 // 2d. Else Desc must be an accessor Property Descriptor, |
6109 DCHECK(desc_is_accessor_descriptor); | 6110 DCHECK(desc_is_accessor_descriptor); |
6110 // 2d i. If O is not undefined, create an own accessor property named P | 6111 // 2d i. If O is not undefined, create an own accessor property named P |
6111 // of object O whose [[Get]], [[Set]], [[Enumerable]] and | 6112 // of object O whose [[Get]], [[Set]], [[Enumerable]] and |
6112 // [[Configurable]] attribute values are described by Desc. If the value | 6113 // [[Configurable]] attribute values are described by Desc. If the value |
6113 // of an attribute field of Desc is absent, the attribute of the newly | 6114 // of an attribute field of Desc is absent, the attribute of the newly |
6114 // created property is set to its default value. | 6115 // created property is set to its default value. |
6115 if (!object->IsUndefined()) { | 6116 if (!o->IsUndefined()) { |
6116 if (!desc->has_enumerable()) desc->set_enumerable(false); | 6117 if (!desc->has_enumerable()) desc->set_enumerable(false); |
6117 if (!desc->has_configurable()) desc->set_configurable(false); | 6118 if (!desc->has_configurable()) desc->set_configurable(false); |
6118 Handle<Object> getter( | 6119 Handle<Object> getter( |
6119 desc->has_get() | 6120 desc->has_get() |
6120 ? desc->get() | 6121 ? desc->get() |
6121 : Handle<Object>::cast(isolate->factory()->undefined_value())); | 6122 : Handle<Object>::cast(isolate->factory()->undefined_value())); |
6122 Handle<Object> setter( | 6123 Handle<Object> setter( |
6123 desc->has_set() | 6124 desc->has_set() |
6124 ? desc->set() | 6125 ? desc->set() |
6125 : Handle<Object>::cast(isolate->factory()->undefined_value())); | 6126 : Handle<Object>::cast(isolate->factory()->undefined_value())); |
6126 MaybeHandle<Object> result = | 6127 MaybeHandle<Object> result = JSObject::DefineAccessor( |
6127 JSObject::DefineAccessor(it, getter, setter, desc->ToAttributes()); | 6128 &lookup_for_store, getter, setter, desc->ToAttributes()); |
6128 if (result.is_null()) return false; | 6129 if (result.is_null()) return false; |
6129 } | 6130 } |
6130 } | 6131 } |
6131 // 2e. Return true. | 6132 // 2e. Return true. |
6132 return true; | 6133 return true; |
6133 } | 6134 } |
6134 // 3. Return true, if every field in Desc is absent. | 6135 // 3. Return true, if every field in Desc is absent. |
6135 // 4. Return true, if every field in Desc also occurs in current and the | 6136 // 4. Return true, if every field in Desc also occurs in current and the |
6136 // value of every field in Desc is the same value as the corresponding field | 6137 // value of every field in Desc is the same value as the corresponding field |
6137 // in current when compared using the SameValue algorithm. | 6138 // in current when compared using the SameValue algorithm. |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6205 } | 6206 } |
6206 | 6207 |
6207 // 8. Else if IsDataDescriptor(current) and IsDataDescriptor(Desc) are both | 6208 // 8. Else if IsDataDescriptor(current) and IsDataDescriptor(Desc) are both |
6208 // true, then: | 6209 // true, then: |
6209 } else if (current_is_data_descriptor && desc_is_data_descriptor) { | 6210 } else if (current_is_data_descriptor && desc_is_data_descriptor) { |
6210 // 8a. If the [[Configurable]] field of current is false, then: | 6211 // 8a. If the [[Configurable]] field of current is false, then: |
6211 if (!current.configurable()) { | 6212 if (!current.configurable()) { |
6212 // [Strong mode] Disallow changing writable -> readonly for | 6213 // [Strong mode] Disallow changing writable -> readonly for |
6213 // non-configurable properties. | 6214 // non-configurable properties. |
6214 if (current.writable() && desc->has_writable() && !desc->writable() && | 6215 if (current.writable() && desc->has_writable() && !desc->writable() && |
6215 object->map()->is_strong()) { | 6216 o->map()->is_strong()) { |
6216 if (should_throw == THROW_ON_ERROR) { | 6217 if (should_throw == THROW_ON_ERROR) { |
6217 isolate->Throw(*isolate->factory()->NewTypeError( | 6218 isolate->Throw(*isolate->factory()->NewTypeError( |
6218 MessageTemplate::kStrongRedefineDisallowed, object, | 6219 MessageTemplate::kStrongRedefineDisallowed, o, it->GetName())); |
6219 it->GetName())); | |
6220 } | 6220 } |
6221 return false; | 6221 return false; |
6222 } | 6222 } |
6223 // 8a i. Return false, if the [[Writable]] field of current is false and | 6223 // 8a i. Return false, if the [[Writable]] field of current is false and |
6224 // the [[Writable]] field of Desc is true. | 6224 // the [[Writable]] field of Desc is true. |
6225 if (!current.writable() && desc->has_writable() && desc->writable()) { | 6225 if (!current.writable() && desc->has_writable() && desc->writable()) { |
6226 if (should_throw == THROW_ON_ERROR) { | 6226 if (should_throw == THROW_ON_ERROR) { |
6227 isolate->Throw(*isolate->factory()->NewTypeError( | 6227 isolate->Throw(*isolate->factory()->NewTypeError( |
6228 MessageTemplate::kRedefineDisallowed, it->GetName())); | 6228 MessageTemplate::kRedefineDisallowed, it->GetName())); |
6229 } | 6229 } |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6264 if (should_throw == THROW_ON_ERROR) { | 6264 if (should_throw == THROW_ON_ERROR) { |
6265 isolate->Throw(*isolate->factory()->NewTypeError( | 6265 isolate->Throw(*isolate->factory()->NewTypeError( |
6266 MessageTemplate::kRedefineDisallowed, it->GetName())); | 6266 MessageTemplate::kRedefineDisallowed, it->GetName())); |
6267 } | 6267 } |
6268 return false; | 6268 return false; |
6269 } | 6269 } |
6270 } | 6270 } |
6271 } | 6271 } |
6272 | 6272 |
6273 // 10. If O is not undefined, then: | 6273 // 10. If O is not undefined, then: |
6274 if (!object->IsUndefined()) { | 6274 if (!o->IsUndefined()) { |
6275 // 10a. For each field of Desc that is present, set the corresponding | 6275 // 10a. For each field of Desc that is present, set the corresponding |
6276 // attribute of the property named P of object O to the value of the field. | 6276 // attribute of the property named P of object O to the value of the field. |
6277 PropertyAttributes attrs = NONE; | 6277 PropertyAttributes attrs = NONE; |
6278 | 6278 |
6279 if (desc->has_enumerable()) { | 6279 if (desc->has_enumerable()) { |
6280 attrs = static_cast<PropertyAttributes>( | 6280 attrs = static_cast<PropertyAttributes>( |
6281 attrs | (desc->enumerable() ? NONE : DONT_ENUM)); | 6281 attrs | (desc->enumerable() ? NONE : DONT_ENUM)); |
6282 } else { | 6282 } else { |
6283 attrs = static_cast<PropertyAttributes>( | 6283 attrs = static_cast<PropertyAttributes>( |
6284 attrs | (current.enumerable() ? NONE : DONT_ENUM)); | 6284 attrs | (current.enumerable() ? NONE : DONT_ENUM)); |
(...skipping 11547 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
17832 if (cell->value() != *new_value) { | 17832 if (cell->value() != *new_value) { |
17833 cell->set_value(*new_value); | 17833 cell->set_value(*new_value); |
17834 Isolate* isolate = cell->GetIsolate(); | 17834 Isolate* isolate = cell->GetIsolate(); |
17835 cell->dependent_code()->DeoptimizeDependentCodeGroup( | 17835 cell->dependent_code()->DeoptimizeDependentCodeGroup( |
17836 isolate, DependentCode::kPropertyCellChangedGroup); | 17836 isolate, DependentCode::kPropertyCellChangedGroup); |
17837 } | 17837 } |
17838 } | 17838 } |
17839 | 17839 |
17840 } // namespace internal | 17840 } // namespace internal |
17841 } // namespace v8 | 17841 } // namespace v8 |
OLD | NEW |