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 848 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
859 bool AccessorInfo::IsCompatibleReceiverMap(Isolate* isolate, | 859 bool AccessorInfo::IsCompatibleReceiverMap(Isolate* isolate, |
860 Handle<AccessorInfo> info, | 860 Handle<AccessorInfo> info, |
861 Handle<Map> map) { | 861 Handle<Map> map) { |
862 if (!info->HasExpectedReceiverType()) return true; | 862 if (!info->HasExpectedReceiverType()) return true; |
863 if (!map->IsJSObjectMap()) return false; | 863 if (!map->IsJSObjectMap()) return false; |
864 return FunctionTemplateInfo::cast(info->expected_receiver_type()) | 864 return FunctionTemplateInfo::cast(info->expected_receiver_type()) |
865 ->IsTemplateFor(*map); | 865 ->IsTemplateFor(*map); |
866 } | 866 } |
867 | 867 |
868 | 868 |
869 MaybeHandle<Object> Object::SetPropertyWithAccessor( | 869 Maybe<bool> Object::SetPropertyWithAccessor(LookupIterator* it, |
870 LookupIterator* it, Handle<Object> value, LanguageMode language_mode) { | 870 Handle<Object> value, |
871 LanguageMode language_mode, | |
872 ShouldThrow should_throw) { | |
871 Isolate* isolate = it->isolate(); | 873 Isolate* isolate = it->isolate(); |
872 Handle<Object> structure = it->GetAccessors(); | 874 Handle<Object> structure = it->GetAccessors(); |
873 Handle<Object> receiver = it->GetReceiver(); | 875 Handle<Object> receiver = it->GetReceiver(); |
874 | 876 |
875 // We should never get here to initialize a const with the hole value since a | 877 // We should never get here to initialize a const with the hole value since a |
876 // const declaration would conflict with the setter. | 878 // const declaration would conflict with the setter. |
877 DCHECK(!structure->IsForeign()); | 879 DCHECK(!structure->IsForeign()); |
878 | 880 |
879 // API style callbacks. | 881 // API style callbacks. |
880 if (structure->IsExecutableAccessorInfo()) { | 882 if (structure->IsExecutableAccessorInfo()) { |
881 Handle<JSObject> holder = it->GetHolder<JSObject>(); | 883 Handle<JSObject> holder = it->GetHolder<JSObject>(); |
882 Handle<Name> name = it->GetName(); | 884 Handle<Name> name = it->GetName(); |
883 Handle<ExecutableAccessorInfo> info = | 885 Handle<ExecutableAccessorInfo> info = |
884 Handle<ExecutableAccessorInfo>::cast(structure); | 886 Handle<ExecutableAccessorInfo>::cast(structure); |
885 if (!info->IsCompatibleReceiver(*receiver)) { | 887 if (!info->IsCompatibleReceiver(*receiver)) { |
886 THROW_NEW_ERROR(isolate, | 888 isolate->Throw(*isolate->factory()->NewTypeError( |
887 NewTypeError(MessageTemplate::kIncompatibleMethodReceiver, | 889 MessageTemplate::kIncompatibleMethodReceiver, name, receiver)); |
888 name, receiver), | 890 return Nothing<bool>(); |
889 Object); | |
890 } | 891 } |
891 | 892 |
892 v8::AccessorNameSetterCallback call_fun = | 893 v8::AccessorNameSetterCallback call_fun = |
893 v8::ToCData<v8::AccessorNameSetterCallback>(info->setter()); | 894 v8::ToCData<v8::AccessorNameSetterCallback>(info->setter()); |
894 if (call_fun == nullptr) return value; | 895 if (call_fun == nullptr) return Just(true); |
896 // TODO(verwaest): Shouldn't this case be unreachable (at least in the | |
897 // long run?) Should we have ExecutableAccessorPairs with missing setter | |
898 // that are "writable"? If they aren't writable, shouldn't we have bailed | |
899 // out already earlier? | |
895 | 900 |
896 LOG(isolate, ApiNamedPropertyAccess("store", *holder, *name)); | 901 LOG(isolate, ApiNamedPropertyAccess("store", *holder, *name)); |
897 PropertyCallbackArguments args(isolate, info->data(), *receiver, *holder); | 902 PropertyCallbackArguments args(isolate, info->data(), *receiver, *holder); |
898 args.Call(call_fun, v8::Utils::ToLocal(name), v8::Utils::ToLocal(value)); | 903 args.Call(call_fun, v8::Utils::ToLocal(name), v8::Utils::ToLocal(value)); |
899 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object); | 904 RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<bool>()); |
900 return value; | 905 return Just(true); |
901 } | 906 } |
902 | 907 |
903 // Regular accessor. | 908 // Regular accessor. |
904 Handle<Object> setter(AccessorPair::cast(*structure)->setter(), isolate); | 909 Handle<Object> setter(AccessorPair::cast(*structure)->setter(), isolate); |
905 if (setter->IsCallable()) { | 910 if (setter->IsCallable()) { |
906 // TODO(rossberg): nicer would be to cast to some JSCallable here... | 911 // TODO(rossberg): nicer would be to cast to some JSCallable here... |
907 return SetPropertyWithDefinedSetter( | 912 return SetPropertyWithDefinedSetter( |
908 receiver, Handle<JSReceiver>::cast(setter), value); | 913 receiver, Handle<JSReceiver>::cast(setter), value, should_throw); |
909 } | 914 } |
910 | 915 |
911 if (is_sloppy(language_mode)) return value; | 916 if (is_sloppy(language_mode)) return Just(true); |
912 | 917 RETURN_FAILURE(isolate, should_throw, |
913 THROW_NEW_ERROR(isolate, | 918 NewTypeError(MessageTemplate::kNoSetterInCallback, |
914 NewTypeError(MessageTemplate::kNoSetterInCallback, | 919 it->GetName(), it->GetHolder<JSObject>())); |
915 it->GetName(), it->GetHolder<JSObject>()), | |
916 Object); | |
917 } | 920 } |
918 | 921 |
919 | 922 |
920 MaybeHandle<Object> Object::GetPropertyWithDefinedGetter( | 923 MaybeHandle<Object> Object::GetPropertyWithDefinedGetter( |
921 Handle<Object> receiver, | 924 Handle<Object> receiver, |
922 Handle<JSReceiver> getter) { | 925 Handle<JSReceiver> getter) { |
923 Isolate* isolate = getter->GetIsolate(); | 926 Isolate* isolate = getter->GetIsolate(); |
924 | 927 |
925 // Platforms with simulators like arm/arm64 expose a funny issue. If the | 928 // Platforms with simulators like arm/arm64 expose a funny issue. If the |
926 // simulator has a separate JS stack pointer from the C++ stack pointer, it | 929 // simulator has a separate JS stack pointer from the C++ stack pointer, it |
(...skipping 11 matching lines...) Expand all Loading... | |
938 | 941 |
939 Debug* debug = isolate->debug(); | 942 Debug* debug = isolate->debug(); |
940 // Handle stepping into a getter if step into is active. | 943 // Handle stepping into a getter if step into is active. |
941 // TODO(rossberg): should this apply to getters that are function proxies? | 944 // TODO(rossberg): should this apply to getters that are function proxies? |
942 if (debug->is_active()) debug->HandleStepIn(getter, false); | 945 if (debug->is_active()) debug->HandleStepIn(getter, false); |
943 | 946 |
944 return Execution::Call(isolate, getter, receiver, 0, NULL); | 947 return Execution::Call(isolate, getter, receiver, 0, NULL); |
945 } | 948 } |
946 | 949 |
947 | 950 |
948 MaybeHandle<Object> Object::SetPropertyWithDefinedSetter( | 951 Maybe<bool> Object::SetPropertyWithDefinedSetter(Handle<Object> receiver, |
949 Handle<Object> receiver, | 952 Handle<JSReceiver> setter, |
950 Handle<JSReceiver> setter, | 953 Handle<Object> value, |
951 Handle<Object> value) { | 954 ShouldThrow should_throw) { |
952 Isolate* isolate = setter->GetIsolate(); | 955 Isolate* isolate = setter->GetIsolate(); |
953 | 956 |
954 Debug* debug = isolate->debug(); | 957 Debug* debug = isolate->debug(); |
955 // Handle stepping into a setter if step into is active. | 958 // Handle stepping into a setter if step into is active. |
956 // TODO(rossberg): should this apply to getters that are function proxies? | 959 // TODO(rossberg): should this apply to getters that are function proxies? |
957 if (debug->is_active()) debug->HandleStepIn(setter, false); | 960 if (debug->is_active()) debug->HandleStepIn(setter, false); |
958 | 961 |
959 Handle<Object> argv[] = { value }; | 962 Handle<Object> argv[] = { value }; |
960 RETURN_ON_EXCEPTION(isolate, Execution::Call(isolate, setter, receiver, | 963 RETURN_ON_EXCEPTION_VALUE(isolate, Execution::Call(isolate, setter, receiver, |
961 arraysize(argv), argv), | 964 arraysize(argv), argv), |
962 Object); | 965 Nothing<bool>()); |
963 return value; | 966 return Just(true); |
964 } | 967 } |
965 | 968 |
966 | 969 |
967 // static | 970 // static |
968 bool JSObject::AllCanRead(LookupIterator* it) { | 971 bool JSObject::AllCanRead(LookupIterator* it) { |
969 // Skip current iteration, it's in state ACCESS_CHECK or INTERCEPTOR, both of | 972 // Skip current iteration, it's in state ACCESS_CHECK or INTERCEPTOR, both of |
970 // which have already been checked. | 973 // which have already been checked. |
971 DCHECK(it->state() == LookupIterator::ACCESS_CHECK || | 974 DCHECK(it->state() == LookupIterator::ACCESS_CHECK || |
972 it->state() == LookupIterator::INTERCEPTOR); | 975 it->state() == LookupIterator::INTERCEPTOR); |
973 for (it->Next(); it->IsFound(); it->Next()) { | 976 for (it->Next(); it->IsFound(); it->Next()) { |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1038 Handle<Object> accessors = it->GetAccessors(); | 1041 Handle<Object> accessors = it->GetAccessors(); |
1039 if (accessors->IsAccessorInfo()) { | 1042 if (accessors->IsAccessorInfo()) { |
1040 if (AccessorInfo::cast(*accessors)->all_can_write()) return true; | 1043 if (AccessorInfo::cast(*accessors)->all_can_write()) return true; |
1041 } | 1044 } |
1042 } | 1045 } |
1043 } | 1046 } |
1044 return false; | 1047 return false; |
1045 } | 1048 } |
1046 | 1049 |
1047 | 1050 |
1048 MaybeHandle<Object> JSObject::SetPropertyWithFailedAccessCheck( | 1051 Maybe<bool> JSObject::SetPropertyWithFailedAccessCheck( |
1049 LookupIterator* it, Handle<Object> value) { | 1052 LookupIterator* it, Handle<Object> value, ShouldThrow should_throw) { |
1050 Handle<JSObject> checked = it->GetHolder<JSObject>(); | 1053 Handle<JSObject> checked = it->GetHolder<JSObject>(); |
1051 if (AllCanWrite(it)) { | 1054 if (AllCanWrite(it)) { |
1052 // The supplied language-mode is ignored by SetPropertyWithAccessor. | 1055 // The supplied language-mode is ignored by SetPropertyWithAccessor. |
1053 return SetPropertyWithAccessor(it, value, SLOPPY); | 1056 return SetPropertyWithAccessor(it, value, SLOPPY, should_throw); |
1054 } | 1057 } |
1055 | 1058 |
1056 it->isolate()->ReportFailedAccessCheck(checked); | 1059 it->isolate()->ReportFailedAccessCheck(checked); |
1057 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(it->isolate(), Object); | 1060 RETURN_VALUE_IF_SCHEDULED_EXCEPTION(it->isolate(), Nothing<bool>()); |
1058 return value; | 1061 UNREACHABLE(); |
Jakob Kummerow
2015/10/27 15:51:52
We're hitting this in the wild (crbug.com/548194).
| |
1062 it->isolate()->Throw( | |
1063 *it->isolate()->factory()->NewTypeError(MessageTemplate::kNoAccess)); | |
1064 return Nothing<bool>(); | |
1059 } | 1065 } |
1060 | 1066 |
1061 | 1067 |
1062 void JSObject::SetNormalizedProperty(Handle<JSObject> object, | 1068 void JSObject::SetNormalizedProperty(Handle<JSObject> object, |
1063 Handle<Name> name, | 1069 Handle<Name> name, |
1064 Handle<Object> value, | 1070 Handle<Object> value, |
1065 PropertyDetails details) { | 1071 PropertyDetails details) { |
1066 DCHECK(!object->HasFastProperties()); | 1072 DCHECK(!object->HasFastProperties()); |
1067 if (!name->IsUniqueName()) { | 1073 if (!name->IsUniqueName()) { |
1068 name = object->GetIsolate()->factory()->InternalizeString( | 1074 name = object->GetIsolate()->factory()->InternalizeString( |
(...skipping 2438 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3507 | 3513 |
3508 // static | 3514 // static |
3509 Handle<Map> Map::Update(Handle<Map> map) { | 3515 Handle<Map> Map::Update(Handle<Map> map) { |
3510 if (!map->is_deprecated()) return map; | 3516 if (!map->is_deprecated()) return map; |
3511 return ReconfigureProperty(map, -1, kData, NONE, Representation::None(), | 3517 return ReconfigureProperty(map, -1, kData, NONE, Representation::None(), |
3512 HeapType::None(map->GetIsolate()), | 3518 HeapType::None(map->GetIsolate()), |
3513 ALLOW_IN_DESCRIPTOR); | 3519 ALLOW_IN_DESCRIPTOR); |
3514 } | 3520 } |
3515 | 3521 |
3516 | 3522 |
3517 MaybeHandle<Object> JSObject::SetPropertyWithInterceptor(LookupIterator* it, | 3523 Maybe<bool> JSObject::SetPropertyWithInterceptor(LookupIterator* it, |
3518 Handle<Object> value) { | 3524 Handle<Object> value) { |
3519 Isolate* isolate = it->isolate(); | 3525 Isolate* isolate = it->isolate(); |
3520 // Make sure that the top context does not change when doing callbacks or | 3526 // Make sure that the top context does not change when doing callbacks or |
3521 // interceptor calls. | 3527 // interceptor calls. |
3522 AssertNoContextChange ncc(isolate); | 3528 AssertNoContextChange ncc(isolate); |
3523 | 3529 |
3524 DCHECK_EQ(LookupIterator::INTERCEPTOR, it->state()); | 3530 DCHECK_EQ(LookupIterator::INTERCEPTOR, it->state()); |
3525 Handle<InterceptorInfo> interceptor(it->GetInterceptor()); | 3531 Handle<InterceptorInfo> interceptor(it->GetInterceptor()); |
3526 if (interceptor->setter()->IsUndefined()) return MaybeHandle<Object>(); | 3532 if (interceptor->setter()->IsUndefined()) return Just(false); |
3527 | 3533 |
3528 Handle<JSObject> holder = it->GetHolder<JSObject>(); | 3534 Handle<JSObject> holder = it->GetHolder<JSObject>(); |
3529 v8::Local<v8::Value> result; | 3535 v8::Local<v8::Value> result; |
3530 PropertyCallbackArguments args(isolate, interceptor->data(), | 3536 PropertyCallbackArguments args(isolate, interceptor->data(), |
3531 *it->GetReceiver(), *holder); | 3537 *it->GetReceiver(), *holder); |
3532 | 3538 |
3533 if (it->IsElement()) { | 3539 if (it->IsElement()) { |
3534 uint32_t index = it->index(); | 3540 uint32_t index = it->index(); |
3535 v8::IndexedPropertySetterCallback setter = | 3541 v8::IndexedPropertySetterCallback setter = |
3536 v8::ToCData<v8::IndexedPropertySetterCallback>(interceptor->setter()); | 3542 v8::ToCData<v8::IndexedPropertySetterCallback>(interceptor->setter()); |
3537 LOG(isolate, | 3543 LOG(isolate, |
3538 ApiIndexedPropertyAccess("interceptor-indexed-set", *holder, index)); | 3544 ApiIndexedPropertyAccess("interceptor-indexed-set", *holder, index)); |
3539 result = args.Call(setter, index, v8::Utils::ToLocal(value)); | 3545 result = args.Call(setter, index, v8::Utils::ToLocal(value)); |
3540 } else { | 3546 } else { |
3541 Handle<Name> name = it->name(); | 3547 Handle<Name> name = it->name(); |
3542 | 3548 |
3543 if (name->IsSymbol() && !interceptor->can_intercept_symbols()) { | 3549 if (name->IsSymbol() && !interceptor->can_intercept_symbols()) { |
3544 return MaybeHandle<Object>(); | 3550 return Just(false); |
3545 } | 3551 } |
3546 | 3552 |
3547 v8::GenericNamedPropertySetterCallback setter = | 3553 v8::GenericNamedPropertySetterCallback setter = |
3548 v8::ToCData<v8::GenericNamedPropertySetterCallback>( | 3554 v8::ToCData<v8::GenericNamedPropertySetterCallback>( |
3549 interceptor->setter()); | 3555 interceptor->setter()); |
3550 LOG(it->isolate(), | 3556 LOG(it->isolate(), |
3551 ApiNamedPropertyAccess("interceptor-named-set", *holder, *name)); | 3557 ApiNamedPropertyAccess("interceptor-named-set", *holder, *name)); |
3552 result = | 3558 result = |
3553 args.Call(setter, v8::Utils::ToLocal(name), v8::Utils::ToLocal(value)); | 3559 args.Call(setter, v8::Utils::ToLocal(name), v8::Utils::ToLocal(value)); |
3554 } | 3560 } |
3555 | 3561 |
3556 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(it->isolate(), Object); | 3562 RETURN_VALUE_IF_SCHEDULED_EXCEPTION(it->isolate(), Nothing<bool>()); |
3557 if (result.IsEmpty()) return MaybeHandle<Object>(); | 3563 if (result.IsEmpty()) return Just(false); |
3558 #ifdef DEBUG | 3564 #ifdef DEBUG |
3559 Handle<Object> result_internal = v8::Utils::OpenHandle(*result); | 3565 Handle<Object> result_internal = v8::Utils::OpenHandle(*result); |
3560 result_internal->VerifyApiCallResultType(); | 3566 result_internal->VerifyApiCallResultType(); |
3561 #endif | 3567 #endif |
3562 return value; | 3568 return Just(true); |
3563 } | 3569 } |
3564 | 3570 |
3565 | 3571 |
3566 MaybeHandle<Object> Object::SetProperty(Handle<Object> object, | 3572 MaybeHandle<Object> Object::SetProperty(Handle<Object> object, |
3567 Handle<Name> name, Handle<Object> value, | 3573 Handle<Name> name, Handle<Object> value, |
3568 LanguageMode language_mode, | 3574 LanguageMode language_mode, |
3569 StoreFromKeyed store_mode) { | 3575 StoreFromKeyed store_mode) { |
3570 LookupIterator it(object, name); | 3576 LookupIterator it(object, name); |
3571 return SetProperty(&it, value, language_mode, store_mode); | 3577 return SetProperty(&it, value, language_mode, store_mode); |
3572 } | 3578 } |
3573 | 3579 |
3574 | 3580 |
3575 MaybeHandle<Object> Object::SetPropertyInternal(LookupIterator* it, | 3581 Maybe<bool> Object::SetPropertyInternal( |
3576 Handle<Object> value, | 3582 LookupIterator* it, Handle<Object> value, LanguageMode language_mode, |
3577 LanguageMode language_mode, | 3583 ShouldThrow should_throw, StoreFromKeyed store_mode, bool* found) { |
3578 StoreFromKeyed store_mode, | |
3579 bool* found) { | |
3580 // Make sure that the top context does not change when doing callbacks or | 3584 // Make sure that the top context does not change when doing callbacks or |
3581 // interceptor calls. | 3585 // interceptor calls. |
3582 AssertNoContextChange ncc(it->isolate()); | 3586 AssertNoContextChange ncc(it->isolate()); |
3583 | 3587 |
3584 *found = true; | 3588 *found = true; |
3585 | 3589 |
3586 bool done = false; | 3590 bool done = false; |
3587 for (; it->IsFound(); it->Next()) { | 3591 for (; it->IsFound(); it->Next()) { |
3588 switch (it->state()) { | 3592 switch (it->state()) { |
3589 case LookupIterator::NOT_FOUND: | 3593 case LookupIterator::NOT_FOUND: |
3590 UNREACHABLE(); | 3594 UNREACHABLE(); |
3591 | 3595 |
3592 case LookupIterator::ACCESS_CHECK: | 3596 case LookupIterator::ACCESS_CHECK: |
3593 if (it->HasAccess()) break; | 3597 if (it->HasAccess()) break; |
3594 // Check whether it makes sense to reuse the lookup iterator. Here it | 3598 // Check whether it makes sense to reuse the lookup iterator. Here it |
3595 // might still call into setters up the prototype chain. | 3599 // might still call into setters up the prototype chain. |
3596 return JSObject::SetPropertyWithFailedAccessCheck(it, value); | 3600 return JSObject::SetPropertyWithFailedAccessCheck(it, value, |
3601 should_throw); | |
3597 | 3602 |
3598 case LookupIterator::JSPROXY: | 3603 case LookupIterator::JSPROXY: |
3599 if (it->HolderIsReceiverOrHiddenPrototype()) { | 3604 if (it->HolderIsReceiverOrHiddenPrototype()) { |
3600 return JSProxy::SetPropertyWithHandler( | 3605 return JSProxy::SetPropertyWithHandler( |
3601 it->GetHolder<JSProxy>(), it->GetReceiver(), it->GetName(), value, | 3606 it->GetHolder<JSProxy>(), it->GetReceiver(), it->GetName(), value, |
3602 language_mode); | 3607 language_mode, should_throw); |
3603 } else { | 3608 } else { |
3604 // TODO(verwaest): Use the MaybeHandle to indicate result. | 3609 // TODO(verwaest): Use the MaybeHandle to indicate result. |
3605 bool has_result = false; | 3610 bool has_result = false; |
3606 MaybeHandle<Object> maybe_result = | 3611 Maybe<bool> maybe_result = |
3607 JSProxy::SetPropertyViaPrototypesWithHandler( | 3612 JSProxy::SetPropertyViaPrototypesWithHandler( |
3608 it->GetHolder<JSProxy>(), it->GetReceiver(), it->GetName(), | 3613 it->GetHolder<JSProxy>(), it->GetReceiver(), it->GetName(), |
3609 value, language_mode, &has_result); | 3614 value, language_mode, should_throw, &has_result); |
3610 if (has_result) return maybe_result; | 3615 if (has_result) return maybe_result; |
3611 done = true; | 3616 done = true; |
3612 } | 3617 } |
3613 break; | 3618 break; |
3614 | 3619 |
3615 case LookupIterator::INTERCEPTOR: | 3620 case LookupIterator::INTERCEPTOR: |
3616 if (it->HolderIsReceiverOrHiddenPrototype()) { | 3621 if (it->HolderIsReceiverOrHiddenPrototype()) { |
3617 MaybeHandle<Object> maybe_result = | 3622 Maybe<bool> maybe_result = |
3618 JSObject::SetPropertyWithInterceptor(it, value); | 3623 JSObject::SetPropertyWithInterceptor(it, value); |
3619 if (!maybe_result.is_null()) return maybe_result; | 3624 if (maybe_result.IsNothing()) return Nothing<bool>(); |
3620 if (it->isolate()->has_pending_exception()) return maybe_result; | 3625 if (maybe_result.FromJust()) return Just(true); |
3621 } else { | 3626 } else { |
3622 Maybe<PropertyAttributes> maybe_attributes = | 3627 Maybe<PropertyAttributes> maybe_attributes = |
3623 JSObject::GetPropertyAttributesWithInterceptor(it); | 3628 JSObject::GetPropertyAttributesWithInterceptor(it); |
3624 if (!maybe_attributes.IsJust()) return MaybeHandle<Object>(); | 3629 if (!maybe_attributes.IsJust()) return Nothing<bool>(); |
3625 done = maybe_attributes.FromJust() != ABSENT; | 3630 done = maybe_attributes.FromJust() != ABSENT; |
3626 if (done && (maybe_attributes.FromJust() & READ_ONLY) != 0) { | 3631 if (done && (maybe_attributes.FromJust() & READ_ONLY) != 0) { |
3627 return WriteToReadOnlyProperty(it, value, language_mode); | 3632 return WriteToReadOnlyProperty(it, value, language_mode, |
3633 should_throw); | |
3628 } | 3634 } |
3629 } | 3635 } |
3630 break; | 3636 break; |
3631 | 3637 |
3632 case LookupIterator::ACCESSOR: { | 3638 case LookupIterator::ACCESSOR: { |
3633 if (it->IsReadOnly()) { | 3639 if (it->IsReadOnly()) { |
3634 return WriteToReadOnlyProperty(it, value, language_mode); | 3640 return WriteToReadOnlyProperty(it, value, language_mode, |
3641 should_throw); | |
3635 } | 3642 } |
3636 Handle<Object> accessors = it->GetAccessors(); | 3643 Handle<Object> accessors = it->GetAccessors(); |
3637 if (accessors->IsAccessorInfo() && | 3644 if (accessors->IsAccessorInfo() && |
3638 !it->HolderIsReceiverOrHiddenPrototype() && | 3645 !it->HolderIsReceiverOrHiddenPrototype() && |
3639 AccessorInfo::cast(*accessors)->is_special_data_property()) { | 3646 AccessorInfo::cast(*accessors)->is_special_data_property()) { |
3640 done = true; | 3647 done = true; |
3641 break; | 3648 break; |
3642 } | 3649 } |
3643 return SetPropertyWithAccessor(it, value, language_mode); | 3650 return SetPropertyWithAccessor(it, value, language_mode, should_throw); |
3644 } | 3651 } |
3645 case LookupIterator::INTEGER_INDEXED_EXOTIC: | 3652 case LookupIterator::INTEGER_INDEXED_EXOTIC: |
3646 // TODO(verwaest): We should throw an exception. | 3653 // TODO(verwaest): We should throw an exception. |
3647 return value; | 3654 return Just(true); |
3648 | 3655 |
3649 case LookupIterator::DATA: | 3656 case LookupIterator::DATA: |
3650 if (it->IsReadOnly()) { | 3657 if (it->IsReadOnly()) { |
3651 return WriteToReadOnlyProperty(it, value, language_mode); | 3658 return WriteToReadOnlyProperty(it, value, language_mode, |
3659 should_throw); | |
3652 } | 3660 } |
3653 if (it->HolderIsReceiverOrHiddenPrototype()) { | 3661 if (it->HolderIsReceiverOrHiddenPrototype()) { |
3654 return SetDataProperty(it, value); | 3662 return SetDataProperty(it, value, should_throw); |
3655 } | 3663 } |
3656 done = true; | 3664 done = true; |
3657 break; | 3665 break; |
3658 | 3666 |
3659 case LookupIterator::TRANSITION: | 3667 case LookupIterator::TRANSITION: |
3660 done = true; | 3668 done = true; |
3661 break; | 3669 break; |
3662 } | 3670 } |
3663 | 3671 |
3664 if (done) break; | 3672 if (done) break; |
3665 } | 3673 } |
3666 | 3674 |
3667 // If the receiver is the JSGlobalObject, the store was contextual. In case | 3675 // If the receiver is the JSGlobalObject, the store was contextual. In case |
3668 // the property did not exist yet on the global object itself, we have to | 3676 // the property did not exist yet on the global object itself, we have to |
3669 // throw a reference error in strict mode. | 3677 // throw a reference error in strict mode. |
3670 if (it->GetReceiver()->IsJSGlobalObject() && is_strict(language_mode)) { | 3678 if (it->GetReceiver()->IsJSGlobalObject() && is_strict(language_mode)) { |
3671 THROW_NEW_ERROR(it->isolate(), | 3679 RETURN_FAILURE(it->isolate(), should_throw, |
3672 NewReferenceError(MessageTemplate::kNotDefined, it->name()), | 3680 NewReferenceError(MessageTemplate::kNotDefined, it->name())); |
3673 Object); | |
3674 } | 3681 } |
3675 | 3682 |
3676 *found = false; | 3683 *found = false; |
3677 return MaybeHandle<Object>(); | 3684 return Nothing<bool>(); |
3678 } | 3685 } |
3679 | 3686 |
3680 | 3687 |
3681 MaybeHandle<Object> Object::SetProperty(LookupIterator* it, | 3688 MaybeHandle<Object> Object::SetProperty(LookupIterator* it, |
3682 Handle<Object> value, | 3689 Handle<Object> value, |
3683 LanguageMode language_mode, | 3690 LanguageMode language_mode, |
3684 StoreFromKeyed store_mode) { | 3691 StoreFromKeyed store_mode) { |
3685 bool found = false; | 3692 MAYBE_RETURN_NULL( |
3686 MaybeHandle<Object> result = | 3693 SetProperty(it, value, language_mode, THROW_ON_ERROR, store_mode)); |
3687 SetPropertyInternal(it, value, language_mode, store_mode, &found); | 3694 return value; |
3688 if (found) return result; | |
3689 return AddDataProperty(it, value, NONE, language_mode, store_mode); | |
3690 } | 3695 } |
3691 | 3696 |
3692 | 3697 |
3698 Maybe<bool> Object::SetProperty(LookupIterator* it, Handle<Object> value, | |
3699 LanguageMode language_mode, | |
3700 ShouldThrow should_throw, | |
3701 StoreFromKeyed store_mode) { | |
3702 bool found = false; | |
3703 Maybe<bool> result = SetPropertyInternal(it, value, language_mode, | |
3704 should_throw, store_mode, &found); | |
3705 if (found) return result; | |
3706 return AddDataProperty(it, value, NONE, language_mode, should_throw, | |
3707 store_mode); | |
3708 } | |
3709 | |
3710 | |
3693 MaybeHandle<Object> Object::SetSuperProperty(LookupIterator* it, | 3711 MaybeHandle<Object> Object::SetSuperProperty(LookupIterator* it, |
3694 Handle<Object> value, | 3712 Handle<Object> value, |
3695 LanguageMode language_mode, | 3713 LanguageMode language_mode, |
3696 StoreFromKeyed store_mode) { | 3714 StoreFromKeyed store_mode) { |
3697 bool found = false; | 3715 bool found = false; |
3698 MaybeHandle<Object> result = | 3716 Maybe<bool> result = SetPropertyInternal(it, value, language_mode, |
3699 SetPropertyInternal(it, value, language_mode, store_mode, &found); | 3717 THROW_ON_ERROR, store_mode, &found); |
3700 if (found) return result; | 3718 if (found) { |
3719 MAYBE_RETURN_NULL(result); | |
3720 return value; | |
3721 } | |
3701 | 3722 |
3702 if (!it->GetReceiver()->IsJSReceiver()) { | 3723 if (!it->GetReceiver()->IsJSReceiver()) { |
3703 return WriteToReadOnlyProperty(it, value, language_mode); | 3724 MAYBE_RETURN_NULL( |
3725 WriteToReadOnlyProperty(it, value, language_mode, THROW_ON_ERROR)); | |
3726 return value; | |
3704 } | 3727 } |
3705 | 3728 |
3706 LookupIterator::Configuration c = LookupIterator::OWN; | 3729 LookupIterator::Configuration c = LookupIterator::OWN; |
3707 LookupIterator own_lookup = | 3730 LookupIterator own_lookup = |
3708 it->IsElement() | 3731 it->IsElement() |
3709 ? LookupIterator(it->isolate(), it->GetReceiver(), it->index(), c) | 3732 ? LookupIterator(it->isolate(), it->GetReceiver(), it->index(), c) |
3710 : LookupIterator(it->GetReceiver(), it->name(), c); | 3733 : LookupIterator(it->GetReceiver(), it->name(), c); |
3711 | 3734 |
3712 for (; own_lookup.IsFound(); own_lookup.Next()) { | 3735 for (; own_lookup.IsFound(); own_lookup.Next()) { |
3713 switch (own_lookup.state()) { | 3736 switch (own_lookup.state()) { |
3714 case LookupIterator::ACCESS_CHECK: | 3737 case LookupIterator::ACCESS_CHECK: |
3715 if (!own_lookup.HasAccess()) { | 3738 if (!own_lookup.HasAccess()) { |
3716 return JSObject::SetPropertyWithFailedAccessCheck(&own_lookup, value); | 3739 MAYBE_RETURN_NULL(JSObject::SetPropertyWithFailedAccessCheck( |
3740 &own_lookup, value, THROW_ON_ERROR)); | |
3741 return value; | |
3717 } | 3742 } |
3718 break; | 3743 break; |
3719 | 3744 |
3720 case LookupIterator::INTEGER_INDEXED_EXOTIC: | 3745 case LookupIterator::INTEGER_INDEXED_EXOTIC: |
3721 return RedefineNonconfigurableProperty(it->isolate(), it->GetName(), | 3746 return RedefineNonconfigurableProperty(it->isolate(), it->GetName(), |
3722 value, language_mode); | 3747 value, language_mode); |
3723 | 3748 |
3724 case LookupIterator::DATA: { | 3749 case LookupIterator::DATA: { |
3725 PropertyDetails details = own_lookup.property_details(); | 3750 PropertyDetails details = own_lookup.property_details(); |
3726 if (details.IsConfigurable() || !details.IsReadOnly()) { | 3751 if (details.IsConfigurable() || !details.IsReadOnly()) { |
3727 return JSObject::DefineOwnPropertyIgnoreAttributes( | 3752 return JSObject::DefineOwnPropertyIgnoreAttributes( |
3728 &own_lookup, value, details.attributes()); | 3753 &own_lookup, value, details.attributes()); |
3729 } | 3754 } |
3730 return WriteToReadOnlyProperty(&own_lookup, value, language_mode); | 3755 MAYBE_RETURN_NULL(WriteToReadOnlyProperty( |
3756 &own_lookup, value, language_mode, THROW_ON_ERROR)); | |
3757 return value; | |
3731 } | 3758 } |
3732 | 3759 |
3733 case LookupIterator::ACCESSOR: { | 3760 case LookupIterator::ACCESSOR: { |
3734 PropertyDetails details = own_lookup.property_details(); | 3761 PropertyDetails details = own_lookup.property_details(); |
3735 if (details.IsConfigurable()) { | 3762 if (details.IsConfigurable()) { |
3736 return JSObject::DefineOwnPropertyIgnoreAttributes( | 3763 return JSObject::DefineOwnPropertyIgnoreAttributes( |
3737 &own_lookup, value, details.attributes()); | 3764 &own_lookup, value, details.attributes()); |
3738 } | 3765 } |
3739 | 3766 |
3740 return RedefineNonconfigurableProperty(it->isolate(), it->GetName(), | 3767 return RedefineNonconfigurableProperty(it->isolate(), it->GetName(), |
3741 value, language_mode); | 3768 value, language_mode); |
3742 } | 3769 } |
3743 | 3770 |
3744 case LookupIterator::INTERCEPTOR: | 3771 case LookupIterator::INTERCEPTOR: |
3745 case LookupIterator::JSPROXY: { | 3772 case LookupIterator::JSPROXY: { |
3746 bool found = false; | 3773 bool found = false; |
3747 MaybeHandle<Object> result = SetPropertyInternal( | 3774 Maybe<bool> result = |
3748 &own_lookup, value, language_mode, store_mode, &found); | 3775 SetPropertyInternal(&own_lookup, value, language_mode, |
3749 if (found) return result; | 3776 THROW_ON_ERROR, store_mode, &found); |
3777 if (found) { | |
3778 MAYBE_RETURN_NULL(result); | |
3779 return value; | |
3780 } | |
3750 break; | 3781 break; |
3751 } | 3782 } |
3752 | 3783 |
3753 case LookupIterator::NOT_FOUND: | 3784 case LookupIterator::NOT_FOUND: |
3754 case LookupIterator::TRANSITION: | 3785 case LookupIterator::TRANSITION: |
3755 UNREACHABLE(); | 3786 UNREACHABLE(); |
3756 } | 3787 } |
3757 } | 3788 } |
3758 | 3789 |
3759 return JSObject::AddDataProperty(&own_lookup, value, NONE, language_mode, | 3790 return JSObject::AddDataProperty(&own_lookup, value, NONE, language_mode, |
(...skipping 19 matching lines...) Expand all Loading... | |
3779 if (is_strong(language_mode)) { | 3810 if (is_strong(language_mode)) { |
3780 THROW_NEW_ERROR( | 3811 THROW_NEW_ERROR( |
3781 isolate, | 3812 isolate, |
3782 NewTypeError(MessageTemplate::kStrongPropertyAccess, name, receiver), | 3813 NewTypeError(MessageTemplate::kStrongPropertyAccess, name, receiver), |
3783 Object); | 3814 Object); |
3784 } | 3815 } |
3785 return isolate->factory()->undefined_value(); | 3816 return isolate->factory()->undefined_value(); |
3786 } | 3817 } |
3787 | 3818 |
3788 | 3819 |
3789 MaybeHandle<Object> Object::CannotCreateProperty(LookupIterator* it, | 3820 Maybe<bool> Object::CannotCreateProperty(Isolate* isolate, |
3790 Handle<Object> value, | 3821 Handle<Object> receiver, |
3791 LanguageMode language_mode) { | 3822 Handle<Object> name, |
3792 return CannotCreateProperty(it->isolate(), it->GetReceiver(), it->GetName(), | 3823 Handle<Object> value, |
3793 value, language_mode); | 3824 LanguageMode language_mode, |
3825 ShouldThrow should_throw) { | |
3826 if (is_sloppy(language_mode)) return Just(true); | |
3827 RETURN_FAILURE( | |
3828 isolate, should_throw, | |
3829 NewTypeError(MessageTemplate::kStrictCannotCreateProperty, name, | |
3830 Object::TypeOf(isolate, receiver), receiver)); | |
3794 } | 3831 } |
3795 | 3832 |
3796 | 3833 |
3797 MaybeHandle<Object> Object::CannotCreateProperty(Isolate* isolate, | 3834 Maybe<bool> Object::WriteToReadOnlyProperty(LookupIterator* it, |
3798 Handle<Object> receiver, | 3835 Handle<Object> value, |
3799 Handle<Object> name, | 3836 LanguageMode language_mode, |
3800 Handle<Object> value, | 3837 ShouldThrow should_throw) { |
3801 LanguageMode language_mode) { | 3838 return WriteToReadOnlyProperty(it->isolate(), it->GetReceiver(), |
3802 if (is_sloppy(language_mode)) return value; | 3839 it->GetName(), value, language_mode, |
3803 Handle<String> typeof_string = Object::TypeOf(isolate, receiver); | 3840 should_throw); |
3804 THROW_NEW_ERROR(isolate, | |
3805 NewTypeError(MessageTemplate::kStrictCannotCreateProperty, | |
3806 name, typeof_string, receiver), | |
3807 Object); | |
3808 } | 3841 } |
3809 | 3842 |
3810 | 3843 |
3811 MaybeHandle<Object> Object::WriteToReadOnlyProperty( | 3844 Maybe<bool> Object::WriteToReadOnlyProperty(Isolate* isolate, |
3812 LookupIterator* it, Handle<Object> value, LanguageMode language_mode) { | 3845 Handle<Object> receiver, |
3813 return WriteToReadOnlyProperty(it->isolate(), it->GetReceiver(), | 3846 Handle<Object> name, |
3814 it->GetName(), value, language_mode); | 3847 Handle<Object> value, |
3848 LanguageMode language_mode, | |
3849 ShouldThrow should_throw) { | |
3850 if (is_sloppy(language_mode)) return Just(true); | |
3851 RETURN_FAILURE(isolate, should_throw, | |
3852 NewTypeError(MessageTemplate::kStrictReadOnlyProperty, name, | |
3853 Object::TypeOf(isolate, receiver), receiver)); | |
3815 } | 3854 } |
3816 | 3855 |
3817 | 3856 |
3818 MaybeHandle<Object> Object::WriteToReadOnlyProperty( | |
3819 Isolate* isolate, Handle<Object> receiver, Handle<Object> name, | |
3820 Handle<Object> value, LanguageMode language_mode) { | |
3821 if (is_sloppy(language_mode)) return value; | |
3822 Handle<String> typeof_string = Object::TypeOf(isolate, receiver); | |
3823 THROW_NEW_ERROR(isolate, | |
3824 NewTypeError(MessageTemplate::kStrictReadOnlyProperty, name, | |
3825 typeof_string, receiver), | |
3826 Object); | |
3827 } | |
3828 | |
3829 | |
3830 MaybeHandle<Object> Object::RedefineNonconfigurableProperty( | 3857 MaybeHandle<Object> Object::RedefineNonconfigurableProperty( |
3831 Isolate* isolate, Handle<Object> name, Handle<Object> value, | 3858 Isolate* isolate, Handle<Object> name, Handle<Object> value, |
3832 LanguageMode language_mode) { | 3859 LanguageMode language_mode) { |
3833 if (is_sloppy(language_mode)) return value; | 3860 if (is_sloppy(language_mode)) return value; |
3834 THROW_NEW_ERROR(isolate, | 3861 THROW_NEW_ERROR(isolate, |
3835 NewTypeError(MessageTemplate::kRedefineDisallowed, name), | 3862 NewTypeError(MessageTemplate::kRedefineDisallowed, name), |
3836 Object); | 3863 Object); |
3837 } | 3864 } |
3838 | 3865 |
3839 | 3866 |
3840 MaybeHandle<Object> Object::SetDataProperty(LookupIterator* it, | 3867 Maybe<bool> Object::SetDataProperty(LookupIterator* it, Handle<Object> value, |
3841 Handle<Object> value) { | 3868 ShouldThrow should_throw) { |
3842 // Proxies are handled on the WithHandler path. Other non-JSObjects cannot | 3869 // Proxies are handled on the WithHandler path. Other non-JSObjects cannot |
3843 // have own properties. | 3870 // have own properties. |
3844 Handle<JSObject> receiver = Handle<JSObject>::cast(it->GetReceiver()); | 3871 Handle<JSObject> receiver = Handle<JSObject>::cast(it->GetReceiver()); |
3845 | 3872 |
3846 // Store on the holder which may be hidden behind the receiver. | 3873 // Store on the holder which may be hidden behind the receiver. |
3847 DCHECK(it->HolderIsReceiverOrHiddenPrototype()); | 3874 DCHECK(it->HolderIsReceiverOrHiddenPrototype()); |
3848 | 3875 |
3849 // Old value for the observation change record. | 3876 // Old value for the observation change record. |
3850 // Fetch before transforming the object since the encoding may become | 3877 // Fetch before transforming the object since the encoding may become |
3851 // incompatible with what's cached in |it|. | 3878 // incompatible with what's cached in |it|. |
3852 bool is_observed = receiver->map()->is_observed() && | 3879 bool is_observed = receiver->map()->is_observed() && |
3853 (it->IsElement() || | 3880 (it->IsElement() || |
3854 !it->isolate()->IsInternallyUsedPropertyName(it->name())); | 3881 !it->isolate()->IsInternallyUsedPropertyName(it->name())); |
3855 MaybeHandle<Object> maybe_old; | 3882 MaybeHandle<Object> maybe_old; |
3856 if (is_observed) maybe_old = it->GetDataValue(); | 3883 if (is_observed) maybe_old = it->GetDataValue(); |
3857 | 3884 |
3858 Handle<Object> to_assign = value; | 3885 Handle<Object> to_assign = value; |
3859 // Convert the incoming value to a number for storing into typed arrays. | 3886 // Convert the incoming value to a number for storing into typed arrays. |
3860 if (it->IsElement() && receiver->HasFixedTypedArrayElements()) { | 3887 if (it->IsElement() && receiver->HasFixedTypedArrayElements()) { |
3861 if (!value->IsNumber() && !value->IsUndefined()) { | 3888 if (!value->IsNumber() && !value->IsUndefined()) { |
3862 ASSIGN_RETURN_ON_EXCEPTION(it->isolate(), to_assign, | 3889 ASSIGN_RETURN_ON_EXCEPTION_VALUE( |
3863 Object::ToNumber(value), Object); | 3890 it->isolate(), to_assign, Object::ToNumber(value), Nothing<bool>()); |
3864 // ToNumber above might modify the receiver, causing the cached | 3891 // ToNumber above might modify the receiver, causing the cached |
3865 // holder_map to mismatch the actual holder->map() after this point. | 3892 // holder_map to mismatch the actual holder->map() after this point. |
3866 // Reload the map to be in consistent state. Other cached state cannot | 3893 // Reload the map to be in consistent state. Other cached state cannot |
3867 // have been invalidated since typed array elements cannot be reconfigured | 3894 // have been invalidated since typed array elements cannot be reconfigured |
3868 // in any way. | 3895 // in any way. |
3869 it->ReloadHolderMap(); | 3896 it->ReloadHolderMap(); |
3870 | 3897 |
3871 // We have to recheck the length. However, it can only change if the | 3898 // We have to recheck the length. However, it can only change if the |
3872 // underlying buffer was neutered, so just check that. | 3899 // underlying buffer was neutered, so just check that. |
3873 if (Handle<JSArrayBufferView>::cast(receiver)->WasNeutered()) { | 3900 if (Handle<JSArrayBufferView>::cast(receiver)->WasNeutered()) { |
3874 return value; | 3901 return Just(true); |
3902 // TODO(neis): According to the spec, this should throw a TypeError. | |
3875 } | 3903 } |
3876 } | 3904 } |
3877 } | 3905 } |
3878 | 3906 |
3879 // Possibly migrate to the most up-to-date map that will be able to store | 3907 // Possibly migrate to the most up-to-date map that will be able to store |
3880 // |value| under it->name(). | 3908 // |value| under it->name(). |
3881 it->PrepareForDataProperty(to_assign); | 3909 it->PrepareForDataProperty(to_assign); |
3882 | 3910 |
3883 // Write the property value. | 3911 // Write the property value. |
3884 it->WriteDataValue(to_assign); | 3912 it->WriteDataValue(to_assign); |
3885 | 3913 |
3886 // Send the change record if there are observers. | 3914 // Send the change record if there are observers. |
3887 if (is_observed && !value->SameValue(*maybe_old.ToHandleChecked())) { | 3915 if (is_observed && !value->SameValue(*maybe_old.ToHandleChecked())) { |
3888 RETURN_ON_EXCEPTION(it->isolate(), JSObject::EnqueueChangeRecord( | 3916 RETURN_ON_EXCEPTION_VALUE( |
3889 receiver, "update", it->GetName(), | 3917 it->isolate(), |
3890 maybe_old.ToHandleChecked()), | 3918 JSObject::EnqueueChangeRecord(receiver, "update", it->GetName(), |
3891 Object); | 3919 maybe_old.ToHandleChecked()), |
3920 Nothing<bool>()); | |
3892 } | 3921 } |
3893 | 3922 |
3894 #if VERIFY_HEAP | 3923 #if VERIFY_HEAP |
3895 if (FLAG_verify_heap) { | 3924 if (FLAG_verify_heap) { |
3896 receiver->JSObjectVerify(); | 3925 receiver->JSObjectVerify(); |
3897 } | 3926 } |
3898 #endif | 3927 #endif |
3899 return value; | 3928 return Just(true); |
3900 } | 3929 } |
3901 | 3930 |
3902 | 3931 |
3903 MUST_USE_RESULT static MaybeHandle<Object> BeginPerformSplice( | 3932 MUST_USE_RESULT static MaybeHandle<Object> BeginPerformSplice( |
3904 Handle<JSArray> object) { | 3933 Handle<JSArray> object) { |
3905 Isolate* isolate = object->GetIsolate(); | 3934 Isolate* isolate = object->GetIsolate(); |
3906 HandleScope scope(isolate); | 3935 HandleScope scope(isolate); |
3907 Handle<Object> args[] = {object}; | 3936 Handle<Object> args[] = {object}; |
3908 | 3937 |
3909 return Execution::Call( | 3938 return Execution::Call( |
(...skipping 29 matching lines...) Expand all Loading... | |
3939 isolate, Handle<JSFunction>(isolate->observers_enqueue_splice()), | 3968 isolate, Handle<JSFunction>(isolate->observers_enqueue_splice()), |
3940 isolate->factory()->undefined_value(), arraysize(args), args); | 3969 isolate->factory()->undefined_value(), arraysize(args), args); |
3941 } | 3970 } |
3942 | 3971 |
3943 | 3972 |
3944 MaybeHandle<Object> Object::AddDataProperty(LookupIterator* it, | 3973 MaybeHandle<Object> Object::AddDataProperty(LookupIterator* it, |
3945 Handle<Object> value, | 3974 Handle<Object> value, |
3946 PropertyAttributes attributes, | 3975 PropertyAttributes attributes, |
3947 LanguageMode language_mode, | 3976 LanguageMode language_mode, |
3948 StoreFromKeyed store_mode) { | 3977 StoreFromKeyed store_mode) { |
3978 MAYBE_RETURN_NULL(AddDataProperty(it, value, attributes, language_mode, | |
3979 THROW_ON_ERROR, store_mode)); | |
3980 return value; | |
3981 } | |
3982 | |
3983 | |
3984 Maybe<bool> Object::AddDataProperty(LookupIterator* it, Handle<Object> value, | |
3985 PropertyAttributes attributes, | |
3986 LanguageMode language_mode, | |
3987 ShouldThrow should_throw, | |
3988 StoreFromKeyed store_mode) { | |
3949 DCHECK(!it->GetReceiver()->IsJSProxy()); | 3989 DCHECK(!it->GetReceiver()->IsJSProxy()); |
3950 if (!it->GetReceiver()->IsJSObject()) { | 3990 if (!it->GetReceiver()->IsJSObject()) { |
3951 return CannotCreateProperty(it, value, language_mode); | 3991 return CannotCreateProperty(it->isolate(), it->GetReceiver(), it->GetName(), |
3992 value, language_mode, should_throw); | |
3952 } | 3993 } |
3953 | 3994 |
3954 DCHECK_NE(LookupIterator::INTEGER_INDEXED_EXOTIC, it->state()); | 3995 DCHECK_NE(LookupIterator::INTEGER_INDEXED_EXOTIC, it->state()); |
3955 | 3996 |
3956 Handle<JSObject> receiver = it->GetStoreTarget(); | 3997 Handle<JSObject> receiver = it->GetStoreTarget(); |
3957 | 3998 |
3958 // If the receiver is a JSGlobalProxy, store on the prototype (JSGlobalObject) | 3999 // If the receiver is a JSGlobalProxy, store on the prototype (JSGlobalObject) |
3959 // instead. If the prototype is Null, the proxy is detached. | 4000 // instead. If the prototype is Null, the proxy is detached. |
3960 if (receiver->IsJSGlobalProxy()) return value; | 4001 if (receiver->IsJSGlobalProxy()) return Just(true); |
3961 | 4002 |
3962 Isolate* isolate = it->isolate(); | 4003 Isolate* isolate = it->isolate(); |
3963 | 4004 |
3964 if (!receiver->map()->is_extensible() && | 4005 if (!receiver->map()->is_extensible() && |
3965 (it->IsElement() || !isolate->IsInternallyUsedPropertyName(it->name()))) { | 4006 (it->IsElement() || !isolate->IsInternallyUsedPropertyName(it->name()))) { |
3966 if (is_sloppy(language_mode)) return value; | 4007 if (is_sloppy(language_mode)) return Just(true); |
3967 THROW_NEW_ERROR(isolate, NewTypeError(MessageTemplate::kObjectNotExtensible, | 4008 RETURN_FAILURE( |
3968 it->GetName()), | 4009 isolate, should_throw, |
3969 Object); | 4010 NewTypeError(MessageTemplate::kObjectNotExtensible, it->GetName())); |
3970 } | 4011 } |
3971 | 4012 |
3972 if (it->IsElement()) { | 4013 if (it->IsElement()) { |
3973 if (receiver->IsJSArray()) { | 4014 if (receiver->IsJSArray()) { |
3974 Handle<JSArray> array = Handle<JSArray>::cast(receiver); | 4015 Handle<JSArray> array = Handle<JSArray>::cast(receiver); |
3975 if (JSArray::WouldChangeReadOnlyLength(array, it->index())) { | 4016 if (JSArray::WouldChangeReadOnlyLength(array, it->index())) { |
3976 if (is_sloppy(language_mode)) return value; | 4017 if (is_sloppy(language_mode)) return Just(true); |
3977 return JSArray::ReadOnlyLengthError(array); | 4018 RETURN_FAILURE(array->GetIsolate(), should_throw, |
4019 NewTypeError(MessageTemplate::kStrictReadOnlyProperty, | |
4020 isolate->factory()->length_string(), | |
4021 Object::TypeOf(isolate, array), array)); | |
3978 } | 4022 } |
3979 | 4023 |
3980 if (FLAG_trace_external_array_abuse && | 4024 if (FLAG_trace_external_array_abuse && |
3981 array->HasFixedTypedArrayElements()) { | 4025 array->HasFixedTypedArrayElements()) { |
3982 CheckArrayAbuse(array, "typed elements write", it->index(), true); | 4026 CheckArrayAbuse(array, "typed elements write", it->index(), true); |
3983 } | 4027 } |
3984 | 4028 |
3985 if (FLAG_trace_js_array_abuse && !array->HasFixedTypedArrayElements()) { | 4029 if (FLAG_trace_js_array_abuse && !array->HasFixedTypedArrayElements()) { |
3986 CheckArrayAbuse(array, "elements write", it->index(), false); | 4030 CheckArrayAbuse(array, "elements write", it->index(), false); |
3987 } | 4031 } |
3988 } | 4032 } |
3989 | 4033 |
3990 MaybeHandle<Object> result = | 4034 Maybe<bool> result = JSObject::AddDataElement(receiver, it->index(), value, |
3991 JSObject::AddDataElement(receiver, it->index(), value, attributes); | 4035 attributes, should_throw); |
3992 JSObject::ValidateElements(receiver); | 4036 JSObject::ValidateElements(receiver); |
3993 return result; | 4037 return result; |
3994 } else { | 4038 } else { |
3995 // Migrate to the most up-to-date map that will be able to store |value| | 4039 // Migrate to the most up-to-date map that will be able to store |value| |
3996 // under it->name() with |attributes|. | 4040 // under it->name() with |attributes|. |
3997 it->PrepareTransitionToDataProperty(value, attributes, store_mode); | 4041 it->PrepareTransitionToDataProperty(value, attributes, store_mode); |
3998 DCHECK_EQ(LookupIterator::TRANSITION, it->state()); | 4042 DCHECK_EQ(LookupIterator::TRANSITION, it->state()); |
3999 it->ApplyTransitionToDataProperty(); | 4043 it->ApplyTransitionToDataProperty(); |
4000 | 4044 |
4001 // TODO(verwaest): Encapsulate dictionary handling better. | 4045 // TODO(verwaest): Encapsulate dictionary handling better. |
4002 if (receiver->map()->is_dictionary_map()) { | 4046 if (receiver->map()->is_dictionary_map()) { |
4003 // TODO(verwaest): Probably should ensure this is done beforehand. | 4047 // TODO(verwaest): Probably should ensure this is done beforehand. |
4004 it->InternalizeName(); | 4048 it->InternalizeName(); |
4005 // TODO(dcarney): just populate TransitionPropertyCell here? | 4049 // TODO(dcarney): just populate TransitionPropertyCell here? |
4006 JSObject::AddSlowProperty(receiver, it->name(), value, attributes); | 4050 JSObject::AddSlowProperty(receiver, it->name(), value, attributes); |
4007 } else { | 4051 } else { |
4008 // Write the property value. | 4052 // Write the property value. |
4009 it->WriteDataValue(value); | 4053 it->WriteDataValue(value); |
4010 } | 4054 } |
4011 | 4055 |
4012 // Send the change record if there are observers. | 4056 // Send the change record if there are observers. |
4013 if (receiver->map()->is_observed() && | 4057 if (receiver->map()->is_observed() && |
4014 !isolate->IsInternallyUsedPropertyName(it->name())) { | 4058 !isolate->IsInternallyUsedPropertyName(it->name())) { |
4015 RETURN_ON_EXCEPTION(isolate, JSObject::EnqueueChangeRecord( | 4059 RETURN_ON_EXCEPTION_VALUE(isolate, JSObject::EnqueueChangeRecord( |
4016 receiver, "add", it->name(), | 4060 receiver, "add", it->name(), |
4017 it->factory()->the_hole_value()), | 4061 it->factory()->the_hole_value()), |
4018 Object); | 4062 Nothing<bool>()); |
4019 } | 4063 } |
4020 #if VERIFY_HEAP | 4064 #if VERIFY_HEAP |
4021 if (FLAG_verify_heap) { | 4065 if (FLAG_verify_heap) { |
4022 receiver->JSObjectVerify(); | 4066 receiver->JSObjectVerify(); |
4023 } | 4067 } |
4024 #endif | 4068 #endif |
4025 } | 4069 } |
4026 | 4070 |
4027 return value; | 4071 return Just(true); |
4028 } | 4072 } |
4029 | 4073 |
4030 | 4074 |
4031 void Map::EnsureDescriptorSlack(Handle<Map> map, int slack) { | 4075 void Map::EnsureDescriptorSlack(Handle<Map> map, int slack) { |
4032 // Only supports adding slack to owned descriptors. | 4076 // Only supports adding slack to owned descriptors. |
4033 DCHECK(map->owns_descriptors()); | 4077 DCHECK(map->owns_descriptors()); |
4034 | 4078 |
4035 Handle<DescriptorArray> descriptors(map->instance_descriptors()); | 4079 Handle<DescriptorArray> descriptors(map->instance_descriptors()); |
4036 int old_size = map->NumberOfOwnDescriptors(); | 4080 int old_size = map->NumberOfOwnDescriptors(); |
4037 if (slack <= descriptors->NumberOfSlackDescriptors()) return; | 4081 if (slack <= descriptors->NumberOfSlackDescriptors()) return; |
(...skipping 331 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4369 Handle<Object> result; | 4413 Handle<Object> result; |
4370 ASSIGN_RETURN_ON_EXCEPTION_VALUE( | 4414 ASSIGN_RETURN_ON_EXCEPTION_VALUE( |
4371 isolate, result, CallTrap(proxy, "has", isolate->derived_has_trap(), | 4415 isolate, result, CallTrap(proxy, "has", isolate->derived_has_trap(), |
4372 arraysize(args), args), | 4416 arraysize(args), args), |
4373 Nothing<bool>()); | 4417 Nothing<bool>()); |
4374 | 4418 |
4375 return Just(result->BooleanValue()); | 4419 return Just(result->BooleanValue()); |
4376 } | 4420 } |
4377 | 4421 |
4378 | 4422 |
4379 MaybeHandle<Object> JSProxy::SetPropertyWithHandler( | 4423 Maybe<bool> JSProxy::SetPropertyWithHandler(Handle<JSProxy> proxy, |
4380 Handle<JSProxy> proxy, Handle<Object> receiver, Handle<Name> name, | 4424 Handle<Object> receiver, |
4381 Handle<Object> value, LanguageMode language_mode) { | 4425 Handle<Name> name, |
4426 Handle<Object> value, | |
4427 LanguageMode language_mode, | |
4428 ShouldThrow should_throw) { | |
4382 Isolate* isolate = proxy->GetIsolate(); | 4429 Isolate* isolate = proxy->GetIsolate(); |
4383 | 4430 |
4384 // TODO(rossberg): adjust once there is a story for symbols vs proxies. | 4431 // TODO(rossberg): adjust once there is a story for symbols vs proxies. |
4385 if (name->IsSymbol()) return value; | 4432 if (name->IsSymbol()) return Just(true); |
4386 | 4433 |
4387 Handle<Object> args[] = { receiver, name, value }; | 4434 Handle<Object> args[] = { receiver, name, value }; |
4388 RETURN_ON_EXCEPTION( | 4435 RETURN_ON_EXCEPTION_VALUE(isolate, |
4389 isolate, | 4436 CallTrap(proxy, "set", isolate->derived_set_trap(), |
4390 CallTrap(proxy, | 4437 arraysize(args), args), |
4391 "set", | 4438 Nothing<bool>()); |
4392 isolate->derived_set_trap(), | |
4393 arraysize(args), | |
4394 args), | |
4395 Object); | |
4396 | 4439 |
4397 return value; | 4440 return Just(true); |
4441 // TODO(neis): This needs to be made spec-conformant by throwing a TypeError | |
4442 // if the trap's result is falsish. | |
4398 } | 4443 } |
4399 | 4444 |
4400 | 4445 |
4401 MaybeHandle<Object> JSProxy::SetPropertyViaPrototypesWithHandler( | 4446 Maybe<bool> JSProxy::SetPropertyViaPrototypesWithHandler( |
4402 Handle<JSProxy> proxy, Handle<Object> receiver, Handle<Name> name, | 4447 Handle<JSProxy> proxy, Handle<Object> receiver, Handle<Name> name, |
4403 Handle<Object> value, LanguageMode language_mode, bool* done) { | 4448 Handle<Object> value, LanguageMode language_mode, ShouldThrow should_throw, |
4449 bool* done) { | |
4404 Isolate* isolate = proxy->GetIsolate(); | 4450 Isolate* isolate = proxy->GetIsolate(); |
4405 Handle<Object> handler(proxy->handler(), isolate); // Trap might morph proxy. | 4451 Handle<Object> handler(proxy->handler(), isolate); // Trap might morph proxy. |
4406 | 4452 |
4407 // TODO(rossberg): adjust once there is a story for symbols vs proxies. | 4453 // TODO(rossberg): adjust once there is a story for symbols vs proxies. |
4408 if (name->IsSymbol()) { | 4454 if (name->IsSymbol()) { |
4409 *done = false; | 4455 *done = false; // Return value will be ignored. |
4410 return isolate->factory()->the_hole_value(); | 4456 return Nothing<bool>(); |
4411 } | 4457 } |
4412 | 4458 |
4413 *done = true; // except where redefined... | 4459 *done = true; // except where redefined... |
4414 Handle<Object> args[] = { name }; | 4460 Handle<Object> args[] = { name }; |
4415 Handle<Object> result; | 4461 Handle<Object> result; |
4416 ASSIGN_RETURN_ON_EXCEPTION( | 4462 ASSIGN_RETURN_ON_EXCEPTION_VALUE( |
4417 isolate, result, | 4463 isolate, result, CallTrap(proxy, "getPropertyDescriptor", |
4418 CallTrap(proxy, | 4464 Handle<Object>(), arraysize(args), args), |
4419 "getPropertyDescriptor", | 4465 Nothing<bool>()); |
4420 Handle<Object>(), | |
4421 arraysize(args), | |
4422 args), | |
4423 Object); | |
4424 | 4466 |
4425 if (result->IsUndefined()) { | 4467 if (result->IsUndefined()) { |
4426 *done = false; | 4468 *done = false; // Return value will be ignored. |
4427 return isolate->factory()->the_hole_value(); | 4469 return Nothing<bool>(); |
4428 } | 4470 } |
4429 | 4471 |
4430 // Emulate [[GetProperty]] semantics for proxies. | 4472 // Emulate [[GetProperty]] semantics for proxies. |
4431 Handle<Object> argv[] = { result }; | 4473 Handle<Object> argv[] = { result }; |
4432 Handle<Object> desc; | 4474 Handle<Object> desc; |
4433 ASSIGN_RETURN_ON_EXCEPTION( | 4475 ASSIGN_RETURN_ON_EXCEPTION_VALUE( |
4434 isolate, desc, | 4476 isolate, desc, |
4435 Execution::Call(isolate, | 4477 Execution::Call(isolate, isolate->to_complete_property_descriptor(), |
4436 isolate->to_complete_property_descriptor(), | 4478 result, arraysize(argv), argv), |
4437 result, | 4479 Nothing<bool>()); |
4438 arraysize(argv), | |
4439 argv), | |
4440 Object); | |
4441 | 4480 |
4442 // [[GetProperty]] requires to check that all properties are configurable. | 4481 // [[GetProperty]] requires to check that all properties are configurable. |
4443 Handle<String> configurable_name = | 4482 Handle<String> configurable_name = |
4444 isolate->factory()->InternalizeOneByteString( | 4483 isolate->factory()->InternalizeOneByteString( |
4445 STATIC_CHAR_VECTOR("configurable_")); | 4484 STATIC_CHAR_VECTOR("configurable_")); |
4446 Handle<Object> configurable = | 4485 Handle<Object> configurable = |
4447 Object::GetProperty(desc, configurable_name).ToHandleChecked(); | 4486 Object::GetProperty(desc, configurable_name).ToHandleChecked(); |
4448 DCHECK(configurable->IsBoolean()); | 4487 DCHECK(configurable->IsBoolean()); |
4449 if (configurable->IsFalse()) { | 4488 if (configurable->IsFalse()) { |
4450 Handle<String> trap = isolate->factory()->InternalizeOneByteString( | 4489 RETURN_FAILURE( |
4451 STATIC_CHAR_VECTOR("getPropertyDescriptor")); | 4490 isolate, should_throw, |
4452 THROW_NEW_ERROR(isolate, | 4491 NewTypeError(MessageTemplate::kProxyPropNotConfigurable, handler, name, |
4453 NewTypeError(MessageTemplate::kProxyPropNotConfigurable, | 4492 isolate->factory()->NewStringFromAsciiChecked( |
4454 handler, name, trap), | 4493 "getPropertyDescriptor"))); |
4455 Object); | |
4456 } | 4494 } |
4457 DCHECK(configurable->IsTrue()); | 4495 DCHECK(configurable->IsTrue()); |
4458 | 4496 |
4459 // Check for DataDescriptor. | 4497 // Check for DataDescriptor. |
4460 Handle<String> hasWritable_name = | 4498 Handle<String> hasWritable_name = |
4461 isolate->factory()->InternalizeOneByteString( | 4499 isolate->factory()->InternalizeOneByteString( |
4462 STATIC_CHAR_VECTOR("hasWritable_")); | 4500 STATIC_CHAR_VECTOR("hasWritable_")); |
4463 Handle<Object> hasWritable = | 4501 Handle<Object> hasWritable = |
4464 Object::GetProperty(desc, hasWritable_name).ToHandleChecked(); | 4502 Object::GetProperty(desc, hasWritable_name).ToHandleChecked(); |
4465 DCHECK(hasWritable->IsBoolean()); | 4503 DCHECK(hasWritable->IsBoolean()); |
4466 if (hasWritable->IsTrue()) { | 4504 if (hasWritable->IsTrue()) { |
4467 Handle<String> writable_name = isolate->factory()->InternalizeOneByteString( | 4505 Handle<String> writable_name = isolate->factory()->InternalizeOneByteString( |
4468 STATIC_CHAR_VECTOR("writable_")); | 4506 STATIC_CHAR_VECTOR("writable_")); |
4469 Handle<Object> writable = | 4507 Handle<Object> writable = |
4470 Object::GetProperty(desc, writable_name).ToHandleChecked(); | 4508 Object::GetProperty(desc, writable_name).ToHandleChecked(); |
4471 DCHECK(writable->IsBoolean()); | 4509 DCHECK(writable->IsBoolean()); |
4472 *done = writable->IsFalse(); | 4510 *done = writable->IsFalse(); |
4473 if (!*done) return isolate->factory()->the_hole_value(); | 4511 if (!*done) return Nothing<bool>(); // Return value will be ignored. |
4474 return WriteToReadOnlyProperty(isolate, receiver, name, value, | 4512 return WriteToReadOnlyProperty(isolate, receiver, name, value, |
4475 language_mode); | 4513 language_mode, should_throw); |
4476 } | 4514 } |
4477 | 4515 |
4478 // We have an AccessorDescriptor. | 4516 // We have an AccessorDescriptor. |
4479 Handle<String> set_name = | 4517 Handle<String> set_name = |
4480 isolate->factory()->InternalizeOneByteString(STATIC_CHAR_VECTOR("set_")); | 4518 isolate->factory()->InternalizeOneByteString(STATIC_CHAR_VECTOR("set_")); |
4481 Handle<Object> setter = Object::GetProperty(desc, set_name).ToHandleChecked(); | 4519 Handle<Object> setter = Object::GetProperty(desc, set_name).ToHandleChecked(); |
4482 if (!setter->IsUndefined()) { | 4520 if (!setter->IsUndefined()) { |
4483 // TODO(rossberg): nicer would be to cast to some JSCallable here... | 4521 // TODO(rossberg): nicer would be to cast to some JSCallable here... |
4484 return SetPropertyWithDefinedSetter( | 4522 return SetPropertyWithDefinedSetter( |
4485 receiver, Handle<JSReceiver>::cast(setter), value); | 4523 receiver, Handle<JSReceiver>::cast(setter), value, should_throw); |
4486 } | 4524 } |
4487 | 4525 |
4488 if (is_sloppy(language_mode)) return value; | 4526 if (is_sloppy(language_mode)) return Just(true); |
4489 THROW_NEW_ERROR( | 4527 RETURN_FAILURE( |
4490 isolate, NewTypeError(MessageTemplate::kNoSetterInCallback, name, proxy), | 4528 isolate, should_throw, |
4491 Object); | 4529 NewTypeError(MessageTemplate::kNoSetterInCallback, name, proxy)); |
4492 } | 4530 } |
4493 | 4531 |
4494 | 4532 |
4495 MaybeHandle<Object> JSProxy::DeletePropertyWithHandler( | 4533 MaybeHandle<Object> JSProxy::DeletePropertyWithHandler( |
4496 Handle<JSProxy> proxy, Handle<Name> name, LanguageMode language_mode) { | 4534 Handle<JSProxy> proxy, Handle<Name> name, LanguageMode language_mode) { |
4497 Isolate* isolate = proxy->GetIsolate(); | 4535 Isolate* isolate = proxy->GetIsolate(); |
4498 | 4536 |
4499 // TODO(rossberg): adjust once there is a story for symbols vs proxies. | 4537 // TODO(rossberg): adjust once there is a story for symbols vs proxies. |
4500 if (name->IsSymbol()) return isolate->factory()->false_value(); | 4538 if (name->IsSymbol()) return isolate->factory()->false_value(); |
4501 | 4539 |
(...skipping 259 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4761 // If there's an interceptor, try to store the property with the | 4799 // If there's an interceptor, try to store the property with the |
4762 // interceptor. | 4800 // interceptor. |
4763 // In case of success, the attributes will have been reset to the default | 4801 // In case of success, the attributes will have been reset to the default |
4764 // attributes of the interceptor, rather than the incoming attributes. | 4802 // attributes of the interceptor, rather than the incoming attributes. |
4765 // | 4803 // |
4766 // TODO(verwaest): JSProxy afterwards verify the attributes that the | 4804 // TODO(verwaest): JSProxy afterwards verify the attributes that the |
4767 // JSProxy claims it has, and verifies that they are compatible. If not, | 4805 // JSProxy claims it has, and verifies that they are compatible. If not, |
4768 // they throw. Here we should do the same. | 4806 // they throw. Here we should do the same. |
4769 case LookupIterator::INTERCEPTOR: | 4807 case LookupIterator::INTERCEPTOR: |
4770 if (handling == DONT_FORCE_FIELD) { | 4808 if (handling == DONT_FORCE_FIELD) { |
4771 MaybeHandle<Object> maybe_result = | 4809 Maybe<bool> result = JSObject::SetPropertyWithInterceptor(it, value); |
4772 JSObject::SetPropertyWithInterceptor(it, value); | 4810 if (result.IsNothing()) return MaybeHandle<Object>(); |
4773 if (!maybe_result.is_null()) return maybe_result; | 4811 if (result.FromJust()) return value; |
4774 if (it->isolate()->has_pending_exception()) return maybe_result; | |
4775 } | 4812 } |
4776 break; | 4813 break; |
4777 | 4814 |
4778 case LookupIterator::ACCESSOR: { | 4815 case LookupIterator::ACCESSOR: { |
4779 Handle<Object> accessors = it->GetAccessors(); | 4816 Handle<Object> accessors = it->GetAccessors(); |
4780 | 4817 |
4781 // Special handling for ExecutableAccessorInfo, which behaves like a | 4818 // Special handling for ExecutableAccessorInfo, which behaves like a |
4782 // data property. | 4819 // data property. |
4783 if (accessors->IsExecutableAccessorInfo() && | 4820 if (accessors->IsExecutableAccessorInfo() && |
4784 handling == DONT_FORCE_FIELD) { | 4821 handling == DONT_FORCE_FIELD) { |
4785 PropertyDetails details = it->property_details(); | 4822 PropertyDetails details = it->property_details(); |
4786 // Ensure the context isn't changed after calling into accessors. | 4823 // Ensure the context isn't changed after calling into accessors. |
4787 AssertNoContextChange ncc(it->isolate()); | 4824 AssertNoContextChange ncc(it->isolate()); |
4788 | 4825 |
4789 Handle<Object> result; | 4826 Maybe<bool> result = JSObject::SetPropertyWithAccessor( |
4790 ASSIGN_RETURN_ON_EXCEPTION( | 4827 it, value, STRICT, THROW_ON_ERROR); |
4791 it->isolate(), result, | 4828 if (result.IsNothing()) return MaybeHandle<Object>(); |
4792 JSObject::SetPropertyWithAccessor(it, value, STRICT), Object); | |
4793 DCHECK(result->SameValue(*value)); | |
4794 | 4829 |
4795 if (details.attributes() == attributes) return value; | 4830 if (details.attributes() == attributes) return value; |
4796 | 4831 |
4797 // Reconfigure the accessor if attributes mismatch. | 4832 // Reconfigure the accessor if attributes mismatch. |
4798 Handle<ExecutableAccessorInfo> new_data = Accessors::CloneAccessor( | 4833 Handle<ExecutableAccessorInfo> new_data = Accessors::CloneAccessor( |
4799 it->isolate(), Handle<ExecutableAccessorInfo>::cast(accessors)); | 4834 it->isolate(), Handle<ExecutableAccessorInfo>::cast(accessors)); |
4800 new_data->set_property_attributes(attributes); | 4835 new_data->set_property_attributes(attributes); |
4801 // By clearing the setter we don't have to introduce a lookup to | 4836 // By clearing the setter we don't have to introduce a lookup to |
4802 // the setter, simply make it unavailable to reflect the | 4837 // the setter, simply make it unavailable to reflect the |
4803 // attributes. | 4838 // attributes. |
(...skipping 18 matching lines...) Expand all Loading... | |
4822 } | 4857 } |
4823 case LookupIterator::INTEGER_INDEXED_EXOTIC: | 4858 case LookupIterator::INTEGER_INDEXED_EXOTIC: |
4824 return RedefineNonconfigurableProperty(it->isolate(), it->GetName(), | 4859 return RedefineNonconfigurableProperty(it->isolate(), it->GetName(), |
4825 value, STRICT); | 4860 value, STRICT); |
4826 | 4861 |
4827 case LookupIterator::DATA: { | 4862 case LookupIterator::DATA: { |
4828 PropertyDetails details = it->property_details(); | 4863 PropertyDetails details = it->property_details(); |
4829 Handle<Object> old_value = it->factory()->the_hole_value(); | 4864 Handle<Object> old_value = it->factory()->the_hole_value(); |
4830 // Regular property update if the attributes match. | 4865 // Regular property update if the attributes match. |
4831 if (details.attributes() == attributes) { | 4866 if (details.attributes() == attributes) { |
4832 return SetDataProperty(it, value); | 4867 MAYBE_RETURN_NULL(SetDataProperty(it, value, THROW_ON_ERROR)); |
4868 return value; | |
4833 } | 4869 } |
4834 | 4870 |
4835 // Special case: properties of typed arrays cannot be reconfigured to | 4871 // Special case: properties of typed arrays cannot be reconfigured to |
4836 // non-writable nor to non-enumerable. | 4872 // non-writable nor to non-enumerable. |
4837 if (it->IsElement() && object->HasFixedTypedArrayElements()) { | 4873 if (it->IsElement() && object->HasFixedTypedArrayElements()) { |
4838 return RedefineNonconfigurableProperty(it->isolate(), it->GetName(), | 4874 return RedefineNonconfigurableProperty(it->isolate(), it->GetName(), |
4839 value, STRICT); | 4875 value, STRICT); |
4840 } | 4876 } |
4841 | 4877 |
4842 // Reconfigure the data property if the attributes mismatch. | 4878 // Reconfigure the data property if the attributes mismatch. |
(...skipping 2112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
6955 if (attrs != NONE) { | 6991 if (attrs != NONE) { |
6956 ApplyAttributesToDictionary(dictionary, attrs); | 6992 ApplyAttributesToDictionary(dictionary, attrs); |
6957 } | 6993 } |
6958 } | 6994 } |
6959 | 6995 |
6960 return Just(true); | 6996 return Just(true); |
6961 } | 6997 } |
6962 | 6998 |
6963 | 6999 |
6964 MaybeHandle<Object> JSObject::Freeze(Handle<JSObject> object) { | 7000 MaybeHandle<Object> JSObject::Freeze(Handle<JSObject> object) { |
6965 return PreventExtensionsWithTransition<FROZEN>(object, THROW_ON_ERROR) | 7001 MAYBE_RETURN_NULL( |
6966 .IsJust() | 7002 PreventExtensionsWithTransition<FROZEN>(object, THROW_ON_ERROR)); |
6967 ? object | 7003 return object; |
6968 : MaybeHandle<Object>(); | |
6969 } | 7004 } |
6970 | 7005 |
6971 | 7006 |
6972 MaybeHandle<Object> JSObject::Seal(Handle<JSObject> object) { | 7007 MaybeHandle<Object> JSObject::Seal(Handle<JSObject> object) { |
6973 return PreventExtensionsWithTransition<SEALED>(object, THROW_ON_ERROR) | 7008 MAYBE_RETURN_NULL( |
6974 .IsJust() | 7009 PreventExtensionsWithTransition<SEALED>(object, THROW_ON_ERROR)); |
6975 ? object | 7010 return object; |
6976 : MaybeHandle<Object>(); | |
6977 } | 7011 } |
6978 | 7012 |
6979 | 7013 |
6980 void JSObject::SetObserved(Handle<JSObject> object) { | 7014 void JSObject::SetObserved(Handle<JSObject> object) { |
6981 DCHECK(!object->IsJSGlobalProxy()); | 7015 DCHECK(!object->IsJSGlobalProxy()); |
6982 DCHECK(!object->IsJSGlobalObject()); | 7016 DCHECK(!object->IsJSGlobalObject()); |
6983 Isolate* isolate = object->GetIsolate(); | 7017 Isolate* isolate = object->GetIsolate(); |
6984 Handle<Map> new_map; | 7018 Handle<Map> new_map; |
6985 Handle<Map> old_map(object->map(), isolate); | 7019 Handle<Map> old_map(object->map(), isolate); |
6986 DCHECK(!old_map->is_observed()); | 7020 DCHECK(!old_map->is_observed()); |
(...skipping 7161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
14148 SeededNumberDictionary::kEntrySize; | 14182 SeededNumberDictionary::kEntrySize; |
14149 return 2 * dictionary_size >= *new_capacity; | 14183 return 2 * dictionary_size >= *new_capacity; |
14150 } | 14184 } |
14151 | 14185 |
14152 | 14186 |
14153 // static | 14187 // static |
14154 MaybeHandle<Object> JSObject::AddDataElement(Handle<JSObject> object, | 14188 MaybeHandle<Object> JSObject::AddDataElement(Handle<JSObject> object, |
14155 uint32_t index, | 14189 uint32_t index, |
14156 Handle<Object> value, | 14190 Handle<Object> value, |
14157 PropertyAttributes attributes) { | 14191 PropertyAttributes attributes) { |
14192 MAYBE_RETURN_NULL( | |
14193 AddDataElement(object, index, value, attributes, THROW_ON_ERROR)); | |
14194 return value; | |
14195 } | |
14196 | |
14197 | |
14198 // static | |
14199 Maybe<bool> JSObject::AddDataElement(Handle<JSObject> object, uint32_t index, | |
14200 Handle<Object> value, | |
14201 PropertyAttributes attributes, | |
14202 ShouldThrow should_throw) { | |
14158 DCHECK(object->map()->is_extensible()); | 14203 DCHECK(object->map()->is_extensible()); |
14159 | 14204 |
14160 Isolate* isolate = object->GetIsolate(); | 14205 Isolate* isolate = object->GetIsolate(); |
14161 | 14206 |
14162 uint32_t old_length = 0; | 14207 uint32_t old_length = 0; |
14163 uint32_t new_capacity = 0; | 14208 uint32_t new_capacity = 0; |
14164 | 14209 |
14165 Handle<Object> old_length_handle; | 14210 Handle<Object> old_length_handle; |
14166 if (object->IsJSArray()) { | 14211 if (object->IsJSArray()) { |
14167 CHECK(JSArray::cast(*object)->length()->ToArrayLength(&old_length)); | 14212 CHECK(JSArray::cast(*object)->length()->ToArrayLength(&old_length)); |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
14208 new_length_handle = isolate->factory()->NewNumberFromUint(new_length); | 14253 new_length_handle = isolate->factory()->NewNumberFromUint(new_length); |
14209 JSArray::cast(*object)->set_length(*new_length_handle); | 14254 JSArray::cast(*object)->set_length(*new_length_handle); |
14210 } | 14255 } |
14211 | 14256 |
14212 if (!old_length_handle.is_null() && new_length != old_length) { | 14257 if (!old_length_handle.is_null() && new_length != old_length) { |
14213 // |old_length_handle| is kept null above unless the object is observed. | 14258 // |old_length_handle| is kept null above unless the object is observed. |
14214 DCHECK(object->map()->is_observed()); | 14259 DCHECK(object->map()->is_observed()); |
14215 Handle<JSArray> array = Handle<JSArray>::cast(object); | 14260 Handle<JSArray> array = Handle<JSArray>::cast(object); |
14216 Handle<String> name = isolate->factory()->Uint32ToString(index); | 14261 Handle<String> name = isolate->factory()->Uint32ToString(index); |
14217 | 14262 |
14218 RETURN_ON_EXCEPTION(isolate, BeginPerformSplice(array), Object); | 14263 RETURN_ON_EXCEPTION_VALUE(isolate, BeginPerformSplice(array), |
14219 RETURN_ON_EXCEPTION( | 14264 Nothing<bool>()); |
14265 RETURN_ON_EXCEPTION_VALUE( | |
14220 isolate, EnqueueChangeRecord(array, "add", name, | 14266 isolate, EnqueueChangeRecord(array, "add", name, |
14221 isolate->factory()->the_hole_value()), | 14267 isolate->factory()->the_hole_value()), |
14222 Object); | 14268 Nothing<bool>()); |
14223 RETURN_ON_EXCEPTION(isolate, | 14269 RETURN_ON_EXCEPTION_VALUE( |
14224 EnqueueChangeRecord(array, "update", | 14270 isolate, EnqueueChangeRecord(array, "update", |
14225 isolate->factory()->length_string(), | 14271 isolate->factory()->length_string(), |
14226 old_length_handle), | 14272 old_length_handle), |
14227 Object); | 14273 Nothing<bool>()); |
14228 RETURN_ON_EXCEPTION(isolate, EndPerformSplice(array), Object); | 14274 RETURN_ON_EXCEPTION_VALUE(isolate, EndPerformSplice(array), |
14275 Nothing<bool>()); | |
14229 Handle<JSArray> deleted = isolate->factory()->NewJSArray(0); | 14276 Handle<JSArray> deleted = isolate->factory()->NewJSArray(0); |
14230 RETURN_ON_EXCEPTION(isolate, EnqueueSpliceRecord(array, old_length, deleted, | 14277 RETURN_ON_EXCEPTION_VALUE(isolate, |
14231 new_length - old_length), | 14278 EnqueueSpliceRecord(array, old_length, deleted, |
14232 Object); | 14279 new_length - old_length), |
14280 Nothing<bool>()); | |
14233 } else if (object->map()->is_observed()) { | 14281 } else if (object->map()->is_observed()) { |
14234 Handle<String> name = isolate->factory()->Uint32ToString(index); | 14282 Handle<String> name = isolate->factory()->Uint32ToString(index); |
14235 RETURN_ON_EXCEPTION( | 14283 RETURN_ON_EXCEPTION_VALUE( |
14236 isolate, EnqueueChangeRecord(object, "add", name, | 14284 isolate, EnqueueChangeRecord(object, "add", name, |
14237 isolate->factory()->the_hole_value()), | 14285 isolate->factory()->the_hole_value()), |
14238 Object); | 14286 Nothing<bool>()); |
14239 } | 14287 } |
14240 | 14288 |
14241 return value; | 14289 return Just(true); |
14242 } | 14290 } |
14243 | 14291 |
14244 | 14292 |
14245 bool JSArray::SetLengthWouldNormalize(uint32_t new_length) { | 14293 bool JSArray::SetLengthWouldNormalize(uint32_t new_length) { |
14246 if (!HasFastElements()) return false; | 14294 if (!HasFastElements()) return false; |
14247 uint32_t capacity = static_cast<uint32_t>(elements()->length()); | 14295 uint32_t capacity = static_cast<uint32_t>(elements()->length()); |
14248 uint32_t new_capacity; | 14296 uint32_t new_capacity; |
14249 return JSArray::SetLengthWouldNormalize(GetHeap(), new_length) && | 14297 return JSArray::SetLengthWouldNormalize(GetHeap(), new_length) && |
14250 ShouldConvertToSlowElements(this, capacity, new_length - 1, | 14298 ShouldConvertToSlowElements(this, capacity, new_length - 1, |
14251 &new_capacity); | 14299 &new_capacity); |
(...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
14434 | 14482 |
14435 bool JSArray::WouldChangeReadOnlyLength(Handle<JSArray> array, | 14483 bool JSArray::WouldChangeReadOnlyLength(Handle<JSArray> array, |
14436 uint32_t index) { | 14484 uint32_t index) { |
14437 uint32_t length = 0; | 14485 uint32_t length = 0; |
14438 CHECK(array->length()->ToArrayLength(&length)); | 14486 CHECK(array->length()->ToArrayLength(&length)); |
14439 if (length <= index) return HasReadOnlyLength(array); | 14487 if (length <= index) return HasReadOnlyLength(array); |
14440 return false; | 14488 return false; |
14441 } | 14489 } |
14442 | 14490 |
14443 | 14491 |
14444 MaybeHandle<Object> JSArray::ReadOnlyLengthError(Handle<JSArray> array) { | |
14445 Isolate* isolate = array->GetIsolate(); | |
14446 Handle<Name> length = isolate->factory()->length_string(); | |
14447 Handle<String> typeof_string = Object::TypeOf(isolate, array); | |
14448 THROW_NEW_ERROR(isolate, | |
14449 NewTypeError(MessageTemplate::kStrictReadOnlyProperty, length, | |
14450 typeof_string, array), | |
14451 Object); | |
14452 } | |
14453 | |
14454 | |
14455 template <typename BackingStore> | 14492 template <typename BackingStore> |
14456 static int FastHoleyElementsUsage(JSObject* object, BackingStore* store) { | 14493 static int FastHoleyElementsUsage(JSObject* object, BackingStore* store) { |
14457 int limit = object->IsJSArray() | 14494 int limit = object->IsJSArray() |
14458 ? Smi::cast(JSArray::cast(object)->length())->value() | 14495 ? Smi::cast(JSArray::cast(object)->length())->value() |
14459 : store->length(); | 14496 : store->length(); |
14460 int used = 0; | 14497 int used = 0; |
14461 for (int i = 0; i < limit; ++i) { | 14498 for (int i = 0; i < limit; ++i) { |
14462 if (!store->is_the_hole(i)) ++used; | 14499 if (!store->is_the_hole(i)) ++used; |
14463 } | 14500 } |
14464 return used; | 14501 return used; |
(...skipping 3367 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
17832 if (cell->value() != *new_value) { | 17869 if (cell->value() != *new_value) { |
17833 cell->set_value(*new_value); | 17870 cell->set_value(*new_value); |
17834 Isolate* isolate = cell->GetIsolate(); | 17871 Isolate* isolate = cell->GetIsolate(); |
17835 cell->dependent_code()->DeoptimizeDependentCodeGroup( | 17872 cell->dependent_code()->DeoptimizeDependentCodeGroup( |
17836 isolate, DependentCode::kPropertyCellChangedGroup); | 17873 isolate, DependentCode::kPropertyCellChangedGroup); |
17837 } | 17874 } |
17838 } | 17875 } |
17839 | 17876 |
17840 } // namespace internal | 17877 } // namespace internal |
17841 } // namespace v8 | 17878 } // namespace v8 |
OLD | NEW |