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 20 matching lines...) Expand all Loading... | |
31 } | 31 } |
32 | 32 |
33 } // namespace | 33 } // namespace |
34 MaybeHandle<FixedArray> KeyAccumulator::GetKeys( | 34 MaybeHandle<FixedArray> KeyAccumulator::GetKeys( |
35 Handle<JSReceiver> object, KeyCollectionMode mode, PropertyFilter filter, | 35 Handle<JSReceiver> object, KeyCollectionMode mode, PropertyFilter filter, |
36 GetKeysConversion keys_conversion, bool filter_proxy_keys, bool is_for_in) { | 36 GetKeysConversion keys_conversion, bool filter_proxy_keys, bool is_for_in) { |
37 Isolate* isolate = object->GetIsolate(); | 37 Isolate* isolate = object->GetIsolate(); |
38 KeyAccumulator accumulator(isolate, mode, filter); | 38 KeyAccumulator accumulator(isolate, mode, filter); |
39 accumulator.set_filter_proxy_keys(filter_proxy_keys); | 39 accumulator.set_filter_proxy_keys(filter_proxy_keys); |
40 accumulator.set_is_for_in(is_for_in); | 40 accumulator.set_is_for_in(is_for_in); |
41 MAYBE_RETURN(accumulator.CollectKeys(object, object), | 41 MAYBE_RETURN(accumulator.CollectKeys(object, object, keys_conversion), |
42 MaybeHandle<FixedArray>()); | 42 MaybeHandle<FixedArray>()); |
43 return accumulator.GetKeys(keys_conversion); | 43 return accumulator.GetKeys(keys_conversion); |
44 } | 44 } |
45 | 45 |
46 Handle<FixedArray> KeyAccumulator::GetKeys(GetKeysConversion convert) { | 46 Handle<FixedArray> KeyAccumulator::GetKeys(GetKeysConversion convert) { |
47 if (keys_.is_null()) { | 47 if (keys_.is_null()) { |
48 return isolate_->factory()->empty_fixed_array(); | 48 return isolate_->factory()->empty_fixed_array(); |
49 } | 49 } |
50 if (mode_ == KeyCollectionMode::kOwnOnly && | 50 if (mode_ == KeyCollectionMode::kOwnOnly && |
51 keys_->map() == isolate_->heap()->fixed_array_map()) { | 51 keys_->map() == isolate_->heap()->fixed_array_map()) { |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
144 if (mode_ == KeyCollectionMode::kOwnOnly && !is_for_in_) { | 144 if (mode_ == KeyCollectionMode::kOwnOnly && !is_for_in_) { |
145 // 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. |
146 keys_ = keys; | 146 keys_ = keys; |
147 return Just(true); | 147 return Just(true); |
148 } | 148 } |
149 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); |
150 return Just(true); | 150 return Just(true); |
151 } | 151 } |
152 | 152 |
153 Maybe<bool> KeyAccumulator::CollectKeys(Handle<JSReceiver> receiver, | 153 Maybe<bool> KeyAccumulator::CollectKeys(Handle<JSReceiver> receiver, |
154 Handle<JSReceiver> object) { | 154 Handle<JSReceiver> object, |
155 GetKeysConversion keys_conversion) { | |
155 // Proxies have no hidden prototype and we should not trigger the | 156 // Proxies have no hidden prototype and we should not trigger the |
156 // [[GetPrototypeOf]] trap on the last iteration when using | 157 // [[GetPrototypeOf]] trap on the last iteration when using |
157 // AdvanceFollowingProxies. | 158 // AdvanceFollowingProxies. |
158 if (mode_ == KeyCollectionMode::kOwnOnly && object->IsJSProxy()) { | 159 if (mode_ == KeyCollectionMode::kOwnOnly && object->IsJSProxy()) { |
159 MAYBE_RETURN(CollectOwnJSProxyKeys(receiver, Handle<JSProxy>::cast(object)), | 160 MAYBE_RETURN(CollectOwnJSProxyKeys(receiver, Handle<JSProxy>::cast(object), |
161 keys_conversion), | |
160 Nothing<bool>()); | 162 Nothing<bool>()); |
161 return Just(true); | 163 return Just(true); |
162 } | 164 } |
163 | 165 |
164 PrototypeIterator::WhereToEnd end = mode_ == KeyCollectionMode::kOwnOnly | 166 PrototypeIterator::WhereToEnd end = mode_ == KeyCollectionMode::kOwnOnly |
165 ? PrototypeIterator::END_AT_NON_HIDDEN | 167 ? PrototypeIterator::END_AT_NON_HIDDEN |
166 : PrototypeIterator::END_AT_NULL; | 168 : PrototypeIterator::END_AT_NULL; |
167 for (PrototypeIterator iter(isolate_, object, kStartAtReceiver, end); | 169 for (PrototypeIterator iter(isolate_, object, kStartAtReceiver, end); |
168 !iter.IsAtEnd();) { | 170 !iter.IsAtEnd();) { |
169 Handle<JSReceiver> current = | 171 Handle<JSReceiver> current = |
170 PrototypeIterator::GetCurrent<JSReceiver>(iter); | 172 PrototypeIterator::GetCurrent<JSReceiver>(iter); |
171 Maybe<bool> result = Just(false); // Dummy initialization. | 173 Maybe<bool> result = Just(false); // Dummy initialization. |
172 if (current->IsJSProxy()) { | 174 if (current->IsJSProxy()) { |
173 result = CollectOwnJSProxyKeys(receiver, Handle<JSProxy>::cast(current)); | 175 result = CollectOwnJSProxyKeys(receiver, Handle<JSProxy>::cast(current), |
176 keys_conversion); | |
174 } else { | 177 } else { |
175 DCHECK(current->IsJSObject()); | 178 DCHECK(current->IsJSObject()); |
176 result = CollectOwnKeys(receiver, Handle<JSObject>::cast(current)); | 179 result = CollectOwnKeys(receiver, Handle<JSObject>::cast(current)); |
177 } | 180 } |
178 MAYBE_RETURN(result, Nothing<bool>()); | 181 MAYBE_RETURN(result, Nothing<bool>()); |
179 if (!result.FromJust()) break; // |false| means "stop iterating". | 182 if (!result.FromJust()) break; // |false| means "stop iterating". |
180 // Iterate through proxies but ignore access checks for the ALL_CAN_READ | 183 // Iterate through proxies but ignore access checks for the ALL_CAN_READ |
181 // case on API objects for OWN_ONLY keys handled in CollectOwnKeys. | 184 // case on API objects for OWN_ONLY keys handled in CollectOwnKeys. |
182 if (!iter.AdvanceFollowingProxiesIgnoringAccessChecks()) { | 185 if (!iter.AdvanceFollowingProxiesIgnoringAccessChecks()) { |
183 return Nothing<bool>(); | 186 return Nothing<bool>(); |
(...skipping 512 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
696 object->global_dictionary()); | 699 object->global_dictionary()); |
697 } else { | 700 } else { |
698 return GetOwnEnumPropertyDictionaryKeys( | 701 return GetOwnEnumPropertyDictionaryKeys( |
699 isolate, KeyCollectionMode::kOwnOnly, nullptr, object, | 702 isolate, KeyCollectionMode::kOwnOnly, nullptr, object, |
700 object->property_dictionary()); | 703 object->property_dictionary()); |
701 } | 704 } |
702 } | 705 } |
703 | 706 |
704 // ES6 9.5.12 | 707 // ES6 9.5.12 |
705 // Returns |true| on success, |nothing| in case of exception. | 708 // Returns |true| on success, |nothing| in case of exception. |
706 Maybe<bool> KeyAccumulator::CollectOwnJSProxyKeys(Handle<JSReceiver> receiver, | 709 Maybe<bool> KeyAccumulator::CollectOwnJSProxyKeys( |
707 Handle<JSProxy> proxy) { | 710 Handle<JSReceiver> receiver, Handle<JSProxy> proxy, |
711 GetKeysConversion keys_conversion) { | |
708 STACK_CHECK(isolate_, Nothing<bool>()); | 712 STACK_CHECK(isolate_, Nothing<bool>()); |
709 // 1. Let handler be the value of the [[ProxyHandler]] internal slot of O. | 713 // 1. Let handler be the value of the [[ProxyHandler]] internal slot of O. |
710 Handle<Object> handler(proxy->handler(), isolate_); | 714 Handle<Object> handler(proxy->handler(), isolate_); |
711 // 2. If handler is null, throw a TypeError exception. | 715 // 2. If handler is null, throw a TypeError exception. |
712 // 3. Assert: Type(handler) is Object. | 716 // 3. Assert: Type(handler) is Object. |
713 if (proxy->IsRevoked()) { | 717 if (proxy->IsRevoked()) { |
714 isolate_->Throw(*isolate_->factory()->NewTypeError( | 718 isolate_->Throw(*isolate_->factory()->NewTypeError( |
715 MessageTemplate::kProxyRevoked, isolate_->factory()->ownKeys_string())); | 719 MessageTemplate::kProxyRevoked, isolate_->factory()->ownKeys_string())); |
716 return Nothing<bool>(); | 720 return Nothing<bool>(); |
717 } | 721 } |
718 // 4. Let target be the value of the [[ProxyTarget]] internal slot of O. | 722 // 4. Let target be the value of the [[ProxyTarget]] internal slot of O. |
719 Handle<JSReceiver> target(proxy->target(), isolate_); | 723 Handle<JSReceiver> target(proxy->target(), isolate_); |
720 // 5. Let trap be ? GetMethod(handler, "ownKeys"). | 724 // 5. Let trap be ? GetMethod(handler, "ownKeys"). |
721 Handle<Object> trap; | 725 Handle<Object> trap; |
722 ASSIGN_RETURN_ON_EXCEPTION_VALUE( | 726 ASSIGN_RETURN_ON_EXCEPTION_VALUE( |
723 isolate_, trap, Object::GetMethod(Handle<JSReceiver>::cast(handler), | 727 isolate_, trap, Object::GetMethod(Handle<JSReceiver>::cast(handler), |
724 isolate_->factory()->ownKeys_string()), | 728 isolate_->factory()->ownKeys_string()), |
725 Nothing<bool>()); | 729 Nothing<bool>()); |
726 // 6. If trap is undefined, then | 730 // 6. If trap is undefined, then |
727 if (trap->IsUndefined(isolate_)) { | 731 if (trap->IsUndefined(isolate_)) { |
728 // 6a. Return target.[[OwnPropertyKeys]](). | 732 // 6a. Return target.[[OwnPropertyKeys]](). |
729 return CollectOwnJSProxyTargetKeys(proxy, target); | 733 return CollectOwnJSProxyTargetKeys(proxy, target, keys_conversion); |
730 } | 734 } |
731 // 7. Let trapResultArray be Call(trap, handler, «target»). | 735 // 7. Let trapResultArray be Call(trap, handler, «target»). |
732 Handle<Object> trap_result_array; | 736 Handle<Object> trap_result_array; |
733 Handle<Object> args[] = {target}; | 737 Handle<Object> args[] = {target}; |
734 ASSIGN_RETURN_ON_EXCEPTION_VALUE( | 738 ASSIGN_RETURN_ON_EXCEPTION_VALUE( |
735 isolate_, trap_result_array, | 739 isolate_, trap_result_array, |
736 Execution::Call(isolate_, trap, handler, arraysize(args), args), | 740 Execution::Call(isolate_, trap, handler, arraysize(args), args), |
737 Nothing<bool>()); | 741 Nothing<bool>()); |
738 // 8. Let trapResult be ? CreateListFromArrayLike(trapResultArray, | 742 // 8. Let trapResult be ? CreateListFromArrayLike(trapResultArray, |
739 // «String, Symbol»). | 743 // «String, Symbol»). |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
842 DCHECK_GT(unchecked_result_keys_size, 0); | 846 DCHECK_GT(unchecked_result_keys_size, 0); |
843 isolate_->Throw(*isolate_->factory()->NewTypeError( | 847 isolate_->Throw(*isolate_->factory()->NewTypeError( |
844 MessageTemplate::kProxyOwnKeysNonExtensible)); | 848 MessageTemplate::kProxyOwnKeysNonExtensible)); |
845 return Nothing<bool>(); | 849 return Nothing<bool>(); |
846 } | 850 } |
847 // 21. Return trapResult. | 851 // 21. Return trapResult. |
848 return AddKeysFromJSProxy(proxy, trap_result); | 852 return AddKeysFromJSProxy(proxy, trap_result); |
849 } | 853 } |
850 | 854 |
851 Maybe<bool> KeyAccumulator::CollectOwnJSProxyTargetKeys( | 855 Maybe<bool> KeyAccumulator::CollectOwnJSProxyTargetKeys( |
852 Handle<JSProxy> proxy, Handle<JSReceiver> target) { | 856 Handle<JSProxy> proxy, Handle<JSReceiver> target, |
857 GetKeysConversion keys_conversion) { | |
853 // TODO(cbruni): avoid creating another KeyAccumulator | 858 // TODO(cbruni): avoid creating another KeyAccumulator |
854 Handle<FixedArray> keys; | 859 Handle<FixedArray> keys; |
855 ASSIGN_RETURN_ON_EXCEPTION_VALUE( | 860 ASSIGN_RETURN_ON_EXCEPTION_VALUE( |
856 isolate_, keys, JSReceiver::OwnPropertyKeys(target), Nothing<bool>()); | 861 isolate_, keys, |
862 KeyAccumulator::GetKeys(target, KeyCollectionMode::kOwnOnly, filter_, | |
Dan Ehrenberg
2016/07/08 22:02:07
It looks like the relevant change here is passing
| |
863 keys_conversion, filter_proxy_keys_, is_for_in_), | |
864 Nothing<bool>()); | |
857 bool prev_filter_proxy_keys_ = filter_proxy_keys_; | 865 bool prev_filter_proxy_keys_ = filter_proxy_keys_; |
858 filter_proxy_keys_ = false; | 866 filter_proxy_keys_ = false; |
859 Maybe<bool> result = AddKeysFromJSProxy(proxy, keys); | 867 Maybe<bool> result = AddKeysFromJSProxy(proxy, keys); |
860 filter_proxy_keys_ = prev_filter_proxy_keys_; | 868 filter_proxy_keys_ = prev_filter_proxy_keys_; |
861 return result; | 869 return result; |
862 } | 870 } |
863 | 871 |
864 } // namespace internal | 872 } // namespace internal |
865 } // namespace v8 | 873 } // namespace v8 |
OLD | NEW |