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 |