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 17 matching lines...) Expand all Loading... |
28 if (!(e->IsName() || e->IsNumber())) return false; | 28 if (!(e->IsName() || e->IsNumber())) return false; |
29 } | 29 } |
30 return true; | 30 return true; |
31 } | 31 } |
32 | 32 |
33 } // namespace | 33 } // namespace |
34 | 34 |
35 // static | 35 // static |
36 MaybeHandle<FixedArray> KeyAccumulator::GetKeys( | 36 MaybeHandle<FixedArray> KeyAccumulator::GetKeys( |
37 Handle<JSReceiver> object, KeyCollectionMode mode, PropertyFilter filter, | 37 Handle<JSReceiver> object, KeyCollectionMode mode, PropertyFilter filter, |
38 GetKeysConversion keys_conversion, bool filter_proxy_keys, bool is_for_in) { | 38 GetKeysConversion keys_conversion, bool is_for_in) { |
39 Isolate* isolate = object->GetIsolate(); | 39 Isolate* isolate = object->GetIsolate(); |
40 FastKeyAccumulator accumulator(isolate, object, mode, filter); | 40 FastKeyAccumulator accumulator(isolate, object, mode, filter); |
41 accumulator.set_filter_proxy_keys(filter_proxy_keys); | |
42 accumulator.set_is_for_in(is_for_in); | 41 accumulator.set_is_for_in(is_for_in); |
43 return accumulator.GetKeys(keys_conversion); | 42 return accumulator.GetKeys(keys_conversion); |
44 } | 43 } |
45 | 44 |
46 Handle<FixedArray> KeyAccumulator::GetKeys(GetKeysConversion convert) { | 45 Handle<FixedArray> KeyAccumulator::GetKeys(GetKeysConversion convert) { |
47 if (keys_.is_null()) { | 46 if (keys_.is_null()) { |
48 return isolate_->factory()->empty_fixed_array(); | 47 return isolate_->factory()->empty_fixed_array(); |
49 } | 48 } |
50 if (mode_ == KeyCollectionMode::kOwnOnly && | 49 if (mode_ == KeyCollectionMode::kOwnOnly && |
51 keys_->map() == isolate_->heap()->fixed_array_map()) { | 50 keys_->map() == isolate_->heap()->fixed_array_map()) { |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
128 store_position++; | 127 store_position++; |
129 } | 128 } |
130 if (store_position == 0) return isolate->factory()->empty_fixed_array(); | 129 if (store_position == 0) return isolate->factory()->empty_fixed_array(); |
131 keys->Shrink(store_position); | 130 keys->Shrink(store_position); |
132 return keys; | 131 return keys; |
133 } | 132 } |
134 | 133 |
135 // Returns "nothing" in case of exception, "true" on success. | 134 // Returns "nothing" in case of exception, "true" on success. |
136 Maybe<bool> KeyAccumulator::AddKeysFromJSProxy(Handle<JSProxy> proxy, | 135 Maybe<bool> KeyAccumulator::AddKeysFromJSProxy(Handle<JSProxy> proxy, |
137 Handle<FixedArray> keys) { | 136 Handle<FixedArray> keys) { |
138 if (filter_proxy_keys_) { | 137 // Postpone the enumerable check for for-in to the ForInFilter step. |
139 DCHECK(!is_for_in_); | 138 if (!is_for_in_) { |
140 ASSIGN_RETURN_ON_EXCEPTION_VALUE( | 139 ASSIGN_RETURN_ON_EXCEPTION_VALUE( |
141 isolate_, keys, FilterProxyKeys(this, proxy, keys, filter_), | 140 isolate_, keys, FilterProxyKeys(this, proxy, keys, filter_), |
142 Nothing<bool>()); | 141 Nothing<bool>()); |
143 } | 142 if (mode_ == KeyCollectionMode::kOwnOnly) { |
144 if (mode_ == KeyCollectionMode::kOwnOnly && !is_for_in_) { | 143 // If we collect only the keys from a JSProxy do not sort or deduplicate. |
145 // If we collect only the keys from a JSProxy do not sort or deduplicate it. | 144 keys_ = keys; |
146 keys_ = keys; | 145 return Just(true); |
147 return Just(true); | 146 } |
148 } | 147 } |
149 AddKeys(keys, is_for_in_ ? CONVERT_TO_ARRAY_INDEX : DO_NOT_CONVERT); | 148 AddKeys(keys, is_for_in_ ? CONVERT_TO_ARRAY_INDEX : DO_NOT_CONVERT); |
150 return Just(true); | 149 return Just(true); |
151 } | 150 } |
152 | 151 |
153 Maybe<bool> KeyAccumulator::CollectKeys(Handle<JSReceiver> receiver, | 152 Maybe<bool> KeyAccumulator::CollectKeys(Handle<JSReceiver> receiver, |
154 Handle<JSReceiver> object) { | 153 Handle<JSReceiver> object) { |
155 // Proxies have no hidden prototype and we should not trigger the | 154 // Proxies have no hidden prototype and we should not trigger the |
156 // [[GetPrototypeOf]] trap on the last iteration when using | 155 // [[GetPrototypeOf]] trap on the last iteration when using |
157 // AdvanceFollowingProxies. | 156 // AdvanceFollowingProxies. |
(...skipping 279 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
437 } | 436 } |
438 } | 437 } |
439 // The properties-only case failed because there were probably elements on the | 438 // The properties-only case failed because there were probably elements on the |
440 // receiver. | 439 // receiver. |
441 return GetOwnKeysWithElements<true>(isolate_, object, keys_conversion); | 440 return GetOwnKeysWithElements<true>(isolate_, object, keys_conversion); |
442 } | 441 } |
443 | 442 |
444 MaybeHandle<FixedArray> FastKeyAccumulator::GetKeysSlow( | 443 MaybeHandle<FixedArray> FastKeyAccumulator::GetKeysSlow( |
445 GetKeysConversion keys_conversion) { | 444 GetKeysConversion keys_conversion) { |
446 KeyAccumulator accumulator(isolate_, mode_, filter_); | 445 KeyAccumulator accumulator(isolate_, mode_, filter_); |
447 accumulator.set_filter_proxy_keys(filter_proxy_keys_); | |
448 accumulator.set_is_for_in(is_for_in_); | 446 accumulator.set_is_for_in(is_for_in_); |
449 accumulator.set_last_non_empty_prototype(last_non_empty_prototype_); | 447 accumulator.set_last_non_empty_prototype(last_non_empty_prototype_); |
450 | 448 |
451 MAYBE_RETURN(accumulator.CollectKeys(receiver_, receiver_), | 449 MAYBE_RETURN(accumulator.CollectKeys(receiver_, receiver_), |
452 MaybeHandle<FixedArray>()); | 450 MaybeHandle<FixedArray>()); |
453 return accumulator.GetKeys(keys_conversion); | 451 return accumulator.GetKeys(keys_conversion); |
454 } | 452 } |
455 | 453 |
456 namespace { | 454 namespace { |
457 | 455 |
(...skipping 395 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
853 return AddKeysFromJSProxy(proxy, trap_result); | 851 return AddKeysFromJSProxy(proxy, trap_result); |
854 } | 852 } |
855 | 853 |
856 Maybe<bool> KeyAccumulator::CollectOwnJSProxyTargetKeys( | 854 Maybe<bool> KeyAccumulator::CollectOwnJSProxyTargetKeys( |
857 Handle<JSProxy> proxy, Handle<JSReceiver> target) { | 855 Handle<JSProxy> proxy, Handle<JSReceiver> target) { |
858 // TODO(cbruni): avoid creating another KeyAccumulator | 856 // TODO(cbruni): avoid creating another KeyAccumulator |
859 Handle<FixedArray> keys; | 857 Handle<FixedArray> keys; |
860 ASSIGN_RETURN_ON_EXCEPTION_VALUE( | 858 ASSIGN_RETURN_ON_EXCEPTION_VALUE( |
861 isolate_, keys, | 859 isolate_, keys, |
862 KeyAccumulator::GetKeys(target, KeyCollectionMode::kOwnOnly, filter_, | 860 KeyAccumulator::GetKeys(target, KeyCollectionMode::kOwnOnly, filter_, |
863 GetKeysConversion::kConvertToString, | 861 GetKeysConversion::kConvertToString, is_for_in_), |
864 filter_proxy_keys_, is_for_in_), | |
865 Nothing<bool>()); | 862 Nothing<bool>()); |
866 bool prev_filter_proxy_keys_ = filter_proxy_keys_; | |
867 filter_proxy_keys_ = false; | |
868 Maybe<bool> result = AddKeysFromJSProxy(proxy, keys); | 863 Maybe<bool> result = AddKeysFromJSProxy(proxy, keys); |
869 filter_proxy_keys_ = prev_filter_proxy_keys_; | |
870 return result; | 864 return result; |
871 } | 865 } |
872 | 866 |
873 } // namespace internal | 867 } // namespace internal |
874 } // namespace v8 | 868 } // namespace v8 |
OLD | NEW |