| 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 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 106 return AddKey(handle(key, isolate_), convert); | 106 return AddKey(handle(key, isolate_), convert); |
| 107 } | 107 } |
| 108 | 108 |
| 109 bool KeyAccumulator::AddKey(Handle<Object> key, AddKeyConversion convert) { | 109 bool KeyAccumulator::AddKey(Handle<Object> key, AddKeyConversion convert) { |
| 110 if (key->IsSymbol()) { | 110 if (key->IsSymbol()) { |
| 111 if (filter_ & SKIP_SYMBOLS) return false; | 111 if (filter_ & SKIP_SYMBOLS) return false; |
| 112 if (Handle<Symbol>::cast(key)->is_private()) return false; | 112 if (Handle<Symbol>::cast(key)->is_private()) return false; |
| 113 return AddSymbolKey(key); | 113 return AddSymbolKey(key); |
| 114 } | 114 } |
| 115 if (filter_ & SKIP_STRINGS) return false; | 115 if (filter_ & SKIP_STRINGS) return false; |
| 116 // Make sure we do not add keys to a proxy-level (see AddKeysFromProxy). | 116 // Make sure we do not add keys to a proxy-level (see AddKeysFromJSProxy). |
| 117 DCHECK_LE(0, level_string_length_); | 117 DCHECK_LE(0, level_string_length_); |
| 118 // In some cases (e.g. proxies) we might get in String-converted ints which | 118 // In some cases (e.g. proxies) we might get in String-converted ints which |
| 119 // should be added to the elements list instead of the properties. For | 119 // should be added to the elements list instead of the properties. For |
| 120 // proxies we have to convert as well but also respect the original order. | 120 // proxies we have to convert as well but also respect the original order. |
| 121 // Therefore we add a converted key to both sides | 121 // Therefore we add a converted key to both sides |
| 122 if (convert == CONVERT_TO_ARRAY_INDEX || convert == PROXY_MAGIC) { | 122 if (convert == CONVERT_TO_ARRAY_INDEX || convert == PROXY_MAGIC) { |
| 123 uint32_t index = 0; | 123 uint32_t index = 0; |
| 124 int prev_length = length_; | 124 int prev_length = length_; |
| 125 int prev_proto = level_string_length_; | 125 int prev_proto = level_string_length_; |
| 126 if ((key->IsString() && Handle<String>::cast(key)->AsArrayIndex(&index)) || | 126 if ((key->IsString() && Handle<String>::cast(key)->AsArrayIndex(&index)) || |
| (...skipping 11 matching lines...) Expand all Loading... |
| 138 level_string_length_ = prev_proto; | 138 level_string_length_ = prev_proto; |
| 139 } | 139 } |
| 140 } | 140 } |
| 141 } | 141 } |
| 142 return AddStringKey(key, convert); | 142 return AddStringKey(key, convert); |
| 143 } | 143 } |
| 144 | 144 |
| 145 bool KeyAccumulator::AddKey(uint32_t key) { return AddIntegerKey(key); } | 145 bool KeyAccumulator::AddKey(uint32_t key) { return AddIntegerKey(key); } |
| 146 | 146 |
| 147 bool KeyAccumulator::AddIntegerKey(uint32_t key) { | 147 bool KeyAccumulator::AddIntegerKey(uint32_t key) { |
| 148 // Make sure we do not add keys to a proxy-level (see AddKeysFromProxy). | 148 // Make sure we do not add keys to a proxy-level (see AddKeysFromJSProxy). |
| 149 // We mark proxy-levels with a negative length | 149 // We mark proxy-levels with a negative length |
| 150 DCHECK_LE(0, level_string_length_); | 150 DCHECK_LE(0, level_string_length_); |
| 151 // Binary search over all but the last level. The last one might not be | 151 // Binary search over all but the last level. The last one might not be |
| 152 // sorted yet. | 152 // sorted yet. |
| 153 for (size_t i = 1; i < elements_.size(); i++) { | 153 for (size_t i = 1; i < elements_.size(); i++) { |
| 154 if (AccumulatorHasKey(elements_[i - 1], key)) return false; | 154 if (AccumulatorHasKey(elements_[i - 1], key)) return false; |
| 155 } | 155 } |
| 156 elements_.back()->push_back(key); | 156 elements_.back()->push_back(key); |
| 157 length_++; | 157 length_++; |
| 158 return true; | 158 return true; |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 204 } | 204 } |
| 205 } | 205 } |
| 206 | 206 |
| 207 void KeyAccumulator::AddKeys(Handle<JSObject> array_like, | 207 void KeyAccumulator::AddKeys(Handle<JSObject> array_like, |
| 208 AddKeyConversion convert) { | 208 AddKeyConversion convert) { |
| 209 DCHECK(array_like->IsJSArray() || array_like->HasSloppyArgumentsElements()); | 209 DCHECK(array_like->IsJSArray() || array_like->HasSloppyArgumentsElements()); |
| 210 ElementsAccessor* accessor = array_like->GetElementsAccessor(); | 210 ElementsAccessor* accessor = array_like->GetElementsAccessor(); |
| 211 accessor->AddElementsToKeyAccumulator(array_like, this, convert); | 211 accessor->AddElementsToKeyAccumulator(array_like, this, convert); |
| 212 } | 212 } |
| 213 | 213 |
| 214 void KeyAccumulator::AddKeysFromProxy(Handle<JSObject> array_like) { | |
| 215 // Proxies define a complete list of keys with no distinction of | |
| 216 // elements and properties, which breaks the normal assumption for the | |
| 217 // KeyAccumulator. | |
| 218 AddKeys(array_like, PROXY_MAGIC); | |
| 219 // Invert the current length to indicate a present proxy, so we can ignore | |
| 220 // element keys for this level. Otherwise we would not fully respect the order | |
| 221 // given by the proxy. | |
| 222 level_string_length_ = -level_string_length_; | |
| 223 } | |
| 224 | |
| 225 MaybeHandle<FixedArray> FilterProxyKeys(Isolate* isolate, Handle<JSProxy> owner, | 214 MaybeHandle<FixedArray> FilterProxyKeys(Isolate* isolate, Handle<JSProxy> owner, |
| 226 Handle<FixedArray> keys, | 215 Handle<FixedArray> keys, |
| 227 PropertyFilter filter) { | 216 PropertyFilter filter) { |
| 228 if (filter == ALL_PROPERTIES) { | 217 if (filter == ALL_PROPERTIES) { |
| 229 // Nothing to do. | 218 // Nothing to do. |
| 230 return keys; | 219 return keys; |
| 231 } | 220 } |
| 232 int store_position = 0; | 221 int store_position = 0; |
| 233 for (int i = 0; i < keys->length(); ++i) { | 222 for (int i = 0; i < keys->length(); ++i) { |
| 234 Handle<Name> key(Name::cast(keys->get(i)), isolate); | 223 Handle<Name> key(Name::cast(keys->get(i)), isolate); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 245 keys->set(store_position, *key); | 234 keys->set(store_position, *key); |
| 246 } | 235 } |
| 247 store_position++; | 236 store_position++; |
| 248 } | 237 } |
| 249 if (store_position == 0) return isolate->factory()->empty_fixed_array(); | 238 if (store_position == 0) return isolate->factory()->empty_fixed_array(); |
| 250 keys->Shrink(store_position); | 239 keys->Shrink(store_position); |
| 251 return keys; | 240 return keys; |
| 252 } | 241 } |
| 253 | 242 |
| 254 // Returns "nothing" in case of exception, "true" on success. | 243 // Returns "nothing" in case of exception, "true" on success. |
| 255 Maybe<bool> KeyAccumulator::AddKeysFromProxy(Handle<JSProxy> proxy, | 244 Maybe<bool> KeyAccumulator::AddKeysFromJSProxy(Handle<JSProxy> proxy, |
| 256 Handle<FixedArray> keys) { | 245 Handle<FixedArray> keys) { |
| 257 if (filter_proxy_keys_) { | 246 if (filter_proxy_keys_) { |
| 258 ASSIGN_RETURN_ON_EXCEPTION_VALUE( | 247 ASSIGN_RETURN_ON_EXCEPTION_VALUE( |
| 259 isolate_, keys, FilterProxyKeys(isolate_, proxy, keys, filter_), | 248 isolate_, keys, FilterProxyKeys(isolate_, proxy, keys, filter_), |
| 260 Nothing<bool>()); | 249 Nothing<bool>()); |
| 261 } | 250 } |
| 262 // Proxies define a complete list of keys with no distinction of | 251 // Proxies define a complete list of keys with no distinction of |
| 263 // elements and properties, which breaks the normal assumption for the | 252 // elements and properties, which breaks the normal assumption for the |
| 264 // KeyAccumulator. | 253 // KeyAccumulator. |
| 265 if (type_ == OWN_ONLY) { | 254 if (type_ == OWN_ONLY) { |
| 266 ownProxyKeys_ = keys; | 255 ownProxyKeys_ = keys; |
| (...skipping 374 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 641 PropertyDetails details = descs->GetDetails(i); | 630 PropertyDetails details = descs->GetDetails(i); |
| 642 if ((details.attributes() & filter_) != 0) continue; | 631 if ((details.attributes() & filter_) != 0) continue; |
| 643 if (filter_ & ONLY_ALL_CAN_READ) { | 632 if (filter_ & ONLY_ALL_CAN_READ) { |
| 644 if (details.kind() != kAccessor) continue; | 633 if (details.kind() != kAccessor) continue; |
| 645 Object* accessors = descs->GetValue(i); | 634 Object* accessors = descs->GetValue(i); |
| 646 if (!accessors->IsAccessorInfo()) continue; | 635 if (!accessors->IsAccessorInfo()) continue; |
| 647 if (!AccessorInfo::cast(accessors)->all_can_read()) continue; | 636 if (!AccessorInfo::cast(accessors)->all_can_read()) continue; |
| 648 } | 637 } |
| 649 Name* key = descs->GetKey(i); | 638 Name* key = descs->GetKey(i); |
| 650 if (key->FilterKey(filter_)) continue; | 639 if (key->FilterKey(filter_)) continue; |
| 651 this->AddKey(key, DO_NOT_CONVERT); | 640 AddKey(key, DO_NOT_CONVERT); |
| 652 } | 641 } |
| 653 } else if (object->IsJSGlobalObject()) { | 642 } else if (object->IsJSGlobalObject()) { |
| 654 GlobalDictionary::CollectKeysTo( | 643 GlobalDictionary::CollectKeysTo( |
| 655 handle(object->global_dictionary(), isolate_), this, filter_); | 644 handle(object->global_dictionary(), isolate_), this, filter_); |
| 656 } else { | 645 } else { |
| 657 NameDictionary::CollectKeysTo( | 646 NameDictionary::CollectKeysTo( |
| 658 handle(object->property_dictionary(), isolate_), this, filter_); | 647 handle(object->property_dictionary(), isolate_), this, filter_); |
| 659 } | 648 } |
| 660 } | 649 } |
| 661 | 650 |
| 662 // Returns |true| on success, |false| if prototype walking should be stopped, | 651 // Returns |true| on success, |false| if prototype walking should be stopped, |
| 663 // |nothing| if an exception was thrown. | 652 // |nothing| if an exception was thrown. |
| 664 Maybe<bool> KeyAccumulator::CollectOwnKeys(Handle<JSReceiver> receiver, | 653 Maybe<bool> KeyAccumulator::CollectOwnKeys(Handle<JSReceiver> receiver, |
| 665 Handle<JSObject> object) { | 654 Handle<JSObject> object) { |
| 666 this->NextPrototype(); | 655 NextPrototype(); |
| 667 // Check access rights if required. | 656 // Check access rights if required. |
| 668 if (object->IsAccessCheckNeeded() && | 657 if (object->IsAccessCheckNeeded() && |
| 669 !isolate_->MayAccess(handle(isolate_->context()), object)) { | 658 !isolate_->MayAccess(handle(isolate_->context()), object)) { |
| 670 // The cross-origin spec says that [[Enumerate]] shall return an empty | 659 // The cross-origin spec says that [[Enumerate]] shall return an empty |
| 671 // iterator when it doesn't have access... | 660 // iterator when it doesn't have access... |
| 672 if (type_ == INCLUDE_PROTOS) { | 661 if (type_ == INCLUDE_PROTOS) { |
| 673 return Just(false); | 662 return Just(false); |
| 674 } | 663 } |
| 675 // ...whereas [[OwnPropertyKeys]] shall return whitelisted properties. | 664 // ...whereas [[OwnPropertyKeys]] shall return whitelisted properties. |
| 676 DCHECK_EQ(OWN_ONLY, type_); | 665 DCHECK_EQ(OWN_ONLY, type_); |
| 677 filter_ = static_cast<PropertyFilter>(filter_ | ONLY_ALL_CAN_READ); | 666 filter_ = static_cast<PropertyFilter>(filter_ | ONLY_ALL_CAN_READ); |
| 678 } | 667 } |
| 679 | 668 |
| 680 this->CollectOwnElementIndices(object); | 669 CollectOwnElementIndices(object); |
| 681 | 670 |
| 682 // Add the element keys from the interceptor. | 671 // Add the element keys from the interceptor. |
| 683 Maybe<bool> success = | 672 Maybe<bool> success = |
| 684 GetKeysFromInterceptor<v8::IndexedPropertyEnumeratorCallback, kIndexed>( | 673 GetKeysFromInterceptor<v8::IndexedPropertyEnumeratorCallback, kIndexed>( |
| 685 receiver, object, this); | 674 receiver, object, this); |
| 686 MAYBE_RETURN(success, Nothing<bool>()); | 675 MAYBE_RETURN(success, Nothing<bool>()); |
| 687 | 676 |
| 688 if (filter_ == ENUMERABLE_STRINGS) { | 677 if (filter_ == ENUMERABLE_STRINGS) { |
| 689 Handle<FixedArray> enum_keys = | 678 Handle<FixedArray> enum_keys = |
| 690 KeyAccumulator::GetEnumPropertyKeys(isolate_, object); | 679 KeyAccumulator::GetEnumPropertyKeys(isolate_, object); |
| 691 this->AddKeys(enum_keys, DO_NOT_CONVERT); | 680 AddKeys(enum_keys, DO_NOT_CONVERT); |
| 692 } else { | 681 } else { |
| 693 this->CollectOwnPropertyNames(object); | 682 CollectOwnPropertyNames(object); |
| 694 } | 683 } |
| 695 | 684 |
| 696 // Add the property keys from the interceptor. | 685 // Add the property keys from the interceptor. |
| 697 success = GetKeysFromInterceptor<v8::GenericNamedPropertyEnumeratorCallback, | 686 success = GetKeysFromInterceptor<v8::GenericNamedPropertyEnumeratorCallback, |
| 698 kNamed>(receiver, object, this); | 687 kNamed>(receiver, object, this); |
| 699 MAYBE_RETURN(success, Nothing<bool>()); | 688 MAYBE_RETURN(success, Nothing<bool>()); |
| 700 return Just(true); | 689 return Just(true); |
| 701 } | 690 } |
| 702 | 691 |
| 703 // static | 692 // static |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 744 Handle<JSReceiver> target(proxy->target(), isolate_); | 733 Handle<JSReceiver> target(proxy->target(), isolate_); |
| 745 // 5. Let trap be ? GetMethod(handler, "ownKeys"). | 734 // 5. Let trap be ? GetMethod(handler, "ownKeys"). |
| 746 Handle<Object> trap; | 735 Handle<Object> trap; |
| 747 ASSIGN_RETURN_ON_EXCEPTION_VALUE( | 736 ASSIGN_RETURN_ON_EXCEPTION_VALUE( |
| 748 isolate_, trap, Object::GetMethod(Handle<JSReceiver>::cast(handler), | 737 isolate_, trap, Object::GetMethod(Handle<JSReceiver>::cast(handler), |
| 749 isolate_->factory()->ownKeys_string()), | 738 isolate_->factory()->ownKeys_string()), |
| 750 Nothing<bool>()); | 739 Nothing<bool>()); |
| 751 // 6. If trap is undefined, then | 740 // 6. If trap is undefined, then |
| 752 if (trap->IsUndefined()) { | 741 if (trap->IsUndefined()) { |
| 753 // 6a. Return target.[[OwnPropertyKeys]](). | 742 // 6a. Return target.[[OwnPropertyKeys]](). |
| 754 KeyCollectionType previous_type = type_; | 743 return CollectOwnJSProxyTargetKeys(proxy, target); |
| 755 type_ = OWN_ONLY; | |
| 756 Maybe<bool> result = this->CollectKeys(receiver, target); | |
| 757 type_ = previous_type; | |
| 758 return result; | |
| 759 } | 744 } |
| 760 // 7. Let trapResultArray be Call(trap, handler, «target»). | 745 // 7. Let trapResultArray be Call(trap, handler, «target»). |
| 761 Handle<Object> trap_result_array; | 746 Handle<Object> trap_result_array; |
| 762 Handle<Object> args[] = {target}; | 747 Handle<Object> args[] = {target}; |
| 763 ASSIGN_RETURN_ON_EXCEPTION_VALUE( | 748 ASSIGN_RETURN_ON_EXCEPTION_VALUE( |
| 764 isolate_, trap_result_array, | 749 isolate_, trap_result_array, |
| 765 Execution::Call(isolate_, trap, handler, arraysize(args), args), | 750 Execution::Call(isolate_, trap, handler, arraysize(args), args), |
| 766 Nothing<bool>()); | 751 Nothing<bool>()); |
| 767 // 8. Let trapResult be ? CreateListFromArrayLike(trapResultArray, | 752 // 8. Let trapResult be ? CreateListFromArrayLike(trapResultArray, |
| 768 // «String, Symbol»). | 753 // «String, Symbol»). |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 803 target_keys->get(i)); | 788 target_keys->get(i)); |
| 804 nonconfigurable_keys_length++; | 789 nonconfigurable_keys_length++; |
| 805 // The key was moved, null it out in the original list. | 790 // The key was moved, null it out in the original list. |
| 806 target_keys->set(i, Smi::FromInt(0)); | 791 target_keys->set(i, Smi::FromInt(0)); |
| 807 } else { | 792 } else { |
| 808 // 14c. Else, | 793 // 14c. Else, |
| 809 // 14c i. Append key as an element of targetConfigurableKeys. | 794 // 14c i. Append key as an element of targetConfigurableKeys. |
| 810 // (No-op, just keep it in |target_keys|.) | 795 // (No-op, just keep it in |target_keys|.) |
| 811 } | 796 } |
| 812 } | 797 } |
| 813 this->NextPrototype(); // Prepare for accumulating keys. | 798 NextPrototype(); // Prepare for accumulating keys. |
| 814 // 15. If extensibleTarget is true and targetNonconfigurableKeys is empty, | 799 // 15. If extensibleTarget is true and targetNonconfigurableKeys is empty, |
| 815 // then: | 800 // then: |
| 816 if (extensible_target && nonconfigurable_keys_length == 0) { | 801 if (extensible_target && nonconfigurable_keys_length == 0) { |
| 817 // 15a. Return trapResult. | 802 // 15a. Return trapResult. |
| 818 return this->AddKeysFromProxy(proxy, trap_result); | 803 return AddKeysFromJSProxy(proxy, trap_result); |
| 819 } | 804 } |
| 820 // 16. Let uncheckedResultKeys be a new List which is a copy of trapResult. | 805 // 16. Let uncheckedResultKeys be a new List which is a copy of trapResult. |
| 821 Zone set_zone(isolate_->allocator()); | 806 Zone set_zone(isolate_->allocator()); |
| 822 const int kPresent = 1; | 807 const int kPresent = 1; |
| 823 const int kGone = 0; | 808 const int kGone = 0; |
| 824 IdentityMap<int> unchecked_result_keys(isolate_->heap(), &set_zone); | 809 IdentityMap<int> unchecked_result_keys(isolate_->heap(), &set_zone); |
| 825 int unchecked_result_keys_size = 0; | 810 int unchecked_result_keys_size = 0; |
| 826 for (int i = 0; i < trap_result->length(); ++i) { | 811 for (int i = 0; i < trap_result->length(); ++i) { |
| 827 DCHECK(trap_result->get(i)->IsUniqueName()); | 812 DCHECK(trap_result->get(i)->IsUniqueName()); |
| 828 Object* key = trap_result->get(i); | 813 Object* key = trap_result->get(i); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 842 isolate_->Throw(*isolate_->factory()->NewTypeError( | 827 isolate_->Throw(*isolate_->factory()->NewTypeError( |
| 843 MessageTemplate::kProxyOwnKeysMissing, handle(key, isolate_))); | 828 MessageTemplate::kProxyOwnKeysMissing, handle(key, isolate_))); |
| 844 return Nothing<bool>(); | 829 return Nothing<bool>(); |
| 845 } | 830 } |
| 846 // 17b. Remove key from uncheckedResultKeys. | 831 // 17b. Remove key from uncheckedResultKeys. |
| 847 *found = kGone; | 832 *found = kGone; |
| 848 unchecked_result_keys_size--; | 833 unchecked_result_keys_size--; |
| 849 } | 834 } |
| 850 // 18. If extensibleTarget is true, return trapResult. | 835 // 18. If extensibleTarget is true, return trapResult. |
| 851 if (extensible_target) { | 836 if (extensible_target) { |
| 852 return this->AddKeysFromProxy(proxy, trap_result); | 837 return AddKeysFromJSProxy(proxy, trap_result); |
| 853 } | 838 } |
| 854 // 19. Repeat, for each key that is an element of targetConfigurableKeys: | 839 // 19. Repeat, for each key that is an element of targetConfigurableKeys: |
| 855 for (int i = 0; i < target_configurable_keys->length(); ++i) { | 840 for (int i = 0; i < target_configurable_keys->length(); ++i) { |
| 856 Object* key = target_configurable_keys->get(i); | 841 Object* key = target_configurable_keys->get(i); |
| 857 if (key->IsSmi()) continue; // Zapped entry, was nonconfigurable. | 842 if (key->IsSmi()) continue; // Zapped entry, was nonconfigurable. |
| 858 // 19a. If key is not an element of uncheckedResultKeys, throw a | 843 // 19a. If key is not an element of uncheckedResultKeys, throw a |
| 859 // TypeError exception. | 844 // TypeError exception. |
| 860 int* found = unchecked_result_keys.Find(key); | 845 int* found = unchecked_result_keys.Find(key); |
| 861 if (found == nullptr || *found == kGone) { | 846 if (found == nullptr || *found == kGone) { |
| 862 isolate_->Throw(*isolate_->factory()->NewTypeError( | 847 isolate_->Throw(*isolate_->factory()->NewTypeError( |
| 863 MessageTemplate::kProxyOwnKeysMissing, handle(key, isolate_))); | 848 MessageTemplate::kProxyOwnKeysMissing, handle(key, isolate_))); |
| 864 return Nothing<bool>(); | 849 return Nothing<bool>(); |
| 865 } | 850 } |
| 866 // 19b. Remove key from uncheckedResultKeys. | 851 // 19b. Remove key from uncheckedResultKeys. |
| 867 *found = kGone; | 852 *found = kGone; |
| 868 unchecked_result_keys_size--; | 853 unchecked_result_keys_size--; |
| 869 } | 854 } |
| 870 // 20. If uncheckedResultKeys is not empty, throw a TypeError exception. | 855 // 20. If uncheckedResultKeys is not empty, throw a TypeError exception. |
| 871 if (unchecked_result_keys_size != 0) { | 856 if (unchecked_result_keys_size != 0) { |
| 872 DCHECK_GT(unchecked_result_keys_size, 0); | 857 DCHECK_GT(unchecked_result_keys_size, 0); |
| 873 isolate_->Throw(*isolate_->factory()->NewTypeError( | 858 isolate_->Throw(*isolate_->factory()->NewTypeError( |
| 874 MessageTemplate::kProxyOwnKeysNonExtensible)); | 859 MessageTemplate::kProxyOwnKeysNonExtensible)); |
| 875 return Nothing<bool>(); | 860 return Nothing<bool>(); |
| 876 } | 861 } |
| 877 // 21. Return trapResult. | 862 // 21. Return trapResult. |
| 878 return this->AddKeysFromProxy(proxy, trap_result); | 863 return AddKeysFromJSProxy(proxy, trap_result); |
| 864 } |
| 865 |
| 866 Maybe<bool> KeyAccumulator::CollectOwnJSProxyTargetKeys( |
| 867 Handle<JSProxy> proxy, Handle<JSReceiver> target) { |
| 868 // TODO(cbruni): avoid creating another KeyAccumulator |
| 869 Handle<FixedArray> keys; |
| 870 ASSIGN_RETURN_ON_EXCEPTION_VALUE( |
| 871 isolate_, keys, JSReceiver::OwnPropertyKeys(target), Nothing<bool>()); |
| 872 NextPrototype(); // Prepare for accumulating keys. |
| 873 bool prev_filter_proxy_keys_ = filter_proxy_keys_; |
| 874 filter_proxy_keys_ = false; |
| 875 Maybe<bool> result = AddKeysFromJSProxy(proxy, keys); |
| 876 filter_proxy_keys_ = prev_filter_proxy_keys_; |
| 877 return result; |
| 879 } | 878 } |
| 880 | 879 |
| 881 } // namespace internal | 880 } // namespace internal |
| 882 } // namespace v8 | 881 } // namespace v8 |
| OLD | NEW |