| 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 |