OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/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 768 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
779 return Object::GetProperty(&it, language_mode); | 779 return Object::GetProperty(&it, language_mode); |
780 } | 780 } |
781 // 8. Let trapResult be ? Call(trap, handler, «target, P, Receiver»). | 781 // 8. Let trapResult be ? Call(trap, handler, «target, P, Receiver»). |
782 Handle<Object> trap_result; | 782 Handle<Object> trap_result; |
783 Handle<Object> args[] = {target, name, receiver}; | 783 Handle<Object> args[] = {target, name, receiver}; |
784 ASSIGN_RETURN_ON_EXCEPTION( | 784 ASSIGN_RETURN_ON_EXCEPTION( |
785 isolate, trap_result, | 785 isolate, trap_result, |
786 Execution::Call(isolate, trap, handler, arraysize(args), args), Object); | 786 Execution::Call(isolate, trap, handler, arraysize(args), args), Object); |
787 // 9. Let targetDesc be ? target.[[GetOwnProperty]](P). | 787 // 9. Let targetDesc be ? target.[[GetOwnProperty]](P). |
788 PropertyDescriptor target_desc; | 788 PropertyDescriptor target_desc; |
789 bool target_found = | 789 Maybe<bool> target_found = |
790 JSReceiver::GetOwnPropertyDescriptor(isolate, target, name, &target_desc); | 790 JSReceiver::GetOwnPropertyDescriptor(isolate, target, name, &target_desc); |
791 if (isolate->has_pending_exception()) return MaybeHandle<Object>(); | 791 MAYBE_RETURN_NULL(target_found); |
792 // 10. If targetDesc is not undefined, then | 792 // 10. If targetDesc is not undefined, then |
793 if (target_found) { | 793 if (target_found.FromJust()) { |
794 // 10.a. If IsDataDescriptor(targetDesc) and targetDesc.[[Configurable]] is | 794 // 10.a. If IsDataDescriptor(targetDesc) and targetDesc.[[Configurable]] is |
795 // false and targetDesc.[[Writable]] is false, then | 795 // false and targetDesc.[[Writable]] is false, then |
796 // 10.a.i. If SameValue(trapResult, targetDesc.[[Value]]) is false, | 796 // 10.a.i. If SameValue(trapResult, targetDesc.[[Value]]) is false, |
797 // throw a TypeError exception. | 797 // throw a TypeError exception. |
798 bool inconsistent = PropertyDescriptor::IsDataDescriptor(&target_desc) && | 798 bool inconsistent = PropertyDescriptor::IsDataDescriptor(&target_desc) && |
799 !target_desc.configurable() && | 799 !target_desc.configurable() && |
800 !target_desc.writable() && | 800 !target_desc.writable() && |
801 !trap_result->SameValue(*target_desc.value()); | 801 !trap_result->SameValue(*target_desc.value()); |
802 // 10.b. If IsAccessorDescriptor(targetDesc) and targetDesc.[[Configurable]] | 802 // 10.b. If IsAccessorDescriptor(targetDesc) and targetDesc.[[Configurable]] |
803 // is false and targetDesc.[[Get]] is undefined, then | 803 // is false and targetDesc.[[Get]] is undefined, then |
(...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
985 Execution::Call(isolate, trap, handler, arraysize(argv), argv), Object); | 985 Execution::Call(isolate, trap, handler, arraysize(argv), argv), Object); |
986 // 8. If Type(handlerProto) is neither Object nor Null, throw a TypeError. | 986 // 8. If Type(handlerProto) is neither Object nor Null, throw a TypeError. |
987 if (!(handler_proto->IsJSReceiver() || handler_proto->IsNull())) { | 987 if (!(handler_proto->IsJSReceiver() || handler_proto->IsNull())) { |
988 THROW_NEW_ERROR(isolate, | 988 THROW_NEW_ERROR(isolate, |
989 NewTypeError(MessageTemplate::kProxyHandlerTrapMissing, | 989 NewTypeError(MessageTemplate::kProxyHandlerTrapMissing, |
990 handler, trap_name), | 990 handler, trap_name), |
991 Object); | 991 Object); |
992 } | 992 } |
993 // 9. Let extensibleTarget be ? IsExtensible(target). | 993 // 9. Let extensibleTarget be ? IsExtensible(target). |
994 Maybe<bool> is_extensible = JSReceiver::IsExtensible(target); | 994 Maybe<bool> is_extensible = JSReceiver::IsExtensible(target); |
995 if (is_extensible.IsNothing()) return MaybeHandle<Object>(); | 995 MAYBE_RETURN_NULL(is_extensible); |
996 // 10. If extensibleTarget is true, return handlerProto. | 996 // 10. If extensibleTarget is true, return handlerProto. |
997 if (is_extensible.FromJust()) return handler_proto; | 997 if (is_extensible.FromJust()) return handler_proto; |
998 // 11. Let targetProto be ? target.[[GetPrototypeOf]](). | 998 // 11. Let targetProto be ? target.[[GetPrototypeOf]](). |
999 Handle<Object> target_proto; | 999 Handle<Object> target_proto; |
1000 ASSIGN_RETURN_ON_EXCEPTION(isolate, target_proto, | 1000 ASSIGN_RETURN_ON_EXCEPTION(isolate, target_proto, |
1001 Object::GetPrototype(isolate, target), Object); | 1001 Object::GetPrototype(isolate, target), Object); |
1002 // 12. If SameValue(handlerProto, targetProto) is false, throw a TypeError. | 1002 // 12. If SameValue(handlerProto, targetProto) is false, throw a TypeError. |
1003 if (!handler_proto->SameValue(*target_proto)) { | 1003 if (!handler_proto->SameValue(*target_proto)) { |
1004 THROW_NEW_ERROR(isolate, | 1004 THROW_NEW_ERROR(isolate, |
1005 NewTypeError(MessageTemplate::kProxyHandlerTrapMissing, | 1005 NewTypeError(MessageTemplate::kProxyHandlerTrapMissing, |
(...skipping 2988 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3994 PropertyDetails details = own_lookup.property_details(); | 3994 PropertyDetails details = own_lookup.property_details(); |
3995 if (details.IsReadOnly()) { | 3995 if (details.IsReadOnly()) { |
3996 return WriteToReadOnlyProperty(&own_lookup, value, should_throw); | 3996 return WriteToReadOnlyProperty(&own_lookup, value, should_throw); |
3997 } | 3997 } |
3998 return SetDataProperty(&own_lookup, value); | 3998 return SetDataProperty(&own_lookup, value); |
3999 } | 3999 } |
4000 | 4000 |
4001 case LookupIterator::INTERCEPTOR: | 4001 case LookupIterator::INTERCEPTOR: |
4002 case LookupIterator::JSPROXY: { | 4002 case LookupIterator::JSPROXY: { |
4003 PropertyDescriptor desc; | 4003 PropertyDescriptor desc; |
4004 bool owned = JSReceiver::GetOwnPropertyDescriptor(&own_lookup, &desc); | 4004 Maybe<bool> owned = |
4005 if (isolate->has_pending_exception()) return Nothing<bool>(); | 4005 JSReceiver::GetOwnPropertyDescriptor(&own_lookup, &desc); |
4006 if (!owned) { | 4006 MAYBE_RETURN(owned, Nothing<bool>()); |
| 4007 if (!owned.FromJust()) { |
4007 return JSReceiver::CreateDataProperty(&own_lookup, value, | 4008 return JSReceiver::CreateDataProperty(&own_lookup, value, |
4008 should_throw); | 4009 should_throw); |
4009 } | 4010 } |
4010 if (PropertyDescriptor::IsAccessorDescriptor(&desc) || | 4011 if (PropertyDescriptor::IsAccessorDescriptor(&desc) || |
4011 !desc.writable()) { | 4012 !desc.writable()) { |
4012 return RedefineIncompatibleProperty(isolate, it->GetName(), value, | 4013 return RedefineIncompatibleProperty(isolate, it->GetName(), value, |
4013 should_throw); | 4014 should_throw); |
4014 } | 4015 } |
4015 | 4016 |
4016 PropertyDescriptor value_desc; | 4017 PropertyDescriptor value_desc; |
4017 value_desc.set_value(value); | 4018 value_desc.set_value(value); |
4018 bool result = JSReceiver::DefineOwnProperty( | 4019 return JSReceiver::DefineOwnProperty(isolate, receiver, it->GetName(), |
4019 isolate, receiver, it->GetName(), &value_desc, should_throw); | 4020 &value_desc, should_throw); |
4020 if (isolate->has_pending_exception()) return Nothing<bool>(); | |
4021 return Just(result); | |
4022 } | 4021 } |
4023 | 4022 |
4024 case LookupIterator::NOT_FOUND: | 4023 case LookupIterator::NOT_FOUND: |
4025 case LookupIterator::TRANSITION: | 4024 case LookupIterator::TRANSITION: |
4026 UNREACHABLE(); | 4025 UNREACHABLE(); |
4027 } | 4026 } |
4028 } | 4027 } |
4029 | 4028 |
4030 return JSObject::AddDataProperty(&own_lookup, value, NONE, should_throw, | 4029 return JSObject::AddDataProperty(&own_lookup, value, NONE, should_throw, |
4031 store_mode); | 4030 store_mode); |
(...skipping 623 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4655 Handle<Object> args[] = {target, name}; | 4654 Handle<Object> args[] = {target, name}; |
4656 ASSIGN_RETURN_ON_EXCEPTION_VALUE( | 4655 ASSIGN_RETURN_ON_EXCEPTION_VALUE( |
4657 isolate, trap_result_obj, | 4656 isolate, trap_result_obj, |
4658 Execution::Call(isolate, trap, handler, arraysize(args), args), | 4657 Execution::Call(isolate, trap, handler, arraysize(args), args), |
4659 Nothing<bool>()); | 4658 Nothing<bool>()); |
4660 bool boolean_trap_result = trap_result_obj->BooleanValue(); | 4659 bool boolean_trap_result = trap_result_obj->BooleanValue(); |
4661 // 9. If booleanTrapResult is false, then: | 4660 // 9. If booleanTrapResult is false, then: |
4662 if (!boolean_trap_result) { | 4661 if (!boolean_trap_result) { |
4663 // 9a. Let targetDesc be ? target.[[GetOwnProperty]](P). | 4662 // 9a. Let targetDesc be ? target.[[GetOwnProperty]](P). |
4664 PropertyDescriptor target_desc; | 4663 PropertyDescriptor target_desc; |
4665 bool target_found = JSReceiver::GetOwnPropertyDescriptor( | 4664 Maybe<bool> target_found = JSReceiver::GetOwnPropertyDescriptor( |
4666 isolate, target, name, &target_desc); | 4665 isolate, target, name, &target_desc); |
| 4666 MAYBE_RETURN(target_found, Nothing<bool>()); |
4667 // 9b. If targetDesc is not undefined, then: | 4667 // 9b. If targetDesc is not undefined, then: |
4668 if (target_found) { | 4668 if (target_found.FromJust()) { |
4669 // 9b i. If targetDesc.[[Configurable]] is false, throw a TypeError | 4669 // 9b i. If targetDesc.[[Configurable]] is false, throw a TypeError |
4670 // exception. | 4670 // exception. |
4671 if (!target_desc.configurable()) { | 4671 if (!target_desc.configurable()) { |
4672 isolate->Throw(*isolate->factory()->NewTypeError( | 4672 isolate->Throw(*isolate->factory()->NewTypeError( |
4673 MessageTemplate::kProxyTargetPropNotConfigurable, name)); | 4673 MessageTemplate::kProxyTargetPropNotConfigurable, name)); |
4674 return Nothing<bool>(); | 4674 return Nothing<bool>(); |
4675 } | 4675 } |
4676 // 9b ii. Let extensibleTarget be ? IsExtensible(target). | 4676 // 9b ii. Let extensibleTarget be ? IsExtensible(target). |
4677 Maybe<bool> maybe_extensible = JSReceiver::IsExtensible(target); | 4677 Maybe<bool> extensible_target = JSReceiver::IsExtensible(target); |
4678 if (maybe_extensible.IsNothing()) return maybe_extensible; | 4678 MAYBE_RETURN(extensible_target, Nothing<bool>()); |
4679 bool extensible_target = maybe_extensible.FromJust(); | |
4680 // 9b iii. If extensibleTarget is false, throw a TypeError exception. | 4679 // 9b iii. If extensibleTarget is false, throw a TypeError exception. |
4681 if (!extensible_target) { | 4680 if (!extensible_target.FromJust()) { |
4682 isolate->Throw(*isolate->factory()->NewTypeError( | 4681 isolate->Throw(*isolate->factory()->NewTypeError( |
4683 MessageTemplate::kProxyTargetNotExtensible)); | 4682 MessageTemplate::kProxyTargetNotExtensible)); |
4684 return Nothing<bool>(); | 4683 return Nothing<bool>(); |
4685 } | 4684 } |
4686 } | 4685 } |
4687 } | 4686 } |
4688 // 10. Return booleanTrapResult. | 4687 // 10. Return booleanTrapResult. |
4689 return Just(boolean_trap_result); | 4688 return Just(boolean_trap_result); |
4690 } | 4689 } |
4691 | 4690 |
4692 | 4691 |
4693 Maybe<bool> JSProxy::SetProperty(Handle<JSProxy> proxy, Handle<Name> name, | 4692 Maybe<bool> JSProxy::SetProperty(Handle<JSProxy> proxy, Handle<Name> name, |
4694 Handle<Object> value, Handle<Object> receiver, | 4693 Handle<Object> value, Handle<Object> receiver, |
4695 LanguageMode language_mode) { | 4694 LanguageMode language_mode) { |
4696 Isolate* isolate = proxy->GetIsolate(); | 4695 Isolate* isolate = proxy->GetIsolate(); |
4697 Factory* factory = isolate->factory(); | 4696 Factory* factory = isolate->factory(); |
4698 Handle<String> trap_name = factory->set_string(); | 4697 Handle<String> trap_name = factory->set_string(); |
4699 ShouldThrow should_throw = | 4698 ShouldThrow should_throw = |
4700 is_sloppy(language_mode) ? DONT_THROW : THROW_ON_ERROR; | 4699 is_sloppy(language_mode) ? DONT_THROW : THROW_ON_ERROR; |
4701 | 4700 |
4702 if (proxy->IsRevoked()) { | 4701 if (proxy->IsRevoked()) { |
4703 isolate->Throw( | 4702 isolate->Throw( |
4704 *factory->NewTypeError(MessageTemplate::kProxyRevoked, trap_name)); | 4703 *factory->NewTypeError(MessageTemplate::kProxyRevoked, trap_name)); |
4705 return Nothing<bool>(); | 4704 return Nothing<bool>(); |
4706 } | 4705 } |
4707 Handle<JSReceiver> target(proxy->target(), isolate); | 4706 Handle<JSReceiver> target(proxy->target(), isolate); |
4708 Handle<JSReceiver> handler(JSReceiver::cast(proxy->handler()), isolate); | 4707 Handle<JSReceiver> handler(JSReceiver::cast(proxy->handler()), isolate); |
4709 | 4708 |
4710 Handle<Object> trap; | 4709 Handle<Object> trap; |
4711 ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, trap, GetTrap(proxy, trap_name), | 4710 ASSIGN_RETURN_ON_EXCEPTION_VALUE( |
4712 Nothing<bool>()); | 4711 isolate, trap, Object::GetMethod(handler, trap_name), Nothing<bool>()); |
4713 if (trap->IsUndefined()) { | 4712 if (trap->IsUndefined()) { |
4714 LookupIterator it = | 4713 LookupIterator it = |
4715 LookupIterator::PropertyOrElement(isolate, receiver, name, target); | 4714 LookupIterator::PropertyOrElement(isolate, receiver, name, target); |
4716 return Object::SetSuperProperty(&it, value, language_mode, | 4715 return Object::SetSuperProperty(&it, value, language_mode, |
4717 Object::MAY_BE_STORE_FROM_KEYED); | 4716 Object::MAY_BE_STORE_FROM_KEYED); |
4718 } | 4717 } |
4719 | 4718 |
4720 Handle<Object> trap_result; | 4719 Handle<Object> trap_result; |
4721 Handle<Object> args[] = {target, name, value, receiver}; | 4720 Handle<Object> args[] = {target, name, value, receiver}; |
4722 ASSIGN_RETURN_ON_EXCEPTION_VALUE( | 4721 ASSIGN_RETURN_ON_EXCEPTION_VALUE( |
4723 isolate, trap_result, | 4722 isolate, trap_result, |
4724 Execution::Call(isolate, trap, handler, arraysize(args), args), | 4723 Execution::Call(isolate, trap, handler, arraysize(args), args), |
4725 Nothing<bool>()); | 4724 Nothing<bool>()); |
4726 if (!trap_result->BooleanValue()) { | 4725 if (!trap_result->BooleanValue()) { |
4727 RETURN_FAILURE(isolate, should_throw, | 4726 RETURN_FAILURE(isolate, should_throw, |
4728 NewTypeError(MessageTemplate::kProxyHandlerReturned, handler, | 4727 NewTypeError(MessageTemplate::kProxyHandlerReturned, handler, |
4729 factory->false_string(), trap_name)); | 4728 factory->false_string(), trap_name)); |
4730 } | 4729 } |
4731 | 4730 |
4732 // Enforce the invariant. | 4731 // Enforce the invariant. |
4733 PropertyDescriptor target_desc; | 4732 PropertyDescriptor target_desc; |
4734 bool owned = | 4733 Maybe<bool> owned = |
4735 JSReceiver::GetOwnPropertyDescriptor(isolate, target, name, &target_desc); | 4734 JSReceiver::GetOwnPropertyDescriptor(isolate, target, name, &target_desc); |
4736 if (isolate->has_pending_exception()) return Nothing<bool>(); | 4735 MAYBE_RETURN(owned, Nothing<bool>()); |
4737 if (owned) { | 4736 if (owned.FromJust()) { |
4738 bool inconsistent = | 4737 bool inconsistent = |
4739 (PropertyDescriptor::IsDataDescriptor(&target_desc) && | 4738 (PropertyDescriptor::IsDataDescriptor(&target_desc) && |
4740 !target_desc.configurable() && !target_desc.writable() && | 4739 !target_desc.configurable() && !target_desc.writable() && |
4741 !value->SameValue(*target_desc.value())) || | 4740 !value->SameValue(*target_desc.value())) || |
4742 (PropertyDescriptor::IsAccessorDescriptor(&target_desc) && | 4741 (PropertyDescriptor::IsAccessorDescriptor(&target_desc) && |
4743 !target_desc.configurable() && target_desc.set()->IsUndefined()); | 4742 !target_desc.configurable() && target_desc.set()->IsUndefined()); |
4744 if (inconsistent) { | 4743 if (inconsistent) { |
4745 isolate->Throw(*isolate->factory()->NewTypeError( | 4744 isolate->Throw(*isolate->factory()->NewTypeError( |
4746 MessageTemplate::kProxyTrapViolatesInvariant, trap_name)); | 4745 MessageTemplate::kProxyTrapViolatesInvariant, trap_name)); |
4747 return Nothing<bool>(); | 4746 return Nothing<bool>(); |
(...skipping 14 matching lines...) Expand all Loading... |
4762 | 4761 |
4763 if (proxy->IsRevoked()) { | 4762 if (proxy->IsRevoked()) { |
4764 isolate->Throw( | 4763 isolate->Throw( |
4765 *factory->NewTypeError(MessageTemplate::kProxyRevoked, trap_name)); | 4764 *factory->NewTypeError(MessageTemplate::kProxyRevoked, trap_name)); |
4766 return Nothing<bool>(); | 4765 return Nothing<bool>(); |
4767 } | 4766 } |
4768 Handle<JSReceiver> target(proxy->target(), isolate); | 4767 Handle<JSReceiver> target(proxy->target(), isolate); |
4769 Handle<JSReceiver> handler(JSReceiver::cast(proxy->handler()), isolate); | 4768 Handle<JSReceiver> handler(JSReceiver::cast(proxy->handler()), isolate); |
4770 | 4769 |
4771 Handle<Object> trap; | 4770 Handle<Object> trap; |
4772 ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, trap, GetTrap(proxy, trap_name), | 4771 ASSIGN_RETURN_ON_EXCEPTION_VALUE( |
4773 Nothing<bool>()); | 4772 isolate, trap, Object::GetMethod(handler, trap_name), Nothing<bool>()); |
4774 if (trap->IsUndefined()) { | 4773 if (trap->IsUndefined()) { |
4775 return JSReceiver::DeletePropertyOrElement(target, name, language_mode); | 4774 return JSReceiver::DeletePropertyOrElement(target, name, language_mode); |
4776 } | 4775 } |
4777 | 4776 |
4778 Handle<Object> trap_result; | 4777 Handle<Object> trap_result; |
4779 Handle<Object> args[] = {target, name}; | 4778 Handle<Object> args[] = {target, name}; |
4780 ASSIGN_RETURN_ON_EXCEPTION_VALUE( | 4779 ASSIGN_RETURN_ON_EXCEPTION_VALUE( |
4781 isolate, trap_result, | 4780 isolate, trap_result, |
4782 Execution::Call(isolate, trap, handler, arraysize(args), args), | 4781 Execution::Call(isolate, trap, handler, arraysize(args), args), |
4783 Nothing<bool>()); | 4782 Nothing<bool>()); |
4784 if (!trap_result->BooleanValue()) { | 4783 if (!trap_result->BooleanValue()) { |
4785 RETURN_FAILURE(isolate, should_throw, | 4784 RETURN_FAILURE(isolate, should_throw, |
4786 NewTypeError(MessageTemplate::kProxyHandlerReturned, handler, | 4785 NewTypeError(MessageTemplate::kProxyHandlerReturned, handler, |
4787 factory->false_string(), trap_name)); | 4786 factory->false_string(), trap_name)); |
4788 } | 4787 } |
4789 | 4788 |
4790 // Enforce the invariant. | 4789 // Enforce the invariant. |
4791 PropertyDescriptor target_desc; | 4790 PropertyDescriptor target_desc; |
4792 bool owned = | 4791 Maybe<bool> owned = |
4793 JSReceiver::GetOwnPropertyDescriptor(isolate, target, name, &target_desc); | 4792 JSReceiver::GetOwnPropertyDescriptor(isolate, target, name, &target_desc); |
4794 if (isolate->has_pending_exception()) return Nothing<bool>(); | 4793 MAYBE_RETURN(owned, Nothing<bool>()); |
4795 if (owned && !target_desc.configurable()) { | 4794 if (owned.FromJust() && !target_desc.configurable()) { |
4796 isolate->Throw(*factory->NewTypeError( | 4795 isolate->Throw(*factory->NewTypeError( |
4797 MessageTemplate::kProxyDeletePropertyViolatesInvariant, name)); | 4796 MessageTemplate::kProxyDeletePropertyViolatesInvariant, name)); |
4798 return Nothing<bool>(); | 4797 return Nothing<bool>(); |
4799 } | 4798 } |
4800 return Just(true); | 4799 return Just(true); |
4801 } | 4800 } |
4802 | 4801 |
4803 | 4802 |
4804 // static | 4803 // static |
4805 MaybeHandle<Context> JSProxy::GetFunctionRealm(Handle<JSProxy> proxy) { | 4804 MaybeHandle<Context> JSProxy::GetFunctionRealm(Handle<JSProxy> proxy) { |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4839 } | 4838 } |
4840 | 4839 |
4841 return JSObject::GetFunctionRealm(Handle<JSObject>::cast(receiver)); | 4840 return JSObject::GetFunctionRealm(Handle<JSObject>::cast(receiver)); |
4842 } | 4841 } |
4843 | 4842 |
4844 | 4843 |
4845 Maybe<PropertyAttributes> JSProxy::GetPropertyAttributes(LookupIterator* it) { | 4844 Maybe<PropertyAttributes> JSProxy::GetPropertyAttributes(LookupIterator* it) { |
4846 Isolate* isolate = it->isolate(); | 4845 Isolate* isolate = it->isolate(); |
4847 HandleScope scope(isolate); | 4846 HandleScope scope(isolate); |
4848 PropertyDescriptor desc; | 4847 PropertyDescriptor desc; |
4849 bool found = JSProxy::GetOwnPropertyDescriptor( | 4848 Maybe<bool> found = JSProxy::GetOwnPropertyDescriptor( |
4850 isolate, it->GetHolder<JSProxy>(), it->GetName(), &desc); | 4849 isolate, it->GetHolder<JSProxy>(), it->GetName(), &desc); |
4851 if (isolate->has_pending_exception()) return Nothing<PropertyAttributes>(); | 4850 MAYBE_RETURN(found, Nothing<PropertyAttributes>()); |
4852 if (!found) return Just(ABSENT); | 4851 if (!found.FromJust()) return Just(ABSENT); |
4853 return Just(desc.ToAttributes()); | 4852 return Just(desc.ToAttributes()); |
4854 } | 4853 } |
4855 | 4854 |
4856 | 4855 |
4857 MaybeHandle<Object> JSProxy::GetTrap(Handle<JSProxy> proxy, | |
4858 Handle<String> trap_name) { | |
4859 DCHECK(!proxy->IsRevoked()); | |
4860 Isolate* isolate = proxy->GetIsolate(); | |
4861 Handle<JSReceiver> handler(JSReceiver::cast(proxy->handler()), isolate); | |
4862 return Object::GetMethod(handler, trap_name); | |
4863 } | |
4864 | |
4865 | |
4866 void JSObject::AllocateStorageForMap(Handle<JSObject> object, Handle<Map> map) { | 4856 void JSObject::AllocateStorageForMap(Handle<JSObject> object, Handle<Map> map) { |
4867 DCHECK(object->map()->GetInObjectProperties() == | 4857 DCHECK(object->map()->GetInObjectProperties() == |
4868 map->GetInObjectProperties()); | 4858 map->GetInObjectProperties()); |
4869 ElementsKind obj_kind = object->map()->elements_kind(); | 4859 ElementsKind obj_kind = object->map()->elements_kind(); |
4870 ElementsKind map_kind = map->elements_kind(); | 4860 ElementsKind map_kind = map->elements_kind(); |
4871 if (map_kind != obj_kind) { | 4861 if (map_kind != obj_kind) { |
4872 ElementsKind to_kind = GetMoreGeneralElementsKind(map_kind, obj_kind); | 4862 ElementsKind to_kind = GetMoreGeneralElementsKind(map_kind, obj_kind); |
4873 if (IsDictionaryElementsKind(obj_kind)) { | 4863 if (IsDictionaryElementsKind(obj_kind)) { |
4874 to_kind = obj_kind; | 4864 to_kind = obj_kind; |
4875 } | 4865 } |
(...skipping 1223 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6099 // 2. Let key be ToPropertyKey(P). | 6089 // 2. Let key be ToPropertyKey(P). |
6100 // 3. ReturnIfAbrupt(key). | 6090 // 3. ReturnIfAbrupt(key). |
6101 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, key, ToPropertyKey(isolate, key)); | 6091 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, key, ToPropertyKey(isolate, key)); |
6102 // 4. Let desc be ToPropertyDescriptor(Attributes). | 6092 // 4. Let desc be ToPropertyDescriptor(Attributes). |
6103 // 5. ReturnIfAbrupt(desc). | 6093 // 5. ReturnIfAbrupt(desc). |
6104 PropertyDescriptor desc; | 6094 PropertyDescriptor desc; |
6105 if (!PropertyDescriptor::ToPropertyDescriptor(isolate, attributes, &desc)) { | 6095 if (!PropertyDescriptor::ToPropertyDescriptor(isolate, attributes, &desc)) { |
6106 return isolate->heap()->exception(); | 6096 return isolate->heap()->exception(); |
6107 } | 6097 } |
6108 // 6. Let success be DefinePropertyOrThrow(O,key, desc). | 6098 // 6. Let success be DefinePropertyOrThrow(O,key, desc). |
6109 bool success = DefineOwnProperty(isolate, Handle<JSReceiver>::cast(object), | 6099 Maybe<bool> success = DefineOwnProperty( |
6110 key, &desc, THROW_ON_ERROR); | 6100 isolate, Handle<JSReceiver>::cast(object), key, &desc, THROW_ON_ERROR); |
6111 // 7. ReturnIfAbrupt(success). | 6101 // 7. ReturnIfAbrupt(success). |
6112 if (isolate->has_pending_exception()) return isolate->heap()->exception(); | 6102 MAYBE_RETURN(success, isolate->heap()->exception()); |
6113 CHECK(success == true); | 6103 CHECK(success.FromJust()); |
6114 // 8. Return O. | 6104 // 8. Return O. |
6115 return *object; | 6105 return *object; |
6116 } | 6106 } |
6117 | 6107 |
6118 | 6108 |
6119 // ES6 19.1.2.3.1 | 6109 // ES6 19.1.2.3.1 |
6120 // static | 6110 // static |
6121 Object* JSReceiver::DefineProperties(Isolate* isolate, Handle<Object> object, | 6111 Object* JSReceiver::DefineProperties(Isolate* isolate, Handle<Object> object, |
6122 Handle<Object> properties) { | 6112 Handle<Object> properties) { |
6123 // 1. If Type(O) is not Object, throw a TypeError exception. | 6113 // 1. If Type(O) is not Object, throw a TypeError exception. |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6173 // desc to the end of descriptors. | 6163 // desc to the end of descriptors. |
6174 descriptors[descriptors_index].set_name(next_key); | 6164 descriptors[descriptors_index].set_name(next_key); |
6175 descriptors_index++; | 6165 descriptors_index++; |
6176 } | 6166 } |
6177 // 8. For each pair from descriptors in list order, | 6167 // 8. For each pair from descriptors in list order, |
6178 for (size_t i = 0; i < descriptors_index; ++i) { | 6168 for (size_t i = 0; i < descriptors_index; ++i) { |
6179 PropertyDescriptor* desc = &descriptors[i]; | 6169 PropertyDescriptor* desc = &descriptors[i]; |
6180 // 8a. Let P be the first element of pair. | 6170 // 8a. Let P be the first element of pair. |
6181 // 8b. Let desc be the second element of pair. | 6171 // 8b. Let desc be the second element of pair. |
6182 // 8c. Let status be DefinePropertyOrThrow(O, P, desc). | 6172 // 8c. Let status be DefinePropertyOrThrow(O, P, desc). |
6183 bool status = DefineOwnProperty(isolate, Handle<JSReceiver>::cast(object), | 6173 Maybe<bool> status = |
6184 desc->name(), desc, THROW_ON_ERROR); | 6174 DefineOwnProperty(isolate, Handle<JSReceiver>::cast(object), |
| 6175 desc->name(), desc, THROW_ON_ERROR); |
6185 // 8d. ReturnIfAbrupt(status). | 6176 // 8d. ReturnIfAbrupt(status). |
6186 if (isolate->has_pending_exception()) return isolate->heap()->exception(); | 6177 MAYBE_RETURN(status, isolate->heap()->exception()); |
6187 CHECK(status == true); | 6178 CHECK(status.FromJust()); |
6188 } | 6179 } |
6189 // 9. Return o. | 6180 // 9. Return o. |
6190 return *object; | 6181 return *object; |
6191 } | 6182 } |
6192 | 6183 |
6193 | 6184 |
6194 // static | 6185 // static |
6195 bool JSReceiver::DefineOwnProperty(Isolate* isolate, Handle<JSReceiver> object, | 6186 Maybe<bool> JSReceiver::DefineOwnProperty(Isolate* isolate, |
6196 Handle<Object> key, PropertyDescriptor* desc, | 6187 Handle<JSReceiver> object, |
6197 ShouldThrow should_throw) { | 6188 Handle<Object> key, |
| 6189 PropertyDescriptor* desc, |
| 6190 ShouldThrow should_throw) { |
6198 if (object->IsJSArray()) { | 6191 if (object->IsJSArray()) { |
6199 return JSArray::DefineOwnProperty(isolate, Handle<JSArray>::cast(object), | 6192 return JSArray::DefineOwnProperty(isolate, Handle<JSArray>::cast(object), |
6200 key, desc, should_throw); | 6193 key, desc, should_throw); |
6201 } | 6194 } |
6202 if (object->IsJSProxy()) { | 6195 if (object->IsJSProxy()) { |
6203 return JSProxy::DefineOwnProperty(isolate, Handle<JSProxy>::cast(object), | 6196 return JSProxy::DefineOwnProperty(isolate, Handle<JSProxy>::cast(object), |
6204 key, desc, should_throw); | 6197 key, desc, should_throw); |
6205 } | 6198 } |
6206 // TODO(jkummerow): Support Modules (ES6 9.4.6.6) | 6199 // TODO(jkummerow): Support Modules (ES6 9.4.6.6) |
6207 | 6200 |
6208 // OrdinaryDefineOwnProperty, by virtue of calling | 6201 // OrdinaryDefineOwnProperty, by virtue of calling |
6209 // DefineOwnPropertyIgnoreAttributes, can handle arguments (ES6 9.4.4.2) | 6202 // DefineOwnPropertyIgnoreAttributes, can handle arguments (ES6 9.4.4.2) |
6210 // and IntegerIndexedExotics (ES6 9.4.5.3), with one exception: | 6203 // and IntegerIndexedExotics (ES6 9.4.5.3), with one exception: |
6211 // TODO(jkummerow): Setting an indexed accessor on a typed array should throw. | 6204 // TODO(jkummerow): Setting an indexed accessor on a typed array should throw. |
6212 return OrdinaryDefineOwnProperty(isolate, Handle<JSObject>::cast(object), key, | 6205 return OrdinaryDefineOwnProperty(isolate, Handle<JSObject>::cast(object), key, |
6213 desc, should_throw); | 6206 desc, should_throw); |
6214 } | 6207 } |
6215 | 6208 |
6216 | 6209 |
6217 // static | 6210 // static |
6218 bool JSReceiver::OrdinaryDefineOwnProperty(Isolate* isolate, | 6211 Maybe<bool> JSReceiver::OrdinaryDefineOwnProperty(Isolate* isolate, |
6219 Handle<JSObject> object, | 6212 Handle<JSObject> object, |
6220 Handle<Object> key, | 6213 Handle<Object> key, |
6221 PropertyDescriptor* desc, | 6214 PropertyDescriptor* desc, |
6222 ShouldThrow should_throw) { | 6215 ShouldThrow should_throw) { |
6223 bool success = false; | 6216 bool success = false; |
6224 DCHECK(key->IsName() || key->IsNumber()); // |key| is a PropertyKey... | 6217 DCHECK(key->IsName() || key->IsNumber()); // |key| is a PropertyKey... |
6225 LookupIterator it = LookupIterator::PropertyOrElement( | 6218 LookupIterator it = LookupIterator::PropertyOrElement( |
6226 isolate, object, key, &success, LookupIterator::HIDDEN); | 6219 isolate, object, key, &success, LookupIterator::HIDDEN); |
6227 DCHECK(success); // ...so creating a LookupIterator can't fail. | 6220 DCHECK(success); // ...so creating a LookupIterator can't fail. |
6228 | 6221 |
6229 // Deal with access checks first. | 6222 // Deal with access checks first. |
6230 if (it.state() == LookupIterator::ACCESS_CHECK) { | 6223 if (it.state() == LookupIterator::ACCESS_CHECK) { |
6231 if (!it.HasAccess()) { | 6224 if (!it.HasAccess()) { |
6232 isolate->ReportFailedAccessCheck(it.GetHolder<JSObject>()); | 6225 isolate->ReportFailedAccessCheck(it.GetHolder<JSObject>()); |
6233 RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, false); | 6226 RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<bool>()); |
6234 return false; | 6227 return Just(false); |
6235 } | 6228 } |
6236 it.Next(); | 6229 it.Next(); |
6237 } | 6230 } |
6238 | 6231 |
6239 return OrdinaryDefineOwnProperty(&it, desc, should_throw); | 6232 return OrdinaryDefineOwnProperty(&it, desc, should_throw); |
6240 } | 6233 } |
6241 | 6234 |
6242 | 6235 |
6243 // ES6 9.1.6.1 | 6236 // ES6 9.1.6.1 |
6244 // static | 6237 // static |
6245 bool JSReceiver::OrdinaryDefineOwnProperty(LookupIterator* it, | 6238 Maybe<bool> JSReceiver::OrdinaryDefineOwnProperty(LookupIterator* it, |
6246 PropertyDescriptor* desc, | 6239 PropertyDescriptor* desc, |
6247 ShouldThrow should_throw) { | 6240 ShouldThrow should_throw) { |
6248 Isolate* isolate = it->isolate(); | 6241 Isolate* isolate = it->isolate(); |
6249 // 1. Let current be O.[[GetOwnProperty]](P). | 6242 // 1. Let current be O.[[GetOwnProperty]](P). |
6250 // 2. ReturnIfAbrupt(current). | 6243 // 2. ReturnIfAbrupt(current). |
6251 PropertyDescriptor current; | 6244 PropertyDescriptor current; |
6252 if (!GetOwnPropertyDescriptor(it, ¤t) && | 6245 MAYBE_RETURN(GetOwnPropertyDescriptor(it, ¤t), Nothing<bool>()); |
6253 isolate->has_pending_exception()) { | 6246 |
6254 return false; | |
6255 } | |
6256 // TODO(jkummerow/verwaest): It would be nice if we didn't have to reset | 6247 // TODO(jkummerow/verwaest): It would be nice if we didn't have to reset |
6257 // the iterator every time. Currently, the reasons why we need it are: | 6248 // the iterator every time. Currently, the reasons why we need it are: |
6258 // - handle interceptors correctly | 6249 // - handle interceptors correctly |
6259 // - handle accessors correctly (which might change the holder's map) | 6250 // - handle accessors correctly (which might change the holder's map) |
6260 it->Restart(); | 6251 it->Restart(); |
6261 // 3. Let extensible be the value of the [[Extensible]] internal slot of O. | 6252 // 3. Let extensible be the value of the [[Extensible]] internal slot of O. |
6262 Handle<JSObject> object = Handle<JSObject>::cast(it->GetReceiver()); | 6253 Handle<JSObject> object = Handle<JSObject>::cast(it->GetReceiver()); |
6263 bool extensible = JSObject::IsExtensible(object); | 6254 bool extensible = JSObject::IsExtensible(object); |
6264 | 6255 |
6265 return ValidateAndApplyPropertyDescriptor(isolate, it, extensible, desc, | 6256 return ValidateAndApplyPropertyDescriptor(isolate, it, extensible, desc, |
6266 ¤t, should_throw); | 6257 ¤t, should_throw); |
6267 } | 6258 } |
6268 | 6259 |
6269 | 6260 |
6270 // ES6 9.1.6.2 | 6261 // ES6 9.1.6.2 |
6271 // static | 6262 // static |
6272 bool JSReceiver::IsCompatiblePropertyDescriptor(Isolate* isolate, | 6263 Maybe<bool> JSReceiver::IsCompatiblePropertyDescriptor( |
6273 bool extensible, | 6264 Isolate* isolate, bool extensible, PropertyDescriptor* desc, |
6274 PropertyDescriptor* desc, | 6265 PropertyDescriptor* current, Handle<Name> property_name) { |
6275 PropertyDescriptor* current, | |
6276 Handle<Name> property_name) { | |
6277 // 1. Return ValidateAndApplyPropertyDescriptor(undefined, undefined, | 6266 // 1. Return ValidateAndApplyPropertyDescriptor(undefined, undefined, |
6278 // Extensible, Desc, Current). | 6267 // Extensible, Desc, Current). |
6279 return ValidateAndApplyPropertyDescriptor( | 6268 return ValidateAndApplyPropertyDescriptor( |
6280 isolate, NULL, extensible, desc, current, THROW_ON_ERROR, property_name); | 6269 isolate, NULL, extensible, desc, current, THROW_ON_ERROR, property_name); |
6281 } | 6270 } |
6282 | 6271 |
6283 | 6272 |
6284 // ES6 9.1.6.3 | 6273 // ES6 9.1.6.3 |
6285 // static | 6274 // static |
6286 bool JSReceiver::ValidateAndApplyPropertyDescriptor( | 6275 Maybe<bool> JSReceiver::ValidateAndApplyPropertyDescriptor( |
6287 Isolate* isolate, LookupIterator* it, bool extensible, | 6276 Isolate* isolate, LookupIterator* it, bool extensible, |
6288 PropertyDescriptor* desc, PropertyDescriptor* current, | 6277 PropertyDescriptor* desc, PropertyDescriptor* current, |
6289 ShouldThrow should_throw, Handle<Name> property_name) { | 6278 ShouldThrow should_throw, Handle<Name> property_name) { |
6290 // We either need a LookupIterator, or a property name. | 6279 // We either need a LookupIterator, or a property name. |
6291 DCHECK((it == NULL) != property_name.is_null()); | 6280 DCHECK((it == NULL) != property_name.is_null()); |
6292 Handle<JSObject> object; | 6281 Handle<JSObject> object; |
6293 if (it != NULL) object = Handle<JSObject>::cast(it->GetReceiver()); | 6282 if (it != NULL) object = Handle<JSObject>::cast(it->GetReceiver()); |
6294 bool desc_is_data_descriptor = PropertyDescriptor::IsDataDescriptor(desc); | 6283 bool desc_is_data_descriptor = PropertyDescriptor::IsDataDescriptor(desc); |
6295 bool desc_is_accessor_descriptor = | 6284 bool desc_is_accessor_descriptor = |
6296 PropertyDescriptor::IsAccessorDescriptor(desc); | 6285 PropertyDescriptor::IsAccessorDescriptor(desc); |
6297 bool desc_is_generic_descriptor = | 6286 bool desc_is_generic_descriptor = |
6298 PropertyDescriptor::IsGenericDescriptor(desc); | 6287 PropertyDescriptor::IsGenericDescriptor(desc); |
6299 // 1. (Assert) | 6288 // 1. (Assert) |
6300 // 2. If current is undefined, then | 6289 // 2. If current is undefined, then |
6301 if (current->is_empty()) { | 6290 if (current->is_empty()) { |
6302 // 2a. If extensible is false, return false. | 6291 // 2a. If extensible is false, return false. |
6303 if (!extensible) { | 6292 if (!extensible) { |
6304 if (should_throw == THROW_ON_ERROR) { | 6293 RETURN_FAILURE(isolate, should_throw, |
6305 isolate->Throw(*isolate->factory()->NewTypeError( | 6294 NewTypeError(MessageTemplate::kDefineDisallowed, |
6306 MessageTemplate::kDefineDisallowed, | 6295 it != NULL ? it->GetName() : property_name)); |
6307 it != NULL ? it->GetName() : property_name)); | |
6308 } | |
6309 return false; | |
6310 } | 6296 } |
6311 // 2c. If IsGenericDescriptor(Desc) or IsDataDescriptor(Desc) is true, then: | 6297 // 2c. If IsGenericDescriptor(Desc) or IsDataDescriptor(Desc) is true, then: |
6312 // (This is equivalent to !IsAccessorDescriptor(desc).) | 6298 // (This is equivalent to !IsAccessorDescriptor(desc).) |
6313 DCHECK((desc_is_generic_descriptor || desc_is_data_descriptor) == | 6299 DCHECK((desc_is_generic_descriptor || desc_is_data_descriptor) == |
6314 !desc_is_accessor_descriptor); | 6300 !desc_is_accessor_descriptor); |
6315 if (!desc_is_accessor_descriptor) { | 6301 if (!desc_is_accessor_descriptor) { |
6316 // 2c i. If O is not undefined, create an own data property named P of | 6302 // 2c i. If O is not undefined, create an own data property named P of |
6317 // object O whose [[Value]], [[Writable]], [[Enumerable]] and | 6303 // object O whose [[Value]], [[Writable]], [[Enumerable]] and |
6318 // [[Configurable]] attribute values are described by Desc. If the value | 6304 // [[Configurable]] attribute values are described by Desc. If the value |
6319 // of an attribute field of Desc is absent, the attribute of the newly | 6305 // of an attribute field of Desc is absent, the attribute of the newly |
6320 // created property is set to its default value. | 6306 // created property is set to its default value. |
6321 if (it != NULL) { | 6307 if (it != NULL) { |
6322 if (!desc->has_writable()) desc->set_writable(false); | 6308 if (!desc->has_writable()) desc->set_writable(false); |
6323 if (!desc->has_enumerable()) desc->set_enumerable(false); | 6309 if (!desc->has_enumerable()) desc->set_enumerable(false); |
6324 if (!desc->has_configurable()) desc->set_configurable(false); | 6310 if (!desc->has_configurable()) desc->set_configurable(false); |
6325 Handle<Object> value( | 6311 Handle<Object> value( |
6326 desc->has_value() | 6312 desc->has_value() |
6327 ? desc->value() | 6313 ? desc->value() |
6328 : Handle<Object>::cast(isolate->factory()->undefined_value())); | 6314 : Handle<Object>::cast(isolate->factory()->undefined_value())); |
6329 MaybeHandle<Object> result = | 6315 MaybeHandle<Object> result = |
6330 JSObject::DefineOwnPropertyIgnoreAttributes( | 6316 JSObject::DefineOwnPropertyIgnoreAttributes( |
6331 it, value, desc->ToAttributes(), JSObject::DONT_FORCE_FIELD); | 6317 it, value, desc->ToAttributes(), JSObject::DONT_FORCE_FIELD); |
6332 if (result.is_null()) return false; | 6318 if (result.is_null()) return Nothing<bool>(); |
6333 } | 6319 } |
6334 } else { | 6320 } else { |
6335 // 2d. Else Desc must be an accessor Property Descriptor, | 6321 // 2d. Else Desc must be an accessor Property Descriptor, |
6336 DCHECK(desc_is_accessor_descriptor); | 6322 DCHECK(desc_is_accessor_descriptor); |
6337 // 2d i. If O is not undefined, create an own accessor property named P | 6323 // 2d i. If O is not undefined, create an own accessor property named P |
6338 // of object O whose [[Get]], [[Set]], [[Enumerable]] and | 6324 // of object O whose [[Get]], [[Set]], [[Enumerable]] and |
6339 // [[Configurable]] attribute values are described by Desc. If the value | 6325 // [[Configurable]] attribute values are described by Desc. If the value |
6340 // of an attribute field of Desc is absent, the attribute of the newly | 6326 // of an attribute field of Desc is absent, the attribute of the newly |
6341 // created property is set to its default value. | 6327 // created property is set to its default value. |
6342 if (it != NULL) { | 6328 if (it != NULL) { |
6343 if (!desc->has_enumerable()) desc->set_enumerable(false); | 6329 if (!desc->has_enumerable()) desc->set_enumerable(false); |
6344 if (!desc->has_configurable()) desc->set_configurable(false); | 6330 if (!desc->has_configurable()) desc->set_configurable(false); |
6345 Handle<Object> getter( | 6331 Handle<Object> getter( |
6346 desc->has_get() | 6332 desc->has_get() |
6347 ? desc->get() | 6333 ? desc->get() |
6348 : Handle<Object>::cast(isolate->factory()->null_value())); | 6334 : Handle<Object>::cast(isolate->factory()->null_value())); |
6349 Handle<Object> setter( | 6335 Handle<Object> setter( |
6350 desc->has_set() | 6336 desc->has_set() |
6351 ? desc->set() | 6337 ? desc->set() |
6352 : Handle<Object>::cast(isolate->factory()->null_value())); | 6338 : Handle<Object>::cast(isolate->factory()->null_value())); |
6353 MaybeHandle<Object> result = | 6339 MaybeHandle<Object> result = |
6354 JSObject::DefineAccessor(it, getter, setter, desc->ToAttributes()); | 6340 JSObject::DefineAccessor(it, getter, setter, desc->ToAttributes()); |
6355 if (result.is_null()) return false; | 6341 if (result.is_null()) return Nothing<bool>(); |
6356 } | 6342 } |
6357 } | 6343 } |
6358 // 2e. Return true. | 6344 // 2e. Return true. |
6359 return true; | 6345 return Just(true); |
6360 } | 6346 } |
6361 // 3. Return true, if every field in Desc is absent. | 6347 // 3. Return true, if every field in Desc is absent. |
6362 // 4. Return true, if every field in Desc also occurs in current and the | 6348 // 4. Return true, if every field in Desc also occurs in current and the |
6363 // value of every field in Desc is the same value as the corresponding field | 6349 // value of every field in Desc is the same value as the corresponding field |
6364 // in current when compared using the SameValue algorithm. | 6350 // in current when compared using the SameValue algorithm. |
6365 if ((!desc->has_enumerable() || | 6351 if ((!desc->has_enumerable() || |
6366 desc->enumerable() == current->enumerable()) && | 6352 desc->enumerable() == current->enumerable()) && |
6367 (!desc->has_configurable() || | 6353 (!desc->has_configurable() || |
6368 desc->configurable() == current->configurable()) && | 6354 desc->configurable() == current->configurable()) && |
6369 (!desc->has_value() || | 6355 (!desc->has_value() || |
6370 (current->has_value() && current->value()->SameValue(*desc->value()))) && | 6356 (current->has_value() && current->value()->SameValue(*desc->value()))) && |
6371 (!desc->has_writable() || | 6357 (!desc->has_writable() || |
6372 (current->has_writable() && current->writable() == desc->writable())) && | 6358 (current->has_writable() && current->writable() == desc->writable())) && |
6373 (!desc->has_get() || | 6359 (!desc->has_get() || |
6374 (current->has_get() && current->get()->SameValue(*desc->get()))) && | 6360 (current->has_get() && current->get()->SameValue(*desc->get()))) && |
6375 (!desc->has_set() || | 6361 (!desc->has_set() || |
6376 (current->has_set() && current->set()->SameValue(*desc->set())))) { | 6362 (current->has_set() && current->set()->SameValue(*desc->set())))) { |
6377 return true; | 6363 return Just(true); |
6378 } | 6364 } |
6379 // 5. If the [[Configurable]] field of current is false, then | 6365 // 5. If the [[Configurable]] field of current is false, then |
6380 if (!current->configurable()) { | 6366 if (!current->configurable()) { |
6381 // 5a. Return false, if the [[Configurable]] field of Desc is true. | 6367 // 5a. Return false, if the [[Configurable]] field of Desc is true. |
6382 if (desc->has_configurable() && desc->configurable()) { | 6368 if (desc->has_configurable() && desc->configurable()) { |
6383 if (should_throw == THROW_ON_ERROR) { | 6369 RETURN_FAILURE(isolate, should_throw, |
6384 isolate->Throw(*isolate->factory()->NewTypeError( | 6370 NewTypeError(MessageTemplate::kRedefineDisallowed, |
6385 MessageTemplate::kRedefineDisallowed, | 6371 it != NULL ? it->GetName() : property_name)); |
6386 it != NULL ? it->GetName() : property_name)); | |
6387 } | |
6388 return false; | |
6389 } | 6372 } |
6390 // 5b. Return false, if the [[Enumerable]] field of Desc is present and the | 6373 // 5b. Return false, if the [[Enumerable]] field of Desc is present and the |
6391 // [[Enumerable]] fields of current and Desc are the Boolean negation of | 6374 // [[Enumerable]] fields of current and Desc are the Boolean negation of |
6392 // each other. | 6375 // each other. |
6393 if (desc->has_enumerable() && desc->enumerable() != current->enumerable()) { | 6376 if (desc->has_enumerable() && desc->enumerable() != current->enumerable()) { |
6394 if (should_throw == THROW_ON_ERROR) { | 6377 RETURN_FAILURE(isolate, should_throw, |
6395 isolate->Throw(*isolate->factory()->NewTypeError( | 6378 NewTypeError(MessageTemplate::kRedefineDisallowed, |
6396 MessageTemplate::kRedefineDisallowed, | 6379 it != NULL ? it->GetName() : property_name)); |
6397 it != NULL ? it->GetName() : property_name)); | |
6398 } | |
6399 return false; | |
6400 } | 6380 } |
6401 } | 6381 } |
6402 | 6382 |
6403 bool current_is_data_descriptor = | 6383 bool current_is_data_descriptor = |
6404 PropertyDescriptor::IsDataDescriptor(current); | 6384 PropertyDescriptor::IsDataDescriptor(current); |
6405 // 6. If IsGenericDescriptor(Desc) is true, no further validation is required. | 6385 // 6. If IsGenericDescriptor(Desc) is true, no further validation is required. |
6406 if (desc_is_generic_descriptor) { | 6386 if (desc_is_generic_descriptor) { |
6407 // Nothing to see here. | 6387 // Nothing to see here. |
6408 | 6388 |
6409 // 7. Else if IsDataDescriptor(current) and IsDataDescriptor(Desc) have | 6389 // 7. Else if IsDataDescriptor(current) and IsDataDescriptor(Desc) have |
6410 // different results, then: | 6390 // different results, then: |
6411 } else if (current_is_data_descriptor != desc_is_data_descriptor) { | 6391 } else if (current_is_data_descriptor != desc_is_data_descriptor) { |
6412 // 7a. Return false, if the [[Configurable]] field of current is false. | 6392 // 7a. Return false, if the [[Configurable]] field of current is false. |
6413 if (!current->configurable()) { | 6393 if (!current->configurable()) { |
6414 if (should_throw == THROW_ON_ERROR) { | 6394 RETURN_FAILURE(isolate, should_throw, |
6415 isolate->Throw(*isolate->factory()->NewTypeError( | 6395 NewTypeError(MessageTemplate::kRedefineDisallowed, |
6416 MessageTemplate::kRedefineDisallowed, | 6396 it != NULL ? it->GetName() : property_name)); |
6417 it != NULL ? it->GetName() : property_name)); | |
6418 } | |
6419 return false; | |
6420 } | 6397 } |
6421 // 7b. If IsDataDescriptor(current) is true, then: | 6398 // 7b. If IsDataDescriptor(current) is true, then: |
6422 if (current_is_data_descriptor) { | 6399 if (current_is_data_descriptor) { |
6423 // 7b i. If O is not undefined, convert the property named P of object O | 6400 // 7b i. If O is not undefined, convert the property named P of object O |
6424 // from a data property to an accessor property. Preserve the existing | 6401 // from a data property to an accessor property. Preserve the existing |
6425 // values of the converted property's [[Configurable]] and [[Enumerable]] | 6402 // values of the converted property's [[Configurable]] and [[Enumerable]] |
6426 // attributes and set the rest of the property's attributes to their | 6403 // attributes and set the rest of the property's attributes to their |
6427 // default values. | 6404 // default values. |
6428 // --> Folded into step 10. | 6405 // --> Folded into step 10. |
6429 } else { | 6406 } else { |
6430 // 7c i. If O is not undefined, convert the property named P of object O | 6407 // 7c i. If O is not undefined, convert the property named P of object O |
6431 // from an accessor property to a data property. Preserve the existing | 6408 // from an accessor property to a data property. Preserve the existing |
6432 // values of the converted property’s [[Configurable]] and [[Enumerable]] | 6409 // values of the converted property’s [[Configurable]] and [[Enumerable]] |
6433 // attributes and set the rest of the property’s attributes to their | 6410 // attributes and set the rest of the property’s attributes to their |
6434 // default values. | 6411 // default values. |
6435 // --> Folded into step 10. | 6412 // --> Folded into step 10. |
6436 } | 6413 } |
6437 | 6414 |
6438 // 8. Else if IsDataDescriptor(current) and IsDataDescriptor(Desc) are both | 6415 // 8. Else if IsDataDescriptor(current) and IsDataDescriptor(Desc) are both |
6439 // true, then: | 6416 // true, then: |
6440 } else if (current_is_data_descriptor && desc_is_data_descriptor) { | 6417 } else if (current_is_data_descriptor && desc_is_data_descriptor) { |
6441 // 8a. If the [[Configurable]] field of current is false, then: | 6418 // 8a. If the [[Configurable]] field of current is false, then: |
6442 if (!current->configurable()) { | 6419 if (!current->configurable()) { |
6443 // [Strong mode] Disallow changing writable -> readonly for | 6420 // [Strong mode] Disallow changing writable -> readonly for |
6444 // non-configurable properties. | 6421 // non-configurable properties. |
6445 if (it != NULL && current->writable() && desc->has_writable() && | 6422 if (it != NULL && current->writable() && desc->has_writable() && |
6446 !desc->writable() && object->map()->is_strong()) { | 6423 !desc->writable() && object->map()->is_strong()) { |
6447 if (should_throw == THROW_ON_ERROR) { | 6424 RETURN_FAILURE(isolate, should_throw, |
6448 isolate->Throw(*isolate->factory()->NewTypeError( | 6425 NewTypeError(MessageTemplate::kStrongRedefineDisallowed, |
6449 MessageTemplate::kStrongRedefineDisallowed, object, | 6426 object, it->GetName())); |
6450 it->GetName())); | |
6451 } | |
6452 return false; | |
6453 } | 6427 } |
6454 // 8a i. Return false, if the [[Writable]] field of current is false and | 6428 // 8a i. Return false, if the [[Writable]] field of current is false and |
6455 // the [[Writable]] field of Desc is true. | 6429 // the [[Writable]] field of Desc is true. |
6456 if (!current->writable() && desc->has_writable() && desc->writable()) { | 6430 if (!current->writable() && desc->has_writable() && desc->writable()) { |
6457 if (should_throw == THROW_ON_ERROR) { | 6431 RETURN_FAILURE( |
6458 isolate->Throw(*isolate->factory()->NewTypeError( | 6432 isolate, should_throw, |
6459 MessageTemplate::kRedefineDisallowed, | 6433 NewTypeError(MessageTemplate::kRedefineDisallowed, |
6460 it != NULL ? it->GetName() : property_name)); | 6434 it != NULL ? it->GetName() : property_name)); |
6461 } | |
6462 return false; | |
6463 } | 6435 } |
6464 // 8a ii. If the [[Writable]] field of current is false, then: | 6436 // 8a ii. If the [[Writable]] field of current is false, then: |
6465 if (!current->writable()) { | 6437 if (!current->writable()) { |
6466 // 8a ii 1. Return false, if the [[Value]] field of Desc is present and | 6438 // 8a ii 1. Return false, if the [[Value]] field of Desc is present and |
6467 // SameValue(Desc.[[Value]], current.[[Value]]) is false. | 6439 // SameValue(Desc.[[Value]], current.[[Value]]) is false. |
6468 if (desc->has_value() && !desc->value()->SameValue(*current->value())) { | 6440 if (desc->has_value() && !desc->value()->SameValue(*current->value())) { |
6469 if (should_throw == THROW_ON_ERROR) { | 6441 RETURN_FAILURE( |
6470 isolate->Throw(*isolate->factory()->NewTypeError( | 6442 isolate, should_throw, |
6471 MessageTemplate::kRedefineDisallowed, | 6443 NewTypeError(MessageTemplate::kRedefineDisallowed, |
6472 it != NULL ? it->GetName() : property_name)); | 6444 it != NULL ? it->GetName() : property_name)); |
6473 } | |
6474 return false; | |
6475 } | 6445 } |
6476 } | 6446 } |
6477 } | 6447 } |
6478 } else { | 6448 } else { |
6479 // 9. Else IsAccessorDescriptor(current) and IsAccessorDescriptor(Desc) | 6449 // 9. Else IsAccessorDescriptor(current) and IsAccessorDescriptor(Desc) |
6480 // are both true, | 6450 // are both true, |
6481 DCHECK(PropertyDescriptor::IsAccessorDescriptor(current) && | 6451 DCHECK(PropertyDescriptor::IsAccessorDescriptor(current) && |
6482 desc_is_accessor_descriptor); | 6452 desc_is_accessor_descriptor); |
6483 // 9a. If the [[Configurable]] field of current is false, then: | 6453 // 9a. If the [[Configurable]] field of current is false, then: |
6484 if (!current->configurable()) { | 6454 if (!current->configurable()) { |
6485 // 9a i. Return false, if the [[Set]] field of Desc is present and | 6455 // 9a i. Return false, if the [[Set]] field of Desc is present and |
6486 // SameValue(Desc.[[Set]], current.[[Set]]) is false. | 6456 // SameValue(Desc.[[Set]], current.[[Set]]) is false. |
6487 if (desc->has_set() && !desc->set()->SameValue(*current->set())) { | 6457 if (desc->has_set() && !desc->set()->SameValue(*current->set())) { |
6488 if (should_throw == THROW_ON_ERROR) { | 6458 RETURN_FAILURE( |
6489 isolate->Throw(*isolate->factory()->NewTypeError( | 6459 isolate, should_throw, |
6490 MessageTemplate::kRedefineDisallowed, | 6460 NewTypeError(MessageTemplate::kRedefineDisallowed, |
6491 it != NULL ? it->GetName() : property_name)); | 6461 it != NULL ? it->GetName() : property_name)); |
6492 } | |
6493 return false; | |
6494 } | 6462 } |
6495 // 9a ii. Return false, if the [[Get]] field of Desc is present and | 6463 // 9a ii. Return false, if the [[Get]] field of Desc is present and |
6496 // SameValue(Desc.[[Get]], current.[[Get]]) is false. | 6464 // SameValue(Desc.[[Get]], current.[[Get]]) is false. |
6497 if (desc->has_get() && !desc->get()->SameValue(*current->get())) { | 6465 if (desc->has_get() && !desc->get()->SameValue(*current->get())) { |
6498 if (should_throw == THROW_ON_ERROR) { | 6466 RETURN_FAILURE( |
6499 isolate->Throw(*isolate->factory()->NewTypeError( | 6467 isolate, should_throw, |
6500 MessageTemplate::kRedefineDisallowed, | 6468 NewTypeError(MessageTemplate::kRedefineDisallowed, |
6501 it != NULL ? it->GetName() : property_name)); | 6469 it != NULL ? it->GetName() : property_name)); |
6502 } | |
6503 return false; | |
6504 } | 6470 } |
6505 } | 6471 } |
6506 } | 6472 } |
6507 | 6473 |
6508 // 10. If O is not undefined, then: | 6474 // 10. If O is not undefined, then: |
6509 if (it != NULL) { | 6475 if (it != NULL) { |
6510 // 10a. For each field of Desc that is present, set the corresponding | 6476 // 10a. For each field of Desc that is present, set the corresponding |
6511 // attribute of the property named P of object O to the value of the field. | 6477 // attribute of the property named P of object O to the value of the field. |
6512 PropertyAttributes attrs = NONE; | 6478 PropertyAttributes attrs = NONE; |
6513 | 6479 |
(...skipping 21 matching lines...) Expand all Loading... |
6535 attrs | (current->writable() ? NONE : READ_ONLY)); | 6501 attrs | (current->writable() ? NONE : READ_ONLY)); |
6536 } | 6502 } |
6537 Handle<Object> value( | 6503 Handle<Object> value( |
6538 desc->has_value() ? desc->value() | 6504 desc->has_value() ? desc->value() |
6539 : current->has_value() | 6505 : current->has_value() |
6540 ? current->value() | 6506 ? current->value() |
6541 : Handle<Object>::cast( | 6507 : Handle<Object>::cast( |
6542 isolate->factory()->undefined_value())); | 6508 isolate->factory()->undefined_value())); |
6543 MaybeHandle<Object> result = JSObject::DefineOwnPropertyIgnoreAttributes( | 6509 MaybeHandle<Object> result = JSObject::DefineOwnPropertyIgnoreAttributes( |
6544 it, value, attrs, JSObject::DONT_FORCE_FIELD); | 6510 it, value, attrs, JSObject::DONT_FORCE_FIELD); |
6545 if (result.is_null()) return false; | 6511 if (result.is_null()) return Nothing<bool>(); |
6546 } else { | 6512 } else { |
6547 DCHECK(desc_is_accessor_descriptor || | 6513 DCHECK(desc_is_accessor_descriptor || |
6548 (desc_is_generic_descriptor && | 6514 (desc_is_generic_descriptor && |
6549 PropertyDescriptor::IsAccessorDescriptor(current))); | 6515 PropertyDescriptor::IsAccessorDescriptor(current))); |
6550 Handle<Object> getter( | 6516 Handle<Object> getter( |
6551 desc->has_get() | 6517 desc->has_get() |
6552 ? desc->get() | 6518 ? desc->get() |
6553 : current->has_get() | 6519 : current->has_get() |
6554 ? current->get() | 6520 ? current->get() |
6555 : Handle<Object>::cast(isolate->factory()->null_value())); | 6521 : Handle<Object>::cast(isolate->factory()->null_value())); |
6556 Handle<Object> setter( | 6522 Handle<Object> setter( |
6557 desc->has_set() | 6523 desc->has_set() |
6558 ? desc->set() | 6524 ? desc->set() |
6559 : current->has_set() | 6525 : current->has_set() |
6560 ? current->set() | 6526 ? current->set() |
6561 : Handle<Object>::cast(isolate->factory()->null_value())); | 6527 : Handle<Object>::cast(isolate->factory()->null_value())); |
6562 MaybeHandle<Object> result = | 6528 MaybeHandle<Object> result = |
6563 JSObject::DefineAccessor(it, getter, setter, attrs); | 6529 JSObject::DefineAccessor(it, getter, setter, attrs); |
6564 if (result.is_null()) return false; | 6530 if (result.is_null()) return Nothing<bool>(); |
6565 } | 6531 } |
6566 } | 6532 } |
6567 | 6533 |
6568 // 11. Return true. | 6534 // 11. Return true. |
6569 return true; | 6535 return Just(true); |
6570 } | 6536 } |
6571 | 6537 |
6572 | 6538 |
6573 // static | 6539 // static |
6574 Maybe<bool> JSReceiver::CreateDataProperty(LookupIterator* it, | 6540 Maybe<bool> JSReceiver::CreateDataProperty(LookupIterator* it, |
6575 Handle<Object> value, | 6541 Handle<Object> value, |
6576 ShouldThrow should_throw) { | 6542 ShouldThrow should_throw) { |
6577 DCHECK(!it->check_prototype_chain()); | 6543 DCHECK(!it->check_prototype_chain()); |
6578 Handle<JSReceiver> receiver = Handle<JSReceiver>::cast(it->GetReceiver()); | 6544 Handle<JSReceiver> receiver = Handle<JSReceiver>::cast(it->GetReceiver()); |
6579 Isolate* isolate = receiver->GetIsolate(); | 6545 Isolate* isolate = receiver->GetIsolate(); |
6580 | 6546 |
6581 if (receiver->IsJSObject()) { | 6547 if (receiver->IsJSObject()) { |
6582 return JSObject::CreateDataProperty(it, value); // Shortcut. | 6548 return JSObject::CreateDataProperty(it, value); // Shortcut. |
6583 } | 6549 } |
6584 | 6550 |
6585 PropertyDescriptor new_desc; | 6551 PropertyDescriptor new_desc; |
6586 new_desc.set_value(value); | 6552 new_desc.set_value(value); |
6587 new_desc.set_writable(true); | 6553 new_desc.set_writable(true); |
6588 new_desc.set_enumerable(true); | 6554 new_desc.set_enumerable(true); |
6589 new_desc.set_configurable(true); | 6555 new_desc.set_configurable(true); |
6590 | 6556 |
6591 bool result = JSReceiver::DefineOwnProperty(isolate, receiver, it->GetName(), | 6557 return JSReceiver::DefineOwnProperty(isolate, receiver, it->GetName(), |
6592 &new_desc, should_throw); | 6558 &new_desc, should_throw); |
6593 if (isolate->has_pending_exception()) return Nothing<bool>(); | |
6594 return Just(result); | |
6595 } | 6559 } |
6596 | 6560 |
6597 | 6561 |
6598 Maybe<bool> JSObject::CreateDataProperty(LookupIterator* it, | 6562 Maybe<bool> JSObject::CreateDataProperty(LookupIterator* it, |
6599 Handle<Object> value) { | 6563 Handle<Object> value) { |
6600 DCHECK(it->GetReceiver()->IsJSObject()); | 6564 DCHECK(it->GetReceiver()->IsJSObject()); |
6601 Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(it); | 6565 MAYBE_RETURN(JSReceiver::GetPropertyAttributes(it), Nothing<bool>()); |
6602 if (maybe.IsNothing()) return Nothing<bool>(); | |
6603 | 6566 |
6604 if (it->IsFound()) { | 6567 if (it->IsFound()) { |
6605 if (!it->IsConfigurable()) return Just(false); | 6568 if (!it->IsConfigurable()) return Just(false); |
6606 } else { | 6569 } else { |
6607 if (!JSObject::IsExtensible(Handle<JSObject>::cast(it->GetReceiver()))) | 6570 if (!JSObject::IsExtensible(Handle<JSObject>::cast(it->GetReceiver()))) |
6608 return Just(false); | 6571 return Just(false); |
6609 } | 6572 } |
6610 | 6573 |
6611 RETURN_ON_EXCEPTION_VALUE( | 6574 RETURN_ON_EXCEPTION_VALUE( |
6612 it->isolate(), | 6575 it->isolate(), |
(...skipping 14 matching lines...) Expand all Loading... |
6627 } | 6590 } |
6628 | 6591 |
6629 | 6592 |
6630 bool PropertyKeyToArrayIndex(Handle<Object> index_obj, uint32_t* output) { | 6593 bool PropertyKeyToArrayIndex(Handle<Object> index_obj, uint32_t* output) { |
6631 return PropertyKeyToArrayLength(index_obj, output) && *output != kMaxUInt32; | 6594 return PropertyKeyToArrayLength(index_obj, output) && *output != kMaxUInt32; |
6632 } | 6595 } |
6633 | 6596 |
6634 | 6597 |
6635 // ES6 9.4.2.1 | 6598 // ES6 9.4.2.1 |
6636 // static | 6599 // static |
6637 bool JSArray::DefineOwnProperty(Isolate* isolate, Handle<JSArray> o, | 6600 Maybe<bool> JSArray::DefineOwnProperty(Isolate* isolate, Handle<JSArray> o, |
6638 Handle<Object> name, PropertyDescriptor* desc, | 6601 Handle<Object> name, |
6639 ShouldThrow should_throw) { | 6602 PropertyDescriptor* desc, |
| 6603 ShouldThrow should_throw) { |
6640 // 1. Assert: IsPropertyKey(P) is true. ("P" is |name|.) | 6604 // 1. Assert: IsPropertyKey(P) is true. ("P" is |name|.) |
6641 // 2. If P is "length", then: | 6605 // 2. If P is "length", then: |
6642 // TODO(jkummerow): Check if we need slow string comparison. | 6606 // TODO(jkummerow): Check if we need slow string comparison. |
6643 if (*name == isolate->heap()->length_string()) { | 6607 if (*name == isolate->heap()->length_string()) { |
6644 // 2a. Return ArraySetLength(A, Desc). | 6608 // 2a. Return ArraySetLength(A, Desc). |
6645 return ArraySetLength(isolate, o, desc, should_throw); | 6609 return ArraySetLength(isolate, o, desc, should_throw); |
6646 } | 6610 } |
6647 // 3. Else if P is an array index, then: | 6611 // 3. Else if P is an array index, then: |
6648 uint32_t index = 0; | 6612 uint32_t index = 0; |
6649 if (PropertyKeyToArrayIndex(name, &index)) { | 6613 if (PropertyKeyToArrayIndex(name, &index)) { |
6650 // 3a. Let oldLenDesc be OrdinaryGetOwnProperty(A, "length"). | 6614 // 3a. Let oldLenDesc be OrdinaryGetOwnProperty(A, "length"). |
6651 PropertyDescriptor old_len_desc; | 6615 PropertyDescriptor old_len_desc; |
6652 bool success = GetOwnPropertyDescriptor( | 6616 Maybe<bool> success = GetOwnPropertyDescriptor( |
6653 isolate, o, isolate->factory()->length_string(), &old_len_desc); | 6617 isolate, o, isolate->factory()->length_string(), &old_len_desc); |
6654 // 3b. (Assert) | 6618 // 3b. (Assert) |
6655 DCHECK(success); | 6619 DCHECK(success.FromJust()); |
6656 USE(success); | 6620 USE(success); |
6657 // 3c. Let oldLen be oldLenDesc.[[Value]]. | 6621 // 3c. Let oldLen be oldLenDesc.[[Value]]. |
6658 uint32_t old_len = 0; | 6622 uint32_t old_len = 0; |
6659 CHECK(old_len_desc.value()->ToArrayLength(&old_len)); | 6623 CHECK(old_len_desc.value()->ToArrayLength(&old_len)); |
6660 // 3d. Let index be ToUint32(P). | 6624 // 3d. Let index be ToUint32(P). |
6661 // (Already done above.) | 6625 // (Already done above.) |
6662 // 3e. (Assert) | 6626 // 3e. (Assert) |
6663 // 3f. If index >= oldLen and oldLenDesc.[[Writable]] is false, | 6627 // 3f. If index >= oldLen and oldLenDesc.[[Writable]] is false, |
6664 // return false. | 6628 // return false. |
6665 if (index >= old_len && old_len_desc.has_writable() && | 6629 if (index >= old_len && old_len_desc.has_writable() && |
6666 !old_len_desc.writable()) { | 6630 !old_len_desc.writable()) { |
6667 if (should_throw == THROW_ON_ERROR) { | 6631 RETURN_FAILURE(isolate, should_throw, |
6668 isolate->Throw(*isolate->factory()->NewTypeError( | 6632 NewTypeError(MessageTemplate::kDefineDisallowed, name)); |
6669 MessageTemplate::kDefineDisallowed, name)); | |
6670 } | |
6671 return false; | |
6672 } | 6633 } |
6673 // 3g. Let succeeded be OrdinaryDefineOwnProperty(A, P, Desc). | 6634 // 3g. Let succeeded be OrdinaryDefineOwnProperty(A, P, Desc). |
6674 bool succeeded = | 6635 Maybe<bool> succeeded = |
6675 OrdinaryDefineOwnProperty(isolate, o, name, desc, should_throw); | 6636 OrdinaryDefineOwnProperty(isolate, o, name, desc, should_throw); |
6676 // 3h. (Assert) | 6637 // 3h. Assert: succeeded is not an abrupt completion. |
| 6638 // In our case, if should_throw == THROW_ON_ERROR, it can be! |
6677 // 3i. If succeeded is false, return false. | 6639 // 3i. If succeeded is false, return false. |
6678 if (!succeeded) return false; | 6640 if (succeeded.IsNothing() || !succeeded.FromJust()) return succeeded; |
6679 // 3j. If index >= oldLen, then: | 6641 // 3j. If index >= oldLen, then: |
6680 if (index >= old_len) { | 6642 if (index >= old_len) { |
6681 // 3j i. Set oldLenDesc.[[Value]] to index + 1. | 6643 // 3j i. Set oldLenDesc.[[Value]] to index + 1. |
6682 old_len_desc.set_value(isolate->factory()->NewNumberFromUint(index + 1)); | 6644 old_len_desc.set_value(isolate->factory()->NewNumberFromUint(index + 1)); |
6683 // 3j ii. Let succeeded be | 6645 // 3j ii. Let succeeded be |
6684 // OrdinaryDefineOwnProperty(A, "length", oldLenDesc). | 6646 // OrdinaryDefineOwnProperty(A, "length", oldLenDesc). |
6685 OrdinaryDefineOwnProperty(isolate, o, isolate->factory()->length_string(), | 6647 succeeded = OrdinaryDefineOwnProperty(isolate, o, |
6686 &old_len_desc, should_throw); | 6648 isolate->factory()->length_string(), |
6687 // 3j iii. (Assert) | 6649 &old_len_desc, should_throw); |
| 6650 // 3j iii. Assert: succeeded is true. |
| 6651 DCHECK(succeeded.FromJust()); |
| 6652 USE(succeeded); |
6688 } | 6653 } |
6689 // 3k. Return true. | 6654 // 3k. Return true. |
6690 return true; | 6655 return Just(true); |
6691 } | 6656 } |
6692 | 6657 |
6693 // 4. Return OrdinaryDefineOwnProperty(A, P, Desc). | 6658 // 4. Return OrdinaryDefineOwnProperty(A, P, Desc). |
6694 return OrdinaryDefineOwnProperty(isolate, o, name, desc, should_throw); | 6659 return OrdinaryDefineOwnProperty(isolate, o, name, desc, should_throw); |
6695 } | 6660 } |
6696 | 6661 |
6697 | 6662 |
6698 // Part of ES6 9.4.2.4 ArraySetLength. | 6663 // Part of ES6 9.4.2.4 ArraySetLength. |
6699 // static | 6664 // static |
6700 bool JSArray::AnythingToArrayLength(Isolate* isolate, | 6665 bool JSArray::AnythingToArrayLength(Isolate* isolate, |
(...skipping 26 matching lines...) Expand all Loading... |
6727 isolate->Throw(*exception); | 6692 isolate->Throw(*exception); |
6728 return false; | 6693 return false; |
6729 } | 6694 } |
6730 CHECK(uint32_v->ToArrayLength(output)); | 6695 CHECK(uint32_v->ToArrayLength(output)); |
6731 return true; | 6696 return true; |
6732 } | 6697 } |
6733 | 6698 |
6734 | 6699 |
6735 // ES6 9.4.2.4 | 6700 // ES6 9.4.2.4 |
6736 // static | 6701 // static |
6737 bool JSArray::ArraySetLength(Isolate* isolate, Handle<JSArray> a, | 6702 Maybe<bool> JSArray::ArraySetLength(Isolate* isolate, Handle<JSArray> a, |
6738 PropertyDescriptor* desc, | 6703 PropertyDescriptor* desc, |
6739 ShouldThrow should_throw) { | 6704 ShouldThrow should_throw) { |
6740 // 1. If the [[Value]] field of Desc is absent, then | 6705 // 1. If the [[Value]] field of Desc is absent, then |
6741 if (!desc->has_value()) { | 6706 if (!desc->has_value()) { |
6742 // 1a. Return OrdinaryDefineOwnProperty(A, "length", Desc). | 6707 // 1a. Return OrdinaryDefineOwnProperty(A, "length", Desc). |
6743 return OrdinaryDefineOwnProperty( | 6708 return OrdinaryDefineOwnProperty( |
6744 isolate, a, isolate->factory()->length_string(), desc, should_throw); | 6709 isolate, a, isolate->factory()->length_string(), desc, should_throw); |
6745 } | 6710 } |
6746 // 2. Let newLenDesc be a copy of Desc. | 6711 // 2. Let newLenDesc be a copy of Desc. |
6747 // (Actual copying is not necessary.) | 6712 // (Actual copying is not necessary.) |
6748 PropertyDescriptor* new_len_desc = desc; | 6713 PropertyDescriptor* new_len_desc = desc; |
6749 // 3. - 7. Convert Desc.[[Value]] to newLen. | 6714 // 3. - 7. Convert Desc.[[Value]] to newLen. |
6750 uint32_t new_len = 0; | 6715 uint32_t new_len = 0; |
6751 if (!AnythingToArrayLength(isolate, desc->value(), &new_len)) { | 6716 if (!AnythingToArrayLength(isolate, desc->value(), &new_len)) { |
6752 if (should_throw == THROW_ON_ERROR && !isolate->has_pending_exception()) { | 6717 DCHECK(isolate->has_pending_exception()); |
6753 isolate->Throw(*isolate->factory()->NewTypeError( | 6718 return Nothing<bool>(); |
6754 MessageTemplate::kCannotConvertToPrimitive)); | |
6755 } | |
6756 return false; | |
6757 } | 6719 } |
6758 // 8. Set newLenDesc.[[Value]] to newLen. | 6720 // 8. Set newLenDesc.[[Value]] to newLen. |
6759 // (Done below, if needed.) | 6721 // (Done below, if needed.) |
6760 // 9. Let oldLenDesc be OrdinaryGetOwnProperty(A, "length"). | 6722 // 9. Let oldLenDesc be OrdinaryGetOwnProperty(A, "length"). |
6761 PropertyDescriptor old_len_desc; | 6723 PropertyDescriptor old_len_desc; |
6762 bool success = GetOwnPropertyDescriptor( | 6724 Maybe<bool> success = GetOwnPropertyDescriptor( |
6763 isolate, a, isolate->factory()->length_string(), &old_len_desc); | 6725 isolate, a, isolate->factory()->length_string(), &old_len_desc); |
6764 // 10. (Assert) | 6726 // 10. (Assert) |
6765 DCHECK(success); | 6727 DCHECK(success.FromJust()); |
6766 USE(success); | 6728 USE(success); |
6767 // 11. Let oldLen be oldLenDesc.[[Value]]. | 6729 // 11. Let oldLen be oldLenDesc.[[Value]]. |
6768 uint32_t old_len = 0; | 6730 uint32_t old_len = 0; |
6769 CHECK(old_len_desc.value()->ToArrayLength(&old_len)); | 6731 CHECK(old_len_desc.value()->ToArrayLength(&old_len)); |
6770 // 12. If newLen >= oldLen, then | 6732 // 12. If newLen >= oldLen, then |
6771 if (new_len >= old_len) { | 6733 if (new_len >= old_len) { |
6772 // 8. Set newLenDesc.[[Value]] to newLen. | 6734 // 8. Set newLenDesc.[[Value]] to newLen. |
6773 // 12a. Return OrdinaryDefineOwnProperty(A, "length", newLenDesc). | 6735 // 12a. Return OrdinaryDefineOwnProperty(A, "length", newLenDesc). |
6774 new_len_desc->set_value(isolate->factory()->NewNumberFromUint(new_len)); | 6736 new_len_desc->set_value(isolate->factory()->NewNumberFromUint(new_len)); |
6775 return OrdinaryDefineOwnProperty(isolate, a, | 6737 return OrdinaryDefineOwnProperty(isolate, a, |
6776 isolate->factory()->length_string(), | 6738 isolate->factory()->length_string(), |
6777 new_len_desc, should_throw); | 6739 new_len_desc, should_throw); |
6778 } | 6740 } |
6779 // 13. If oldLenDesc.[[Writable]] is false, return false. | 6741 // 13. If oldLenDesc.[[Writable]] is false, return false. |
6780 if (!old_len_desc.writable()) { | 6742 if (!old_len_desc.writable()) { |
6781 if (should_throw == THROW_ON_ERROR) | 6743 RETURN_FAILURE(isolate, should_throw, |
6782 isolate->Throw(*isolate->factory()->NewTypeError( | 6744 NewTypeError(MessageTemplate::kRedefineDisallowed, |
6783 MessageTemplate::kRedefineDisallowed, | 6745 isolate->factory()->length_string())); |
6784 isolate->factory()->length_string())); | |
6785 return false; | |
6786 } | 6746 } |
6787 // 14. If newLenDesc.[[Writable]] is absent or has the value true, | 6747 // 14. If newLenDesc.[[Writable]] is absent or has the value true, |
6788 // let newWritable be true. | 6748 // let newWritable be true. |
6789 bool new_writable = false; | 6749 bool new_writable = false; |
6790 if (!new_len_desc->has_writable() || new_len_desc->writable()) { | 6750 if (!new_len_desc->has_writable() || new_len_desc->writable()) { |
6791 new_writable = true; | 6751 new_writable = true; |
6792 } else { | 6752 } else { |
6793 // 15. Else, | 6753 // 15. Else, |
6794 // 15a. Need to defer setting the [[Writable]] attribute to false in case | 6754 // 15a. Need to defer setting the [[Writable]] attribute to false in case |
6795 // any elements cannot be deleted. | 6755 // any elements cannot be deleted. |
6796 // 15b. Let newWritable be false. (It's initialized as "false" anyway.) | 6756 // 15b. Let newWritable be false. (It's initialized as "false" anyway.) |
6797 // 15c. Set newLenDesc.[[Writable]] to true. | 6757 // 15c. Set newLenDesc.[[Writable]] to true. |
6798 // (Not needed.) | 6758 // (Not needed.) |
6799 } | 6759 } |
6800 // Most of steps 16 through 19 is implemented by JSArray::SetLength. | 6760 // Most of steps 16 through 19 is implemented by JSArray::SetLength. |
6801 if (JSArray::ObservableSetLength(a, new_len).is_null()) { | 6761 if (JSArray::ObservableSetLength(a, new_len).is_null()) { |
6802 DCHECK(isolate->has_pending_exception()); | 6762 DCHECK(isolate->has_pending_exception()); |
6803 return false; | 6763 return Nothing<bool>(); |
6804 } | 6764 } |
6805 // Steps 19d-ii, 20. | 6765 // Steps 19d-ii, 20. |
6806 if (!new_writable) { | 6766 if (!new_writable) { |
6807 PropertyDescriptor readonly; | 6767 PropertyDescriptor readonly; |
6808 readonly.set_writable(false); | 6768 readonly.set_writable(false); |
6809 OrdinaryDefineOwnProperty(isolate, a, isolate->factory()->length_string(), | 6769 Maybe<bool> success = OrdinaryDefineOwnProperty( |
6810 &readonly, should_throw); | 6770 isolate, a, isolate->factory()->length_string(), &readonly, |
| 6771 should_throw); |
| 6772 DCHECK(success.FromJust()); |
| 6773 USE(success); |
6811 } | 6774 } |
6812 uint32_t actual_new_len = 0; | 6775 uint32_t actual_new_len = 0; |
6813 CHECK(a->length()->ToArrayLength(&actual_new_len)); | 6776 CHECK(a->length()->ToArrayLength(&actual_new_len)); |
6814 // Steps 19d-v, 21. Return false if there were non-deletable elements. | 6777 // Steps 19d-v, 21. Return false if there were non-deletable elements. |
6815 success = actual_new_len == new_len; | 6778 bool result = actual_new_len == new_len; |
6816 if (!success && should_throw == THROW_ON_ERROR) { | 6779 if (!result) { |
6817 isolate->Throw(*isolate->factory()->NewTypeError( | 6780 RETURN_FAILURE( |
6818 MessageTemplate::kStrictDeleteProperty, | 6781 isolate, should_throw, |
6819 isolate->factory()->NewNumberFromUint(actual_new_len - 1), a)); | 6782 NewTypeError(MessageTemplate::kStrictDeleteProperty, |
| 6783 isolate->factory()->NewNumberFromUint(actual_new_len - 1), |
| 6784 a)); |
6820 } | 6785 } |
6821 return success; | 6786 return Just(result); |
6822 } | 6787 } |
6823 | 6788 |
6824 | 6789 |
6825 // ES6 9.5.6 | 6790 // ES6 9.5.6 |
6826 // static | 6791 // static |
6827 bool JSProxy::DefineOwnProperty(Isolate* isolate, Handle<JSProxy> proxy, | 6792 Maybe<bool> JSProxy::DefineOwnProperty(Isolate* isolate, Handle<JSProxy> proxy, |
6828 Handle<Object> key, PropertyDescriptor* desc, | 6793 Handle<Object> key, |
6829 ShouldThrow should_throw) { | 6794 PropertyDescriptor* desc, |
| 6795 ShouldThrow should_throw) { |
6830 Handle<String> trap_name = isolate->factory()->defineProperty_string(); | 6796 Handle<String> trap_name = isolate->factory()->defineProperty_string(); |
6831 // 1. Assert: IsPropertyKey(P) is true. | 6797 // 1. Assert: IsPropertyKey(P) is true. |
6832 DCHECK(key->IsName() || key->IsNumber()); | 6798 DCHECK(key->IsName() || key->IsNumber()); |
6833 // 2. Let handler be the value of the [[ProxyHandler]] internal slot of O. | 6799 // 2. Let handler be the value of the [[ProxyHandler]] internal slot of O. |
6834 Handle<Object> handler(proxy->handler(), isolate); | 6800 Handle<Object> handler(proxy->handler(), isolate); |
6835 // 3. If handler is null, throw a TypeError exception. | 6801 // 3. If handler is null, throw a TypeError exception. |
6836 // 4. Assert: Type(handler) is Object. | 6802 // 4. Assert: Type(handler) is Object. |
6837 if (proxy->IsRevoked()) { | 6803 if (proxy->IsRevoked()) { |
6838 isolate->Throw(*isolate->factory()->NewTypeError( | 6804 isolate->Throw(*isolate->factory()->NewTypeError( |
6839 MessageTemplate::kProxyRevoked, trap_name)); | 6805 MessageTemplate::kProxyRevoked, trap_name)); |
6840 return false; | 6806 return Nothing<bool>(); |
6841 } | 6807 } |
6842 // 5. Let target be the value of the [[ProxyTarget]] internal slot of O. | 6808 // 5. Let target be the value of the [[ProxyTarget]] internal slot of O. |
6843 Handle<JSReceiver> target(proxy->target(), isolate); | 6809 Handle<JSReceiver> target(proxy->target(), isolate); |
6844 // 6. Let trap be ? GetMethod(handler, "defineProperty"). | 6810 // 6. Let trap be ? GetMethod(handler, "defineProperty"). |
6845 Handle<Object> trap; | 6811 Handle<Object> trap; |
6846 ASSIGN_RETURN_ON_EXCEPTION_VALUE( | 6812 ASSIGN_RETURN_ON_EXCEPTION_VALUE( |
6847 isolate, trap, | 6813 isolate, trap, |
6848 Object::GetMethod(Handle<JSReceiver>::cast(handler), trap_name), false); | 6814 Object::GetMethod(Handle<JSReceiver>::cast(handler), trap_name), |
| 6815 Nothing<bool>()); |
6849 // 7. If trap is undefined, then: | 6816 // 7. If trap is undefined, then: |
6850 if (trap->IsUndefined()) { | 6817 if (trap->IsUndefined()) { |
6851 // 7a. Return target.[[DefineOwnProperty]](P, Desc). | 6818 // 7a. Return target.[[DefineOwnProperty]](P, Desc). |
6852 return JSReceiver::DefineOwnProperty(isolate, target, key, desc, | 6819 return JSReceiver::DefineOwnProperty(isolate, target, key, desc, |
6853 should_throw); | 6820 should_throw); |
6854 } | 6821 } |
6855 // 8. Let descObj be FromPropertyDescriptor(Desc). | 6822 // 8. Let descObj be FromPropertyDescriptor(Desc). |
6856 Handle<Object> desc_obj = desc->ToObject(isolate); | 6823 Handle<Object> desc_obj = desc->ToObject(isolate); |
6857 // 9. Let booleanTrapResult be | 6824 // 9. Let booleanTrapResult be |
6858 // ToBoolean(? Call(trap, handler, «target, P, descObj»)). | 6825 // ToBoolean(? Call(trap, handler, «target, P, descObj»)). |
6859 Handle<Name> property_name = | 6826 Handle<Name> property_name = |
6860 key->IsName() | 6827 key->IsName() |
6861 ? Handle<Name>::cast(key) | 6828 ? Handle<Name>::cast(key) |
6862 : Handle<Name>::cast(isolate->factory()->NumberToString(key)); | 6829 : Handle<Name>::cast(isolate->factory()->NumberToString(key)); |
6863 Handle<Object> trap_result_obj; | 6830 Handle<Object> trap_result_obj; |
6864 Handle<Object> args[] = {target, property_name, desc_obj}; | 6831 Handle<Object> args[] = {target, property_name, desc_obj}; |
6865 ASSIGN_RETURN_ON_EXCEPTION_VALUE( | 6832 ASSIGN_RETURN_ON_EXCEPTION_VALUE( |
6866 isolate, trap_result_obj, | 6833 isolate, trap_result_obj, |
6867 Execution::Call(isolate, trap, handler, arraysize(args), args), false); | 6834 Execution::Call(isolate, trap, handler, arraysize(args), args), |
| 6835 Nothing<bool>()); |
6868 // 10. If booleanTrapResult is false, return false. | 6836 // 10. If booleanTrapResult is false, return false. |
6869 if (!trap_result_obj->BooleanValue()) { | 6837 if (!trap_result_obj->BooleanValue()) { |
6870 if (should_throw == THROW_ON_ERROR) { | 6838 // TODO(jkummerow): Better error message? |
6871 // TODO(jkummerow): Better error message? | 6839 RETURN_FAILURE(isolate, should_throw, |
6872 isolate->Throw(*isolate->factory()->NewTypeError( | 6840 NewTypeError(MessageTemplate::kProxyHandlerReturned, handler, |
6873 MessageTemplate::kProxyHandlerReturned, handler, trap_result_obj, | 6841 trap_result_obj, trap_name)); |
6874 trap_name)); | |
6875 } | |
6876 return false; | |
6877 } | 6842 } |
6878 // 11. Let targetDesc be ? target.[[GetOwnProperty]](P). | 6843 // 11. Let targetDesc be ? target.[[GetOwnProperty]](P). |
6879 PropertyDescriptor target_desc; | 6844 PropertyDescriptor target_desc; |
6880 bool target_found = | 6845 Maybe<bool> target_found = |
6881 JSReceiver::GetOwnPropertyDescriptor(isolate, target, key, &target_desc); | 6846 JSReceiver::GetOwnPropertyDescriptor(isolate, target, key, &target_desc); |
6882 if (isolate->has_pending_exception()) return false; | 6847 MAYBE_RETURN(target_found, Nothing<bool>()); |
6883 // 12. Let extensibleTarget be ? IsExtensible(target). | 6848 // 12. Let extensibleTarget be ? IsExtensible(target). |
6884 Maybe<bool> maybe_extensible = JSReceiver::IsExtensible(target); | 6849 Maybe<bool> maybe_extensible = JSReceiver::IsExtensible(target); |
6885 if (maybe_extensible.IsNothing()) return false; | 6850 MAYBE_RETURN(maybe_extensible, Nothing<bool>()); |
6886 bool extensible_target = maybe_extensible.FromJust(); | 6851 bool extensible_target = maybe_extensible.FromJust(); |
6887 // 13. If Desc has a [[Configurable]] field and if Desc.[[Configurable]] | 6852 // 13. If Desc has a [[Configurable]] field and if Desc.[[Configurable]] |
6888 // is false, then: | 6853 // is false, then: |
6889 // 13a. Let settingConfigFalse be true. | 6854 // 13a. Let settingConfigFalse be true. |
6890 // 14. Else let settingConfigFalse be false. | 6855 // 14. Else let settingConfigFalse be false. |
6891 bool setting_config_false = desc->has_configurable() && !desc->configurable(); | 6856 bool setting_config_false = desc->has_configurable() && !desc->configurable(); |
6892 // 15. If targetDesc is undefined, then | 6857 // 15. If targetDesc is undefined, then |
6893 if (!target_found) { | 6858 if (!target_found.FromJust()) { |
6894 // 15a. If extensibleTarget is false, throw a TypeError exception. | 6859 // 15a. If extensibleTarget is false, throw a TypeError exception. |
6895 if (!extensible_target) { | 6860 if (!extensible_target) { |
6896 isolate->Throw(*isolate->factory()->NewTypeError( | 6861 isolate->Throw(*isolate->factory()->NewTypeError( |
6897 MessageTemplate::kProxyTargetNotExtensible)); | 6862 MessageTemplate::kProxyTargetNotExtensible)); |
6898 return false; | 6863 return Nothing<bool>(); |
6899 } | 6864 } |
6900 // 15b. If settingConfigFalse is true, throw a TypeError exception. | 6865 // 15b. If settingConfigFalse is true, throw a TypeError exception. |
6901 if (setting_config_false) { | 6866 if (setting_config_false) { |
6902 // TODO(jkummerow): Better error message? | 6867 // TODO(jkummerow): Better error message? |
6903 isolate->Throw(*isolate->factory()->NewTypeError( | 6868 isolate->Throw(*isolate->factory()->NewTypeError( |
6904 MessageTemplate::kRedefineDisallowed, key)); | 6869 MessageTemplate::kRedefineDisallowed, key)); |
6905 return false; | 6870 return Nothing<bool>(); |
6906 } | 6871 } |
6907 } else { | 6872 } else { |
6908 // 16. Else targetDesc is not undefined, | 6873 // 16. Else targetDesc is not undefined, |
6909 // 16a. If IsCompatiblePropertyDescriptor(extensibleTarget, Desc, | 6874 // 16a. If IsCompatiblePropertyDescriptor(extensibleTarget, Desc, |
6910 // targetDesc) is false, throw a TypeError exception. | 6875 // targetDesc) is false, throw a TypeError exception. |
6911 bool valid = IsCompatiblePropertyDescriptor( | 6876 Maybe<bool> valid = IsCompatiblePropertyDescriptor( |
6912 isolate, extensible_target, desc, &target_desc, property_name); | 6877 isolate, extensible_target, desc, &target_desc, property_name); |
6913 if (!valid) { | 6878 MAYBE_RETURN(valid, Nothing<bool>()); |
6914 DCHECK(isolate->has_pending_exception()); | 6879 DCHECK(valid.FromJust()); |
6915 return false; | |
6916 } | |
6917 // 16b. If settingConfigFalse is true and targetDesc.[[Configurable]] is | 6880 // 16b. If settingConfigFalse is true and targetDesc.[[Configurable]] is |
6918 // true, throw a TypeError exception. | 6881 // true, throw a TypeError exception. |
6919 if (setting_config_false && target_desc.configurable()) { | 6882 if (setting_config_false && target_desc.configurable()) { |
6920 // TODO(jkummerow): Better error message? | 6883 // TODO(jkummerow): Better error message? |
6921 isolate->Throw(*isolate->factory()->NewTypeError( | 6884 isolate->Throw(*isolate->factory()->NewTypeError( |
6922 MessageTemplate::kRedefineDisallowed, key)); | 6885 MessageTemplate::kRedefineDisallowed, key)); |
6923 return false; | 6886 return Nothing<bool>(); |
6924 } | 6887 } |
6925 } | 6888 } |
6926 // 17. Return true. | 6889 // 17. Return true. |
6927 return true; | 6890 return Just(true); |
6928 } | 6891 } |
6929 | 6892 |
6930 | 6893 |
6931 // static | 6894 // static |
6932 bool JSReceiver::GetOwnPropertyDescriptor(Isolate* isolate, | 6895 Maybe<bool> JSReceiver::GetOwnPropertyDescriptor(Isolate* isolate, |
6933 Handle<JSReceiver> object, | 6896 Handle<JSReceiver> object, |
6934 Handle<Object> key, | 6897 Handle<Object> key, |
6935 PropertyDescriptor* desc) { | 6898 PropertyDescriptor* desc) { |
6936 bool success = false; | 6899 bool success = false; |
6937 DCHECK(key->IsName() || key->IsNumber()); // |key| is a PropertyKey... | 6900 DCHECK(key->IsName() || key->IsNumber()); // |key| is a PropertyKey... |
6938 LookupIterator it = LookupIterator::PropertyOrElement( | 6901 LookupIterator it = LookupIterator::PropertyOrElement( |
6939 isolate, object, key, &success, LookupIterator::HIDDEN); | 6902 isolate, object, key, &success, LookupIterator::HIDDEN); |
6940 DCHECK(success); // ...so creating a LookupIterator can't fail. | 6903 DCHECK(success); // ...so creating a LookupIterator can't fail. |
6941 return GetOwnPropertyDescriptor(&it, desc); | 6904 return GetOwnPropertyDescriptor(&it, desc); |
6942 } | 6905 } |
6943 | 6906 |
6944 | 6907 |
6945 // TODO(jkummerow): Any chance to unify this with | |
6946 // "MaybeHandle<Object> GetOwnProperty()" in runtime-object.cc? | |
6947 | |
6948 // ES6 9.1.5.1 | 6908 // ES6 9.1.5.1 |
6949 // Returns true on success; false if there was an exception or no property. | 6909 // Returns true on success, false if the property didn't exist, nothing if |
| 6910 // an exception was thrown. |
6950 // static | 6911 // static |
6951 bool JSReceiver::GetOwnPropertyDescriptor(LookupIterator* it, | 6912 Maybe<bool> JSReceiver::GetOwnPropertyDescriptor(LookupIterator* it, |
6952 PropertyDescriptor* desc) { | 6913 PropertyDescriptor* desc) { |
6953 Isolate* isolate = it->isolate(); | 6914 Isolate* isolate = it->isolate(); |
6954 // "Virtual" dispatch. | 6915 // "Virtual" dispatch. |
6955 if (it->IsFound() && it->GetHolder<JSReceiver>()->IsJSProxy()) { | 6916 if (it->IsFound() && it->GetHolder<JSReceiver>()->IsJSProxy()) { |
6956 return JSProxy::GetOwnPropertyDescriptor(isolate, it->GetHolder<JSProxy>(), | 6917 return JSProxy::GetOwnPropertyDescriptor(isolate, it->GetHolder<JSProxy>(), |
6957 it->GetName(), desc); | 6918 it->GetName(), desc); |
6958 } | 6919 } |
6959 | 6920 |
6960 // 1. (Assert) | 6921 // 1. (Assert) |
6961 // 2. If O does not have an own property with key P, return undefined. | 6922 // 2. If O does not have an own property with key P, return undefined. |
6962 Maybe<PropertyAttributes> maybe = JSObject::GetPropertyAttributes(it); | 6923 Maybe<PropertyAttributes> maybe = JSObject::GetPropertyAttributes(it); |
6963 | 6924 MAYBE_RETURN(maybe, Nothing<bool>()); |
6964 if (!maybe.IsJust()) return false; | |
6965 PropertyAttributes attrs = maybe.FromJust(); | 6925 PropertyAttributes attrs = maybe.FromJust(); |
6966 if (attrs == ABSENT) return false; | 6926 if (attrs == ABSENT) return Just(false); |
6967 DCHECK(!isolate->has_pending_exception()); | 6927 DCHECK(!isolate->has_pending_exception()); |
6968 | 6928 |
6969 // 3. Let D be a newly created Property Descriptor with no fields. | 6929 // 3. Let D be a newly created Property Descriptor with no fields. |
6970 DCHECK(desc->is_empty()); | 6930 DCHECK(desc->is_empty()); |
6971 // 4. Let X be O's own property whose key is P. | 6931 // 4. Let X be O's own property whose key is P. |
6972 // 5. If X is a data property, then | 6932 // 5. If X is a data property, then |
6973 bool is_accessor_pair = it->state() == LookupIterator::ACCESSOR && | 6933 bool is_accessor_pair = it->state() == LookupIterator::ACCESSOR && |
6974 it->GetAccessors()->IsAccessorPair(); | 6934 it->GetAccessors()->IsAccessorPair(); |
6975 if (!is_accessor_pair) { | 6935 if (!is_accessor_pair) { |
6976 // 5a. Set D.[[Value]] to the value of X's [[Value]] attribute. | 6936 // 5a. Set D.[[Value]] to the value of X's [[Value]] attribute. |
6977 Handle<Object> value; | 6937 Handle<Object> value; |
6978 if (!JSObject::GetProperty(it).ToHandle(&value)) { | 6938 if (!JSObject::GetProperty(it).ToHandle(&value)) { |
6979 DCHECK(isolate->has_pending_exception()); | 6939 DCHECK(isolate->has_pending_exception()); |
6980 return false; | 6940 return Nothing<bool>(); |
6981 } | 6941 } |
6982 desc->set_value(value); | 6942 desc->set_value(value); |
6983 // 5b. Set D.[[Writable]] to the value of X's [[Writable]] attribute | 6943 // 5b. Set D.[[Writable]] to the value of X's [[Writable]] attribute |
6984 desc->set_writable((attrs & READ_ONLY) == 0); | 6944 desc->set_writable((attrs & READ_ONLY) == 0); |
6985 } else { | 6945 } else { |
6986 // 6. Else X is an accessor property, so | 6946 // 6. Else X is an accessor property, so |
6987 Handle<AccessorPair> accessors = | 6947 Handle<AccessorPair> accessors = |
6988 Handle<AccessorPair>::cast(it->GetAccessors()); | 6948 Handle<AccessorPair>::cast(it->GetAccessors()); |
6989 // 6a. Set D.[[Get]] to the value of X's [[Get]] attribute. | 6949 // 6a. Set D.[[Get]] to the value of X's [[Get]] attribute. |
6990 desc->set_get(handle(accessors->GetComponent(ACCESSOR_GETTER), isolate)); | 6950 desc->set_get(handle(accessors->GetComponent(ACCESSOR_GETTER), isolate)); |
6991 // 6b. Set D.[[Set]] to the value of X's [[Set]] attribute. | 6951 // 6b. Set D.[[Set]] to the value of X's [[Set]] attribute. |
6992 desc->set_set(handle(accessors->GetComponent(ACCESSOR_SETTER), isolate)); | 6952 desc->set_set(handle(accessors->GetComponent(ACCESSOR_SETTER), isolate)); |
6993 } | 6953 } |
6994 | 6954 |
6995 // 7. Set D.[[Enumerable]] to the value of X's [[Enumerable]] attribute. | 6955 // 7. Set D.[[Enumerable]] to the value of X's [[Enumerable]] attribute. |
6996 desc->set_enumerable((attrs & DONT_ENUM) == 0); | 6956 desc->set_enumerable((attrs & DONT_ENUM) == 0); |
6997 // 8. Set D.[[Configurable]] to the value of X's [[Configurable]] attribute. | 6957 // 8. Set D.[[Configurable]] to the value of X's [[Configurable]] attribute. |
6998 desc->set_configurable((attrs & DONT_DELETE) == 0); | 6958 desc->set_configurable((attrs & DONT_DELETE) == 0); |
6999 // 9. Return D. | 6959 // 9. Return D. |
7000 DCHECK(PropertyDescriptor::IsAccessorDescriptor(desc) != | 6960 DCHECK(PropertyDescriptor::IsAccessorDescriptor(desc) != |
7001 PropertyDescriptor::IsDataDescriptor(desc)); | 6961 PropertyDescriptor::IsDataDescriptor(desc)); |
7002 return true; | 6962 return Just(true); |
7003 } | 6963 } |
7004 | 6964 |
7005 | 6965 |
7006 // ES6 9.5.5 | 6966 // ES6 9.5.5 |
7007 // static | 6967 // static |
7008 bool JSProxy::GetOwnPropertyDescriptor(Isolate* isolate, Handle<JSProxy> proxy, | 6968 Maybe<bool> JSProxy::GetOwnPropertyDescriptor(Isolate* isolate, |
7009 Handle<Name> name, | 6969 Handle<JSProxy> proxy, |
7010 PropertyDescriptor* desc) { | 6970 Handle<Name> name, |
| 6971 PropertyDescriptor* desc) { |
7011 Handle<String> trap_name = | 6972 Handle<String> trap_name = |
7012 isolate->factory()->getOwnPropertyDescriptor_string(); | 6973 isolate->factory()->getOwnPropertyDescriptor_string(); |
7013 // 1. (Assert) | 6974 // 1. (Assert) |
7014 // 2. Let handler be the value of the [[ProxyHandler]] internal slot of O. | 6975 // 2. Let handler be the value of the [[ProxyHandler]] internal slot of O. |
7015 Handle<Object> handler(proxy->handler(), isolate); | 6976 Handle<Object> handler(proxy->handler(), isolate); |
7016 // 3. If handler is null, throw a TypeError exception. | 6977 // 3. If handler is null, throw a TypeError exception. |
7017 // 4. Assert: Type(handler) is Object. | 6978 // 4. Assert: Type(handler) is Object. |
7018 if (proxy->IsRevoked()) { | 6979 if (proxy->IsRevoked()) { |
7019 isolate->Throw(*isolate->factory()->NewTypeError( | 6980 isolate->Throw(*isolate->factory()->NewTypeError( |
7020 MessageTemplate::kProxyRevoked, trap_name)); | 6981 MessageTemplate::kProxyRevoked, trap_name)); |
7021 return false; | 6982 return Nothing<bool>(); |
7022 } | 6983 } |
7023 // 5. Let target be the value of the [[ProxyTarget]] internal slot of O. | 6984 // 5. Let target be the value of the [[ProxyTarget]] internal slot of O. |
7024 Handle<JSReceiver> target(proxy->target(), isolate); | 6985 Handle<JSReceiver> target(proxy->target(), isolate); |
7025 // 6. Let trap be ? GetMethod(handler, "getOwnPropertyDescriptor"). | 6986 // 6. Let trap be ? GetMethod(handler, "getOwnPropertyDescriptor"). |
7026 Handle<Object> trap; | 6987 Handle<Object> trap; |
7027 ASSIGN_RETURN_ON_EXCEPTION_VALUE( | 6988 ASSIGN_RETURN_ON_EXCEPTION_VALUE( |
7028 isolate, trap, | 6989 isolate, trap, |
7029 Object::GetMethod(Handle<JSReceiver>::cast(handler), trap_name), false); | 6990 Object::GetMethod(Handle<JSReceiver>::cast(handler), trap_name), |
| 6991 Nothing<bool>()); |
7030 // 7. If trap is undefined, then | 6992 // 7. If trap is undefined, then |
7031 if (trap->IsUndefined()) { | 6993 if (trap->IsUndefined()) { |
7032 // 7a. Return target.[[GetOwnProperty]](P). | 6994 // 7a. Return target.[[GetOwnProperty]](P). |
7033 return JSReceiver::GetOwnPropertyDescriptor(isolate, target, name, desc); | 6995 return JSReceiver::GetOwnPropertyDescriptor(isolate, target, name, desc); |
7034 } | 6996 } |
7035 // 8. Let trapResultObj be ? Call(trap, handler, «target, P»). | 6997 // 8. Let trapResultObj be ? Call(trap, handler, «target, P»). |
7036 Handle<Object> trap_result_obj; | 6998 Handle<Object> trap_result_obj; |
7037 Handle<Object> args[] = {target, name}; | 6999 Handle<Object> args[] = {target, name}; |
7038 ASSIGN_RETURN_ON_EXCEPTION_VALUE( | 7000 ASSIGN_RETURN_ON_EXCEPTION_VALUE( |
7039 isolate, trap_result_obj, | 7001 isolate, trap_result_obj, |
7040 Execution::Call(isolate, trap, handler, arraysize(args), args), false); | 7002 Execution::Call(isolate, trap, handler, arraysize(args), args), |
| 7003 Nothing<bool>()); |
7041 // 9. If Type(trapResultObj) is neither Object nor Undefined, throw a | 7004 // 9. If Type(trapResultObj) is neither Object nor Undefined, throw a |
7042 // TypeError exception. | 7005 // TypeError exception. |
7043 if (!trap_result_obj->IsJSReceiver() && !trap_result_obj->IsUndefined()) { | 7006 if (!trap_result_obj->IsJSReceiver() && !trap_result_obj->IsUndefined()) { |
7044 isolate->Throw(*isolate->factory()->NewTypeError( | 7007 isolate->Throw(*isolate->factory()->NewTypeError( |
7045 MessageTemplate::kProxyHandlerReturned, handler, trap_result_obj, | 7008 MessageTemplate::kProxyHandlerReturned, handler, trap_result_obj, |
7046 name)); | 7009 name)); |
7047 return false; | 7010 return Nothing<bool>(); |
7048 } | 7011 } |
7049 // 10. Let targetDesc be ? target.[[GetOwnProperty]](P). | 7012 // 10. Let targetDesc be ? target.[[GetOwnProperty]](P). |
7050 PropertyDescriptor target_desc; | 7013 PropertyDescriptor target_desc; |
7051 JSReceiver::GetOwnPropertyDescriptor(isolate, target, name, &target_desc); | 7014 Maybe<bool> found = |
7052 if (isolate->has_pending_exception()) return false; | 7015 JSReceiver::GetOwnPropertyDescriptor(isolate, target, name, &target_desc); |
| 7016 MAYBE_RETURN(found, Nothing<bool>()); |
7053 // 11. If trapResultObj is undefined, then | 7017 // 11. If trapResultObj is undefined, then |
7054 if (trap_result_obj->IsUndefined()) { | 7018 if (trap_result_obj->IsUndefined()) { |
7055 // 11a. If targetDesc is undefined, return undefined. | 7019 // 11a. If targetDesc is undefined, return undefined. |
7056 if (target_desc.is_empty()) return false; | 7020 if (!found.FromJust()) return Just(false); |
7057 // 11b. If targetDesc.[[Configurable]] is false, throw a TypeError | 7021 // 11b. If targetDesc.[[Configurable]] is false, throw a TypeError |
7058 // exception. | 7022 // exception. |
7059 if (!target_desc.configurable()) { | 7023 if (!target_desc.configurable()) { |
7060 isolate->Throw(*isolate->factory()->NewTypeError( | 7024 isolate->Throw(*isolate->factory()->NewTypeError( |
7061 MessageTemplate::kProxyTargetPropNotConfigurable, name)); | 7025 MessageTemplate::kProxyTargetPropNotConfigurable, name)); |
7062 return false; | 7026 return Nothing<bool>(); |
7063 } | 7027 } |
7064 // 11c. Let extensibleTarget be ? IsExtensible(target). | 7028 // 11c. Let extensibleTarget be ? IsExtensible(target). |
7065 Maybe<bool> maybe_extensible = JSReceiver::IsExtensible(target); | 7029 Maybe<bool> extensible_target = JSReceiver::IsExtensible(target); |
7066 if (maybe_extensible.IsNothing()) return false; | 7030 MAYBE_RETURN(extensible_target, Nothing<bool>()); |
7067 bool extensible_target = maybe_extensible.FromJust(); | |
7068 // 11d. (Assert) | 7031 // 11d. (Assert) |
7069 // 11e. If extensibleTarget is false, throw a TypeError exception. | 7032 // 11e. If extensibleTarget is false, throw a TypeError exception. |
7070 if (!extensible_target) { | 7033 if (!extensible_target.FromJust()) { |
7071 isolate->Throw(*isolate->factory()->NewTypeError( | 7034 isolate->Throw(*isolate->factory()->NewTypeError( |
7072 MessageTemplate::kProxyTargetNotExtensible)); | 7035 MessageTemplate::kProxyTargetNotExtensible)); |
7073 return false; | 7036 return Nothing<bool>(); |
7074 } | 7037 } |
7075 // 11f. Return undefined. | 7038 // 11f. Return undefined. |
7076 return false; // |desc->is_empty()| is what JavaScript calls "undefined". | 7039 return Just(false); |
7077 } | 7040 } |
7078 // 12. Let extensibleTarget be ? IsExtensible(target). | 7041 // 12. Let extensibleTarget be ? IsExtensible(target). |
7079 Maybe<bool> maybe_extensible = JSReceiver::IsExtensible(target); | 7042 Maybe<bool> extensible_target = JSReceiver::IsExtensible(target); |
7080 if (maybe_extensible.IsNothing()) return false; | 7043 MAYBE_RETURN(extensible_target, Nothing<bool>()); |
7081 bool extensible_target = maybe_extensible.FromJust(); | |
7082 // 13. Let resultDesc be ? ToPropertyDescriptor(trapResultObj). | 7044 // 13. Let resultDesc be ? ToPropertyDescriptor(trapResultObj). |
7083 if (!PropertyDescriptor::ToPropertyDescriptor(isolate, trap_result_obj, | 7045 if (!PropertyDescriptor::ToPropertyDescriptor(isolate, trap_result_obj, |
7084 desc)) { | 7046 desc)) { |
7085 DCHECK(isolate->has_pending_exception()); | 7047 DCHECK(isolate->has_pending_exception()); |
7086 return false; | 7048 return Nothing<bool>(); |
7087 } | 7049 } |
7088 // 14. Call CompletePropertyDescriptor(resultDesc). | 7050 // 14. Call CompletePropertyDescriptor(resultDesc). |
7089 PropertyDescriptor::CompletePropertyDescriptor(isolate, desc); | 7051 PropertyDescriptor::CompletePropertyDescriptor(isolate, desc); |
7090 // 15. Let valid be IsCompatiblePropertyDescriptor (extensibleTarget, | 7052 // 15. Let valid be IsCompatiblePropertyDescriptor (extensibleTarget, |
7091 // resultDesc, targetDesc). | 7053 // resultDesc, targetDesc). |
7092 bool valid = IsCompatiblePropertyDescriptor(isolate, extensible_target, desc, | 7054 Maybe<bool> valid = IsCompatiblePropertyDescriptor( |
7093 &target_desc, name); | 7055 isolate, extensible_target.FromJust(), desc, &target_desc, name); |
7094 // 16. If valid is false, throw a TypeError exception. | 7056 // 16. If valid is false, throw a TypeError exception. |
7095 if (!valid) { | 7057 MAYBE_RETURN(valid, Nothing<bool>()); |
7096 DCHECK(isolate->has_pending_exception()); | 7058 DCHECK(valid.FromJust()); |
7097 return false; | |
7098 } | |
7099 // 17. If resultDesc.[[Configurable]] is false, then | 7059 // 17. If resultDesc.[[Configurable]] is false, then |
7100 if (!desc->configurable()) { | 7060 if (!desc->configurable()) { |
7101 // 17a. If targetDesc is undefined or targetDesc.[[Configurable]] is true: | 7061 // 17a. If targetDesc is undefined or targetDesc.[[Configurable]] is true: |
7102 if (target_desc.is_empty() || target_desc.configurable()) { | 7062 if (target_desc.is_empty() || target_desc.configurable()) { |
7103 // 17a i. Throw a TypeError exception. | 7063 // 17a i. Throw a TypeError exception. |
7104 isolate->Throw(*isolate->factory()->NewTypeError( | 7064 isolate->Throw(*isolate->factory()->NewTypeError( |
7105 MessageTemplate::kRedefineDisallowed, name)); | 7065 MessageTemplate::kRedefineDisallowed, name)); |
7106 return false; | 7066 return Nothing<bool>(); |
7107 } | 7067 } |
7108 } | 7068 } |
7109 // 18. Return resultDesc. | 7069 // 18. Return resultDesc. |
7110 return true; | 7070 return Just(true); |
7111 } | 7071 } |
7112 | 7072 |
7113 | 7073 |
7114 bool JSObject::ReferencesObjectFromElements(FixedArray* elements, | 7074 bool JSObject::ReferencesObjectFromElements(FixedArray* elements, |
7115 ElementsKind kind, | 7075 ElementsKind kind, |
7116 Object* object) { | 7076 Object* object) { |
7117 DCHECK(IsFastObjectElementsKind(kind) || | 7077 DCHECK(IsFastObjectElementsKind(kind) || |
7118 kind == DICTIONARY_ELEMENTS); | 7078 kind == DICTIONARY_ELEMENTS); |
7119 if (IsFastObjectElementsKind(kind)) { | 7079 if (IsFastObjectElementsKind(kind)) { |
7120 int length = IsJSArray() | 7080 int length = IsJSArray() |
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7278 PropertyDescriptor no_conf; | 7238 PropertyDescriptor no_conf; |
7279 no_conf.set_configurable(false); | 7239 no_conf.set_configurable(false); |
7280 | 7240 |
7281 PropertyDescriptor no_conf_no_write; | 7241 PropertyDescriptor no_conf_no_write; |
7282 no_conf_no_write.set_configurable(false); | 7242 no_conf_no_write.set_configurable(false); |
7283 no_conf_no_write.set_writable(false); | 7243 no_conf_no_write.set_writable(false); |
7284 | 7244 |
7285 if (level == SEALED) { | 7245 if (level == SEALED) { |
7286 for (int i = 0; i < keys->length(); ++i) { | 7246 for (int i = 0; i < keys->length(); ++i) { |
7287 Handle<Object> key(keys->get(i), isolate); | 7247 Handle<Object> key(keys->get(i), isolate); |
7288 DefineOwnProperty(isolate, receiver, key, &no_conf, THROW_ON_ERROR); | 7248 MAYBE_RETURN( |
7289 if (isolate->has_pending_exception()) return Nothing<bool>(); | 7249 DefineOwnProperty(isolate, receiver, key, &no_conf, THROW_ON_ERROR), |
| 7250 Nothing<bool>()); |
7290 } | 7251 } |
7291 return Just(true); | 7252 return Just(true); |
7292 } | 7253 } |
7293 | 7254 |
7294 for (int i = 0; i < keys->length(); ++i) { | 7255 for (int i = 0; i < keys->length(); ++i) { |
7295 Handle<Object> key(keys->get(i), isolate); | 7256 Handle<Object> key(keys->get(i), isolate); |
7296 PropertyDescriptor current_desc; | 7257 PropertyDescriptor current_desc; |
7297 bool owned = JSReceiver::GetOwnPropertyDescriptor(isolate, receiver, key, | 7258 Maybe<bool> owned = JSReceiver::GetOwnPropertyDescriptor( |
7298 ¤t_desc); | 7259 isolate, receiver, key, ¤t_desc); |
7299 if (isolate->has_pending_exception()) return Nothing<bool>(); | 7260 MAYBE_RETURN(owned, Nothing<bool>()); |
7300 if (owned) { | 7261 if (owned.FromJust()) { |
7301 PropertyDescriptor desc = | 7262 PropertyDescriptor desc = |
7302 PropertyDescriptor::IsAccessorDescriptor(¤t_desc) | 7263 PropertyDescriptor::IsAccessorDescriptor(¤t_desc) |
7303 ? no_conf | 7264 ? no_conf |
7304 : no_conf_no_write; | 7265 : no_conf_no_write; |
7305 DefineOwnProperty(isolate, receiver, key, &desc, THROW_ON_ERROR); | 7266 MAYBE_RETURN( |
7306 if (isolate->has_pending_exception()) return Nothing<bool>(); | 7267 DefineOwnProperty(isolate, receiver, key, &desc, THROW_ON_ERROR), |
| 7268 Nothing<bool>()); |
7307 } | 7269 } |
7308 } | 7270 } |
7309 return Just(true); | 7271 return Just(true); |
7310 } | 7272 } |
7311 | 7273 |
7312 | 7274 |
7313 Maybe<bool> JSReceiver::TestIntegrityLevel(Handle<JSReceiver> object, | 7275 Maybe<bool> JSReceiver::TestIntegrityLevel(Handle<JSReceiver> object, |
7314 IntegrityLevel level) { | 7276 IntegrityLevel level) { |
7315 DCHECK(level == SEALED || level == FROZEN); | 7277 DCHECK(level == SEALED || level == FROZEN); |
7316 Isolate* isolate = object->GetIsolate(); | 7278 Isolate* isolate = object->GetIsolate(); |
7317 | 7279 |
7318 Maybe<bool> extensible = JSReceiver::IsExtensible(object); | 7280 Maybe<bool> extensible = JSReceiver::IsExtensible(object); |
7319 MAYBE_RETURN(extensible, Nothing<bool>()); | 7281 MAYBE_RETURN(extensible, Nothing<bool>()); |
7320 if (extensible.FromJust()) return Just(false); | 7282 if (extensible.FromJust()) return Just(false); |
7321 | 7283 |
7322 Handle<FixedArray> keys; | 7284 Handle<FixedArray> keys; |
7323 ASSIGN_RETURN_ON_EXCEPTION_VALUE( | 7285 ASSIGN_RETURN_ON_EXCEPTION_VALUE( |
7324 isolate, keys, JSReceiver::OwnPropertyKeys(object), Nothing<bool>()); | 7286 isolate, keys, JSReceiver::OwnPropertyKeys(object), Nothing<bool>()); |
7325 | 7287 |
7326 for (int i = 0; i < keys->length(); ++i) { | 7288 for (int i = 0; i < keys->length(); ++i) { |
7327 Handle<Object> key(keys->get(i), isolate); | 7289 Handle<Object> key(keys->get(i), isolate); |
7328 PropertyDescriptor current_desc; | 7290 PropertyDescriptor current_desc; |
7329 bool owned = JSReceiver::GetOwnPropertyDescriptor(isolate, object, key, | 7291 Maybe<bool> owned = JSReceiver::GetOwnPropertyDescriptor( |
7330 ¤t_desc); | 7292 isolate, object, key, ¤t_desc); |
7331 if (isolate->has_pending_exception()) return Nothing<bool>(); | 7293 MAYBE_RETURN(owned, Nothing<bool>()); |
7332 if (owned) { | 7294 if (owned.FromJust()) { |
7333 if (current_desc.configurable()) return Just(false); | 7295 if (current_desc.configurable()) return Just(false); |
7334 if (level == FROZEN && | 7296 if (level == FROZEN && |
7335 PropertyDescriptor::IsDataDescriptor(¤t_desc) && | 7297 PropertyDescriptor::IsDataDescriptor(¤t_desc) && |
7336 current_desc.writable()) { | 7298 current_desc.writable()) { |
7337 return Just(false); | 7299 return Just(false); |
7338 } | 7300 } |
7339 } | 7301 } |
7340 } | 7302 } |
7341 return Just(true); | 7303 return Just(true); |
7342 } | 7304 } |
(...skipping 19 matching lines...) Expand all Loading... |
7362 | 7324 |
7363 if (proxy->IsRevoked()) { | 7325 if (proxy->IsRevoked()) { |
7364 isolate->Throw( | 7326 isolate->Throw( |
7365 *factory->NewTypeError(MessageTemplate::kProxyRevoked, trap_name)); | 7327 *factory->NewTypeError(MessageTemplate::kProxyRevoked, trap_name)); |
7366 return Nothing<bool>(); | 7328 return Nothing<bool>(); |
7367 } | 7329 } |
7368 Handle<JSReceiver> target(proxy->target(), isolate); | 7330 Handle<JSReceiver> target(proxy->target(), isolate); |
7369 Handle<JSReceiver> handler(JSReceiver::cast(proxy->handler()), isolate); | 7331 Handle<JSReceiver> handler(JSReceiver::cast(proxy->handler()), isolate); |
7370 | 7332 |
7371 Handle<Object> trap; | 7333 Handle<Object> trap; |
7372 ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, trap, GetTrap(proxy, trap_name), | 7334 ASSIGN_RETURN_ON_EXCEPTION_VALUE( |
7373 Nothing<bool>()); | 7335 isolate, trap, Object::GetMethod(handler, trap_name), Nothing<bool>()); |
7374 if (trap->IsUndefined()) { | 7336 if (trap->IsUndefined()) { |
7375 return JSReceiver::PreventExtensions(target, should_throw); | 7337 return JSReceiver::PreventExtensions(target, should_throw); |
7376 } | 7338 } |
7377 | 7339 |
7378 Handle<Object> trap_result; | 7340 Handle<Object> trap_result; |
7379 Handle<Object> args[] = {target}; | 7341 Handle<Object> args[] = {target}; |
7380 ASSIGN_RETURN_ON_EXCEPTION_VALUE( | 7342 ASSIGN_RETURN_ON_EXCEPTION_VALUE( |
7381 isolate, trap_result, | 7343 isolate, trap_result, |
7382 Execution::Call(isolate, trap, handler, arraysize(args), args), | 7344 Execution::Call(isolate, trap, handler, arraysize(args), args), |
7383 Nothing<bool>()); | 7345 Nothing<bool>()); |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7471 | 7433 |
7472 if (proxy->IsRevoked()) { | 7434 if (proxy->IsRevoked()) { |
7473 isolate->Throw( | 7435 isolate->Throw( |
7474 *factory->NewTypeError(MessageTemplate::kProxyRevoked, trap_name)); | 7436 *factory->NewTypeError(MessageTemplate::kProxyRevoked, trap_name)); |
7475 return Nothing<bool>(); | 7437 return Nothing<bool>(); |
7476 } | 7438 } |
7477 Handle<JSReceiver> target(proxy->target(), isolate); | 7439 Handle<JSReceiver> target(proxy->target(), isolate); |
7478 Handle<JSReceiver> handler(JSReceiver::cast(proxy->handler()), isolate); | 7440 Handle<JSReceiver> handler(JSReceiver::cast(proxy->handler()), isolate); |
7479 | 7441 |
7480 Handle<Object> trap; | 7442 Handle<Object> trap; |
7481 ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, trap, GetTrap(proxy, trap_name), | 7443 ASSIGN_RETURN_ON_EXCEPTION_VALUE( |
7482 Nothing<bool>()); | 7444 isolate, trap, Object::GetMethod(handler, trap_name), Nothing<bool>()); |
7483 if (trap->IsUndefined()) { | 7445 if (trap->IsUndefined()) { |
7484 return JSReceiver::IsExtensible(target); | 7446 return JSReceiver::IsExtensible(target); |
7485 } | 7447 } |
7486 | 7448 |
7487 Handle<Object> trap_result; | 7449 Handle<Object> trap_result; |
7488 Handle<Object> args[] = {target}; | 7450 Handle<Object> args[] = {target}; |
7489 ASSIGN_RETURN_ON_EXCEPTION_VALUE( | 7451 ASSIGN_RETURN_ON_EXCEPTION_VALUE( |
7490 isolate, trap_result, | 7452 isolate, trap_result, |
7491 Execution::Call(isolate, trap, handler, arraysize(args), args), | 7453 Execution::Call(isolate, trap, handler, arraysize(args), args), |
7492 Nothing<bool>()); | 7454 Nothing<bool>()); |
(...skipping 758 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8251 Handle<FixedArray> storage = isolate->factory()->NewFixedArray(length); | 8213 Handle<FixedArray> storage = isolate->factory()->NewFixedArray(length); |
8252 dictionary->CopyEnumKeysTo(*storage); | 8214 dictionary->CopyEnumKeysTo(*storage); |
8253 return storage; | 8215 return storage; |
8254 } | 8216 } |
8255 } | 8217 } |
8256 | 8218 |
8257 | 8219 |
8258 enum IndexedOrNamed { kIndexed, kNamed }; | 8220 enum IndexedOrNamed { kIndexed, kNamed }; |
8259 | 8221 |
8260 | 8222 |
8261 // Returns false iff there was an exception. | 8223 // Returns |true| on success, |nothing| on exception. |
8262 template <class Callback, IndexedOrNamed type> | 8224 template <class Callback, IndexedOrNamed type> |
8263 static bool GetKeysFromInterceptor(Isolate* isolate, | 8225 static Maybe<bool> GetKeysFromInterceptor(Isolate* isolate, |
8264 Handle<JSReceiver> receiver, | 8226 Handle<JSReceiver> receiver, |
8265 Handle<JSObject> object, | 8227 Handle<JSObject> object, |
8266 PropertyFilter filter, | 8228 PropertyFilter filter, |
8267 KeyAccumulator* accumulator) { | 8229 KeyAccumulator* accumulator) { |
8268 if (type == kIndexed) { | 8230 if (type == kIndexed) { |
8269 if (!object->HasIndexedInterceptor()) return true; | 8231 if (!object->HasIndexedInterceptor()) return Just(true); |
8270 } else { | 8232 } else { |
8271 if (!object->HasNamedInterceptor()) return true; | 8233 if (!object->HasNamedInterceptor()) return Just(true); |
8272 } | 8234 } |
8273 Handle<InterceptorInfo> interceptor(type == kIndexed | 8235 Handle<InterceptorInfo> interceptor(type == kIndexed |
8274 ? object->GetIndexedInterceptor() | 8236 ? object->GetIndexedInterceptor() |
8275 : object->GetNamedInterceptor(), | 8237 : object->GetNamedInterceptor(), |
8276 isolate); | 8238 isolate); |
8277 if ((filter & ONLY_ALL_CAN_READ) && !interceptor->all_can_read()) { | 8239 if ((filter & ONLY_ALL_CAN_READ) && !interceptor->all_can_read()) { |
8278 return true; | 8240 return Just(true); |
8279 } | 8241 } |
8280 PropertyCallbackArguments args(isolate, interceptor->data(), *receiver, | 8242 PropertyCallbackArguments args(isolate, interceptor->data(), *receiver, |
8281 *object); | 8243 *object); |
8282 v8::Local<v8::Object> result; | 8244 v8::Local<v8::Object> result; |
8283 if (!interceptor->enumerator()->IsUndefined()) { | 8245 if (!interceptor->enumerator()->IsUndefined()) { |
8284 Callback enum_fun = v8::ToCData<Callback>(interceptor->enumerator()); | 8246 Callback enum_fun = v8::ToCData<Callback>(interceptor->enumerator()); |
8285 const char* log_tag = type == kIndexed ? "interceptor-indexed-enum" | 8247 const char* log_tag = type == kIndexed ? "interceptor-indexed-enum" |
8286 : "interceptor-named-enum"; | 8248 : "interceptor-named-enum"; |
8287 LOG(isolate, ApiObjectAccess(log_tag, *object)); | 8249 LOG(isolate, ApiObjectAccess(log_tag, *object)); |
8288 result = args.Call(enum_fun); | 8250 result = args.Call(enum_fun); |
8289 } | 8251 } |
8290 RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, false); | 8252 RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<bool>()); |
8291 if (result.IsEmpty()) return true; | 8253 if (result.IsEmpty()) return Just(true); |
8292 DCHECK(v8::Utils::OpenHandle(*result)->IsJSArray() || | 8254 DCHECK(v8::Utils::OpenHandle(*result)->IsJSArray() || |
8293 (v8::Utils::OpenHandle(*result)->IsJSObject() && | 8255 (v8::Utils::OpenHandle(*result)->IsJSObject() && |
8294 Handle<JSObject>::cast(v8::Utils::OpenHandle(*result)) | 8256 Handle<JSObject>::cast(v8::Utils::OpenHandle(*result)) |
8295 ->HasSloppyArgumentsElements())); | 8257 ->HasSloppyArgumentsElements())); |
8296 // The accumulator takes care of string/symbol filtering. | 8258 // The accumulator takes care of string/symbol filtering. |
8297 if (type == kIndexed) { | 8259 if (type == kIndexed) { |
8298 accumulator->AddElementKeysFromInterceptor( | 8260 accumulator->AddElementKeysFromInterceptor( |
8299 Handle<JSObject>::cast(v8::Utils::OpenHandle(*result))); | 8261 Handle<JSObject>::cast(v8::Utils::OpenHandle(*result))); |
8300 } else { | 8262 } else { |
8301 accumulator->AddKeys( | 8263 accumulator->AddKeys( |
8302 Handle<JSObject>::cast(v8::Utils::OpenHandle(*result))); | 8264 Handle<JSObject>::cast(v8::Utils::OpenHandle(*result))); |
8303 } | 8265 } |
8304 return true; | 8266 return Just(true); |
8305 } | 8267 } |
8306 | 8268 |
8307 | 8269 |
8308 static bool GetKeysFromJSObject(Isolate* isolate, Handle<JSReceiver> receiver, | 8270 // Returns |true| on success, |false| if prototype walking should be stopped, |
8309 Handle<JSObject> object, PropertyFilter* filter, | 8271 // |nothing| if an exception was thrown. |
8310 JSReceiver::KeyCollectionType type, | 8272 static Maybe<bool> GetKeysFromJSObject(Isolate* isolate, |
8311 KeyAccumulator* accumulator) { | 8273 Handle<JSReceiver> receiver, |
| 8274 Handle<JSObject> object, |
| 8275 PropertyFilter* filter, |
| 8276 JSReceiver::KeyCollectionType type, |
| 8277 KeyAccumulator* accumulator) { |
8312 accumulator->NextPrototype(); | 8278 accumulator->NextPrototype(); |
8313 // Check access rights if required. | 8279 // Check access rights if required. |
8314 if (object->IsAccessCheckNeeded() && | 8280 if (object->IsAccessCheckNeeded() && |
8315 !isolate->MayAccess(handle(isolate->context()), object)) { | 8281 !isolate->MayAccess(handle(isolate->context()), object)) { |
8316 // The cross-origin spec says that [[Enumerate]] shall return an empty | 8282 // The cross-origin spec says that [[Enumerate]] shall return an empty |
8317 // iterator when it doesn't have access... | 8283 // iterator when it doesn't have access... |
8318 if (type == JSReceiver::INCLUDE_PROTOS) { | 8284 if (type == JSReceiver::INCLUDE_PROTOS) { |
8319 return false; | 8285 return Just(false); |
8320 } | 8286 } |
8321 // ...whereas [[OwnPropertyKeys]] shall return whitelisted properties. | 8287 // ...whereas [[OwnPropertyKeys]] shall return whitelisted properties. |
8322 DCHECK(type == JSReceiver::OWN_ONLY); | 8288 DCHECK(type == JSReceiver::OWN_ONLY); |
8323 *filter = static_cast<PropertyFilter>(*filter | ONLY_ALL_CAN_READ); | 8289 *filter = static_cast<PropertyFilter>(*filter | ONLY_ALL_CAN_READ); |
8324 } | 8290 } |
8325 | 8291 |
8326 JSObject::CollectOwnElementKeys(object, accumulator, *filter); | 8292 JSObject::CollectOwnElementKeys(object, accumulator, *filter); |
8327 | 8293 |
8328 // Add the element keys from the interceptor. | 8294 // Add the element keys from the interceptor. |
8329 if (!GetKeysFromInterceptor<v8::IndexedPropertyEnumeratorCallback, kIndexed>( | 8295 Maybe<bool> success = |
8330 isolate, receiver, object, *filter, accumulator)) { | 8296 GetKeysFromInterceptor<v8::IndexedPropertyEnumeratorCallback, kIndexed>( |
8331 DCHECK(isolate->has_pending_exception()); | 8297 isolate, receiver, object, *filter, accumulator); |
8332 return false; | 8298 MAYBE_RETURN(success, Nothing<bool>()); |
8333 } | |
8334 | 8299 |
8335 if (*filter == ENUMERABLE_STRINGS) { | 8300 if (*filter == ENUMERABLE_STRINGS) { |
8336 // We can cache the computed property keys if access checks are | 8301 // We can cache the computed property keys if access checks are |
8337 // not needed and no interceptors are involved. | 8302 // not needed and no interceptors are involved. |
8338 // | 8303 // |
8339 // We do not use the cache if the object has elements and | 8304 // We do not use the cache if the object has elements and |
8340 // therefore it does not make sense to cache the property names | 8305 // therefore it does not make sense to cache the property names |
8341 // for arguments objects. Arguments objects will always have | 8306 // for arguments objects. Arguments objects will always have |
8342 // elements. | 8307 // elements. |
8343 // Wrapped strings have elements, but don't have an elements | 8308 // Wrapped strings have elements, but don't have an elements |
8344 // array or dictionary. So the fast inline test for whether to | 8309 // array or dictionary. So the fast inline test for whether to |
8345 // use the cache says yes, so we should not create a cache. | 8310 // use the cache says yes, so we should not create a cache. |
8346 Handle<JSFunction> arguments_function( | 8311 Handle<JSFunction> arguments_function( |
8347 JSFunction::cast(isolate->sloppy_arguments_map()->GetConstructor())); | 8312 JSFunction::cast(isolate->sloppy_arguments_map()->GetConstructor())); |
8348 bool cache_enum_length = | 8313 bool cache_enum_length = |
8349 ((object->map()->GetConstructor() != *arguments_function) && | 8314 ((object->map()->GetConstructor() != *arguments_function) && |
8350 !object->IsJSValue() && !object->IsAccessCheckNeeded() && | 8315 !object->IsJSValue() && !object->IsAccessCheckNeeded() && |
8351 !object->HasNamedInterceptor() && !object->HasIndexedInterceptor()); | 8316 !object->HasNamedInterceptor() && !object->HasIndexedInterceptor()); |
8352 // Compute the property keys and cache them if possible. | 8317 // Compute the property keys and cache them if possible. |
8353 Handle<FixedArray> enum_keys = | 8318 Handle<FixedArray> enum_keys = |
8354 JSObject::GetEnumPropertyKeys(object, cache_enum_length); | 8319 JSObject::GetEnumPropertyKeys(object, cache_enum_length); |
8355 accumulator->AddKeys(enum_keys); | 8320 accumulator->AddKeys(enum_keys); |
8356 } else { | 8321 } else { |
8357 object->CollectOwnPropertyNames(accumulator, *filter); | 8322 object->CollectOwnPropertyNames(accumulator, *filter); |
8358 } | 8323 } |
8359 | 8324 |
8360 // Add the property keys from the interceptor. | 8325 // Add the property keys from the interceptor. |
8361 if (!GetKeysFromInterceptor<v8::GenericNamedPropertyEnumeratorCallback, | 8326 success = GetKeysFromInterceptor<v8::GenericNamedPropertyEnumeratorCallback, |
8362 kNamed>(isolate, receiver, object, *filter, | 8327 kNamed>(isolate, receiver, object, *filter, |
8363 accumulator)) { | 8328 accumulator); |
8364 DCHECK(isolate->has_pending_exception()); | 8329 MAYBE_RETURN(success, Nothing<bool>()); |
8365 return false; | 8330 return Just(true); |
8366 } | |
8367 return true; | |
8368 } | 8331 } |
8369 | 8332 |
8370 | 8333 |
8371 // Helper function for JSReceiver::GetKeys() below. Can be called recursively. | 8334 // Helper function for JSReceiver::GetKeys() below. Can be called recursively. |
8372 // Returns false iff an exception was thrown. | 8335 // Returns |true| or |nothing|. |
8373 static bool GetKeys_Internal(Isolate* isolate, Handle<JSReceiver> receiver, | 8336 static Maybe<bool> GetKeys_Internal(Isolate* isolate, |
8374 Handle<JSReceiver> object, | 8337 Handle<JSReceiver> receiver, |
8375 JSReceiver::KeyCollectionType type, | 8338 Handle<JSReceiver> object, |
8376 PropertyFilter filter, | 8339 JSReceiver::KeyCollectionType type, |
8377 KeyAccumulator* accumulator) { | 8340 PropertyFilter filter, |
| 8341 KeyAccumulator* accumulator) { |
8378 PrototypeIterator::WhereToEnd end = type == JSReceiver::OWN_ONLY | 8342 PrototypeIterator::WhereToEnd end = type == JSReceiver::OWN_ONLY |
8379 ? PrototypeIterator::END_AT_NON_HIDDEN | 8343 ? PrototypeIterator::END_AT_NON_HIDDEN |
8380 : PrototypeIterator::END_AT_NULL; | 8344 : PrototypeIterator::END_AT_NULL; |
8381 for (PrototypeIterator iter(isolate, object, | 8345 for (PrototypeIterator iter(isolate, object, |
8382 PrototypeIterator::START_AT_RECEIVER); | 8346 PrototypeIterator::START_AT_RECEIVER); |
8383 !iter.IsAtEnd(end); iter.Advance()) { | 8347 !iter.IsAtEnd(end); iter.Advance()) { |
8384 Handle<JSReceiver> current = | 8348 Handle<JSReceiver> current = |
8385 PrototypeIterator::GetCurrent<JSReceiver>(iter); | 8349 PrototypeIterator::GetCurrent<JSReceiver>(iter); |
8386 bool result = false; | 8350 Maybe<bool> result = Just(false); // Dummy initialization. |
8387 if (current->IsJSProxy()) { | 8351 if (current->IsJSProxy()) { |
8388 if (type == JSReceiver::OWN_ONLY) { | 8352 if (type == JSReceiver::OWN_ONLY) { |
8389 result = JSProxy::OwnPropertyKeys(isolate, receiver, | 8353 result = JSProxy::OwnPropertyKeys(isolate, receiver, |
8390 Handle<JSProxy>::cast(current), | 8354 Handle<JSProxy>::cast(current), |
8391 filter, accumulator); | 8355 filter, accumulator); |
8392 } else { | 8356 } else { |
8393 DCHECK(type == JSReceiver::INCLUDE_PROTOS); | 8357 DCHECK(type == JSReceiver::INCLUDE_PROTOS); |
8394 result = JSProxy::Enumerate( | 8358 result = JSProxy::Enumerate( |
8395 isolate, receiver, Handle<JSProxy>::cast(current), accumulator); | 8359 isolate, receiver, Handle<JSProxy>::cast(current), accumulator); |
8396 } | 8360 } |
8397 } else { | 8361 } else { |
8398 DCHECK(current->IsJSObject()); | 8362 DCHECK(current->IsJSObject()); |
8399 result = GetKeysFromJSObject(isolate, receiver, | 8363 result = GetKeysFromJSObject(isolate, receiver, |
8400 Handle<JSObject>::cast(current), &filter, | 8364 Handle<JSObject>::cast(current), &filter, |
8401 type, accumulator); | 8365 type, accumulator); |
8402 } | 8366 } |
8403 if (!result) { | 8367 MAYBE_RETURN(result, Nothing<bool>()); |
8404 if (isolate->has_pending_exception()) { | 8368 if (!result.FromJust()) break; // |false| means "stop iterating". |
8405 return false; | |
8406 } | |
8407 // If there was no exception, then "false" means "stop iterating". | |
8408 break; | |
8409 } | |
8410 } | 8369 } |
8411 return true; | 8370 return Just(true); |
8412 } | 8371 } |
8413 | 8372 |
8414 | 8373 |
8415 // ES6 9.5.11 | 8374 // ES6 9.5.11 |
8416 // Returns false in case of exception. | 8375 // Returns false in case of exception. |
8417 // static | 8376 // static |
8418 bool JSProxy::Enumerate(Isolate* isolate, Handle<JSReceiver> receiver, | 8377 Maybe<bool> JSProxy::Enumerate(Isolate* isolate, Handle<JSReceiver> receiver, |
8419 Handle<JSProxy> proxy, KeyAccumulator* accumulator) { | 8378 Handle<JSProxy> proxy, |
| 8379 KeyAccumulator* accumulator) { |
8420 // 1. Let handler be the value of the [[ProxyHandler]] internal slot of O. | 8380 // 1. Let handler be the value of the [[ProxyHandler]] internal slot of O. |
8421 Handle<Object> handler(proxy->handler(), isolate); | 8381 Handle<Object> handler(proxy->handler(), isolate); |
8422 // 2. If handler is null, throw a TypeError exception. | 8382 // 2. If handler is null, throw a TypeError exception. |
8423 // 3. Assert: Type(handler) is Object. | 8383 // 3. Assert: Type(handler) is Object. |
8424 if (proxy->IsRevoked()) { | 8384 if (proxy->IsRevoked()) { |
8425 isolate->Throw(*isolate->factory()->NewTypeError( | 8385 isolate->Throw(*isolate->factory()->NewTypeError( |
8426 MessageTemplate::kProxyRevoked, | 8386 MessageTemplate::kProxyRevoked, |
8427 isolate->factory()->enumerate_string())); | 8387 isolate->factory()->enumerate_string())); |
8428 return false; | 8388 return Nothing<bool>(); |
8429 } | 8389 } |
8430 // 4. Let target be the value of the [[ProxyTarget]] internal slot of O. | 8390 // 4. Let target be the value of the [[ProxyTarget]] internal slot of O. |
8431 Handle<JSReceiver> target(proxy->target(), isolate); | 8391 Handle<JSReceiver> target(proxy->target(), isolate); |
8432 // 5. Let trap be ? GetMethod(handler, "enumerate"). | 8392 // 5. Let trap be ? GetMethod(handler, "enumerate"). |
8433 Handle<Object> trap; | 8393 Handle<Object> trap; |
8434 ASSIGN_RETURN_ON_EXCEPTION_VALUE( | 8394 ASSIGN_RETURN_ON_EXCEPTION_VALUE( |
8435 isolate, trap, Object::GetMethod(Handle<JSReceiver>::cast(handler), | 8395 isolate, trap, Object::GetMethod(Handle<JSReceiver>::cast(handler), |
8436 isolate->factory()->enumerate_string()), | 8396 isolate->factory()->enumerate_string()), |
8437 false); | 8397 Nothing<bool>()); |
8438 // 6. If trap is undefined, then | 8398 // 6. If trap is undefined, then |
8439 if (trap->IsUndefined()) { | 8399 if (trap->IsUndefined()) { |
8440 // 6a. Return target.[[Enumerate]](). | 8400 // 6a. Return target.[[Enumerate]](). |
8441 return GetKeys_Internal(isolate, receiver, target, INCLUDE_PROTOS, | 8401 return GetKeys_Internal(isolate, receiver, target, INCLUDE_PROTOS, |
8442 ENUMERABLE_STRINGS, accumulator); | 8402 ENUMERABLE_STRINGS, accumulator); |
8443 } | 8403 } |
8444 // The "proxy_enumerate" helper calls the trap (steps 7 - 9), which returns | 8404 // The "proxy_enumerate" helper calls the trap (steps 7 - 9), which returns |
8445 // a generator; it then iterates over that generator until it's exhausted | 8405 // a generator; it then iterates over that generator until it's exhausted |
8446 // and returns an array containing the generated values. | 8406 // and returns an array containing the generated values. |
8447 Handle<Object> trap_result_array; | 8407 Handle<Object> trap_result_array; |
8448 Handle<Object> args[] = {trap, handler, target}; | 8408 Handle<Object> args[] = {trap, handler, target}; |
8449 ASSIGN_RETURN_ON_EXCEPTION_VALUE( | 8409 ASSIGN_RETURN_ON_EXCEPTION_VALUE( |
8450 isolate, trap_result_array, | 8410 isolate, trap_result_array, |
8451 Execution::Call(isolate, isolate->proxy_enumerate(), | 8411 Execution::Call(isolate, isolate->proxy_enumerate(), |
8452 isolate->factory()->undefined_value(), arraysize(args), | 8412 isolate->factory()->undefined_value(), arraysize(args), |
8453 args), | 8413 args), |
8454 false); | 8414 Nothing<bool>()); |
8455 accumulator->NextPrototype(); | 8415 accumulator->NextPrototype(); |
8456 accumulator->AddKeysFromProxy(Handle<JSObject>::cast(trap_result_array)); | 8416 accumulator->AddKeysFromProxy(Handle<JSObject>::cast(trap_result_array)); |
8457 return true; | 8417 return Just(true); |
8458 } | 8418 } |
8459 | 8419 |
8460 | 8420 |
8461 // ES6 7.3.17 for elementTypes = (String, Symbol) | 8421 // ES6 7.3.17 for elementTypes = (String, Symbol) |
8462 static MaybeHandle<FixedArray> CreateListFromArrayLike_StringSymbol( | 8422 static MaybeHandle<FixedArray> CreateListFromArrayLike_StringSymbol( |
8463 Isolate* isolate, Handle<Object> object) { | 8423 Isolate* isolate, Handle<Object> object) { |
8464 // 1. ReturnIfAbrupt(object). | 8424 // 1. ReturnIfAbrupt(object). |
8465 // 2. (default elementTypes -- not applicable.) | 8425 // 2. (default elementTypes -- not applicable.) |
8466 // 3. If Type(obj) is not Object, throw a TypeError exception. | 8426 // 3. If Type(obj) is not Object, throw a TypeError exception. |
8467 if (!object->IsJSReceiver()) { | 8427 if (!object->IsJSReceiver()) { |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8510 next = isolate->factory()->InternalizeName(Handle<Name>::cast(next)); | 8470 next = isolate->factory()->InternalizeName(Handle<Name>::cast(next)); |
8511 list->set(index, *next); | 8471 list->set(index, *next); |
8512 // 7e. Set index to index + 1. (See loop header.) | 8472 // 7e. Set index to index + 1. (See loop header.) |
8513 } | 8473 } |
8514 // 8. Return list. | 8474 // 8. Return list. |
8515 return list; | 8475 return list; |
8516 } | 8476 } |
8517 | 8477 |
8518 | 8478 |
8519 // ES6 9.5.12 | 8479 // ES6 9.5.12 |
8520 // Returns "false" in case of exception. | 8480 // Returns |true| on success, |nothing| in case of exception. |
8521 // static | 8481 // static |
8522 bool JSProxy::OwnPropertyKeys(Isolate* isolate, Handle<JSReceiver> receiver, | 8482 Maybe<bool> JSProxy::OwnPropertyKeys(Isolate* isolate, |
8523 Handle<JSProxy> proxy, PropertyFilter filter, | 8483 Handle<JSReceiver> receiver, |
8524 KeyAccumulator* accumulator) { | 8484 Handle<JSProxy> proxy, |
| 8485 PropertyFilter filter, |
| 8486 KeyAccumulator* accumulator) { |
8525 // 1. Let handler be the value of the [[ProxyHandler]] internal slot of O. | 8487 // 1. Let handler be the value of the [[ProxyHandler]] internal slot of O. |
8526 Handle<Object> handler(proxy->handler(), isolate); | 8488 Handle<Object> handler(proxy->handler(), isolate); |
8527 // 2. If handler is null, throw a TypeError exception. | 8489 // 2. If handler is null, throw a TypeError exception. |
8528 // 3. Assert: Type(handler) is Object. | 8490 // 3. Assert: Type(handler) is Object. |
8529 if (proxy->IsRevoked()) { | 8491 if (proxy->IsRevoked()) { |
8530 isolate->Throw(*isolate->factory()->NewTypeError( | 8492 isolate->Throw(*isolate->factory()->NewTypeError( |
8531 MessageTemplate::kProxyRevoked, isolate->factory()->ownKeys_string())); | 8493 MessageTemplate::kProxyRevoked, isolate->factory()->ownKeys_string())); |
8532 return false; | 8494 return Nothing<bool>(); |
8533 } | 8495 } |
8534 // 4. Let target be the value of the [[ProxyTarget]] internal slot of O. | 8496 // 4. Let target be the value of the [[ProxyTarget]] internal slot of O. |
8535 Handle<JSReceiver> target(proxy->target(), isolate); | 8497 Handle<JSReceiver> target(proxy->target(), isolate); |
8536 // 5. Let trap be ? GetMethod(handler, "ownKeys"). | 8498 // 5. Let trap be ? GetMethod(handler, "ownKeys"). |
8537 Handle<Object> trap; | 8499 Handle<Object> trap; |
8538 ASSIGN_RETURN_ON_EXCEPTION_VALUE( | 8500 ASSIGN_RETURN_ON_EXCEPTION_VALUE( |
8539 isolate, trap, Object::GetMethod(Handle<JSReceiver>::cast(handler), | 8501 isolate, trap, Object::GetMethod(Handle<JSReceiver>::cast(handler), |
8540 isolate->factory()->ownKeys_string()), | 8502 isolate->factory()->ownKeys_string()), |
8541 false); | 8503 Nothing<bool>()); |
8542 // 6. If trap is undefined, then | 8504 // 6. If trap is undefined, then |
8543 if (trap->IsUndefined()) { | 8505 if (trap->IsUndefined()) { |
8544 // 6a. Return target.[[OwnPropertyKeys]](). | 8506 // 6a. Return target.[[OwnPropertyKeys]](). |
8545 return GetKeys_Internal(isolate, receiver, target, OWN_ONLY, filter, | 8507 return GetKeys_Internal(isolate, receiver, target, OWN_ONLY, filter, |
8546 accumulator); | 8508 accumulator); |
8547 } | 8509 } |
8548 // 7. Let trapResultArray be Call(trap, handler, «target»). | 8510 // 7. Let trapResultArray be Call(trap, handler, «target»). |
8549 Handle<Object> trap_result_array; | 8511 Handle<Object> trap_result_array; |
8550 Handle<Object> args[] = {target}; | 8512 Handle<Object> args[] = {target}; |
8551 ASSIGN_RETURN_ON_EXCEPTION_VALUE( | 8513 ASSIGN_RETURN_ON_EXCEPTION_VALUE( |
8552 isolate, trap_result_array, | 8514 isolate, trap_result_array, |
8553 Execution::Call(isolate, trap, handler, arraysize(args), args), false); | 8515 Execution::Call(isolate, trap, handler, arraysize(args), args), |
| 8516 Nothing<bool>()); |
8554 // 8. Let trapResult be ? CreateListFromArrayLike(trapResultArray, | 8517 // 8. Let trapResult be ? CreateListFromArrayLike(trapResultArray, |
8555 // «String, Symbol»). | 8518 // «String, Symbol»). |
8556 Handle<FixedArray> trap_result; | 8519 Handle<FixedArray> trap_result; |
8557 ASSIGN_RETURN_ON_EXCEPTION_VALUE( | 8520 ASSIGN_RETURN_ON_EXCEPTION_VALUE( |
8558 isolate, trap_result, | 8521 isolate, trap_result, |
8559 CreateListFromArrayLike_StringSymbol(isolate, trap_result_array), false); | 8522 CreateListFromArrayLike_StringSymbol(isolate, trap_result_array), |
| 8523 Nothing<bool>()); |
8560 // 9. Let extensibleTarget be ? IsExtensible(target). | 8524 // 9. Let extensibleTarget be ? IsExtensible(target). |
8561 Maybe<bool> maybe_extensible = JSReceiver::IsExtensible(target); | 8525 Maybe<bool> maybe_extensible = JSReceiver::IsExtensible(target); |
8562 if (maybe_extensible.IsNothing()) return false; | 8526 MAYBE_RETURN(maybe_extensible, Nothing<bool>()); |
8563 bool extensible_target = maybe_extensible.FromJust(); | 8527 bool extensible_target = maybe_extensible.FromJust(); |
8564 // 10. Let targetKeys be ? target.[[OwnPropertyKeys]](). | 8528 // 10. Let targetKeys be ? target.[[OwnPropertyKeys]](). |
8565 Handle<FixedArray> target_keys; | 8529 Handle<FixedArray> target_keys; |
8566 ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, target_keys, | 8530 ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, target_keys, |
8567 JSReceiver::OwnPropertyKeys(target), false); | 8531 JSReceiver::OwnPropertyKeys(target), |
| 8532 Nothing<bool>()); |
8568 // 11. (Assert) | 8533 // 11. (Assert) |
8569 // 12. Let targetConfigurableKeys be an empty List. | 8534 // 12. Let targetConfigurableKeys be an empty List. |
8570 // To save memory, we're re-using target_keys and will modify it in-place. | 8535 // To save memory, we're re-using target_keys and will modify it in-place. |
8571 Handle<FixedArray> target_configurable_keys = target_keys; | 8536 Handle<FixedArray> target_configurable_keys = target_keys; |
8572 // 13. Let targetNonconfigurableKeys be an empty List. | 8537 // 13. Let targetNonconfigurableKeys be an empty List. |
8573 Handle<FixedArray> target_nonconfigurable_keys = | 8538 Handle<FixedArray> target_nonconfigurable_keys = |
8574 isolate->factory()->NewFixedArray(target_keys->length()); | 8539 isolate->factory()->NewFixedArray(target_keys->length()); |
8575 int nonconfigurable_keys_length = 0; | 8540 int nonconfigurable_keys_length = 0; |
8576 // 14. Repeat, for each element key of targetKeys: | 8541 // 14. Repeat, for each element key of targetKeys: |
8577 for (int i = 0; i < target_keys->length(); ++i) { | 8542 for (int i = 0; i < target_keys->length(); ++i) { |
8578 // 14a. Let desc be ? target.[[GetOwnProperty]](key). | 8543 // 14a. Let desc be ? target.[[GetOwnProperty]](key). |
8579 PropertyDescriptor desc; | 8544 PropertyDescriptor desc; |
8580 bool found = JSReceiver::GetOwnPropertyDescriptor( | 8545 Maybe<bool> found = JSReceiver::GetOwnPropertyDescriptor( |
8581 isolate, target, handle(target_keys->get(i), isolate), &desc); | 8546 isolate, target, handle(target_keys->get(i), isolate), &desc); |
8582 if (isolate->has_pending_exception()) return false; | 8547 MAYBE_RETURN(found, Nothing<bool>()); |
8583 // 14b. If desc is not undefined and desc.[[Configurable]] is false, then | 8548 // 14b. If desc is not undefined and desc.[[Configurable]] is false, then |
8584 if (found && !desc.configurable()) { | 8549 if (found.FromJust() && !desc.configurable()) { |
8585 // 14b i. Append key as an element of targetNonconfigurableKeys. | 8550 // 14b i. Append key as an element of targetNonconfigurableKeys. |
8586 target_nonconfigurable_keys->set(nonconfigurable_keys_length, | 8551 target_nonconfigurable_keys->set(nonconfigurable_keys_length, |
8587 target_keys->get(i)); | 8552 target_keys->get(i)); |
8588 nonconfigurable_keys_length++; | 8553 nonconfigurable_keys_length++; |
8589 // The key was moved, null it out in the original list. | 8554 // The key was moved, null it out in the original list. |
8590 target_keys->set(i, Smi::FromInt(0)); | 8555 target_keys->set(i, Smi::FromInt(0)); |
8591 } else { | 8556 } else { |
8592 // 14c. Else, | 8557 // 14c. Else, |
8593 // 14c i. Append key as an element of targetConfigurableKeys. | 8558 // 14c i. Append key as an element of targetConfigurableKeys. |
8594 // (No-op, just keep it in |target_keys|.) | 8559 // (No-op, just keep it in |target_keys|.) |
(...skipping 18 matching lines...) Expand all Loading... |
8613 } | 8578 } |
8614 // 17. Repeat, for each key that is an element of targetNonconfigurableKeys: | 8579 // 17. Repeat, for each key that is an element of targetNonconfigurableKeys: |
8615 for (int i = 0; i < nonconfigurable_keys_length; ++i) { | 8580 for (int i = 0; i < nonconfigurable_keys_length; ++i) { |
8616 Object* key = target_nonconfigurable_keys->get(i); | 8581 Object* key = target_nonconfigurable_keys->get(i); |
8617 // 17a. If key is not an element of uncheckedResultKeys, throw a | 8582 // 17a. If key is not an element of uncheckedResultKeys, throw a |
8618 // TypeError exception. | 8583 // TypeError exception. |
8619 int* found = unchecked_result_keys.Find(key); | 8584 int* found = unchecked_result_keys.Find(key); |
8620 if (found == nullptr || *found == kGone) { | 8585 if (found == nullptr || *found == kGone) { |
8621 isolate->Throw(*isolate->factory()->NewTypeError( | 8586 isolate->Throw(*isolate->factory()->NewTypeError( |
8622 MessageTemplate::kProxyTrapResultMustInclude, handle(key, isolate))); | 8587 MessageTemplate::kProxyTrapResultMustInclude, handle(key, isolate))); |
8623 return false; | 8588 return Nothing<bool>(); |
8624 } | 8589 } |
8625 // 17b. Remove key from uncheckedResultKeys. | 8590 // 17b. Remove key from uncheckedResultKeys. |
8626 *found = kGone; | 8591 *found = kGone; |
8627 unchecked_result_keys_size--; | 8592 unchecked_result_keys_size--; |
8628 } | 8593 } |
8629 // 18. If extensibleTarget is true, return trapResult. | 8594 // 18. If extensibleTarget is true, return trapResult. |
8630 if (extensible_target) { | 8595 if (extensible_target) { |
8631 return accumulator->AddKeysFromProxy(proxy, trap_result); | 8596 return accumulator->AddKeysFromProxy(proxy, trap_result); |
8632 } | 8597 } |
8633 // 19. Repeat, for each key that is an element of targetConfigurableKeys: | 8598 // 19. Repeat, for each key that is an element of targetConfigurableKeys: |
8634 for (int i = 0; i < target_configurable_keys->length(); ++i) { | 8599 for (int i = 0; i < target_configurable_keys->length(); ++i) { |
8635 Object* key = target_configurable_keys->get(i); | 8600 Object* key = target_configurable_keys->get(i); |
8636 if (key->IsSmi()) continue; // Zapped entry, was nonconfigurable. | 8601 if (key->IsSmi()) continue; // Zapped entry, was nonconfigurable. |
8637 // 19a. If key is not an element of uncheckedResultKeys, throw a | 8602 // 19a. If key is not an element of uncheckedResultKeys, throw a |
8638 // TypeError exception. | 8603 // TypeError exception. |
8639 int* found = unchecked_result_keys.Find(key); | 8604 int* found = unchecked_result_keys.Find(key); |
8640 if (found == nullptr || *found == kGone) { | 8605 if (found == nullptr || *found == kGone) { |
8641 isolate->Throw(*isolate->factory()->NewTypeError( | 8606 isolate->Throw(*isolate->factory()->NewTypeError( |
8642 MessageTemplate::kProxyTrapResultMustInclude, handle(key, isolate))); | 8607 MessageTemplate::kProxyTrapResultMustInclude, handle(key, isolate))); |
8643 return false; | 8608 return Nothing<bool>(); |
8644 } | 8609 } |
8645 // 19b. Remove key from uncheckedResultKeys. | 8610 // 19b. Remove key from uncheckedResultKeys. |
8646 *found = kGone; | 8611 *found = kGone; |
8647 unchecked_result_keys_size--; | 8612 unchecked_result_keys_size--; |
8648 } | 8613 } |
8649 // 20. If uncheckedResultKeys is not empty, throw a TypeError exception. | 8614 // 20. If uncheckedResultKeys is not empty, throw a TypeError exception. |
8650 if (unchecked_result_keys_size != 0) { | 8615 if (unchecked_result_keys_size != 0) { |
8651 DCHECK_GT(unchecked_result_keys_size, 0); | 8616 DCHECK_GT(unchecked_result_keys_size, 0); |
8652 isolate->Throw(*isolate->factory()->NewTypeError( | 8617 isolate->Throw(*isolate->factory()->NewTypeError( |
8653 MessageTemplate::kProxyTargetNotExtensible)); | 8618 MessageTemplate::kProxyTargetNotExtensible)); |
8654 return false; | 8619 return Nothing<bool>(); |
8655 } | 8620 } |
8656 // 21. Return trapResult. | 8621 // 21. Return trapResult. |
8657 return accumulator->AddKeysFromProxy(proxy, trap_result); | 8622 return accumulator->AddKeysFromProxy(proxy, trap_result); |
8658 } | 8623 } |
8659 | 8624 |
8660 | 8625 |
8661 MaybeHandle<FixedArray> JSReceiver::GetKeys(Handle<JSReceiver> object, | 8626 MaybeHandle<FixedArray> JSReceiver::GetKeys(Handle<JSReceiver> object, |
8662 KeyCollectionType type, | 8627 KeyCollectionType type, |
8663 PropertyFilter filter, | 8628 PropertyFilter filter, |
8664 GetKeysConversion keys_conversion) { | 8629 GetKeysConversion keys_conversion) { |
8665 USE(ContainsOnlyValidKeys); | 8630 USE(ContainsOnlyValidKeys); |
8666 Isolate* isolate = object->GetIsolate(); | 8631 Isolate* isolate = object->GetIsolate(); |
8667 KeyAccumulator accumulator(isolate, filter); | 8632 KeyAccumulator accumulator(isolate, filter); |
8668 if (!GetKeys_Internal(isolate, object, object, type, filter, &accumulator)) { | 8633 MAYBE_RETURN( |
8669 DCHECK(isolate->has_pending_exception()); | 8634 GetKeys_Internal(isolate, object, object, type, filter, &accumulator), |
8670 return MaybeHandle<FixedArray>(); | 8635 MaybeHandle<FixedArray>()); |
8671 } | |
8672 Handle<FixedArray> keys = accumulator.GetKeys(keys_conversion); | 8636 Handle<FixedArray> keys = accumulator.GetKeys(keys_conversion); |
8673 DCHECK(ContainsOnlyValidKeys(keys)); | 8637 DCHECK(ContainsOnlyValidKeys(keys)); |
8674 return keys; | 8638 return keys; |
8675 } | 8639 } |
8676 | 8640 |
8677 | 8641 |
8678 bool Map::DictionaryElementsInPrototypeChainOnly() { | 8642 bool Map::DictionaryElementsInPrototypeChainOnly() { |
8679 if (IsDictionaryElementsKind(elements_kind())) { | 8643 if (IsDictionaryElementsKind(elements_kind())) { |
8680 return false; | 8644 return false; |
8681 } | 8645 } |
(...skipping 10517 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
19199 if (cell->value() != *new_value) { | 19163 if (cell->value() != *new_value) { |
19200 cell->set_value(*new_value); | 19164 cell->set_value(*new_value); |
19201 Isolate* isolate = cell->GetIsolate(); | 19165 Isolate* isolate = cell->GetIsolate(); |
19202 cell->dependent_code()->DeoptimizeDependentCodeGroup( | 19166 cell->dependent_code()->DeoptimizeDependentCodeGroup( |
19203 isolate, DependentCode::kPropertyCellChangedGroup); | 19167 isolate, DependentCode::kPropertyCellChangedGroup); |
19204 } | 19168 } |
19205 } | 19169 } |
19206 | 19170 |
19207 } // namespace internal | 19171 } // namespace internal |
19208 } // namespace v8 | 19172 } // namespace v8 |
OLD | NEW |