OLD | NEW |
1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 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/objects.h" | 5 #include "src/objects.h" |
6 | 6 |
7 #include <cmath> | 7 #include <cmath> |
8 #include <iomanip> | 8 #include <iomanip> |
9 #include <sstream> | 9 #include <sstream> |
10 | 10 |
(...skipping 745 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
756 case LookupIterator::INTEGER_INDEXED_EXOTIC: | 756 case LookupIterator::INTEGER_INDEXED_EXOTIC: |
757 return ReadAbsentProperty(it); | 757 return ReadAbsentProperty(it); |
758 case LookupIterator::DATA: | 758 case LookupIterator::DATA: |
759 return it->GetDataValue(); | 759 return it->GetDataValue(); |
760 } | 760 } |
761 } | 761 } |
762 return ReadAbsentProperty(it); | 762 return ReadAbsentProperty(it); |
763 } | 763 } |
764 | 764 |
765 | 765 |
766 #define STACK_CHECK(result_value) \ | |
767 do { \ | |
768 StackLimitCheck stack_check(isolate); \ | |
769 if (stack_check.HasOverflowed()) { \ | |
770 isolate->Throw(*isolate->factory()->NewRangeError( \ | |
771 MessageTemplate::kStackOverflow)); \ | |
772 return result_value; \ | |
773 } \ | |
774 } while (false) | |
775 | |
776 | |
777 // static | 766 // static |
778 MaybeHandle<Object> JSProxy::GetProperty(Isolate* isolate, | 767 MaybeHandle<Object> JSProxy::GetProperty(Isolate* isolate, |
779 Handle<JSProxy> proxy, | 768 Handle<JSProxy> proxy, |
780 Handle<Name> name, | 769 Handle<Name> name, |
781 Handle<Object> receiver, | 770 Handle<Object> receiver, |
782 bool* was_found) { | 771 bool* was_found) { |
783 *was_found = true; | 772 *was_found = true; |
784 if (receiver->IsJSGlobalObject()) { | 773 if (receiver->IsJSGlobalObject()) { |
785 THROW_NEW_ERROR( | 774 THROW_NEW_ERROR( |
786 isolate, | 775 isolate, |
787 NewTypeError(MessageTemplate::kReadGlobalReferenceThroughProxy, name), | 776 NewTypeError(MessageTemplate::kReadGlobalReferenceThroughProxy, name), |
788 Object); | 777 Object); |
789 } | 778 } |
790 | 779 |
791 DCHECK(!name->IsPrivate()); | 780 DCHECK(!name->IsPrivate()); |
792 STACK_CHECK(MaybeHandle<Object>()); | 781 STACK_CHECK(isolate, MaybeHandle<Object>()); |
793 Handle<Name> trap_name = isolate->factory()->get_string(); | 782 Handle<Name> trap_name = isolate->factory()->get_string(); |
794 // 1. Assert: IsPropertyKey(P) is true. | 783 // 1. Assert: IsPropertyKey(P) is true. |
795 // 2. Let handler be the value of the [[ProxyHandler]] internal slot of O. | 784 // 2. Let handler be the value of the [[ProxyHandler]] internal slot of O. |
796 Handle<Object> handler(proxy->handler(), isolate); | 785 Handle<Object> handler(proxy->handler(), isolate); |
797 // 3. If handler is null, throw a TypeError exception. | 786 // 3. If handler is null, throw a TypeError exception. |
798 // 4. Assert: Type(handler) is Object. | 787 // 4. Assert: Type(handler) is Object. |
799 if (proxy->IsRevoked()) { | 788 if (proxy->IsRevoked()) { |
800 THROW_NEW_ERROR(isolate, | 789 THROW_NEW_ERROR(isolate, |
801 NewTypeError(MessageTemplate::kProxyRevoked, trap_name), | 790 NewTypeError(MessageTemplate::kProxyRevoked, trap_name), |
802 Object); | 791 Object); |
(...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
995 isolate->counters()->cow_arrays_converted()->Increment(); | 984 isolate->counters()->cow_arrays_converted()->Increment(); |
996 } | 985 } |
997 | 986 |
998 | 987 |
999 // ES6 9.5.1 | 988 // ES6 9.5.1 |
1000 // static | 989 // static |
1001 MaybeHandle<Object> JSProxy::GetPrototype(Handle<JSProxy> proxy) { | 990 MaybeHandle<Object> JSProxy::GetPrototype(Handle<JSProxy> proxy) { |
1002 Isolate* isolate = proxy->GetIsolate(); | 991 Isolate* isolate = proxy->GetIsolate(); |
1003 Handle<String> trap_name = isolate->factory()->getPrototypeOf_string(); | 992 Handle<String> trap_name = isolate->factory()->getPrototypeOf_string(); |
1004 | 993 |
1005 STACK_CHECK(MaybeHandle<Object>()); | 994 STACK_CHECK(isolate, MaybeHandle<Object>()); |
1006 | 995 |
1007 // 1. Let handler be the value of the [[ProxyHandler]] internal slot. | 996 // 1. Let handler be the value of the [[ProxyHandler]] internal slot. |
1008 // 2. If handler is null, throw a TypeError exception. | 997 // 2. If handler is null, throw a TypeError exception. |
1009 // 3. Assert: Type(handler) is Object. | 998 // 3. Assert: Type(handler) is Object. |
1010 // 4. Let target be the value of the [[ProxyTarget]] internal slot. | 999 // 4. Let target be the value of the [[ProxyTarget]] internal slot. |
1011 if (proxy->IsRevoked()) { | 1000 if (proxy->IsRevoked()) { |
1012 THROW_NEW_ERROR(isolate, | 1001 THROW_NEW_ERROR(isolate, |
1013 NewTypeError(MessageTemplate::kProxyRevoked, trap_name), | 1002 NewTypeError(MessageTemplate::kProxyRevoked, trap_name), |
1014 Object); | 1003 Object); |
1015 } | 1004 } |
(...skipping 3826 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4842 void JSProxy::Revoke(Handle<JSProxy> proxy) { | 4831 void JSProxy::Revoke(Handle<JSProxy> proxy) { |
4843 Isolate* isolate = proxy->GetIsolate(); | 4832 Isolate* isolate = proxy->GetIsolate(); |
4844 if (!proxy->IsRevoked()) proxy->set_handler(isolate->heap()->null_value()); | 4833 if (!proxy->IsRevoked()) proxy->set_handler(isolate->heap()->null_value()); |
4845 DCHECK(proxy->IsRevoked()); | 4834 DCHECK(proxy->IsRevoked()); |
4846 } | 4835 } |
4847 | 4836 |
4848 | 4837 |
4849 Maybe<bool> JSProxy::HasProperty(Isolate* isolate, Handle<JSProxy> proxy, | 4838 Maybe<bool> JSProxy::HasProperty(Isolate* isolate, Handle<JSProxy> proxy, |
4850 Handle<Name> name) { | 4839 Handle<Name> name) { |
4851 DCHECK(!name->IsPrivate()); | 4840 DCHECK(!name->IsPrivate()); |
4852 STACK_CHECK(Nothing<bool>()); | 4841 STACK_CHECK(isolate, Nothing<bool>()); |
4853 // 1. (Assert) | 4842 // 1. (Assert) |
4854 // 2. Let handler be the value of the [[ProxyHandler]] internal slot of O. | 4843 // 2. Let handler be the value of the [[ProxyHandler]] internal slot of O. |
4855 Handle<Object> handler(proxy->handler(), isolate); | 4844 Handle<Object> handler(proxy->handler(), isolate); |
4856 // 3. If handler is null, throw a TypeError exception. | 4845 // 3. If handler is null, throw a TypeError exception. |
4857 // 4. Assert: Type(handler) is Object. | 4846 // 4. Assert: Type(handler) is Object. |
4858 if (proxy->IsRevoked()) { | 4847 if (proxy->IsRevoked()) { |
4859 isolate->Throw(*isolate->factory()->NewTypeError( | 4848 isolate->Throw(*isolate->factory()->NewTypeError( |
4860 MessageTemplate::kProxyRevoked, isolate->factory()->has_string())); | 4849 MessageTemplate::kProxyRevoked, isolate->factory()->has_string())); |
4861 return Nothing<bool>(); | 4850 return Nothing<bool>(); |
4862 } | 4851 } |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4911 // 10. Return booleanTrapResult. | 4900 // 10. Return booleanTrapResult. |
4912 return Just(boolean_trap_result); | 4901 return Just(boolean_trap_result); |
4913 } | 4902 } |
4914 | 4903 |
4915 | 4904 |
4916 Maybe<bool> JSProxy::SetProperty(Handle<JSProxy> proxy, Handle<Name> name, | 4905 Maybe<bool> JSProxy::SetProperty(Handle<JSProxy> proxy, Handle<Name> name, |
4917 Handle<Object> value, Handle<Object> receiver, | 4906 Handle<Object> value, Handle<Object> receiver, |
4918 LanguageMode language_mode) { | 4907 LanguageMode language_mode) { |
4919 DCHECK(!name->IsPrivate()); | 4908 DCHECK(!name->IsPrivate()); |
4920 Isolate* isolate = proxy->GetIsolate(); | 4909 Isolate* isolate = proxy->GetIsolate(); |
4921 STACK_CHECK(Nothing<bool>()); | 4910 STACK_CHECK(isolate, Nothing<bool>()); |
4922 Factory* factory = isolate->factory(); | 4911 Factory* factory = isolate->factory(); |
4923 Handle<String> trap_name = factory->set_string(); | 4912 Handle<String> trap_name = factory->set_string(); |
4924 ShouldThrow should_throw = | 4913 ShouldThrow should_throw = |
4925 is_sloppy(language_mode) ? DONT_THROW : THROW_ON_ERROR; | 4914 is_sloppy(language_mode) ? DONT_THROW : THROW_ON_ERROR; |
4926 | 4915 |
4927 if (proxy->IsRevoked()) { | 4916 if (proxy->IsRevoked()) { |
4928 isolate->Throw( | 4917 isolate->Throw( |
4929 *factory->NewTypeError(MessageTemplate::kProxyRevoked, trap_name)); | 4918 *factory->NewTypeError(MessageTemplate::kProxyRevoked, trap_name)); |
4930 return Nothing<bool>(); | 4919 return Nothing<bool>(); |
4931 } | 4920 } |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4982 } | 4971 } |
4983 | 4972 |
4984 | 4973 |
4985 Maybe<bool> JSProxy::DeletePropertyOrElement(Handle<JSProxy> proxy, | 4974 Maybe<bool> JSProxy::DeletePropertyOrElement(Handle<JSProxy> proxy, |
4986 Handle<Name> name, | 4975 Handle<Name> name, |
4987 LanguageMode language_mode) { | 4976 LanguageMode language_mode) { |
4988 DCHECK(!name->IsPrivate()); | 4977 DCHECK(!name->IsPrivate()); |
4989 ShouldThrow should_throw = | 4978 ShouldThrow should_throw = |
4990 is_sloppy(language_mode) ? DONT_THROW : THROW_ON_ERROR; | 4979 is_sloppy(language_mode) ? DONT_THROW : THROW_ON_ERROR; |
4991 Isolate* isolate = proxy->GetIsolate(); | 4980 Isolate* isolate = proxy->GetIsolate(); |
4992 STACK_CHECK(Nothing<bool>()); | 4981 STACK_CHECK(isolate, Nothing<bool>()); |
4993 Factory* factory = isolate->factory(); | 4982 Factory* factory = isolate->factory(); |
4994 Handle<String> trap_name = factory->deleteProperty_string(); | 4983 Handle<String> trap_name = factory->deleteProperty_string(); |
4995 | 4984 |
4996 if (proxy->IsRevoked()) { | 4985 if (proxy->IsRevoked()) { |
4997 isolate->Throw( | 4986 isolate->Throw( |
4998 *factory->NewTypeError(MessageTemplate::kProxyRevoked, trap_name)); | 4987 *factory->NewTypeError(MessageTemplate::kProxyRevoked, trap_name)); |
4999 return Nothing<bool>(); | 4988 return Nothing<bool>(); |
5000 } | 4989 } |
5001 Handle<JSReceiver> target(proxy->target(), isolate); | 4990 Handle<JSReceiver> target(proxy->target(), isolate); |
5002 Handle<JSReceiver> handler(JSReceiver::cast(proxy->handler()), isolate); | 4991 Handle<JSReceiver> handler(JSReceiver::cast(proxy->handler()), isolate); |
(...skipping 1883 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6886 return Just(result); | 6875 return Just(result); |
6887 } | 6876 } |
6888 | 6877 |
6889 | 6878 |
6890 // ES6 9.5.6 | 6879 // ES6 9.5.6 |
6891 // static | 6880 // static |
6892 Maybe<bool> JSProxy::DefineOwnProperty(Isolate* isolate, Handle<JSProxy> proxy, | 6881 Maybe<bool> JSProxy::DefineOwnProperty(Isolate* isolate, Handle<JSProxy> proxy, |
6893 Handle<Object> key, | 6882 Handle<Object> key, |
6894 PropertyDescriptor* desc, | 6883 PropertyDescriptor* desc, |
6895 ShouldThrow should_throw) { | 6884 ShouldThrow should_throw) { |
6896 STACK_CHECK(Nothing<bool>()); | 6885 STACK_CHECK(isolate, Nothing<bool>()); |
6897 if (key->IsSymbol() && Handle<Symbol>::cast(key)->IsPrivate()) { | 6886 if (key->IsSymbol() && Handle<Symbol>::cast(key)->IsPrivate()) { |
6898 return SetPrivateProperty(isolate, proxy, Handle<Symbol>::cast(key), desc, | 6887 return SetPrivateProperty(isolate, proxy, Handle<Symbol>::cast(key), desc, |
6899 should_throw); | 6888 should_throw); |
6900 } | 6889 } |
6901 Handle<String> trap_name = isolate->factory()->defineProperty_string(); | 6890 Handle<String> trap_name = isolate->factory()->defineProperty_string(); |
6902 // 1. Assert: IsPropertyKey(P) is true. | 6891 // 1. Assert: IsPropertyKey(P) is true. |
6903 DCHECK(key->IsName() || key->IsNumber()); | 6892 DCHECK(key->IsName() || key->IsNumber()); |
6904 // 2. Let handler be the value of the [[ProxyHandler]] internal slot of O. | 6893 // 2. Let handler be the value of the [[ProxyHandler]] internal slot of O. |
6905 Handle<Object> handler(proxy->handler(), isolate); | 6894 Handle<Object> handler(proxy->handler(), isolate); |
6906 // 3. If handler is null, throw a TypeError exception. | 6895 // 3. If handler is null, throw a TypeError exception. |
(...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7107 } | 7096 } |
7108 | 7097 |
7109 | 7098 |
7110 // ES6 9.5.5 | 7099 // ES6 9.5.5 |
7111 // static | 7100 // static |
7112 Maybe<bool> JSProxy::GetOwnPropertyDescriptor(Isolate* isolate, | 7101 Maybe<bool> JSProxy::GetOwnPropertyDescriptor(Isolate* isolate, |
7113 Handle<JSProxy> proxy, | 7102 Handle<JSProxy> proxy, |
7114 Handle<Name> name, | 7103 Handle<Name> name, |
7115 PropertyDescriptor* desc) { | 7104 PropertyDescriptor* desc) { |
7116 DCHECK(!name->IsPrivate()); | 7105 DCHECK(!name->IsPrivate()); |
7117 STACK_CHECK(Nothing<bool>()); | 7106 STACK_CHECK(isolate, Nothing<bool>()); |
7118 | 7107 |
7119 Handle<String> trap_name = | 7108 Handle<String> trap_name = |
7120 isolate->factory()->getOwnPropertyDescriptor_string(); | 7109 isolate->factory()->getOwnPropertyDescriptor_string(); |
7121 // 1. (Assert) | 7110 // 1. (Assert) |
7122 // 2. Let handler be the value of the [[ProxyHandler]] internal slot of O. | 7111 // 2. Let handler be the value of the [[ProxyHandler]] internal slot of O. |
7123 Handle<Object> handler(proxy->handler(), isolate); | 7112 Handle<Object> handler(proxy->handler(), isolate); |
7124 // 3. If handler is null, throw a TypeError exception. | 7113 // 3. If handler is null, throw a TypeError exception. |
7125 // 4. Assert: Type(handler) is Object. | 7114 // 4. Assert: Type(handler) is Object. |
7126 if (proxy->IsRevoked()) { | 7115 if (proxy->IsRevoked()) { |
7127 isolate->Throw(*isolate->factory()->NewTypeError( | 7116 isolate->Throw(*isolate->factory()->NewTypeError( |
(...skipping 337 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7465 } | 7454 } |
7466 DCHECK(object->IsJSObject()); | 7455 DCHECK(object->IsJSObject()); |
7467 return JSObject::PreventExtensions(Handle<JSObject>::cast(object), | 7456 return JSObject::PreventExtensions(Handle<JSObject>::cast(object), |
7468 should_throw); | 7457 should_throw); |
7469 } | 7458 } |
7470 | 7459 |
7471 | 7460 |
7472 Maybe<bool> JSProxy::PreventExtensions(Handle<JSProxy> proxy, | 7461 Maybe<bool> JSProxy::PreventExtensions(Handle<JSProxy> proxy, |
7473 ShouldThrow should_throw) { | 7462 ShouldThrow should_throw) { |
7474 Isolate* isolate = proxy->GetIsolate(); | 7463 Isolate* isolate = proxy->GetIsolate(); |
7475 STACK_CHECK(Nothing<bool>()); | 7464 STACK_CHECK(isolate, Nothing<bool>()); |
7476 Factory* factory = isolate->factory(); | 7465 Factory* factory = isolate->factory(); |
7477 Handle<String> trap_name = factory->preventExtensions_string(); | 7466 Handle<String> trap_name = factory->preventExtensions_string(); |
7478 | 7467 |
7479 if (proxy->IsRevoked()) { | 7468 if (proxy->IsRevoked()) { |
7480 isolate->Throw( | 7469 isolate->Throw( |
7481 *factory->NewTypeError(MessageTemplate::kProxyRevoked, trap_name)); | 7470 *factory->NewTypeError(MessageTemplate::kProxyRevoked, trap_name)); |
7482 return Nothing<bool>(); | 7471 return Nothing<bool>(); |
7483 } | 7472 } |
7484 Handle<JSReceiver> target(proxy->target(), isolate); | 7473 Handle<JSReceiver> target(proxy->target(), isolate); |
7485 Handle<JSReceiver> handler(JSReceiver::cast(proxy->handler()), isolate); | 7474 Handle<JSReceiver> handler(JSReceiver::cast(proxy->handler()), isolate); |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7567 Maybe<bool> JSReceiver::IsExtensible(Handle<JSReceiver> object) { | 7556 Maybe<bool> JSReceiver::IsExtensible(Handle<JSReceiver> object) { |
7568 if (object->IsJSProxy()) { | 7557 if (object->IsJSProxy()) { |
7569 return JSProxy::IsExtensible(Handle<JSProxy>::cast(object)); | 7558 return JSProxy::IsExtensible(Handle<JSProxy>::cast(object)); |
7570 } | 7559 } |
7571 return Just(JSObject::IsExtensible(Handle<JSObject>::cast(object))); | 7560 return Just(JSObject::IsExtensible(Handle<JSObject>::cast(object))); |
7572 } | 7561 } |
7573 | 7562 |
7574 | 7563 |
7575 Maybe<bool> JSProxy::IsExtensible(Handle<JSProxy> proxy) { | 7564 Maybe<bool> JSProxy::IsExtensible(Handle<JSProxy> proxy) { |
7576 Isolate* isolate = proxy->GetIsolate(); | 7565 Isolate* isolate = proxy->GetIsolate(); |
7577 STACK_CHECK(Nothing<bool>()); | 7566 STACK_CHECK(isolate, Nothing<bool>()); |
7578 Factory* factory = isolate->factory(); | 7567 Factory* factory = isolate->factory(); |
7579 Handle<String> trap_name = factory->isExtensible_string(); | 7568 Handle<String> trap_name = factory->isExtensible_string(); |
7580 | 7569 |
7581 if (proxy->IsRevoked()) { | 7570 if (proxy->IsRevoked()) { |
7582 isolate->Throw( | 7571 isolate->Throw( |
7583 *factory->NewTypeError(MessageTemplate::kProxyRevoked, trap_name)); | 7572 *factory->NewTypeError(MessageTemplate::kProxyRevoked, trap_name)); |
7584 return Nothing<bool>(); | 7573 return Nothing<bool>(); |
7585 } | 7574 } |
7586 Handle<JSReceiver> target(proxy->target(), isolate); | 7575 Handle<JSReceiver> target(proxy->target(), isolate); |
7587 Handle<JSReceiver> handler(JSReceiver::cast(proxy->handler()), isolate); | 7576 Handle<JSReceiver> handler(JSReceiver::cast(proxy->handler()), isolate); |
(...skipping 313 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7901 } | 7890 } |
7902 } | 7891 } |
7903 } else { | 7892 } else { |
7904 // Only deep copy fields from the object literal expression. | 7893 // Only deep copy fields from the object literal expression. |
7905 // In particular, don't try to copy the length attribute of | 7894 // In particular, don't try to copy the length attribute of |
7906 // an array. | 7895 // an array. |
7907 PropertyFilter filter = static_cast<PropertyFilter>( | 7896 PropertyFilter filter = static_cast<PropertyFilter>( |
7908 ONLY_WRITABLE | ONLY_ENUMERABLE | ONLY_CONFIGURABLE); | 7897 ONLY_WRITABLE | ONLY_ENUMERABLE | ONLY_CONFIGURABLE); |
7909 KeyAccumulator accumulator(isolate, OWN_ONLY, filter); | 7898 KeyAccumulator accumulator(isolate, OWN_ONLY, filter); |
7910 accumulator.NextPrototype(); | 7899 accumulator.NextPrototype(); |
7911 copy->CollectOwnPropertyNames(&accumulator, filter); | 7900 accumulator.CollectOwnPropertyNames(copy); |
7912 Handle<FixedArray> names = accumulator.GetKeys(); | 7901 Handle<FixedArray> names = accumulator.GetKeys(); |
7913 for (int i = 0; i < names->length(); i++) { | 7902 for (int i = 0; i < names->length(); i++) { |
7914 DCHECK(names->get(i)->IsName()); | 7903 DCHECK(names->get(i)->IsName()); |
7915 Handle<Name> name(Name::cast(names->get(i))); | 7904 Handle<Name> name(Name::cast(names->get(i))); |
7916 Handle<Object> value = | 7905 Handle<Object> value = |
7917 JSObject::GetProperty(copy, name).ToHandleChecked(); | 7906 JSObject::GetProperty(copy, name).ToHandleChecked(); |
7918 if (value->IsJSObject()) { | 7907 if (value->IsJSObject()) { |
7919 Handle<JSObject> result; | 7908 Handle<JSObject> result; |
7920 ASSIGN_RETURN_ON_EXCEPTION( | 7909 ASSIGN_RETURN_ON_EXCEPTION( |
7921 isolate, result, | 7910 isolate, result, |
(...skipping 286 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8208 static bool ContainsOnlyValidKeys(Handle<FixedArray> array) { | 8197 static bool ContainsOnlyValidKeys(Handle<FixedArray> array) { |
8209 int len = array->length(); | 8198 int len = array->length(); |
8210 for (int i = 0; i < len; i++) { | 8199 for (int i = 0; i < len; i++) { |
8211 Object* e = array->get(i); | 8200 Object* e = array->get(i); |
8212 if (!(e->IsName() || e->IsNumber())) return false; | 8201 if (!(e->IsName() || e->IsNumber())) return false; |
8213 } | 8202 } |
8214 return true; | 8203 return true; |
8215 } | 8204 } |
8216 | 8205 |
8217 | 8206 |
8218 static Handle<FixedArray> ReduceFixedArrayTo( | |
8219 Handle<FixedArray> array, int length) { | |
8220 DCHECK_LE(length, array->length()); | |
8221 if (array->length() == length) return array; | |
8222 return array->GetIsolate()->factory()->CopyFixedArrayUpTo(array, length); | |
8223 } | |
8224 | |
8225 bool Map::OnlyHasSimpleProperties() { | 8207 bool Map::OnlyHasSimpleProperties() { |
8226 // Wrapped string elements aren't explicitly stored in the elements backing | 8208 // Wrapped string elements aren't explicitly stored in the elements backing |
8227 // store, but are loaded indirectly from the underlying string. | 8209 // store, but are loaded indirectly from the underlying string. |
8228 return !IsStringWrapperElementsKind(elements_kind()) && | 8210 return !IsStringWrapperElementsKind(elements_kind()) && |
8229 instance_type() > LAST_SPECIAL_RECEIVER_TYPE && | 8211 instance_type() > LAST_SPECIAL_RECEIVER_TYPE && |
8230 !has_hidden_prototype() && !is_dictionary_map(); | 8212 !has_hidden_prototype() && !is_dictionary_map(); |
8231 } | 8213 } |
8232 | 8214 |
8233 // static | |
8234 Handle<FixedArray> JSObject::GetFastEnumPropertyKeys(Isolate* isolate, | |
8235 Handle<JSObject> object) { | |
8236 Handle<Map> map(object->map()); | |
8237 bool cache_enum_length = map->OnlyHasSimpleProperties(); | |
8238 | |
8239 Handle<DescriptorArray> descs = | |
8240 Handle<DescriptorArray>(map->instance_descriptors(), isolate); | |
8241 int own_property_count = map->EnumLength(); | |
8242 // If the enum length of the given map is set to kInvalidEnumCache, this | |
8243 // means that the map itself has never used the present enum cache. The | |
8244 // first step to using the cache is to set the enum length of the map by | |
8245 // counting the number of own descriptors that are ENUMERABLE_STRINGS. | |
8246 if (own_property_count == kInvalidEnumCacheSentinel) { | |
8247 own_property_count = | |
8248 map->NumberOfDescribedProperties(OWN_DESCRIPTORS, ENUMERABLE_STRINGS); | |
8249 } else { | |
8250 DCHECK( | |
8251 own_property_count == | |
8252 map->NumberOfDescribedProperties(OWN_DESCRIPTORS, ENUMERABLE_STRINGS)); | |
8253 } | |
8254 | |
8255 if (descs->HasEnumCache()) { | |
8256 Handle<FixedArray> keys(descs->GetEnumCache(), isolate); | |
8257 // In case the number of properties required in the enum are actually | |
8258 // present, we can reuse the enum cache. Otherwise, this means that the | |
8259 // enum cache was generated for a previous (smaller) version of the | |
8260 // Descriptor Array. In that case we regenerate the enum cache. | |
8261 if (own_property_count <= keys->length()) { | |
8262 isolate->counters()->enum_cache_hits()->Increment(); | |
8263 if (cache_enum_length) map->SetEnumLength(own_property_count); | |
8264 return ReduceFixedArrayTo(keys, own_property_count); | |
8265 } | |
8266 } | |
8267 | |
8268 if (descs->IsEmpty()) { | |
8269 isolate->counters()->enum_cache_hits()->Increment(); | |
8270 if (cache_enum_length) map->SetEnumLength(0); | |
8271 return isolate->factory()->empty_fixed_array(); | |
8272 } | |
8273 | |
8274 isolate->counters()->enum_cache_misses()->Increment(); | |
8275 | |
8276 Handle<FixedArray> storage = | |
8277 isolate->factory()->NewFixedArray(own_property_count); | |
8278 Handle<FixedArray> indices = | |
8279 isolate->factory()->NewFixedArray(own_property_count); | |
8280 | |
8281 int size = map->NumberOfOwnDescriptors(); | |
8282 int index = 0; | |
8283 | |
8284 for (int i = 0; i < size; i++) { | |
8285 PropertyDetails details = descs->GetDetails(i); | |
8286 if (details.IsDontEnum()) continue; | |
8287 Object* key = descs->GetKey(i); | |
8288 if (key->IsSymbol()) continue; | |
8289 storage->set(index, key); | |
8290 if (!indices.is_null()) { | |
8291 if (details.type() != DATA) { | |
8292 indices = Handle<FixedArray>(); | |
8293 } else { | |
8294 FieldIndex field_index = FieldIndex::ForDescriptor(*map, i); | |
8295 int load_by_field_index = field_index.GetLoadByFieldIndex(); | |
8296 indices->set(index, Smi::FromInt(load_by_field_index)); | |
8297 } | |
8298 } | |
8299 index++; | |
8300 } | |
8301 DCHECK(index == storage->length()); | |
8302 | |
8303 DescriptorArray::SetEnumCache(descs, isolate, storage, indices); | |
8304 if (cache_enum_length) { | |
8305 map->SetEnumLength(own_property_count); | |
8306 } | |
8307 return storage; | |
8308 } | |
8309 | |
8310 | |
8311 Handle<FixedArray> JSObject::GetEnumPropertyKeys(Handle<JSObject> object) { | |
8312 Isolate* isolate = object->GetIsolate(); | |
8313 if (object->HasFastProperties()) { | |
8314 return GetFastEnumPropertyKeys(isolate, object); | |
8315 } else if (object->IsJSGlobalObject()) { | |
8316 Handle<GlobalDictionary> dictionary(object->global_dictionary()); | |
8317 int length = dictionary->NumberOfEnumElements(); | |
8318 if (length == 0) { | |
8319 return isolate->factory()->empty_fixed_array(); | |
8320 } | |
8321 Handle<FixedArray> storage = isolate->factory()->NewFixedArray(length); | |
8322 dictionary->CopyEnumKeysTo(*storage); | |
8323 return storage; | |
8324 } else { | |
8325 Handle<NameDictionary> dictionary(object->property_dictionary()); | |
8326 int length = dictionary->NumberOfEnumElements(); | |
8327 if (length == 0) { | |
8328 return isolate->factory()->empty_fixed_array(); | |
8329 } | |
8330 Handle<FixedArray> storage = isolate->factory()->NewFixedArray(length); | |
8331 dictionary->CopyEnumKeysTo(*storage); | |
8332 return storage; | |
8333 } | |
8334 } | |
8335 | |
8336 | |
8337 enum IndexedOrNamed { kIndexed, kNamed }; | |
8338 | |
8339 | |
8340 // Returns |true| on success, |nothing| on exception. | |
8341 template <class Callback, IndexedOrNamed type> | |
8342 static Maybe<bool> GetKeysFromInterceptor(Isolate* isolate, | |
8343 Handle<JSReceiver> receiver, | |
8344 Handle<JSObject> object, | |
8345 PropertyFilter filter, | |
8346 KeyAccumulator* accumulator) { | |
8347 if (type == kIndexed) { | |
8348 if (!object->HasIndexedInterceptor()) return Just(true); | |
8349 } else { | |
8350 if (!object->HasNamedInterceptor()) return Just(true); | |
8351 } | |
8352 Handle<InterceptorInfo> interceptor(type == kIndexed | |
8353 ? object->GetIndexedInterceptor() | |
8354 : object->GetNamedInterceptor(), | |
8355 isolate); | |
8356 if ((filter & ONLY_ALL_CAN_READ) && !interceptor->all_can_read()) { | |
8357 return Just(true); | |
8358 } | |
8359 PropertyCallbackArguments args(isolate, interceptor->data(), *receiver, | |
8360 *object, Object::DONT_THROW); | |
8361 Handle<JSObject> result; | |
8362 if (!interceptor->enumerator()->IsUndefined()) { | |
8363 Callback enum_fun = v8::ToCData<Callback>(interceptor->enumerator()); | |
8364 const char* log_tag = type == kIndexed ? "interceptor-indexed-enum" | |
8365 : "interceptor-named-enum"; | |
8366 LOG(isolate, ApiObjectAccess(log_tag, *object)); | |
8367 result = args.Call(enum_fun); | |
8368 } | |
8369 RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<bool>()); | |
8370 if (result.is_null()) return Just(true); | |
8371 DCHECK(result->IsJSArray() || result->HasSloppyArgumentsElements()); | |
8372 // The accumulator takes care of string/symbol filtering. | |
8373 if (type == kIndexed) { | |
8374 accumulator->AddElementKeysFromInterceptor(result); | |
8375 } else { | |
8376 accumulator->AddKeys(result, DO_NOT_CONVERT); | |
8377 } | |
8378 return Just(true); | |
8379 } | |
8380 | |
8381 | |
8382 // Returns |true| on success, |false| if prototype walking should be stopped, | |
8383 // |nothing| if an exception was thrown. | |
8384 static Maybe<bool> GetKeysFromJSObject(Isolate* isolate, | |
8385 Handle<JSReceiver> receiver, | |
8386 Handle<JSObject> object, | |
8387 PropertyFilter* filter, | |
8388 KeyCollectionType type, | |
8389 KeyAccumulator* accumulator) { | |
8390 accumulator->NextPrototype(); | |
8391 // Check access rights if required. | |
8392 if (object->IsAccessCheckNeeded() && | |
8393 !isolate->MayAccess(handle(isolate->context()), object)) { | |
8394 // The cross-origin spec says that [[Enumerate]] shall return an empty | |
8395 // iterator when it doesn't have access... | |
8396 if (type == INCLUDE_PROTOS) { | |
8397 return Just(false); | |
8398 } | |
8399 // ...whereas [[OwnPropertyKeys]] shall return whitelisted properties. | |
8400 DCHECK_EQ(OWN_ONLY, type); | |
8401 *filter = static_cast<PropertyFilter>(*filter | ONLY_ALL_CAN_READ); | |
8402 } | |
8403 | |
8404 JSObject::CollectOwnElementKeys(object, accumulator, *filter); | |
8405 | |
8406 // Add the element keys from the interceptor. | |
8407 Maybe<bool> success = | |
8408 GetKeysFromInterceptor<v8::IndexedPropertyEnumeratorCallback, kIndexed>( | |
8409 isolate, receiver, object, *filter, accumulator); | |
8410 MAYBE_RETURN(success, Nothing<bool>()); | |
8411 | |
8412 if (*filter == ENUMERABLE_STRINGS) { | |
8413 Handle<FixedArray> enum_keys = JSObject::GetEnumPropertyKeys(object); | |
8414 accumulator->AddKeys(enum_keys, DO_NOT_CONVERT); | |
8415 } else { | |
8416 object->CollectOwnPropertyNames(accumulator, *filter); | |
8417 } | |
8418 | |
8419 // Add the property keys from the interceptor. | |
8420 success = GetKeysFromInterceptor<v8::GenericNamedPropertyEnumeratorCallback, | |
8421 kNamed>(isolate, receiver, object, *filter, | |
8422 accumulator); | |
8423 MAYBE_RETURN(success, Nothing<bool>()); | |
8424 return Just(true); | |
8425 } | |
8426 | |
8427 | |
8428 // Helper function for JSReceiver::GetKeys() below. Can be called recursively. | |
8429 // Returns |true| or |nothing|. | |
8430 static Maybe<bool> GetKeys_Internal(Isolate* isolate, | |
8431 Handle<JSReceiver> receiver, | |
8432 Handle<JSReceiver> object, | |
8433 KeyCollectionType type, | |
8434 PropertyFilter filter, | |
8435 KeyAccumulator* accumulator) { | |
8436 // Proxies have no hidden prototype and we should not trigger the | |
8437 // [[GetPrototypeOf]] trap on the last iteration when using | |
8438 // AdvanceFollowingProxies. | |
8439 if (type == OWN_ONLY && object->IsJSProxy()) { | |
8440 MAYBE_RETURN(JSProxy::OwnPropertyKeys(isolate, receiver, | |
8441 Handle<JSProxy>::cast(object), filter, | |
8442 accumulator), | |
8443 Nothing<bool>()); | |
8444 return Just(true); | |
8445 } | |
8446 | |
8447 PrototypeIterator::WhereToEnd end = type == OWN_ONLY | |
8448 ? PrototypeIterator::END_AT_NON_HIDDEN | |
8449 : PrototypeIterator::END_AT_NULL; | |
8450 for (PrototypeIterator iter(isolate, object, | |
8451 PrototypeIterator::START_AT_RECEIVER, end); | |
8452 !iter.IsAtEnd();) { | |
8453 Handle<JSReceiver> current = | |
8454 PrototypeIterator::GetCurrent<JSReceiver>(iter); | |
8455 Maybe<bool> result = Just(false); // Dummy initialization. | |
8456 if (current->IsJSProxy()) { | |
8457 result = JSProxy::OwnPropertyKeys(isolate, receiver, | |
8458 Handle<JSProxy>::cast(current), filter, | |
8459 accumulator); | |
8460 } else { | |
8461 DCHECK(current->IsJSObject()); | |
8462 result = GetKeysFromJSObject(isolate, receiver, | |
8463 Handle<JSObject>::cast(current), &filter, | |
8464 type, accumulator); | |
8465 } | |
8466 MAYBE_RETURN(result, Nothing<bool>()); | |
8467 if (!result.FromJust()) break; // |false| means "stop iterating". | |
8468 // Iterate through proxies but ignore access checks for the ALL_CAN_READ | |
8469 // case on API objects for OWN_ONLY keys handlede in GgetKeysFromJSObject. | |
8470 if (!iter.AdvanceFollowingProxiesIgnoringAccessChecks()) { | |
8471 return Nothing<bool>(); | |
8472 } | |
8473 } | |
8474 return Just(true); | |
8475 } | |
8476 | |
8477 | |
8478 // ES6 9.5.12 | |
8479 // Returns |true| on success, |nothing| in case of exception. | |
8480 // static | |
8481 Maybe<bool> JSProxy::OwnPropertyKeys(Isolate* isolate, | |
8482 Handle<JSReceiver> receiver, | |
8483 Handle<JSProxy> proxy, | |
8484 PropertyFilter filter, | |
8485 KeyAccumulator* accumulator) { | |
8486 STACK_CHECK(Nothing<bool>()); | |
8487 // 1. Let handler be the value of the [[ProxyHandler]] internal slot of O. | |
8488 Handle<Object> handler(proxy->handler(), isolate); | |
8489 // 2. If handler is null, throw a TypeError exception. | |
8490 // 3. Assert: Type(handler) is Object. | |
8491 if (proxy->IsRevoked()) { | |
8492 isolate->Throw(*isolate->factory()->NewTypeError( | |
8493 MessageTemplate::kProxyRevoked, isolate->factory()->ownKeys_string())); | |
8494 return Nothing<bool>(); | |
8495 } | |
8496 // 4. Let target be the value of the [[ProxyTarget]] internal slot of O. | |
8497 Handle<JSReceiver> target(proxy->target(), isolate); | |
8498 // 5. Let trap be ? GetMethod(handler, "ownKeys"). | |
8499 Handle<Object> trap; | |
8500 ASSIGN_RETURN_ON_EXCEPTION_VALUE( | |
8501 isolate, trap, Object::GetMethod(Handle<JSReceiver>::cast(handler), | |
8502 isolate->factory()->ownKeys_string()), | |
8503 Nothing<bool>()); | |
8504 // 6. If trap is undefined, then | |
8505 if (trap->IsUndefined()) { | |
8506 // 6a. Return target.[[OwnPropertyKeys]](). | |
8507 return GetKeys_Internal(isolate, receiver, target, OWN_ONLY, filter, | |
8508 accumulator); | |
8509 } | |
8510 // 7. Let trapResultArray be Call(trap, handler, «target»). | |
8511 Handle<Object> trap_result_array; | |
8512 Handle<Object> args[] = {target}; | |
8513 ASSIGN_RETURN_ON_EXCEPTION_VALUE( | |
8514 isolate, trap_result_array, | |
8515 Execution::Call(isolate, trap, handler, arraysize(args), args), | |
8516 Nothing<bool>()); | |
8517 // 8. Let trapResult be ? CreateListFromArrayLike(trapResultArray, | |
8518 // «String, Symbol»). | |
8519 Handle<FixedArray> trap_result; | |
8520 ASSIGN_RETURN_ON_EXCEPTION_VALUE( | |
8521 isolate, trap_result, | |
8522 Object::CreateListFromArrayLike(isolate, trap_result_array, | |
8523 ElementTypes::kStringAndSymbol), | |
8524 Nothing<bool>()); | |
8525 // 9. Let extensibleTarget be ? IsExtensible(target). | |
8526 Maybe<bool> maybe_extensible = JSReceiver::IsExtensible(target); | |
8527 MAYBE_RETURN(maybe_extensible, Nothing<bool>()); | |
8528 bool extensible_target = maybe_extensible.FromJust(); | |
8529 // 10. Let targetKeys be ? target.[[OwnPropertyKeys]](). | |
8530 Handle<FixedArray> target_keys; | |
8531 ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, target_keys, | |
8532 JSReceiver::OwnPropertyKeys(target), | |
8533 Nothing<bool>()); | |
8534 // 11. (Assert) | |
8535 // 12. Let targetConfigurableKeys be an empty List. | |
8536 // To save memory, we're re-using target_keys and will modify it in-place. | |
8537 Handle<FixedArray> target_configurable_keys = target_keys; | |
8538 // 13. Let targetNonconfigurableKeys be an empty List. | |
8539 Handle<FixedArray> target_nonconfigurable_keys = | |
8540 isolate->factory()->NewFixedArray(target_keys->length()); | |
8541 int nonconfigurable_keys_length = 0; | |
8542 // 14. Repeat, for each element key of targetKeys: | |
8543 for (int i = 0; i < target_keys->length(); ++i) { | |
8544 // 14a. Let desc be ? target.[[GetOwnProperty]](key). | |
8545 PropertyDescriptor desc; | |
8546 Maybe<bool> found = JSReceiver::GetOwnPropertyDescriptor( | |
8547 isolate, target, handle(target_keys->get(i), isolate), &desc); | |
8548 MAYBE_RETURN(found, Nothing<bool>()); | |
8549 // 14b. If desc is not undefined and desc.[[Configurable]] is false, then | |
8550 if (found.FromJust() && !desc.configurable()) { | |
8551 // 14b i. Append key as an element of targetNonconfigurableKeys. | |
8552 target_nonconfigurable_keys->set(nonconfigurable_keys_length, | |
8553 target_keys->get(i)); | |
8554 nonconfigurable_keys_length++; | |
8555 // The key was moved, null it out in the original list. | |
8556 target_keys->set(i, Smi::FromInt(0)); | |
8557 } else { | |
8558 // 14c. Else, | |
8559 // 14c i. Append key as an element of targetConfigurableKeys. | |
8560 // (No-op, just keep it in |target_keys|.) | |
8561 } | |
8562 } | |
8563 accumulator->NextPrototype(); // Prepare for accumulating keys. | |
8564 // 15. If extensibleTarget is true and targetNonconfigurableKeys is empty, | |
8565 // then: | |
8566 if (extensible_target && nonconfigurable_keys_length == 0) { | |
8567 // 15a. Return trapResult. | |
8568 return accumulator->AddKeysFromProxy(proxy, trap_result); | |
8569 } | |
8570 // 16. Let uncheckedResultKeys be a new List which is a copy of trapResult. | |
8571 Zone set_zone(isolate->allocator()); | |
8572 const int kPresent = 1; | |
8573 const int kGone = 0; | |
8574 IdentityMap<int> unchecked_result_keys(isolate->heap(), &set_zone); | |
8575 int unchecked_result_keys_size = 0; | |
8576 for (int i = 0; i < trap_result->length(); ++i) { | |
8577 DCHECK(trap_result->get(i)->IsUniqueName()); | |
8578 Object* key = trap_result->get(i); | |
8579 int* entry = unchecked_result_keys.Get(key); | |
8580 if (*entry != kPresent) { | |
8581 *entry = kPresent; | |
8582 unchecked_result_keys_size++; | |
8583 } | |
8584 } | |
8585 // 17. Repeat, for each key that is an element of targetNonconfigurableKeys: | |
8586 for (int i = 0; i < nonconfigurable_keys_length; ++i) { | |
8587 Object* key = target_nonconfigurable_keys->get(i); | |
8588 // 17a. If key is not an element of uncheckedResultKeys, throw a | |
8589 // TypeError exception. | |
8590 int* found = unchecked_result_keys.Find(key); | |
8591 if (found == nullptr || *found == kGone) { | |
8592 isolate->Throw(*isolate->factory()->NewTypeError( | |
8593 MessageTemplate::kProxyOwnKeysMissing, handle(key, isolate))); | |
8594 return Nothing<bool>(); | |
8595 } | |
8596 // 17b. Remove key from uncheckedResultKeys. | |
8597 *found = kGone; | |
8598 unchecked_result_keys_size--; | |
8599 } | |
8600 // 18. If extensibleTarget is true, return trapResult. | |
8601 if (extensible_target) { | |
8602 return accumulator->AddKeysFromProxy(proxy, trap_result); | |
8603 } | |
8604 // 19. Repeat, for each key that is an element of targetConfigurableKeys: | |
8605 for (int i = 0; i < target_configurable_keys->length(); ++i) { | |
8606 Object* key = target_configurable_keys->get(i); | |
8607 if (key->IsSmi()) continue; // Zapped entry, was nonconfigurable. | |
8608 // 19a. If key is not an element of uncheckedResultKeys, throw a | |
8609 // TypeError exception. | |
8610 int* found = unchecked_result_keys.Find(key); | |
8611 if (found == nullptr || *found == kGone) { | |
8612 isolate->Throw(*isolate->factory()->NewTypeError( | |
8613 MessageTemplate::kProxyOwnKeysMissing, handle(key, isolate))); | |
8614 return Nothing<bool>(); | |
8615 } | |
8616 // 19b. Remove key from uncheckedResultKeys. | |
8617 *found = kGone; | |
8618 unchecked_result_keys_size--; | |
8619 } | |
8620 // 20. If uncheckedResultKeys is not empty, throw a TypeError exception. | |
8621 if (unchecked_result_keys_size != 0) { | |
8622 DCHECK_GT(unchecked_result_keys_size, 0); | |
8623 isolate->Throw(*isolate->factory()->NewTypeError( | |
8624 MessageTemplate::kProxyOwnKeysNonExtensible)); | |
8625 return Nothing<bool>(); | |
8626 } | |
8627 // 21. Return trapResult. | |
8628 return accumulator->AddKeysFromProxy(proxy, trap_result); | |
8629 } | |
8630 | |
8631 MaybeHandle<FixedArray> JSReceiver::GetKeys(Handle<JSReceiver> object, | 8215 MaybeHandle<FixedArray> JSReceiver::GetKeys(Handle<JSReceiver> object, |
8632 KeyCollectionType type, | 8216 KeyCollectionType type, |
8633 PropertyFilter filter, | 8217 PropertyFilter filter, |
8634 GetKeysConversion keys_conversion, | 8218 GetKeysConversion keys_conversion, |
8635 bool filter_proxy_keys) { | 8219 bool filter_proxy_keys) { |
8636 USE(ContainsOnlyValidKeys); | 8220 USE(ContainsOnlyValidKeys); |
8637 Isolate* isolate = object->GetIsolate(); | 8221 Isolate* isolate = object->GetIsolate(); |
8638 KeyAccumulator accumulator(isolate, type, filter); | 8222 KeyAccumulator accumulator(isolate, type, filter); |
8639 accumulator.set_filter_proxy_keys(filter_proxy_keys); | 8223 accumulator.set_filter_proxy_keys(filter_proxy_keys); |
8640 MAYBE_RETURN( | 8224 MAYBE_RETURN(accumulator.GetKeys_Internal(object, object, type), |
8641 GetKeys_Internal(isolate, object, object, type, filter, &accumulator), | 8225 MaybeHandle<FixedArray>()); |
8642 MaybeHandle<FixedArray>()); | |
8643 Handle<FixedArray> keys = accumulator.GetKeys(keys_conversion); | 8226 Handle<FixedArray> keys = accumulator.GetKeys(keys_conversion); |
8644 DCHECK(ContainsOnlyValidKeys(keys)); | 8227 DCHECK(ContainsOnlyValidKeys(keys)); |
8645 return keys; | 8228 return keys; |
8646 } | 8229 } |
8647 | 8230 |
8648 MUST_USE_RESULT Maybe<bool> FastGetOwnValuesOrEntries( | 8231 MUST_USE_RESULT Maybe<bool> FastGetOwnValuesOrEntries( |
8649 Isolate* isolate, Handle<JSReceiver> receiver, bool get_entries, | 8232 Isolate* isolate, Handle<JSReceiver> receiver, bool get_entries, |
8650 Handle<FixedArray>* result) { | 8233 Handle<FixedArray>* result) { |
8651 Handle<Map> map(JSReceiver::cast(*receiver)->map(), isolate); | 8234 Handle<Map> map(JSReceiver::cast(*receiver)->map(), isolate); |
8652 | 8235 |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8729 if (filter == ENUMERABLE_STRINGS) { | 8312 if (filter == ENUMERABLE_STRINGS) { |
8730 Maybe<bool> fast_values_or_entries = FastGetOwnValuesOrEntries( | 8313 Maybe<bool> fast_values_or_entries = FastGetOwnValuesOrEntries( |
8731 isolate, object, get_entries, &values_or_entries); | 8314 isolate, object, get_entries, &values_or_entries); |
8732 if (fast_values_or_entries.IsNothing()) return MaybeHandle<FixedArray>(); | 8315 if (fast_values_or_entries.IsNothing()) return MaybeHandle<FixedArray>(); |
8733 if (fast_values_or_entries.FromJust()) return values_or_entries; | 8316 if (fast_values_or_entries.FromJust()) return values_or_entries; |
8734 } | 8317 } |
8735 | 8318 |
8736 PropertyFilter key_filter = | 8319 PropertyFilter key_filter = |
8737 static_cast<PropertyFilter>(filter & ~ONLY_ENUMERABLE); | 8320 static_cast<PropertyFilter>(filter & ~ONLY_ENUMERABLE); |
8738 KeyAccumulator accumulator(isolate, OWN_ONLY, key_filter); | 8321 KeyAccumulator accumulator(isolate, OWN_ONLY, key_filter); |
8739 MAYBE_RETURN(GetKeys_Internal(isolate, object, object, OWN_ONLY, key_filter, | 8322 MAYBE_RETURN(accumulator.GetKeys_Internal(object, object, OWN_ONLY), |
8740 &accumulator), | |
8741 MaybeHandle<FixedArray>()); | 8323 MaybeHandle<FixedArray>()); |
8742 Handle<FixedArray> keys = accumulator.GetKeys(CONVERT_TO_STRING); | 8324 Handle<FixedArray> keys = accumulator.GetKeys(CONVERT_TO_STRING); |
8743 DCHECK(ContainsOnlyValidKeys(keys)); | 8325 DCHECK(ContainsOnlyValidKeys(keys)); |
8744 | 8326 |
8745 values_or_entries = isolate->factory()->NewFixedArray(keys->length()); | 8327 values_or_entries = isolate->factory()->NewFixedArray(keys->length()); |
8746 int length = 0; | 8328 int length = 0; |
8747 | 8329 |
8748 for (int i = 0; i < keys->length(); ++i) { | 8330 for (int i = 0; i < keys->length(); ++i) { |
8749 Handle<Name> key = Handle<Name>::cast(handle(keys->get(i), isolate)); | 8331 Handle<Name> key = Handle<Name>::cast(handle(keys->get(i), isolate)); |
8750 | 8332 |
(...skipping 6056 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
14807 from_javascript, should_throw); | 14389 from_javascript, should_throw); |
14808 } | 14390 } |
14809 | 14391 |
14810 | 14392 |
14811 // ES6: 9.5.2 [[SetPrototypeOf]] (V) | 14393 // ES6: 9.5.2 [[SetPrototypeOf]] (V) |
14812 // static | 14394 // static |
14813 Maybe<bool> JSProxy::SetPrototype(Handle<JSProxy> proxy, Handle<Object> value, | 14395 Maybe<bool> JSProxy::SetPrototype(Handle<JSProxy> proxy, Handle<Object> value, |
14814 bool from_javascript, | 14396 bool from_javascript, |
14815 ShouldThrow should_throw) { | 14397 ShouldThrow should_throw) { |
14816 Isolate* isolate = proxy->GetIsolate(); | 14398 Isolate* isolate = proxy->GetIsolate(); |
14817 STACK_CHECK(Nothing<bool>()); | 14399 STACK_CHECK(isolate, Nothing<bool>()); |
14818 Handle<Name> trap_name = isolate->factory()->setPrototypeOf_string(); | 14400 Handle<Name> trap_name = isolate->factory()->setPrototypeOf_string(); |
14819 // 1. Assert: Either Type(V) is Object or Type(V) is Null. | 14401 // 1. Assert: Either Type(V) is Object or Type(V) is Null. |
14820 DCHECK(value->IsJSReceiver() || value->IsNull()); | 14402 DCHECK(value->IsJSReceiver() || value->IsNull()); |
14821 // 2. Let handler be the value of the [[ProxyHandler]] internal slot of O. | 14403 // 2. Let handler be the value of the [[ProxyHandler]] internal slot of O. |
14822 Handle<Object> handler(proxy->handler(), isolate); | 14404 Handle<Object> handler(proxy->handler(), isolate); |
14823 // 3. If handler is null, throw a TypeError exception. | 14405 // 3. If handler is null, throw a TypeError exception. |
14824 // 4. Assert: Type(handler) is Object. | 14406 // 4. Assert: Type(handler) is Object. |
14825 if (proxy->IsRevoked()) { | 14407 if (proxy->IsRevoked()) { |
14826 isolate->Throw(*isolate->factory()->NewTypeError( | 14408 isolate->Throw(*isolate->factory()->NewTypeError( |
14827 MessageTemplate::kProxyRevoked, trap_name)); | 14409 MessageTemplate::kProxyRevoked, trap_name)); |
(...skipping 830 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
15658 j++ < len) { | 15240 j++ < len) { |
15659 SwapPairs(numbers, i, p); | 15241 SwapPairs(numbers, i, p); |
15660 } | 15242 } |
15661 } | 15243 } |
15662 } else { | 15244 } else { |
15663 HeapSortPairs(this, numbers, len); | 15245 HeapSortPairs(this, numbers, len); |
15664 return; | 15246 return; |
15665 } | 15247 } |
15666 } | 15248 } |
15667 | 15249 |
15668 void JSObject::CollectOwnPropertyNames(KeyAccumulator* keys, | |
15669 PropertyFilter filter) { | |
15670 if (HasFastProperties()) { | |
15671 int real_size = map()->NumberOfOwnDescriptors(); | |
15672 Handle<DescriptorArray> descs(map()->instance_descriptors()); | |
15673 for (int i = 0; i < real_size; i++) { | |
15674 PropertyDetails details = descs->GetDetails(i); | |
15675 if ((details.attributes() & filter) != 0) continue; | |
15676 if (filter & ONLY_ALL_CAN_READ) { | |
15677 if (details.kind() != kAccessor) continue; | |
15678 Object* accessors = descs->GetValue(i); | |
15679 if (!accessors->IsAccessorInfo()) continue; | |
15680 if (!AccessorInfo::cast(accessors)->all_can_read()) continue; | |
15681 } | |
15682 Name* key = descs->GetKey(i); | |
15683 if (key->FilterKey(filter)) continue; | |
15684 keys->AddKey(key, DO_NOT_CONVERT); | |
15685 } | |
15686 } else if (IsJSGlobalObject()) { | |
15687 GlobalDictionary::CollectKeysTo(handle(global_dictionary()), keys, filter); | |
15688 } else { | |
15689 NameDictionary::CollectKeysTo(handle(property_dictionary()), keys, filter); | |
15690 } | |
15691 } | |
15692 | |
15693 bool JSObject::WasConstructedFromApiFunction() { | 15250 bool JSObject::WasConstructedFromApiFunction() { |
15694 auto instance_type = map()->instance_type(); | 15251 auto instance_type = map()->instance_type(); |
15695 bool is_api_object = instance_type == JS_API_OBJECT_TYPE || | 15252 bool is_api_object = instance_type == JS_API_OBJECT_TYPE || |
15696 instance_type == JS_SPECIAL_API_OBJECT_TYPE; | 15253 instance_type == JS_SPECIAL_API_OBJECT_TYPE; |
15697 #ifdef ENABLE_SLOW_DCHECKS | 15254 #ifdef ENABLE_SLOW_DCHECKS |
15698 if (FLAG_enable_slow_asserts) { | 15255 if (FLAG_enable_slow_asserts) { |
15699 Object* maybe_constructor = map()->GetConstructor(); | 15256 Object* maybe_constructor = map()->GetConstructor(); |
15700 if (!maybe_constructor->IsJSFunction()) return false; | 15257 if (!maybe_constructor->IsJSFunction()) return false; |
15701 JSFunction* constructor = JSFunction::cast(maybe_constructor); | 15258 JSFunction* constructor = JSFunction::cast(maybe_constructor); |
15702 if (constructor->shared()->IsApiFunction()) { | 15259 if (constructor->shared()->IsApiFunction()) { |
15703 DCHECK(is_api_object); | 15260 DCHECK(is_api_object); |
15704 } else { | 15261 } else { |
15705 DCHECK(!is_api_object); | 15262 DCHECK(!is_api_object); |
15706 } | 15263 } |
15707 } | 15264 } |
15708 #endif | 15265 #endif |
15709 return is_api_object; | 15266 return is_api_object; |
15710 } | 15267 } |
15711 | 15268 |
15712 void JSObject::CollectOwnElementKeys(Handle<JSObject> object, | |
15713 KeyAccumulator* keys, | |
15714 PropertyFilter filter) { | |
15715 if (filter & SKIP_STRINGS) return; | |
15716 ElementsAccessor* accessor = object->GetElementsAccessor(); | |
15717 accessor->CollectElementIndices(object, keys, kMaxUInt32, filter, 0); | |
15718 } | |
15719 | |
15720 | |
15721 MaybeHandle<String> Object::ObjectProtoToString(Isolate* isolate, | 15269 MaybeHandle<String> Object::ObjectProtoToString(Isolate* isolate, |
15722 Handle<Object> object) { | 15270 Handle<Object> object) { |
15723 if (object->IsUndefined()) return isolate->factory()->undefined_to_string(); | 15271 if (object->IsUndefined()) return isolate->factory()->undefined_to_string(); |
15724 if (object->IsNull()) return isolate->factory()->null_to_string(); | 15272 if (object->IsNull()) return isolate->factory()->null_to_string(); |
15725 | 15273 |
15726 Handle<JSReceiver> receiver = | 15274 Handle<JSReceiver> receiver = |
15727 Object::ToObject(isolate, object).ToHandleChecked(); | 15275 Object::ToObject(isolate, object).ToHandleChecked(); |
15728 | 15276 |
15729 Handle<String> tag; | 15277 Handle<String> tag; |
15730 Handle<Object> to_string_tag; | 15278 Handle<Object> to_string_tag; |
(...skipping 832 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
16563 template Handle<NameDictionary> | 16111 template Handle<NameDictionary> |
16564 Dictionary<NameDictionary, NameDictionaryShape, Handle<Name> >:: | 16112 Dictionary<NameDictionary, NameDictionaryShape, Handle<Name> >:: |
16565 EnsureCapacity(Handle<NameDictionary>, int, Handle<Name>); | 16113 EnsureCapacity(Handle<NameDictionary>, int, Handle<Name>); |
16566 | 16114 |
16567 template int HashTable<SeededNumberDictionary, SeededNumberDictionaryShape, | 16115 template int HashTable<SeededNumberDictionary, SeededNumberDictionaryShape, |
16568 uint32_t>::FindEntry(uint32_t); | 16116 uint32_t>::FindEntry(uint32_t); |
16569 | 16117 |
16570 template int NameDictionaryBase<NameDictionary, NameDictionaryShape>::FindEntry( | 16118 template int NameDictionaryBase<NameDictionary, NameDictionaryShape>::FindEntry( |
16571 Handle<Name>); | 16119 Handle<Name>); |
16572 | 16120 |
| 16121 template int Dictionary<GlobalDictionary, GlobalDictionaryShape, Handle<Name>>:: |
| 16122 NumberOfElementsFilterAttributes(PropertyFilter filter); |
| 16123 |
| 16124 template int Dictionary<NameDictionary, NameDictionaryShape, Handle<Name>>:: |
| 16125 NumberOfElementsFilterAttributes(PropertyFilter filter); |
| 16126 |
| 16127 template void Dictionary<GlobalDictionary, GlobalDictionaryShape, |
| 16128 Handle<Name>>::CopyEnumKeysTo(FixedArray* storage); |
| 16129 |
| 16130 template void Dictionary<NameDictionary, NameDictionaryShape, |
| 16131 Handle<Name>>::CopyEnumKeysTo(FixedArray* storage); |
| 16132 |
| 16133 template void |
| 16134 Dictionary<GlobalDictionary, GlobalDictionaryShape, Handle<Name>>:: |
| 16135 CollectKeysTo(Handle<Dictionary<GlobalDictionary, GlobalDictionaryShape, |
| 16136 Handle<Name>>> |
| 16137 dictionary, |
| 16138 KeyAccumulator* keys, PropertyFilter filter); |
| 16139 |
| 16140 template void |
| 16141 Dictionary<NameDictionary, NameDictionaryShape, Handle<Name>>::CollectKeysTo( |
| 16142 Handle<Dictionary<NameDictionary, NameDictionaryShape, Handle<Name>>> |
| 16143 dictionary, |
| 16144 KeyAccumulator* keys, PropertyFilter filter); |
16573 | 16145 |
16574 Handle<Object> JSObject::PrepareSlowElementsForSort( | 16146 Handle<Object> JSObject::PrepareSlowElementsForSort( |
16575 Handle<JSObject> object, uint32_t limit) { | 16147 Handle<JSObject> object, uint32_t limit) { |
16576 DCHECK(object->HasDictionaryElements()); | 16148 DCHECK(object->HasDictionaryElements()); |
16577 Isolate* isolate = object->GetIsolate(); | 16149 Isolate* isolate = object->GetIsolate(); |
16578 // Must stay in dictionary mode, either because of requires_slow_elements, | 16150 // Must stay in dictionary mode, either because of requires_slow_elements, |
16579 // or because we are not going to sort (and therefore compact) all of the | 16151 // or because we are not going to sort (and therefore compact) all of the |
16580 // elements. | 16152 // elements. |
16581 Handle<SeededNumberDictionary> dict(object->element_dictionary(), isolate); | 16153 Handle<SeededNumberDictionary> dict(object->element_dictionary(), isolate); |
16582 Handle<SeededNumberDictionary> new_dict = | 16154 Handle<SeededNumberDictionary> new_dict = |
(...skipping 2249 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
18832 if (cell->value() != *new_value) { | 18404 if (cell->value() != *new_value) { |
18833 cell->set_value(*new_value); | 18405 cell->set_value(*new_value); |
18834 Isolate* isolate = cell->GetIsolate(); | 18406 Isolate* isolate = cell->GetIsolate(); |
18835 cell->dependent_code()->DeoptimizeDependentCodeGroup( | 18407 cell->dependent_code()->DeoptimizeDependentCodeGroup( |
18836 isolate, DependentCode::kPropertyCellChangedGroup); | 18408 isolate, DependentCode::kPropertyCellChangedGroup); |
18837 } | 18409 } |
18838 } | 18410 } |
18839 | 18411 |
18840 } // namespace internal | 18412 } // namespace internal |
18841 } // namespace v8 | 18413 } // namespace v8 |
OLD | NEW |