| Index: src/objects.cc
|
| diff --git a/src/objects.cc b/src/objects.cc
|
| index 326b6f169ceb29b9c6364866bb21775fcbf73d3d..22afd5ba257927287d77c3190320293a317a7670 100644
|
| --- a/src/objects.cc
|
| +++ b/src/objects.cc
|
| @@ -8099,7 +8099,7 @@ MaybeHandle<JSObject> JSObjectWalkVisitor<ContextObject>::StructureWalk(
|
| ONLY_WRITABLE | ONLY_ENUMERABLE | ONLY_CONFIGURABLE);
|
| KeyAccumulator accumulator(isolate, filter);
|
| accumulator.NextPrototype();
|
| - copy->CollectOwnPropertyNames(&accumulator, filter);
|
| + copy->CollectOwnPropertyKeys(&accumulator, filter);
|
| Handle<FixedArray> names = accumulator.GetKeys();
|
| for (int i = 0; i < names->length(); i++) {
|
| DCHECK(names->get(i)->IsName());
|
| @@ -8622,30 +8622,7 @@ static Maybe<bool> GetKeysFromJSObject(Isolate* isolate,
|
| isolate, receiver, object, *filter, accumulator);
|
| MAYBE_RETURN(success, Nothing<bool>());
|
|
|
| - if (*filter == ENUMERABLE_STRINGS) {
|
| - // 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.
|
| - Handle<JSFunction> arguments_function(
|
| - JSFunction::cast(isolate->sloppy_arguments_map()->GetConstructor()));
|
| - bool cache_enum_length =
|
| - ((object->map()->GetConstructor() != *arguments_function) &&
|
| - !object->IsJSValue() && !object->IsAccessCheckNeeded() &&
|
| - !object->HasNamedInterceptor() && !object->HasIndexedInterceptor());
|
| - // Compute the property keys and cache them if possible.
|
| - Handle<FixedArray> enum_keys =
|
| - JSObject::GetEnumPropertyKeys(object, cache_enum_length);
|
| - accumulator->AddKeys(enum_keys);
|
| - } else {
|
| - object->CollectOwnPropertyNames(accumulator, *filter);
|
| - }
|
| + object->CollectOwnPropertyKeys(accumulator, *filter, type);
|
|
|
| // Add the property keys from the interceptor.
|
| success = GetKeysFromInterceptor<v8::GenericNamedPropertyEnumeratorCallback,
|
| @@ -16381,14 +16358,21 @@ void FixedArray::SortPairs(FixedArray* numbers, uint32_t len) {
|
| }
|
|
|
|
|
| -void JSObject::CollectOwnPropertyNames(KeyAccumulator* keys,
|
| - PropertyFilter filter) {
|
| +void JSObject::CollectOwnPropertyKeys(KeyAccumulator* keys,
|
| + PropertyFilter filter,
|
| + JSReceiver::KeyCollectionType type) {
|
| if (HasFastProperties()) {
|
| int real_size = map()->NumberOfOwnDescriptors();
|
| Handle<DescriptorArray> descs(map()->instance_descriptors());
|
| for (int i = 0; i < real_size; i++) {
|
| PropertyDetails details = descs->GetDetails(i);
|
| - if ((details.attributes() & filter) != 0) continue;
|
| + if ((details.attributes() & filter) != 0) {
|
| + if (type == JSReceiver::OWN_ONLY) continue;
|
| + if (details.attributes() & DONT_ENUM) {
|
| + keys->HideKey(descs->GetKey(i));
|
| + }
|
| + continue;
|
| + }
|
| if (filter & ONLY_ALL_CAN_READ) {
|
| if (details.kind() != kAccessor) continue;
|
| Object* accessors = descs->GetValue(i);
|
| @@ -18432,20 +18416,27 @@ template <typename Derived, typename Shape, typename Key>
|
| void Dictionary<Derived, Shape, Key>::CollectKeysTo(
|
| Handle<Dictionary<Derived, Shape, Key> > dictionary, KeyAccumulator* keys,
|
| PropertyFilter filter) {
|
| + if (dictionary->NumberOfElements() == 0) return;
|
| int capacity = dictionary->Capacity();
|
| Handle<FixedArray> array =
|
| keys->isolate()->factory()->NewFixedArray(dictionary->NumberOfElements());
|
| int array_size = 0;
|
| + std::vector<int> hidden_key_indices;
|
|
|
| {
|
| DisallowHeapAllocation no_gc;
|
| Dictionary<Derived, Shape, Key>* raw_dict = *dictionary;
|
| for (int i = 0; i < capacity; i++) {
|
| - Object* k = raw_dict->KeyAt(i);
|
| - if (!raw_dict->IsKey(k) || k->FilterKey(filter)) continue;
|
| + Object* key = raw_dict->KeyAt(i);
|
| + if (!raw_dict->IsKey(key) || key->FilterKey(filter)) continue;
|
| if (raw_dict->IsDeleted(i)) continue;
|
| PropertyDetails details = raw_dict->DetailsAt(i);
|
| - if ((details.attributes() & filter) != 0) continue;
|
| + if ((details.attributes() & filter) != 0) {
|
| + if (details.attributes() & DONT_ENUM) {
|
| + hidden_key_indices.push_back(i);
|
| + }
|
| + continue;
|
| + }
|
| if (filter & ONLY_ALL_CAN_READ) {
|
| if (details.kind() != kAccessor) continue;
|
| Object* accessors = raw_dict->ValueAt(i);
|
| @@ -18462,7 +18453,9 @@ void Dictionary<Derived, Shape, Key>::CollectKeysTo(
|
| Smi** start = reinterpret_cast<Smi**>(array->GetFirstElementAddress());
|
| std::sort(start, start + array_size, cmp);
|
| }
|
| -
|
| + for (int i = 0; i < hidden_key_indices.size(); i++) {
|
| + keys->HideKey(dictionary->KeyAt(hidden_key_indices[i]));
|
| + }
|
| for (int i = 0; i < array_size; i++) {
|
| int index = Smi::cast(array->get(i))->value();
|
| keys->AddKey(dictionary->KeyAt(index));
|
|
|