Index: src/objects.cc |
diff --git a/src/objects.cc b/src/objects.cc |
index 4f9773cf7ce427947af6c23877ba4d72078dde6d..f192d9b6a56a20ed42131f18c5cfbabce2755350 100644 |
--- a/src/objects.cc |
+++ b/src/objects.cc |
@@ -6759,11 +6759,10 @@ void KeyAccumulator::AddKey(Handle<Object> key, int check_limit) { |
} |
-void KeyAccumulator::AddKeys(Handle<FixedArray> array, |
- FixedArray::KeyFilter filter) { |
+void KeyAccumulator::AddKeys(Handle<FixedArray> array, KeyFilter filter) { |
int add_length = array->length(); |
if (add_length == 0) return; |
- if (keys_.is_null() && filter == FixedArray::ALL_KEYS) { |
+ if (keys_.is_null() && filter == INCLUDE_SYMBOLS) { |
keys_ = array; |
length_ = keys_->length(); |
return; |
@@ -6772,14 +6771,13 @@ void KeyAccumulator::AddKeys(Handle<FixedArray> array, |
int previous_key_count = length_; |
for (int i = 0; i < add_length; i++) { |
Handle<Object> current(array->get(i), isolate_); |
- if (filter == FixedArray::NON_SYMBOL_KEYS && current->IsSymbol()) continue; |
+ if (filter == SKIP_SYMBOLS && current->IsSymbol()) continue; |
AddKey(current, previous_key_count); |
} |
} |
-void KeyAccumulator::AddKeys(Handle<JSObject> array_like, |
- FixedArray::KeyFilter filter) { |
+void KeyAccumulator::AddKeys(Handle<JSObject> array_like, KeyFilter filter) { |
DCHECK(array_like->IsJSArray() || array_like->HasSloppyArgumentsElements()); |
ElementsAccessor* accessor = array_like->GetElementsAccessor(); |
accessor->AddElementsToKeyAccumulator(array_like, this, filter); |
@@ -6831,7 +6829,8 @@ void KeyAccumulator::Grow() { |
MaybeHandle<FixedArray> JSReceiver::GetKeys(Handle<JSReceiver> object, |
- KeyCollectionType type) { |
+ KeyCollectionType type, |
+ KeyFilter filter) { |
USE(ContainsOnlyValidKeys); |
Isolate* isolate = object->GetIsolate(); |
KeyAccumulator accumulator(isolate); |
@@ -6857,7 +6856,7 @@ MaybeHandle<FixedArray> JSReceiver::GetKeys(Handle<JSReceiver> object, |
arraysize(args), |
args), |
FixedArray); |
- accumulator.AddKeys(Handle<JSObject>::cast(names), FixedArray::ALL_KEYS); |
+ accumulator.AddKeys(Handle<JSObject>::cast(names), filter); |
break; |
} |
@@ -6876,7 +6875,7 @@ MaybeHandle<FixedArray> JSReceiver::GetKeys(Handle<JSReceiver> object, |
Handle<FixedArray> element_keys = |
isolate->factory()->NewFixedArray(current->NumberOfEnumElements()); |
current->GetEnumElementKeys(*element_keys); |
- accumulator.AddKeys(element_keys, FixedArray::ALL_KEYS); |
+ accumulator.AddKeys(element_keys, filter); |
DCHECK(ContainsOnlyValidKeys(accumulator.GetKeys())); |
// Add the element keys from the interceptor. |
@@ -6884,38 +6883,49 @@ MaybeHandle<FixedArray> JSReceiver::GetKeys(Handle<JSReceiver> object, |
Handle<JSObject> result; |
if (JSObject::GetKeysForIndexedInterceptor( |
current, object).ToHandle(&result)) { |
- accumulator.AddKeys(result, FixedArray::ALL_KEYS); |
+ accumulator.AddKeys(result, filter); |
} |
DCHECK(ContainsOnlyValidKeys(accumulator.GetKeys())); |
} |
- // We can cache the computed property keys if access checks are |
- // not needed and no interceptors are involved. |
- // |
- // We do not use the cache if the object has elements and |
- // therefore it does not make sense to cache the property names |
- // for arguments objects. Arguments objects will always have |
- // elements. |
- // Wrapped strings have elements, but don't have an elements |
- // array or dictionary. So the fast inline test for whether to |
- // use the cache says yes, so we should not create a cache. |
- bool cache_enum_length = |
- ((current->map()->GetConstructor() != *arguments_function) && |
- !current->IsJSValue() && !current->IsAccessCheckNeeded() && |
- !current->HasNamedInterceptor() && !current->HasIndexedInterceptor()); |
- // Compute the property keys and cache them if possible. |
- |
- Handle<FixedArray> enum_keys = |
- JSObject::GetEnumPropertyKeys(current, cache_enum_length); |
- accumulator.AddKeys(enum_keys, FixedArray::ALL_KEYS); |
+ if (filter == SKIP_SYMBOLS) { |
+ // We can cache the computed property keys if access checks are |
+ // not needed and no interceptors are involved. |
+ // |
+ // We do not use the cache if the object has elements and |
+ // therefore it does not make sense to cache the property names |
+ // for arguments objects. Arguments objects will always have |
+ // elements. |
+ // Wrapped strings have elements, but don't have an elements |
+ // array or dictionary. So the fast inline test for whether to |
+ // use the cache says yes, so we should not create a cache. |
+ bool cache_enum_length = |
+ ((current->map()->GetConstructor() != *arguments_function) && |
+ !current->IsJSValue() && !current->IsAccessCheckNeeded() && |
+ !current->HasNamedInterceptor() && |
+ !current->HasIndexedInterceptor()); |
+ // Compute the property keys and cache them if possible. |
+ |
+ Handle<FixedArray> enum_keys = |
+ JSObject::GetEnumPropertyKeys(current, cache_enum_length); |
+ accumulator.AddKeys(enum_keys, filter); |
+ } else { |
+ DCHECK(filter == INCLUDE_SYMBOLS); |
+ PropertyAttributes attr_filter = |
+ static_cast<PropertyAttributes>(DONT_ENUM | PRIVATE_SYMBOL); |
+ Handle<FixedArray> property_keys = isolate->factory()->NewFixedArray( |
+ current->NumberOfOwnProperties(attr_filter)); |
+ current->GetOwnPropertyNames(*property_keys, 0, attr_filter); |
+ accumulator.AddKeys(property_keys, filter); |
+ } |
DCHECK(ContainsOnlyValidKeys(accumulator.GetKeys())); |
- // Add the non-symbol property keys from the interceptor. |
+ // Add the property keys from the interceptor. |
if (current->HasNamedInterceptor()) { |
Handle<JSObject> result; |
if (JSObject::GetKeysForNamedInterceptor( |
current, object).ToHandle(&result)) { |
- accumulator.AddKeys(result, FixedArray::NON_SYMBOL_KEYS); |
+ accumulator.AddKeys(result, filter); |
} |
DCHECK(ContainsOnlyValidKeys(accumulator.GetKeys())); |
} |
@@ -13833,13 +13843,8 @@ int JSObject::GetOwnPropertyNames(FixedArray* storage, int index, |
int JSObject::NumberOfOwnElements(PropertyAttributes filter) { |
- return GetOwnElementKeys(NULL, filter); |
-} |
- |
- |
-int JSObject::NumberOfEnumElements() { |
// Fast case for objects with no elements. |
- if (!IsJSValue() && HasFastObjectElements()) { |
+ if (!IsJSValue() && HasFastElements()) { |
uint32_t length = IsJSArray() ? |
static_cast<uint32_t>( |
Smi::cast(JSArray::cast(this)->length())->value()) : |
@@ -13847,6 +13852,11 @@ int JSObject::NumberOfEnumElements() { |
if (length == 0) return 0; |
} |
// Compute the number of enumerable elements. |
+ return GetOwnElementKeys(NULL, filter); |
+} |
+ |
+ |
+int JSObject::NumberOfEnumElements() { |
return NumberOfOwnElements(static_cast<PropertyAttributes>(DONT_ENUM)); |
} |