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 866 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
877 Handle<Map> map) { | 877 Handle<Map> map) { |
878 if (!info->HasExpectedReceiverType()) return true; | 878 if (!info->HasExpectedReceiverType()) return true; |
879 if (!map->IsJSObjectMap()) return false; | 879 if (!map->IsJSObjectMap()) return false; |
880 return FunctionTemplateInfo::cast(info->expected_receiver_type()) | 880 return FunctionTemplateInfo::cast(info->expected_receiver_type()) |
881 ->IsTemplateFor(*map); | 881 ->IsTemplateFor(*map); |
882 } | 882 } |
883 | 883 |
884 | 884 |
885 Maybe<bool> Object::SetPropertyWithAccessor(LookupIterator* it, | 885 Maybe<bool> Object::SetPropertyWithAccessor(LookupIterator* it, |
886 Handle<Object> value, | 886 Handle<Object> value, |
887 LanguageMode language_mode, | |
888 ShouldThrow should_throw) { | 887 ShouldThrow should_throw) { |
889 Isolate* isolate = it->isolate(); | 888 Isolate* isolate = it->isolate(); |
890 Handle<Object> structure = it->GetAccessors(); | 889 Handle<Object> structure = it->GetAccessors(); |
891 Handle<Object> receiver = it->GetReceiver(); | 890 Handle<Object> receiver = it->GetReceiver(); |
892 | 891 |
893 // We should never get here to initialize a const with the hole value since a | 892 // We should never get here to initialize a const with the hole value since a |
894 // const declaration would conflict with the setter. | 893 // const declaration would conflict with the setter. |
895 DCHECK(!structure->IsForeign()); | 894 DCHECK(!structure->IsForeign()); |
896 | 895 |
897 // API style callbacks. | 896 // API style callbacks. |
(...skipping 24 matching lines...) Expand all Loading... |
922 } | 921 } |
923 | 922 |
924 // Regular accessor. | 923 // Regular accessor. |
925 Handle<Object> setter(AccessorPair::cast(*structure)->setter(), isolate); | 924 Handle<Object> setter(AccessorPair::cast(*structure)->setter(), isolate); |
926 if (setter->IsCallable()) { | 925 if (setter->IsCallable()) { |
927 // TODO(rossberg): nicer would be to cast to some JSCallable here... | 926 // TODO(rossberg): nicer would be to cast to some JSCallable here... |
928 return SetPropertyWithDefinedSetter( | 927 return SetPropertyWithDefinedSetter( |
929 receiver, Handle<JSReceiver>::cast(setter), value, should_throw); | 928 receiver, Handle<JSReceiver>::cast(setter), value, should_throw); |
930 } | 929 } |
931 | 930 |
932 if (is_sloppy(language_mode)) return Just(true); | |
933 RETURN_FAILURE(isolate, should_throw, | 931 RETURN_FAILURE(isolate, should_throw, |
934 NewTypeError(MessageTemplate::kNoSetterInCallback, | 932 NewTypeError(MessageTemplate::kNoSetterInCallback, |
935 it->GetName(), it->GetHolder<JSObject>())); | 933 it->GetName(), it->GetHolder<JSObject>())); |
936 } | 934 } |
937 | 935 |
938 | 936 |
939 MaybeHandle<Object> Object::GetPropertyWithDefinedGetter( | 937 MaybeHandle<Object> Object::GetPropertyWithDefinedGetter( |
940 Handle<Object> receiver, | 938 Handle<Object> receiver, |
941 Handle<JSReceiver> getter) { | 939 Handle<JSReceiver> getter) { |
942 Isolate* isolate = getter->GetIsolate(); | 940 Isolate* isolate = getter->GetIsolate(); |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1061 } | 1059 } |
1062 } | 1060 } |
1063 return false; | 1061 return false; |
1064 } | 1062 } |
1065 | 1063 |
1066 | 1064 |
1067 Maybe<bool> JSObject::SetPropertyWithFailedAccessCheck( | 1065 Maybe<bool> JSObject::SetPropertyWithFailedAccessCheck( |
1068 LookupIterator* it, Handle<Object> value, ShouldThrow should_throw) { | 1066 LookupIterator* it, Handle<Object> value, ShouldThrow should_throw) { |
1069 Handle<JSObject> checked = it->GetHolder<JSObject>(); | 1067 Handle<JSObject> checked = it->GetHolder<JSObject>(); |
1070 if (AllCanWrite(it)) { | 1068 if (AllCanWrite(it)) { |
1071 // The supplied language-mode is ignored by SetPropertyWithAccessor. | 1069 return SetPropertyWithAccessor(it, value, should_throw); |
1072 return SetPropertyWithAccessor(it, value, SLOPPY, should_throw); | |
1073 } | 1070 } |
1074 | 1071 |
1075 it->isolate()->ReportFailedAccessCheck(checked); | 1072 it->isolate()->ReportFailedAccessCheck(checked); |
1076 RETURN_VALUE_IF_SCHEDULED_EXCEPTION(it->isolate(), Nothing<bool>()); | 1073 RETURN_VALUE_IF_SCHEDULED_EXCEPTION(it->isolate(), Nothing<bool>()); |
1077 UNREACHABLE(); | 1074 UNREACHABLE(); |
1078 it->isolate()->Throw( | 1075 it->isolate()->Throw( |
1079 *it->isolate()->factory()->NewTypeError(MessageTemplate::kNoAccess)); | 1076 *it->isolate()->factory()->NewTypeError(MessageTemplate::kNoAccess)); |
1080 return Nothing<bool>(); | 1077 return Nothing<bool>(); |
1081 } | 1078 } |
1082 | 1079 |
(...skipping 2514 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3597 #endif | 3594 #endif |
3598 return Just(true); | 3595 return Just(true); |
3599 } | 3596 } |
3600 | 3597 |
3601 | 3598 |
3602 MaybeHandle<Object> Object::SetProperty(Handle<Object> object, | 3599 MaybeHandle<Object> Object::SetProperty(Handle<Object> object, |
3603 Handle<Name> name, Handle<Object> value, | 3600 Handle<Name> name, Handle<Object> value, |
3604 LanguageMode language_mode, | 3601 LanguageMode language_mode, |
3605 StoreFromKeyed store_mode) { | 3602 StoreFromKeyed store_mode) { |
3606 LookupIterator it(object, name); | 3603 LookupIterator it(object, name); |
3607 return SetProperty(&it, value, language_mode, store_mode); | 3604 MAYBE_RETURN_NULL(SetProperty(&it, value, language_mode, store_mode)); |
| 3605 return value; |
3608 } | 3606 } |
3609 | 3607 |
3610 | 3608 |
3611 Maybe<bool> Object::SetPropertyInternal( | 3609 Maybe<bool> Object::SetPropertyInternal(LookupIterator* it, |
3612 LookupIterator* it, Handle<Object> value, LanguageMode language_mode, | 3610 Handle<Object> value, |
3613 ShouldThrow should_throw, StoreFromKeyed store_mode, bool* found) { | 3611 LanguageMode language_mode, |
| 3612 StoreFromKeyed store_mode, |
| 3613 bool* found) { |
| 3614 ShouldThrow should_throw = |
| 3615 is_sloppy(language_mode) ? DONT_THROW : THROW_ON_ERROR; |
| 3616 |
3614 // Make sure that the top context does not change when doing callbacks or | 3617 // Make sure that the top context does not change when doing callbacks or |
3615 // interceptor calls. | 3618 // interceptor calls. |
3616 AssertNoContextChange ncc(it->isolate()); | 3619 AssertNoContextChange ncc(it->isolate()); |
3617 | 3620 |
3618 *found = true; | 3621 *found = true; |
3619 | 3622 |
3620 bool done = false; | 3623 bool done = false; |
3621 for (; it->IsFound(); it->Next()) { | 3624 for (; it->IsFound(); it->Next()) { |
3622 switch (it->state()) { | 3625 switch (it->state()) { |
3623 case LookupIterator::NOT_FOUND: | 3626 case LookupIterator::NOT_FOUND: |
3624 UNREACHABLE(); | 3627 UNREACHABLE(); |
3625 | 3628 |
3626 case LookupIterator::ACCESS_CHECK: | 3629 case LookupIterator::ACCESS_CHECK: |
3627 if (it->HasAccess()) break; | 3630 if (it->HasAccess()) break; |
3628 // Check whether it makes sense to reuse the lookup iterator. Here it | 3631 // Check whether it makes sense to reuse the lookup iterator. Here it |
3629 // might still call into setters up the prototype chain. | 3632 // might still call into setters up the prototype chain. |
3630 return JSObject::SetPropertyWithFailedAccessCheck(it, value, | 3633 return JSObject::SetPropertyWithFailedAccessCheck(it, value, |
3631 should_throw); | 3634 should_throw); |
3632 | 3635 |
3633 case LookupIterator::JSPROXY: | 3636 case LookupIterator::JSPROXY: |
3634 if (it->HolderIsReceiverOrHiddenPrototype()) { | 3637 if (it->HolderIsReceiverOrHiddenPrototype()) { |
3635 return JSProxy::SetPropertyWithHandler( | 3638 return JSProxy::SetPropertyWithHandler( |
3636 it->GetHolder<JSProxy>(), it->GetReceiver(), it->GetName(), value, | 3639 it->GetHolder<JSProxy>(), it->GetReceiver(), it->GetName(), value, |
3637 language_mode, should_throw); | 3640 should_throw); |
3638 } else { | 3641 } else { |
3639 // TODO(verwaest): Use the MaybeHandle to indicate result. | 3642 // TODO(verwaest): Use the MaybeHandle to indicate result. |
3640 bool has_result = false; | 3643 bool has_result = false; |
3641 Maybe<bool> maybe_result = | 3644 Maybe<bool> maybe_result = |
3642 JSProxy::SetPropertyViaPrototypesWithHandler( | 3645 JSProxy::SetPropertyViaPrototypesWithHandler( |
3643 it->GetHolder<JSProxy>(), it->GetReceiver(), it->GetName(), | 3646 it->GetHolder<JSProxy>(), it->GetReceiver(), it->GetName(), |
3644 value, language_mode, should_throw, &has_result); | 3647 value, should_throw, &has_result); |
3645 if (has_result) return maybe_result; | 3648 if (has_result) return maybe_result; |
3646 done = true; | 3649 done = true; |
3647 } | 3650 } |
3648 break; | 3651 break; |
3649 | 3652 |
3650 case LookupIterator::INTERCEPTOR: | 3653 case LookupIterator::INTERCEPTOR: |
3651 if (it->HolderIsReceiverOrHiddenPrototype()) { | 3654 if (it->HolderIsReceiverOrHiddenPrototype()) { |
3652 Maybe<bool> maybe_result = | 3655 Maybe<bool> result = JSObject::SetPropertyWithInterceptor(it, value); |
3653 JSObject::SetPropertyWithInterceptor(it, value); | 3656 if (result.IsNothing() || result.FromJust()) return result; |
3654 if (maybe_result.IsNothing()) return Nothing<bool>(); | |
3655 if (maybe_result.FromJust()) return Just(true); | |
3656 } else { | 3657 } else { |
3657 Maybe<PropertyAttributes> maybe_attributes = | 3658 Maybe<PropertyAttributes> maybe_attributes = |
3658 JSObject::GetPropertyAttributesWithInterceptor(it); | 3659 JSObject::GetPropertyAttributesWithInterceptor(it); |
3659 if (!maybe_attributes.IsJust()) return Nothing<bool>(); | 3660 if (!maybe_attributes.IsJust()) return Nothing<bool>(); |
3660 done = maybe_attributes.FromJust() != ABSENT; | 3661 done = maybe_attributes.FromJust() != ABSENT; |
3661 if (done && (maybe_attributes.FromJust() & READ_ONLY) != 0) { | 3662 if (done && (maybe_attributes.FromJust() & READ_ONLY) != 0) { |
3662 return WriteToReadOnlyProperty(it, value, language_mode, | 3663 return WriteToReadOnlyProperty(it, value, should_throw); |
3663 should_throw); | |
3664 } | 3664 } |
3665 } | 3665 } |
3666 break; | 3666 break; |
3667 | 3667 |
3668 case LookupIterator::ACCESSOR: { | 3668 case LookupIterator::ACCESSOR: { |
3669 if (it->IsReadOnly()) { | 3669 if (it->IsReadOnly()) { |
3670 return WriteToReadOnlyProperty(it, value, language_mode, | 3670 return WriteToReadOnlyProperty(it, value, should_throw); |
3671 should_throw); | |
3672 } | 3671 } |
3673 Handle<Object> accessors = it->GetAccessors(); | 3672 Handle<Object> accessors = it->GetAccessors(); |
3674 if (accessors->IsAccessorInfo() && | 3673 if (accessors->IsAccessorInfo() && |
3675 !it->HolderIsReceiverOrHiddenPrototype() && | 3674 !it->HolderIsReceiverOrHiddenPrototype() && |
3676 AccessorInfo::cast(*accessors)->is_special_data_property()) { | 3675 AccessorInfo::cast(*accessors)->is_special_data_property()) { |
3677 done = true; | 3676 done = true; |
3678 break; | 3677 break; |
3679 } | 3678 } |
3680 return SetPropertyWithAccessor(it, value, language_mode, should_throw); | 3679 return SetPropertyWithAccessor(it, value, should_throw); |
3681 } | 3680 } |
3682 case LookupIterator::INTEGER_INDEXED_EXOTIC: | 3681 case LookupIterator::INTEGER_INDEXED_EXOTIC: |
3683 // TODO(verwaest): We should throw an exception. | 3682 // TODO(verwaest): We should throw an exception. |
3684 return Just(true); | 3683 return Just(true); |
3685 | 3684 |
3686 case LookupIterator::DATA: | 3685 case LookupIterator::DATA: |
3687 if (it->IsReadOnly()) { | 3686 if (it->IsReadOnly()) { |
3688 return WriteToReadOnlyProperty(it, value, language_mode, | 3687 return WriteToReadOnlyProperty(it, value, should_throw); |
3689 should_throw); | |
3690 } | 3688 } |
3691 if (it->HolderIsReceiverOrHiddenPrototype()) { | 3689 if (it->HolderIsReceiverOrHiddenPrototype()) { |
3692 return SetDataProperty(it, value, should_throw); | 3690 return SetDataProperty(it, value, should_throw); |
3693 } | 3691 } |
3694 done = true; | 3692 done = true; |
3695 break; | 3693 break; |
3696 | 3694 |
3697 case LookupIterator::TRANSITION: | 3695 case LookupIterator::TRANSITION: |
3698 done = true; | 3696 done = true; |
3699 break; | 3697 break; |
3700 } | 3698 } |
3701 | 3699 |
3702 if (done) break; | 3700 if (done) break; |
3703 } | 3701 } |
3704 | 3702 |
3705 // If the receiver is the JSGlobalObject, the store was contextual. In case | 3703 // If the receiver is the JSGlobalObject, the store was contextual. In case |
3706 // the property did not exist yet on the global object itself, we have to | 3704 // the property did not exist yet on the global object itself, we have to |
3707 // throw a reference error in strict mode. | 3705 // throw a reference error in strict mode. In sloppy mode, we continue. |
3708 if (it->GetReceiver()->IsJSGlobalObject() && is_strict(language_mode)) { | 3706 if (it->GetReceiver()->IsJSGlobalObject() && is_strict(language_mode)) { |
3709 RETURN_FAILURE(it->isolate(), should_throw, | 3707 it->isolate()->Throw(*it->isolate()->factory()->NewReferenceError( |
3710 NewReferenceError(MessageTemplate::kNotDefined, it->name())); | 3708 MessageTemplate::kNotDefined, it->name())); |
| 3709 return Nothing<bool>(); |
3711 } | 3710 } |
3712 | 3711 |
3713 *found = false; | 3712 *found = false; |
3714 return Nothing<bool>(); | 3713 return Nothing<bool>(); |
3715 } | 3714 } |
3716 | 3715 |
3717 | 3716 |
3718 MaybeHandle<Object> Object::SetProperty(LookupIterator* it, | |
3719 Handle<Object> value, | |
3720 LanguageMode language_mode, | |
3721 StoreFromKeyed store_mode) { | |
3722 MAYBE_RETURN_NULL( | |
3723 SetProperty(it, value, language_mode, THROW_ON_ERROR, store_mode)); | |
3724 return value; | |
3725 } | |
3726 | |
3727 | |
3728 Maybe<bool> Object::SetProperty(LookupIterator* it, Handle<Object> value, | 3717 Maybe<bool> Object::SetProperty(LookupIterator* it, Handle<Object> value, |
3729 LanguageMode language_mode, | 3718 LanguageMode language_mode, |
3730 ShouldThrow should_throw, | |
3731 StoreFromKeyed store_mode) { | 3719 StoreFromKeyed store_mode) { |
3732 bool found = false; | 3720 bool found = false; |
3733 Maybe<bool> result = SetPropertyInternal(it, value, language_mode, | 3721 Maybe<bool> result = |
3734 should_throw, store_mode, &found); | 3722 SetPropertyInternal(it, value, language_mode, store_mode, &found); |
3735 if (found) return result; | 3723 if (found) return result; |
3736 return AddDataProperty(it, value, NONE, language_mode, should_throw, | 3724 ShouldThrow should_throw = |
3737 store_mode); | 3725 is_sloppy(language_mode) ? DONT_THROW : THROW_ON_ERROR; |
| 3726 return AddDataProperty(it, value, NONE, should_throw, store_mode); |
3738 } | 3727 } |
3739 | 3728 |
3740 | 3729 |
3741 MaybeHandle<Object> Object::SetSuperProperty(LookupIterator* it, | 3730 Maybe<bool> Object::SetSuperProperty(LookupIterator* it, Handle<Object> value, |
3742 Handle<Object> value, | 3731 LanguageMode language_mode, |
3743 LanguageMode language_mode, | 3732 StoreFromKeyed store_mode) { |
3744 StoreFromKeyed store_mode) { | 3733 ShouldThrow should_throw = |
| 3734 is_sloppy(language_mode) ? DONT_THROW : THROW_ON_ERROR; |
| 3735 |
3745 bool found = false; | 3736 bool found = false; |
3746 Maybe<bool> result = SetPropertyInternal(it, value, language_mode, | 3737 Maybe<bool> result = |
3747 THROW_ON_ERROR, store_mode, &found); | 3738 SetPropertyInternal(it, value, language_mode, store_mode, &found); |
3748 if (found) { | 3739 if (found) return result; |
3749 MAYBE_RETURN_NULL(result); | |
3750 return value; | |
3751 } | |
3752 | 3740 |
3753 if (!it->GetReceiver()->IsJSReceiver()) { | 3741 if (!it->GetReceiver()->IsJSReceiver()) { |
3754 MAYBE_RETURN_NULL( | 3742 return WriteToReadOnlyProperty(it, value, should_throw); |
3755 WriteToReadOnlyProperty(it, value, language_mode, THROW_ON_ERROR)); | |
3756 return value; | |
3757 } | 3743 } |
3758 | 3744 |
3759 LookupIterator::Configuration c = LookupIterator::OWN; | 3745 LookupIterator::Configuration c = LookupIterator::OWN; |
3760 LookupIterator own_lookup = | 3746 LookupIterator own_lookup = |
3761 it->IsElement() | 3747 it->IsElement() |
3762 ? LookupIterator(it->isolate(), it->GetReceiver(), it->index(), c) | 3748 ? LookupIterator(it->isolate(), it->GetReceiver(), it->index(), c) |
3763 : LookupIterator(it->GetReceiver(), it->name(), c); | 3749 : LookupIterator(it->GetReceiver(), it->name(), c); |
3764 | 3750 |
3765 for (; own_lookup.IsFound(); own_lookup.Next()) { | 3751 for (; own_lookup.IsFound(); own_lookup.Next()) { |
3766 switch (own_lookup.state()) { | 3752 switch (own_lookup.state()) { |
3767 case LookupIterator::ACCESS_CHECK: | 3753 case LookupIterator::ACCESS_CHECK: |
3768 if (!own_lookup.HasAccess()) { | 3754 if (!own_lookup.HasAccess()) { |
3769 MAYBE_RETURN_NULL(JSObject::SetPropertyWithFailedAccessCheck( | 3755 return JSObject::SetPropertyWithFailedAccessCheck(&own_lookup, value, |
3770 &own_lookup, value, THROW_ON_ERROR)); | 3756 should_throw); |
3771 return value; | |
3772 } | 3757 } |
3773 break; | 3758 break; |
3774 | 3759 |
3775 case LookupIterator::INTEGER_INDEXED_EXOTIC: | 3760 case LookupIterator::INTEGER_INDEXED_EXOTIC: |
3776 return RedefineNonconfigurableProperty(it->isolate(), it->GetName(), | 3761 return RedefineNonconfigurableProperty(it->isolate(), it->GetName(), |
3777 value, language_mode); | 3762 value, should_throw); |
3778 | 3763 |
3779 case LookupIterator::DATA: { | 3764 case LookupIterator::DATA: { |
3780 PropertyDetails details = own_lookup.property_details(); | 3765 PropertyDetails details = own_lookup.property_details(); |
3781 if (details.IsConfigurable() || !details.IsReadOnly()) { | 3766 if (details.IsConfigurable() || !details.IsReadOnly()) { |
3782 return JSObject::DefineOwnPropertyIgnoreAttributes( | 3767 return JSObject::DefineOwnPropertyIgnoreAttributes( |
3783 &own_lookup, value, details.attributes()); | 3768 &own_lookup, value, details.attributes(), should_throw); |
3784 } | 3769 } |
3785 MAYBE_RETURN_NULL(WriteToReadOnlyProperty( | 3770 return WriteToReadOnlyProperty(&own_lookup, value, should_throw); |
3786 &own_lookup, value, language_mode, THROW_ON_ERROR)); | |
3787 return value; | |
3788 } | 3771 } |
3789 | 3772 |
3790 case LookupIterator::ACCESSOR: { | 3773 case LookupIterator::ACCESSOR: { |
3791 PropertyDetails details = own_lookup.property_details(); | 3774 PropertyDetails details = own_lookup.property_details(); |
3792 if (details.IsConfigurable()) { | 3775 if (details.IsConfigurable()) { |
3793 return JSObject::DefineOwnPropertyIgnoreAttributes( | 3776 return JSObject::DefineOwnPropertyIgnoreAttributes( |
3794 &own_lookup, value, details.attributes()); | 3777 &own_lookup, value, details.attributes(), should_throw); |
3795 } | 3778 } |
3796 | 3779 |
3797 return RedefineNonconfigurableProperty(it->isolate(), it->GetName(), | 3780 return RedefineNonconfigurableProperty(it->isolate(), it->GetName(), |
3798 value, language_mode); | 3781 value, should_throw); |
3799 } | 3782 } |
3800 | 3783 |
3801 case LookupIterator::INTERCEPTOR: | 3784 case LookupIterator::INTERCEPTOR: |
3802 case LookupIterator::JSPROXY: { | 3785 case LookupIterator::JSPROXY: { |
3803 bool found = false; | 3786 bool found = false; |
3804 Maybe<bool> result = | 3787 Maybe<bool> result = SetPropertyInternal( |
3805 SetPropertyInternal(&own_lookup, value, language_mode, | 3788 &own_lookup, value, language_mode, store_mode, &found); |
3806 THROW_ON_ERROR, store_mode, &found); | 3789 if (found) return result; |
3807 if (found) { | |
3808 MAYBE_RETURN_NULL(result); | |
3809 return value; | |
3810 } | |
3811 break; | 3790 break; |
3812 } | 3791 } |
3813 | 3792 |
3814 case LookupIterator::NOT_FOUND: | 3793 case LookupIterator::NOT_FOUND: |
3815 case LookupIterator::TRANSITION: | 3794 case LookupIterator::TRANSITION: |
3816 UNREACHABLE(); | 3795 UNREACHABLE(); |
3817 } | 3796 } |
3818 } | 3797 } |
3819 | 3798 |
3820 return JSObject::AddDataProperty(&own_lookup, value, NONE, language_mode, | 3799 return JSObject::AddDataProperty(&own_lookup, value, NONE, should_throw, |
3821 store_mode); | 3800 store_mode); |
3822 } | 3801 } |
3823 | 3802 |
3824 | 3803 |
3825 MaybeHandle<Object> Object::ReadAbsentProperty(LookupIterator* it, | 3804 MaybeHandle<Object> Object::ReadAbsentProperty(LookupIterator* it, |
3826 LanguageMode language_mode) { | 3805 LanguageMode language_mode) { |
3827 if (is_strong(language_mode)) { | 3806 if (is_strong(language_mode)) { |
3828 THROW_NEW_ERROR(it->isolate(), | 3807 THROW_NEW_ERROR(it->isolate(), |
3829 NewTypeError(MessageTemplate::kStrongPropertyAccess, | 3808 NewTypeError(MessageTemplate::kStrongPropertyAccess, |
3830 it->GetName(), it->GetReceiver()), | 3809 it->GetName(), it->GetReceiver()), |
(...skipping 13 matching lines...) Expand all Loading... |
3844 Object); | 3823 Object); |
3845 } | 3824 } |
3846 return isolate->factory()->undefined_value(); | 3825 return isolate->factory()->undefined_value(); |
3847 } | 3826 } |
3848 | 3827 |
3849 | 3828 |
3850 Maybe<bool> Object::CannotCreateProperty(Isolate* isolate, | 3829 Maybe<bool> Object::CannotCreateProperty(Isolate* isolate, |
3851 Handle<Object> receiver, | 3830 Handle<Object> receiver, |
3852 Handle<Object> name, | 3831 Handle<Object> name, |
3853 Handle<Object> value, | 3832 Handle<Object> value, |
3854 LanguageMode language_mode, | |
3855 ShouldThrow should_throw) { | 3833 ShouldThrow should_throw) { |
3856 if (is_sloppy(language_mode)) return Just(true); | |
3857 RETURN_FAILURE( | 3834 RETURN_FAILURE( |
3858 isolate, should_throw, | 3835 isolate, should_throw, |
3859 NewTypeError(MessageTemplate::kStrictCannotCreateProperty, name, | 3836 NewTypeError(MessageTemplate::kStrictCannotCreateProperty, name, |
3860 Object::TypeOf(isolate, receiver), receiver)); | 3837 Object::TypeOf(isolate, receiver), receiver)); |
3861 } | 3838 } |
3862 | 3839 |
3863 | 3840 |
3864 Maybe<bool> Object::WriteToReadOnlyProperty(LookupIterator* it, | 3841 Maybe<bool> Object::WriteToReadOnlyProperty(LookupIterator* it, |
3865 Handle<Object> value, | 3842 Handle<Object> value, |
3866 LanguageMode language_mode, | |
3867 ShouldThrow should_throw) { | 3843 ShouldThrow should_throw) { |
3868 return WriteToReadOnlyProperty(it->isolate(), it->GetReceiver(), | 3844 return WriteToReadOnlyProperty(it->isolate(), it->GetReceiver(), |
3869 it->GetName(), value, language_mode, | 3845 it->GetName(), value, should_throw); |
3870 should_throw); | |
3871 } | 3846 } |
3872 | 3847 |
3873 | 3848 |
3874 Maybe<bool> Object::WriteToReadOnlyProperty(Isolate* isolate, | 3849 Maybe<bool> Object::WriteToReadOnlyProperty(Isolate* isolate, |
3875 Handle<Object> receiver, | 3850 Handle<Object> receiver, |
3876 Handle<Object> name, | 3851 Handle<Object> name, |
3877 Handle<Object> value, | 3852 Handle<Object> value, |
3878 LanguageMode language_mode, | |
3879 ShouldThrow should_throw) { | 3853 ShouldThrow should_throw) { |
3880 if (is_sloppy(language_mode)) return Just(true); | |
3881 RETURN_FAILURE(isolate, should_throw, | 3854 RETURN_FAILURE(isolate, should_throw, |
3882 NewTypeError(MessageTemplate::kStrictReadOnlyProperty, name, | 3855 NewTypeError(MessageTemplate::kStrictReadOnlyProperty, name, |
3883 Object::TypeOf(isolate, receiver), receiver)); | 3856 Object::TypeOf(isolate, receiver), receiver)); |
3884 } | 3857 } |
3885 | 3858 |
3886 | 3859 |
3887 MaybeHandle<Object> Object::RedefineNonconfigurableProperty( | 3860 Maybe<bool> Object::RedefineNonconfigurableProperty(Isolate* isolate, |
3888 Isolate* isolate, Handle<Object> name, Handle<Object> value, | 3861 Handle<Object> name, |
3889 LanguageMode language_mode) { | 3862 Handle<Object> value, |
3890 if (is_sloppy(language_mode)) return value; | 3863 ShouldThrow should_throw) { |
3891 THROW_NEW_ERROR(isolate, | 3864 RETURN_FAILURE(isolate, should_throw, |
3892 NewTypeError(MessageTemplate::kRedefineDisallowed, name), | 3865 NewTypeError(MessageTemplate::kRedefineDisallowed, name)); |
3893 Object); | |
3894 } | 3866 } |
3895 | 3867 |
3896 | 3868 |
3897 Maybe<bool> Object::SetDataProperty(LookupIterator* it, Handle<Object> value, | 3869 Maybe<bool> Object::SetDataProperty(LookupIterator* it, Handle<Object> value, |
3898 ShouldThrow should_throw) { | 3870 ShouldThrow should_throw) { |
3899 // Proxies are handled on the WithHandler path. Other non-JSObjects cannot | 3871 // Proxies are handled on the WithHandler path. Other non-JSObjects cannot |
3900 // have own properties. | 3872 // have own properties. |
3901 Handle<JSObject> receiver = Handle<JSObject>::cast(it->GetReceiver()); | 3873 Handle<JSObject> receiver = Handle<JSObject>::cast(it->GetReceiver()); |
3902 | 3874 |
3903 // Store on the holder which may be hidden behind the receiver. | 3875 // Store on the holder which may be hidden behind the receiver. |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3993 isolate->factory()->NewNumberFromUint(add_count); | 3965 isolate->factory()->NewNumberFromUint(add_count); |
3994 | 3966 |
3995 Handle<Object> args[] = {object, index_object, deleted, add_count_object}; | 3967 Handle<Object> args[] = {object, index_object, deleted, add_count_object}; |
3996 | 3968 |
3997 return Execution::Call( | 3969 return Execution::Call( |
3998 isolate, Handle<JSFunction>(isolate->observers_enqueue_splice()), | 3970 isolate, Handle<JSFunction>(isolate->observers_enqueue_splice()), |
3999 isolate->factory()->undefined_value(), arraysize(args), args); | 3971 isolate->factory()->undefined_value(), arraysize(args), args); |
4000 } | 3972 } |
4001 | 3973 |
4002 | 3974 |
4003 MaybeHandle<Object> Object::AddDataProperty(LookupIterator* it, | |
4004 Handle<Object> value, | |
4005 PropertyAttributes attributes, | |
4006 LanguageMode language_mode, | |
4007 StoreFromKeyed store_mode) { | |
4008 MAYBE_RETURN_NULL(AddDataProperty(it, value, attributes, language_mode, | |
4009 THROW_ON_ERROR, store_mode)); | |
4010 return value; | |
4011 } | |
4012 | |
4013 | |
4014 Maybe<bool> Object::AddDataProperty(LookupIterator* it, Handle<Object> value, | 3975 Maybe<bool> Object::AddDataProperty(LookupIterator* it, Handle<Object> value, |
4015 PropertyAttributes attributes, | 3976 PropertyAttributes attributes, |
4016 LanguageMode language_mode, | |
4017 ShouldThrow should_throw, | 3977 ShouldThrow should_throw, |
4018 StoreFromKeyed store_mode) { | 3978 StoreFromKeyed store_mode) { |
4019 DCHECK(!it->GetReceiver()->IsJSProxy()); | 3979 DCHECK(!it->GetReceiver()->IsJSProxy()); |
4020 if (!it->GetReceiver()->IsJSObject()) { | 3980 if (!it->GetReceiver()->IsJSObject()) { |
4021 return CannotCreateProperty(it->isolate(), it->GetReceiver(), it->GetName(), | 3981 return CannotCreateProperty(it->isolate(), it->GetReceiver(), it->GetName(), |
4022 value, language_mode, should_throw); | 3982 value, should_throw); |
4023 } | 3983 } |
4024 | 3984 |
4025 DCHECK_NE(LookupIterator::INTEGER_INDEXED_EXOTIC, it->state()); | 3985 DCHECK_NE(LookupIterator::INTEGER_INDEXED_EXOTIC, it->state()); |
4026 | 3986 |
4027 Handle<JSObject> receiver = it->GetStoreTarget(); | 3987 Handle<JSObject> receiver = it->GetStoreTarget(); |
4028 | 3988 |
4029 // If the receiver is a JSGlobalProxy, store on the prototype (JSGlobalObject) | 3989 // If the receiver is a JSGlobalProxy, store on the prototype (JSGlobalObject) |
4030 // instead. If the prototype is Null, the proxy is detached. | 3990 // instead. If the prototype is Null, the proxy is detached. |
4031 if (receiver->IsJSGlobalProxy()) return Just(true); | 3991 if (receiver->IsJSGlobalProxy()) return Just(true); |
4032 | 3992 |
4033 Isolate* isolate = it->isolate(); | 3993 Isolate* isolate = it->isolate(); |
4034 | 3994 |
4035 if (!receiver->map()->is_extensible() && | 3995 if (!receiver->map()->is_extensible() && |
4036 (it->IsElement() || !isolate->IsInternallyUsedPropertyName(it->name()))) { | 3996 (it->IsElement() || !isolate->IsInternallyUsedPropertyName(it->name()))) { |
4037 if (is_sloppy(language_mode)) return Just(true); | |
4038 RETURN_FAILURE( | 3997 RETURN_FAILURE( |
4039 isolate, should_throw, | 3998 isolate, should_throw, |
4040 NewTypeError(MessageTemplate::kObjectNotExtensible, it->GetName())); | 3999 NewTypeError(MessageTemplate::kObjectNotExtensible, it->GetName())); |
4041 } | 4000 } |
4042 | 4001 |
4043 if (it->IsElement()) { | 4002 if (it->IsElement()) { |
4044 if (receiver->IsJSArray()) { | 4003 if (receiver->IsJSArray()) { |
4045 Handle<JSArray> array = Handle<JSArray>::cast(receiver); | 4004 Handle<JSArray> array = Handle<JSArray>::cast(receiver); |
4046 if (JSArray::WouldChangeReadOnlyLength(array, it->index())) { | 4005 if (JSArray::WouldChangeReadOnlyLength(array, it->index())) { |
4047 if (is_sloppy(language_mode)) return Just(true); | |
4048 RETURN_FAILURE(array->GetIsolate(), should_throw, | 4006 RETURN_FAILURE(array->GetIsolate(), should_throw, |
4049 NewTypeError(MessageTemplate::kStrictReadOnlyProperty, | 4007 NewTypeError(MessageTemplate::kStrictReadOnlyProperty, |
4050 isolate->factory()->length_string(), | 4008 isolate->factory()->length_string(), |
4051 Object::TypeOf(isolate, array), array)); | 4009 Object::TypeOf(isolate, array), array)); |
4052 } | 4010 } |
4053 | 4011 |
4054 if (FLAG_trace_external_array_abuse && | 4012 if (FLAG_trace_external_array_abuse && |
4055 array->HasFixedTypedArrayElements()) { | 4013 array->HasFixedTypedArrayElements()) { |
4056 CheckArrayAbuse(array, "typed elements write", it->index(), true); | 4014 CheckArrayAbuse(array, "typed elements write", it->index(), true); |
4057 } | 4015 } |
(...skipping 389 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4447 Nothing<bool>()); | 4405 Nothing<bool>()); |
4448 | 4406 |
4449 return Just(result->BooleanValue()); | 4407 return Just(result->BooleanValue()); |
4450 } | 4408 } |
4451 | 4409 |
4452 | 4410 |
4453 Maybe<bool> JSProxy::SetPropertyWithHandler(Handle<JSProxy> proxy, | 4411 Maybe<bool> JSProxy::SetPropertyWithHandler(Handle<JSProxy> proxy, |
4454 Handle<Object> receiver, | 4412 Handle<Object> receiver, |
4455 Handle<Name> name, | 4413 Handle<Name> name, |
4456 Handle<Object> value, | 4414 Handle<Object> value, |
4457 LanguageMode language_mode, | |
4458 ShouldThrow should_throw) { | 4415 ShouldThrow should_throw) { |
4459 Isolate* isolate = proxy->GetIsolate(); | 4416 Isolate* isolate = proxy->GetIsolate(); |
4460 | 4417 |
4461 // TODO(rossberg): adjust once there is a story for symbols vs proxies. | 4418 // TODO(rossberg): adjust once there is a story for symbols vs proxies. |
4462 if (name->IsSymbol()) return Just(true); | 4419 if (name->IsSymbol()) return Just(true); |
4463 | 4420 |
4464 Handle<Object> args[] = { receiver, name, value }; | 4421 Handle<Object> args[] = { receiver, name, value }; |
4465 RETURN_ON_EXCEPTION_VALUE(isolate, | 4422 RETURN_ON_EXCEPTION_VALUE(isolate, |
4466 CallTrap(proxy, "set", isolate->derived_set_trap(), | 4423 CallTrap(proxy, "set", isolate->derived_set_trap(), |
4467 arraysize(args), args), | 4424 arraysize(args), args), |
4468 Nothing<bool>()); | 4425 Nothing<bool>()); |
4469 | 4426 |
4470 return Just(true); | 4427 return Just(true); |
4471 // TODO(neis): This needs to be made spec-conformant by throwing a TypeError | 4428 // TODO(neis): This needs to be made spec-conformant by looking at the |
4472 // if the trap's result is falsish. | 4429 // trap's result. |
4473 } | 4430 } |
4474 | 4431 |
4475 | 4432 |
4476 Maybe<bool> JSProxy::SetPropertyViaPrototypesWithHandler( | 4433 Maybe<bool> JSProxy::SetPropertyViaPrototypesWithHandler( |
4477 Handle<JSProxy> proxy, Handle<Object> receiver, Handle<Name> name, | 4434 Handle<JSProxy> proxy, Handle<Object> receiver, Handle<Name> name, |
4478 Handle<Object> value, LanguageMode language_mode, ShouldThrow should_throw, | 4435 Handle<Object> value, ShouldThrow should_throw, bool* done) { |
4479 bool* done) { | |
4480 Isolate* isolate = proxy->GetIsolate(); | 4436 Isolate* isolate = proxy->GetIsolate(); |
4481 Handle<Object> handler(proxy->handler(), isolate); // Trap might morph proxy. | 4437 Handle<Object> handler(proxy->handler(), isolate); // Trap might morph proxy. |
4482 | 4438 |
4483 // TODO(rossberg): adjust once there is a story for symbols vs proxies. | 4439 // TODO(rossberg): adjust once there is a story for symbols vs proxies. |
4484 if (name->IsSymbol()) { | 4440 if (name->IsSymbol()) { |
4485 *done = false; // Return value will be ignored. | 4441 *done = false; // Return value will be ignored. |
4486 return Nothing<bool>(); | 4442 return Nothing<bool>(); |
4487 } | 4443 } |
4488 | 4444 |
4489 *done = true; // except where redefined... | 4445 *done = true; // except where redefined... |
(...skipping 19 matching lines...) Expand all Loading... |
4509 Nothing<bool>()); | 4465 Nothing<bool>()); |
4510 | 4466 |
4511 // [[GetProperty]] requires to check that all properties are configurable. | 4467 // [[GetProperty]] requires to check that all properties are configurable. |
4512 Handle<String> configurable_name = | 4468 Handle<String> configurable_name = |
4513 isolate->factory()->InternalizeOneByteString( | 4469 isolate->factory()->InternalizeOneByteString( |
4514 STATIC_CHAR_VECTOR("configurable_")); | 4470 STATIC_CHAR_VECTOR("configurable_")); |
4515 Handle<Object> configurable = | 4471 Handle<Object> configurable = |
4516 Object::GetProperty(desc, configurable_name).ToHandleChecked(); | 4472 Object::GetProperty(desc, configurable_name).ToHandleChecked(); |
4517 DCHECK(configurable->IsBoolean()); | 4473 DCHECK(configurable->IsBoolean()); |
4518 if (configurable->IsFalse()) { | 4474 if (configurable->IsFalse()) { |
4519 RETURN_FAILURE( | 4475 isolate->Throw(*isolate->factory()->NewTypeError( |
4520 isolate, should_throw, | 4476 MessageTemplate::kProxyPropNotConfigurable, handler, name, |
4521 NewTypeError(MessageTemplate::kProxyPropNotConfigurable, handler, name, | 4477 isolate->factory()->NewStringFromAsciiChecked( |
4522 isolate->factory()->NewStringFromAsciiChecked( | 4478 "getPropertyDescriptor"))); |
4523 "getPropertyDescriptor"))); | 4479 return Nothing<bool>(); |
4524 } | 4480 } |
4525 DCHECK(configurable->IsTrue()); | 4481 DCHECK(configurable->IsTrue()); |
4526 | 4482 |
4527 // Check for DataDescriptor. | 4483 // Check for DataDescriptor. |
4528 Handle<String> hasWritable_name = | 4484 Handle<String> hasWritable_name = |
4529 isolate->factory()->InternalizeOneByteString( | 4485 isolate->factory()->InternalizeOneByteString( |
4530 STATIC_CHAR_VECTOR("hasWritable_")); | 4486 STATIC_CHAR_VECTOR("hasWritable_")); |
4531 Handle<Object> hasWritable = | 4487 Handle<Object> hasWritable = |
4532 Object::GetProperty(desc, hasWritable_name).ToHandleChecked(); | 4488 Object::GetProperty(desc, hasWritable_name).ToHandleChecked(); |
4533 DCHECK(hasWritable->IsBoolean()); | 4489 DCHECK(hasWritable->IsBoolean()); |
4534 if (hasWritable->IsTrue()) { | 4490 if (hasWritable->IsTrue()) { |
4535 Handle<String> writable_name = isolate->factory()->InternalizeOneByteString( | 4491 Handle<String> writable_name = isolate->factory()->InternalizeOneByteString( |
4536 STATIC_CHAR_VECTOR("writable_")); | 4492 STATIC_CHAR_VECTOR("writable_")); |
4537 Handle<Object> writable = | 4493 Handle<Object> writable = |
4538 Object::GetProperty(desc, writable_name).ToHandleChecked(); | 4494 Object::GetProperty(desc, writable_name).ToHandleChecked(); |
4539 DCHECK(writable->IsBoolean()); | 4495 DCHECK(writable->IsBoolean()); |
4540 *done = writable->IsFalse(); | 4496 *done = writable->IsFalse(); |
4541 if (!*done) return Nothing<bool>(); // Return value will be ignored. | 4497 if (!*done) return Nothing<bool>(); // Return value will be ignored. |
4542 return WriteToReadOnlyProperty(isolate, receiver, name, value, | 4498 return WriteToReadOnlyProperty(isolate, receiver, name, value, |
4543 language_mode, should_throw); | 4499 should_throw); |
4544 } | 4500 } |
4545 | 4501 |
4546 // We have an AccessorDescriptor. | 4502 // We have an AccessorDescriptor. |
4547 Handle<String> set_name = | 4503 Handle<String> set_name = |
4548 isolate->factory()->InternalizeOneByteString(STATIC_CHAR_VECTOR("set_")); | 4504 isolate->factory()->InternalizeOneByteString(STATIC_CHAR_VECTOR("set_")); |
4549 Handle<Object> setter = Object::GetProperty(desc, set_name).ToHandleChecked(); | 4505 Handle<Object> setter = Object::GetProperty(desc, set_name).ToHandleChecked(); |
4550 if (!setter->IsUndefined()) { | 4506 if (!setter->IsUndefined()) { |
4551 // TODO(rossberg): nicer would be to cast to some JSCallable here... | 4507 // TODO(rossberg): nicer would be to cast to some JSCallable here... |
4552 return SetPropertyWithDefinedSetter( | 4508 return SetPropertyWithDefinedSetter( |
4553 receiver, Handle<JSReceiver>::cast(setter), value, should_throw); | 4509 receiver, Handle<JSReceiver>::cast(setter), value, should_throw); |
4554 } | 4510 } |
4555 | 4511 |
4556 if (is_sloppy(language_mode)) return Just(true); | |
4557 RETURN_FAILURE( | 4512 RETURN_FAILURE( |
4558 isolate, should_throw, | 4513 isolate, should_throw, |
4559 NewTypeError(MessageTemplate::kNoSetterInCallback, name, proxy)); | 4514 NewTypeError(MessageTemplate::kNoSetterInCallback, name, proxy)); |
4560 } | 4515 } |
4561 | 4516 |
4562 | 4517 |
4563 MaybeHandle<Object> JSProxy::DeletePropertyWithHandler( | 4518 MaybeHandle<Object> JSProxy::DeletePropertyWithHandler( |
4564 Handle<JSProxy> proxy, Handle<Name> name, LanguageMode language_mode) { | 4519 Handle<JSProxy> proxy, Handle<Name> name, LanguageMode language_mode) { |
4565 Isolate* isolate = proxy->GetIsolate(); | 4520 Isolate* isolate = proxy->GetIsolate(); |
4566 | 4521 |
(...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4780 #ifdef DEBUG | 4735 #ifdef DEBUG |
4781 uint32_t index; | 4736 uint32_t index; |
4782 DCHECK(!object->IsJSProxy()); | 4737 DCHECK(!object->IsJSProxy()); |
4783 DCHECK(!name->AsArrayIndex(&index)); | 4738 DCHECK(!name->AsArrayIndex(&index)); |
4784 Maybe<PropertyAttributes> maybe = GetPropertyAttributes(&it); | 4739 Maybe<PropertyAttributes> maybe = GetPropertyAttributes(&it); |
4785 DCHECK(maybe.IsJust()); | 4740 DCHECK(maybe.IsJust()); |
4786 DCHECK(!it.IsFound()); | 4741 DCHECK(!it.IsFound()); |
4787 DCHECK(object->map()->is_extensible() || | 4742 DCHECK(object->map()->is_extensible() || |
4788 it.isolate()->IsInternallyUsedPropertyName(name)); | 4743 it.isolate()->IsInternallyUsedPropertyName(name)); |
4789 #endif | 4744 #endif |
4790 AddDataProperty(&it, value, attributes, STRICT, | 4745 CHECK(AddDataProperty(&it, value, attributes, THROW_ON_ERROR, |
4791 CERTAINLY_NOT_STORE_FROM_KEYED).Check(); | 4746 CERTAINLY_NOT_STORE_FROM_KEYED) |
| 4747 .IsJust()); |
4792 } | 4748 } |
4793 | 4749 |
4794 | 4750 |
4795 // static | 4751 // static |
4796 void ExecutableAccessorInfo::ClearSetter(Handle<ExecutableAccessorInfo> info) { | 4752 void ExecutableAccessorInfo::ClearSetter(Handle<ExecutableAccessorInfo> info) { |
4797 Handle<Object> object = v8::FromCData(info->GetIsolate(), nullptr); | 4753 Handle<Object> object = v8::FromCData(info->GetIsolate(), nullptr); |
4798 info->set_setter(*object); | 4754 info->set_setter(*object); |
4799 } | 4755 } |
4800 | 4756 |
4801 | 4757 |
4802 // Reconfigures a property to a data property with attributes, even if it is not | 4758 // Reconfigures a property to a data property with attributes, even if it is not |
4803 // reconfigurable. | 4759 // reconfigurable. |
4804 // Requires a LookupIterator that does not look at the prototype chain beyond | 4760 // Requires a LookupIterator that does not look at the prototype chain beyond |
4805 // hidden prototypes. | 4761 // hidden prototypes. |
4806 MaybeHandle<Object> JSObject::DefineOwnPropertyIgnoreAttributes( | 4762 MaybeHandle<Object> JSObject::DefineOwnPropertyIgnoreAttributes( |
4807 LookupIterator* it, Handle<Object> value, PropertyAttributes attributes, | 4763 LookupIterator* it, Handle<Object> value, PropertyAttributes attributes, |
4808 ExecutableAccessorInfoHandling handling) { | 4764 ExecutableAccessorInfoHandling handling) { |
| 4765 MAYBE_RETURN_NULL(DefineOwnPropertyIgnoreAttributes( |
| 4766 it, value, attributes, THROW_ON_ERROR, handling)); |
| 4767 return value; |
| 4768 } |
| 4769 |
| 4770 |
| 4771 Maybe<bool> JSObject::DefineOwnPropertyIgnoreAttributes( |
| 4772 LookupIterator* it, Handle<Object> value, PropertyAttributes attributes, |
| 4773 ShouldThrow should_throw, ExecutableAccessorInfoHandling handling) { |
4809 Handle<JSObject> object = Handle<JSObject>::cast(it->GetReceiver()); | 4774 Handle<JSObject> object = Handle<JSObject>::cast(it->GetReceiver()); |
4810 bool is_observed = object->map()->is_observed() && | 4775 bool is_observed = object->map()->is_observed() && |
4811 (it->IsElement() || | 4776 (it->IsElement() || |
4812 !it->isolate()->IsInternallyUsedPropertyName(it->name())); | 4777 !it->isolate()->IsInternallyUsedPropertyName(it->name())); |
4813 | 4778 |
4814 for (; it->IsFound(); it->Next()) { | 4779 for (; it->IsFound(); it->Next()) { |
4815 switch (it->state()) { | 4780 switch (it->state()) { |
4816 case LookupIterator::JSPROXY: | 4781 case LookupIterator::JSPROXY: |
4817 case LookupIterator::NOT_FOUND: | 4782 case LookupIterator::NOT_FOUND: |
4818 case LookupIterator::TRANSITION: | 4783 case LookupIterator::TRANSITION: |
4819 UNREACHABLE(); | 4784 UNREACHABLE(); |
4820 | 4785 |
4821 case LookupIterator::ACCESS_CHECK: | 4786 case LookupIterator::ACCESS_CHECK: |
4822 if (!it->HasAccess()) { | 4787 if (!it->HasAccess()) { |
4823 it->isolate()->ReportFailedAccessCheck(it->GetHolder<JSObject>()); | 4788 it->isolate()->ReportFailedAccessCheck(it->GetHolder<JSObject>()); |
4824 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(it->isolate(), Object); | 4789 RETURN_VALUE_IF_SCHEDULED_EXCEPTION(it->isolate(), Nothing<bool>()); |
4825 return value; | 4790 return Just(true); |
4826 } | 4791 } |
4827 break; | 4792 break; |
4828 | 4793 |
4829 // If there's an interceptor, try to store the property with the | 4794 // If there's an interceptor, try to store the property with the |
4830 // interceptor. | 4795 // interceptor. |
4831 // In case of success, the attributes will have been reset to the default | 4796 // In case of success, the attributes will have been reset to the default |
4832 // attributes of the interceptor, rather than the incoming attributes. | 4797 // attributes of the interceptor, rather than the incoming attributes. |
4833 // | 4798 // |
4834 // TODO(verwaest): JSProxy afterwards verify the attributes that the | 4799 // TODO(verwaest): JSProxy afterwards verify the attributes that the |
4835 // JSProxy claims it has, and verifies that they are compatible. If not, | 4800 // JSProxy claims it has, and verifies that they are compatible. If not, |
4836 // they throw. Here we should do the same. | 4801 // they throw. Here we should do the same. |
4837 case LookupIterator::INTERCEPTOR: | 4802 case LookupIterator::INTERCEPTOR: |
4838 if (handling == DONT_FORCE_FIELD) { | 4803 if (handling == DONT_FORCE_FIELD) { |
4839 Maybe<bool> result = JSObject::SetPropertyWithInterceptor(it, value); | 4804 Maybe<bool> result = JSObject::SetPropertyWithInterceptor(it, value); |
4840 if (result.IsNothing()) return MaybeHandle<Object>(); | 4805 if (result.IsNothing() || result.FromJust()) return result; |
4841 if (result.FromJust()) return value; | |
4842 } | 4806 } |
4843 break; | 4807 break; |
4844 | 4808 |
4845 case LookupIterator::ACCESSOR: { | 4809 case LookupIterator::ACCESSOR: { |
4846 Handle<Object> accessors = it->GetAccessors(); | 4810 Handle<Object> accessors = it->GetAccessors(); |
4847 | 4811 |
4848 // Special handling for ExecutableAccessorInfo, which behaves like a | 4812 // Special handling for ExecutableAccessorInfo, which behaves like a |
4849 // data property. | 4813 // data property. |
4850 if (accessors->IsExecutableAccessorInfo() && | 4814 if (accessors->IsExecutableAccessorInfo() && |
4851 handling == DONT_FORCE_FIELD) { | 4815 handling == DONT_FORCE_FIELD) { |
4852 PropertyDetails details = it->property_details(); | 4816 PropertyDetails details = it->property_details(); |
4853 // Ensure the context isn't changed after calling into accessors. | 4817 // Ensure the context isn't changed after calling into accessors. |
4854 AssertNoContextChange ncc(it->isolate()); | 4818 AssertNoContextChange ncc(it->isolate()); |
4855 | 4819 |
4856 Maybe<bool> result = JSObject::SetPropertyWithAccessor( | 4820 Maybe<bool> result = |
4857 it, value, STRICT, THROW_ON_ERROR); | 4821 JSObject::SetPropertyWithAccessor(it, value, should_throw); |
4858 if (result.IsNothing()) return MaybeHandle<Object>(); | 4822 if (result.IsNothing() || !result.FromJust()) return result; |
4859 | 4823 |
4860 if (details.attributes() == attributes) return value; | 4824 if (details.attributes() == attributes) return Just(true); |
4861 | 4825 |
4862 // Reconfigure the accessor if attributes mismatch. | 4826 // Reconfigure the accessor if attributes mismatch. |
4863 Handle<ExecutableAccessorInfo> new_data = Accessors::CloneAccessor( | 4827 Handle<ExecutableAccessorInfo> new_data = Accessors::CloneAccessor( |
4864 it->isolate(), Handle<ExecutableAccessorInfo>::cast(accessors)); | 4828 it->isolate(), Handle<ExecutableAccessorInfo>::cast(accessors)); |
4865 new_data->set_property_attributes(attributes); | 4829 new_data->set_property_attributes(attributes); |
4866 // By clearing the setter we don't have to introduce a lookup to | 4830 // By clearing the setter we don't have to introduce a lookup to |
4867 // the setter, simply make it unavailable to reflect the | 4831 // the setter, simply make it unavailable to reflect the |
4868 // attributes. | 4832 // attributes. |
4869 if (attributes & READ_ONLY) { | 4833 if (attributes & READ_ONLY) { |
4870 ExecutableAccessorInfo::ClearSetter(new_data); | 4834 ExecutableAccessorInfo::ClearSetter(new_data); |
4871 } | 4835 } |
4872 | 4836 |
4873 it->TransitionToAccessorPair(new_data, attributes); | 4837 it->TransitionToAccessorPair(new_data, attributes); |
4874 } else { | 4838 } else { |
4875 it->ReconfigureDataProperty(value, attributes); | 4839 it->ReconfigureDataProperty(value, attributes); |
4876 } | 4840 } |
4877 | 4841 |
4878 if (is_observed) { | 4842 if (is_observed) { |
4879 RETURN_ON_EXCEPTION( | 4843 RETURN_ON_EXCEPTION_VALUE( |
4880 it->isolate(), | 4844 it->isolate(), |
4881 EnqueueChangeRecord(object, "reconfigure", it->GetName(), | 4845 EnqueueChangeRecord(object, "reconfigure", it->GetName(), |
4882 it->factory()->the_hole_value()), | 4846 it->factory()->the_hole_value()), |
4883 Object); | 4847 Nothing<bool>()); |
4884 } | 4848 } |
4885 | 4849 |
4886 return value; | 4850 return Just(true); |
4887 } | 4851 } |
4888 case LookupIterator::INTEGER_INDEXED_EXOTIC: | 4852 case LookupIterator::INTEGER_INDEXED_EXOTIC: |
4889 return RedefineNonconfigurableProperty(it->isolate(), it->GetName(), | 4853 return RedefineNonconfigurableProperty(it->isolate(), it->GetName(), |
4890 value, STRICT); | 4854 value, should_throw); |
4891 | 4855 |
4892 case LookupIterator::DATA: { | 4856 case LookupIterator::DATA: { |
4893 PropertyDetails details = it->property_details(); | 4857 PropertyDetails details = it->property_details(); |
4894 Handle<Object> old_value = it->factory()->the_hole_value(); | 4858 Handle<Object> old_value = it->factory()->the_hole_value(); |
4895 // Regular property update if the attributes match. | 4859 // Regular property update if the attributes match. |
4896 if (details.attributes() == attributes) { | 4860 if (details.attributes() == attributes) { |
4897 MAYBE_RETURN_NULL(SetDataProperty(it, value, THROW_ON_ERROR)); | 4861 return SetDataProperty(it, value, should_throw); |
4898 return value; | |
4899 } | 4862 } |
4900 | 4863 |
4901 // Special case: properties of typed arrays cannot be reconfigured to | 4864 // Special case: properties of typed arrays cannot be reconfigured to |
4902 // non-writable nor to non-enumerable. | 4865 // non-writable nor to non-enumerable. |
4903 if (it->IsElement() && object->HasFixedTypedArrayElements()) { | 4866 if (it->IsElement() && object->HasFixedTypedArrayElements()) { |
4904 return RedefineNonconfigurableProperty(it->isolate(), it->GetName(), | 4867 return RedefineNonconfigurableProperty(it->isolate(), it->GetName(), |
4905 value, STRICT); | 4868 value, should_throw); |
4906 } | 4869 } |
4907 | 4870 |
4908 // Reconfigure the data property if the attributes mismatch. | 4871 // Reconfigure the data property if the attributes mismatch. |
4909 if (is_observed) old_value = it->GetDataValue(); | 4872 if (is_observed) old_value = it->GetDataValue(); |
4910 | 4873 |
4911 it->ReconfigureDataProperty(value, attributes); | 4874 it->ReconfigureDataProperty(value, attributes); |
4912 | 4875 |
4913 if (is_observed) { | 4876 if (is_observed) { |
4914 if (old_value->SameValue(*value)) { | 4877 if (old_value->SameValue(*value)) { |
4915 old_value = it->factory()->the_hole_value(); | 4878 old_value = it->factory()->the_hole_value(); |
4916 } | 4879 } |
4917 RETURN_ON_EXCEPTION(it->isolate(), | 4880 RETURN_ON_EXCEPTION_VALUE( |
4918 EnqueueChangeRecord(object, "reconfigure", | 4881 it->isolate(), EnqueueChangeRecord(object, "reconfigure", |
4919 it->GetName(), old_value), | 4882 it->GetName(), old_value), |
4920 Object); | 4883 Nothing<bool>()); |
4921 } | 4884 } |
4922 return value; | 4885 return Just(true); |
4923 } | 4886 } |
4924 } | 4887 } |
4925 } | 4888 } |
4926 | 4889 |
4927 return AddDataProperty(it, value, attributes, STRICT, | 4890 return AddDataProperty(it, value, attributes, should_throw, |
4928 CERTAINLY_NOT_STORE_FROM_KEYED); | 4891 CERTAINLY_NOT_STORE_FROM_KEYED); |
4929 } | 4892 } |
4930 | 4893 |
4931 | 4894 |
4932 MaybeHandle<Object> JSObject::SetOwnPropertyIgnoreAttributes( | 4895 MaybeHandle<Object> JSObject::SetOwnPropertyIgnoreAttributes( |
4933 Handle<JSObject> object, Handle<Name> name, Handle<Object> value, | 4896 Handle<JSObject> object, Handle<Name> name, Handle<Object> value, |
4934 PropertyAttributes attributes, ExecutableAccessorInfoHandling handling) { | 4897 PropertyAttributes attributes, ExecutableAccessorInfoHandling handling) { |
4935 DCHECK(!value->IsTheHole()); | 4898 DCHECK(!value->IsTheHole()); |
4936 LookupIterator it(object, name, LookupIterator::OWN); | 4899 LookupIterator it(object, name, LookupIterator::OWN); |
4937 return DefineOwnPropertyIgnoreAttributes(&it, value, attributes, handling); | 4900 return DefineOwnPropertyIgnoreAttributes(&it, value, attributes, handling); |
(...skipping 12993 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
17931 if (cell->value() != *new_value) { | 17894 if (cell->value() != *new_value) { |
17932 cell->set_value(*new_value); | 17895 cell->set_value(*new_value); |
17933 Isolate* isolate = cell->GetIsolate(); | 17896 Isolate* isolate = cell->GetIsolate(); |
17934 cell->dependent_code()->DeoptimizeDependentCodeGroup( | 17897 cell->dependent_code()->DeoptimizeDependentCodeGroup( |
17935 isolate, DependentCode::kPropertyCellChangedGroup); | 17898 isolate, DependentCode::kPropertyCellChangedGroup); |
17936 } | 17899 } |
17937 } | 17900 } |
17938 | 17901 |
17939 } // namespace internal | 17902 } // namespace internal |
17940 } // namespace v8 | 17903 } // namespace v8 |
OLD | NEW |