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