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 847 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
858 bool AccessorInfo::IsCompatibleReceiverMap(Isolate* isolate, | 858 bool AccessorInfo::IsCompatibleReceiverMap(Isolate* isolate, |
859 Handle<AccessorInfo> info, | 859 Handle<AccessorInfo> info, |
860 Handle<Map> map) { | 860 Handle<Map> map) { |
861 if (!info->HasExpectedReceiverType()) return true; | 861 if (!info->HasExpectedReceiverType()) return true; |
862 if (!map->IsJSObjectMap()) return false; | 862 if (!map->IsJSObjectMap()) return false; |
863 return FunctionTemplateInfo::cast(info->expected_receiver_type()) | 863 return FunctionTemplateInfo::cast(info->expected_receiver_type()) |
864 ->IsTemplateFor(*map); | 864 ->IsTemplateFor(*map); |
865 } | 865 } |
866 | 866 |
867 | 867 |
868 MaybeHandle<Object> Object::SetPropertyWithAccessor( | 868 #define RETURN_FAILURE(isolate, should_throw, call) \ |
869 LookupIterator* it, Handle<Object> value, LanguageMode language_mode) { | 869 do { \ |
870 if ((should_throw) == DONT_THROW) { \ | |
871 return Just(false); \ | |
872 } else { \ | |
873 isolate->Throw(*isolate->factory()->call); \ | |
874 return Nothing<bool>(); \ | |
875 } \ | |
876 } while (false) | |
877 | |
878 | |
879 Maybe<bool> Object::SetPropertyWithAccessor(LookupIterator* it, | |
880 Handle<Object> value, | |
881 LanguageMode language_mode, | |
882 ShouldThrow should_throw) { | |
870 Isolate* isolate = it->isolate(); | 883 Isolate* isolate = it->isolate(); |
871 Handle<Object> structure = it->GetAccessors(); | 884 Handle<Object> structure = it->GetAccessors(); |
872 Handle<Object> receiver = it->GetReceiver(); | 885 Handle<Object> receiver = it->GetReceiver(); |
873 | 886 |
874 // We should never get here to initialize a const with the hole value since a | 887 // We should never get here to initialize a const with the hole value since a |
875 // const declaration would conflict with the setter. | 888 // const declaration would conflict with the setter. |
876 DCHECK(!structure->IsForeign()); | 889 DCHECK(!structure->IsForeign()); |
877 | 890 |
878 // API style callbacks. | 891 // API style callbacks. |
879 if (structure->IsExecutableAccessorInfo()) { | 892 if (structure->IsExecutableAccessorInfo()) { |
880 Handle<JSObject> holder = it->GetHolder<JSObject>(); | 893 Handle<JSObject> holder = it->GetHolder<JSObject>(); |
881 Handle<Name> name = it->GetName(); | 894 Handle<Name> name = it->GetName(); |
882 Handle<ExecutableAccessorInfo> info = | 895 Handle<ExecutableAccessorInfo> info = |
883 Handle<ExecutableAccessorInfo>::cast(structure); | 896 Handle<ExecutableAccessorInfo>::cast(structure); |
884 if (!info->IsCompatibleReceiver(*receiver)) { | 897 if (!info->IsCompatibleReceiver(*receiver)) { |
885 THROW_NEW_ERROR(isolate, | 898 isolate->Throw(*isolate->factory()->NewTypeError( |
886 NewTypeError(MessageTemplate::kIncompatibleMethodReceiver, | 899 MessageTemplate::kIncompatibleMethodReceiver, name, receiver)); |
887 name, receiver), | 900 return Nothing<bool>(); |
888 Object); | |
889 } | 901 } |
890 | 902 |
891 v8::AccessorNameSetterCallback call_fun = | 903 v8::AccessorNameSetterCallback call_fun = |
892 v8::ToCData<v8::AccessorNameSetterCallback>(info->setter()); | 904 v8::ToCData<v8::AccessorNameSetterCallback>(info->setter()); |
893 if (call_fun == nullptr) return value; | 905 if (call_fun == nullptr) return Just(true); |
Toon Verwaest
2015/10/20 15:25:06
Shouldn't this case be unreachable (at least in th
neis
2015/10/21 14:42:25
Done.
| |
894 | 906 |
895 LOG(isolate, ApiNamedPropertyAccess("store", *holder, *name)); | 907 LOG(isolate, ApiNamedPropertyAccess("store", *holder, *name)); |
896 PropertyCallbackArguments args(isolate, info->data(), *receiver, *holder); | 908 PropertyCallbackArguments args(isolate, info->data(), *receiver, *holder); |
897 args.Call(call_fun, v8::Utils::ToLocal(name), v8::Utils::ToLocal(value)); | 909 args.Call(call_fun, v8::Utils::ToLocal(name), v8::Utils::ToLocal(value)); |
898 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object); | 910 RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<bool>()); |
899 return value; | 911 return Just(true); |
900 } | 912 } |
901 | 913 |
902 // Regular accessor. | 914 // Regular accessor. |
903 Handle<Object> setter(AccessorPair::cast(*structure)->setter(), isolate); | 915 Handle<Object> setter(AccessorPair::cast(*structure)->setter(), isolate); |
904 if (setter->IsCallable()) { | 916 if (setter->IsCallable()) { |
905 // TODO(rossberg): nicer would be to cast to some JSCallable here... | 917 // TODO(rossberg): nicer would be to cast to some JSCallable here... |
906 return SetPropertyWithDefinedSetter( | 918 return SetPropertyWithDefinedSetter( |
907 receiver, Handle<JSReceiver>::cast(setter), value); | 919 receiver, Handle<JSReceiver>::cast(setter), value, should_throw); |
908 } | 920 } |
909 | 921 |
910 if (is_sloppy(language_mode)) return value; | 922 if (is_sloppy(language_mode)) return Just(true); |
911 | 923 RETURN_FAILURE(isolate, should_throw, |
912 THROW_NEW_ERROR(isolate, | 924 NewTypeError(MessageTemplate::kNoSetterInCallback, |
913 NewTypeError(MessageTemplate::kNoSetterInCallback, | 925 it->GetName(), it->GetHolder<JSObject>())); |
914 it->GetName(), it->GetHolder<JSObject>()), | |
915 Object); | |
916 } | 926 } |
917 | 927 |
918 | 928 |
919 MaybeHandle<Object> Object::GetPropertyWithDefinedGetter( | 929 MaybeHandle<Object> Object::GetPropertyWithDefinedGetter( |
920 Handle<Object> receiver, | 930 Handle<Object> receiver, |
921 Handle<JSReceiver> getter) { | 931 Handle<JSReceiver> getter) { |
922 Isolate* isolate = getter->GetIsolate(); | 932 Isolate* isolate = getter->GetIsolate(); |
923 | 933 |
924 // Platforms with simulators like arm/arm64 expose a funny issue. If the | 934 // Platforms with simulators like arm/arm64 expose a funny issue. If the |
925 // simulator has a separate JS stack pointer from the C++ stack pointer, it | 935 // simulator has a separate JS stack pointer from the C++ stack pointer, it |
(...skipping 11 matching lines...) Expand all Loading... | |
937 | 947 |
938 Debug* debug = isolate->debug(); | 948 Debug* debug = isolate->debug(); |
939 // Handle stepping into a getter if step into is active. | 949 // Handle stepping into a getter if step into is active. |
940 // TODO(rossberg): should this apply to getters that are function proxies? | 950 // TODO(rossberg): should this apply to getters that are function proxies? |
941 if (debug->is_active()) debug->HandleStepIn(getter, false); | 951 if (debug->is_active()) debug->HandleStepIn(getter, false); |
942 | 952 |
943 return Execution::Call(isolate, getter, receiver, 0, NULL); | 953 return Execution::Call(isolate, getter, receiver, 0, NULL); |
944 } | 954 } |
945 | 955 |
946 | 956 |
947 MaybeHandle<Object> Object::SetPropertyWithDefinedSetter( | 957 Maybe<bool> Object::SetPropertyWithDefinedSetter(Handle<Object> receiver, |
948 Handle<Object> receiver, | 958 Handle<JSReceiver> setter, |
949 Handle<JSReceiver> setter, | 959 Handle<Object> value, |
950 Handle<Object> value) { | 960 ShouldThrow should_throw) { |
951 Isolate* isolate = setter->GetIsolate(); | 961 Isolate* isolate = setter->GetIsolate(); |
952 | 962 |
953 Debug* debug = isolate->debug(); | 963 Debug* debug = isolate->debug(); |
954 // Handle stepping into a setter if step into is active. | 964 // Handle stepping into a setter if step into is active. |
955 // TODO(rossberg): should this apply to getters that are function proxies? | 965 // TODO(rossberg): should this apply to getters that are function proxies? |
956 if (debug->is_active()) debug->HandleStepIn(setter, false); | 966 if (debug->is_active()) debug->HandleStepIn(setter, false); |
957 | 967 |
958 Handle<Object> argv[] = { value }; | 968 Handle<Object> argv[] = { value }; |
959 RETURN_ON_EXCEPTION(isolate, Execution::Call(isolate, setter, receiver, | 969 RETURN_ON_EXCEPTION_VALUE(isolate, Execution::Call(isolate, setter, receiver, |
960 arraysize(argv), argv), | 970 arraysize(argv), argv), |
961 Object); | 971 Nothing<bool>()); |
962 return value; | 972 return Just(true); |
963 } | 973 } |
964 | 974 |
965 | 975 |
966 // static | 976 // static |
967 bool JSObject::AllCanRead(LookupIterator* it) { | 977 bool JSObject::AllCanRead(LookupIterator* it) { |
968 // Skip current iteration, it's in state ACCESS_CHECK or INTERCEPTOR, both of | 978 // Skip current iteration, it's in state ACCESS_CHECK or INTERCEPTOR, both of |
969 // which have already been checked. | 979 // which have already been checked. |
970 DCHECK(it->state() == LookupIterator::ACCESS_CHECK || | 980 DCHECK(it->state() == LookupIterator::ACCESS_CHECK || |
971 it->state() == LookupIterator::INTERCEPTOR); | 981 it->state() == LookupIterator::INTERCEPTOR); |
972 for (it->Next(); it->IsFound(); it->Next()) { | 982 for (it->Next(); it->IsFound(); it->Next()) { |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1037 Handle<Object> accessors = it->GetAccessors(); | 1047 Handle<Object> accessors = it->GetAccessors(); |
1038 if (accessors->IsAccessorInfo()) { | 1048 if (accessors->IsAccessorInfo()) { |
1039 if (AccessorInfo::cast(*accessors)->all_can_write()) return true; | 1049 if (AccessorInfo::cast(*accessors)->all_can_write()) return true; |
1040 } | 1050 } |
1041 } | 1051 } |
1042 } | 1052 } |
1043 return false; | 1053 return false; |
1044 } | 1054 } |
1045 | 1055 |
1046 | 1056 |
1047 MaybeHandle<Object> JSObject::SetPropertyWithFailedAccessCheck( | 1057 Maybe<bool> JSObject::SetPropertyWithFailedAccessCheck( |
1048 LookupIterator* it, Handle<Object> value) { | 1058 LookupIterator* it, Handle<Object> value, ShouldThrow should_throw) { |
1049 Handle<JSObject> checked = it->GetHolder<JSObject>(); | 1059 Handle<JSObject> checked = it->GetHolder<JSObject>(); |
1050 if (AllCanWrite(it)) { | 1060 if (AllCanWrite(it)) { |
1051 // The supplied language-mode is ignored by SetPropertyWithAccessor. | 1061 // The supplied language-mode is ignored by SetPropertyWithAccessor. |
1052 return SetPropertyWithAccessor(it, value, SLOPPY); | 1062 return SetPropertyWithAccessor(it, value, SLOPPY, should_throw); |
1053 } | 1063 } |
1054 | 1064 |
1055 it->isolate()->ReportFailedAccessCheck(checked); | 1065 it->isolate()->ReportFailedAccessCheck(checked); |
1056 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(it->isolate(), Object); | 1066 RETURN_VALUE_IF_SCHEDULED_EXCEPTION(it->isolate(), Nothing<bool>()); |
1057 return value; | 1067 UNREACHABLE(); |
1068 it->isolate()->Throw( | |
1069 *it->isolate()->factory()->NewTypeError(MessageTemplate::kNoAccess)); | |
1070 return Nothing<bool>(); | |
Toon Verwaest
2015/10/20 15:25:06
Nice. Wouldn't it be helpful to extract this to a
neis
2015/10/21 14:42:25
Yes, and this should probably be used in many othe
| |
1058 } | 1071 } |
1059 | 1072 |
1060 | 1073 |
1061 void JSObject::SetNormalizedProperty(Handle<JSObject> object, | 1074 void JSObject::SetNormalizedProperty(Handle<JSObject> object, |
1062 Handle<Name> name, | 1075 Handle<Name> name, |
1063 Handle<Object> value, | 1076 Handle<Object> value, |
1064 PropertyDetails details) { | 1077 PropertyDetails details) { |
1065 DCHECK(!object->HasFastProperties()); | 1078 DCHECK(!object->HasFastProperties()); |
1066 if (!name->IsUniqueName()) { | 1079 if (!name->IsUniqueName()) { |
1067 name = object->GetIsolate()->factory()->InternalizeString( | 1080 name = object->GetIsolate()->factory()->InternalizeString( |
(...skipping 2438 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3506 | 3519 |
3507 // static | 3520 // static |
3508 Handle<Map> Map::Update(Handle<Map> map) { | 3521 Handle<Map> Map::Update(Handle<Map> map) { |
3509 if (!map->is_deprecated()) return map; | 3522 if (!map->is_deprecated()) return map; |
3510 return ReconfigureProperty(map, -1, kData, NONE, Representation::None(), | 3523 return ReconfigureProperty(map, -1, kData, NONE, Representation::None(), |
3511 HeapType::None(map->GetIsolate()), | 3524 HeapType::None(map->GetIsolate()), |
3512 ALLOW_IN_DESCRIPTOR); | 3525 ALLOW_IN_DESCRIPTOR); |
3513 } | 3526 } |
3514 | 3527 |
3515 | 3528 |
3516 MaybeHandle<Object> JSObject::SetPropertyWithInterceptor(LookupIterator* it, | 3529 Maybe<bool> JSObject::SetPropertyWithInterceptor(LookupIterator* it, |
3517 Handle<Object> value) { | 3530 Handle<Object> value, |
3531 ShouldThrow should_throw) { | |
3518 Isolate* isolate = it->isolate(); | 3532 Isolate* isolate = it->isolate(); |
3519 // Make sure that the top context does not change when doing callbacks or | 3533 // Make sure that the top context does not change when doing callbacks or |
3520 // interceptor calls. | 3534 // interceptor calls. |
3521 AssertNoContextChange ncc(isolate); | 3535 AssertNoContextChange ncc(isolate); |
3522 | 3536 |
3523 DCHECK_EQ(LookupIterator::INTERCEPTOR, it->state()); | 3537 DCHECK_EQ(LookupIterator::INTERCEPTOR, it->state()); |
3524 Handle<InterceptorInfo> interceptor(it->GetInterceptor()); | 3538 Handle<InterceptorInfo> interceptor(it->GetInterceptor()); |
3525 if (interceptor->setter()->IsUndefined()) return MaybeHandle<Object>(); | 3539 if (interceptor->setter()->IsUndefined()) return Nothing<bool>(); |
3526 | 3540 |
3527 Handle<JSObject> holder = it->GetHolder<JSObject>(); | 3541 Handle<JSObject> holder = it->GetHolder<JSObject>(); |
3528 v8::Local<v8::Value> result; | 3542 v8::Local<v8::Value> result; |
3529 PropertyCallbackArguments args(isolate, interceptor->data(), | 3543 PropertyCallbackArguments args(isolate, interceptor->data(), |
3530 *it->GetReceiver(), *holder); | 3544 *it->GetReceiver(), *holder); |
3531 | 3545 |
3532 if (it->IsElement()) { | 3546 if (it->IsElement()) { |
3533 uint32_t index = it->index(); | 3547 uint32_t index = it->index(); |
3534 v8::IndexedPropertySetterCallback setter = | 3548 v8::IndexedPropertySetterCallback setter = |
3535 v8::ToCData<v8::IndexedPropertySetterCallback>(interceptor->setter()); | 3549 v8::ToCData<v8::IndexedPropertySetterCallback>(interceptor->setter()); |
3536 LOG(isolate, | 3550 LOG(isolate, |
3537 ApiIndexedPropertyAccess("interceptor-indexed-set", *holder, index)); | 3551 ApiIndexedPropertyAccess("interceptor-indexed-set", *holder, index)); |
3538 result = args.Call(setter, index, v8::Utils::ToLocal(value)); | 3552 result = args.Call(setter, index, v8::Utils::ToLocal(value)); |
3539 } else { | 3553 } else { |
3540 Handle<Name> name = it->name(); | 3554 Handle<Name> name = it->name(); |
3541 | 3555 |
3542 if (name->IsSymbol() && !interceptor->can_intercept_symbols()) { | 3556 if (name->IsSymbol() && !interceptor->can_intercept_symbols()) { |
3543 return MaybeHandle<Object>(); | 3557 return Nothing<bool>(); |
3544 } | 3558 } |
3545 | 3559 |
3546 v8::GenericNamedPropertySetterCallback setter = | 3560 v8::GenericNamedPropertySetterCallback setter = |
3547 v8::ToCData<v8::GenericNamedPropertySetterCallback>( | 3561 v8::ToCData<v8::GenericNamedPropertySetterCallback>( |
3548 interceptor->setter()); | 3562 interceptor->setter()); |
3549 LOG(it->isolate(), | 3563 LOG(it->isolate(), |
3550 ApiNamedPropertyAccess("interceptor-named-set", *holder, *name)); | 3564 ApiNamedPropertyAccess("interceptor-named-set", *holder, *name)); |
3551 result = | 3565 result = |
3552 args.Call(setter, v8::Utils::ToLocal(name), v8::Utils::ToLocal(value)); | 3566 args.Call(setter, v8::Utils::ToLocal(name), v8::Utils::ToLocal(value)); |
3553 } | 3567 } |
3554 | 3568 |
3555 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(it->isolate(), Object); | 3569 RETURN_VALUE_IF_SCHEDULED_EXCEPTION(it->isolate(), Nothing<bool>()); |
3556 if (result.IsEmpty()) return MaybeHandle<Object>(); | 3570 if (result.IsEmpty()) return Nothing<bool>(); |
3557 #ifdef DEBUG | 3571 #ifdef DEBUG |
3558 Handle<Object> result_internal = v8::Utils::OpenHandle(*result); | 3572 Handle<Object> result_internal = v8::Utils::OpenHandle(*result); |
3559 result_internal->VerifyApiCallResultType(); | 3573 result_internal->VerifyApiCallResultType(); |
3560 #endif | 3574 #endif |
3561 return value; | 3575 return Just(true); |
3562 } | 3576 } |
3563 | 3577 |
3564 | 3578 |
3565 MaybeHandle<Object> Object::SetProperty(Handle<Object> object, | 3579 MaybeHandle<Object> Object::SetProperty(Handle<Object> object, |
3566 Handle<Name> name, Handle<Object> value, | 3580 Handle<Name> name, Handle<Object> value, |
3567 LanguageMode language_mode, | 3581 LanguageMode language_mode, |
3568 StoreFromKeyed store_mode) { | 3582 StoreFromKeyed store_mode) { |
3569 LookupIterator it(object, name); | 3583 LookupIterator it(object, name); |
3570 return SetProperty(&it, value, language_mode, store_mode); | 3584 return SetProperty(&it, value, language_mode, store_mode); |
3571 } | 3585 } |
3572 | 3586 |
3573 | 3587 |
3574 MaybeHandle<Object> Object::SetPropertyInternal(LookupIterator* it, | 3588 Maybe<bool> Object::SetPropertyInternal( |
3575 Handle<Object> value, | 3589 LookupIterator* it, Handle<Object> value, LanguageMode language_mode, |
3576 LanguageMode language_mode, | 3590 ShouldThrow should_throw, StoreFromKeyed store_mode, bool* found) { |
3577 StoreFromKeyed store_mode, | |
3578 bool* found) { | |
3579 // Make sure that the top context does not change when doing callbacks or | 3591 // Make sure that the top context does not change when doing callbacks or |
3580 // interceptor calls. | 3592 // interceptor calls. |
3581 AssertNoContextChange ncc(it->isolate()); | 3593 AssertNoContextChange ncc(it->isolate()); |
3582 | 3594 |
3583 *found = true; | 3595 *found = true; |
3584 | 3596 |
3585 bool done = false; | 3597 bool done = false; |
3586 for (; it->IsFound(); it->Next()) { | 3598 for (; it->IsFound(); it->Next()) { |
3587 switch (it->state()) { | 3599 switch (it->state()) { |
3588 case LookupIterator::NOT_FOUND: | 3600 case LookupIterator::NOT_FOUND: |
3589 UNREACHABLE(); | 3601 UNREACHABLE(); |
3590 | 3602 |
3591 case LookupIterator::ACCESS_CHECK: | 3603 case LookupIterator::ACCESS_CHECK: |
3592 if (it->HasAccess()) break; | 3604 if (it->HasAccess()) break; |
3593 // Check whether it makes sense to reuse the lookup iterator. Here it | 3605 // Check whether it makes sense to reuse the lookup iterator. Here it |
3594 // might still call into setters up the prototype chain. | 3606 // might still call into setters up the prototype chain. |
3595 return JSObject::SetPropertyWithFailedAccessCheck(it, value); | 3607 return JSObject::SetPropertyWithFailedAccessCheck(it, value, |
3608 should_throw); | |
3596 | 3609 |
3597 case LookupIterator::JSPROXY: | 3610 case LookupIterator::JSPROXY: |
3598 if (it->HolderIsReceiverOrHiddenPrototype()) { | 3611 if (it->HolderIsReceiverOrHiddenPrototype()) { |
3599 return JSProxy::SetPropertyWithHandler( | 3612 return JSProxy::SetPropertyWithHandler( |
3600 it->GetHolder<JSProxy>(), it->GetReceiver(), it->GetName(), value, | 3613 it->GetHolder<JSProxy>(), it->GetReceiver(), it->GetName(), value, |
3601 language_mode); | 3614 language_mode, should_throw); |
3602 } else { | 3615 } else { |
3603 // TODO(verwaest): Use the MaybeHandle to indicate result. | 3616 // TODO(verwaest): Use the MaybeHandle to indicate result. |
3604 bool has_result = false; | 3617 bool has_result = false; |
3605 MaybeHandle<Object> maybe_result = | 3618 Maybe<bool> maybe_result = |
3606 JSProxy::SetPropertyViaPrototypesWithHandler( | 3619 JSProxy::SetPropertyViaPrototypesWithHandler( |
3607 it->GetHolder<JSProxy>(), it->GetReceiver(), it->GetName(), | 3620 it->GetHolder<JSProxy>(), it->GetReceiver(), it->GetName(), |
3608 value, language_mode, &has_result); | 3621 value, language_mode, should_throw, &has_result); |
3609 if (has_result) return maybe_result; | 3622 if (has_result) return maybe_result; |
3610 done = true; | 3623 done = true; |
3611 } | 3624 } |
3612 break; | 3625 break; |
3613 | 3626 |
3614 case LookupIterator::INTERCEPTOR: | 3627 case LookupIterator::INTERCEPTOR: |
3615 if (it->HolderIsReceiverOrHiddenPrototype()) { | 3628 if (it->HolderIsReceiverOrHiddenPrototype()) { |
3616 MaybeHandle<Object> maybe_result = | 3629 Maybe<bool> maybe_result = |
3617 JSObject::SetPropertyWithInterceptor(it, value); | 3630 JSObject::SetPropertyWithInterceptor(it, value, should_throw); |
3618 if (!maybe_result.is_null()) return maybe_result; | 3631 if (maybe_result.IsJust()) return maybe_result; |
3619 if (it->isolate()->has_pending_exception()) return maybe_result; | 3632 if (it->isolate()->has_pending_exception()) return maybe_result; |
3620 } else { | 3633 } else { |
3621 Maybe<PropertyAttributes> maybe_attributes = | 3634 Maybe<PropertyAttributes> maybe_attributes = |
3622 JSObject::GetPropertyAttributesWithInterceptor(it); | 3635 JSObject::GetPropertyAttributesWithInterceptor(it); |
3623 if (!maybe_attributes.IsJust()) return MaybeHandle<Object>(); | 3636 if (!maybe_attributes.IsJust()) return Nothing<bool>(); |
3624 done = maybe_attributes.FromJust() != ABSENT; | 3637 done = maybe_attributes.FromJust() != ABSENT; |
3625 if (done && (maybe_attributes.FromJust() & READ_ONLY) != 0) { | 3638 if (done && (maybe_attributes.FromJust() & READ_ONLY) != 0) { |
3626 return WriteToReadOnlyProperty(it, value, language_mode); | 3639 return WriteToReadOnlyProperty(it, value, language_mode, |
3640 should_throw); | |
3627 } | 3641 } |
3628 } | 3642 } |
3629 break; | 3643 break; |
3630 | 3644 |
3631 case LookupIterator::ACCESSOR: { | 3645 case LookupIterator::ACCESSOR: { |
3632 if (it->IsReadOnly()) { | 3646 if (it->IsReadOnly()) { |
3633 return WriteToReadOnlyProperty(it, value, language_mode); | 3647 return WriteToReadOnlyProperty(it, value, language_mode, |
3648 should_throw); | |
3634 } | 3649 } |
3635 Handle<Object> accessors = it->GetAccessors(); | 3650 Handle<Object> accessors = it->GetAccessors(); |
3636 if (accessors->IsAccessorInfo() && | 3651 if (accessors->IsAccessorInfo() && |
3637 !it->HolderIsReceiverOrHiddenPrototype() && | 3652 !it->HolderIsReceiverOrHiddenPrototype() && |
3638 AccessorInfo::cast(*accessors)->is_special_data_property()) { | 3653 AccessorInfo::cast(*accessors)->is_special_data_property()) { |
3639 done = true; | 3654 done = true; |
3640 break; | 3655 break; |
3641 } | 3656 } |
3642 return SetPropertyWithAccessor(it, value, language_mode); | 3657 return SetPropertyWithAccessor(it, value, language_mode, should_throw); |
3643 } | 3658 } |
3644 case LookupIterator::INTEGER_INDEXED_EXOTIC: | 3659 case LookupIterator::INTEGER_INDEXED_EXOTIC: |
3645 // TODO(verwaest): We should throw an exception. | 3660 // TODO(verwaest): We should throw an exception. |
3646 return value; | 3661 return Just(true); |
3647 | 3662 |
3648 case LookupIterator::DATA: | 3663 case LookupIterator::DATA: |
3649 if (it->IsReadOnly()) { | 3664 if (it->IsReadOnly()) { |
3650 return WriteToReadOnlyProperty(it, value, language_mode); | 3665 return WriteToReadOnlyProperty(it, value, language_mode, |
3666 should_throw); | |
3651 } | 3667 } |
3652 if (it->HolderIsReceiverOrHiddenPrototype()) { | 3668 if (it->HolderIsReceiverOrHiddenPrototype()) { |
3653 return SetDataProperty(it, value); | 3669 return SetDataProperty(it, value, should_throw); |
3654 } | 3670 } |
3655 done = true; | 3671 done = true; |
3656 break; | 3672 break; |
3657 | 3673 |
3658 case LookupIterator::TRANSITION: | 3674 case LookupIterator::TRANSITION: |
3659 done = true; | 3675 done = true; |
3660 break; | 3676 break; |
3661 } | 3677 } |
3662 | 3678 |
3663 if (done) break; | 3679 if (done) break; |
3664 } | 3680 } |
3665 | 3681 |
3666 // If the receiver is the JSGlobalObject, the store was contextual. In case | 3682 // If the receiver is the JSGlobalObject, the store was contextual. In case |
3667 // the property did not exist yet on the global object itself, we have to | 3683 // the property did not exist yet on the global object itself, we have to |
3668 // throw a reference error in strict mode. | 3684 // throw a reference error in strict mode. |
3669 if (it->GetReceiver()->IsJSGlobalObject() && is_strict(language_mode)) { | 3685 if (it->GetReceiver()->IsJSGlobalObject() && is_strict(language_mode)) { |
3670 THROW_NEW_ERROR(it->isolate(), | 3686 RETURN_FAILURE(it->isolate(), should_throw, |
3671 NewReferenceError(MessageTemplate::kNotDefined, it->name()), | 3687 NewReferenceError(MessageTemplate::kNotDefined, it->name())); |
3672 Object); | |
3673 } | 3688 } |
3674 | 3689 |
3675 *found = false; | 3690 *found = false; |
3676 return MaybeHandle<Object>(); | 3691 return Nothing<bool>(); |
3677 } | 3692 } |
3678 | 3693 |
3679 | 3694 |
3680 MaybeHandle<Object> Object::SetProperty(LookupIterator* it, | 3695 MaybeHandle<Object> Object::SetProperty(LookupIterator* it, |
3681 Handle<Object> value, | 3696 Handle<Object> value, |
3682 LanguageMode language_mode, | 3697 LanguageMode language_mode, |
3683 StoreFromKeyed store_mode) { | 3698 StoreFromKeyed store_mode) { |
3684 bool found = false; | 3699 Maybe<bool> result = |
3685 MaybeHandle<Object> result = | 3700 SetProperty(it, value, language_mode, THROW_ON_ERROR, store_mode); |
3686 SetPropertyInternal(it, value, language_mode, store_mode, &found); | 3701 return result.IsJust() ? value : MaybeHandle<Object>(); |
rossberg
2015/10/14 15:59:06
This pattern occurs several times, maybe introduce
| |
3687 if (found) return result; | |
3688 return AddDataProperty(it, value, NONE, language_mode, store_mode); | |
3689 } | 3702 } |
3690 | 3703 |
3691 | 3704 |
3705 Maybe<bool> Object::SetProperty(LookupIterator* it, Handle<Object> value, | |
3706 LanguageMode language_mode, | |
3707 ShouldThrow should_throw, | |
3708 StoreFromKeyed store_mode) { | |
3709 bool found = false; | |
3710 Maybe<bool> result = SetPropertyInternal(it, value, language_mode, | |
3711 should_throw, store_mode, &found); | |
3712 if (found) return result; | |
3713 return AddDataProperty(it, value, NONE, language_mode, should_throw, | |
3714 store_mode); | |
3715 } | |
3716 | |
3717 | |
3692 MaybeHandle<Object> Object::SetSuperProperty(LookupIterator* it, | 3718 MaybeHandle<Object> Object::SetSuperProperty(LookupIterator* it, |
3693 Handle<Object> value, | 3719 Handle<Object> value, |
3694 LanguageMode language_mode, | 3720 LanguageMode language_mode, |
3695 StoreFromKeyed store_mode) { | 3721 StoreFromKeyed store_mode) { |
3696 bool found = false; | 3722 bool found = false; |
3697 MaybeHandle<Object> result = | 3723 Maybe<bool> result = SetPropertyInternal(it, value, language_mode, |
3698 SetPropertyInternal(it, value, language_mode, store_mode, &found); | 3724 THROW_ON_ERROR, store_mode, &found); |
3699 if (found) return result; | 3725 if (found) return result.IsJust() ? value : MaybeHandle<Object>(); |
3700 | 3726 |
3701 if (!it->GetReceiver()->IsJSReceiver()) { | 3727 if (!it->GetReceiver()->IsJSReceiver()) { |
3702 return WriteToReadOnlyProperty(it, value, language_mode); | 3728 Maybe<bool> result = |
3729 WriteToReadOnlyProperty(it, value, language_mode, THROW_ON_ERROR); | |
3730 return result.IsJust() ? value : MaybeHandle<Object>(); | |
3703 } | 3731 } |
3704 | 3732 |
3705 LookupIterator::Configuration c = LookupIterator::OWN; | 3733 LookupIterator::Configuration c = LookupIterator::OWN; |
3706 LookupIterator own_lookup = | 3734 LookupIterator own_lookup = |
3707 it->IsElement() | 3735 it->IsElement() |
3708 ? LookupIterator(it->isolate(), it->GetReceiver(), it->index(), c) | 3736 ? LookupIterator(it->isolate(), it->GetReceiver(), it->index(), c) |
3709 : LookupIterator(it->GetReceiver(), it->name(), c); | 3737 : LookupIterator(it->GetReceiver(), it->name(), c); |
3710 | 3738 |
3711 for (; own_lookup.IsFound(); own_lookup.Next()) { | 3739 for (; own_lookup.IsFound(); own_lookup.Next()) { |
3712 switch (own_lookup.state()) { | 3740 switch (own_lookup.state()) { |
3713 case LookupIterator::ACCESS_CHECK: | 3741 case LookupIterator::ACCESS_CHECK: |
3714 if (!own_lookup.HasAccess()) { | 3742 if (!own_lookup.HasAccess()) { |
3715 return JSObject::SetPropertyWithFailedAccessCheck(&own_lookup, value); | 3743 Maybe<bool> result = JSObject::SetPropertyWithFailedAccessCheck( |
3744 &own_lookup, value, THROW_ON_ERROR); | |
3745 return result.IsJust() ? value : MaybeHandle<Object>(); | |
3716 } | 3746 } |
3717 break; | 3747 break; |
3718 | 3748 |
3719 case LookupIterator::INTEGER_INDEXED_EXOTIC: | 3749 case LookupIterator::INTEGER_INDEXED_EXOTIC: |
3720 return RedefineNonconfigurableProperty(it->isolate(), it->GetName(), | 3750 return RedefineNonconfigurableProperty(it->isolate(), it->GetName(), |
3721 value, language_mode); | 3751 value, language_mode); |
3722 | 3752 |
3723 case LookupIterator::DATA: { | 3753 case LookupIterator::DATA: { |
3724 PropertyDetails details = own_lookup.property_details(); | 3754 PropertyDetails details = own_lookup.property_details(); |
3725 if (details.IsConfigurable() || !details.IsReadOnly()) { | 3755 if (details.IsConfigurable() || !details.IsReadOnly()) { |
3726 return JSObject::DefineOwnPropertyIgnoreAttributes( | 3756 return JSObject::DefineOwnPropertyIgnoreAttributes( |
3727 &own_lookup, value, details.attributes()); | 3757 &own_lookup, value, details.attributes()); |
3728 } | 3758 } |
3729 return WriteToReadOnlyProperty(&own_lookup, value, language_mode); | 3759 Maybe<bool> result = WriteToReadOnlyProperty( |
3760 &own_lookup, value, language_mode, THROW_ON_ERROR); | |
3761 return result.IsJust() ? value : MaybeHandle<Object>(); | |
3730 } | 3762 } |
3731 | 3763 |
3732 case LookupIterator::ACCESSOR: { | 3764 case LookupIterator::ACCESSOR: { |
3733 PropertyDetails details = own_lookup.property_details(); | 3765 PropertyDetails details = own_lookup.property_details(); |
3734 if (details.IsConfigurable()) { | 3766 if (details.IsConfigurable()) { |
3735 return JSObject::DefineOwnPropertyIgnoreAttributes( | 3767 return JSObject::DefineOwnPropertyIgnoreAttributes( |
3736 &own_lookup, value, details.attributes()); | 3768 &own_lookup, value, details.attributes()); |
3737 } | 3769 } |
3738 | 3770 |
3739 return RedefineNonconfigurableProperty(it->isolate(), it->GetName(), | 3771 return RedefineNonconfigurableProperty(it->isolate(), it->GetName(), |
3740 value, language_mode); | 3772 value, language_mode); |
3741 } | 3773 } |
3742 | 3774 |
3743 case LookupIterator::INTERCEPTOR: | 3775 case LookupIterator::INTERCEPTOR: |
3744 case LookupIterator::JSPROXY: { | 3776 case LookupIterator::JSPROXY: { |
3745 bool found = false; | 3777 bool found = false; |
3746 MaybeHandle<Object> result = SetPropertyInternal( | 3778 Maybe<bool> result = |
3747 &own_lookup, value, language_mode, store_mode, &found); | 3779 SetPropertyInternal(&own_lookup, value, language_mode, |
3748 if (found) return result; | 3780 THROW_ON_ERROR, store_mode, &found); |
3781 if (found) return result.IsJust() ? value : MaybeHandle<Object>(); | |
3749 break; | 3782 break; |
3750 } | 3783 } |
3751 | 3784 |
3752 case LookupIterator::NOT_FOUND: | 3785 case LookupIterator::NOT_FOUND: |
3753 case LookupIterator::TRANSITION: | 3786 case LookupIterator::TRANSITION: |
3754 UNREACHABLE(); | 3787 UNREACHABLE(); |
3755 } | 3788 } |
3756 } | 3789 } |
3757 | 3790 |
3758 return JSObject::AddDataProperty(&own_lookup, value, NONE, language_mode, | 3791 return JSObject::AddDataProperty(&own_lookup, value, NONE, language_mode, |
(...skipping 19 matching lines...) Expand all Loading... | |
3778 if (is_strong(language_mode)) { | 3811 if (is_strong(language_mode)) { |
3779 THROW_NEW_ERROR( | 3812 THROW_NEW_ERROR( |
3780 isolate, | 3813 isolate, |
3781 NewTypeError(MessageTemplate::kStrongPropertyAccess, name, receiver), | 3814 NewTypeError(MessageTemplate::kStrongPropertyAccess, name, receiver), |
3782 Object); | 3815 Object); |
3783 } | 3816 } |
3784 return isolate->factory()->undefined_value(); | 3817 return isolate->factory()->undefined_value(); |
3785 } | 3818 } |
3786 | 3819 |
3787 | 3820 |
3788 MaybeHandle<Object> Object::CannotCreateProperty(LookupIterator* it, | 3821 Maybe<bool> Object::CannotCreateProperty(Isolate* isolate, |
3789 Handle<Object> value, | 3822 Handle<Object> receiver, |
3790 LanguageMode language_mode) { | 3823 Handle<Object> name, |
3791 return CannotCreateProperty(it->isolate(), it->GetReceiver(), it->GetName(), | 3824 Handle<Object> value, |
3792 value, language_mode); | 3825 LanguageMode language_mode, |
3826 ShouldThrow should_throw) { | |
3827 if (is_sloppy(language_mode)) return Just(true); | |
3828 RETURN_FAILURE( | |
3829 isolate, should_throw, | |
3830 NewTypeError(MessageTemplate::kStrictCannotCreateProperty, name, | |
3831 Object::TypeOf(isolate, receiver), receiver)); | |
3793 } | 3832 } |
3794 | 3833 |
3795 | 3834 |
3796 MaybeHandle<Object> Object::CannotCreateProperty(Isolate* isolate, | 3835 Maybe<bool> Object::WriteToReadOnlyProperty(LookupIterator* it, |
3797 Handle<Object> receiver, | 3836 Handle<Object> value, |
3798 Handle<Object> name, | 3837 LanguageMode language_mode, |
3799 Handle<Object> value, | 3838 ShouldThrow should_throw) { |
3800 LanguageMode language_mode) { | 3839 return WriteToReadOnlyProperty(it->isolate(), it->GetReceiver(), |
3801 if (is_sloppy(language_mode)) return value; | 3840 it->GetName(), value, language_mode, |
3802 Handle<String> typeof_string = Object::TypeOf(isolate, receiver); | 3841 should_throw); |
3803 THROW_NEW_ERROR(isolate, | |
3804 NewTypeError(MessageTemplate::kStrictCannotCreateProperty, | |
3805 name, typeof_string, receiver), | |
3806 Object); | |
3807 } | 3842 } |
3808 | 3843 |
3809 | 3844 |
3810 MaybeHandle<Object> Object::WriteToReadOnlyProperty( | 3845 Maybe<bool> Object::WriteToReadOnlyProperty(Isolate* isolate, |
3811 LookupIterator* it, Handle<Object> value, LanguageMode language_mode) { | 3846 Handle<Object> receiver, |
3812 return WriteToReadOnlyProperty(it->isolate(), it->GetReceiver(), | 3847 Handle<Object> name, |
3813 it->GetName(), value, language_mode); | 3848 Handle<Object> value, |
3849 LanguageMode language_mode, | |
3850 ShouldThrow should_throw) { | |
3851 if (is_sloppy(language_mode)) return Just(true); | |
3852 RETURN_FAILURE(isolate, should_throw, | |
3853 NewTypeError(MessageTemplate::kStrictReadOnlyProperty, name, | |
3854 Object::TypeOf(isolate, receiver), receiver)); | |
3814 } | 3855 } |
3815 | 3856 |
3816 | 3857 |
3817 MaybeHandle<Object> Object::WriteToReadOnlyProperty( | |
3818 Isolate* isolate, Handle<Object> receiver, Handle<Object> name, | |
3819 Handle<Object> value, LanguageMode language_mode) { | |
3820 if (is_sloppy(language_mode)) return value; | |
3821 Handle<String> typeof_string = Object::TypeOf(isolate, receiver); | |
3822 THROW_NEW_ERROR(isolate, | |
3823 NewTypeError(MessageTemplate::kStrictReadOnlyProperty, name, | |
3824 typeof_string, receiver), | |
3825 Object); | |
3826 } | |
3827 | |
3828 | |
3829 MaybeHandle<Object> Object::RedefineNonconfigurableProperty( | 3858 MaybeHandle<Object> Object::RedefineNonconfigurableProperty( |
3830 Isolate* isolate, Handle<Object> name, Handle<Object> value, | 3859 Isolate* isolate, Handle<Object> name, Handle<Object> value, |
3831 LanguageMode language_mode) { | 3860 LanguageMode language_mode) { |
3832 if (is_sloppy(language_mode)) return value; | 3861 if (is_sloppy(language_mode)) return value; |
3833 THROW_NEW_ERROR(isolate, | 3862 THROW_NEW_ERROR(isolate, |
3834 NewTypeError(MessageTemplate::kRedefineDisallowed, name), | 3863 NewTypeError(MessageTemplate::kRedefineDisallowed, name), |
3835 Object); | 3864 Object); |
3836 } | 3865 } |
3837 | 3866 |
3838 | 3867 |
3839 MaybeHandle<Object> Object::SetDataProperty(LookupIterator* it, | 3868 Maybe<bool> Object::SetDataProperty(LookupIterator* it, Handle<Object> value, |
3840 Handle<Object> value) { | 3869 ShouldThrow should_throw) { |
3841 // Proxies are handled on the WithHandler path. Other non-JSObjects cannot | 3870 // Proxies are handled on the WithHandler path. Other non-JSObjects cannot |
3842 // have own properties. | 3871 // have own properties. |
3843 Handle<JSObject> receiver = Handle<JSObject>::cast(it->GetReceiver()); | 3872 Handle<JSObject> receiver = Handle<JSObject>::cast(it->GetReceiver()); |
3844 | 3873 |
3845 // Store on the holder which may be hidden behind the receiver. | 3874 // Store on the holder which may be hidden behind the receiver. |
3846 DCHECK(it->HolderIsReceiverOrHiddenPrototype()); | 3875 DCHECK(it->HolderIsReceiverOrHiddenPrototype()); |
3847 | 3876 |
3848 // Old value for the observation change record. | 3877 // Old value for the observation change record. |
3849 // Fetch before transforming the object since the encoding may become | 3878 // Fetch before transforming the object since the encoding may become |
3850 // incompatible with what's cached in |it|. | 3879 // incompatible with what's cached in |it|. |
3851 bool is_observed = receiver->map()->is_observed() && | 3880 bool is_observed = receiver->map()->is_observed() && |
3852 (it->IsElement() || | 3881 (it->IsElement() || |
3853 !it->isolate()->IsInternallyUsedPropertyName(it->name())); | 3882 !it->isolate()->IsInternallyUsedPropertyName(it->name())); |
3854 MaybeHandle<Object> maybe_old; | 3883 MaybeHandle<Object> maybe_old; |
3855 if (is_observed) maybe_old = it->GetDataValue(); | 3884 if (is_observed) maybe_old = it->GetDataValue(); |
3856 | 3885 |
3857 Handle<Object> to_assign = value; | 3886 Handle<Object> to_assign = value; |
3858 // Convert the incoming value to a number for storing into typed arrays. | 3887 // Convert the incoming value to a number for storing into typed arrays. |
3859 if (it->IsElement() && receiver->HasFixedTypedArrayElements()) { | 3888 if (it->IsElement() && receiver->HasFixedTypedArrayElements()) { |
3860 if (!value->IsNumber() && !value->IsUndefined()) { | 3889 if (!value->IsNumber() && !value->IsUndefined()) { |
3861 ASSIGN_RETURN_ON_EXCEPTION(it->isolate(), to_assign, | 3890 ASSIGN_RETURN_ON_EXCEPTION_VALUE( |
3862 Object::ToNumber(value), Object); | 3891 it->isolate(), to_assign, Object::ToNumber(value), Nothing<bool>()); |
3863 // ToNumber above might modify the receiver, causing the cached | 3892 // ToNumber above might modify the receiver, causing the cached |
3864 // holder_map to mismatch the actual holder->map() after this point. | 3893 // holder_map to mismatch the actual holder->map() after this point. |
3865 // Reload the map to be in consistent state. Other cached state cannot | 3894 // Reload the map to be in consistent state. Other cached state cannot |
3866 // have been invalidated since typed array elements cannot be reconfigured | 3895 // have been invalidated since typed array elements cannot be reconfigured |
3867 // in any way. | 3896 // in any way. |
3868 it->ReloadHolderMap(); | 3897 it->ReloadHolderMap(); |
3869 | 3898 |
3870 // We have to recheck the length. However, it can only change if the | 3899 // We have to recheck the length. However, it can only change if the |
3871 // underlying buffer was neutered, so just check that. | 3900 // underlying buffer was neutered, so just check that. |
3872 if (Handle<JSArrayBufferView>::cast(receiver)->WasNeutered()) { | 3901 if (Handle<JSArrayBufferView>::cast(receiver)->WasNeutered()) { |
3873 return value; | 3902 return Just(true); |
3903 // TODO(neis): According to the spec, this should throw a TypeError. | |
3874 } | 3904 } |
3875 } | 3905 } |
3876 } | 3906 } |
3877 | 3907 |
3878 // Possibly migrate to the most up-to-date map that will be able to store | 3908 // Possibly migrate to the most up-to-date map that will be able to store |
3879 // |value| under it->name(). | 3909 // |value| under it->name(). |
3880 it->PrepareForDataProperty(to_assign); | 3910 it->PrepareForDataProperty(to_assign); |
3881 | 3911 |
3882 // Write the property value. | 3912 // Write the property value. |
3883 it->WriteDataValue(to_assign); | 3913 it->WriteDataValue(to_assign); |
3884 | 3914 |
3885 // Send the change record if there are observers. | 3915 // Send the change record if there are observers. |
3886 if (is_observed && !value->SameValue(*maybe_old.ToHandleChecked())) { | 3916 if (is_observed && !value->SameValue(*maybe_old.ToHandleChecked())) { |
3887 RETURN_ON_EXCEPTION(it->isolate(), JSObject::EnqueueChangeRecord( | 3917 RETURN_ON_EXCEPTION_VALUE( |
3888 receiver, "update", it->GetName(), | 3918 it->isolate(), |
3889 maybe_old.ToHandleChecked()), | 3919 JSObject::EnqueueChangeRecord(receiver, "update", it->GetName(), |
3890 Object); | 3920 maybe_old.ToHandleChecked()), |
3921 Nothing<bool>()); | |
3891 } | 3922 } |
3892 | 3923 |
3893 #if VERIFY_HEAP | 3924 #if VERIFY_HEAP |
3894 if (FLAG_verify_heap) { | 3925 if (FLAG_verify_heap) { |
3895 receiver->JSObjectVerify(); | 3926 receiver->JSObjectVerify(); |
3896 } | 3927 } |
3897 #endif | 3928 #endif |
3898 return value; | 3929 return Just(true); |
3899 } | 3930 } |
3900 | 3931 |
3901 | 3932 |
3902 MUST_USE_RESULT static MaybeHandle<Object> BeginPerformSplice( | 3933 MUST_USE_RESULT static MaybeHandle<Object> BeginPerformSplice( |
3903 Handle<JSArray> object) { | 3934 Handle<JSArray> object) { |
3904 Isolate* isolate = object->GetIsolate(); | 3935 Isolate* isolate = object->GetIsolate(); |
3905 HandleScope scope(isolate); | 3936 HandleScope scope(isolate); |
3906 Handle<Object> args[] = {object}; | 3937 Handle<Object> args[] = {object}; |
3907 | 3938 |
3908 return Execution::Call( | 3939 return Execution::Call( |
(...skipping 29 matching lines...) Expand all Loading... | |
3938 isolate, Handle<JSFunction>(isolate->observers_enqueue_splice()), | 3969 isolate, Handle<JSFunction>(isolate->observers_enqueue_splice()), |
3939 isolate->factory()->undefined_value(), arraysize(args), args); | 3970 isolate->factory()->undefined_value(), arraysize(args), args); |
3940 } | 3971 } |
3941 | 3972 |
3942 | 3973 |
3943 MaybeHandle<Object> Object::AddDataProperty(LookupIterator* it, | 3974 MaybeHandle<Object> Object::AddDataProperty(LookupIterator* it, |
3944 Handle<Object> value, | 3975 Handle<Object> value, |
3945 PropertyAttributes attributes, | 3976 PropertyAttributes attributes, |
3946 LanguageMode language_mode, | 3977 LanguageMode language_mode, |
3947 StoreFromKeyed store_mode) { | 3978 StoreFromKeyed store_mode) { |
3979 Maybe<bool> result = AddDataProperty(it, value, attributes, language_mode, | |
3980 THROW_ON_ERROR, store_mode); | |
3981 return result.IsJust() ? value : MaybeHandle<Object>(); | |
3982 } | |
3983 | |
3984 | |
3985 Maybe<bool> Object::AddDataProperty(LookupIterator* it, Handle<Object> value, | |
3986 PropertyAttributes attributes, | |
3987 LanguageMode language_mode, | |
3988 ShouldThrow should_throw, | |
3989 StoreFromKeyed store_mode) { | |
3948 DCHECK(!it->GetReceiver()->IsJSProxy()); | 3990 DCHECK(!it->GetReceiver()->IsJSProxy()); |
3949 if (!it->GetReceiver()->IsJSObject()) { | 3991 if (!it->GetReceiver()->IsJSObject()) { |
3950 return CannotCreateProperty(it, value, language_mode); | 3992 return CannotCreateProperty(it->isolate(), it->GetReceiver(), it->GetName(), |
3993 value, language_mode, should_throw); | |
3951 } | 3994 } |
3952 | 3995 |
3953 DCHECK_NE(LookupIterator::INTEGER_INDEXED_EXOTIC, it->state()); | 3996 DCHECK_NE(LookupIterator::INTEGER_INDEXED_EXOTIC, it->state()); |
3954 | 3997 |
3955 Handle<JSObject> receiver = it->GetStoreTarget(); | 3998 Handle<JSObject> receiver = it->GetStoreTarget(); |
3956 | 3999 |
3957 // If the receiver is a JSGlobalProxy, store on the prototype (JSGlobalObject) | 4000 // If the receiver is a JSGlobalProxy, store on the prototype (JSGlobalObject) |
3958 // instead. If the prototype is Null, the proxy is detached. | 4001 // instead. If the prototype is Null, the proxy is detached. |
3959 if (receiver->IsJSGlobalProxy()) return value; | 4002 if (receiver->IsJSGlobalProxy()) return Just(true); |
3960 | 4003 |
3961 Isolate* isolate = it->isolate(); | 4004 Isolate* isolate = it->isolate(); |
3962 | 4005 |
3963 if (!receiver->map()->is_extensible() && | 4006 if (!receiver->map()->is_extensible() && |
3964 (it->IsElement() || !isolate->IsInternallyUsedPropertyName(it->name()))) { | 4007 (it->IsElement() || !isolate->IsInternallyUsedPropertyName(it->name()))) { |
3965 if (is_sloppy(language_mode)) return value; | 4008 if (is_sloppy(language_mode)) return Just(true); |
3966 THROW_NEW_ERROR(isolate, NewTypeError(MessageTemplate::kObjectNotExtensible, | 4009 RETURN_FAILURE( |
3967 it->GetName()), | 4010 isolate, should_throw, |
3968 Object); | 4011 NewTypeError(MessageTemplate::kObjectNotExtensible, it->GetName())); |
3969 } | 4012 } |
3970 | 4013 |
3971 if (it->IsElement()) { | 4014 if (it->IsElement()) { |
3972 if (receiver->IsJSArray()) { | 4015 if (receiver->IsJSArray()) { |
3973 Handle<JSArray> array = Handle<JSArray>::cast(receiver); | 4016 Handle<JSArray> array = Handle<JSArray>::cast(receiver); |
3974 if (JSArray::WouldChangeReadOnlyLength(array, it->index())) { | 4017 if (JSArray::WouldChangeReadOnlyLength(array, it->index())) { |
3975 if (is_sloppy(language_mode)) return value; | 4018 if (is_sloppy(language_mode)) return Just(true); |
3976 return JSArray::ReadOnlyLengthError(array); | 4019 RETURN_FAILURE(array->GetIsolate(), should_throw, |
4020 NewTypeError(MessageTemplate::kStrictReadOnlyProperty, | |
4021 isolate->factory()->length_string(), | |
4022 Object::TypeOf(isolate, array), array)); | |
3977 } | 4023 } |
3978 | 4024 |
3979 if (FLAG_trace_external_array_abuse && | 4025 if (FLAG_trace_external_array_abuse && |
3980 array->HasFixedTypedArrayElements()) { | 4026 array->HasFixedTypedArrayElements()) { |
3981 CheckArrayAbuse(array, "typed elements write", it->index(), true); | 4027 CheckArrayAbuse(array, "typed elements write", it->index(), true); |
3982 } | 4028 } |
3983 | 4029 |
3984 if (FLAG_trace_js_array_abuse && !array->HasFixedTypedArrayElements()) { | 4030 if (FLAG_trace_js_array_abuse && !array->HasFixedTypedArrayElements()) { |
3985 CheckArrayAbuse(array, "elements write", it->index(), false); | 4031 CheckArrayAbuse(array, "elements write", it->index(), false); |
3986 } | 4032 } |
3987 } | 4033 } |
3988 | 4034 |
3989 MaybeHandle<Object> result = | 4035 Maybe<bool> result = JSObject::AddDataElement(receiver, it->index(), value, |
3990 JSObject::AddDataElement(receiver, it->index(), value, attributes); | 4036 attributes, should_throw); |
3991 JSObject::ValidateElements(receiver); | 4037 JSObject::ValidateElements(receiver); |
3992 return result; | 4038 return result; |
3993 } else { | 4039 } else { |
3994 // Migrate to the most up-to-date map that will be able to store |value| | 4040 // Migrate to the most up-to-date map that will be able to store |value| |
3995 // under it->name() with |attributes|. | 4041 // under it->name() with |attributes|. |
3996 it->PrepareTransitionToDataProperty(value, attributes, store_mode); | 4042 it->PrepareTransitionToDataProperty(value, attributes, store_mode); |
3997 DCHECK_EQ(LookupIterator::TRANSITION, it->state()); | 4043 DCHECK_EQ(LookupIterator::TRANSITION, it->state()); |
3998 it->ApplyTransitionToDataProperty(); | 4044 it->ApplyTransitionToDataProperty(); |
3999 | 4045 |
4000 // TODO(verwaest): Encapsulate dictionary handling better. | 4046 // TODO(verwaest): Encapsulate dictionary handling better. |
4001 if (receiver->map()->is_dictionary_map()) { | 4047 if (receiver->map()->is_dictionary_map()) { |
4002 // TODO(verwaest): Probably should ensure this is done beforehand. | 4048 // TODO(verwaest): Probably should ensure this is done beforehand. |
4003 it->InternalizeName(); | 4049 it->InternalizeName(); |
4004 // TODO(dcarney): just populate TransitionPropertyCell here? | 4050 // TODO(dcarney): just populate TransitionPropertyCell here? |
4005 JSObject::AddSlowProperty(receiver, it->name(), value, attributes); | 4051 JSObject::AddSlowProperty(receiver, it->name(), value, attributes); |
4006 } else { | 4052 } else { |
4007 // Write the property value. | 4053 // Write the property value. |
4008 it->WriteDataValue(value); | 4054 it->WriteDataValue(value); |
4009 } | 4055 } |
4010 | 4056 |
4011 // Send the change record if there are observers. | 4057 // Send the change record if there are observers. |
4012 if (receiver->map()->is_observed() && | 4058 if (receiver->map()->is_observed() && |
4013 !isolate->IsInternallyUsedPropertyName(it->name())) { | 4059 !isolate->IsInternallyUsedPropertyName(it->name())) { |
4014 RETURN_ON_EXCEPTION(isolate, JSObject::EnqueueChangeRecord( | 4060 RETURN_ON_EXCEPTION_VALUE(isolate, JSObject::EnqueueChangeRecord( |
4015 receiver, "add", it->name(), | 4061 receiver, "add", it->name(), |
4016 it->factory()->the_hole_value()), | 4062 it->factory()->the_hole_value()), |
4017 Object); | 4063 Nothing<bool>()); |
4018 } | 4064 } |
4019 #if VERIFY_HEAP | 4065 #if VERIFY_HEAP |
4020 if (FLAG_verify_heap) { | 4066 if (FLAG_verify_heap) { |
4021 receiver->JSObjectVerify(); | 4067 receiver->JSObjectVerify(); |
4022 } | 4068 } |
4023 #endif | 4069 #endif |
4024 } | 4070 } |
4025 | 4071 |
4026 return value; | 4072 return Just(true); |
4027 } | 4073 } |
4028 | 4074 |
4029 | 4075 |
4030 void Map::EnsureDescriptorSlack(Handle<Map> map, int slack) { | 4076 void Map::EnsureDescriptorSlack(Handle<Map> map, int slack) { |
4031 // Only supports adding slack to owned descriptors. | 4077 // Only supports adding slack to owned descriptors. |
4032 DCHECK(map->owns_descriptors()); | 4078 DCHECK(map->owns_descriptors()); |
4033 | 4079 |
4034 Handle<DescriptorArray> descriptors(map->instance_descriptors()); | 4080 Handle<DescriptorArray> descriptors(map->instance_descriptors()); |
4035 int old_size = map->NumberOfOwnDescriptors(); | 4081 int old_size = map->NumberOfOwnDescriptors(); |
4036 if (slack <= descriptors->NumberOfSlackDescriptors()) return; | 4082 if (slack <= descriptors->NumberOfSlackDescriptors()) return; |
(...skipping 331 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4368 Handle<Object> result; | 4414 Handle<Object> result; |
4369 ASSIGN_RETURN_ON_EXCEPTION_VALUE( | 4415 ASSIGN_RETURN_ON_EXCEPTION_VALUE( |
4370 isolate, result, CallTrap(proxy, "has", isolate->derived_has_trap(), | 4416 isolate, result, CallTrap(proxy, "has", isolate->derived_has_trap(), |
4371 arraysize(args), args), | 4417 arraysize(args), args), |
4372 Nothing<bool>()); | 4418 Nothing<bool>()); |
4373 | 4419 |
4374 return Just(result->BooleanValue()); | 4420 return Just(result->BooleanValue()); |
4375 } | 4421 } |
4376 | 4422 |
4377 | 4423 |
4378 MaybeHandle<Object> JSProxy::SetPropertyWithHandler( | 4424 Maybe<bool> JSProxy::SetPropertyWithHandler(Handle<JSProxy> proxy, |
4379 Handle<JSProxy> proxy, Handle<Object> receiver, Handle<Name> name, | 4425 Handle<Object> receiver, |
4380 Handle<Object> value, LanguageMode language_mode) { | 4426 Handle<Name> name, |
4427 Handle<Object> value, | |
4428 LanguageMode language_mode, | |
4429 ShouldThrow should_throw) { | |
4381 Isolate* isolate = proxy->GetIsolate(); | 4430 Isolate* isolate = proxy->GetIsolate(); |
4382 | 4431 |
4383 // TODO(rossberg): adjust once there is a story for symbols vs proxies. | 4432 // TODO(rossberg): adjust once there is a story for symbols vs proxies. |
4384 if (name->IsSymbol()) return value; | 4433 if (name->IsSymbol()) return Just(false); |
4385 | 4434 |
4386 Handle<Object> args[] = { receiver, name, value }; | 4435 Handle<Object> args[] = { receiver, name, value }; |
4387 RETURN_ON_EXCEPTION( | 4436 RETURN_ON_EXCEPTION_VALUE(isolate, |
4388 isolate, | 4437 CallTrap(proxy, "set", isolate->derived_set_trap(), |
4389 CallTrap(proxy, | 4438 arraysize(args), args), |
4390 "set", | 4439 Nothing<bool>()); |
4391 isolate->derived_set_trap(), | |
4392 arraysize(args), | |
4393 args), | |
4394 Object); | |
4395 | 4440 |
4396 return value; | 4441 return Just(false); |
4442 | |
4443 // TODO(neis): This needs to be made spec-conformant, eg as follows: | |
4444 /* | |
Toon Verwaest
2015/10/20 15:25:06
I wouldn't add this commented out code. Open an is
neis
2015/10/21 14:42:25
Done.
| |
4445 Handle<Object> result; | |
4446 ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, result, | |
4447 CallTrap(proxy, "set", | |
4448 isolate->derived_set_trap(), | |
4449 arraysize(args), args), | |
4450 Nothing<bool>()); | |
4451 Handle<Object> handler(proxy->handler(), isolate); | |
4452 if (result->BooleanValue()) return Just(true); | |
4453 RETURN_FAILURE(isolate, should_throw, NewTypeError( | |
4454 MessageTemplate::kProxyHandlerReturned, handler, result, | |
4455 isolate->factory()->InternalizeUtf8String("set"))); | |
4456 */ | |
4397 } | 4457 } |
4398 | 4458 |
4399 | 4459 |
4400 MaybeHandle<Object> JSProxy::SetPropertyViaPrototypesWithHandler( | 4460 Maybe<bool> JSProxy::SetPropertyViaPrototypesWithHandler( |
4401 Handle<JSProxy> proxy, Handle<Object> receiver, Handle<Name> name, | 4461 Handle<JSProxy> proxy, Handle<Object> receiver, Handle<Name> name, |
4402 Handle<Object> value, LanguageMode language_mode, bool* done) { | 4462 Handle<Object> value, LanguageMode language_mode, ShouldThrow should_throw, |
4463 bool* done) { | |
4403 Isolate* isolate = proxy->GetIsolate(); | 4464 Isolate* isolate = proxy->GetIsolate(); |
4404 Handle<Object> handler(proxy->handler(), isolate); // Trap might morph proxy. | 4465 Handle<Object> handler(proxy->handler(), isolate); // Trap might morph proxy. |
4405 | 4466 |
4406 // TODO(rossberg): adjust once there is a story for symbols vs proxies. | 4467 // TODO(rossberg): adjust once there is a story for symbols vs proxies. |
4407 if (name->IsSymbol()) { | 4468 if (name->IsSymbol()) { |
4408 *done = false; | 4469 *done = false; // Return value will be ignored. |
4409 return isolate->factory()->the_hole_value(); | 4470 return Nothing<bool>(); |
4410 } | 4471 } |
4411 | 4472 |
4412 *done = true; // except where redefined... | 4473 *done = true; // except where redefined... |
4413 Handle<Object> args[] = { name }; | 4474 Handle<Object> args[] = { name }; |
4414 Handle<Object> result; | 4475 Handle<Object> result; |
4415 ASSIGN_RETURN_ON_EXCEPTION( | 4476 ASSIGN_RETURN_ON_EXCEPTION_VALUE( |
4416 isolate, result, | 4477 isolate, result, CallTrap(proxy, "getPropertyDescriptor", |
4417 CallTrap(proxy, | 4478 Handle<Object>(), arraysize(args), args), |
4418 "getPropertyDescriptor", | 4479 Nothing<bool>()); |
4419 Handle<Object>(), | |
4420 arraysize(args), | |
4421 args), | |
4422 Object); | |
4423 | 4480 |
4424 if (result->IsUndefined()) { | 4481 if (result->IsUndefined()) { |
4425 *done = false; | 4482 *done = false; // Return value will be ignored. |
4426 return isolate->factory()->the_hole_value(); | 4483 return Nothing<bool>(); |
4427 } | 4484 } |
4428 | 4485 |
4429 // Emulate [[GetProperty]] semantics for proxies. | 4486 // Emulate [[GetProperty]] semantics for proxies. |
4430 Handle<Object> argv[] = { result }; | 4487 Handle<Object> argv[] = { result }; |
4431 Handle<Object> desc; | 4488 Handle<Object> desc; |
4432 ASSIGN_RETURN_ON_EXCEPTION( | 4489 ASSIGN_RETURN_ON_EXCEPTION_VALUE( |
4433 isolate, desc, | 4490 isolate, desc, |
4434 Execution::Call(isolate, | 4491 Execution::Call(isolate, isolate->to_complete_property_descriptor(), |
4435 isolate->to_complete_property_descriptor(), | 4492 result, arraysize(argv), argv), |
4436 result, | 4493 Nothing<bool>()); |
4437 arraysize(argv), | |
4438 argv), | |
4439 Object); | |
4440 | 4494 |
4441 // [[GetProperty]] requires to check that all properties are configurable. | 4495 // [[GetProperty]] requires to check that all properties are configurable. |
4442 Handle<String> configurable_name = | 4496 Handle<String> configurable_name = |
4443 isolate->factory()->InternalizeOneByteString( | 4497 isolate->factory()->InternalizeOneByteString( |
4444 STATIC_CHAR_VECTOR("configurable_")); | 4498 STATIC_CHAR_VECTOR("configurable_")); |
4445 Handle<Object> configurable = | 4499 Handle<Object> configurable = |
4446 Object::GetProperty(desc, configurable_name).ToHandleChecked(); | 4500 Object::GetProperty(desc, configurable_name).ToHandleChecked(); |
4447 DCHECK(configurable->IsBoolean()); | 4501 DCHECK(configurable->IsBoolean()); |
4448 if (configurable->IsFalse()) { | 4502 if (configurable->IsFalse()) { |
4449 Handle<String> trap = isolate->factory()->InternalizeOneByteString( | 4503 RETURN_FAILURE( |
4450 STATIC_CHAR_VECTOR("getPropertyDescriptor")); | 4504 isolate, should_throw, |
4451 THROW_NEW_ERROR(isolate, | 4505 NewTypeError(MessageTemplate::kProxyPropNotConfigurable, handler, name, |
4452 NewTypeError(MessageTemplate::kProxyPropNotConfigurable, | 4506 isolate->factory()->NewStringFromAsciiChecked( |
4453 handler, name, trap), | 4507 "getPropertyDescriptor"))); |
4454 Object); | |
4455 } | 4508 } |
4456 DCHECK(configurable->IsTrue()); | 4509 DCHECK(configurable->IsTrue()); |
4457 | 4510 |
4458 // Check for DataDescriptor. | 4511 // Check for DataDescriptor. |
4459 Handle<String> hasWritable_name = | 4512 Handle<String> hasWritable_name = |
4460 isolate->factory()->InternalizeOneByteString( | 4513 isolate->factory()->InternalizeOneByteString( |
4461 STATIC_CHAR_VECTOR("hasWritable_")); | 4514 STATIC_CHAR_VECTOR("hasWritable_")); |
4462 Handle<Object> hasWritable = | 4515 Handle<Object> hasWritable = |
4463 Object::GetProperty(desc, hasWritable_name).ToHandleChecked(); | 4516 Object::GetProperty(desc, hasWritable_name).ToHandleChecked(); |
4464 DCHECK(hasWritable->IsBoolean()); | 4517 DCHECK(hasWritable->IsBoolean()); |
4465 if (hasWritable->IsTrue()) { | 4518 if (hasWritable->IsTrue()) { |
4466 Handle<String> writable_name = isolate->factory()->InternalizeOneByteString( | 4519 Handle<String> writable_name = isolate->factory()->InternalizeOneByteString( |
4467 STATIC_CHAR_VECTOR("writable_")); | 4520 STATIC_CHAR_VECTOR("writable_")); |
4468 Handle<Object> writable = | 4521 Handle<Object> writable = |
4469 Object::GetProperty(desc, writable_name).ToHandleChecked(); | 4522 Object::GetProperty(desc, writable_name).ToHandleChecked(); |
4470 DCHECK(writable->IsBoolean()); | 4523 DCHECK(writable->IsBoolean()); |
4471 *done = writable->IsFalse(); | 4524 *done = writable->IsFalse(); |
4472 if (!*done) return isolate->factory()->the_hole_value(); | 4525 if (!*done) return Nothing<bool>(); // Return value will be ignored. |
4473 return WriteToReadOnlyProperty(isolate, receiver, name, value, | 4526 return WriteToReadOnlyProperty(isolate, receiver, name, value, |
4474 language_mode); | 4527 language_mode, should_throw); |
4475 } | 4528 } |
4476 | 4529 |
4477 // We have an AccessorDescriptor. | 4530 // We have an AccessorDescriptor. |
4478 Handle<String> set_name = | 4531 Handle<String> set_name = |
4479 isolate->factory()->InternalizeOneByteString(STATIC_CHAR_VECTOR("set_")); | 4532 isolate->factory()->InternalizeOneByteString(STATIC_CHAR_VECTOR("set_")); |
4480 Handle<Object> setter = Object::GetProperty(desc, set_name).ToHandleChecked(); | 4533 Handle<Object> setter = Object::GetProperty(desc, set_name).ToHandleChecked(); |
4481 if (!setter->IsUndefined()) { | 4534 if (!setter->IsUndefined()) { |
4482 // TODO(rossberg): nicer would be to cast to some JSCallable here... | 4535 // TODO(rossberg): nicer would be to cast to some JSCallable here... |
4483 return SetPropertyWithDefinedSetter( | 4536 return SetPropertyWithDefinedSetter( |
4484 receiver, Handle<JSReceiver>::cast(setter), value); | 4537 receiver, Handle<JSReceiver>::cast(setter), value, should_throw); |
4485 } | 4538 } |
4486 | 4539 |
4487 if (is_sloppy(language_mode)) return value; | 4540 if (is_sloppy(language_mode)) return Just(true); |
4488 THROW_NEW_ERROR( | 4541 RETURN_FAILURE( |
4489 isolate, NewTypeError(MessageTemplate::kNoSetterInCallback, name, proxy), | 4542 isolate, should_throw, |
4490 Object); | 4543 NewTypeError(MessageTemplate::kNoSetterInCallback, name, proxy)); |
4491 } | 4544 } |
4492 | 4545 |
4493 | 4546 |
4494 MaybeHandle<Object> JSProxy::DeletePropertyWithHandler( | 4547 MaybeHandle<Object> JSProxy::DeletePropertyWithHandler( |
4495 Handle<JSProxy> proxy, Handle<Name> name, LanguageMode language_mode) { | 4548 Handle<JSProxy> proxy, Handle<Name> name, LanguageMode language_mode) { |
4496 Isolate* isolate = proxy->GetIsolate(); | 4549 Isolate* isolate = proxy->GetIsolate(); |
4497 | 4550 |
4498 // TODO(rossberg): adjust once there is a story for symbols vs proxies. | 4551 // TODO(rossberg): adjust once there is a story for symbols vs proxies. |
4499 if (name->IsSymbol()) return isolate->factory()->false_value(); | 4552 if (name->IsSymbol()) return isolate->factory()->false_value(); |
4500 | 4553 |
(...skipping 259 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4760 // If there's an interceptor, try to store the property with the | 4813 // If there's an interceptor, try to store the property with the |
4761 // interceptor. | 4814 // interceptor. |
4762 // In case of success, the attributes will have been reset to the default | 4815 // In case of success, the attributes will have been reset to the default |
4763 // attributes of the interceptor, rather than the incoming attributes. | 4816 // attributes of the interceptor, rather than the incoming attributes. |
4764 // | 4817 // |
4765 // TODO(verwaest): JSProxy afterwards verify the attributes that the | 4818 // TODO(verwaest): JSProxy afterwards verify the attributes that the |
4766 // JSProxy claims it has, and verifies that they are compatible. If not, | 4819 // JSProxy claims it has, and verifies that they are compatible. If not, |
4767 // they throw. Here we should do the same. | 4820 // they throw. Here we should do the same. |
4768 case LookupIterator::INTERCEPTOR: | 4821 case LookupIterator::INTERCEPTOR: |
4769 if (handling == DONT_FORCE_FIELD) { | 4822 if (handling == DONT_FORCE_FIELD) { |
4770 MaybeHandle<Object> maybe_result = | 4823 Maybe<bool> result = |
4771 JSObject::SetPropertyWithInterceptor(it, value); | 4824 JSObject::SetPropertyWithInterceptor(it, value, THROW_ON_ERROR); |
4772 if (!maybe_result.is_null()) return maybe_result; | 4825 if (result.IsJust()) return value; |
4773 if (it->isolate()->has_pending_exception()) return maybe_result; | 4826 if (it->isolate()->has_pending_exception()) |
4827 return MaybeHandle<Object>(); | |
4774 } | 4828 } |
4775 break; | 4829 break; |
4776 | 4830 |
4777 case LookupIterator::ACCESSOR: { | 4831 case LookupIterator::ACCESSOR: { |
4778 Handle<Object> accessors = it->GetAccessors(); | 4832 Handle<Object> accessors = it->GetAccessors(); |
4779 | 4833 |
4780 // Special handling for ExecutableAccessorInfo, which behaves like a | 4834 // Special handling for ExecutableAccessorInfo, which behaves like a |
4781 // data property. | 4835 // data property. |
4782 if (accessors->IsExecutableAccessorInfo() && | 4836 if (accessors->IsExecutableAccessorInfo() && |
4783 handling == DONT_FORCE_FIELD) { | 4837 handling == DONT_FORCE_FIELD) { |
4784 PropertyDetails details = it->property_details(); | 4838 PropertyDetails details = it->property_details(); |
4785 // Ensure the context isn't changed after calling into accessors. | 4839 // Ensure the context isn't changed after calling into accessors. |
4786 AssertNoContextChange ncc(it->isolate()); | 4840 AssertNoContextChange ncc(it->isolate()); |
4787 | 4841 |
4788 Handle<Object> result; | 4842 Maybe<bool> result = JSObject::SetPropertyWithAccessor( |
4789 ASSIGN_RETURN_ON_EXCEPTION( | 4843 it, value, STRICT, THROW_ON_ERROR); |
4790 it->isolate(), result, | 4844 if (result.IsNothing()) return MaybeHandle<Object>(); |
4791 JSObject::SetPropertyWithAccessor(it, value, STRICT), Object); | |
4792 DCHECK(result->SameValue(*value)); | |
4793 | 4845 |
4794 if (details.attributes() == attributes) return value; | 4846 if (details.attributes() == attributes) return value; |
4795 | 4847 |
4796 // Reconfigure the accessor if attributes mismatch. | 4848 // Reconfigure the accessor if attributes mismatch. |
4797 Handle<ExecutableAccessorInfo> new_data = Accessors::CloneAccessor( | 4849 Handle<ExecutableAccessorInfo> new_data = Accessors::CloneAccessor( |
4798 it->isolate(), Handle<ExecutableAccessorInfo>::cast(accessors)); | 4850 it->isolate(), Handle<ExecutableAccessorInfo>::cast(accessors)); |
4799 new_data->set_property_attributes(attributes); | 4851 new_data->set_property_attributes(attributes); |
4800 // By clearing the setter we don't have to introduce a lookup to | 4852 // By clearing the setter we don't have to introduce a lookup to |
4801 // the setter, simply make it unavailable to reflect the | 4853 // the setter, simply make it unavailable to reflect the |
4802 // attributes. | 4854 // attributes. |
(...skipping 18 matching lines...) Expand all Loading... | |
4821 } | 4873 } |
4822 case LookupIterator::INTEGER_INDEXED_EXOTIC: | 4874 case LookupIterator::INTEGER_INDEXED_EXOTIC: |
4823 return RedefineNonconfigurableProperty(it->isolate(), it->GetName(), | 4875 return RedefineNonconfigurableProperty(it->isolate(), it->GetName(), |
4824 value, STRICT); | 4876 value, STRICT); |
4825 | 4877 |
4826 case LookupIterator::DATA: { | 4878 case LookupIterator::DATA: { |
4827 PropertyDetails details = it->property_details(); | 4879 PropertyDetails details = it->property_details(); |
4828 Handle<Object> old_value = it->factory()->the_hole_value(); | 4880 Handle<Object> old_value = it->factory()->the_hole_value(); |
4829 // Regular property update if the attributes match. | 4881 // Regular property update if the attributes match. |
4830 if (details.attributes() == attributes) { | 4882 if (details.attributes() == attributes) { |
4831 return SetDataProperty(it, value); | 4883 Maybe<bool> result = SetDataProperty(it, value, THROW_ON_ERROR); |
4884 return result.IsJust() ? value : MaybeHandle<Object>(); | |
4832 } | 4885 } |
4833 | 4886 |
4834 // Special case: properties of typed arrays cannot be reconfigured to | 4887 // Special case: properties of typed arrays cannot be reconfigured to |
4835 // non-writable nor to non-enumerable. | 4888 // non-writable nor to non-enumerable. |
4836 if (it->IsElement() && object->HasFixedTypedArrayElements()) { | 4889 if (it->IsElement() && object->HasFixedTypedArrayElements()) { |
4837 return RedefineNonconfigurableProperty(it->isolate(), it->GetName(), | 4890 return RedefineNonconfigurableProperty(it->isolate(), it->GetName(), |
4838 value, STRICT); | 4891 value, STRICT); |
4839 } | 4892 } |
4840 | 4893 |
4841 // Reconfigure the data property if the attributes mismatch. | 4894 // Reconfigure the data property if the attributes mismatch. |
(...skipping 1869 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
6711 | 6764 |
6712 return context->extension_object()->ReferencesObject(obj); | 6765 return context->extension_object()->ReferencesObject(obj); |
6713 } | 6766 } |
6714 } | 6767 } |
6715 | 6768 |
6716 // No references to object. | 6769 // No references to object. |
6717 return false; | 6770 return false; |
6718 } | 6771 } |
6719 | 6772 |
6720 | 6773 |
6774 static MaybeHandle<Object> ReturnObjectOrThrowTypeError( | |
6775 Handle<JSObject> object, Maybe<bool> maybe, MessageTemplate::Template msg) { | |
6776 if (!maybe.IsJust()) return MaybeHandle<Object>(); | |
6777 if (maybe.FromJust()) return object; | |
6778 Isolate* isolate = object->GetIsolate(); | |
6779 THROW_NEW_ERROR(isolate, NewTypeError(msg), Object); | |
6780 } | |
6781 | |
6782 | |
6721 Maybe<bool> JSObject::PreventExtensionsInternal(Handle<JSObject> object) { | 6783 Maybe<bool> JSObject::PreventExtensionsInternal(Handle<JSObject> object) { |
6722 Isolate* isolate = object->GetIsolate(); | 6784 Isolate* isolate = object->GetIsolate(); |
6723 | 6785 |
6724 if (!object->map()->is_extensible()) return Just(true); | 6786 if (!object->map()->is_extensible()) return Just(true); |
6725 | 6787 |
6726 if (!object->HasSloppyArgumentsElements() && !object->map()->is_observed()) { | 6788 if (!object->HasSloppyArgumentsElements() && !object->map()->is_observed()) { |
6727 return PreventExtensionsWithTransition<NONE>(object); | 6789 return PreventExtensionsWithTransition<NONE>(object); |
6728 } | 6790 } |
6729 | 6791 |
6730 if (object->IsAccessCheckNeeded() && | 6792 if (object->IsAccessCheckNeeded() && |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
6770 RETURN_ON_EXCEPTION_VALUE( | 6832 RETURN_ON_EXCEPTION_VALUE( |
6771 isolate, | 6833 isolate, |
6772 EnqueueChangeRecord(object, "preventExtensions", Handle<Name>(), | 6834 EnqueueChangeRecord(object, "preventExtensions", Handle<Name>(), |
6773 isolate->factory()->the_hole_value()), | 6835 isolate->factory()->the_hole_value()), |
6774 Nothing<bool>()); | 6836 Nothing<bool>()); |
6775 } | 6837 } |
6776 return Just(true); | 6838 return Just(true); |
6777 } | 6839 } |
6778 | 6840 |
6779 | 6841 |
6780 static MaybeHandle<Object> ReturnObjectOrThrowTypeError( | |
6781 Handle<JSObject> object, Maybe<bool> maybe, MessageTemplate::Template msg) { | |
6782 if (!maybe.IsJust()) return MaybeHandle<Object>(); | |
6783 if (maybe.FromJust()) return object; | |
6784 Isolate* isolate = object->GetIsolate(); | |
6785 THROW_NEW_ERROR(isolate, NewTypeError(msg), Object); | |
6786 } | |
6787 | |
6788 | |
6789 MaybeHandle<Object> JSObject::PreventExtensions(Handle<JSObject> object) { | 6842 MaybeHandle<Object> JSObject::PreventExtensions(Handle<JSObject> object) { |
6790 return ReturnObjectOrThrowTypeError(object, PreventExtensionsInternal(object), | 6843 return ReturnObjectOrThrowTypeError(object, PreventExtensionsInternal(object), |
6791 MessageTemplate::kCannotPreventExt); | 6844 MessageTemplate::kCannotPreventExt); |
6792 } | 6845 } |
6793 | 6846 |
6794 | 6847 |
6795 bool JSObject::IsExtensible(Handle<JSObject> object) { | 6848 bool JSObject::IsExtensible(Handle<JSObject> object) { |
6796 Isolate* isolate = object->GetIsolate(); | 6849 Isolate* isolate = object->GetIsolate(); |
6797 if (object->IsAccessCheckNeeded() && | 6850 if (object->IsAccessCheckNeeded() && |
6798 !isolate->MayAccess(handle(isolate->context()), object)) { | 6851 !isolate->MayAccess(handle(isolate->context()), object)) { |
(...skipping 7197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
13996 SeededNumberDictionary::kEntrySize; | 14049 SeededNumberDictionary::kEntrySize; |
13997 return 2 * dictionary_size >= *new_capacity; | 14050 return 2 * dictionary_size >= *new_capacity; |
13998 } | 14051 } |
13999 | 14052 |
14000 | 14053 |
14001 // static | 14054 // static |
14002 MaybeHandle<Object> JSObject::AddDataElement(Handle<JSObject> object, | 14055 MaybeHandle<Object> JSObject::AddDataElement(Handle<JSObject> object, |
14003 uint32_t index, | 14056 uint32_t index, |
14004 Handle<Object> value, | 14057 Handle<Object> value, |
14005 PropertyAttributes attributes) { | 14058 PropertyAttributes attributes) { |
14059 Maybe<bool> result = | |
14060 AddDataElement(object, index, value, attributes, THROW_ON_ERROR); | |
14061 return result.IsJust() ? value : MaybeHandle<Object>(); | |
14062 } | |
14063 | |
14064 | |
14065 // static | |
14066 Maybe<bool> JSObject::AddDataElement(Handle<JSObject> object, uint32_t index, | |
14067 Handle<Object> value, | |
14068 PropertyAttributes attributes, | |
14069 ShouldThrow should_throw) { | |
14006 DCHECK(object->map()->is_extensible()); | 14070 DCHECK(object->map()->is_extensible()); |
14007 | 14071 |
14008 Isolate* isolate = object->GetIsolate(); | 14072 Isolate* isolate = object->GetIsolate(); |
14009 | 14073 |
14010 uint32_t old_length = 0; | 14074 uint32_t old_length = 0; |
14011 uint32_t new_capacity = 0; | 14075 uint32_t new_capacity = 0; |
14012 | 14076 |
14013 Handle<Object> old_length_handle; | 14077 Handle<Object> old_length_handle; |
14014 if (object->IsJSArray()) { | 14078 if (object->IsJSArray()) { |
14015 CHECK(JSArray::cast(*object)->length()->ToArrayLength(&old_length)); | 14079 CHECK(JSArray::cast(*object)->length()->ToArrayLength(&old_length)); |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
14056 new_length_handle = isolate->factory()->NewNumberFromUint(new_length); | 14120 new_length_handle = isolate->factory()->NewNumberFromUint(new_length); |
14057 JSArray::cast(*object)->set_length(*new_length_handle); | 14121 JSArray::cast(*object)->set_length(*new_length_handle); |
14058 } | 14122 } |
14059 | 14123 |
14060 if (!old_length_handle.is_null() && new_length != old_length) { | 14124 if (!old_length_handle.is_null() && new_length != old_length) { |
14061 // |old_length_handle| is kept null above unless the object is observed. | 14125 // |old_length_handle| is kept null above unless the object is observed. |
14062 DCHECK(object->map()->is_observed()); | 14126 DCHECK(object->map()->is_observed()); |
14063 Handle<JSArray> array = Handle<JSArray>::cast(object); | 14127 Handle<JSArray> array = Handle<JSArray>::cast(object); |
14064 Handle<String> name = isolate->factory()->Uint32ToString(index); | 14128 Handle<String> name = isolate->factory()->Uint32ToString(index); |
14065 | 14129 |
14066 RETURN_ON_EXCEPTION(isolate, BeginPerformSplice(array), Object); | 14130 RETURN_ON_EXCEPTION_VALUE(isolate, BeginPerformSplice(array), |
14067 RETURN_ON_EXCEPTION( | 14131 Nothing<bool>()); |
14132 RETURN_ON_EXCEPTION_VALUE( | |
14068 isolate, EnqueueChangeRecord(array, "add", name, | 14133 isolate, EnqueueChangeRecord(array, "add", name, |
14069 isolate->factory()->the_hole_value()), | 14134 isolate->factory()->the_hole_value()), |
14070 Object); | 14135 Nothing<bool>()); |
14071 RETURN_ON_EXCEPTION(isolate, | 14136 RETURN_ON_EXCEPTION_VALUE( |
14072 EnqueueChangeRecord(array, "update", | 14137 isolate, EnqueueChangeRecord(array, "update", |
14073 isolate->factory()->length_string(), | 14138 isolate->factory()->length_string(), |
14074 old_length_handle), | 14139 old_length_handle), |
14075 Object); | 14140 Nothing<bool>()); |
14076 RETURN_ON_EXCEPTION(isolate, EndPerformSplice(array), Object); | 14141 RETURN_ON_EXCEPTION_VALUE(isolate, EndPerformSplice(array), |
14142 Nothing<bool>()); | |
14077 Handle<JSArray> deleted = isolate->factory()->NewJSArray(0); | 14143 Handle<JSArray> deleted = isolate->factory()->NewJSArray(0); |
14078 RETURN_ON_EXCEPTION(isolate, EnqueueSpliceRecord(array, old_length, deleted, | 14144 RETURN_ON_EXCEPTION_VALUE(isolate, |
14079 new_length - old_length), | 14145 EnqueueSpliceRecord(array, old_length, deleted, |
14080 Object); | 14146 new_length - old_length), |
14147 Nothing<bool>()); | |
14081 } else if (object->map()->is_observed()) { | 14148 } else if (object->map()->is_observed()) { |
14082 Handle<String> name = isolate->factory()->Uint32ToString(index); | 14149 Handle<String> name = isolate->factory()->Uint32ToString(index); |
14083 RETURN_ON_EXCEPTION( | 14150 RETURN_ON_EXCEPTION_VALUE( |
14084 isolate, EnqueueChangeRecord(object, "add", name, | 14151 isolate, EnqueueChangeRecord(object, "add", name, |
14085 isolate->factory()->the_hole_value()), | 14152 isolate->factory()->the_hole_value()), |
14086 Object); | 14153 Nothing<bool>()); |
14087 } | 14154 } |
14088 | 14155 |
14089 return value; | 14156 return Just(true); |
14090 } | 14157 } |
14091 | 14158 |
14092 | 14159 |
14093 bool JSArray::SetLengthWouldNormalize(uint32_t new_length) { | 14160 bool JSArray::SetLengthWouldNormalize(uint32_t new_length) { |
14094 if (!HasFastElements()) return false; | 14161 if (!HasFastElements()) return false; |
14095 uint32_t capacity = static_cast<uint32_t>(elements()->length()); | 14162 uint32_t capacity = static_cast<uint32_t>(elements()->length()); |
14096 uint32_t new_capacity; | 14163 uint32_t new_capacity; |
14097 return JSArray::SetLengthWouldNormalize(GetHeap(), new_length) && | 14164 return JSArray::SetLengthWouldNormalize(GetHeap(), new_length) && |
14098 ShouldConvertToSlowElements(this, capacity, new_length - 1, | 14165 ShouldConvertToSlowElements(this, capacity, new_length - 1, |
14099 &new_capacity); | 14166 &new_capacity); |
(...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
14282 | 14349 |
14283 bool JSArray::WouldChangeReadOnlyLength(Handle<JSArray> array, | 14350 bool JSArray::WouldChangeReadOnlyLength(Handle<JSArray> array, |
14284 uint32_t index) { | 14351 uint32_t index) { |
14285 uint32_t length = 0; | 14352 uint32_t length = 0; |
14286 CHECK(array->length()->ToArrayLength(&length)); | 14353 CHECK(array->length()->ToArrayLength(&length)); |
14287 if (length <= index) return HasReadOnlyLength(array); | 14354 if (length <= index) return HasReadOnlyLength(array); |
14288 return false; | 14355 return false; |
14289 } | 14356 } |
14290 | 14357 |
14291 | 14358 |
14292 MaybeHandle<Object> JSArray::ReadOnlyLengthError(Handle<JSArray> array) { | |
14293 Isolate* isolate = array->GetIsolate(); | |
14294 Handle<Name> length = isolate->factory()->length_string(); | |
14295 Handle<String> typeof_string = Object::TypeOf(isolate, array); | |
14296 THROW_NEW_ERROR(isolate, | |
14297 NewTypeError(MessageTemplate::kStrictReadOnlyProperty, length, | |
14298 typeof_string, array), | |
14299 Object); | |
14300 } | |
14301 | |
14302 | |
14303 template <typename BackingStore> | 14359 template <typename BackingStore> |
14304 static int FastHoleyElementsUsage(JSObject* object, BackingStore* store) { | 14360 static int FastHoleyElementsUsage(JSObject* object, BackingStore* store) { |
14305 int limit = object->IsJSArray() | 14361 int limit = object->IsJSArray() |
14306 ? Smi::cast(JSArray::cast(object)->length())->value() | 14362 ? Smi::cast(JSArray::cast(object)->length())->value() |
14307 : store->length(); | 14363 : store->length(); |
14308 int used = 0; | 14364 int used = 0; |
14309 for (int i = 0; i < limit; ++i) { | 14365 for (int i = 0; i < limit; ++i) { |
14310 if (!store->is_the_hole(i)) ++used; | 14366 if (!store->is_the_hole(i)) ++used; |
14311 } | 14367 } |
14312 return used; | 14368 return used; |
(...skipping 3349 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
17662 if (cell->value() != *new_value) { | 17718 if (cell->value() != *new_value) { |
17663 cell->set_value(*new_value); | 17719 cell->set_value(*new_value); |
17664 Isolate* isolate = cell->GetIsolate(); | 17720 Isolate* isolate = cell->GetIsolate(); |
17665 cell->dependent_code()->DeoptimizeDependentCodeGroup( | 17721 cell->dependent_code()->DeoptimizeDependentCodeGroup( |
17666 isolate, DependentCode::kPropertyCellChangedGroup); | 17722 isolate, DependentCode::kPropertyCellChangedGroup); |
17667 } | 17723 } |
17668 } | 17724 } |
17669 | 17725 |
17670 } // namespace internal | 17726 } // namespace internal |
17671 } // namespace v8 | 17727 } // namespace v8 |
OLD | NEW |