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