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/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #include "src/accessors.h" | 7 #include "src/accessors.h" |
8 #include "src/allocation-site-scopes.h" | 8 #include "src/allocation-site-scopes.h" |
9 #include "src/api.h" | 9 #include "src/api.h" |
10 #include "src/arguments.h" | 10 #include "src/arguments.h" |
(...skipping 576 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
587 return GetPropertyWithAccessor(it->GetReceiver(), it->name(), | 587 return GetPropertyWithAccessor(it->GetReceiver(), it->name(), |
588 it->GetHolder<JSObject>(), | 588 it->GetHolder<JSObject>(), |
589 it->GetAccessors()); | 589 it->GetAccessors()); |
590 } | 590 } |
591 it->isolate()->ReportFailedAccessCheck(checked, v8::ACCESS_GET); | 591 it->isolate()->ReportFailedAccessCheck(checked, v8::ACCESS_GET); |
592 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(it->isolate(), Object); | 592 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(it->isolate(), Object); |
593 return it->factory()->undefined_value(); | 593 return it->factory()->undefined_value(); |
594 } | 594 } |
595 | 595 |
596 | 596 |
597 PropertyAttributes JSObject::GetPropertyAttributesWithFailedAccessCheck( | 597 Maybe<PropertyAttributes> JSObject::GetPropertyAttributesWithFailedAccessCheck( |
598 LookupIterator* it) { | 598 LookupIterator* it) { |
599 Handle<JSObject> checked = it->GetHolder<JSObject>(); | 599 Handle<JSObject> checked = it->GetHolder<JSObject>(); |
600 if (FindAllCanReadHolder(it)) return it->property_details().attributes(); | 600 if (FindAllCanReadHolder(it)) |
| 601 return maybe(it->property_details().attributes()); |
601 it->isolate()->ReportFailedAccessCheck(checked, v8::ACCESS_HAS); | 602 it->isolate()->ReportFailedAccessCheck(checked, v8::ACCESS_HAS); |
602 // TODO(yangguo): Issue 3269, check for scheduled exception missing? | 603 RETURN_VALUE_IF_SCHEDULED_EXCEPTION(it->isolate(), |
603 return ABSENT; | 604 Maybe<PropertyAttributes>()); |
| 605 return maybe(ABSENT); |
604 } | 606 } |
605 | 607 |
606 | 608 |
607 static bool FindAllCanWriteHolder(LookupIterator* it) { | 609 static bool FindAllCanWriteHolder(LookupIterator* it) { |
608 it->skip_interceptor(); | 610 it->skip_interceptor(); |
609 it->skip_access_check(); | 611 it->skip_access_check(); |
610 for (; it->IsFound(); it->Next()) { | 612 for (; it->IsFound(); it->Next()) { |
611 if (it->state() == LookupIterator::PROPERTY && it->HasProperty() && | 613 if (it->state() == LookupIterator::PROPERTY && it->HasProperty() && |
612 it->property_kind() == LookupIterator::ACCESSOR) { | 614 it->property_kind() == LookupIterator::ACCESSOR) { |
613 Handle<Object> accessors = it->GetAccessors(); | 615 Handle<Object> accessors = it->GetAccessors(); |
(...skipping 2398 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3012 case LookupIterator::INTERCEPTOR: | 3014 case LookupIterator::INTERCEPTOR: |
3013 if (it->HolderIsReceiver()) { | 3015 if (it->HolderIsReceiver()) { |
3014 MaybeHandle<Object> maybe_result = | 3016 MaybeHandle<Object> maybe_result = |
3015 JSObject::SetPropertyWithInterceptor(it, value); | 3017 JSObject::SetPropertyWithInterceptor(it, value); |
3016 if (!maybe_result.is_null()) return maybe_result; | 3018 if (!maybe_result.is_null()) return maybe_result; |
3017 if (it->isolate()->has_pending_exception()) return maybe_result; | 3019 if (it->isolate()->has_pending_exception()) return maybe_result; |
3018 } else { | 3020 } else { |
3019 Maybe<PropertyAttributes> maybe_attributes = | 3021 Maybe<PropertyAttributes> maybe_attributes = |
3020 JSObject::GetPropertyAttributesWithInterceptor( | 3022 JSObject::GetPropertyAttributesWithInterceptor( |
3021 it->GetHolder<JSObject>(), it->GetReceiver(), it->name()); | 3023 it->GetHolder<JSObject>(), it->GetReceiver(), it->name()); |
3022 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(it->isolate(), Object); | 3024 if (!maybe_attributes.has_value) return MaybeHandle<Object>(); |
3023 done = maybe_attributes.has_value; | 3025 done = maybe_attributes.value != ABSENT; |
3024 if (done && (maybe_attributes.value & READ_ONLY) != 0) { | 3026 if (done && (maybe_attributes.value & READ_ONLY) != 0) { |
3025 return WriteToReadOnlyProperty(it, value, strict_mode); | 3027 return WriteToReadOnlyProperty(it, value, strict_mode); |
3026 } | 3028 } |
3027 } | 3029 } |
3028 break; | 3030 break; |
3029 | 3031 |
3030 case LookupIterator::PROPERTY: | 3032 case LookupIterator::PROPERTY: |
3031 if (!it->HasProperty()) break; | 3033 if (!it->HasProperty()) break; |
3032 if (it->property_details().IsReadOnly()) { | 3034 if (it->property_details().IsReadOnly()) { |
3033 return WriteToReadOnlyProperty(it, value, strict_mode); | 3035 return WriteToReadOnlyProperty(it, value, strict_mode); |
(...skipping 553 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3587 return result->HandlerResult(JSProxy::cast(iter.GetCurrent())); | 3589 return result->HandlerResult(JSProxy::cast(iter.GetCurrent())); |
3588 } | 3590 } |
3589 JSObject::cast(iter.GetCurrent())->LookupOwnRealNamedProperty(name, result); | 3591 JSObject::cast(iter.GetCurrent())->LookupOwnRealNamedProperty(name, result); |
3590 ASSERT(!(result->IsFound() && result->type() == INTERCEPTOR)); | 3592 ASSERT(!(result->IsFound() && result->type() == INTERCEPTOR)); |
3591 if (result->IsFound()) return; | 3593 if (result->IsFound()) return; |
3592 } | 3594 } |
3593 result->NotFound(); | 3595 result->NotFound(); |
3594 } | 3596 } |
3595 | 3597 |
3596 | 3598 |
3597 bool JSProxy::HasPropertyWithHandler(Handle<JSProxy> proxy, Handle<Name> name) { | 3599 Maybe<bool> JSProxy::HasPropertyWithHandler(Handle<JSProxy> proxy, |
| 3600 Handle<Name> name) { |
3598 Isolate* isolate = proxy->GetIsolate(); | 3601 Isolate* isolate = proxy->GetIsolate(); |
3599 | 3602 |
3600 // TODO(rossberg): adjust once there is a story for symbols vs proxies. | 3603 // TODO(rossberg): adjust once there is a story for symbols vs proxies. |
3601 if (name->IsSymbol()) return false; | 3604 if (name->IsSymbol()) return maybe(false); |
3602 | 3605 |
3603 Handle<Object> args[] = { name }; | 3606 Handle<Object> args[] = { name }; |
3604 Handle<Object> result; | 3607 Handle<Object> result; |
3605 ASSIGN_RETURN_ON_EXCEPTION_VALUE( | 3608 ASSIGN_RETURN_ON_EXCEPTION_VALUE( |
3606 isolate, result, | 3609 isolate, result, CallTrap(proxy, "has", isolate->derived_has_trap(), |
3607 CallTrap(proxy, | 3610 ARRAY_SIZE(args), args), |
3608 "has", | 3611 Maybe<bool>()); |
3609 isolate->derived_has_trap(), | |
3610 ARRAY_SIZE(args), | |
3611 args), | |
3612 false); | |
3613 | 3612 |
3614 return result->BooleanValue(); | 3613 return maybe(result->BooleanValue()); |
3615 } | 3614 } |
3616 | 3615 |
3617 | 3616 |
3618 MaybeHandle<Object> JSProxy::SetPropertyWithHandler(Handle<JSProxy> proxy, | 3617 MaybeHandle<Object> JSProxy::SetPropertyWithHandler(Handle<JSProxy> proxy, |
3619 Handle<Object> receiver, | 3618 Handle<Object> receiver, |
3620 Handle<Name> name, | 3619 Handle<Name> name, |
3621 Handle<Object> value, | 3620 Handle<Object> value, |
3622 StrictMode strict_mode) { | 3621 StrictMode strict_mode) { |
3623 Isolate* isolate = proxy->GetIsolate(); | 3622 Isolate* isolate = proxy->GetIsolate(); |
3624 | 3623 |
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3772 | 3771 |
3773 | 3772 |
3774 MaybeHandle<Object> JSProxy::DeleteElementWithHandler( | 3773 MaybeHandle<Object> JSProxy::DeleteElementWithHandler( |
3775 Handle<JSProxy> proxy, uint32_t index, DeleteMode mode) { | 3774 Handle<JSProxy> proxy, uint32_t index, DeleteMode mode) { |
3776 Isolate* isolate = proxy->GetIsolate(); | 3775 Isolate* isolate = proxy->GetIsolate(); |
3777 Handle<String> name = isolate->factory()->Uint32ToString(index); | 3776 Handle<String> name = isolate->factory()->Uint32ToString(index); |
3778 return JSProxy::DeletePropertyWithHandler(proxy, name, mode); | 3777 return JSProxy::DeletePropertyWithHandler(proxy, name, mode); |
3779 } | 3778 } |
3780 | 3779 |
3781 | 3780 |
3782 PropertyAttributes JSProxy::GetPropertyAttributesWithHandler( | 3781 Maybe<PropertyAttributes> JSProxy::GetPropertyAttributesWithHandler( |
3783 Handle<JSProxy> proxy, | 3782 Handle<JSProxy> proxy, Handle<Object> receiver, Handle<Name> name) { |
3784 Handle<Object> receiver, | |
3785 Handle<Name> name) { | |
3786 Isolate* isolate = proxy->GetIsolate(); | 3783 Isolate* isolate = proxy->GetIsolate(); |
3787 HandleScope scope(isolate); | 3784 HandleScope scope(isolate); |
3788 | 3785 |
3789 // TODO(rossberg): adjust once there is a story for symbols vs proxies. | 3786 // TODO(rossberg): adjust once there is a story for symbols vs proxies. |
3790 if (name->IsSymbol()) return ABSENT; | 3787 if (name->IsSymbol()) return maybe(ABSENT); |
3791 | 3788 |
3792 Handle<Object> args[] = { name }; | 3789 Handle<Object> args[] = { name }; |
3793 Handle<Object> result; | 3790 Handle<Object> result; |
3794 ASSIGN_RETURN_ON_EXCEPTION_VALUE( | 3791 ASSIGN_RETURN_ON_EXCEPTION_VALUE( |
3795 isolate, result, | 3792 isolate, result, |
3796 proxy->CallTrap(proxy, | 3793 proxy->CallTrap(proxy, "getPropertyDescriptor", Handle<Object>(), |
3797 "getPropertyDescriptor", | 3794 ARRAY_SIZE(args), args), |
3798 Handle<Object>(), | 3795 Maybe<PropertyAttributes>()); |
3799 ARRAY_SIZE(args), | |
3800 args), | |
3801 NONE); | |
3802 | 3796 |
3803 if (result->IsUndefined()) return ABSENT; | 3797 if (result->IsUndefined()) return maybe(ABSENT); |
3804 | 3798 |
3805 Handle<Object> argv[] = { result }; | 3799 Handle<Object> argv[] = { result }; |
3806 Handle<Object> desc; | 3800 Handle<Object> desc; |
3807 ASSIGN_RETURN_ON_EXCEPTION_VALUE( | 3801 ASSIGN_RETURN_ON_EXCEPTION_VALUE( |
3808 isolate, desc, | 3802 isolate, desc, |
3809 Execution::Call(isolate, | 3803 Execution::Call(isolate, isolate->to_complete_property_descriptor(), |
3810 isolate->to_complete_property_descriptor(), | 3804 result, ARRAY_SIZE(argv), argv), |
3811 result, | 3805 Maybe<PropertyAttributes>()); |
3812 ARRAY_SIZE(argv), | |
3813 argv), | |
3814 NONE); | |
3815 | 3806 |
3816 // Convert result to PropertyAttributes. | 3807 // Convert result to PropertyAttributes. |
3817 Handle<String> enum_n = isolate->factory()->InternalizeOneByteString( | 3808 Handle<String> enum_n = isolate->factory()->InternalizeOneByteString( |
3818 STATIC_ASCII_VECTOR("enumerable_")); | 3809 STATIC_ASCII_VECTOR("enumerable_")); |
3819 Handle<Object> enumerable; | 3810 Handle<Object> enumerable; |
3820 ASSIGN_RETURN_ON_EXCEPTION_VALUE( | 3811 ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, enumerable, |
3821 isolate, enumerable, Object::GetProperty(desc, enum_n), NONE); | 3812 Object::GetProperty(desc, enum_n), |
| 3813 Maybe<PropertyAttributes>()); |
3822 Handle<String> conf_n = isolate->factory()->InternalizeOneByteString( | 3814 Handle<String> conf_n = isolate->factory()->InternalizeOneByteString( |
3823 STATIC_ASCII_VECTOR("configurable_")); | 3815 STATIC_ASCII_VECTOR("configurable_")); |
3824 Handle<Object> configurable; | 3816 Handle<Object> configurable; |
3825 ASSIGN_RETURN_ON_EXCEPTION_VALUE( | 3817 ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, configurable, |
3826 isolate, configurable, Object::GetProperty(desc, conf_n), NONE); | 3818 Object::GetProperty(desc, conf_n), |
| 3819 Maybe<PropertyAttributes>()); |
3827 Handle<String> writ_n = isolate->factory()->InternalizeOneByteString( | 3820 Handle<String> writ_n = isolate->factory()->InternalizeOneByteString( |
3828 STATIC_ASCII_VECTOR("writable_")); | 3821 STATIC_ASCII_VECTOR("writable_")); |
3829 Handle<Object> writable; | 3822 Handle<Object> writable; |
3830 ASSIGN_RETURN_ON_EXCEPTION_VALUE( | 3823 ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, writable, |
3831 isolate, writable, Object::GetProperty(desc, writ_n), NONE); | 3824 Object::GetProperty(desc, writ_n), |
| 3825 Maybe<PropertyAttributes>()); |
3832 if (!writable->BooleanValue()) { | 3826 if (!writable->BooleanValue()) { |
3833 Handle<String> set_n = isolate->factory()->InternalizeOneByteString( | 3827 Handle<String> set_n = isolate->factory()->InternalizeOneByteString( |
3834 STATIC_ASCII_VECTOR("set_")); | 3828 STATIC_ASCII_VECTOR("set_")); |
3835 Handle<Object> setter; | 3829 Handle<Object> setter; |
3836 ASSIGN_RETURN_ON_EXCEPTION_VALUE( | 3830 ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, setter, |
3837 isolate, setter, Object::GetProperty(desc, set_n), NONE); | 3831 Object::GetProperty(desc, set_n), |
| 3832 Maybe<PropertyAttributes>()); |
3838 writable = isolate->factory()->ToBoolean(!setter->IsUndefined()); | 3833 writable = isolate->factory()->ToBoolean(!setter->IsUndefined()); |
3839 } | 3834 } |
3840 | 3835 |
3841 if (configurable->IsFalse()) { | 3836 if (configurable->IsFalse()) { |
3842 Handle<Object> handler(proxy->handler(), isolate); | 3837 Handle<Object> handler(proxy->handler(), isolate); |
3843 Handle<String> trap = isolate->factory()->InternalizeOneByteString( | 3838 Handle<String> trap = isolate->factory()->InternalizeOneByteString( |
3844 STATIC_ASCII_VECTOR("getPropertyDescriptor")); | 3839 STATIC_ASCII_VECTOR("getPropertyDescriptor")); |
3845 Handle<Object> args[] = { handler, trap, name }; | 3840 Handle<Object> args[] = { handler, trap, name }; |
3846 Handle<Object> error = isolate->factory()->NewTypeError( | 3841 Handle<Object> error = isolate->factory()->NewTypeError( |
3847 "proxy_prop_not_configurable", HandleVector(args, ARRAY_SIZE(args))); | 3842 "proxy_prop_not_configurable", HandleVector(args, ARRAY_SIZE(args))); |
3848 isolate->Throw(*error); | 3843 isolate->Throw(*error); |
3849 return NONE; | 3844 return maybe(NONE); |
3850 } | 3845 } |
3851 | 3846 |
3852 int attributes = NONE; | 3847 int attributes = NONE; |
3853 if (!enumerable->BooleanValue()) attributes |= DONT_ENUM; | 3848 if (!enumerable->BooleanValue()) attributes |= DONT_ENUM; |
3854 if (!configurable->BooleanValue()) attributes |= DONT_DELETE; | 3849 if (!configurable->BooleanValue()) attributes |= DONT_DELETE; |
3855 if (!writable->BooleanValue()) attributes |= READ_ONLY; | 3850 if (!writable->BooleanValue()) attributes |= READ_ONLY; |
3856 return static_cast<PropertyAttributes>(attributes); | 3851 return maybe(static_cast<PropertyAttributes>(attributes)); |
3857 } | 3852 } |
3858 | 3853 |
3859 | 3854 |
3860 PropertyAttributes JSProxy::GetElementAttributeWithHandler( | 3855 Maybe<PropertyAttributes> JSProxy::GetElementAttributeWithHandler( |
3861 Handle<JSProxy> proxy, | 3856 Handle<JSProxy> proxy, Handle<JSReceiver> receiver, uint32_t index) { |
3862 Handle<JSReceiver> receiver, | |
3863 uint32_t index) { | |
3864 Isolate* isolate = proxy->GetIsolate(); | 3857 Isolate* isolate = proxy->GetIsolate(); |
3865 Handle<String> name = isolate->factory()->Uint32ToString(index); | 3858 Handle<String> name = isolate->factory()->Uint32ToString(index); |
3866 return GetPropertyAttributesWithHandler(proxy, receiver, name); | 3859 return GetPropertyAttributesWithHandler(proxy, receiver, name); |
3867 } | 3860 } |
3868 | 3861 |
3869 | 3862 |
3870 void JSProxy::Fix(Handle<JSProxy> proxy) { | 3863 void JSProxy::Fix(Handle<JSProxy> proxy) { |
3871 Isolate* isolate = proxy->GetIsolate(); | 3864 Isolate* isolate = proxy->GetIsolate(); |
3872 | 3865 |
3873 // Save identity hash. | 3866 // Save identity hash. |
(...skipping 397 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4271 | 4264 |
4272 return value; | 4265 return value; |
4273 } | 4266 } |
4274 | 4267 |
4275 | 4268 |
4276 Maybe<PropertyAttributes> JSObject::GetPropertyAttributesWithInterceptor( | 4269 Maybe<PropertyAttributes> JSObject::GetPropertyAttributesWithInterceptor( |
4277 Handle<JSObject> holder, | 4270 Handle<JSObject> holder, |
4278 Handle<Object> receiver, | 4271 Handle<Object> receiver, |
4279 Handle<Name> name) { | 4272 Handle<Name> name) { |
4280 // TODO(rossberg): Support symbols in the API. | 4273 // TODO(rossberg): Support symbols in the API. |
4281 if (name->IsSymbol()) return Maybe<PropertyAttributes>(); | 4274 if (name->IsSymbol()) return maybe(ABSENT); |
4282 | 4275 |
4283 Isolate* isolate = holder->GetIsolate(); | 4276 Isolate* isolate = holder->GetIsolate(); |
4284 HandleScope scope(isolate); | 4277 HandleScope scope(isolate); |
4285 | 4278 |
4286 // Make sure that the top context does not change when doing | 4279 // Make sure that the top context does not change when doing |
4287 // callbacks or interceptor calls. | 4280 // callbacks or interceptor calls. |
4288 AssertNoContextChange ncc(isolate); | 4281 AssertNoContextChange ncc(isolate); |
4289 | 4282 |
4290 Handle<InterceptorInfo> interceptor(holder->GetNamedInterceptor()); | 4283 Handle<InterceptorInfo> interceptor(holder->GetNamedInterceptor()); |
4291 PropertyCallbackArguments args( | 4284 PropertyCallbackArguments args( |
4292 isolate, interceptor->data(), *receiver, *holder); | 4285 isolate, interceptor->data(), *receiver, *holder); |
4293 if (!interceptor->query()->IsUndefined()) { | 4286 if (!interceptor->query()->IsUndefined()) { |
4294 v8::NamedPropertyQueryCallback query = | 4287 v8::NamedPropertyQueryCallback query = |
4295 v8::ToCData<v8::NamedPropertyQueryCallback>(interceptor->query()); | 4288 v8::ToCData<v8::NamedPropertyQueryCallback>(interceptor->query()); |
4296 LOG(isolate, | 4289 LOG(isolate, |
4297 ApiNamedPropertyAccess("interceptor-named-has", *holder, *name)); | 4290 ApiNamedPropertyAccess("interceptor-named-has", *holder, *name)); |
4298 v8::Handle<v8::Integer> result = | 4291 v8::Handle<v8::Integer> result = |
4299 args.Call(query, v8::Utils::ToLocal(Handle<String>::cast(name))); | 4292 args.Call(query, v8::Utils::ToLocal(Handle<String>::cast(name))); |
4300 if (!result.IsEmpty()) { | 4293 if (!result.IsEmpty()) { |
4301 ASSERT(result->IsInt32()); | 4294 ASSERT(result->IsInt32()); |
4302 return Maybe<PropertyAttributes>( | 4295 return maybe(static_cast<PropertyAttributes>(result->Int32Value())); |
4303 static_cast<PropertyAttributes>(result->Int32Value())); | |
4304 } | 4296 } |
4305 } else if (!interceptor->getter()->IsUndefined()) { | 4297 } else if (!interceptor->getter()->IsUndefined()) { |
4306 v8::NamedPropertyGetterCallback getter = | 4298 v8::NamedPropertyGetterCallback getter = |
4307 v8::ToCData<v8::NamedPropertyGetterCallback>(interceptor->getter()); | 4299 v8::ToCData<v8::NamedPropertyGetterCallback>(interceptor->getter()); |
4308 LOG(isolate, | 4300 LOG(isolate, |
4309 ApiNamedPropertyAccess("interceptor-named-get-has", *holder, *name)); | 4301 ApiNamedPropertyAccess("interceptor-named-get-has", *holder, *name)); |
4310 v8::Handle<v8::Value> result = | 4302 v8::Handle<v8::Value> result = |
4311 args.Call(getter, v8::Utils::ToLocal(Handle<String>::cast(name))); | 4303 args.Call(getter, v8::Utils::ToLocal(Handle<String>::cast(name))); |
4312 if (!result.IsEmpty()) return Maybe<PropertyAttributes>(DONT_ENUM); | 4304 if (!result.IsEmpty()) return maybe(DONT_ENUM); |
4313 } | 4305 } |
4314 return Maybe<PropertyAttributes>(); | 4306 |
| 4307 RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Maybe<PropertyAttributes>()); |
| 4308 return maybe(ABSENT); |
4315 } | 4309 } |
4316 | 4310 |
4317 | 4311 |
4318 PropertyAttributes JSReceiver::GetOwnPropertyAttributes( | 4312 Maybe<PropertyAttributes> JSReceiver::GetOwnPropertyAttributes( |
4319 Handle<JSReceiver> object, Handle<Name> name) { | 4313 Handle<JSReceiver> object, Handle<Name> name) { |
4320 // Check whether the name is an array index. | 4314 // Check whether the name is an array index. |
4321 uint32_t index = 0; | 4315 uint32_t index = 0; |
4322 if (object->IsJSObject() && name->AsArrayIndex(&index)) { | 4316 if (object->IsJSObject() && name->AsArrayIndex(&index)) { |
4323 return GetOwnElementAttribute(object, index); | 4317 return GetOwnElementAttribute(object, index); |
4324 } | 4318 } |
4325 LookupIterator it(object, name, LookupIterator::CHECK_OWN); | 4319 LookupIterator it(object, name, LookupIterator::CHECK_OWN); |
4326 return GetPropertyAttributes(&it); | 4320 return GetPropertyAttributes(&it); |
4327 } | 4321 } |
4328 | 4322 |
4329 | 4323 |
4330 PropertyAttributes JSReceiver::GetPropertyAttributes(LookupIterator* it) { | 4324 Maybe<PropertyAttributes> JSReceiver::GetPropertyAttributes( |
| 4325 LookupIterator* it) { |
4331 for (; it->IsFound(); it->Next()) { | 4326 for (; it->IsFound(); it->Next()) { |
4332 switch (it->state()) { | 4327 switch (it->state()) { |
4333 case LookupIterator::NOT_FOUND: | 4328 case LookupIterator::NOT_FOUND: |
4334 UNREACHABLE(); | 4329 UNREACHABLE(); |
4335 case LookupIterator::JSPROXY: | 4330 case LookupIterator::JSPROXY: |
4336 return JSProxy::GetPropertyAttributesWithHandler( | 4331 return JSProxy::GetPropertyAttributesWithHandler( |
4337 it->GetHolder<JSProxy>(), it->GetReceiver(), it->name()); | 4332 it->GetHolder<JSProxy>(), it->GetReceiver(), it->name()); |
4338 case LookupIterator::INTERCEPTOR: { | 4333 case LookupIterator::INTERCEPTOR: { |
4339 Maybe<PropertyAttributes> result = | 4334 Maybe<PropertyAttributes> result = |
4340 JSObject::GetPropertyAttributesWithInterceptor( | 4335 JSObject::GetPropertyAttributesWithInterceptor( |
4341 it->GetHolder<JSObject>(), it->GetReceiver(), it->name()); | 4336 it->GetHolder<JSObject>(), it->GetReceiver(), it->name()); |
4342 if (result.has_value) return result.value; | 4337 if (!result.has_value) return result; |
| 4338 if (result.value != ABSENT) return result; |
4343 break; | 4339 break; |
4344 } | 4340 } |
4345 case LookupIterator::ACCESS_CHECK: | 4341 case LookupIterator::ACCESS_CHECK: |
4346 if (it->HasAccess(v8::ACCESS_HAS)) break; | 4342 if (it->HasAccess(v8::ACCESS_HAS)) break; |
4347 return JSObject::GetPropertyAttributesWithFailedAccessCheck(it); | 4343 return JSObject::GetPropertyAttributesWithFailedAccessCheck(it); |
4348 case LookupIterator::PROPERTY: | 4344 case LookupIterator::PROPERTY: |
4349 if (it->HasProperty()) return it->property_details().attributes(); | 4345 if (it->HasProperty()) { |
| 4346 return maybe(it->property_details().attributes()); |
| 4347 } |
4350 break; | 4348 break; |
4351 } | 4349 } |
4352 } | 4350 } |
4353 return ABSENT; | 4351 return maybe(ABSENT); |
4354 } | 4352 } |
4355 | 4353 |
4356 | 4354 |
4357 PropertyAttributes JSObject::GetElementAttributeWithReceiver( | 4355 Maybe<PropertyAttributes> JSObject::GetElementAttributeWithReceiver( |
4358 Handle<JSObject> object, | 4356 Handle<JSObject> object, Handle<JSReceiver> receiver, uint32_t index, |
4359 Handle<JSReceiver> receiver, | |
4360 uint32_t index, | |
4361 bool check_prototype) { | 4357 bool check_prototype) { |
4362 Isolate* isolate = object->GetIsolate(); | 4358 Isolate* isolate = object->GetIsolate(); |
4363 | 4359 |
4364 // Check access rights if needed. | 4360 // Check access rights if needed. |
4365 if (object->IsAccessCheckNeeded()) { | 4361 if (object->IsAccessCheckNeeded()) { |
4366 if (!isolate->MayIndexedAccess(object, index, v8::ACCESS_HAS)) { | 4362 if (!isolate->MayIndexedAccess(object, index, v8::ACCESS_HAS)) { |
4367 isolate->ReportFailedAccessCheck(object, v8::ACCESS_HAS); | 4363 isolate->ReportFailedAccessCheck(object, v8::ACCESS_HAS); |
4368 // TODO(yangguo): Issue 3269, check for scheduled exception missing? | 4364 RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Maybe<PropertyAttributes>()); |
4369 return ABSENT; | 4365 return maybe(ABSENT); |
4370 } | 4366 } |
4371 } | 4367 } |
4372 | 4368 |
4373 if (object->IsJSGlobalProxy()) { | 4369 if (object->IsJSGlobalProxy()) { |
4374 PrototypeIterator iter(isolate, object); | 4370 PrototypeIterator iter(isolate, object); |
4375 if (iter.IsAtEnd()) return ABSENT; | 4371 if (iter.IsAtEnd()) return maybe(ABSENT); |
4376 ASSERT(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject()); | 4372 ASSERT(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject()); |
4377 return JSObject::GetElementAttributeWithReceiver( | 4373 return JSObject::GetElementAttributeWithReceiver( |
4378 Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)), receiver, | 4374 Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)), receiver, |
4379 index, check_prototype); | 4375 index, check_prototype); |
4380 } | 4376 } |
4381 | 4377 |
4382 // Check for lookup interceptor except when bootstrapping. | 4378 // Check for lookup interceptor except when bootstrapping. |
4383 if (object->HasIndexedInterceptor() && !isolate->bootstrapper()->IsActive()) { | 4379 if (object->HasIndexedInterceptor() && !isolate->bootstrapper()->IsActive()) { |
4384 return JSObject::GetElementAttributeWithInterceptor( | 4380 return JSObject::GetElementAttributeWithInterceptor( |
4385 object, receiver, index, check_prototype); | 4381 object, receiver, index, check_prototype); |
4386 } | 4382 } |
4387 | 4383 |
4388 return GetElementAttributeWithoutInterceptor( | 4384 return GetElementAttributeWithoutInterceptor( |
4389 object, receiver, index, check_prototype); | 4385 object, receiver, index, check_prototype); |
4390 } | 4386 } |
4391 | 4387 |
4392 | 4388 |
4393 PropertyAttributes JSObject::GetElementAttributeWithInterceptor( | 4389 Maybe<PropertyAttributes> JSObject::GetElementAttributeWithInterceptor( |
4394 Handle<JSObject> object, | 4390 Handle<JSObject> object, Handle<JSReceiver> receiver, uint32_t index, |
4395 Handle<JSReceiver> receiver, | |
4396 uint32_t index, | |
4397 bool check_prototype) { | 4391 bool check_prototype) { |
4398 Isolate* isolate = object->GetIsolate(); | 4392 Isolate* isolate = object->GetIsolate(); |
4399 HandleScope scope(isolate); | 4393 HandleScope scope(isolate); |
4400 | 4394 |
4401 // Make sure that the top context does not change when doing | 4395 // Make sure that the top context does not change when doing |
4402 // callbacks or interceptor calls. | 4396 // callbacks or interceptor calls. |
4403 AssertNoContextChange ncc(isolate); | 4397 AssertNoContextChange ncc(isolate); |
4404 | 4398 |
4405 Handle<InterceptorInfo> interceptor(object->GetIndexedInterceptor()); | 4399 Handle<InterceptorInfo> interceptor(object->GetIndexedInterceptor()); |
4406 PropertyCallbackArguments args( | 4400 PropertyCallbackArguments args( |
4407 isolate, interceptor->data(), *receiver, *object); | 4401 isolate, interceptor->data(), *receiver, *object); |
4408 if (!interceptor->query()->IsUndefined()) { | 4402 if (!interceptor->query()->IsUndefined()) { |
4409 v8::IndexedPropertyQueryCallback query = | 4403 v8::IndexedPropertyQueryCallback query = |
4410 v8::ToCData<v8::IndexedPropertyQueryCallback>(interceptor->query()); | 4404 v8::ToCData<v8::IndexedPropertyQueryCallback>(interceptor->query()); |
4411 LOG(isolate, | 4405 LOG(isolate, |
4412 ApiIndexedPropertyAccess("interceptor-indexed-has", *object, index)); | 4406 ApiIndexedPropertyAccess("interceptor-indexed-has", *object, index)); |
4413 v8::Handle<v8::Integer> result = args.Call(query, index); | 4407 v8::Handle<v8::Integer> result = args.Call(query, index); |
4414 if (!result.IsEmpty()) | 4408 if (!result.IsEmpty()) |
4415 return static_cast<PropertyAttributes>(result->Int32Value()); | 4409 return maybe(static_cast<PropertyAttributes>(result->Int32Value())); |
4416 } else if (!interceptor->getter()->IsUndefined()) { | 4410 } else if (!interceptor->getter()->IsUndefined()) { |
4417 v8::IndexedPropertyGetterCallback getter = | 4411 v8::IndexedPropertyGetterCallback getter = |
4418 v8::ToCData<v8::IndexedPropertyGetterCallback>(interceptor->getter()); | 4412 v8::ToCData<v8::IndexedPropertyGetterCallback>(interceptor->getter()); |
4419 LOG(isolate, | 4413 LOG(isolate, |
4420 ApiIndexedPropertyAccess( | 4414 ApiIndexedPropertyAccess( |
4421 "interceptor-indexed-get-has", *object, index)); | 4415 "interceptor-indexed-get-has", *object, index)); |
4422 v8::Handle<v8::Value> result = args.Call(getter, index); | 4416 v8::Handle<v8::Value> result = args.Call(getter, index); |
4423 if (!result.IsEmpty()) return NONE; | 4417 if (!result.IsEmpty()) return maybe(NONE); |
4424 } | 4418 } |
4425 | 4419 |
4426 return GetElementAttributeWithoutInterceptor( | 4420 return GetElementAttributeWithoutInterceptor( |
4427 object, receiver, index, check_prototype); | 4421 object, receiver, index, check_prototype); |
4428 } | 4422 } |
4429 | 4423 |
4430 | 4424 |
4431 PropertyAttributes JSObject::GetElementAttributeWithoutInterceptor( | 4425 Maybe<PropertyAttributes> JSObject::GetElementAttributeWithoutInterceptor( |
4432 Handle<JSObject> object, | 4426 Handle<JSObject> object, Handle<JSReceiver> receiver, uint32_t index, |
4433 Handle<JSReceiver> receiver, | |
4434 uint32_t index, | |
4435 bool check_prototype) { | 4427 bool check_prototype) { |
4436 PropertyAttributes attr = object->GetElementsAccessor()->GetAttributes( | 4428 PropertyAttributes attr = object->GetElementsAccessor()->GetAttributes( |
4437 receiver, object, index); | 4429 receiver, object, index); |
4438 if (attr != ABSENT) return attr; | 4430 if (attr != ABSENT) return maybe(attr); |
4439 | 4431 |
4440 // Handle [] on String objects. | 4432 // Handle [] on String objects. |
4441 if (object->IsStringObjectWithCharacterAt(index)) { | 4433 if (object->IsStringObjectWithCharacterAt(index)) { |
4442 return static_cast<PropertyAttributes>(READ_ONLY | DONT_DELETE); | 4434 return maybe(static_cast<PropertyAttributes>(READ_ONLY | DONT_DELETE)); |
4443 } | 4435 } |
4444 | 4436 |
4445 if (!check_prototype) return ABSENT; | 4437 if (!check_prototype) return maybe(ABSENT); |
4446 | 4438 |
4447 PrototypeIterator iter(object->GetIsolate(), object); | 4439 PrototypeIterator iter(object->GetIsolate(), object); |
4448 if (PrototypeIterator::GetCurrent(iter)->IsJSProxy()) { | 4440 if (PrototypeIterator::GetCurrent(iter)->IsJSProxy()) { |
4449 // We need to follow the spec and simulate a call to [[GetOwnProperty]]. | 4441 // We need to follow the spec and simulate a call to [[GetOwnProperty]]. |
4450 return JSProxy::GetElementAttributeWithHandler( | 4442 return JSProxy::GetElementAttributeWithHandler( |
4451 Handle<JSProxy>::cast(PrototypeIterator::GetCurrent(iter)), receiver, | 4443 Handle<JSProxy>::cast(PrototypeIterator::GetCurrent(iter)), receiver, |
4452 index); | 4444 index); |
4453 } | 4445 } |
4454 if (iter.IsAtEnd()) return ABSENT; | 4446 if (iter.IsAtEnd()) return maybe(ABSENT); |
4455 return GetElementAttributeWithReceiver( | 4447 return GetElementAttributeWithReceiver( |
4456 Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)), receiver, | 4448 Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)), receiver, |
4457 index, true); | 4449 index, true); |
4458 } | 4450 } |
4459 | 4451 |
4460 | 4452 |
4461 Handle<NormalizedMapCache> NormalizedMapCache::New(Isolate* isolate) { | 4453 Handle<NormalizedMapCache> NormalizedMapCache::New(Isolate* isolate) { |
4462 Handle<FixedArray> array( | 4454 Handle<FixedArray> array( |
4463 isolate->factory()->NewFixedArray(kEntries, TENURED)); | 4455 isolate->factory()->NewFixedArray(kEntries, TENURED)); |
4464 return Handle<NormalizedMapCache>::cast(array); | 4456 return Handle<NormalizedMapCache>::cast(array); |
(...skipping 559 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5024 | 5016 |
5025 Handle<ObjectHashTable> hashtable(ObjectHashTable::cast(inline_value)); | 5017 Handle<ObjectHashTable> hashtable(ObjectHashTable::cast(inline_value)); |
5026 bool was_present = false; | 5018 bool was_present = false; |
5027 ObjectHashTable::Remove(hashtable, key, &was_present); | 5019 ObjectHashTable::Remove(hashtable, key, &was_present); |
5028 } | 5020 } |
5029 | 5021 |
5030 | 5022 |
5031 bool JSObject::HasHiddenProperties(Handle<JSObject> object) { | 5023 bool JSObject::HasHiddenProperties(Handle<JSObject> object) { |
5032 Handle<Name> hidden = object->GetIsolate()->factory()->hidden_string(); | 5024 Handle<Name> hidden = object->GetIsolate()->factory()->hidden_string(); |
5033 LookupIterator it(object, hidden, LookupIterator::CHECK_OWN_REAL); | 5025 LookupIterator it(object, hidden, LookupIterator::CHECK_OWN_REAL); |
5034 return GetPropertyAttributes(&it) != ABSENT; | 5026 Maybe<PropertyAttributes> maybe = GetPropertyAttributes(&it); |
| 5027 // Cannot get an exception since the hidden_string isn't accessible to JS. |
| 5028 ASSERT(maybe.has_value); |
| 5029 return maybe.value != ABSENT; |
5035 } | 5030 } |
5036 | 5031 |
5037 | 5032 |
5038 Object* JSObject::GetHiddenPropertiesHashTable() { | 5033 Object* JSObject::GetHiddenPropertiesHashTable() { |
5039 ASSERT(!IsJSGlobalProxy()); | 5034 ASSERT(!IsJSGlobalProxy()); |
5040 if (HasFastProperties()) { | 5035 if (HasFastProperties()) { |
5041 // If the object has fast properties, check whether the first slot | 5036 // If the object has fast properties, check whether the first slot |
5042 // in the descriptor array matches the hidden string. Since the | 5037 // in the descriptor array matches the hidden string. Since the |
5043 // hidden strings hash code is zero (and no other name has hash | 5038 // hidden strings hash code is zero (and no other name has hash |
5044 // code zero) it will always occupy the first entry if present. | 5039 // code zero) it will always occupy the first entry if present. |
(...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5247 if (iter.IsAtEnd()) return factory->false_value(); | 5242 if (iter.IsAtEnd()) return factory->false_value(); |
5248 ASSERT(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject()); | 5243 ASSERT(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject()); |
5249 return DeleteElement( | 5244 return DeleteElement( |
5250 Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)), index, | 5245 Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)), index, |
5251 mode); | 5246 mode); |
5252 } | 5247 } |
5253 | 5248 |
5254 Handle<Object> old_value; | 5249 Handle<Object> old_value; |
5255 bool should_enqueue_change_record = false; | 5250 bool should_enqueue_change_record = false; |
5256 if (object->map()->is_observed()) { | 5251 if (object->map()->is_observed()) { |
5257 should_enqueue_change_record = HasOwnElement(object, index); | 5252 Maybe<bool> maybe = HasOwnElement(object, index); |
| 5253 if (!maybe.has_value) return MaybeHandle<Object>(); |
| 5254 should_enqueue_change_record = maybe.value; |
5258 if (should_enqueue_change_record) { | 5255 if (should_enqueue_change_record) { |
5259 if (!GetOwnElementAccessorPair(object, index).is_null()) { | 5256 if (!GetOwnElementAccessorPair(object, index).is_null()) { |
5260 old_value = Handle<Object>::cast(factory->the_hole_value()); | 5257 old_value = Handle<Object>::cast(factory->the_hole_value()); |
5261 } else { | 5258 } else { |
5262 old_value = Object::GetElement( | 5259 old_value = Object::GetElement( |
5263 isolate, object, index).ToHandleChecked(); | 5260 isolate, object, index).ToHandleChecked(); |
5264 } | 5261 } |
5265 } | 5262 } |
5266 } | 5263 } |
5267 | 5264 |
5268 // Skip interceptor if forcing deletion. | 5265 // Skip interceptor if forcing deletion. |
5269 MaybeHandle<Object> maybe_result; | 5266 MaybeHandle<Object> maybe_result; |
5270 if (object->HasIndexedInterceptor() && mode != FORCE_DELETION) { | 5267 if (object->HasIndexedInterceptor() && mode != FORCE_DELETION) { |
5271 maybe_result = DeleteElementWithInterceptor(object, index); | 5268 maybe_result = DeleteElementWithInterceptor(object, index); |
5272 } else { | 5269 } else { |
5273 maybe_result = object->GetElementsAccessor()->Delete(object, index, mode); | 5270 maybe_result = object->GetElementsAccessor()->Delete(object, index, mode); |
5274 } | 5271 } |
5275 Handle<Object> result; | 5272 Handle<Object> result; |
5276 ASSIGN_RETURN_ON_EXCEPTION(isolate, result, maybe_result, Object); | 5273 ASSIGN_RETURN_ON_EXCEPTION(isolate, result, maybe_result, Object); |
5277 | 5274 |
5278 if (should_enqueue_change_record && !HasOwnElement(object, index)) { | 5275 if (should_enqueue_change_record) { |
5279 Handle<String> name = factory->Uint32ToString(index); | 5276 Maybe<bool> maybe = HasOwnElement(object, index); |
5280 EnqueueChangeRecord(object, "delete", name, old_value); | 5277 if (!maybe.has_value) return MaybeHandle<Object>(); |
| 5278 if (!maybe.value) { |
| 5279 Handle<String> name = factory->Uint32ToString(index); |
| 5280 EnqueueChangeRecord(object, "delete", name, old_value); |
| 5281 } |
5281 } | 5282 } |
5282 | 5283 |
5283 return result; | 5284 return result; |
5284 } | 5285 } |
5285 | 5286 |
5286 | 5287 |
5287 MaybeHandle<Object> JSObject::DeleteProperty(Handle<JSObject> object, | 5288 MaybeHandle<Object> JSObject::DeleteProperty(Handle<JSObject> object, |
5288 Handle<Name> name, | 5289 Handle<Name> name, |
5289 DeleteMode mode) { | 5290 DeleteMode mode) { |
5290 Isolate* isolate = object->GetIsolate(); | 5291 Isolate* isolate = object->GetIsolate(); |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5348 DeletePropertyWithInterceptor(object, name), | 5349 DeletePropertyWithInterceptor(object, name), |
5349 Object); | 5350 Object); |
5350 } | 5351 } |
5351 } else { | 5352 } else { |
5352 // Normalize object if needed. | 5353 // Normalize object if needed. |
5353 NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0); | 5354 NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0); |
5354 // Make sure the properties are normalized before removing the entry. | 5355 // Make sure the properties are normalized before removing the entry. |
5355 result = DeleteNormalizedProperty(object, name, mode); | 5356 result = DeleteNormalizedProperty(object, name, mode); |
5356 } | 5357 } |
5357 | 5358 |
5358 if (is_observed && !HasOwnProperty(object, name)) { | 5359 if (is_observed) { |
5359 EnqueueChangeRecord(object, "delete", name, old_value); | 5360 Maybe<bool> maybe = HasOwnProperty(object, name); |
| 5361 if (!maybe.has_value) return MaybeHandle<Object>(); |
| 5362 if (!maybe.value) { |
| 5363 EnqueueChangeRecord(object, "delete", name, old_value); |
| 5364 } |
5360 } | 5365 } |
5361 | 5366 |
5362 return result; | 5367 return result; |
5363 } | 5368 } |
5364 | 5369 |
5365 | 5370 |
5366 MaybeHandle<Object> JSReceiver::DeleteElement(Handle<JSReceiver> object, | 5371 MaybeHandle<Object> JSReceiver::DeleteElement(Handle<JSReceiver> object, |
5367 uint32_t index, | 5372 uint32_t index, |
5368 DeleteMode mode) { | 5373 DeleteMode mode) { |
5369 if (object->IsJSProxy()) { | 5374 if (object->IsJSProxy()) { |
(...skipping 462 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5832 copy->FastPropertyAtPut(index, *value); | 5837 copy->FastPropertyAtPut(index, *value); |
5833 } | 5838 } |
5834 } | 5839 } |
5835 } else { | 5840 } else { |
5836 Handle<FixedArray> names = | 5841 Handle<FixedArray> names = |
5837 isolate->factory()->NewFixedArray(copy->NumberOfOwnProperties()); | 5842 isolate->factory()->NewFixedArray(copy->NumberOfOwnProperties()); |
5838 copy->GetOwnPropertyNames(*names, 0); | 5843 copy->GetOwnPropertyNames(*names, 0); |
5839 for (int i = 0; i < names->length(); i++) { | 5844 for (int i = 0; i < names->length(); i++) { |
5840 ASSERT(names->get(i)->IsString()); | 5845 ASSERT(names->get(i)->IsString()); |
5841 Handle<String> key_string(String::cast(names->get(i))); | 5846 Handle<String> key_string(String::cast(names->get(i))); |
5842 PropertyAttributes attributes = | 5847 Maybe<PropertyAttributes> maybe = |
5843 JSReceiver::GetOwnPropertyAttributes(copy, key_string); | 5848 JSReceiver::GetOwnPropertyAttributes(copy, key_string); |
| 5849 ASSERT(maybe.has_value); |
| 5850 PropertyAttributes attributes = maybe.value; |
5844 // Only deep copy fields from the object literal expression. | 5851 // Only deep copy fields from the object literal expression. |
5845 // In particular, don't try to copy the length attribute of | 5852 // In particular, don't try to copy the length attribute of |
5846 // an array. | 5853 // an array. |
5847 if (attributes != NONE) continue; | 5854 if (attributes != NONE) continue; |
5848 Handle<Object> value = | 5855 Handle<Object> value = |
5849 Object::GetProperty(copy, key_string).ToHandleChecked(); | 5856 Object::GetProperty(copy, key_string).ToHandleChecked(); |
5850 if (value->IsJSObject()) { | 5857 if (value->IsJSObject()) { |
5851 Handle<JSObject> result; | 5858 Handle<JSObject> result; |
5852 ASSIGN_RETURN_ON_EXCEPTION( | 5859 ASSIGN_RETURN_ON_EXCEPTION( |
5853 isolate, result, | 5860 isolate, result, |
(...skipping 727 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6581 // object. | 6588 // object. |
6582 Deoptimizer::DeoptimizeGlobalObject(*object); | 6589 Deoptimizer::DeoptimizeGlobalObject(*object); |
6583 } | 6590 } |
6584 | 6591 |
6585 // Update the dictionary with the new CALLBACKS property. | 6592 // Update the dictionary with the new CALLBACKS property. |
6586 PropertyDetails details = PropertyDetails(attributes, CALLBACKS, 0); | 6593 PropertyDetails details = PropertyDetails(attributes, CALLBACKS, 0); |
6587 SetNormalizedProperty(object, name, structure, details); | 6594 SetNormalizedProperty(object, name, structure, details); |
6588 } | 6595 } |
6589 | 6596 |
6590 | 6597 |
6591 void JSObject::DefineAccessor(Handle<JSObject> object, | 6598 MaybeHandle<Object> JSObject::DefineAccessor(Handle<JSObject> object, |
6592 Handle<Name> name, | 6599 Handle<Name> name, |
6593 Handle<Object> getter, | 6600 Handle<Object> getter, |
6594 Handle<Object> setter, | 6601 Handle<Object> setter, |
6595 PropertyAttributes attributes) { | 6602 PropertyAttributes attributes) { |
6596 Isolate* isolate = object->GetIsolate(); | 6603 Isolate* isolate = object->GetIsolate(); |
6597 // Check access rights if needed. | 6604 // Check access rights if needed. |
6598 if (object->IsAccessCheckNeeded() && | 6605 if (object->IsAccessCheckNeeded() && |
6599 !isolate->MayNamedAccess(object, name, v8::ACCESS_SET)) { | 6606 !isolate->MayNamedAccess(object, name, v8::ACCESS_SET)) { |
6600 isolate->ReportFailedAccessCheck(object, v8::ACCESS_SET); | 6607 isolate->ReportFailedAccessCheck(object, v8::ACCESS_SET); |
6601 // TODO(yangguo): Issue 3269, check for scheduled exception missing? | 6608 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object); |
6602 return; | 6609 return isolate->factory()->undefined_value(); |
6603 } | 6610 } |
6604 | 6611 |
6605 if (object->IsJSGlobalProxy()) { | 6612 if (object->IsJSGlobalProxy()) { |
6606 PrototypeIterator iter(isolate, object); | 6613 PrototypeIterator iter(isolate, object); |
6607 if (iter.IsAtEnd()) return; | 6614 if (iter.IsAtEnd()) return isolate->factory()->undefined_value(); |
6608 ASSERT(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject()); | 6615 ASSERT(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject()); |
6609 DefineAccessor(Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)), | 6616 DefineAccessor(Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)), |
6610 name, getter, setter, attributes); | 6617 name, getter, setter, attributes); |
6611 return; | 6618 return isolate->factory()->undefined_value(); |
6612 } | 6619 } |
6613 | 6620 |
6614 // Make sure that the top context does not change when doing callbacks or | 6621 // Make sure that the top context does not change when doing callbacks or |
6615 // interceptor calls. | 6622 // interceptor calls. |
6616 AssertNoContextChange ncc(isolate); | 6623 AssertNoContextChange ncc(isolate); |
6617 | 6624 |
6618 // Try to flatten before operating on the string. | 6625 // Try to flatten before operating on the string. |
6619 if (name->IsString()) name = String::Flatten(Handle<String>::cast(name)); | 6626 if (name->IsString()) name = String::Flatten(Handle<String>::cast(name)); |
6620 | 6627 |
6621 uint32_t index = 0; | 6628 uint32_t index = 0; |
6622 bool is_element = name->AsArrayIndex(&index); | 6629 bool is_element = name->AsArrayIndex(&index); |
6623 | 6630 |
6624 Handle<Object> old_value = isolate->factory()->the_hole_value(); | 6631 Handle<Object> old_value = isolate->factory()->the_hole_value(); |
6625 bool is_observed = object->map()->is_observed() && | 6632 bool is_observed = object->map()->is_observed() && |
6626 *name != isolate->heap()->hidden_string(); | 6633 *name != isolate->heap()->hidden_string(); |
6627 bool preexists = false; | 6634 bool preexists = false; |
6628 if (is_observed) { | 6635 if (is_observed) { |
6629 if (is_element) { | 6636 if (is_element) { |
6630 preexists = HasOwnElement(object, index); | 6637 Maybe<bool> maybe = HasOwnElement(object, index); |
| 6638 ASSERT(maybe.has_value); |
| 6639 preexists = maybe.value; |
6631 if (preexists && GetOwnElementAccessorPair(object, index).is_null()) { | 6640 if (preexists && GetOwnElementAccessorPair(object, index).is_null()) { |
6632 old_value = | 6641 old_value = |
6633 Object::GetElement(isolate, object, index).ToHandleChecked(); | 6642 Object::GetElement(isolate, object, index).ToHandleChecked(); |
6634 } | 6643 } |
6635 } else { | 6644 } else { |
6636 LookupResult lookup(isolate); | 6645 LookupResult lookup(isolate); |
6637 object->LookupOwn(name, &lookup, true); | 6646 object->LookupOwn(name, &lookup, true); |
6638 preexists = lookup.IsProperty(); | 6647 preexists = lookup.IsProperty(); |
6639 if (preexists && lookup.IsDataProperty()) { | 6648 if (preexists && lookup.IsDataProperty()) { |
6640 old_value = | 6649 old_value = |
6641 Object::GetPropertyOrElement(object, name).ToHandleChecked(); | 6650 Object::GetPropertyOrElement(object, name).ToHandleChecked(); |
6642 } | 6651 } |
6643 } | 6652 } |
6644 } | 6653 } |
6645 | 6654 |
6646 if (is_element) { | 6655 if (is_element) { |
6647 DefineElementAccessor(object, index, getter, setter, attributes); | 6656 DefineElementAccessor(object, index, getter, setter, attributes); |
6648 } else { | 6657 } else { |
6649 DefinePropertyAccessor(object, name, getter, setter, attributes); | 6658 DefinePropertyAccessor(object, name, getter, setter, attributes); |
6650 } | 6659 } |
6651 | 6660 |
6652 if (is_observed) { | 6661 if (is_observed) { |
6653 const char* type = preexists ? "reconfigure" : "add"; | 6662 const char* type = preexists ? "reconfigure" : "add"; |
6654 EnqueueChangeRecord(object, type, name, old_value); | 6663 EnqueueChangeRecord(object, type, name, old_value); |
6655 } | 6664 } |
| 6665 |
| 6666 return isolate->factory()->undefined_value(); |
6656 } | 6667 } |
6657 | 6668 |
6658 | 6669 |
6659 static bool TryAccessorTransition(Handle<JSObject> self, | 6670 static bool TryAccessorTransition(Handle<JSObject> self, |
6660 Handle<Map> transitioned_map, | 6671 Handle<Map> transitioned_map, |
6661 int target_descriptor, | 6672 int target_descriptor, |
6662 AccessorComponent component, | 6673 AccessorComponent component, |
6663 Handle<Object> accessor, | 6674 Handle<Object> accessor, |
6664 PropertyAttributes attributes) { | 6675 PropertyAttributes attributes) { |
6665 DescriptorArray* descs = transitioned_map->instance_descriptors(); | 6676 DescriptorArray* descs = transitioned_map->instance_descriptors(); |
(...skipping 4982 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
11648 | 11659 |
11649 | 11660 |
11650 // Returns false if the passed-in index is marked non-configurable, | 11661 // Returns false if the passed-in index is marked non-configurable, |
11651 // which will cause the ES5 truncation operation to halt, and thus | 11662 // which will cause the ES5 truncation operation to halt, and thus |
11652 // no further old values need be collected. | 11663 // no further old values need be collected. |
11653 static bool GetOldValue(Isolate* isolate, | 11664 static bool GetOldValue(Isolate* isolate, |
11654 Handle<JSObject> object, | 11665 Handle<JSObject> object, |
11655 uint32_t index, | 11666 uint32_t index, |
11656 List<Handle<Object> >* old_values, | 11667 List<Handle<Object> >* old_values, |
11657 List<uint32_t>* indices) { | 11668 List<uint32_t>* indices) { |
11658 PropertyAttributes attributes = | 11669 Maybe<PropertyAttributes> maybe = |
11659 JSReceiver::GetOwnElementAttribute(object, index); | 11670 JSReceiver::GetOwnElementAttribute(object, index); |
11660 ASSERT(attributes != ABSENT); | 11671 ASSERT(maybe.has_value); |
11661 if (attributes == DONT_DELETE) return false; | 11672 ASSERT(maybe.value != ABSENT); |
| 11673 if (maybe.value == DONT_DELETE) return false; |
11662 Handle<Object> value; | 11674 Handle<Object> value; |
11663 if (!JSObject::GetOwnElementAccessorPair(object, index).is_null()) { | 11675 if (!JSObject::GetOwnElementAccessorPair(object, index).is_null()) { |
11664 value = Handle<Object>::cast(isolate->factory()->the_hole_value()); | 11676 value = Handle<Object>::cast(isolate->factory()->the_hole_value()); |
11665 } else { | 11677 } else { |
11666 value = Object::GetElement(isolate, object, index).ToHandleChecked(); | 11678 value = Object::GetElement(isolate, object, index).ToHandleChecked(); |
11667 } | 11679 } |
11668 old_values->Add(value); | 11680 old_values->Add(value); |
11669 indices->Add(index); | 11681 indices->Add(index); |
11670 return true; | 11682 return true; |
11671 } | 11683 } |
(...skipping 1212 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
12884 } | 12896 } |
12885 | 12897 |
12886 if (!object->map()->is_observed()) { | 12898 if (!object->map()->is_observed()) { |
12887 return object->HasIndexedInterceptor() | 12899 return object->HasIndexedInterceptor() |
12888 ? SetElementWithInterceptor(object, index, value, attributes, | 12900 ? SetElementWithInterceptor(object, index, value, attributes, |
12889 strict_mode, check_prototype, set_mode) | 12901 strict_mode, check_prototype, set_mode) |
12890 : SetElementWithoutInterceptor(object, index, value, attributes, | 12902 : SetElementWithoutInterceptor(object, index, value, attributes, |
12891 strict_mode, check_prototype, set_mode); | 12903 strict_mode, check_prototype, set_mode); |
12892 } | 12904 } |
12893 | 12905 |
12894 PropertyAttributes old_attributes = | 12906 Maybe<PropertyAttributes> maybe = |
12895 JSReceiver::GetOwnElementAttribute(object, index); | 12907 JSReceiver::GetOwnElementAttribute(object, index); |
| 12908 if (!maybe.has_value) return MaybeHandle<Object>(); |
| 12909 PropertyAttributes old_attributes = maybe.value; |
| 12910 |
12896 Handle<Object> old_value = isolate->factory()->the_hole_value(); | 12911 Handle<Object> old_value = isolate->factory()->the_hole_value(); |
12897 Handle<Object> old_length_handle; | 12912 Handle<Object> old_length_handle; |
12898 Handle<Object> new_length_handle; | 12913 Handle<Object> new_length_handle; |
12899 | 12914 |
12900 if (old_attributes != ABSENT) { | 12915 if (old_attributes != ABSENT) { |
12901 if (GetOwnElementAccessorPair(object, index).is_null()) { | 12916 if (GetOwnElementAccessorPair(object, index).is_null()) { |
12902 old_value = Object::GetElement(isolate, object, index).ToHandleChecked(); | 12917 old_value = Object::GetElement(isolate, object, index).ToHandleChecked(); |
12903 } | 12918 } |
12904 } else if (object->IsJSArray()) { | 12919 } else if (object->IsJSArray()) { |
12905 // Store old array length in case adding an element grows the array. | 12920 // Store old array length in case adding an element grows the array. |
12906 old_length_handle = handle(Handle<JSArray>::cast(object)->length(), | 12921 old_length_handle = handle(Handle<JSArray>::cast(object)->length(), |
12907 isolate); | 12922 isolate); |
12908 } | 12923 } |
12909 | 12924 |
12910 // Check for lookup interceptor | 12925 // Check for lookup interceptor |
12911 Handle<Object> result; | 12926 Handle<Object> result; |
12912 ASSIGN_RETURN_ON_EXCEPTION( | 12927 ASSIGN_RETURN_ON_EXCEPTION( |
12913 isolate, result, | 12928 isolate, result, |
12914 object->HasIndexedInterceptor() | 12929 object->HasIndexedInterceptor() |
12915 ? SetElementWithInterceptor( | 12930 ? SetElementWithInterceptor( |
12916 object, index, value, attributes, | 12931 object, index, value, attributes, |
12917 strict_mode, check_prototype, set_mode) | 12932 strict_mode, check_prototype, set_mode) |
12918 : SetElementWithoutInterceptor( | 12933 : SetElementWithoutInterceptor( |
12919 object, index, value, attributes, | 12934 object, index, value, attributes, |
12920 strict_mode, check_prototype, set_mode), | 12935 strict_mode, check_prototype, set_mode), |
12921 Object); | 12936 Object); |
12922 | 12937 |
12923 Handle<String> name = isolate->factory()->Uint32ToString(index); | 12938 Handle<String> name = isolate->factory()->Uint32ToString(index); |
12924 PropertyAttributes new_attributes = GetOwnElementAttribute(object, index); | 12939 maybe = GetOwnElementAttribute(object, index); |
| 12940 if (!maybe.has_value) return MaybeHandle<Object>(); |
| 12941 PropertyAttributes new_attributes = maybe.value; |
| 12942 |
12925 if (old_attributes == ABSENT) { | 12943 if (old_attributes == ABSENT) { |
12926 if (object->IsJSArray() && | 12944 if (object->IsJSArray() && |
12927 !old_length_handle->SameValue( | 12945 !old_length_handle->SameValue( |
12928 Handle<JSArray>::cast(object)->length())) { | 12946 Handle<JSArray>::cast(object)->length())) { |
12929 new_length_handle = handle(Handle<JSArray>::cast(object)->length(), | 12947 new_length_handle = handle(Handle<JSArray>::cast(object)->length(), |
12930 isolate); | 12948 isolate); |
12931 uint32_t old_length = 0; | 12949 uint32_t old_length = 0; |
12932 uint32_t new_length = 0; | 12950 uint32_t new_length = 0; |
12933 CHECK(old_length_handle->ToArrayIndex(&old_length)); | 12951 CHECK(old_length_handle->ToArrayIndex(&old_length)); |
12934 CHECK(new_length_handle->ToArrayIndex(&new_length)); | 12952 CHECK(new_length_handle->ToArrayIndex(&new_length)); |
(...skipping 749 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
13684 if (result.IsEmpty()) return MaybeHandle<JSObject>(); | 13702 if (result.IsEmpty()) return MaybeHandle<JSObject>(); |
13685 #if ENABLE_EXTRA_CHECKS | 13703 #if ENABLE_EXTRA_CHECKS |
13686 CHECK(v8::Utils::OpenHandle(*result)->IsJSArray() || | 13704 CHECK(v8::Utils::OpenHandle(*result)->IsJSArray() || |
13687 v8::Utils::OpenHandle(*result)->HasSloppyArgumentsElements()); | 13705 v8::Utils::OpenHandle(*result)->HasSloppyArgumentsElements()); |
13688 #endif | 13706 #endif |
13689 // Rebox before returning. | 13707 // Rebox before returning. |
13690 return handle(*v8::Utils::OpenHandle(*result), isolate); | 13708 return handle(*v8::Utils::OpenHandle(*result), isolate); |
13691 } | 13709 } |
13692 | 13710 |
13693 | 13711 |
13694 bool JSObject::HasRealNamedProperty(Handle<JSObject> object, | 13712 Maybe<bool> JSObject::HasRealNamedProperty(Handle<JSObject> object, |
13695 Handle<Name> key) { | 13713 Handle<Name> key) { |
13696 Isolate* isolate = object->GetIsolate(); | 13714 Isolate* isolate = object->GetIsolate(); |
13697 SealHandleScope shs(isolate); | 13715 SealHandleScope shs(isolate); |
13698 // Check access rights if needed. | 13716 // Check access rights if needed. |
13699 if (object->IsAccessCheckNeeded()) { | 13717 if (object->IsAccessCheckNeeded()) { |
13700 if (!isolate->MayNamedAccess(object, key, v8::ACCESS_HAS)) { | 13718 if (!isolate->MayNamedAccess(object, key, v8::ACCESS_HAS)) { |
13701 isolate->ReportFailedAccessCheck(object, v8::ACCESS_HAS); | 13719 isolate->ReportFailedAccessCheck(object, v8::ACCESS_HAS); |
13702 // TODO(yangguo): Issue 3269, check for scheduled exception missing? | 13720 RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Maybe<bool>()); |
13703 return false; | 13721 return maybe(false); |
13704 } | 13722 } |
13705 } | 13723 } |
13706 | 13724 |
13707 LookupResult result(isolate); | 13725 LookupResult result(isolate); |
13708 object->LookupOwnRealNamedProperty(key, &result); | 13726 object->LookupOwnRealNamedProperty(key, &result); |
13709 return result.IsFound() && !result.IsInterceptor(); | 13727 return maybe(result.IsFound() && !result.IsInterceptor()); |
13710 } | 13728 } |
13711 | 13729 |
13712 | 13730 |
13713 bool JSObject::HasRealElementProperty(Handle<JSObject> object, uint32_t index) { | 13731 Maybe<bool> JSObject::HasRealElementProperty(Handle<JSObject> object, |
| 13732 uint32_t index) { |
13714 Isolate* isolate = object->GetIsolate(); | 13733 Isolate* isolate = object->GetIsolate(); |
13715 HandleScope scope(isolate); | 13734 HandleScope scope(isolate); |
13716 // Check access rights if needed. | 13735 // Check access rights if needed. |
13717 if (object->IsAccessCheckNeeded()) { | 13736 if (object->IsAccessCheckNeeded()) { |
13718 if (!isolate->MayIndexedAccess(object, index, v8::ACCESS_HAS)) { | 13737 if (!isolate->MayIndexedAccess(object, index, v8::ACCESS_HAS)) { |
13719 isolate->ReportFailedAccessCheck(object, v8::ACCESS_HAS); | 13738 isolate->ReportFailedAccessCheck(object, v8::ACCESS_HAS); |
13720 // TODO(yangguo): Issue 3269, check for scheduled exception missing? | 13739 RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Maybe<bool>()); |
13721 return false; | 13740 return maybe(false); |
13722 } | 13741 } |
13723 } | 13742 } |
13724 | 13743 |
13725 if (object->IsJSGlobalProxy()) { | 13744 if (object->IsJSGlobalProxy()) { |
13726 HandleScope scope(isolate); | 13745 HandleScope scope(isolate); |
13727 PrototypeIterator iter(isolate, object); | 13746 PrototypeIterator iter(isolate, object); |
13728 if (iter.IsAtEnd()) return false; | 13747 if (iter.IsAtEnd()) return maybe(false); |
13729 ASSERT(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject()); | 13748 ASSERT(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject()); |
13730 return HasRealElementProperty( | 13749 return HasRealElementProperty( |
13731 Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)), index); | 13750 Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)), index); |
13732 } | 13751 } |
13733 | 13752 |
13734 return GetElementAttributeWithoutInterceptor( | 13753 Maybe<PropertyAttributes> result = |
13735 object, object, index, false) != ABSENT; | 13754 GetElementAttributeWithoutInterceptor(object, object, index, false); |
| 13755 if (!result.has_value) return Maybe<bool>(); |
| 13756 return maybe(result.value != ABSENT); |
13736 } | 13757 } |
13737 | 13758 |
13738 | 13759 |
13739 bool JSObject::HasRealNamedCallbackProperty(Handle<JSObject> object, | 13760 Maybe<bool> JSObject::HasRealNamedCallbackProperty(Handle<JSObject> object, |
13740 Handle<Name> key) { | 13761 Handle<Name> key) { |
13741 Isolate* isolate = object->GetIsolate(); | 13762 Isolate* isolate = object->GetIsolate(); |
13742 SealHandleScope shs(isolate); | 13763 SealHandleScope shs(isolate); |
13743 // Check access rights if needed. | 13764 // Check access rights if needed. |
13744 if (object->IsAccessCheckNeeded()) { | 13765 if (object->IsAccessCheckNeeded()) { |
13745 if (!isolate->MayNamedAccess(object, key, v8::ACCESS_HAS)) { | 13766 if (!isolate->MayNamedAccess(object, key, v8::ACCESS_HAS)) { |
13746 isolate->ReportFailedAccessCheck(object, v8::ACCESS_HAS); | 13767 isolate->ReportFailedAccessCheck(object, v8::ACCESS_HAS); |
13747 // TODO(yangguo): Issue 3269, check for scheduled exception missing? | 13768 RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Maybe<bool>()); |
13748 return false; | 13769 return maybe(false); |
13749 } | 13770 } |
13750 } | 13771 } |
13751 | 13772 |
13752 LookupResult result(isolate); | 13773 LookupResult result(isolate); |
13753 object->LookupOwnRealNamedProperty(key, &result); | 13774 object->LookupOwnRealNamedProperty(key, &result); |
13754 return result.IsPropertyCallbacks(); | 13775 return maybe(result.IsPropertyCallbacks()); |
13755 } | 13776 } |
13756 | 13777 |
13757 | 13778 |
13758 int JSObject::NumberOfOwnProperties(PropertyAttributes filter) { | 13779 int JSObject::NumberOfOwnProperties(PropertyAttributes filter) { |
13759 if (HasFastProperties()) { | 13780 if (HasFastProperties()) { |
13760 Map* map = this->map(); | 13781 Map* map = this->map(); |
13761 if (filter == NONE) return map->NumberOfOwnDescriptors(); | 13782 if (filter == NONE) return map->NumberOfOwnDescriptors(); |
13762 if (filter & DONT_ENUM) { | 13783 if (filter & DONT_ENUM) { |
13763 int result = map->EnumLength(); | 13784 int result = map->EnumLength(); |
13764 if (result != kInvalidEnumCacheSentinel) return result; | 13785 if (result != kInvalidEnumCacheSentinel) return result; |
(...skipping 3177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
16942 #define ERROR_MESSAGES_TEXTS(C, T) T, | 16963 #define ERROR_MESSAGES_TEXTS(C, T) T, |
16943 static const char* error_messages_[] = { | 16964 static const char* error_messages_[] = { |
16944 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS) | 16965 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS) |
16945 }; | 16966 }; |
16946 #undef ERROR_MESSAGES_TEXTS | 16967 #undef ERROR_MESSAGES_TEXTS |
16947 return error_messages_[reason]; | 16968 return error_messages_[reason]; |
16948 } | 16969 } |
16949 | 16970 |
16950 | 16971 |
16951 } } // namespace v8::internal | 16972 } } // namespace v8::internal |
OLD | NEW |