OLD | NEW |
---|---|
1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 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 6398 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
6409 if (!Object::ToObject(isolate, properties).ToHandle(&props)) { | 6409 if (!Object::ToObject(isolate, properties).ToHandle(&props)) { |
6410 THROW_NEW_ERROR(isolate, | 6410 THROW_NEW_ERROR(isolate, |
6411 NewTypeError(MessageTemplate::kUndefinedOrNullToObject), | 6411 NewTypeError(MessageTemplate::kUndefinedOrNullToObject), |
6412 Object); | 6412 Object); |
6413 } | 6413 } |
6414 // 4. Let keys be props.[[OwnPropertyKeys]](). | 6414 // 4. Let keys be props.[[OwnPropertyKeys]](). |
6415 // 5. ReturnIfAbrupt(keys). | 6415 // 5. ReturnIfAbrupt(keys). |
6416 Handle<FixedArray> keys; | 6416 Handle<FixedArray> keys; |
6417 ASSIGN_RETURN_ON_EXCEPTION( | 6417 ASSIGN_RETURN_ON_EXCEPTION( |
6418 isolate, keys, | 6418 isolate, keys, |
6419 JSReceiver::GetKeys(props, JSReceiver::OWN_ONLY, ALL_PROPERTIES), Object); | 6419 JSReceiver::GetKeys(props, KeyCollectionType::OWN_ONLY, ALL_PROPERTIES), |
6420 Object); | |
6420 // 6. Let descriptors be an empty List. | 6421 // 6. Let descriptors be an empty List. |
6421 int capacity = keys->length(); | 6422 int capacity = keys->length(); |
6422 std::vector<PropertyDescriptor> descriptors(capacity); | 6423 std::vector<PropertyDescriptor> descriptors(capacity); |
6423 size_t descriptors_index = 0; | 6424 size_t descriptors_index = 0; |
6424 // 7. Repeat for each element nextKey of keys in List order, | 6425 // 7. Repeat for each element nextKey of keys in List order, |
6425 for (int i = 0; i < keys->length(); ++i) { | 6426 for (int i = 0; i < keys->length(); ++i) { |
6426 Handle<Object> next_key(keys->get(i), isolate); | 6427 Handle<Object> next_key(keys->get(i), isolate); |
6427 // 7a. Let propDesc be props.[[GetOwnProperty]](nextKey). | 6428 // 7a. Let propDesc be props.[[GetOwnProperty]](nextKey). |
6428 // 7b. ReturnIfAbrupt(propDesc). | 6429 // 7b. ReturnIfAbrupt(propDesc). |
6429 bool success = false; | 6430 bool success = false; |
(...skipping 1690 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
8120 } | 8121 } |
8121 } | 8122 } |
8122 } | 8123 } |
8123 } | 8124 } |
8124 } else { | 8125 } else { |
8125 // Only deep copy fields from the object literal expression. | 8126 // Only deep copy fields from the object literal expression. |
8126 // In particular, don't try to copy the length attribute of | 8127 // In particular, don't try to copy the length attribute of |
8127 // an array. | 8128 // an array. |
8128 PropertyFilter filter = static_cast<PropertyFilter>( | 8129 PropertyFilter filter = static_cast<PropertyFilter>( |
8129 ONLY_WRITABLE | ONLY_ENUMERABLE | ONLY_CONFIGURABLE); | 8130 ONLY_WRITABLE | ONLY_ENUMERABLE | ONLY_CONFIGURABLE); |
8130 KeyAccumulator accumulator(isolate, filter); | 8131 KeyAccumulator accumulator(isolate, KeyCollectionType::OWN_ONLY, filter); |
8131 accumulator.NextPrototype(); | 8132 accumulator.NextPrototype(); |
8132 copy->CollectOwnPropertyNames(&accumulator, filter); | 8133 copy->CollectOwnPropertyNames(&accumulator, filter); |
8133 Handle<FixedArray> names = accumulator.GetKeys(); | 8134 Handle<FixedArray> names = accumulator.GetKeys(); |
8134 for (int i = 0; i < names->length(); i++) { | 8135 for (int i = 0; i < names->length(); i++) { |
8135 DCHECK(names->get(i)->IsName()); | 8136 DCHECK(names->get(i)->IsName()); |
8136 Handle<Name> name(Name::cast(names->get(i))); | 8137 Handle<Name> name(Name::cast(names->get(i))); |
8137 Handle<Object> value = | 8138 Handle<Object> value = |
8138 Object::GetProperty(copy, name).ToHandleChecked(); | 8139 Object::GetProperty(copy, name).ToHandleChecked(); |
8139 if (value->IsJSObject()) { | 8140 if (value->IsJSObject()) { |
8140 Handle<JSObject> result; | 8141 Handle<JSObject> result; |
(...skipping 484 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
8625 return Just(true); | 8626 return Just(true); |
8626 } | 8627 } |
8627 | 8628 |
8628 | 8629 |
8629 // Returns |true| on success, |false| if prototype walking should be stopped, | 8630 // Returns |true| on success, |false| if prototype walking should be stopped, |
8630 // |nothing| if an exception was thrown. | 8631 // |nothing| if an exception was thrown. |
8631 static Maybe<bool> GetKeysFromJSObject(Isolate* isolate, | 8632 static Maybe<bool> GetKeysFromJSObject(Isolate* isolate, |
8632 Handle<JSReceiver> receiver, | 8633 Handle<JSReceiver> receiver, |
8633 Handle<JSObject> object, | 8634 Handle<JSObject> object, |
8634 PropertyFilter* filter, | 8635 PropertyFilter* filter, |
8635 JSReceiver::KeyCollectionType type, | 8636 KeyCollectionType type, |
8636 KeyAccumulator* accumulator) { | 8637 KeyAccumulator* accumulator) { |
8637 accumulator->NextPrototype(); | 8638 accumulator->NextPrototype(); |
8638 // Check access rights if required. | 8639 // Check access rights if required. |
8639 if (object->IsAccessCheckNeeded() && | 8640 if (object->IsAccessCheckNeeded() && |
8640 !isolate->MayAccess(handle(isolate->context()), object)) { | 8641 !isolate->MayAccess(handle(isolate->context()), object)) { |
8641 // The cross-origin spec says that [[Enumerate]] shall return an empty | 8642 // The cross-origin spec says that [[Enumerate]] shall return an empty |
8642 // iterator when it doesn't have access... | 8643 // iterator when it doesn't have access... |
8643 if (type == JSReceiver::INCLUDE_PROTOS) { | 8644 if (type == KeyCollectionType::INCLUDE_PROTOS) { |
8644 return Just(false); | 8645 return Just(false); |
8645 } | 8646 } |
8646 // ...whereas [[OwnPropertyKeys]] shall return whitelisted properties. | 8647 // ...whereas [[OwnPropertyKeys]] shall return whitelisted properties. |
8647 DCHECK(type == JSReceiver::OWN_ONLY); | 8648 DCHECK_EQ(KeyCollectionType::OWN_ONLY, type); |
8648 *filter = static_cast<PropertyFilter>(*filter | ONLY_ALL_CAN_READ); | 8649 *filter = static_cast<PropertyFilter>(*filter | ONLY_ALL_CAN_READ); |
8649 } | 8650 } |
8650 | 8651 |
8651 JSObject::CollectOwnElementKeys(object, accumulator, *filter); | 8652 JSObject::CollectOwnElementKeys(object, accumulator, *filter); |
8652 | 8653 |
8653 // Add the element keys from the interceptor. | 8654 // Add the element keys from the interceptor. |
8654 Maybe<bool> success = | 8655 Maybe<bool> success = |
8655 GetKeysFromInterceptor<v8::IndexedPropertyEnumeratorCallback, kIndexed>( | 8656 GetKeysFromInterceptor<v8::IndexedPropertyEnumeratorCallback, kIndexed>( |
8656 isolate, receiver, object, *filter, accumulator); | 8657 isolate, receiver, object, *filter, accumulator); |
8657 MAYBE_RETURN(success, Nothing<bool>()); | 8658 MAYBE_RETURN(success, Nothing<bool>()); |
(...skipping 30 matching lines...) Expand all Loading... | |
8688 MAYBE_RETURN(success, Nothing<bool>()); | 8689 MAYBE_RETURN(success, Nothing<bool>()); |
8689 return Just(true); | 8690 return Just(true); |
8690 } | 8691 } |
8691 | 8692 |
8692 | 8693 |
8693 // Helper function for JSReceiver::GetKeys() below. Can be called recursively. | 8694 // Helper function for JSReceiver::GetKeys() below. Can be called recursively. |
8694 // Returns |true| or |nothing|. | 8695 // Returns |true| or |nothing|. |
8695 static Maybe<bool> GetKeys_Internal(Isolate* isolate, | 8696 static Maybe<bool> GetKeys_Internal(Isolate* isolate, |
8696 Handle<JSReceiver> receiver, | 8697 Handle<JSReceiver> receiver, |
8697 Handle<JSReceiver> object, | 8698 Handle<JSReceiver> object, |
8698 JSReceiver::KeyCollectionType type, | 8699 KeyCollectionType type, |
8699 PropertyFilter filter, | 8700 PropertyFilter filter, |
8700 KeyAccumulator* accumulator) { | 8701 KeyAccumulator* accumulator) { |
8701 PrototypeIterator::WhereToEnd end = type == JSReceiver::OWN_ONLY | 8702 PrototypeIterator::WhereToEnd end = type == KeyCollectionType::OWN_ONLY |
8702 ? PrototypeIterator::END_AT_NON_HIDDEN | 8703 ? PrototypeIterator::END_AT_NON_HIDDEN |
8703 : PrototypeIterator::END_AT_NULL; | 8704 : PrototypeIterator::END_AT_NULL; |
8704 for (PrototypeIterator iter(isolate, object, | 8705 for (PrototypeIterator iter(isolate, object, |
8705 PrototypeIterator::START_AT_RECEIVER); | 8706 PrototypeIterator::START_AT_RECEIVER); |
8706 !iter.IsAtEnd(end); iter.Advance()) { | 8707 !iter.IsAtEnd(end); iter.Advance()) { |
8707 Handle<JSReceiver> current = | 8708 Handle<JSReceiver> current = |
8708 PrototypeIterator::GetCurrent<JSReceiver>(iter); | 8709 PrototypeIterator::GetCurrent<JSReceiver>(iter); |
8709 Maybe<bool> result = Just(false); // Dummy initialization. | 8710 Maybe<bool> result = Just(false); // Dummy initialization. |
8710 if (current->IsJSProxy()) { | 8711 if (current->IsJSProxy()) { |
8711 if (type == JSReceiver::OWN_ONLY) { | 8712 if (type == KeyCollectionType::OWN_ONLY) { |
8712 result = JSProxy::OwnPropertyKeys(isolate, receiver, | 8713 result = JSProxy::OwnPropertyKeys(isolate, receiver, |
8713 Handle<JSProxy>::cast(current), | 8714 Handle<JSProxy>::cast(current), |
8714 filter, accumulator); | 8715 filter, accumulator); |
8715 } else { | 8716 } else { |
8716 DCHECK(type == JSReceiver::INCLUDE_PROTOS); | 8717 DCHECK(type == KeyCollectionType::INCLUDE_PROTOS); |
8717 result = JSProxy::Enumerate( | 8718 result = JSProxy::Enumerate( |
8718 isolate, receiver, Handle<JSProxy>::cast(current), accumulator); | 8719 isolate, receiver, Handle<JSProxy>::cast(current), accumulator); |
8719 } | 8720 } |
8720 } else { | 8721 } else { |
8721 DCHECK(current->IsJSObject()); | 8722 DCHECK(current->IsJSObject()); |
8722 result = GetKeysFromJSObject(isolate, receiver, | 8723 result = GetKeysFromJSObject(isolate, receiver, |
8723 Handle<JSObject>::cast(current), &filter, | 8724 Handle<JSObject>::cast(current), &filter, |
8724 type, accumulator); | 8725 type, accumulator); |
8725 } | 8726 } |
8726 MAYBE_RETURN(result, Nothing<bool>()); | 8727 MAYBE_RETURN(result, Nothing<bool>()); |
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
8868 // then: | 8869 // then: |
8869 if (extensible_target && nonconfigurable_keys_length == 0) { | 8870 if (extensible_target && nonconfigurable_keys_length == 0) { |
8870 // 15a. Return trapResult. | 8871 // 15a. Return trapResult. |
8871 return accumulator->AddKeysFromProxy(proxy, trap_result); | 8872 return accumulator->AddKeysFromProxy(proxy, trap_result); |
8872 } | 8873 } |
8873 // 16. Let uncheckedResultKeys be a new List which is a copy of trapResult. | 8874 // 16. Let uncheckedResultKeys be a new List which is a copy of trapResult. |
8874 Zone set_zone; | 8875 Zone set_zone; |
8875 const int kPresent = 1; | 8876 const int kPresent = 1; |
8876 const int kGone = 0; | 8877 const int kGone = 0; |
8877 IdentityMap<int> unchecked_result_keys(isolate->heap(), &set_zone); | 8878 IdentityMap<int> unchecked_result_keys(isolate->heap(), &set_zone); |
8878 int unchecked_result_keys_size = trap_result->length(); | 8879 int unchecked_result_keys_size = 0; |
8879 for (int i = 0; i < trap_result->length(); ++i) { | 8880 for (int i = 0; i < trap_result->length(); ++i) { |
8880 DCHECK(trap_result->get(i)->IsUniqueName()); | 8881 DCHECK(trap_result->get(i)->IsUniqueName()); |
8881 unchecked_result_keys.Set(trap_result->get(i), kPresent); | 8882 Object* key = trap_result->get(i); |
8883 int* found = unchecked_result_keys.Find(key); | |
8884 if (found == nullptr || *found == kGone) { | |
Camillo Bruni
2016/02/04 11:59:07
I didn't fully check how IdentityMaps work, but th
| |
8885 unchecked_result_keys.Set(key, kPresent); | |
8886 unchecked_result_keys_size++; | |
8887 } | |
8882 } | 8888 } |
8883 // 17. Repeat, for each key that is an element of targetNonconfigurableKeys: | 8889 // 17. Repeat, for each key that is an element of targetNonconfigurableKeys: |
8884 for (int i = 0; i < nonconfigurable_keys_length; ++i) { | 8890 for (int i = 0; i < nonconfigurable_keys_length; ++i) { |
8885 Object* key = target_nonconfigurable_keys->get(i); | 8891 Object* key = target_nonconfigurable_keys->get(i); |
8886 // 17a. If key is not an element of uncheckedResultKeys, throw a | 8892 // 17a. If key is not an element of uncheckedResultKeys, throw a |
8887 // TypeError exception. | 8893 // TypeError exception. |
8888 int* found = unchecked_result_keys.Find(key); | 8894 int* found = unchecked_result_keys.Find(key); |
8889 if (found == nullptr || *found == kGone) { | 8895 if (found == nullptr || *found == kGone) { |
8890 isolate->Throw(*isolate->factory()->NewTypeError( | 8896 isolate->Throw(*isolate->factory()->NewTypeError( |
8891 MessageTemplate::kProxyOwnKeysMissing, handle(key, isolate))); | 8897 MessageTemplate::kProxyOwnKeysMissing, handle(key, isolate))); |
8892 return Nothing<bool>(); | 8898 return Nothing<bool>(); |
8893 } | 8899 } |
8894 // 17b. Remove key from uncheckedResultKeys. | 8900 // 17b. Remove key from uncheckedResultKeys. |
Camillo Bruni
2016/02/04 11:59:07
I read this now as remove all occurences of key fr
| |
8895 *found = kGone; | 8901 *found = kGone; |
8896 unchecked_result_keys_size--; | 8902 unchecked_result_keys_size--; |
8897 } | 8903 } |
8898 // 18. If extensibleTarget is true, return trapResult. | 8904 // 18. If extensibleTarget is true, return trapResult. |
8899 if (extensible_target) { | 8905 if (extensible_target) { |
8900 return accumulator->AddKeysFromProxy(proxy, trap_result); | 8906 return accumulator->AddKeysFromProxy(proxy, trap_result); |
8901 } | 8907 } |
8902 // 19. Repeat, for each key that is an element of targetConfigurableKeys: | 8908 // 19. Repeat, for each key that is an element of targetConfigurableKeys: |
8903 for (int i = 0; i < target_configurable_keys->length(); ++i) { | 8909 for (int i = 0; i < target_configurable_keys->length(); ++i) { |
8904 Object* key = target_configurable_keys->get(i); | 8910 Object* key = target_configurable_keys->get(i); |
(...skipping 21 matching lines...) Expand all Loading... | |
8926 return accumulator->AddKeysFromProxy(proxy, trap_result); | 8932 return accumulator->AddKeysFromProxy(proxy, trap_result); |
8927 } | 8933 } |
8928 | 8934 |
8929 | 8935 |
8930 MaybeHandle<FixedArray> JSReceiver::GetKeys(Handle<JSReceiver> object, | 8936 MaybeHandle<FixedArray> JSReceiver::GetKeys(Handle<JSReceiver> object, |
8931 KeyCollectionType type, | 8937 KeyCollectionType type, |
8932 PropertyFilter filter, | 8938 PropertyFilter filter, |
8933 GetKeysConversion keys_conversion) { | 8939 GetKeysConversion keys_conversion) { |
8934 USE(ContainsOnlyValidKeys); | 8940 USE(ContainsOnlyValidKeys); |
8935 Isolate* isolate = object->GetIsolate(); | 8941 Isolate* isolate = object->GetIsolate(); |
8936 KeyAccumulator accumulator(isolate, filter); | 8942 KeyAccumulator accumulator(isolate, type, filter); |
8937 MAYBE_RETURN( | 8943 MAYBE_RETURN( |
8938 GetKeys_Internal(isolate, object, object, type, filter, &accumulator), | 8944 GetKeys_Internal(isolate, object, object, type, filter, &accumulator), |
8939 MaybeHandle<FixedArray>()); | 8945 MaybeHandle<FixedArray>()); |
8940 Handle<FixedArray> keys = accumulator.GetKeys(keys_conversion); | 8946 Handle<FixedArray> keys = accumulator.GetKeys(keys_conversion); |
8941 DCHECK(ContainsOnlyValidKeys(keys)); | 8947 DCHECK(ContainsOnlyValidKeys(keys)); |
8942 return keys; | 8948 return keys; |
8943 } | 8949 } |
8944 | 8950 |
8945 | 8951 |
8946 bool Map::DictionaryElementsInPrototypeChainOnly() { | 8952 bool Map::DictionaryElementsInPrototypeChainOnly() { |
(...skipping 10823 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
19770 if (cell->value() != *new_value) { | 19776 if (cell->value() != *new_value) { |
19771 cell->set_value(*new_value); | 19777 cell->set_value(*new_value); |
19772 Isolate* isolate = cell->GetIsolate(); | 19778 Isolate* isolate = cell->GetIsolate(); |
19773 cell->dependent_code()->DeoptimizeDependentCodeGroup( | 19779 cell->dependent_code()->DeoptimizeDependentCodeGroup( |
19774 isolate, DependentCode::kPropertyCellChangedGroup); | 19780 isolate, DependentCode::kPropertyCellChangedGroup); |
19775 } | 19781 } |
19776 } | 19782 } |
19777 | 19783 |
19778 } // namespace internal | 19784 } // namespace internal |
19779 } // namespace v8 | 19785 } // namespace v8 |
OLD | NEW |