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 6100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6111 Handle<JSReceiver> props; | 6111 Handle<JSReceiver> props; |
6112 if (!Object::ToObject(isolate, properties).ToHandle(&props)) { | 6112 if (!Object::ToObject(isolate, properties).ToHandle(&props)) { |
6113 THROW_NEW_ERROR_RETURN_FAILURE( | 6113 THROW_NEW_ERROR_RETURN_FAILURE( |
6114 isolate, NewTypeError(MessageTemplate::kUndefinedOrNullToObject)); | 6114 isolate, NewTypeError(MessageTemplate::kUndefinedOrNullToObject)); |
6115 } | 6115 } |
6116 // 4. Let keys be props.[[OwnPropertyKeys]](). | 6116 // 4. Let keys be props.[[OwnPropertyKeys]](). |
6117 // 5. ReturnIfAbrupt(keys). | 6117 // 5. ReturnIfAbrupt(keys). |
6118 Handle<FixedArray> keys; | 6118 Handle<FixedArray> keys; |
6119 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( | 6119 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( |
6120 isolate, keys, | 6120 isolate, keys, |
6121 JSReceiver::GetKeys(props, JSReceiver::OWN_ONLY, INCLUDE_SYMBOLS)); | 6121 JSReceiver::GetKeys(props, JSReceiver::OWN_ONLY, ALL_PROPERTIES)); |
6122 // 6. Let descriptors be an empty List. | 6122 // 6. Let descriptors be an empty List. |
6123 int capacity = keys->length(); | 6123 int capacity = keys->length(); |
6124 std::vector<PropertyDescriptor> descriptors(capacity); | 6124 std::vector<PropertyDescriptor> descriptors(capacity); |
| 6125 size_t descriptors_index = 0; |
6125 // 7. Repeat for each element nextKey of keys in List order, | 6126 // 7. Repeat for each element nextKey of keys in List order, |
6126 for (int i = 0; i < keys->length(); ++i) { | 6127 for (int i = 0; i < keys->length(); ++i) { |
6127 Handle<Object> next_key(keys->get(i), isolate); | 6128 Handle<Object> next_key(keys->get(i), isolate); |
6128 // 7a. Let propDesc be props.[[GetOwnProperty]](nextKey). | 6129 // 7a. Let propDesc be props.[[GetOwnProperty]](nextKey). |
6129 // 7b. ReturnIfAbrupt(propDesc). | 6130 // 7b. ReturnIfAbrupt(propDesc). |
6130 bool success = false; | 6131 bool success = false; |
6131 LookupIterator it = LookupIterator::PropertyOrElement( | 6132 LookupIterator it = LookupIterator::PropertyOrElement( |
6132 isolate, props, next_key, &success, LookupIterator::HIDDEN); | 6133 isolate, props, next_key, &success, LookupIterator::HIDDEN); |
6133 DCHECK(success); | 6134 DCHECK(success); |
6134 Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it); | 6135 Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it); |
6135 if (!maybe.IsJust()) return isolate->heap()->exception(); | 6136 if (!maybe.IsJust()) return isolate->heap()->exception(); |
6136 PropertyAttributes attrs = maybe.FromJust(); | 6137 PropertyAttributes attrs = maybe.FromJust(); |
6137 // 7c. If propDesc is not undefined and propDesc.[[Enumerable]] is true: | 6138 // 7c. If propDesc is not undefined and propDesc.[[Enumerable]] is true: |
6138 if (attrs == ABSENT) continue; | 6139 if (attrs == ABSENT) continue; |
6139 // GetKeys() only returns enumerable keys. | 6140 if (attrs & DONT_ENUM) continue; |
6140 DCHECK((attrs & DONT_ENUM) == 0); | |
6141 // 7c i. Let descObj be Get(props, nextKey). | 6141 // 7c i. Let descObj be Get(props, nextKey). |
6142 // 7c ii. ReturnIfAbrupt(descObj). | 6142 // 7c ii. ReturnIfAbrupt(descObj). |
6143 Handle<Object> desc_obj; | 6143 Handle<Object> desc_obj; |
6144 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, desc_obj, | 6144 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, desc_obj, |
6145 Object::GetProperty(&it)); | 6145 Object::GetProperty(&it)); |
6146 // 7c iii. Let desc be ToPropertyDescriptor(descObj). | 6146 // 7c iii. Let desc be ToPropertyDescriptor(descObj). |
6147 success = PropertyDescriptor::ToPropertyDescriptor(isolate, desc_obj, | 6147 success = PropertyDescriptor::ToPropertyDescriptor( |
6148 &descriptors[i]); | 6148 isolate, desc_obj, &descriptors[descriptors_index]); |
6149 // 7c iv. ReturnIfAbrupt(desc). | 6149 // 7c iv. ReturnIfAbrupt(desc). |
6150 if (!success) return isolate->heap()->exception(); | 6150 if (!success) return isolate->heap()->exception(); |
6151 // 7c v. Append the pair (a two element List) consisting of nextKey and | 6151 // 7c v. Append the pair (a two element List) consisting of nextKey and |
6152 // desc to the end of descriptors. | 6152 // desc to the end of descriptors. |
6153 descriptors[i].set_name(next_key); | 6153 descriptors[descriptors_index].set_name(next_key); |
| 6154 descriptors_index++; |
6154 } | 6155 } |
6155 // 8. For each pair from descriptors in list order, | 6156 // 8. For each pair from descriptors in list order, |
6156 for (size_t i = 0; i < descriptors.size(); ++i) { | 6157 for (size_t i = 0; i < descriptors_index; ++i) { |
6157 PropertyDescriptor* desc = &descriptors[i]; | 6158 PropertyDescriptor* desc = &descriptors[i]; |
6158 // 8a. Let P be the first element of pair. | 6159 // 8a. Let P be the first element of pair. |
6159 // 8b. Let desc be the second element of pair. | 6160 // 8b. Let desc be the second element of pair. |
6160 // 8c. Let status be DefinePropertyOrThrow(O, P, desc). | 6161 // 8c. Let status be DefinePropertyOrThrow(O, P, desc). |
6161 bool status = DefineOwnProperty(isolate, Handle<JSReceiver>::cast(object), | 6162 bool status = DefineOwnProperty(isolate, Handle<JSReceiver>::cast(object), |
6162 desc->name(), desc, THROW_ON_ERROR); | 6163 desc->name(), desc, THROW_ON_ERROR); |
6163 // 8d. ReturnIfAbrupt(status). | 6164 // 8d. ReturnIfAbrupt(status). |
6164 if (isolate->has_pending_exception()) return isolate->heap()->exception(); | 6165 if (isolate->has_pending_exception()) return isolate->heap()->exception(); |
6165 CHECK(status == true); | 6166 CHECK(status == true); |
6166 } | 6167 } |
(...skipping 1543 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7710 copy->FastPropertyAtPut(index, *value); | 7711 copy->FastPropertyAtPut(index, *value); |
7711 } | 7712 } |
7712 } | 7713 } |
7713 } | 7714 } |
7714 } | 7715 } |
7715 } else { | 7716 } else { |
7716 Handle<FixedArray> names = | 7717 Handle<FixedArray> names = |
7717 isolate->factory()->NewFixedArray(copy->NumberOfOwnProperties()); | 7718 isolate->factory()->NewFixedArray(copy->NumberOfOwnProperties()); |
7718 copy->GetOwnPropertyNames(*names, 0); | 7719 copy->GetOwnPropertyNames(*names, 0); |
7719 for (int i = 0; i < names->length(); i++) { | 7720 for (int i = 0; i < names->length(); i++) { |
7720 DCHECK(names->get(i)->IsString()); | 7721 DCHECK(names->get(i)->IsName()); |
7721 Handle<String> key_string(String::cast(names->get(i))); | 7722 Handle<Name> name(Name::cast(names->get(i))); |
7722 Maybe<PropertyAttributes> maybe = | 7723 Maybe<PropertyAttributes> maybe = |
7723 JSReceiver::GetOwnPropertyAttributes(copy, key_string); | 7724 JSReceiver::GetOwnPropertyAttributes(copy, name); |
7724 DCHECK(maybe.IsJust()); | 7725 DCHECK(maybe.IsJust()); |
7725 PropertyAttributes attributes = maybe.FromJust(); | 7726 PropertyAttributes attributes = maybe.FromJust(); |
7726 // Only deep copy fields from the object literal expression. | 7727 // Only deep copy fields from the object literal expression. |
7727 // In particular, don't try to copy the length attribute of | 7728 // In particular, don't try to copy the length attribute of |
7728 // an array. | 7729 // an array. |
7729 if (attributes != NONE) continue; | 7730 if (attributes != NONE) continue; |
7730 Handle<Object> value = | 7731 Handle<Object> value = |
7731 Object::GetProperty(copy, key_string).ToHandleChecked(); | 7732 Object::GetProperty(copy, name).ToHandleChecked(); |
7732 if (value->IsJSObject()) { | 7733 if (value->IsJSObject()) { |
7733 Handle<JSObject> result; | 7734 Handle<JSObject> result; |
7734 ASSIGN_RETURN_ON_EXCEPTION( | 7735 ASSIGN_RETURN_ON_EXCEPTION( |
7735 isolate, result, | 7736 isolate, result, |
7736 VisitElementOrProperty(copy, Handle<JSObject>::cast(value)), | 7737 VisitElementOrProperty(copy, Handle<JSObject>::cast(value)), |
7737 JSObject); | 7738 JSObject); |
7738 if (copying) { | 7739 if (copying) { |
7739 // Creating object copy for literals. No strict mode needed. | 7740 // Creating object copy for literals. No strict mode needed. |
7740 JSObject::SetProperty(copy, key_string, result, SLOPPY).Assert(); | 7741 JSObject::SetProperty(copy, name, result, SLOPPY).Assert(); |
7741 } | 7742 } |
7742 } | 7743 } |
7743 } | 7744 } |
7744 } | 7745 } |
7745 | 7746 |
7746 // Deep copy own elements. | 7747 // Deep copy own elements. |
7747 // Pixel elements cannot be created using an object literal. | 7748 // Pixel elements cannot be created using an object literal. |
7748 DCHECK(!copy->HasFixedTypedArrayElements()); | 7749 DCHECK(!copy->HasFixedTypedArrayElements()); |
7749 switch (kind) { | 7750 switch (kind) { |
7750 case FAST_SMI_ELEMENTS: | 7751 case FAST_SMI_ELEMENTS: |
(...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7934 DCHECK(!current->HasNamedInterceptor()); | 7935 DCHECK(!current->HasNamedInterceptor()); |
7935 DCHECK(!current->HasIndexedInterceptor()); | 7936 DCHECK(!current->HasIndexedInterceptor()); |
7936 if (current->NumberOfEnumElements() > 0) return false; | 7937 if (current->NumberOfEnumElements() > 0) return false; |
7937 if (current != this && enum_length != 0) return false; | 7938 if (current != this && enum_length != 0) return false; |
7938 } | 7939 } |
7939 return true; | 7940 return true; |
7940 } | 7941 } |
7941 | 7942 |
7942 | 7943 |
7943 int Map::NumberOfDescribedProperties(DescriptorFlag which, | 7944 int Map::NumberOfDescribedProperties(DescriptorFlag which, |
7944 PropertyAttributes filter) { | 7945 PropertyFilter filter) { |
7945 int result = 0; | 7946 int result = 0; |
7946 DescriptorArray* descs = instance_descriptors(); | 7947 DescriptorArray* descs = instance_descriptors(); |
7947 int limit = which == ALL_DESCRIPTORS | 7948 int limit = which == ALL_DESCRIPTORS |
7948 ? descs->number_of_descriptors() | 7949 ? descs->number_of_descriptors() |
7949 : NumberOfOwnDescriptors(); | 7950 : NumberOfOwnDescriptors(); |
7950 for (int i = 0; i < limit; i++) { | 7951 for (int i = 0; i < limit; i++) { |
7951 if ((descs->GetDetails(i).attributes() & filter) == 0 && | 7952 if ((descs->GetDetails(i).attributes() & filter) == 0 && |
7952 !descs->GetKey(i)->FilterKey(filter)) { | 7953 !descs->GetKey(i)->FilterKey(filter)) { |
7953 result++; | 7954 result++; |
7954 } | 7955 } |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7999 Handle<FixedArray> GetFastEnumPropertyKeys(Isolate* isolate, | 8000 Handle<FixedArray> GetFastEnumPropertyKeys(Isolate* isolate, |
8000 Handle<JSObject> object, | 8001 Handle<JSObject> object, |
8001 bool cache_enum_length) { | 8002 bool cache_enum_length) { |
8002 Handle<Map> map(object->map()); | 8003 Handle<Map> map(object->map()); |
8003 Handle<DescriptorArray> descs = | 8004 Handle<DescriptorArray> descs = |
8004 Handle<DescriptorArray>(map->instance_descriptors(), isolate); | 8005 Handle<DescriptorArray>(map->instance_descriptors(), isolate); |
8005 int own_property_count = map->EnumLength(); | 8006 int own_property_count = map->EnumLength(); |
8006 // If the enum length of the given map is set to kInvalidEnumCache, this | 8007 // If the enum length of the given map is set to kInvalidEnumCache, this |
8007 // means that the map itself has never used the present enum cache. The | 8008 // means that the map itself has never used the present enum cache. The |
8008 // first step to using the cache is to set the enum length of the map by | 8009 // first step to using the cache is to set the enum length of the map by |
8009 // counting the number of own descriptors that are not DONT_ENUM or | 8010 // counting the number of own descriptors that are ENUMERABLE_STRINGS. |
8010 // SYMBOLIC. | |
8011 if (own_property_count == kInvalidEnumCacheSentinel) { | 8011 if (own_property_count == kInvalidEnumCacheSentinel) { |
8012 own_property_count = | 8012 own_property_count = |
8013 map->NumberOfDescribedProperties(OWN_DESCRIPTORS, DONT_SHOW); | 8013 map->NumberOfDescribedProperties(OWN_DESCRIPTORS, ENUMERABLE_STRINGS); |
8014 } else { | 8014 } else { |
8015 DCHECK(own_property_count == | 8015 DCHECK( |
8016 map->NumberOfDescribedProperties(OWN_DESCRIPTORS, DONT_SHOW)); | 8016 own_property_count == |
| 8017 map->NumberOfDescribedProperties(OWN_DESCRIPTORS, ENUMERABLE_STRINGS)); |
8017 } | 8018 } |
8018 | 8019 |
8019 if (descs->HasEnumCache()) { | 8020 if (descs->HasEnumCache()) { |
8020 Handle<FixedArray> keys(descs->GetEnumCache(), isolate); | 8021 Handle<FixedArray> keys(descs->GetEnumCache(), isolate); |
8021 // In case the number of properties required in the enum are actually | 8022 // In case the number of properties required in the enum are actually |
8022 // present, we can reuse the enum cache. Otherwise, this means that the | 8023 // present, we can reuse the enum cache. Otherwise, this means that the |
8023 // enum cache was generated for a previous (smaller) version of the | 8024 // enum cache was generated for a previous (smaller) version of the |
8024 // Descriptor Array. In that case we regenerate the enum cache. | 8025 // Descriptor Array. In that case we regenerate the enum cache. |
8025 if (own_property_count <= keys->length()) { | 8026 if (own_property_count <= keys->length()) { |
8026 isolate->counters()->enum_cache_hits()->Increment(); | 8027 isolate->counters()->enum_cache_hits()->Increment(); |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8094 return Handle<FixedArray>(isolate->heap()->empty_fixed_array()); | 8095 return Handle<FixedArray>(isolate->heap()->empty_fixed_array()); |
8095 } | 8096 } |
8096 Handle<FixedArray> storage = isolate->factory()->NewFixedArray(length); | 8097 Handle<FixedArray> storage = isolate->factory()->NewFixedArray(length); |
8097 dictionary->CopyEnumKeysTo(*storage); | 8098 dictionary->CopyEnumKeysTo(*storage); |
8098 return storage; | 8099 return storage; |
8099 } | 8100 } |
8100 } | 8101 } |
8101 | 8102 |
8102 | 8103 |
8103 static bool GetKeysFromJSObject(Isolate* isolate, Handle<JSReceiver> receiver, | 8104 static bool GetKeysFromJSObject(Isolate* isolate, Handle<JSReceiver> receiver, |
8104 Handle<JSObject> object, KeyFilter filter, | 8105 Handle<JSObject> object, PropertyFilter filter, |
8105 Enumerability enum_policy, | |
8106 KeyAccumulator* accumulator) { | 8106 KeyAccumulator* accumulator) { |
8107 accumulator->NextPrototype(); | 8107 accumulator->NextPrototype(); |
8108 // Check access rights if required. | 8108 // Check access rights if required. |
8109 if (object->IsAccessCheckNeeded() && | 8109 if (object->IsAccessCheckNeeded() && |
8110 !isolate->MayAccess(handle(isolate->context()), object)) { | 8110 !isolate->MayAccess(handle(isolate->context()), object)) { |
8111 // TODO(jkummerow): Get whitelisted (all-can-read) keys. | 8111 // TODO(jkummerow): Get whitelisted (all-can-read) keys. |
8112 // It's probably best to implement a "GetKeysWithFailedAccessCheck" | 8112 // It's probably best to implement a "GetKeysWithFailedAccessCheck" |
8113 // helper, which will need to look at both interceptors and accessors. | 8113 // helper, which will need to look at both interceptors and accessors. |
8114 return false; | 8114 return false; |
8115 } | 8115 } |
8116 | 8116 |
8117 PropertyAttributes attr_filter = static_cast<PropertyAttributes>( | 8117 JSObject::CollectOwnElementKeys(object, accumulator, filter); |
8118 (enum_policy == RESPECT_ENUMERABILITY ? DONT_ENUM : NONE) | | |
8119 PRIVATE_SYMBOL); | |
8120 | |
8121 JSObject::CollectOwnElementKeys(object, accumulator, attr_filter); | |
8122 | 8118 |
8123 // Add the element keys from the interceptor. | 8119 // Add the element keys from the interceptor. |
8124 if (object->HasIndexedInterceptor()) { | 8120 if (object->HasIndexedInterceptor()) { |
8125 Handle<JSObject> result; | 8121 Handle<JSObject> result; |
8126 if (JSObject::GetKeysForIndexedInterceptor(object, receiver) | 8122 if (JSObject::GetKeysForIndexedInterceptor(object, receiver) |
8127 .ToHandle(&result)) { | 8123 .ToHandle(&result)) { |
8128 accumulator->AddElementKeysFromInterceptor(result); | 8124 accumulator->AddElementKeysFromInterceptor(result); |
8129 } | 8125 } |
8130 RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, false); | 8126 RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, false); |
8131 } | 8127 } |
8132 | 8128 |
8133 if (filter == SKIP_SYMBOLS) { | 8129 if (filter == ENUMERABLE_STRINGS) { |
8134 if (enum_policy == IGNORE_ENUMERABILITY) UNIMPLEMENTED(); | |
8135 | |
8136 // We can cache the computed property keys if access checks are | 8130 // We can cache the computed property keys if access checks are |
8137 // not needed and no interceptors are involved. | 8131 // not needed and no interceptors are involved. |
8138 // | 8132 // |
8139 // We do not use the cache if the object has elements and | 8133 // We do not use the cache if the object has elements and |
8140 // therefore it does not make sense to cache the property names | 8134 // therefore it does not make sense to cache the property names |
8141 // for arguments objects. Arguments objects will always have | 8135 // for arguments objects. Arguments objects will always have |
8142 // elements. | 8136 // elements. |
8143 // Wrapped strings have elements, but don't have an elements | 8137 // Wrapped strings have elements, but don't have an elements |
8144 // array or dictionary. So the fast inline test for whether to | 8138 // array or dictionary. So the fast inline test for whether to |
8145 // use the cache says yes, so we should not create a cache. | 8139 // use the cache says yes, so we should not create a cache. |
8146 Handle<JSFunction> arguments_function( | 8140 Handle<JSFunction> arguments_function( |
8147 JSFunction::cast(isolate->sloppy_arguments_map()->GetConstructor())); | 8141 JSFunction::cast(isolate->sloppy_arguments_map()->GetConstructor())); |
8148 bool cache_enum_length = | 8142 bool cache_enum_length = |
8149 ((object->map()->GetConstructor() != *arguments_function) && | 8143 ((object->map()->GetConstructor() != *arguments_function) && |
8150 !object->IsJSValue() && !object->IsAccessCheckNeeded() && | 8144 !object->IsJSValue() && !object->IsAccessCheckNeeded() && |
8151 !object->HasNamedInterceptor() && !object->HasIndexedInterceptor()); | 8145 !object->HasNamedInterceptor() && !object->HasIndexedInterceptor()); |
8152 // Compute the property keys and cache them if possible. | 8146 // Compute the property keys and cache them if possible. |
8153 Handle<FixedArray> enum_keys = | 8147 Handle<FixedArray> enum_keys = |
8154 JSObject::GetEnumPropertyKeys(object, cache_enum_length); | 8148 JSObject::GetEnumPropertyKeys(object, cache_enum_length); |
8155 accumulator->AddKeys(enum_keys); | 8149 accumulator->AddKeys(enum_keys); |
8156 } else { | 8150 } else { |
8157 DCHECK(filter == INCLUDE_SYMBOLS); | 8151 object->CollectOwnPropertyNames(accumulator, filter); |
8158 object->CollectOwnPropertyNames(accumulator, attr_filter); | |
8159 } | 8152 } |
8160 | 8153 |
8161 // Add the property keys from the interceptor. | 8154 // Add the property keys from the interceptor. |
8162 if (object->HasNamedInterceptor()) { | 8155 if (object->HasNamedInterceptor()) { |
8163 Handle<JSObject> result; | 8156 Handle<JSObject> result; |
8164 if (JSObject::GetKeysForNamedInterceptor(object, receiver) | 8157 if (JSObject::GetKeysForNamedInterceptor(object, receiver) |
8165 .ToHandle(&result)) { | 8158 .ToHandle(&result)) { |
8166 accumulator->AddKeys(result); | 8159 accumulator->AddKeys(result); |
8167 } | 8160 } |
8168 RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, false); | 8161 RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, false); |
8169 } | 8162 } |
8170 return true; | 8163 return true; |
8171 } | 8164 } |
8172 | 8165 |
8173 | 8166 |
8174 // Helper function for JSReceiver::GetKeys() below. Can be called recursively. | 8167 // Helper function for JSReceiver::GetKeys() below. Can be called recursively. |
8175 // Returns false iff an exception was thrown. | 8168 // Returns false iff an exception was thrown. |
8176 static bool GetKeys_Internal(Isolate* isolate, Handle<JSReceiver> receiver, | 8169 static bool GetKeys_Internal(Isolate* isolate, Handle<JSReceiver> receiver, |
8177 Handle<JSReceiver> object, | 8170 Handle<JSReceiver> object, |
8178 JSReceiver::KeyCollectionType type, | 8171 JSReceiver::KeyCollectionType type, |
8179 KeyFilter filter, Enumerability enum_policy, | 8172 PropertyFilter filter, |
8180 KeyAccumulator* accumulator) { | 8173 KeyAccumulator* accumulator) { |
8181 PrototypeIterator::WhereToEnd end = type == JSReceiver::OWN_ONLY | 8174 PrototypeIterator::WhereToEnd end = type == JSReceiver::OWN_ONLY |
8182 ? PrototypeIterator::END_AT_NON_HIDDEN | 8175 ? PrototypeIterator::END_AT_NON_HIDDEN |
8183 : PrototypeIterator::END_AT_NULL; | 8176 : PrototypeIterator::END_AT_NULL; |
8184 for (PrototypeIterator iter(isolate, object, | 8177 for (PrototypeIterator iter(isolate, object, |
8185 PrototypeIterator::START_AT_RECEIVER); | 8178 PrototypeIterator::START_AT_RECEIVER); |
8186 !iter.IsAtEnd(end); iter.Advance()) { | 8179 !iter.IsAtEnd(end); iter.Advance()) { |
8187 Handle<JSReceiver> current = | 8180 Handle<JSReceiver> current = |
8188 PrototypeIterator::GetCurrent<JSReceiver>(iter); | 8181 PrototypeIterator::GetCurrent<JSReceiver>(iter); |
8189 bool result = false; | 8182 bool result = false; |
8190 if (current->IsJSProxy()) { | 8183 if (current->IsJSProxy()) { |
8191 if (type == JSReceiver::OWN_ONLY) { | 8184 if (type == JSReceiver::OWN_ONLY) { |
8192 result = JSProxy::OwnPropertyKeys(isolate, receiver, | 8185 result = JSProxy::OwnPropertyKeys(isolate, receiver, |
8193 Handle<JSProxy>::cast(current), | 8186 Handle<JSProxy>::cast(current), |
8194 filter, enum_policy, accumulator); | 8187 filter, accumulator); |
8195 } else { | 8188 } else { |
8196 DCHECK(type == JSReceiver::INCLUDE_PROTOS); | 8189 DCHECK(type == JSReceiver::INCLUDE_PROTOS); |
8197 result = JSProxy::Enumerate( | 8190 result = JSProxy::Enumerate( |
8198 isolate, receiver, Handle<JSProxy>::cast(current), accumulator); | 8191 isolate, receiver, Handle<JSProxy>::cast(current), accumulator); |
8199 } | 8192 } |
8200 } else { | 8193 } else { |
8201 DCHECK(current->IsJSObject()); | 8194 DCHECK(current->IsJSObject()); |
8202 result = GetKeysFromJSObject(isolate, receiver, | 8195 result = GetKeysFromJSObject(isolate, receiver, |
8203 Handle<JSObject>::cast(current), filter, | 8196 Handle<JSObject>::cast(current), filter, |
8204 enum_policy, accumulator); | 8197 accumulator); |
8205 } | 8198 } |
8206 if (!result) { | 8199 if (!result) { |
8207 if (isolate->has_pending_exception()) { | 8200 if (isolate->has_pending_exception()) { |
8208 return false; | 8201 return false; |
8209 } | 8202 } |
8210 // If there was no exception, then "false" means "stop iterating". | 8203 // If there was no exception, then "false" means "stop iterating". |
8211 break; | 8204 break; |
8212 } | 8205 } |
8213 } | 8206 } |
8214 return true; | 8207 return true; |
(...skipping 21 matching lines...) Expand all Loading... |
8236 // 5. Let trap be ? GetMethod(handler, "enumerate"). | 8229 // 5. Let trap be ? GetMethod(handler, "enumerate"). |
8237 Handle<Object> trap; | 8230 Handle<Object> trap; |
8238 ASSIGN_RETURN_ON_EXCEPTION_VALUE( | 8231 ASSIGN_RETURN_ON_EXCEPTION_VALUE( |
8239 isolate, trap, Object::GetMethod(Handle<JSReceiver>::cast(handler), | 8232 isolate, trap, Object::GetMethod(Handle<JSReceiver>::cast(handler), |
8240 isolate->factory()->enumerate_string()), | 8233 isolate->factory()->enumerate_string()), |
8241 false); | 8234 false); |
8242 // 6. If trap is undefined, then | 8235 // 6. If trap is undefined, then |
8243 if (trap->IsUndefined()) { | 8236 if (trap->IsUndefined()) { |
8244 // 6a. Return target.[[Enumerate]](). | 8237 // 6a. Return target.[[Enumerate]](). |
8245 return GetKeys_Internal(isolate, receiver, target, INCLUDE_PROTOS, | 8238 return GetKeys_Internal(isolate, receiver, target, INCLUDE_PROTOS, |
8246 SKIP_SYMBOLS, RESPECT_ENUMERABILITY, accumulator); | 8239 ENUMERABLE_STRINGS, accumulator); |
8247 } | 8240 } |
8248 // The "proxy_enumerate" helper calls the trap (steps 7 - 9), which returns | 8241 // The "proxy_enumerate" helper calls the trap (steps 7 - 9), which returns |
8249 // a generator; it then iterates over that generator until it's exhausted | 8242 // a generator; it then iterates over that generator until it's exhausted |
8250 // and returns an array containing the generated values. | 8243 // and returns an array containing the generated values. |
8251 Handle<Object> trap_result_array; | 8244 Handle<Object> trap_result_array; |
8252 Handle<Object> args[] = {trap, handler, target}; | 8245 Handle<Object> args[] = {trap, handler, target}; |
8253 ASSIGN_RETURN_ON_EXCEPTION_VALUE( | 8246 ASSIGN_RETURN_ON_EXCEPTION_VALUE( |
8254 isolate, trap_result_array, | 8247 isolate, trap_result_array, |
8255 Execution::Call(isolate, isolate->proxy_enumerate(), | 8248 Execution::Call(isolate, isolate->proxy_enumerate(), |
8256 isolate->factory()->undefined_value(), arraysize(args), | 8249 isolate->factory()->undefined_value(), arraysize(args), |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8317 } | 8310 } |
8318 // 8. Return list. | 8311 // 8. Return list. |
8319 return list; | 8312 return list; |
8320 } | 8313 } |
8321 | 8314 |
8322 | 8315 |
8323 // ES6 9.5.12 | 8316 // ES6 9.5.12 |
8324 // Returns "false" in case of exception. | 8317 // Returns "false" in case of exception. |
8325 // static | 8318 // static |
8326 bool JSProxy::OwnPropertyKeys(Isolate* isolate, Handle<JSReceiver> receiver, | 8319 bool JSProxy::OwnPropertyKeys(Isolate* isolate, Handle<JSReceiver> receiver, |
8327 Handle<JSProxy> proxy, KeyFilter filter, | 8320 Handle<JSProxy> proxy, PropertyFilter filter, |
8328 Enumerability enum_policy, | |
8329 KeyAccumulator* accumulator) { | 8321 KeyAccumulator* accumulator) { |
8330 // 1. Let handler be the value of the [[ProxyHandler]] internal slot of O. | 8322 // 1. Let handler be the value of the [[ProxyHandler]] internal slot of O. |
8331 Handle<Object> handler(proxy->handler(), isolate); | 8323 Handle<Object> handler(proxy->handler(), isolate); |
8332 // 2. If handler is null, throw a TypeError exception. | 8324 // 2. If handler is null, throw a TypeError exception. |
8333 if (proxy->IsRevoked()) { | 8325 if (proxy->IsRevoked()) { |
8334 isolate->Throw(*isolate->factory()->NewTypeError( | 8326 isolate->Throw(*isolate->factory()->NewTypeError( |
8335 MessageTemplate::kProxyRevoked, isolate->factory()->ownKeys_string())); | 8327 MessageTemplate::kProxyRevoked, isolate->factory()->ownKeys_string())); |
8336 return false; | 8328 return false; |
8337 } | 8329 } |
8338 // 3. Assert: Type(handler) is Object. | 8330 // 3. Assert: Type(handler) is Object. |
8339 DCHECK(handler->IsJSReceiver()); | 8331 DCHECK(handler->IsJSReceiver()); |
8340 // 4. Let target be the value of the [[ProxyTarget]] internal slot of O. | 8332 // 4. Let target be the value of the [[ProxyTarget]] internal slot of O. |
8341 Handle<JSReceiver> target(JSReceiver::cast(proxy->target()), isolate); | 8333 Handle<JSReceiver> target(JSReceiver::cast(proxy->target()), isolate); |
8342 // 5. Let trap be ? GetMethod(handler, "ownKeys"). | 8334 // 5. Let trap be ? GetMethod(handler, "ownKeys"). |
8343 Handle<Object> trap; | 8335 Handle<Object> trap; |
8344 ASSIGN_RETURN_ON_EXCEPTION_VALUE( | 8336 ASSIGN_RETURN_ON_EXCEPTION_VALUE( |
8345 isolate, trap, Object::GetMethod(Handle<JSReceiver>::cast(handler), | 8337 isolate, trap, Object::GetMethod(Handle<JSReceiver>::cast(handler), |
8346 isolate->factory()->ownKeys_string()), | 8338 isolate->factory()->ownKeys_string()), |
8347 false); | 8339 false); |
8348 // 6. If trap is undefined, then | 8340 // 6. If trap is undefined, then |
8349 if (trap->IsUndefined()) { | 8341 if (trap->IsUndefined()) { |
8350 // 6a. Return target.[[OwnPropertyKeys]](). | 8342 // 6a. Return target.[[OwnPropertyKeys]](). |
8351 return GetKeys_Internal(isolate, receiver, target, OWN_ONLY, filter, | 8343 return GetKeys_Internal(isolate, receiver, target, OWN_ONLY, filter, |
8352 enum_policy, accumulator); | 8344 accumulator); |
8353 } | 8345 } |
8354 // 7. Let trapResultArray be Call(trap, handler, «target»). | 8346 // 7. Let trapResultArray be Call(trap, handler, «target»). |
8355 Handle<Object> trap_result_array; | 8347 Handle<Object> trap_result_array; |
8356 Handle<Object> args[] = {target}; | 8348 Handle<Object> args[] = {target}; |
8357 ASSIGN_RETURN_ON_EXCEPTION_VALUE( | 8349 ASSIGN_RETURN_ON_EXCEPTION_VALUE( |
8358 isolate, trap_result_array, | 8350 isolate, trap_result_array, |
8359 Execution::Call(isolate, trap, handler, arraysize(args), args), false); | 8351 Execution::Call(isolate, trap, handler, arraysize(args), args), false); |
8360 // 8. Let trapResult be ? CreateListFromArrayLike(trapResultArray, | 8352 // 8. Let trapResult be ? CreateListFromArrayLike(trapResultArray, |
8361 // «String, Symbol»). | 8353 // «String, Symbol»). |
8362 Handle<FixedArray> trap_result; | 8354 Handle<FixedArray> trap_result; |
8363 ASSIGN_RETURN_ON_EXCEPTION_VALUE( | 8355 ASSIGN_RETURN_ON_EXCEPTION_VALUE( |
8364 isolate, trap_result, | 8356 isolate, trap_result, |
8365 CreateListFromArrayLike_StringSymbol(isolate, trap_result_array), false); | 8357 CreateListFromArrayLike_StringSymbol(isolate, trap_result_array), false); |
8366 // 9. Let extensibleTarget be ? IsExtensible(target). | 8358 // 9. Let extensibleTarget be ? IsExtensible(target). |
8367 Maybe<bool> maybe_extensible = JSReceiver::IsExtensible(target); | 8359 Maybe<bool> maybe_extensible = JSReceiver::IsExtensible(target); |
8368 if (maybe_extensible.IsNothing()) return false; | 8360 if (maybe_extensible.IsNothing()) return false; |
8369 bool extensible_target = maybe_extensible.FromJust(); | 8361 bool extensible_target = maybe_extensible.FromJust(); |
8370 // 10. Let targetKeys be ? target.[[OwnPropertyKeys]](). | 8362 // 10. Let targetKeys be ? target.[[OwnPropertyKeys]](). |
8371 Handle<FixedArray> target_keys; | 8363 Handle<FixedArray> target_keys; |
8372 ASSIGN_RETURN_ON_EXCEPTION_VALUE( | 8364 ASSIGN_RETURN_ON_EXCEPTION_VALUE( |
8373 isolate, target_keys, | 8365 isolate, target_keys, |
8374 JSReceiver::GetKeys(target, JSReceiver::OWN_ONLY, INCLUDE_SYMBOLS, | 8366 JSReceiver::GetKeys(target, JSReceiver::OWN_ONLY, ALL_PROPERTIES, |
8375 CONVERT_TO_STRING, IGNORE_ENUMERABILITY), | 8367 CONVERT_TO_STRING), |
8376 false); | 8368 false); |
8377 // 11. (Assert) | 8369 // 11. (Assert) |
8378 // 12. Let targetConfigurableKeys be an empty List. | 8370 // 12. Let targetConfigurableKeys be an empty List. |
8379 // To save memory, we're re-using target_keys and will modify it in-place. | 8371 // To save memory, we're re-using target_keys and will modify it in-place. |
8380 Handle<FixedArray> target_configurable_keys = target_keys; | 8372 Handle<FixedArray> target_configurable_keys = target_keys; |
8381 // 13. Let targetNonconfigurableKeys be an empty List. | 8373 // 13. Let targetNonconfigurableKeys be an empty List. |
8382 Handle<FixedArray> target_nonconfigurable_keys = | 8374 Handle<FixedArray> target_nonconfigurable_keys = |
8383 isolate->factory()->NewFixedArray(target_keys->length()); | 8375 isolate->factory()->NewFixedArray(target_keys->length()); |
8384 int nonconfigurable_keys_length = 0; | 8376 int nonconfigurable_keys_length = 0; |
8385 // 14. Repeat, for each element key of targetKeys: | 8377 // 14. Repeat, for each element key of targetKeys: |
(...skipping 15 matching lines...) Expand all Loading... |
8401 // 14c. Else, | 8393 // 14c. Else, |
8402 // 14c i. Append key as an element of targetConfigurableKeys. | 8394 // 14c i. Append key as an element of targetConfigurableKeys. |
8403 // (No-op, just keep it in |target_keys|.) | 8395 // (No-op, just keep it in |target_keys|.) |
8404 } | 8396 } |
8405 } | 8397 } |
8406 accumulator->NextPrototype(); // Prepare for accumulating keys. | 8398 accumulator->NextPrototype(); // Prepare for accumulating keys. |
8407 // 15. If extensibleTarget is true and targetNonconfigurableKeys is empty, | 8399 // 15. If extensibleTarget is true and targetNonconfigurableKeys is empty, |
8408 // then: | 8400 // then: |
8409 if (extensible_target && nonconfigurable_keys_length == 0) { | 8401 if (extensible_target && nonconfigurable_keys_length == 0) { |
8410 // 15a. Return trapResult. | 8402 // 15a. Return trapResult. |
8411 return accumulator->AddKeysFromProxy(proxy, trap_result, filter, | 8403 return accumulator->AddKeysFromProxy(proxy, trap_result); |
8412 enum_policy); | |
8413 } | 8404 } |
8414 // 16. Let uncheckedResultKeys be a new List which is a copy of trapResult. | 8405 // 16. Let uncheckedResultKeys be a new List which is a copy of trapResult. |
8415 Zone set_zone; | 8406 Zone set_zone; |
8416 const int kPresent = 1; | 8407 const int kPresent = 1; |
8417 const int kGone = 0; | 8408 const int kGone = 0; |
8418 IdentityMap<int> unchecked_result_keys(isolate->heap(), &set_zone); | 8409 IdentityMap<int> unchecked_result_keys(isolate->heap(), &set_zone); |
8419 int unchecked_result_keys_size = trap_result->length(); | 8410 int unchecked_result_keys_size = trap_result->length(); |
8420 for (int i = 0; i < trap_result->length(); ++i) { | 8411 for (int i = 0; i < trap_result->length(); ++i) { |
8421 DCHECK(trap_result->get(i)->IsUniqueName()); | 8412 DCHECK(trap_result->get(i)->IsUniqueName()); |
8422 unchecked_result_keys.Set(trap_result->get(i), kPresent); | 8413 unchecked_result_keys.Set(trap_result->get(i), kPresent); |
8423 } | 8414 } |
8424 // 17. Repeat, for each key that is an element of targetNonconfigurableKeys: | 8415 // 17. Repeat, for each key that is an element of targetNonconfigurableKeys: |
8425 for (int i = 0; i < nonconfigurable_keys_length; ++i) { | 8416 for (int i = 0; i < nonconfigurable_keys_length; ++i) { |
8426 Object* key = target_nonconfigurable_keys->get(i); | 8417 Object* key = target_nonconfigurable_keys->get(i); |
8427 // 17a. If key is not an element of uncheckedResultKeys, throw a | 8418 // 17a. If key is not an element of uncheckedResultKeys, throw a |
8428 // TypeError exception. | 8419 // TypeError exception. |
8429 int* found = unchecked_result_keys.Find(key); | 8420 int* found = unchecked_result_keys.Find(key); |
8430 if (found == nullptr || *found == kGone) { | 8421 if (found == nullptr || *found == kGone) { |
8431 isolate->Throw(*isolate->factory()->NewTypeError( | 8422 isolate->Throw(*isolate->factory()->NewTypeError( |
8432 MessageTemplate::kProxyTrapResultMustInclude, handle(key, isolate))); | 8423 MessageTemplate::kProxyTrapResultMustInclude, handle(key, isolate))); |
8433 return false; | 8424 return false; |
8434 } | 8425 } |
8435 // 17b. Remove key from uncheckedResultKeys. | 8426 // 17b. Remove key from uncheckedResultKeys. |
8436 *found = kGone; | 8427 *found = kGone; |
8437 unchecked_result_keys_size--; | 8428 unchecked_result_keys_size--; |
8438 } | 8429 } |
8439 // 18. If extensibleTarget is true, return trapResult. | 8430 // 18. If extensibleTarget is true, return trapResult. |
8440 if (extensible_target) { | 8431 if (extensible_target) { |
8441 return accumulator->AddKeysFromProxy(proxy, trap_result, filter, | 8432 return accumulator->AddKeysFromProxy(proxy, trap_result); |
8442 enum_policy); | |
8443 } | 8433 } |
8444 // 19. Repeat, for each key that is an element of targetConfigurableKeys: | 8434 // 19. Repeat, for each key that is an element of targetConfigurableKeys: |
8445 for (int i = 0; i < target_configurable_keys->length(); ++i) { | 8435 for (int i = 0; i < target_configurable_keys->length(); ++i) { |
8446 Object* key = target_configurable_keys->get(i); | 8436 Object* key = target_configurable_keys->get(i); |
8447 if (key->IsSmi()) continue; // Zapped entry, was nonconfigurable. | 8437 if (key->IsSmi()) continue; // Zapped entry, was nonconfigurable. |
8448 // 19a. If key is not an element of uncheckedResultKeys, throw a | 8438 // 19a. If key is not an element of uncheckedResultKeys, throw a |
8449 // TypeError exception. | 8439 // TypeError exception. |
8450 int* found = unchecked_result_keys.Find(key); | 8440 int* found = unchecked_result_keys.Find(key); |
8451 if (found == nullptr || *found == kGone) { | 8441 if (found == nullptr || *found == kGone) { |
8452 isolate->Throw(*isolate->factory()->NewTypeError( | 8442 isolate->Throw(*isolate->factory()->NewTypeError( |
8453 MessageTemplate::kProxyTrapResultMustInclude, handle(key, isolate))); | 8443 MessageTemplate::kProxyTrapResultMustInclude, handle(key, isolate))); |
8454 return false; | 8444 return false; |
8455 } | 8445 } |
8456 // 19b. Remove key from uncheckedResultKeys. | 8446 // 19b. Remove key from uncheckedResultKeys. |
8457 *found = kGone; | 8447 *found = kGone; |
8458 unchecked_result_keys_size--; | 8448 unchecked_result_keys_size--; |
8459 } | 8449 } |
8460 // 20. If uncheckedResultKeys is not empty, throw a TypeError exception. | 8450 // 20. If uncheckedResultKeys is not empty, throw a TypeError exception. |
8461 if (unchecked_result_keys_size != 0) { | 8451 if (unchecked_result_keys_size != 0) { |
8462 DCHECK_GT(unchecked_result_keys_size, 0); | 8452 DCHECK_GT(unchecked_result_keys_size, 0); |
8463 isolate->Throw(*isolate->factory()->NewTypeError( | 8453 isolate->Throw(*isolate->factory()->NewTypeError( |
8464 MessageTemplate::kProxyTargetNotExtensible)); | 8454 MessageTemplate::kProxyTargetNotExtensible)); |
8465 return false; | 8455 return false; |
8466 } | 8456 } |
8467 // 21. Return trapResult. | 8457 // 21. Return trapResult. |
8468 return accumulator->AddKeysFromProxy(proxy, trap_result, filter, enum_policy); | 8458 return accumulator->AddKeysFromProxy(proxy, trap_result); |
8469 } | 8459 } |
8470 | 8460 |
8471 | 8461 |
8472 MaybeHandle<FixedArray> JSReceiver::GetKeys(Handle<JSReceiver> object, | 8462 MaybeHandle<FixedArray> JSReceiver::GetKeys(Handle<JSReceiver> object, |
8473 KeyCollectionType type, | 8463 KeyCollectionType type, |
8474 KeyFilter filter, | 8464 PropertyFilter filter, |
8475 GetKeysConversion keys_conversion, | 8465 GetKeysConversion keys_conversion) { |
8476 Enumerability enum_policy) { | |
8477 USE(ContainsOnlyValidKeys); | 8466 USE(ContainsOnlyValidKeys); |
8478 Isolate* isolate = object->GetIsolate(); | 8467 Isolate* isolate = object->GetIsolate(); |
8479 KeyAccumulator accumulator(isolate, filter); | 8468 KeyAccumulator accumulator(isolate, filter); |
8480 if (!GetKeys_Internal(isolate, object, object, type, filter, enum_policy, | 8469 if (!GetKeys_Internal(isolate, object, object, type, filter, &accumulator)) { |
8481 &accumulator)) { | |
8482 DCHECK(isolate->has_pending_exception()); | 8470 DCHECK(isolate->has_pending_exception()); |
8483 return MaybeHandle<FixedArray>(); | 8471 return MaybeHandle<FixedArray>(); |
8484 } | 8472 } |
8485 Handle<FixedArray> keys = accumulator.GetKeys(keys_conversion); | 8473 Handle<FixedArray> keys = accumulator.GetKeys(keys_conversion); |
8486 DCHECK(ContainsOnlyValidKeys(keys)); | 8474 DCHECK(ContainsOnlyValidKeys(keys)); |
8487 return keys; | 8475 return keys; |
8488 } | 8476 } |
8489 | 8477 |
8490 | 8478 |
8491 bool Map::DictionaryElementsInPrototypeChainOnly() { | 8479 bool Map::DictionaryElementsInPrototypeChainOnly() { |
(...skipping 5947 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
14439 return array; | 14427 return array; |
14440 } | 14428 } |
14441 | 14429 |
14442 Isolate* isolate = array->GetIsolate(); | 14430 Isolate* isolate = array->GetIsolate(); |
14443 List<uint32_t> indices; | 14431 List<uint32_t> indices; |
14444 List<Handle<Object> > old_values; | 14432 List<Handle<Object> > old_values; |
14445 Handle<Object> old_length_handle(array->length(), isolate); | 14433 Handle<Object> old_length_handle(array->length(), isolate); |
14446 uint32_t old_length = 0; | 14434 uint32_t old_length = 0; |
14447 CHECK(old_length_handle->ToArrayLength(&old_length)); | 14435 CHECK(old_length_handle->ToArrayLength(&old_length)); |
14448 | 14436 |
14449 static const PropertyAttributes kNoAttrFilter = NONE; | 14437 int num_elements = array->NumberOfOwnElements(ALL_PROPERTIES); |
14450 int num_elements = array->NumberOfOwnElements(kNoAttrFilter); | |
14451 if (num_elements > 0) { | 14438 if (num_elements > 0) { |
14452 if (old_length == static_cast<uint32_t>(num_elements)) { | 14439 if (old_length == static_cast<uint32_t>(num_elements)) { |
14453 // Simple case for arrays without holes. | 14440 // Simple case for arrays without holes. |
14454 for (uint32_t i = old_length - 1; i + 1 > new_length; --i) { | 14441 for (uint32_t i = old_length - 1; i + 1 > new_length; --i) { |
14455 if (!GetOldValue(isolate, array, i, &old_values, &indices)) break; | 14442 if (!GetOldValue(isolate, array, i, &old_values, &indices)) break; |
14456 } | 14443 } |
14457 } else { | 14444 } else { |
14458 // For sparse arrays, only iterate over existing elements. | 14445 // For sparse arrays, only iterate over existing elements. |
14459 // TODO(rafaelw): For fast, sparse arrays, we can avoid iterating over | 14446 // TODO(rafaelw): For fast, sparse arrays, we can avoid iterating over |
14460 // the to-be-removed indices twice. | 14447 // the to-be-removed indices twice. |
14461 Handle<FixedArray> keys = isolate->factory()->NewFixedArray(num_elements); | 14448 Handle<FixedArray> keys = isolate->factory()->NewFixedArray(num_elements); |
14462 array->GetOwnElementKeys(*keys, kNoAttrFilter); | 14449 array->GetOwnElementKeys(*keys, ALL_PROPERTIES); |
14463 while (num_elements-- > 0) { | 14450 while (num_elements-- > 0) { |
14464 uint32_t index = NumberToUint32(keys->get(num_elements)); | 14451 uint32_t index = NumberToUint32(keys->get(num_elements)); |
14465 if (index < new_length) break; | 14452 if (index < new_length) break; |
14466 if (!GetOldValue(isolate, array, index, &old_values, &indices)) break; | 14453 if (!GetOldValue(isolate, array, index, &old_values, &indices)) break; |
14467 } | 14454 } |
14468 } | 14455 } |
14469 } | 14456 } |
14470 | 14457 |
14471 SetLength(array, new_length); | 14458 SetLength(array, new_length); |
14472 | 14459 |
(...skipping 1205 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
15678 Maybe<bool> JSObject::HasRealNamedCallbackProperty(Handle<JSObject> object, | 15665 Maybe<bool> JSObject::HasRealNamedCallbackProperty(Handle<JSObject> object, |
15679 Handle<Name> name) { | 15666 Handle<Name> name) { |
15680 LookupIterator it = LookupIterator::PropertyOrElement( | 15667 LookupIterator it = LookupIterator::PropertyOrElement( |
15681 name->GetIsolate(), object, name, LookupIterator::OWN_SKIP_INTERCEPTOR); | 15668 name->GetIsolate(), object, name, LookupIterator::OWN_SKIP_INTERCEPTOR); |
15682 Maybe<PropertyAttributes> maybe_result = GetPropertyAttributes(&it); | 15669 Maybe<PropertyAttributes> maybe_result = GetPropertyAttributes(&it); |
15683 return maybe_result.IsJust() ? Just(it.state() == LookupIterator::ACCESSOR) | 15670 return maybe_result.IsJust() ? Just(it.state() == LookupIterator::ACCESSOR) |
15684 : Nothing<bool>(); | 15671 : Nothing<bool>(); |
15685 } | 15672 } |
15686 | 15673 |
15687 | 15674 |
15688 int JSObject::NumberOfOwnProperties(PropertyAttributes filter) { | 15675 // Private symbols are always filtered out. |
| 15676 int JSObject::NumberOfOwnProperties(PropertyFilter filter) { |
15689 if (HasFastProperties()) { | 15677 if (HasFastProperties()) { |
15690 Map* map = this->map(); | 15678 Map* map = this->map(); |
15691 if (filter == NONE) return map->NumberOfOwnDescriptors(); | 15679 if (filter == ENUMERABLE_STRINGS) { |
15692 if (filter == DONT_SHOW) { | 15680 // The cached enum length was computed with filter == ENUMERABLE_STRING, |
15693 // The cached enum length was computed with filter == DONT_SHOW, so | 15681 // so that's the only filter for which it's valid to retrieve it. |
15694 // that's the only filter for which it's valid to retrieve it. | |
15695 int result = map->EnumLength(); | 15682 int result = map->EnumLength(); |
15696 if (result != kInvalidEnumCacheSentinel) return result; | 15683 if (result != kInvalidEnumCacheSentinel) return result; |
15697 } | 15684 } |
15698 return map->NumberOfDescribedProperties(OWN_DESCRIPTORS, filter); | 15685 return map->NumberOfDescribedProperties(OWN_DESCRIPTORS, filter); |
15699 } else if (IsJSGlobalObject()) { | 15686 } else if (IsJSGlobalObject()) { |
15700 return global_dictionary()->NumberOfElementsFilterAttributes(filter); | 15687 return global_dictionary()->NumberOfElementsFilterAttributes(filter); |
15701 } else { | 15688 } else { |
15702 return property_dictionary()->NumberOfElementsFilterAttributes(filter); | 15689 return property_dictionary()->NumberOfElementsFilterAttributes(filter); |
15703 } | 15690 } |
15704 } | 15691 } |
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
15814 HeapSortPairs(this, numbers, len); | 15801 HeapSortPairs(this, numbers, len); |
15815 return; | 15802 return; |
15816 } | 15803 } |
15817 } | 15804 } |
15818 | 15805 |
15819 | 15806 |
15820 // Fill in the names of own properties into the supplied storage. The main | 15807 // Fill in the names of own properties into the supplied storage. The main |
15821 // purpose of this function is to provide reflection information for the object | 15808 // purpose of this function is to provide reflection information for the object |
15822 // mirrors. | 15809 // mirrors. |
15823 int JSObject::GetOwnPropertyNames(FixedArray* storage, int index, | 15810 int JSObject::GetOwnPropertyNames(FixedArray* storage, int index, |
15824 PropertyAttributes filter) { | 15811 PropertyFilter filter) { |
15825 DCHECK(storage->length() >= (NumberOfOwnProperties(filter) - index)); | 15812 DCHECK(storage->length() >= (NumberOfOwnProperties(filter) - index)); |
15826 if (HasFastProperties()) { | 15813 if (HasFastProperties()) { |
15827 int start_index = index; | 15814 int start_index = index; |
15828 int real_size = map()->NumberOfOwnDescriptors(); | 15815 int real_size = map()->NumberOfOwnDescriptors(); |
15829 DescriptorArray* descs = map()->instance_descriptors(); | 15816 DescriptorArray* descs = map()->instance_descriptors(); |
15830 for (int i = 0; i < real_size; i++) { | 15817 for (int i = 0; i < real_size; i++) { |
15831 if ((descs->GetDetails(i).attributes() & filter) == 0 && | 15818 if ((descs->GetDetails(i).attributes() & filter) == 0 && |
15832 !descs->GetKey(i)->FilterKey(filter)) { | 15819 !descs->GetKey(i)->FilterKey(filter)) { |
15833 storage->set(index++, descs->GetKey(i)); | 15820 storage->set(index++, descs->GetKey(i)); |
15834 } | 15821 } |
15835 } | 15822 } |
15836 return index - start_index; | 15823 return index - start_index; |
15837 } else if (IsJSGlobalObject()) { | 15824 } else if (IsJSGlobalObject()) { |
15838 return global_dictionary()->CopyKeysTo(storage, index, filter, | 15825 return global_dictionary()->CopyKeysTo(storage, index, filter, |
15839 GlobalDictionary::UNSORTED); | 15826 GlobalDictionary::UNSORTED); |
15840 } else { | 15827 } else { |
15841 return property_dictionary()->CopyKeysTo(storage, index, filter, | 15828 return property_dictionary()->CopyKeysTo(storage, index, filter, |
15842 NameDictionary::UNSORTED); | 15829 NameDictionary::UNSORTED); |
15843 } | 15830 } |
15844 } | 15831 } |
15845 | 15832 |
15846 | 15833 |
15847 void JSObject::CollectOwnPropertyNames(KeyAccumulator* keys, | 15834 void JSObject::CollectOwnPropertyNames(KeyAccumulator* keys, |
15848 PropertyAttributes filter) { | 15835 PropertyFilter filter) { |
15849 if (HasFastProperties()) { | 15836 if (HasFastProperties()) { |
15850 int real_size = map()->NumberOfOwnDescriptors(); | 15837 int real_size = map()->NumberOfOwnDescriptors(); |
15851 Handle<DescriptorArray> descs(map()->instance_descriptors()); | 15838 Handle<DescriptorArray> descs(map()->instance_descriptors()); |
15852 for (int i = 0; i < real_size; i++) { | 15839 for (int i = 0; i < real_size; i++) { |
15853 if ((descs->GetDetails(i).attributes() & filter) != 0) continue; | 15840 if ((descs->GetDetails(i).attributes() & filter) != 0) continue; |
15854 Name* key = descs->GetKey(i); | 15841 Name* key = descs->GetKey(i); |
15855 if (key->FilterKey(filter)) continue; | 15842 if (key->FilterKey(filter)) continue; |
15856 keys->AddKey(key); | 15843 keys->AddKey(key); |
15857 } | 15844 } |
15858 } else if (IsJSGlobalObject()) { | 15845 } else if (IsJSGlobalObject()) { |
15859 GlobalDictionary::CollectKeysTo(handle(global_dictionary()), keys, filter); | 15846 GlobalDictionary::CollectKeysTo(handle(global_dictionary()), keys, filter); |
15860 } else { | 15847 } else { |
15861 NameDictionary::CollectKeysTo(handle(property_dictionary()), keys, filter); | 15848 NameDictionary::CollectKeysTo(handle(property_dictionary()), keys, filter); |
15862 } | 15849 } |
15863 } | 15850 } |
15864 | 15851 |
15865 | 15852 |
15866 int JSObject::NumberOfOwnElements(PropertyAttributes filter) { | 15853 int JSObject::NumberOfOwnElements(PropertyFilter filter) { |
15867 // Fast case for objects with no elements. | 15854 // Fast case for objects with no elements. |
15868 if (!IsJSValue() && HasFastElements()) { | 15855 if (!IsJSValue() && HasFastElements()) { |
15869 uint32_t length = | 15856 uint32_t length = |
15870 IsJSArray() | 15857 IsJSArray() |
15871 ? static_cast<uint32_t>( | 15858 ? static_cast<uint32_t>( |
15872 Smi::cast(JSArray::cast(this)->length())->value()) | 15859 Smi::cast(JSArray::cast(this)->length())->value()) |
15873 : static_cast<uint32_t>(FixedArrayBase::cast(elements())->length()); | 15860 : static_cast<uint32_t>(FixedArrayBase::cast(elements())->length()); |
15874 if (length == 0) return 0; | 15861 if (length == 0) return 0; |
15875 } | 15862 } |
15876 // Compute the number of enumerable elements. | 15863 // Compute the number of enumerable elements. |
15877 return GetOwnElementKeys(NULL, filter); | 15864 return GetOwnElementKeys(NULL, filter); |
15878 } | 15865 } |
15879 | 15866 |
15880 | 15867 |
15881 int JSObject::NumberOfEnumElements() { | 15868 int JSObject::NumberOfEnumElements() { |
15882 return NumberOfOwnElements(static_cast<PropertyAttributes>(DONT_ENUM)); | 15869 return NumberOfOwnElements(ONLY_ENUMERABLE); |
15883 } | 15870 } |
15884 | 15871 |
15885 | 15872 |
15886 void JSObject::CollectOwnElementKeys(Handle<JSObject> object, | 15873 void JSObject::CollectOwnElementKeys(Handle<JSObject> object, |
15887 KeyAccumulator* keys, | 15874 KeyAccumulator* keys, |
15888 PropertyAttributes filter) { | 15875 PropertyFilter filter) { |
15889 uint32_t string_keys = 0; | 15876 uint32_t string_keys = 0; |
15890 | 15877 |
15891 // If this is a String wrapper, add the string indices first, | 15878 // If this is a String wrapper, add the string indices first, |
15892 // as they're guaranteed to precede the elements in numerical order | 15879 // as they're guaranteed to precede the elements in numerical order |
15893 // and ascending order is required by ECMA-262, 6th, 9.1.12. | 15880 // and ascending order is required by ECMA-262, 6th, 9.1.12. |
15894 if (object->IsJSValue()) { | 15881 if (object->IsJSValue()) { |
15895 Object* val = JSValue::cast(*object)->value(); | 15882 Object* val = JSValue::cast(*object)->value(); |
15896 if (val->IsString()) { | 15883 if (val->IsString()) { |
15897 String* str = String::cast(val); | 15884 String* str = String::cast(val); |
15898 string_keys = str->length(); | 15885 string_keys = str->length(); |
15899 for (uint32_t i = 0; i < string_keys; i++) { | 15886 for (uint32_t i = 0; i < string_keys; i++) { |
15900 keys->AddKey(i); | 15887 keys->AddKey(i); |
15901 } | 15888 } |
15902 } | 15889 } |
15903 } | 15890 } |
15904 ElementsAccessor* accessor = object->GetElementsAccessor(); | 15891 ElementsAccessor* accessor = object->GetElementsAccessor(); |
15905 accessor->CollectElementIndices(object, keys, kMaxUInt32, filter, 0); | 15892 accessor->CollectElementIndices(object, keys, kMaxUInt32, filter, 0); |
15906 } | 15893 } |
15907 | 15894 |
15908 | 15895 |
15909 int JSObject::GetOwnElementKeys(FixedArray* storage, | 15896 int JSObject::GetOwnElementKeys(FixedArray* storage, PropertyFilter filter) { |
15910 PropertyAttributes filter) { | |
15911 int counter = 0; | 15897 int counter = 0; |
15912 | 15898 |
15913 // If this is a String wrapper, add the string indices first, | 15899 // If this is a String wrapper, add the string indices first, |
15914 // as they're guaranteed to precede the elements in numerical order | 15900 // as they're guaranteed to precede the elements in numerical order |
15915 // and ascending order is required by ECMA-262, 6th, 9.1.12. | 15901 // and ascending order is required by ECMA-262, 6th, 9.1.12. |
15916 if (IsJSValue()) { | 15902 if (IsJSValue()) { |
15917 Object* val = JSValue::cast(this)->value(); | 15903 Object* val = JSValue::cast(this)->value(); |
15918 if (val->IsString()) { | 15904 if (val->IsString()) { |
15919 String* str = String::cast(val); | 15905 String* str = String::cast(val); |
15920 if (storage) { | 15906 if (storage) { |
(...skipping 1810 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
17731 if (entry == kNotFound) return AddNumberEntry(dictionary, key, value); | 17717 if (entry == kNotFound) return AddNumberEntry(dictionary, key, value); |
17732 Handle<Object> object_key = | 17718 Handle<Object> object_key = |
17733 UnseededNumberDictionaryShape::AsHandle(dictionary->GetIsolate(), key); | 17719 UnseededNumberDictionaryShape::AsHandle(dictionary->GetIsolate(), key); |
17734 dictionary->SetEntry(entry, object_key, value); | 17720 dictionary->SetEntry(entry, object_key, value); |
17735 return dictionary; | 17721 return dictionary; |
17736 } | 17722 } |
17737 | 17723 |
17738 | 17724 |
17739 template <typename Derived, typename Shape, typename Key> | 17725 template <typename Derived, typename Shape, typename Key> |
17740 int Dictionary<Derived, Shape, Key>::NumberOfElementsFilterAttributes( | 17726 int Dictionary<Derived, Shape, Key>::NumberOfElementsFilterAttributes( |
17741 PropertyAttributes filter) { | 17727 PropertyFilter filter) { |
17742 int capacity = this->Capacity(); | 17728 int capacity = this->Capacity(); |
17743 int result = 0; | 17729 int result = 0; |
17744 for (int i = 0; i < capacity; i++) { | 17730 for (int i = 0; i < capacity; i++) { |
17745 Object* k = this->KeyAt(i); | 17731 Object* k = this->KeyAt(i); |
17746 if (this->IsKey(k) && !k->FilterKey(filter)) { | 17732 if (this->IsKey(k) && !k->FilterKey(filter)) { |
17747 if (this->IsDeleted(i)) continue; | 17733 if (this->IsDeleted(i)) continue; |
17748 PropertyDetails details = this->DetailsAt(i); | 17734 PropertyDetails details = this->DetailsAt(i); |
17749 PropertyAttributes attr = details.attributes(); | 17735 PropertyAttributes attr = details.attributes(); |
17750 if ((attr & filter) == 0) result++; | 17736 if ((attr & filter) == 0) result++; |
17751 } | 17737 } |
17752 } | 17738 } |
17753 return result; | 17739 return result; |
17754 } | 17740 } |
17755 | 17741 |
17756 | 17742 |
17757 template <typename Derived, typename Shape, typename Key> | 17743 template <typename Derived, typename Shape, typename Key> |
17758 bool Dictionary<Derived, Shape, Key>::HasComplexElements() { | 17744 bool Dictionary<Derived, Shape, Key>::HasComplexElements() { |
17759 int capacity = this->Capacity(); | 17745 int capacity = this->Capacity(); |
17760 for (int i = 0; i < capacity; i++) { | 17746 for (int i = 0; i < capacity; i++) { |
17761 Object* k = this->KeyAt(i); | 17747 Object* k = this->KeyAt(i); |
17762 if (this->IsKey(k) && !k->FilterKey(NONE)) { | 17748 if (this->IsKey(k) && !k->FilterKey(ALL_PROPERTIES)) { |
17763 if (this->IsDeleted(i)) continue; | 17749 if (this->IsDeleted(i)) continue; |
17764 PropertyDetails details = this->DetailsAt(i); | 17750 PropertyDetails details = this->DetailsAt(i); |
17765 if (details.type() == ACCESSOR_CONSTANT) return true; | 17751 if (details.type() == ACCESSOR_CONSTANT) return true; |
17766 PropertyAttributes attr = details.attributes(); | 17752 PropertyAttributes attr = details.attributes(); |
17767 if (attr & (READ_ONLY | DONT_DELETE | DONT_ENUM)) return true; | 17753 if (attr & ALL_ATTRIBUTES_MASK) return true; |
17768 } | 17754 } |
17769 } | 17755 } |
17770 return false; | 17756 return false; |
17771 } | 17757 } |
17772 | 17758 |
17773 | 17759 |
17774 template <typename Dictionary> | 17760 template <typename Dictionary> |
17775 struct EnumIndexComparator { | 17761 struct EnumIndexComparator { |
17776 explicit EnumIndexComparator(Dictionary* dict) : dict(dict) {} | 17762 explicit EnumIndexComparator(Dictionary* dict) : dict(dict) {} |
17777 bool operator() (Smi* a, Smi* b) { | 17763 bool operator() (Smi* a, Smi* b) { |
(...skipping 26 matching lines...) Expand all Loading... |
17804 std::sort(start, start + length, cmp); | 17790 std::sort(start, start + length, cmp); |
17805 for (int i = 0; i < length; i++) { | 17791 for (int i = 0; i < length; i++) { |
17806 int index = Smi::cast(storage->get(i))->value(); | 17792 int index = Smi::cast(storage->get(i))->value(); |
17807 storage->set(i, this->KeyAt(index)); | 17793 storage->set(i, this->KeyAt(index)); |
17808 } | 17794 } |
17809 } | 17795 } |
17810 | 17796 |
17811 | 17797 |
17812 template <typename Derived, typename Shape, typename Key> | 17798 template <typename Derived, typename Shape, typename Key> |
17813 int Dictionary<Derived, Shape, Key>::CopyKeysTo( | 17799 int Dictionary<Derived, Shape, Key>::CopyKeysTo( |
17814 FixedArray* storage, int index, PropertyAttributes filter, | 17800 FixedArray* storage, int index, PropertyFilter filter, |
17815 typename Dictionary<Derived, Shape, Key>::SortMode sort_mode) { | 17801 typename Dictionary<Derived, Shape, Key>::SortMode sort_mode) { |
17816 DCHECK(storage->length() >= NumberOfElementsFilterAttributes(filter)); | 17802 DCHECK(storage->length() >= NumberOfElementsFilterAttributes(filter)); |
17817 int start_index = index; | 17803 int start_index = index; |
17818 int capacity = this->Capacity(); | 17804 int capacity = this->Capacity(); |
17819 for (int i = 0; i < capacity; i++) { | 17805 for (int i = 0; i < capacity; i++) { |
17820 Object* k = this->KeyAt(i); | 17806 Object* k = this->KeyAt(i); |
17821 if (!this->IsKey(k) || k->FilterKey(filter)) continue; | 17807 if (!this->IsKey(k) || k->FilterKey(filter)) continue; |
17822 if (this->IsDeleted(i)) continue; | 17808 if (this->IsDeleted(i)) continue; |
17823 PropertyDetails details = this->DetailsAt(i); | 17809 PropertyDetails details = this->DetailsAt(i); |
17824 PropertyAttributes attr = details.attributes(); | 17810 PropertyAttributes attr = details.attributes(); |
17825 if ((attr & filter) != 0) continue; | 17811 if ((attr & filter) != 0) continue; |
17826 storage->set(index++, k); | 17812 storage->set(index++, k); |
17827 } | 17813 } |
17828 if (sort_mode == Dictionary::SORTED) { | 17814 if (sort_mode == Dictionary::SORTED) { |
17829 storage->SortPairs(storage, index); | 17815 storage->SortPairs(storage, index); |
17830 } | 17816 } |
17831 DCHECK(storage->length() >= index); | 17817 DCHECK(storage->length() >= index); |
17832 return index - start_index; | 17818 return index - start_index; |
17833 } | 17819 } |
17834 | 17820 |
17835 | 17821 |
17836 template <typename Derived, typename Shape, typename Key> | 17822 template <typename Derived, typename Shape, typename Key> |
17837 void Dictionary<Derived, Shape, Key>::CollectKeysTo( | 17823 void Dictionary<Derived, Shape, Key>::CollectKeysTo( |
17838 Handle<Dictionary<Derived, Shape, Key> > dictionary, KeyAccumulator* keys, | 17824 Handle<Dictionary<Derived, Shape, Key> > dictionary, KeyAccumulator* keys, |
17839 PropertyAttributes filter) { | 17825 PropertyFilter filter) { |
17840 int capacity = dictionary->Capacity(); | 17826 int capacity = dictionary->Capacity(); |
17841 Handle<FixedArray> array = | 17827 Handle<FixedArray> array = |
17842 keys->isolate()->factory()->NewFixedArray(dictionary->NumberOfElements()); | 17828 keys->isolate()->factory()->NewFixedArray(dictionary->NumberOfElements()); |
17843 int array_size = 0; | 17829 int array_size = 0; |
17844 | 17830 |
17845 { | 17831 { |
17846 DisallowHeapAllocation no_gc; | 17832 DisallowHeapAllocation no_gc; |
17847 Dictionary<Derived, Shape, Key>* raw_dict = *dictionary; | 17833 Dictionary<Derived, Shape, Key>* raw_dict = *dictionary; |
17848 for (int i = 0; i < capacity; i++) { | 17834 for (int i = 0; i < capacity; i++) { |
17849 Object* k = raw_dict->KeyAt(i); | 17835 Object* k = raw_dict->KeyAt(i); |
(...skipping 1219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
19069 if (cell->value() != *new_value) { | 19055 if (cell->value() != *new_value) { |
19070 cell->set_value(*new_value); | 19056 cell->set_value(*new_value); |
19071 Isolate* isolate = cell->GetIsolate(); | 19057 Isolate* isolate = cell->GetIsolate(); |
19072 cell->dependent_code()->DeoptimizeDependentCodeGroup( | 19058 cell->dependent_code()->DeoptimizeDependentCodeGroup( |
19073 isolate, DependentCode::kPropertyCellChangedGroup); | 19059 isolate, DependentCode::kPropertyCellChangedGroup); |
19074 } | 19060 } |
19075 } | 19061 } |
19076 | 19062 |
19077 } // namespace internal | 19063 } // namespace internal |
19078 } // namespace v8 | 19064 } // namespace v8 |
OLD | NEW |