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 6006 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6017 bool JSReceiver::OrdinaryDefineOwnProperty(Isolate* isolate, | 6017 bool JSReceiver::OrdinaryDefineOwnProperty(Isolate* isolate, |
6018 Handle<JSObject> object, | 6018 Handle<JSObject> object, |
6019 Handle<Object> key, | 6019 Handle<Object> key, |
6020 PropertyDescriptor* desc, | 6020 PropertyDescriptor* desc, |
6021 ShouldThrow should_throw) { | 6021 ShouldThrow should_throw) { |
6022 bool success = false; | 6022 bool success = false; |
6023 DCHECK(key->IsName() || key->IsNumber()); // |key| is a PropertyKey... | 6023 DCHECK(key->IsName() || key->IsNumber()); // |key| is a PropertyKey... |
6024 LookupIterator it = LookupIterator::PropertyOrElement( | 6024 LookupIterator it = LookupIterator::PropertyOrElement( |
6025 isolate, object, key, &success, LookupIterator::HIDDEN); | 6025 isolate, object, key, &success, LookupIterator::HIDDEN); |
6026 DCHECK(success); // ...so creating a LookupIterator can't fail. | 6026 DCHECK(success); // ...so creating a LookupIterator can't fail. |
6027 | |
6028 // Deal with access checks first. | |
6029 if (it.state() == LookupIterator::ACCESS_CHECK) { | |
6030 if (!it.HasAccess()) { | |
6031 isolate->ReportFailedAccessCheck(it.GetHolder<JSObject>()); | |
6032 RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, false); | |
6033 return false; | |
6034 } | |
6035 it.Next(); | |
6036 } | |
6037 | |
6038 return OrdinaryDefineOwnProperty(&it, desc, should_throw); | 6027 return OrdinaryDefineOwnProperty(&it, desc, should_throw); |
6039 } | 6028 } |
6040 | 6029 |
6041 | 6030 |
6042 // ES6 9.1.6.1 | 6031 // ES6 9.1.6.1 |
6043 // static | 6032 // static |
6044 bool JSReceiver::OrdinaryDefineOwnProperty(LookupIterator* it, | 6033 bool JSReceiver::OrdinaryDefineOwnProperty(LookupIterator* it, |
6045 PropertyDescriptor* desc, | 6034 PropertyDescriptor* desc, |
6046 ShouldThrow should_throw) { | 6035 ShouldThrow should_throw) { |
6047 Isolate* isolate = it->isolate(); | 6036 Isolate* isolate = it->isolate(); |
6048 // == OrdinaryDefineOwnProperty (O, P, Desc) == | 6037 // == OrdinaryDefineOwnProperty (O, P, Desc) == |
6049 // 1. Let current be O.[[GetOwnProperty]](P). | 6038 // 1. Let current be O.[[GetOwnProperty]](P). |
6050 // 2. ReturnIfAbrupt(current). | 6039 // 2. ReturnIfAbrupt(current). |
6051 PropertyDescriptor current; | 6040 PropertyDescriptor current; |
6052 if (!GetOwnPropertyDescriptor(it, ¤t) && | 6041 if (!GetOwnPropertyDescriptor(it, ¤t) && |
6053 isolate->has_pending_exception()) { | 6042 isolate->has_pending_exception()) { |
6054 return false; | 6043 return false; |
6055 } | 6044 } |
6056 // TODO(jkummerow/verwaest): It would be nice if we didn't have to reset | |
6057 // the iterator every time. Currently, the reasons why we need it are: | |
6058 // - handle interceptors correctly | |
6059 // - handle accessors correctly (which might change the holder's map) | |
6060 it->Restart(); | |
6061 // 3. Let extensible be the value of the [[Extensible]] internal slot of O. | 6045 // 3. Let extensible be the value of the [[Extensible]] internal slot of O. |
6062 Handle<JSObject> object = Handle<JSObject>::cast(it->GetReceiver()); | 6046 Handle<JSObject> o = Handle<JSObject>::cast(it->GetReceiver()); |
6063 bool extensible = JSObject::IsExtensible(object); | 6047 bool extensible = JSObject::IsExtensible(o); |
6064 | 6048 |
6065 bool desc_is_data_descriptor = PropertyDescriptor::IsDataDescriptor(desc); | 6049 bool desc_is_data_descriptor = PropertyDescriptor::IsDataDescriptor(desc); |
6066 bool desc_is_accessor_descriptor = | 6050 bool desc_is_accessor_descriptor = |
6067 PropertyDescriptor::IsAccessorDescriptor(desc); | 6051 PropertyDescriptor::IsAccessorDescriptor(desc); |
6068 bool desc_is_generic_descriptor = | 6052 bool desc_is_generic_descriptor = |
6069 PropertyDescriptor::IsGenericDescriptor(desc); | 6053 PropertyDescriptor::IsGenericDescriptor(desc); |
6070 | 6054 |
6071 // == ValidateAndApplyPropertyDescriptor (O, P, extensible, Desc, current) == | 6055 // == ValidateAndApplyPropertyDescriptor (O, P, extensible, Desc, current) == |
6072 // 2. If current is undefined, then | 6056 // 2. If current is undefined, then |
6073 if (current.is_empty()) { | 6057 if (current.is_empty()) { |
6074 // 2a. If extensible is false, return false. | 6058 // 2a. If extensible is false, return false. |
6075 if (!extensible) { | 6059 if (!extensible) { |
6076 if (should_throw == THROW_ON_ERROR) { | 6060 if (should_throw == THROW_ON_ERROR) { |
6077 isolate->Throw(*isolate->factory()->NewTypeError( | 6061 isolate->Throw(*isolate->factory()->NewTypeError( |
6078 MessageTemplate::kDefineDisallowed, it->GetName())); | 6062 MessageTemplate::kDefineDisallowed, it->GetName())); |
6079 } | 6063 } |
6080 return false; | 6064 return false; |
6081 } | 6065 } |
6082 // 2c. If IsGenericDescriptor(Desc) or IsDataDescriptor(Desc) is true, then: | 6066 // 2c. If IsGenericDescriptor(Desc) or IsDataDescriptor(Desc) is true, then: |
6083 // (This is equivalent to !IsAccessorDescriptor(desc).) | 6067 // (This is equivalent to !IsAccessorDescriptor(desc).) |
6084 DCHECK((desc_is_generic_descriptor || desc_is_data_descriptor) == | 6068 DCHECK((desc_is_generic_descriptor || desc_is_data_descriptor) == |
6085 !desc_is_accessor_descriptor); | 6069 !desc_is_accessor_descriptor); |
6086 if (!desc_is_accessor_descriptor) { | 6070 if (!desc_is_accessor_descriptor) { |
6087 // 2c i. If O is not undefined, create an own data property named P of | 6071 // 2c i. If O is not undefined, create an own data property named P of |
6088 // object O whose [[Value]], [[Writable]], [[Enumerable]] and | 6072 // object O whose [[Value]], [[Writable]], [[Enumerable]] and |
6089 // [[Configurable]] attribute values are described by Desc. If the value | 6073 // [[Configurable]] attribute values are described by Desc. If the value |
6090 // of an attribute field of Desc is absent, the attribute of the newly | 6074 // of an attribute field of Desc is absent, the attribute of the newly |
6091 // created property is set to its default value. | 6075 // created property is set to its default value. |
6092 if (!object->IsUndefined()) { | 6076 if (!o->IsUndefined()) { |
6093 if (!desc->has_writable()) desc->set_writable(false); | 6077 if (!desc->has_writable()) desc->set_writable(false); |
6094 if (!desc->has_enumerable()) desc->set_enumerable(false); | 6078 if (!desc->has_enumerable()) desc->set_enumerable(false); |
6095 if (!desc->has_configurable()) desc->set_configurable(false); | 6079 if (!desc->has_configurable()) desc->set_configurable(false); |
6096 Handle<Object> value( | 6080 Handle<Object> value( |
6097 desc->has_value() | 6081 desc->has_value() |
6098 ? desc->value() | 6082 ? desc->value() |
6099 : Handle<Object>::cast(isolate->factory()->undefined_value())); | 6083 : Handle<Object>::cast(isolate->factory()->undefined_value())); |
6100 MaybeHandle<Object> result = | 6084 MaybeHandle<Object> result = |
6101 JSObject::DefineOwnPropertyIgnoreAttributes( | 6085 JSObject::DefineOwnPropertyIgnoreAttributes(it, value, |
6102 it, value, desc->ToAttributes(), JSObject::DONT_FORCE_FIELD); | 6086 desc->ToAttributes()); |
6103 if (result.is_null()) return false; | 6087 if (result.is_null()) return false; |
6104 } | 6088 } |
6105 } else { | 6089 } else { |
6106 // 2d. Else Desc must be an accessor Property Descriptor, | 6090 // 2d. Else Desc must be an accessor Property Descriptor, |
6107 DCHECK(desc_is_accessor_descriptor); | 6091 DCHECK(desc_is_accessor_descriptor); |
6108 // 2d i. If O is not undefined, create an own accessor property named P | 6092 // 2d i. If O is not undefined, create an own accessor property named P |
6109 // of object O whose [[Get]], [[Set]], [[Enumerable]] and | 6093 // of object O whose [[Get]], [[Set]], [[Enumerable]] and |
6110 // [[Configurable]] attribute values are described by Desc. If the value | 6094 // [[Configurable]] attribute values are described by Desc. If the value |
6111 // of an attribute field of Desc is absent, the attribute of the newly | 6095 // of an attribute field of Desc is absent, the attribute of the newly |
6112 // created property is set to its default value. | 6096 // created property is set to its default value. |
6113 if (!object->IsUndefined()) { | 6097 if (!o->IsUndefined()) { |
6114 if (!desc->has_enumerable()) desc->set_enumerable(false); | 6098 if (!desc->has_enumerable()) desc->set_enumerable(false); |
6115 if (!desc->has_configurable()) desc->set_configurable(false); | 6099 if (!desc->has_configurable()) desc->set_configurable(false); |
6116 Handle<Object> getter( | 6100 Handle<Object> getter( |
6117 desc->has_get() | 6101 desc->has_get() |
6118 ? desc->get() | 6102 ? desc->get() |
6119 : Handle<Object>::cast(isolate->factory()->undefined_value())); | 6103 : Handle<Object>::cast(isolate->factory()->undefined_value())); |
6120 Handle<Object> setter( | 6104 Handle<Object> setter( |
6121 desc->has_set() | 6105 desc->has_set() |
6122 ? desc->set() | 6106 ? desc->set() |
6123 : Handle<Object>::cast(isolate->factory()->undefined_value())); | 6107 : Handle<Object>::cast(isolate->factory()->undefined_value())); |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6203 } | 6187 } |
6204 | 6188 |
6205 // 8. Else if IsDataDescriptor(current) and IsDataDescriptor(Desc) are both | 6189 // 8. Else if IsDataDescriptor(current) and IsDataDescriptor(Desc) are both |
6206 // true, then: | 6190 // true, then: |
6207 } else if (current_is_data_descriptor && desc_is_data_descriptor) { | 6191 } else if (current_is_data_descriptor && desc_is_data_descriptor) { |
6208 // 8a. If the [[Configurable]] field of current is false, then: | 6192 // 8a. If the [[Configurable]] field of current is false, then: |
6209 if (!current.configurable()) { | 6193 if (!current.configurable()) { |
6210 // [Strong mode] Disallow changing writable -> readonly for | 6194 // [Strong mode] Disallow changing writable -> readonly for |
6211 // non-configurable properties. | 6195 // non-configurable properties. |
6212 if (current.writable() && desc->has_writable() && !desc->writable() && | 6196 if (current.writable() && desc->has_writable() && !desc->writable() && |
6213 object->map()->is_strong()) { | 6197 o->map()->is_strong()) { |
6214 if (should_throw == THROW_ON_ERROR) { | 6198 if (should_throw == THROW_ON_ERROR) { |
6215 isolate->Throw(*isolate->factory()->NewTypeError( | 6199 isolate->Throw(*isolate->factory()->NewTypeError( |
6216 MessageTemplate::kStrongRedefineDisallowed, object, | 6200 MessageTemplate::kStrongRedefineDisallowed, o, it->GetName())); |
6217 it->GetName())); | |
6218 } | 6201 } |
6219 return false; | 6202 return false; |
6220 } | 6203 } |
6221 // 8a i. Return false, if the [[Writable]] field of current is false and | 6204 // 8a i. Return false, if the [[Writable]] field of current is false and |
6222 // the [[Writable]] field of Desc is true. | 6205 // the [[Writable]] field of Desc is true. |
6223 if (!current.writable() && desc->has_writable() && desc->writable()) { | 6206 if (!current.writable() && desc->has_writable() && desc->writable()) { |
6224 if (should_throw == THROW_ON_ERROR) { | 6207 if (should_throw == THROW_ON_ERROR) { |
6225 isolate->Throw(*isolate->factory()->NewTypeError( | 6208 isolate->Throw(*isolate->factory()->NewTypeError( |
6226 MessageTemplate::kRedefineDisallowed, it->GetName())); | 6209 MessageTemplate::kRedefineDisallowed, it->GetName())); |
6227 } | 6210 } |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6262 if (should_throw == THROW_ON_ERROR) { | 6245 if (should_throw == THROW_ON_ERROR) { |
6263 isolate->Throw(*isolate->factory()->NewTypeError( | 6246 isolate->Throw(*isolate->factory()->NewTypeError( |
6264 MessageTemplate::kRedefineDisallowed, it->GetName())); | 6247 MessageTemplate::kRedefineDisallowed, it->GetName())); |
6265 } | 6248 } |
6266 return false; | 6249 return false; |
6267 } | 6250 } |
6268 } | 6251 } |
6269 } | 6252 } |
6270 | 6253 |
6271 // 10. If O is not undefined, then: | 6254 // 10. If O is not undefined, then: |
6272 if (!object->IsUndefined()) { | 6255 if (!o->IsUndefined()) { |
6273 // 10a. For each field of Desc that is present, set the corresponding | 6256 // 10a. For each field of Desc that is present, set the corresponding |
6274 // attribute of the property named P of object O to the value of the field. | 6257 // attribute of the property named P of object O to the value of the field. |
6275 PropertyAttributes attrs = NONE; | 6258 PropertyAttributes attrs = NONE; |
6276 | 6259 |
6277 if (desc->has_enumerable()) { | 6260 if (desc->has_enumerable()) { |
6278 attrs = static_cast<PropertyAttributes>( | 6261 attrs = static_cast<PropertyAttributes>( |
6279 attrs | (desc->enumerable() ? NONE : DONT_ENUM)); | 6262 attrs | (desc->enumerable() ? NONE : DONT_ENUM)); |
6280 } else { | 6263 } else { |
6281 attrs = static_cast<PropertyAttributes>( | 6264 attrs = static_cast<PropertyAttributes>( |
6282 attrs | (current.enumerable() ? NONE : DONT_ENUM)); | 6265 attrs | (current.enumerable() ? NONE : DONT_ENUM)); |
(...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6525 OrdinaryDefineOwnProperty(isolate, a, isolate->factory()->length_string(), | 6508 OrdinaryDefineOwnProperty(isolate, a, isolate->factory()->length_string(), |
6526 &readonly, should_throw); | 6509 &readonly, should_throw); |
6527 } | 6510 } |
6528 uint32_t actual_new_len = 0; | 6511 uint32_t actual_new_len = 0; |
6529 CHECK(a->length()->ToArrayLength(&actual_new_len)); | 6512 CHECK(a->length()->ToArrayLength(&actual_new_len)); |
6530 // Steps 19d-v, 21. Return false if there were non-deletable elements. | 6513 // Steps 19d-v, 21. Return false if there were non-deletable elements. |
6531 success = actual_new_len == new_len; | 6514 success = actual_new_len == new_len; |
6532 if (!success && should_throw == THROW_ON_ERROR) { | 6515 if (!success && should_throw == THROW_ON_ERROR) { |
6533 isolate->Throw(*isolate->factory()->NewTypeError( | 6516 isolate->Throw(*isolate->factory()->NewTypeError( |
6534 MessageTemplate::kStrictDeleteProperty, | 6517 MessageTemplate::kStrictDeleteProperty, |
6535 isolate->factory()->NewNumberFromUint(actual_new_len - 1), a)); | 6518 isolate->factory()->NewNumberFromUint(actual_new_len - 1))); |
6536 } | 6519 } |
6537 return success; | 6520 return success; |
6538 } | 6521 } |
6539 | 6522 |
6540 | 6523 |
6541 // static | 6524 // static |
6542 bool JSReceiver::GetOwnPropertyDescriptor(Isolate* isolate, | 6525 bool JSReceiver::GetOwnPropertyDescriptor(Isolate* isolate, |
6543 Handle<JSObject> object, | 6526 Handle<JSObject> object, |
6544 Handle<Object> key, | 6527 Handle<Object> key, |
6545 PropertyDescriptor* desc) { | 6528 PropertyDescriptor* desc) { |
(...skipping 28 matching lines...) Expand all Loading... |
6574 DCHECK(!isolate->has_pending_exception()); | 6557 DCHECK(!isolate->has_pending_exception()); |
6575 | 6558 |
6576 // 3. Let D be a newly created Property Descriptor with no fields. | 6559 // 3. Let D be a newly created Property Descriptor with no fields. |
6577 DCHECK(desc->is_empty()); | 6560 DCHECK(desc->is_empty()); |
6578 // 4. Let X be O's own property whose key is P. | 6561 // 4. Let X be O's own property whose key is P. |
6579 // 5. If X is a data property, then | 6562 // 5. If X is a data property, then |
6580 bool is_accessor_pair = it->state() == LookupIterator::ACCESSOR && | 6563 bool is_accessor_pair = it->state() == LookupIterator::ACCESSOR && |
6581 it->GetAccessors()->IsAccessorPair(); | 6564 it->GetAccessors()->IsAccessorPair(); |
6582 if (!is_accessor_pair) { | 6565 if (!is_accessor_pair) { |
6583 // 5a. Set D.[[Value]] to the value of X's [[Value]] attribute. | 6566 // 5a. Set D.[[Value]] to the value of X's [[Value]] attribute. |
6584 Handle<Object> value; | 6567 Handle<Object> value = JSObject::GetProperty(it).ToHandleChecked(); |
6585 if (!JSObject::GetProperty(it).ToHandle(&value)) { | |
6586 DCHECK(isolate->has_pending_exception()); | |
6587 return false; | |
6588 } | |
6589 desc->set_value(value); | 6568 desc->set_value(value); |
6590 // 5b. Set D.[[Writable]] to the value of X's [[Writable]] attribute | 6569 // 5b. Set D.[[Writable]] to the value of X's [[Writable]] attribute |
6591 desc->set_writable((attrs & READ_ONLY) == 0); | 6570 desc->set_writable((attrs & READ_ONLY) == 0); |
6592 } else { | 6571 } else { |
6593 // 6. Else X is an accessor property, so | 6572 // 6. Else X is an accessor property, so |
6594 Handle<AccessorPair> accessors = | 6573 Handle<AccessorPair> accessors = |
6595 Handle<AccessorPair>::cast(it->GetAccessors()); | 6574 Handle<AccessorPair>::cast(it->GetAccessors()); |
6596 // 6a. Set D.[[Get]] to the value of X's [[Get]] attribute. | 6575 // 6a. Set D.[[Get]] to the value of X's [[Get]] attribute. |
6597 desc->set_get(handle(accessors->GetComponent(ACCESSOR_GETTER), isolate)); | 6576 desc->set_get(handle(accessors->GetComponent(ACCESSOR_GETTER), isolate)); |
6598 // 6b. Set D.[[Set]] to the value of X's [[Set]] attribute. | 6577 // 6b. Set D.[[Set]] to the value of X's [[Set]] attribute. |
(...skipping 1199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7798 !current->HasNamedInterceptor() && | 7777 !current->HasNamedInterceptor() && |
7799 !current->HasIndexedInterceptor()); | 7778 !current->HasIndexedInterceptor()); |
7800 // Compute the property keys and cache them if possible. | 7779 // Compute the property keys and cache them if possible. |
7801 Handle<FixedArray> enum_keys = | 7780 Handle<FixedArray> enum_keys = |
7802 JSObject::GetEnumPropertyKeys(current, cache_enum_length); | 7781 JSObject::GetEnumPropertyKeys(current, cache_enum_length); |
7803 accumulator.AddKeys(enum_keys); | 7782 accumulator.AddKeys(enum_keys); |
7804 } else { | 7783 } else { |
7805 DCHECK(filter == INCLUDE_SYMBOLS); | 7784 DCHECK(filter == INCLUDE_SYMBOLS); |
7806 PropertyAttributes attr_filter = | 7785 PropertyAttributes attr_filter = |
7807 static_cast<PropertyAttributes>(DONT_ENUM | PRIVATE_SYMBOL); | 7786 static_cast<PropertyAttributes>(DONT_ENUM | PRIVATE_SYMBOL); |
7808 Handle<FixedArray> property_keys = isolate->factory()->NewFixedArray( | 7787 JSObject::CollectOwnElementKeys(current, &accumulator, attr_filter); |
7809 current->NumberOfOwnProperties(attr_filter)); | |
7810 current->GetOwnPropertyNames(*property_keys, 0, attr_filter); | |
7811 accumulator.AddKeys(property_keys); | |
7812 } | 7788 } |
7813 | 7789 |
7814 // Add the property keys from the interceptor. | 7790 // Add the property keys from the interceptor. |
7815 if (current->HasNamedInterceptor()) { | 7791 if (current->HasNamedInterceptor()) { |
7816 Handle<JSObject> result; | 7792 Handle<JSObject> result; |
7817 if (JSObject::GetKeysForNamedInterceptor(current, object) | 7793 if (JSObject::GetKeysForNamedInterceptor(current, object) |
7818 .ToHandle(&result)) { | 7794 .ToHandle(&result)) { |
7819 accumulator.AddKeys(result); | 7795 accumulator.AddKeys(result); |
7820 } | 7796 } |
7821 } | 7797 } |
(...skipping 10012 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
17834 if (cell->value() != *new_value) { | 17810 if (cell->value() != *new_value) { |
17835 cell->set_value(*new_value); | 17811 cell->set_value(*new_value); |
17836 Isolate* isolate = cell->GetIsolate(); | 17812 Isolate* isolate = cell->GetIsolate(); |
17837 cell->dependent_code()->DeoptimizeDependentCodeGroup( | 17813 cell->dependent_code()->DeoptimizeDependentCodeGroup( |
17838 isolate, DependentCode::kPropertyCellChangedGroup); | 17814 isolate, DependentCode::kPropertyCellChangedGroup); |
17839 } | 17815 } |
17840 } | 17816 } |
17841 | 17817 |
17842 } // namespace internal | 17818 } // namespace internal |
17843 } // namespace v8 | 17819 } // namespace v8 |
OLD | NEW |