Chromium Code Reviews| 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/keys.h" | 5 #include "src/keys.h" |
| 6 | 6 |
| 7 #include "src/api-arguments.h" | 7 #include "src/api-arguments.h" |
| 8 #include "src/elements.h" | 8 #include "src/elements.h" |
| 9 #include "src/factory.h" | 9 #include "src/factory.h" |
| 10 #include "src/identity-map.h" | 10 #include "src/identity-map.h" |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 62 AddKey(handle(key, isolate_), convert); | 62 AddKey(handle(key, isolate_), convert); |
| 63 } | 63 } |
| 64 | 64 |
| 65 void KeyAccumulator::AddKey(Handle<Object> key, AddKeyConversion convert) { | 65 void KeyAccumulator::AddKey(Handle<Object> key, AddKeyConversion convert) { |
| 66 if (key->IsSymbol()) { | 66 if (key->IsSymbol()) { |
| 67 if (filter_ & SKIP_SYMBOLS) return; | 67 if (filter_ & SKIP_SYMBOLS) return; |
| 68 if (Handle<Symbol>::cast(key)->is_private()) return; | 68 if (Handle<Symbol>::cast(key)->is_private()) return; |
| 69 } else if (filter_ & SKIP_STRINGS) { | 69 } else if (filter_ & SKIP_STRINGS) { |
| 70 return; | 70 return; |
| 71 } | 71 } |
| 72 if (IsShadowed(key)) return; | |
| 72 if (keys_.is_null()) { | 73 if (keys_.is_null()) { |
| 73 keys_ = OrderedHashSet::Allocate(isolate_, 16); | 74 keys_ = OrderedHashSet::Allocate(isolate_, 16); |
| 74 } | 75 } |
| 75 uint32_t index; | 76 uint32_t index; |
| 76 if (convert == CONVERT_TO_ARRAY_INDEX && key->IsString() && | 77 if (convert == CONVERT_TO_ARRAY_INDEX && key->IsString() && |
| 77 Handle<String>::cast(key)->AsArrayIndex(&index)) { | 78 Handle<String>::cast(key)->AsArrayIndex(&index)) { |
| 78 key = isolate_->factory()->NewNumberFromUint(index); | 79 key = isolate_->factory()->NewNumberFromUint(index); |
| 79 } | 80 } |
| 80 keys_ = OrderedHashSet::Add(keys(), key); | 81 keys_ = OrderedHashSet::Add(keys(), key); |
| 81 } | 82 } |
| 82 | 83 |
| 83 void KeyAccumulator::AddKeys(Handle<FixedArray> array, | 84 void KeyAccumulator::AddKeys(Handle<FixedArray> array, |
| 84 AddKeyConversion convert) { | 85 AddKeyConversion convert) { |
| 85 int add_length = array->length(); | 86 int add_length = array->length(); |
| 86 for (int i = 0; i < add_length; i++) { | 87 for (int i = 0; i < add_length; i++) { |
| 87 Handle<Object> current(array->get(i), isolate_); | 88 Handle<Object> current(array->get(i), isolate_); |
| 88 AddKey(current, convert); | 89 AddKey(current, convert); |
| 89 } | 90 } |
| 90 } | 91 } |
| 91 | 92 |
| 92 void KeyAccumulator::AddKeys(Handle<JSObject> array_like, | 93 void KeyAccumulator::AddKeys(Handle<JSObject> array_like, |
| 93 AddKeyConversion convert) { | 94 AddKeyConversion convert) { |
| 94 DCHECK(array_like->IsJSArray() || array_like->HasSloppyArgumentsElements()); | 95 DCHECK(array_like->IsJSArray() || array_like->HasSloppyArgumentsElements()); |
| 95 ElementsAccessor* accessor = array_like->GetElementsAccessor(); | 96 ElementsAccessor* accessor = array_like->GetElementsAccessor(); |
| 96 accessor->AddElementsToKeyAccumulator(array_like, this, convert); | 97 accessor->AddElementsToKeyAccumulator(array_like, this, convert); |
| 97 } | 98 } |
| 98 | 99 |
| 99 MaybeHandle<FixedArray> FilterProxyKeys(Isolate* isolate, Handle<JSProxy> owner, | 100 MaybeHandle<FixedArray> FilterProxyKeys(KeyAccumulator* accumulator, |
| 101 Handle<JSProxy> owner, | |
| 100 Handle<FixedArray> keys, | 102 Handle<FixedArray> keys, |
| 101 PropertyFilter filter) { | 103 PropertyFilter filter) { |
| 102 if (filter == ALL_PROPERTIES) { | 104 if (filter == ALL_PROPERTIES) { |
| 103 // Nothing to do. | 105 // Nothing to do. |
| 104 return keys; | 106 return keys; |
| 105 } | 107 } |
| 108 Isolate* isolate = accumulator->isolate(); | |
| 106 int store_position = 0; | 109 int store_position = 0; |
| 107 for (int i = 0; i < keys->length(); ++i) { | 110 for (int i = 0; i < keys->length(); ++i) { |
| 108 Handle<Name> key(Name::cast(keys->get(i)), isolate); | 111 Handle<Name> key(Name::cast(keys->get(i)), isolate); |
| 109 if (key->FilterKey(filter)) continue; // Skip this key. | 112 if (key->FilterKey(filter)) continue; // Skip this key. |
| 110 if (filter & ONLY_ENUMERABLE) { | 113 if (filter & ONLY_ENUMERABLE) { |
| 111 PropertyDescriptor desc; | 114 PropertyDescriptor desc; |
| 112 Maybe<bool> found = | 115 Maybe<bool> found = |
| 113 JSProxy::GetOwnPropertyDescriptor(isolate, owner, key, &desc); | 116 JSProxy::GetOwnPropertyDescriptor(isolate, owner, key, &desc); |
| 114 MAYBE_RETURN(found, MaybeHandle<FixedArray>()); | 117 MAYBE_RETURN(found, MaybeHandle<FixedArray>()); |
| 115 if (!found.FromJust() || !desc.enumerable()) continue; // Skip this key. | 118 if (!found.FromJust()) continue; |
| 119 if (!desc.enumerable()) { | |
| 120 accumulator->AddShadowKey(key); | |
| 121 continue; | |
| 122 } | |
| 116 } | 123 } |
| 117 // Keep this key. | 124 // Keep this key. |
| 118 if (store_position != i) { | 125 if (store_position != i) { |
| 119 keys->set(store_position, *key); | 126 keys->set(store_position, *key); |
| 120 } | 127 } |
| 121 store_position++; | 128 store_position++; |
| 122 } | 129 } |
| 123 if (store_position == 0) return isolate->factory()->empty_fixed_array(); | 130 if (store_position == 0) return isolate->factory()->empty_fixed_array(); |
| 124 keys->Shrink(store_position); | 131 keys->Shrink(store_position); |
| 125 return keys; | 132 return keys; |
| 126 } | 133 } |
| 127 | 134 |
| 128 // Returns "nothing" in case of exception, "true" on success. | 135 // Returns "nothing" in case of exception, "true" on success. |
| 129 Maybe<bool> KeyAccumulator::AddKeysFromJSProxy(Handle<JSProxy> proxy, | 136 Maybe<bool> KeyAccumulator::AddKeysFromJSProxy(Handle<JSProxy> proxy, |
| 130 Handle<FixedArray> keys) { | 137 Handle<FixedArray> keys) { |
| 131 if (filter_proxy_keys_) { | 138 if (filter_proxy_keys_) { |
| 132 DCHECK(!is_for_in_); | 139 DCHECK(!is_for_in_); |
| 133 ASSIGN_RETURN_ON_EXCEPTION_VALUE( | 140 ASSIGN_RETURN_ON_EXCEPTION_VALUE( |
| 134 isolate_, keys, FilterProxyKeys(isolate_, proxy, keys, filter_), | 141 isolate_, keys, FilterProxyKeys(this, proxy, keys, filter_), |
| 135 Nothing<bool>()); | 142 Nothing<bool>()); |
| 136 } | 143 } |
| 137 if (mode_ == KeyCollectionMode::kOwnOnly && !is_for_in_) { | 144 if (mode_ == KeyCollectionMode::kOwnOnly && !is_for_in_) { |
| 138 // If we collect only the keys from a JSProxy do not sort or deduplicate it. | 145 // If we collect only the keys from a JSProxy do not sort or deduplicate it. |
| 139 keys_ = keys; | 146 keys_ = keys; |
| 140 return Just(true); | 147 return Just(true); |
| 141 } | 148 } |
| 142 AddKeys(keys, is_for_in_ ? CONVERT_TO_ARRAY_INDEX : DO_NOT_CONVERT); | 149 AddKeys(keys, is_for_in_ ? CONVERT_TO_ARRAY_INDEX : DO_NOT_CONVERT); |
| 143 return Just(true); | 150 return Just(true); |
| 144 } | 151 } |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 176 return Nothing<bool>(); | 183 return Nothing<bool>(); |
| 177 } | 184 } |
| 178 if (!last_non_empty_prototype_.is_null() && | 185 if (!last_non_empty_prototype_.is_null() && |
| 179 *last_non_empty_prototype_ == *current) { | 186 *last_non_empty_prototype_ == *current) { |
| 180 break; | 187 break; |
| 181 } | 188 } |
| 182 } | 189 } |
| 183 return Just(true); | 190 return Just(true); |
| 184 } | 191 } |
| 185 | 192 |
| 193 bool KeyAccumulator::IsShadowed(Handle<Object> key) { | |
| 194 if (shadowed_keys_.is_null()) return false; | |
| 195 return shadowed_keys_->Has(isolate_, key); | |
| 196 } | |
| 197 | |
| 198 void KeyAccumulator::AddShadowKey(Object* key) { | |
| 199 if (mode_ == KeyCollectionMode::kOwnOnly) return; | |
| 200 AddShadowKey(handle(key, isolate_)); | |
| 201 } | |
| 202 void KeyAccumulator::AddShadowKey(Handle<Object> key) { | |
| 203 if (mode_ == KeyCollectionMode::kOwnOnly) return; | |
| 204 if (shadowed_keys_.is_null()) { | |
| 205 shadowed_keys_ = ObjectHashSet::New(isolate_, 16); | |
| 206 } | |
| 207 shadowed_keys_ = ObjectHashSet::Add(shadowed_keys_, key); | |
| 208 } | |
| 209 | |
| 186 namespace { | 210 namespace { |
| 187 | 211 |
| 188 void TrySettingEmptyEnumCache(JSReceiver* object) { | 212 void TrySettingEmptyEnumCache(JSReceiver* object) { |
| 189 Map* map = object->map(); | 213 Map* map = object->map(); |
| 190 DCHECK_EQ(kInvalidEnumCacheSentinel, map->EnumLength()); | 214 DCHECK_EQ(kInvalidEnumCacheSentinel, map->EnumLength()); |
| 191 if (!map->OnlyHasSimpleProperties()) return; | 215 if (!map->OnlyHasSimpleProperties()) return; |
| 192 if (map->IsJSProxyMap()) return; | 216 if (map->IsJSProxyMap()) return; |
| 193 if (map->NumberOfOwnDescriptors() > 0) { | 217 if (map->NumberOfOwnDescriptors() > 0) { |
| 194 int number_of_enumerable_own_properties = | 218 int number_of_enumerable_own_properties = |
| 195 map->NumberOfDescribedProperties(OWN_DESCRIPTORS, ENUMERABLE_STRINGS); | 219 map->NumberOfDescribedProperties(OWN_DESCRIPTORS, ENUMERABLE_STRINGS); |
| (...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 322 template <bool fast_properties> | 346 template <bool fast_properties> |
| 323 Handle<FixedArray> GetOwnKeysWithElements(Isolate* isolate, | 347 Handle<FixedArray> GetOwnKeysWithElements(Isolate* isolate, |
| 324 Handle<JSObject> object, | 348 Handle<JSObject> object, |
| 325 GetKeysConversion convert) { | 349 GetKeysConversion convert) { |
| 326 Handle<FixedArray> keys; | 350 Handle<FixedArray> keys; |
| 327 ElementsAccessor* accessor = object->GetElementsAccessor(); | 351 ElementsAccessor* accessor = object->GetElementsAccessor(); |
| 328 if (fast_properties) { | 352 if (fast_properties) { |
| 329 keys = GetFastEnumPropertyKeys(isolate, object); | 353 keys = GetFastEnumPropertyKeys(isolate, object); |
| 330 } else { | 354 } else { |
| 331 // TODO(cbruni): preallocate big enough array to also hold elements. | 355 // TODO(cbruni): preallocate big enough array to also hold elements. |
| 332 keys = KeyAccumulator::GetEnumPropertyKeys(isolate, object); | 356 keys = KeyAccumulator::GetOwnEnumPropertyKeys(isolate, object); |
| 333 } | 357 } |
| 334 Handle<FixedArray> result = | 358 Handle<FixedArray> result = |
| 335 accessor->PrependElementIndices(object, keys, convert, ONLY_ENUMERABLE); | 359 accessor->PrependElementIndices(object, keys, convert, ONLY_ENUMERABLE); |
| 336 | 360 |
| 337 if (FLAG_trace_for_in_enumerate) { | 361 if (FLAG_trace_for_in_enumerate) { |
| 338 PrintF("| strings=%d symbols=0 elements=%u || prototypes>=1 ||\n", | 362 PrintF("| strings=%d symbols=0 elements=%u || prototypes>=1 ||\n", |
| 339 keys->length(), result->length() - keys->length()); | 363 keys->length(), result->length() - keys->length()); |
| 340 } | 364 } |
| 341 return result; | 365 return result; |
| 342 } | 366 } |
| (...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 478 } | 502 } |
| 479 | 503 |
| 480 namespace { | 504 namespace { |
| 481 | 505 |
| 482 template <bool skip_symbols> | 506 template <bool skip_symbols> |
| 483 int CollectOwnPropertyNamesInternal(Handle<JSObject> object, | 507 int CollectOwnPropertyNamesInternal(Handle<JSObject> object, |
| 484 KeyAccumulator* keys, | 508 KeyAccumulator* keys, |
| 485 Handle<DescriptorArray> descs, | 509 Handle<DescriptorArray> descs, |
| 486 int start_index, int limit) { | 510 int start_index, int limit) { |
| 487 int first_skipped = -1; | 511 int first_skipped = -1; |
| 512 PropertyFilter filter = keys->filter(); | |
| 513 KeyCollectionMode mode = keys->mode(); | |
| 514 bool is_shadowing_key = false; | |
|
adamk
2016/06/27 19:19:33
This declaration seems like it'd be clearer inside
Camillo Bruni
2016/06/29 17:27:56
pushing it into the loop
| |
| 488 for (int i = start_index; i < limit; i++) { | 515 for (int i = start_index; i < limit; i++) { |
| 516 is_shadowing_key = false; | |
| 489 PropertyDetails details = descs->GetDetails(i); | 517 PropertyDetails details = descs->GetDetails(i); |
| 490 if ((details.attributes() & keys->filter()) != 0) continue; | 518 |
| 491 if (keys->filter() & ONLY_ALL_CAN_READ) { | 519 if ((details.attributes() & filter) != 0) { |
| 520 if (mode == KeyCollectionMode::kIncludePrototypes) { | |
| 521 is_shadowing_key = true; | |
| 522 } else { | |
| 523 continue; | |
| 524 } | |
| 525 } | |
| 526 | |
| 527 if (filter & ONLY_ALL_CAN_READ) { | |
| 492 if (details.kind() != kAccessor) continue; | 528 if (details.kind() != kAccessor) continue; |
| 493 Object* accessors = descs->GetValue(i); | 529 Object* accessors = descs->GetValue(i); |
| 494 if (!accessors->IsAccessorInfo()) continue; | 530 if (!accessors->IsAccessorInfo()) continue; |
| 495 if (!AccessorInfo::cast(accessors)->all_can_read()) continue; | 531 if (!AccessorInfo::cast(accessors)->all_can_read()) continue; |
| 496 } | 532 } |
| 533 | |
| 497 Name* key = descs->GetKey(i); | 534 Name* key = descs->GetKey(i); |
| 498 if (skip_symbols == key->IsSymbol()) { | 535 if (skip_symbols == key->IsSymbol()) { |
| 499 if (first_skipped == -1) first_skipped = i; | 536 if (first_skipped == -1) first_skipped = i; |
| 500 continue; | 537 continue; |
| 501 } | 538 } |
| 502 if (key->FilterKey(keys->filter())) continue; | 539 if (key->FilterKey(keys->filter())) continue; |
| 503 keys->AddKey(key, DO_NOT_CONVERT); | 540 |
| 541 if (is_shadowing_key) { | |
| 542 keys->AddShadowKey(key); | |
| 543 } else { | |
| 544 keys->AddKey(key, DO_NOT_CONVERT); | |
| 545 } | |
| 504 } | 546 } |
| 505 return first_skipped; | 547 return first_skipped; |
| 506 } | 548 } |
| 507 | 549 |
| 550 template <class T> | |
| 551 Handle<FixedArray> GetOwnEnumPropertyDictionaryKeys(Isolate* isolate, | |
| 552 KeyCollectionMode mode, | |
| 553 KeyAccumulator* accumulator, | |
| 554 Handle<JSObject> object, | |
| 555 T* raw_dictionary) { | |
| 556 Handle<T> dictionary(raw_dictionary, isolate); | |
| 557 int length = dictionary->NumberOfEnumElements(); | |
| 558 if (length == 0) { | |
| 559 return isolate->factory()->empty_fixed_array(); | |
| 560 } | |
| 561 Handle<FixedArray> storage = isolate->factory()->NewFixedArray(length); | |
| 562 T::CopyEnumKeysTo(dictionary, storage, mode, accumulator); | |
| 563 return storage; | |
| 564 } | |
| 508 } // namespace | 565 } // namespace |
| 509 | 566 |
| 510 Maybe<bool> KeyAccumulator::CollectOwnPropertyNames(Handle<JSReceiver> receiver, | 567 Maybe<bool> KeyAccumulator::CollectOwnPropertyNames(Handle<JSReceiver> receiver, |
| 511 Handle<JSObject> object) { | 568 Handle<JSObject> object) { |
| 512 if (filter_ == ENUMERABLE_STRINGS) { | 569 if (filter_ == ENUMERABLE_STRINGS) { |
| 513 Handle<FixedArray> enum_keys = | 570 Handle<FixedArray> enum_keys; |
| 514 KeyAccumulator::GetEnumPropertyKeys(isolate_, object); | 571 if (object->HasFastProperties()) { |
| 572 enum_keys = KeyAccumulator::GetOwnEnumPropertyKeys(isolate_, object); | |
| 573 // If the number of properties equals the length of enumerable properties | |
| 574 // we do not have to filter out non-enumerable ones | |
| 575 Map* map = object->map(); | |
| 576 int nof_descriptors = map->NumberOfOwnDescriptors(); | |
| 577 if (enum_keys->length() != nof_descriptors) { | |
| 578 Handle<DescriptorArray> descs = | |
| 579 Handle<DescriptorArray>(map->instance_descriptors(), isolate_); | |
| 580 for (int i = 0; i < nof_descriptors; i++) { | |
| 581 PropertyDetails details = descs->GetDetails(i); | |
| 582 if (!details.IsDontEnum()) continue; | |
| 583 Object* key = descs->GetKey(i); | |
| 584 this->AddShadowKey(key); | |
| 585 } | |
| 586 } | |
| 587 } else if (object->IsJSGlobalObject()) { | |
| 588 enum_keys = GetOwnEnumPropertyDictionaryKeys( | |
| 589 isolate_, mode_, this, object, object->global_dictionary()); | |
| 590 } else { | |
| 591 enum_keys = GetOwnEnumPropertyDictionaryKeys( | |
| 592 isolate_, mode_, this, object, object->property_dictionary()); | |
| 593 } | |
| 515 AddKeys(enum_keys, DO_NOT_CONVERT); | 594 AddKeys(enum_keys, DO_NOT_CONVERT); |
| 516 } else { | 595 } else { |
| 517 if (object->HasFastProperties()) { | 596 if (object->HasFastProperties()) { |
| 518 int limit = object->map()->NumberOfOwnDescriptors(); | 597 int limit = object->map()->NumberOfOwnDescriptors(); |
| 519 Handle<DescriptorArray> descs(object->map()->instance_descriptors(), | 598 Handle<DescriptorArray> descs(object->map()->instance_descriptors(), |
| 520 isolate_); | 599 isolate_); |
| 521 // First collect the strings, | 600 // First collect the strings, |
| 522 int first_symbol = | 601 int first_symbol = |
| 523 CollectOwnPropertyNamesInternal<true>(object, this, descs, 0, limit); | 602 CollectOwnPropertyNamesInternal<true>(object, this, descs, 0, limit); |
| 524 // then the symbols. | 603 // then the symbols. |
| 525 if (first_symbol != -1) { | 604 if (first_symbol != -1) { |
| 526 CollectOwnPropertyNamesInternal<false>(object, this, descs, | 605 CollectOwnPropertyNamesInternal<false>(object, this, descs, |
| 527 first_symbol, limit); | 606 first_symbol, limit); |
| 528 } | 607 } |
| 529 } else if (object->IsJSGlobalObject()) { | 608 } else if (object->IsJSGlobalObject()) { |
| 530 GlobalDictionary::CollectKeysTo( | 609 GlobalDictionary::CollectKeysTo( |
| 531 handle(object->global_dictionary(), isolate_), this, filter_); | 610 handle(object->global_dictionary(), isolate_), this); |
| 532 } else { | 611 } else { |
| 533 NameDictionary::CollectKeysTo( | 612 NameDictionary::CollectKeysTo( |
| 534 handle(object->property_dictionary(), isolate_), this, filter_); | 613 handle(object->property_dictionary(), isolate_), this); |
| 535 } | 614 } |
| 536 } | 615 } |
| 537 // Add the property keys from the interceptor. | 616 // Add the property keys from the interceptor. |
| 538 return CollectInterceptorKeys<v8::GenericNamedPropertyEnumeratorCallback, | 617 return CollectInterceptorKeys<v8::GenericNamedPropertyEnumeratorCallback, |
| 539 kNamed>(receiver, object, this); | 618 kNamed>(receiver, object, this); |
| 540 } | 619 } |
| 541 | 620 |
| 542 // Returns |true| on success, |false| if prototype walking should be stopped, | 621 // Returns |true| on success, |false| if prototype walking should be stopped, |
| 543 // |nothing| if an exception was thrown. | 622 // |nothing| if an exception was thrown. |
| 544 Maybe<bool> KeyAccumulator::CollectOwnKeys(Handle<JSReceiver> receiver, | 623 Maybe<bool> KeyAccumulator::CollectOwnKeys(Handle<JSReceiver> receiver, |
| 545 Handle<JSObject> object) { | 624 Handle<JSObject> object) { |
| 546 // Check access rights if required. | 625 // Check access rights if required. |
| 547 if (object->IsAccessCheckNeeded() && | 626 if (object->IsAccessCheckNeeded() && |
| 548 !isolate_->MayAccess(handle(isolate_->context()), object)) { | 627 !isolate_->MayAccess(handle(isolate_->context()), object)) { |
| 549 // The cross-origin spec says that [[Enumerate]] shall return an empty | 628 // The cross-origin spec says that [[Enumerate]] shall return an empty |
| 550 // iterator when it doesn't have access... | 629 // iterator when it doesn't have access... |
| 551 if (mode_ == KeyCollectionMode::kIncludePrototypes) { | 630 if (mode_ == KeyCollectionMode::kIncludePrototypes) { |
| 552 return Just(false); | 631 return Just(false); |
| 553 } | 632 } |
| 554 // ...whereas [[OwnPropertyKeys]] shall return whitelisted properties. | 633 // ...whereas [[OwnPropertyKeys]] shall return whitelisted properties. |
| 555 DCHECK(KeyCollectionMode::kOwnOnly == mode_); | 634 DCHECK(KeyCollectionMode::kOwnOnly == mode_); |
| 556 filter_ = static_cast<PropertyFilter>(filter_ | ONLY_ALL_CAN_READ); | 635 filter_ = static_cast<PropertyFilter>(filter_ | ONLY_ALL_CAN_READ); |
| 557 } | 636 } |
| 558 MAYBE_RETURN(CollectOwnElementIndices(receiver, object), Nothing<bool>()); | 637 MAYBE_RETURN(CollectOwnElementIndices(receiver, object), Nothing<bool>()); |
| 559 MAYBE_RETURN(CollectOwnPropertyNames(receiver, object), Nothing<bool>()); | 638 MAYBE_RETURN(CollectOwnPropertyNames(receiver, object), Nothing<bool>()); |
| 560 return Just(true); | 639 return Just(true); |
| 561 } | 640 } |
| 562 | 641 |
| 563 // static | 642 // static |
| 564 Handle<FixedArray> KeyAccumulator::GetEnumPropertyKeys( | 643 Handle<FixedArray> KeyAccumulator::GetOwnEnumPropertyKeys( |
| 565 Isolate* isolate, Handle<JSObject> object) { | 644 Isolate* isolate, Handle<JSObject> object) { |
| 566 if (object->HasFastProperties()) { | 645 if (object->HasFastProperties()) { |
| 567 return GetFastEnumPropertyKeys(isolate, object); | 646 return GetFastEnumPropertyKeys(isolate, object); |
| 568 } else if (object->IsJSGlobalObject()) { | 647 } else if (object->IsJSGlobalObject()) { |
| 569 Handle<GlobalDictionary> dictionary(object->global_dictionary(), isolate); | 648 return GetOwnEnumPropertyDictionaryKeys( |
| 570 int length = dictionary->NumberOfEnumElements(); | 649 isolate, KeyCollectionMode::kOwnOnly, nullptr, object, |
| 571 if (length == 0) { | 650 object->global_dictionary()); |
| 572 return isolate->factory()->empty_fixed_array(); | |
| 573 } | |
| 574 Handle<FixedArray> storage = isolate->factory()->NewFixedArray(length); | |
| 575 dictionary->CopyEnumKeysTo(*storage); | |
| 576 return storage; | |
| 577 } else { | 651 } else { |
| 578 Handle<NameDictionary> dictionary(object->property_dictionary(), isolate); | 652 return GetOwnEnumPropertyDictionaryKeys( |
| 579 int length = dictionary->NumberOfEnumElements(); | 653 isolate, KeyCollectionMode::kOwnOnly, nullptr, object, |
| 580 if (length == 0) { | 654 object->property_dictionary()); |
| 581 return isolate->factory()->empty_fixed_array(); | |
| 582 } | |
| 583 Handle<FixedArray> storage = isolate->factory()->NewFixedArray(length); | |
| 584 dictionary->CopyEnumKeysTo(*storage); | |
| 585 return storage; | |
| 586 } | 655 } |
| 587 } | 656 } |
| 588 | 657 |
| 589 // ES6 9.5.12 | 658 // ES6 9.5.12 |
| 590 // Returns |true| on success, |nothing| in case of exception. | 659 // Returns |true| on success, |nothing| in case of exception. |
| 591 Maybe<bool> KeyAccumulator::CollectOwnJSProxyKeys(Handle<JSReceiver> receiver, | 660 Maybe<bool> KeyAccumulator::CollectOwnJSProxyKeys(Handle<JSReceiver> receiver, |
| 592 Handle<JSProxy> proxy) { | 661 Handle<JSProxy> proxy) { |
| 593 STACK_CHECK(isolate_, Nothing<bool>()); | 662 STACK_CHECK(isolate_, Nothing<bool>()); |
| 594 // 1. Let handler be the value of the [[ProxyHandler]] internal slot of O. | 663 // 1. Let handler be the value of the [[ProxyHandler]] internal slot of O. |
| 595 Handle<Object> handler(proxy->handler(), isolate_); | 664 Handle<Object> handler(proxy->handler(), isolate_); |
| (...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 741 isolate_, keys, JSReceiver::OwnPropertyKeys(target), Nothing<bool>()); | 810 isolate_, keys, JSReceiver::OwnPropertyKeys(target), Nothing<bool>()); |
| 742 bool prev_filter_proxy_keys_ = filter_proxy_keys_; | 811 bool prev_filter_proxy_keys_ = filter_proxy_keys_; |
| 743 filter_proxy_keys_ = false; | 812 filter_proxy_keys_ = false; |
| 744 Maybe<bool> result = AddKeysFromJSProxy(proxy, keys); | 813 Maybe<bool> result = AddKeysFromJSProxy(proxy, keys); |
| 745 filter_proxy_keys_ = prev_filter_proxy_keys_; | 814 filter_proxy_keys_ = prev_filter_proxy_keys_; |
| 746 return result; | 815 return result; |
| 747 } | 816 } |
| 748 | 817 |
| 749 } // namespace internal | 818 } // namespace internal |
| 750 } // namespace v8 | 819 } // namespace v8 |
| OLD | NEW |