Chromium Code Reviews| 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 |