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 3715 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3726 args.Call(setter, v8::Utils::ToLocal(name), v8::Utils::ToLocal(value)); | 3726 args.Call(setter, v8::Utils::ToLocal(name), v8::Utils::ToLocal(value)); |
3727 } | 3727 } |
3728 | 3728 |
3729 RETURN_VALUE_IF_SCHEDULED_EXCEPTION(it->isolate(), Nothing<bool>()); | 3729 RETURN_VALUE_IF_SCHEDULED_EXCEPTION(it->isolate(), Nothing<bool>()); |
3730 if (result.IsEmpty()) return Just(false); | 3730 if (result.IsEmpty()) return Just(false); |
3731 #ifdef DEBUG | 3731 #ifdef DEBUG |
3732 Handle<Object> result_internal = v8::Utils::OpenHandle(*result); | 3732 Handle<Object> result_internal = v8::Utils::OpenHandle(*result); |
3733 result_internal->VerifyApiCallResultType(); | 3733 result_internal->VerifyApiCallResultType(); |
3734 #endif | 3734 #endif |
3735 return Just(true); | 3735 return Just(true); |
| 3736 // TODO(neis): In the future, we may want to actually return the interceptor's |
| 3737 // result, which then should be a boolean. |
3736 } | 3738 } |
3737 | 3739 |
3738 | 3740 |
3739 MaybeHandle<Object> Object::SetProperty(Handle<Object> object, | 3741 MaybeHandle<Object> Object::SetProperty(Handle<Object> object, |
3740 Handle<Name> name, Handle<Object> value, | 3742 Handle<Name> name, Handle<Object> value, |
3741 LanguageMode language_mode, | 3743 LanguageMode language_mode, |
3742 StoreFromKeyed store_mode) { | 3744 StoreFromKeyed store_mode) { |
3743 LookupIterator it(object, name); | 3745 LookupIterator it(object, name); |
3744 MAYBE_RETURN_NULL(SetProperty(&it, value, language_mode, store_mode)); | 3746 MAYBE_RETURN_NULL(SetProperty(&it, value, language_mode, store_mode)); |
3745 return value; | 3747 return value; |
(...skipping 21 matching lines...) Expand all Loading... |
3767 UNREACHABLE(); | 3769 UNREACHABLE(); |
3768 | 3770 |
3769 case LookupIterator::ACCESS_CHECK: | 3771 case LookupIterator::ACCESS_CHECK: |
3770 if (it->HasAccess()) break; | 3772 if (it->HasAccess()) break; |
3771 // Check whether it makes sense to reuse the lookup iterator. Here it | 3773 // Check whether it makes sense to reuse the lookup iterator. Here it |
3772 // might still call into setters up the prototype chain. | 3774 // might still call into setters up the prototype chain. |
3773 return JSObject::SetPropertyWithFailedAccessCheck(it, value, | 3775 return JSObject::SetPropertyWithFailedAccessCheck(it, value, |
3774 should_throw); | 3776 should_throw); |
3775 | 3777 |
3776 case LookupIterator::JSPROXY: | 3778 case LookupIterator::JSPROXY: |
3777 if (it->HolderIsReceiverOrHiddenPrototype()) { | 3779 return JSProxy::SetProperty(it->GetHolder<JSProxy>(), it->GetName(), |
3778 return JSProxy::SetPropertyWithHandler( | 3780 value, it->GetReceiver(), language_mode); |
3779 it->GetHolder<JSProxy>(), it->GetReceiver(), it->GetName(), value, | |
3780 should_throw); | |
3781 } else { | |
3782 // TODO(verwaest): Use the MaybeHandle to indicate result. | |
3783 bool has_result = false; | |
3784 Maybe<bool> maybe_result = | |
3785 JSProxy::SetPropertyViaPrototypesWithHandler( | |
3786 it->GetHolder<JSProxy>(), it->GetReceiver(), it->GetName(), | |
3787 value, should_throw, &has_result); | |
3788 if (has_result) return maybe_result; | |
3789 done = true; | |
3790 } | |
3791 break; | |
3792 | 3781 |
3793 case LookupIterator::INTERCEPTOR: | 3782 case LookupIterator::INTERCEPTOR: |
3794 if (it->HolderIsReceiverOrHiddenPrototype()) { | 3783 if (it->HolderIsReceiverOrHiddenPrototype()) { |
3795 Maybe<bool> result = JSObject::SetPropertyWithInterceptor(it, value); | 3784 Maybe<bool> result = JSObject::SetPropertyWithInterceptor(it, value); |
3796 if (result.IsNothing() || result.FromJust()) return result; | 3785 if (result.IsNothing() || result.FromJust()) return result; |
3797 } else { | 3786 } else { |
3798 Maybe<PropertyAttributes> maybe_attributes = | 3787 Maybe<PropertyAttributes> maybe_attributes = |
3799 JSObject::GetPropertyAttributesWithInterceptor(it); | 3788 JSObject::GetPropertyAttributesWithInterceptor(it); |
3800 if (!maybe_attributes.IsJust()) return Nothing<bool>(); | 3789 if (!maybe_attributes.IsJust()) return Nothing<bool>(); |
3801 done = maybe_attributes.FromJust() != ABSENT; | 3790 done = maybe_attributes.FromJust() != ABSENT; |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3865 is_sloppy(language_mode) ? DONT_THROW : THROW_ON_ERROR; | 3854 is_sloppy(language_mode) ? DONT_THROW : THROW_ON_ERROR; |
3866 return AddDataProperty(it, value, NONE, should_throw, store_mode); | 3855 return AddDataProperty(it, value, NONE, should_throw, store_mode); |
3867 } | 3856 } |
3868 | 3857 |
3869 | 3858 |
3870 Maybe<bool> Object::SetSuperProperty(LookupIterator* it, Handle<Object> value, | 3859 Maybe<bool> Object::SetSuperProperty(LookupIterator* it, Handle<Object> value, |
3871 LanguageMode language_mode, | 3860 LanguageMode language_mode, |
3872 StoreFromKeyed store_mode) { | 3861 StoreFromKeyed store_mode) { |
3873 ShouldThrow should_throw = | 3862 ShouldThrow should_throw = |
3874 is_sloppy(language_mode) ? DONT_THROW : THROW_ON_ERROR; | 3863 is_sloppy(language_mode) ? DONT_THROW : THROW_ON_ERROR; |
| 3864 Isolate* isolate = it->isolate(); |
3875 | 3865 |
3876 bool found = false; | 3866 bool found = false; |
3877 Maybe<bool> result = | 3867 Maybe<bool> result = |
3878 SetPropertyInternal(it, value, language_mode, store_mode, &found); | 3868 SetPropertyInternal(it, value, language_mode, store_mode, &found); |
3879 if (found) return result; | 3869 if (found) return result; |
3880 | 3870 |
3881 // The property either doesn't exist on the holder or exists there as a data | 3871 // The property either doesn't exist on the holder or exists there as a data |
3882 // property. | 3872 // property. |
3883 | 3873 |
3884 if (!it->GetReceiver()->IsJSReceiver()) { | 3874 if (!it->GetReceiver()->IsJSReceiver()) { |
3885 return WriteToReadOnlyProperty(it, value, should_throw); | 3875 return WriteToReadOnlyProperty(it, value, should_throw); |
3886 } | 3876 } |
| 3877 Handle<JSReceiver> receiver = Handle<JSReceiver>::cast(it->GetReceiver()); |
3887 | 3878 |
3888 LookupIterator::Configuration c = LookupIterator::OWN; | 3879 LookupIterator::Configuration c = LookupIterator::OWN; |
3889 LookupIterator own_lookup = | 3880 LookupIterator own_lookup = |
3890 it->IsElement() | 3881 it->IsElement() ? LookupIterator(isolate, receiver, it->index(), c) |
3891 ? LookupIterator(it->isolate(), it->GetReceiver(), it->index(), c) | 3882 : LookupIterator(receiver, it->name(), c); |
3892 : LookupIterator(it->GetReceiver(), it->name(), c); | |
3893 | 3883 |
3894 for (; own_lookup.IsFound(); own_lookup.Next()) { | 3884 for (; own_lookup.IsFound(); own_lookup.Next()) { |
3895 switch (own_lookup.state()) { | 3885 switch (own_lookup.state()) { |
3896 case LookupIterator::ACCESS_CHECK: | 3886 case LookupIterator::ACCESS_CHECK: |
3897 if (!own_lookup.HasAccess()) { | 3887 if (!own_lookup.HasAccess()) { |
3898 return JSObject::SetPropertyWithFailedAccessCheck(&own_lookup, value, | 3888 return JSObject::SetPropertyWithFailedAccessCheck(&own_lookup, value, |
3899 should_throw); | 3889 should_throw); |
3900 } | 3890 } |
3901 break; | 3891 break; |
3902 | 3892 |
3903 case LookupIterator::INTEGER_INDEXED_EXOTIC: | 3893 case LookupIterator::INTEGER_INDEXED_EXOTIC: |
3904 return RedefineIncompatibleProperty(it->isolate(), it->GetName(), value, | 3894 case LookupIterator::ACCESSOR: |
| 3895 return RedefineIncompatibleProperty(isolate, it->GetName(), value, |
3905 should_throw); | 3896 should_throw); |
3906 | 3897 |
3907 case LookupIterator::DATA: { | 3898 case LookupIterator::DATA: { |
3908 PropertyDetails details = own_lookup.property_details(); | 3899 PropertyDetails details = own_lookup.property_details(); |
3909 if (details.IsReadOnly()) { | 3900 if (details.IsReadOnly()) { |
3910 return WriteToReadOnlyProperty(&own_lookup, value, should_throw); | 3901 return WriteToReadOnlyProperty(&own_lookup, value, should_throw); |
3911 } | 3902 } |
3912 return SetDataProperty(&own_lookup, value); | 3903 return SetDataProperty(&own_lookup, value); |
3913 } | 3904 } |
3914 | 3905 |
3915 case LookupIterator::ACCESSOR: { | |
3916 return RedefineIncompatibleProperty(it->isolate(), it->GetName(), value, | |
3917 should_throw); | |
3918 } | |
3919 | |
3920 case LookupIterator::INTERCEPTOR: | 3906 case LookupIterator::INTERCEPTOR: |
3921 case LookupIterator::JSPROXY: { | 3907 case LookupIterator::JSPROXY: { |
3922 bool found = false; | 3908 PropertyDescriptor desc; |
3923 Maybe<bool> result = SetPropertyInternal( | 3909 bool owned = JSReceiver::GetOwnPropertyDescriptor(&own_lookup, &desc); |
3924 &own_lookup, value, language_mode, store_mode, &found); | 3910 if (isolate->has_pending_exception()) return Nothing<bool>(); |
3925 if (found) return result; | 3911 if (!owned) { |
3926 break; | 3912 return JSReceiver::CreateDataProperty(&own_lookup, value, |
| 3913 should_throw); |
| 3914 } |
| 3915 if (PropertyDescriptor::IsAccessorDescriptor(&desc) || |
| 3916 !desc.writable()) { |
| 3917 return RedefineIncompatibleProperty(isolate, it->GetName(), value, |
| 3918 should_throw); |
| 3919 } |
| 3920 |
| 3921 PropertyDescriptor value_desc; |
| 3922 value_desc.set_value(value); |
| 3923 bool result = JSReceiver::DefineOwnProperty( |
| 3924 isolate, receiver, it->GetName(), &value_desc, should_throw); |
| 3925 if (isolate->has_pending_exception()) return Nothing<bool>(); |
| 3926 return Just(result); |
3927 } | 3927 } |
3928 | 3928 |
3929 case LookupIterator::NOT_FOUND: | 3929 case LookupIterator::NOT_FOUND: |
3930 case LookupIterator::TRANSITION: | 3930 case LookupIterator::TRANSITION: |
3931 UNREACHABLE(); | 3931 UNREACHABLE(); |
3932 } | 3932 } |
3933 } | 3933 } |
3934 | 3934 |
3935 return JSObject::AddDataProperty(&own_lookup, value, NONE, should_throw, | 3935 return JSObject::AddDataProperty(&own_lookup, value, NONE, should_throw, |
3936 store_mode); | 3936 store_mode); |
(...skipping 645 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4582 isolate->Throw(*isolate->factory()->NewTypeError( | 4582 isolate->Throw(*isolate->factory()->NewTypeError( |
4583 MessageTemplate::kProxyTargetNotExtensible)); | 4583 MessageTemplate::kProxyTargetNotExtensible)); |
4584 } | 4584 } |
4585 } | 4585 } |
4586 } | 4586 } |
4587 // 10. Return booleanTrapResult. | 4587 // 10. Return booleanTrapResult. |
4588 return Just(boolean_trap_result); | 4588 return Just(boolean_trap_result); |
4589 } | 4589 } |
4590 | 4590 |
4591 | 4591 |
4592 Maybe<bool> JSProxy::SetPropertyWithHandler(Handle<JSProxy> proxy, | 4592 Maybe<bool> JSProxy::SetProperty(Handle<JSProxy> proxy, Handle<Name> name, |
4593 Handle<Object> receiver, | 4593 Handle<Object> value, Handle<Object> receiver, |
4594 Handle<Name> name, | 4594 LanguageMode language_mode) { |
4595 Handle<Object> value, | |
4596 ShouldThrow should_throw) { | |
4597 Isolate* isolate = proxy->GetIsolate(); | 4595 Isolate* isolate = proxy->GetIsolate(); |
| 4596 Factory* factory = isolate->factory(); |
| 4597 Handle<String> trap_name = factory->set_string(); |
| 4598 ShouldThrow should_throw = |
| 4599 is_sloppy(language_mode) ? DONT_THROW : THROW_ON_ERROR; |
4598 | 4600 |
4599 // TODO(rossberg): adjust once there is a story for symbols vs proxies. | 4601 if (proxy->IsRevoked()) { |
4600 if (name->IsSymbol()) return Just(true); | 4602 isolate->Throw( |
| 4603 *factory->NewTypeError(MessageTemplate::kProxyRevoked, trap_name)); |
| 4604 return Nothing<bool>(); |
| 4605 } |
4601 | 4606 |
4602 Handle<Object> args[] = { receiver, name, value }; | 4607 Handle<JSReceiver> target(JSReceiver::cast(proxy->target()), isolate); |
4603 RETURN_ON_EXCEPTION_VALUE(isolate, | 4608 Handle<JSReceiver> handler(JSReceiver::cast(proxy->handler()), isolate); |
4604 CallTrap(proxy, "set", isolate->derived_set_trap(), | |
4605 arraysize(args), args), | |
4606 Nothing<bool>()); | |
4607 | 4609 |
| 4610 Handle<Object> trap; |
| 4611 ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, trap, GetTrap(proxy, trap_name), |
| 4612 Nothing<bool>()); |
| 4613 if (trap->IsUndefined()) { |
| 4614 LookupIterator it = |
| 4615 LookupIterator::PropertyOrElement(isolate, receiver, name, target); |
| 4616 return Object::SetSuperProperty(&it, value, language_mode, |
| 4617 Object::MAY_BE_STORE_FROM_KEYED); |
| 4618 } |
| 4619 |
| 4620 Handle<Object> trap_result; |
| 4621 Handle<Object> args[] = {target, name, value, receiver}; |
| 4622 ASSIGN_RETURN_ON_EXCEPTION_VALUE( |
| 4623 isolate, trap_result, |
| 4624 Execution::Call(isolate, trap, handler, arraysize(args), args), |
| 4625 Nothing<bool>()); |
| 4626 if (!trap_result->BooleanValue()) { |
| 4627 RETURN_FAILURE(isolate, should_throw, |
| 4628 NewTypeError(MessageTemplate::kProxyHandlerReturned, handler, |
| 4629 factory->false_string(), trap_name)); |
| 4630 } |
| 4631 |
| 4632 // Enforce the invariant. |
| 4633 PropertyDescriptor target_desc; |
| 4634 bool owned = |
| 4635 JSReceiver::GetOwnPropertyDescriptor(isolate, target, name, &target_desc); |
| 4636 if (isolate->has_pending_exception()) return Nothing<bool>(); |
| 4637 if (owned) { |
| 4638 bool inconsistent = |
| 4639 (PropertyDescriptor::IsDataDescriptor(&target_desc) && |
| 4640 !target_desc.configurable() && !target_desc.writable() && |
| 4641 !value->SameValue(*target_desc.value())) || |
| 4642 (PropertyDescriptor::IsAccessorDescriptor(&target_desc) && |
| 4643 !target_desc.configurable() && target_desc.set()->IsUndefined()); |
| 4644 if (inconsistent) { |
| 4645 isolate->Throw(*isolate->factory()->NewTypeError( |
| 4646 MessageTemplate::kProxyTrapViolatesInvariant, trap_name)); |
| 4647 return Nothing<bool>(); |
| 4648 } |
| 4649 } |
4608 return Just(true); | 4650 return Just(true); |
4609 // TODO(neis): This needs to be made spec-conformant by looking at the | |
4610 // trap's result. | |
4611 } | 4651 } |
4612 | 4652 |
4613 | 4653 |
4614 Maybe<bool> JSProxy::SetPropertyViaPrototypesWithHandler( | |
4615 Handle<JSProxy> proxy, Handle<Object> receiver, Handle<Name> name, | |
4616 Handle<Object> value, ShouldThrow should_throw, bool* done) { | |
4617 Isolate* isolate = proxy->GetIsolate(); | |
4618 Handle<Object> handler(proxy->handler(), isolate); // Trap might morph proxy. | |
4619 | |
4620 // TODO(rossberg): adjust once there is a story for symbols vs proxies. | |
4621 if (name->IsSymbol()) { | |
4622 *done = false; // Return value will be ignored. | |
4623 return Nothing<bool>(); | |
4624 } | |
4625 | |
4626 *done = true; // except where redefined... | |
4627 Handle<Object> args[] = { name }; | |
4628 Handle<Object> result; | |
4629 ASSIGN_RETURN_ON_EXCEPTION_VALUE( | |
4630 isolate, result, CallTrap(proxy, "getPropertyDescriptor", | |
4631 Handle<Object>(), arraysize(args), args), | |
4632 Nothing<bool>()); | |
4633 | |
4634 if (result->IsUndefined()) { | |
4635 *done = false; // Return value will be ignored. | |
4636 return Nothing<bool>(); | |
4637 } | |
4638 | |
4639 // Emulate [[GetProperty]] semantics for proxies. | |
4640 Handle<Object> argv[] = { result }; | |
4641 Handle<Object> desc; | |
4642 ASSIGN_RETURN_ON_EXCEPTION_VALUE( | |
4643 isolate, desc, | |
4644 Execution::Call(isolate, isolate->to_complete_property_descriptor(), | |
4645 result, arraysize(argv), argv), | |
4646 Nothing<bool>()); | |
4647 | |
4648 // [[GetProperty]] requires to check that all properties are configurable. | |
4649 Handle<String> configurable_name = | |
4650 isolate->factory()->InternalizeOneByteString( | |
4651 STATIC_CHAR_VECTOR("configurable_")); | |
4652 Handle<Object> configurable = | |
4653 Object::GetProperty(desc, configurable_name).ToHandleChecked(); | |
4654 DCHECK(configurable->IsBoolean()); | |
4655 if (configurable->IsFalse()) { | |
4656 isolate->Throw(*isolate->factory()->NewTypeError( | |
4657 MessageTemplate::kProxyPropNotConfigurable, handler, name, | |
4658 isolate->factory()->NewStringFromAsciiChecked( | |
4659 "getPropertyDescriptor"))); | |
4660 return Nothing<bool>(); | |
4661 } | |
4662 DCHECK(configurable->IsTrue()); | |
4663 | |
4664 // Check for DataDescriptor. | |
4665 Handle<String> hasWritable_name = | |
4666 isolate->factory()->InternalizeOneByteString( | |
4667 STATIC_CHAR_VECTOR("hasWritable_")); | |
4668 Handle<Object> hasWritable = | |
4669 Object::GetProperty(desc, hasWritable_name).ToHandleChecked(); | |
4670 DCHECK(hasWritable->IsBoolean()); | |
4671 if (hasWritable->IsTrue()) { | |
4672 Handle<String> writable_name = isolate->factory()->InternalizeOneByteString( | |
4673 STATIC_CHAR_VECTOR("writable_")); | |
4674 Handle<Object> writable = | |
4675 Object::GetProperty(desc, writable_name).ToHandleChecked(); | |
4676 DCHECK(writable->IsBoolean()); | |
4677 *done = writable->IsFalse(); | |
4678 if (!*done) return Nothing<bool>(); // Return value will be ignored. | |
4679 return WriteToReadOnlyProperty(isolate, receiver, name, value, | |
4680 should_throw); | |
4681 } | |
4682 | |
4683 // We have an AccessorDescriptor. | |
4684 Handle<String> set_name = | |
4685 isolate->factory()->InternalizeOneByteString(STATIC_CHAR_VECTOR("set_")); | |
4686 Handle<Object> setter = Object::GetProperty(desc, set_name).ToHandleChecked(); | |
4687 if (!setter->IsUndefined()) { | |
4688 // TODO(rossberg): nicer would be to cast to some JSCallable here... | |
4689 return SetPropertyWithDefinedSetter( | |
4690 receiver, Handle<JSReceiver>::cast(setter), value, should_throw); | |
4691 } | |
4692 | |
4693 RETURN_FAILURE( | |
4694 isolate, should_throw, | |
4695 NewTypeError(MessageTemplate::kNoSetterInCallback, name, proxy)); | |
4696 } | |
4697 | |
4698 | |
4699 Maybe<bool> JSProxy::DeletePropertyOrElement(Handle<JSProxy> proxy, | 4654 Maybe<bool> JSProxy::DeletePropertyOrElement(Handle<JSProxy> proxy, |
4700 Handle<Name> name, | 4655 Handle<Name> name, |
4701 LanguageMode language_mode) { | 4656 LanguageMode language_mode) { |
4702 ShouldThrow should_throw = | 4657 ShouldThrow should_throw = |
4703 is_sloppy(language_mode) ? DONT_THROW : THROW_ON_ERROR; | 4658 is_sloppy(language_mode) ? DONT_THROW : THROW_ON_ERROR; |
4704 Isolate* isolate = proxy->GetIsolate(); | 4659 Isolate* isolate = proxy->GetIsolate(); |
4705 Factory* factory = isolate->factory(); | 4660 Factory* factory = isolate->factory(); |
4706 Handle<String> trap_name = factory->deleteProperty_string(); | 4661 Handle<String> trap_name = factory->deleteProperty_string(); |
4707 | 4662 |
4708 if (proxy->IsRevoked()) { | 4663 if (proxy->IsRevoked()) { |
(...skipping 373 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5082 MaybeHandle<Object> JSObject::DefinePropertyOrElementIgnoreAttributes( | 5037 MaybeHandle<Object> JSObject::DefinePropertyOrElementIgnoreAttributes( |
5083 Handle<JSObject> object, Handle<Name> name, Handle<Object> value, | 5038 Handle<JSObject> object, Handle<Name> name, Handle<Object> value, |
5084 PropertyAttributes attributes, ExecutableAccessorInfoHandling handling) { | 5039 PropertyAttributes attributes, ExecutableAccessorInfoHandling handling) { |
5085 Isolate* isolate = object->GetIsolate(); | 5040 Isolate* isolate = object->GetIsolate(); |
5086 LookupIterator it = LookupIterator::PropertyOrElement(isolate, object, name, | 5041 LookupIterator it = LookupIterator::PropertyOrElement(isolate, object, name, |
5087 LookupIterator::OWN); | 5042 LookupIterator::OWN); |
5088 return DefineOwnPropertyIgnoreAttributes(&it, value, attributes, handling); | 5043 return DefineOwnPropertyIgnoreAttributes(&it, value, attributes, handling); |
5089 } | 5044 } |
5090 | 5045 |
5091 | 5046 |
5092 Maybe<bool> JSObject::CreateDataProperty(LookupIterator* it, | |
5093 Handle<Object> value) { | |
5094 DCHECK(it->GetReceiver()->IsJSObject()); | |
5095 Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(it); | |
5096 if (maybe.IsNothing()) return Nothing<bool>(); | |
5097 | |
5098 if (it->IsFound()) { | |
5099 if (!it->IsConfigurable()) return Just(false); | |
5100 } else { | |
5101 if (!JSObject::IsExtensible(Handle<JSObject>::cast(it->GetReceiver()))) | |
5102 return Just(false); | |
5103 } | |
5104 | |
5105 RETURN_ON_EXCEPTION_VALUE( | |
5106 it->isolate(), | |
5107 DefineOwnPropertyIgnoreAttributes(it, value, NONE, DONT_FORCE_FIELD), | |
5108 Nothing<bool>()); | |
5109 | |
5110 return Just(true); | |
5111 } | |
5112 | |
5113 | |
5114 Maybe<PropertyAttributes> JSObject::GetPropertyAttributesWithInterceptor( | 5047 Maybe<PropertyAttributes> JSObject::GetPropertyAttributesWithInterceptor( |
5115 LookupIterator* it) { | 5048 LookupIterator* it) { |
5116 Isolate* isolate = it->isolate(); | 5049 Isolate* isolate = it->isolate(); |
5117 // Make sure that the top context does not change when doing | 5050 // Make sure that the top context does not change when doing |
5118 // callbacks or interceptor calls. | 5051 // callbacks or interceptor calls. |
5119 AssertNoContextChange ncc(isolate); | 5052 AssertNoContextChange ncc(isolate); |
5120 HandleScope scope(isolate); | 5053 HandleScope scope(isolate); |
5121 | 5054 |
5122 Handle<JSObject> holder = it->GetHolder<JSObject>(); | 5055 Handle<JSObject> holder = it->GetHolder<JSObject>(); |
5123 Handle<InterceptorInfo> interceptor(it->GetInterceptor()); | 5056 Handle<InterceptorInfo> interceptor(it->GetInterceptor()); |
(...skipping 1436 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6560 } | 6493 } |
6561 } | 6494 } |
6562 | 6495 |
6563 // 11. Return true. | 6496 // 11. Return true. |
6564 return true; | 6497 return true; |
6565 } | 6498 } |
6566 | 6499 |
6567 | 6500 |
6568 // static | 6501 // static |
6569 Maybe<bool> JSReceiver::CreateDataProperty(LookupIterator* it, | 6502 Maybe<bool> JSReceiver::CreateDataProperty(LookupIterator* it, |
6570 Handle<Object> value) { | 6503 Handle<Object> value, |
6571 // TODO(rossberg): Support proxies. | 6504 ShouldThrow should_throw) { |
6572 if (!it->GetReceiver()->IsJSObject()) return Nothing<bool>(); | 6505 DCHECK(!it->check_prototype_chain()); |
6573 return JSObject::CreateDataProperty(it, value); | 6506 Handle<JSReceiver> receiver = Handle<JSReceiver>::cast(it->GetReceiver()); |
| 6507 Isolate* isolate = receiver->GetIsolate(); |
| 6508 |
| 6509 if (receiver->IsJSObject()) { |
| 6510 return JSObject::CreateDataProperty(it, value); // Shortcut. |
| 6511 } |
| 6512 |
| 6513 PropertyDescriptor new_desc; |
| 6514 new_desc.set_value(value); |
| 6515 new_desc.set_writable(true); |
| 6516 new_desc.set_enumerable(true); |
| 6517 new_desc.set_configurable(true); |
| 6518 |
| 6519 bool result = JSReceiver::DefineOwnProperty(isolate, receiver, it->GetName(), |
| 6520 &new_desc, should_throw); |
| 6521 if (isolate->has_pending_exception()) return Nothing<bool>(); |
| 6522 return Just(result); |
6574 } | 6523 } |
6575 | 6524 |
6576 | 6525 |
| 6526 Maybe<bool> JSObject::CreateDataProperty(LookupIterator* it, |
| 6527 Handle<Object> value) { |
| 6528 DCHECK(it->GetReceiver()->IsJSObject()); |
| 6529 Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(it); |
| 6530 if (maybe.IsNothing()) return Nothing<bool>(); |
| 6531 |
| 6532 if (it->IsFound()) { |
| 6533 if (!it->IsConfigurable()) return Just(false); |
| 6534 } else { |
| 6535 if (!JSObject::IsExtensible(Handle<JSObject>::cast(it->GetReceiver()))) |
| 6536 return Just(false); |
| 6537 } |
| 6538 |
| 6539 RETURN_ON_EXCEPTION_VALUE( |
| 6540 it->isolate(), |
| 6541 DefineOwnPropertyIgnoreAttributes(it, value, NONE, DONT_FORCE_FIELD), |
| 6542 Nothing<bool>()); |
| 6543 |
| 6544 return Just(true); |
| 6545 } |
| 6546 |
| 6547 |
6577 // TODO(jkummerow): Consider unification with FastAsArrayLength() in | 6548 // TODO(jkummerow): Consider unification with FastAsArrayLength() in |
6578 // accessors.cc. | 6549 // accessors.cc. |
6579 bool PropertyKeyToArrayLength(Handle<Object> value, uint32_t* length) { | 6550 bool PropertyKeyToArrayLength(Handle<Object> value, uint32_t* length) { |
6580 DCHECK(value->IsNumber() || value->IsName()); | 6551 DCHECK(value->IsNumber() || value->IsName()); |
6581 if (value->ToArrayLength(length)) return true; | 6552 if (value->ToArrayLength(length)) return true; |
6582 if (value->IsString()) return String::cast(*value)->AsArrayIndex(length); | 6553 if (value->IsString()) return String::cast(*value)->AsArrayIndex(length); |
6583 return false; | 6554 return false; |
6584 } | 6555 } |
6585 | 6556 |
6586 | 6557 |
(...skipping 775 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7362 ASSIGN_RETURN_ON_EXCEPTION_VALUE( | 7333 ASSIGN_RETURN_ON_EXCEPTION_VALUE( |
7363 isolate, trap_result, | 7334 isolate, trap_result, |
7364 Execution::Call(isolate, trap, handler, arraysize(args), args), | 7335 Execution::Call(isolate, trap, handler, arraysize(args), args), |
7365 Nothing<bool>()); | 7336 Nothing<bool>()); |
7366 | 7337 |
7367 // Enforce the invariant. | 7338 // Enforce the invariant. |
7368 Maybe<bool> target_result = JSReceiver::IsExtensible(target); | 7339 Maybe<bool> target_result = JSReceiver::IsExtensible(target); |
7369 MAYBE_RETURN(target_result, Nothing<bool>()); | 7340 MAYBE_RETURN(target_result, Nothing<bool>()); |
7370 if (target_result.FromJust() != trap_result->BooleanValue()) { | 7341 if (target_result.FromJust() != trap_result->BooleanValue()) { |
7371 isolate->Throw(*factory->NewTypeError( | 7342 isolate->Throw(*factory->NewTypeError( |
7372 MessageTemplate::kProxyIsExtensibleViolatesInvariant)); | 7343 MessageTemplate::kProxyTrapViolatesInvariant, trap_name)); |
7373 return Nothing<bool>(); | 7344 return Nothing<bool>(); |
7374 } | 7345 } |
7375 return target_result; | 7346 return target_result; |
7376 } | 7347 } |
7377 | 7348 |
7378 | 7349 |
7379 bool JSObject::IsExtensible(Handle<JSObject> object) { | 7350 bool JSObject::IsExtensible(Handle<JSObject> object) { |
7380 Isolate* isolate = object->GetIsolate(); | 7351 Isolate* isolate = object->GetIsolate(); |
7381 if (object->IsAccessCheckNeeded() && | 7352 if (object->IsAccessCheckNeeded() && |
7382 !isolate->MayAccess(handle(isolate->context()), object)) { | 7353 !isolate->MayAccess(handle(isolate->context()), object)) { |
(...skipping 11605 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
18988 if (cell->value() != *new_value) { | 18959 if (cell->value() != *new_value) { |
18989 cell->set_value(*new_value); | 18960 cell->set_value(*new_value); |
18990 Isolate* isolate = cell->GetIsolate(); | 18961 Isolate* isolate = cell->GetIsolate(); |
18991 cell->dependent_code()->DeoptimizeDependentCodeGroup( | 18962 cell->dependent_code()->DeoptimizeDependentCodeGroup( |
18992 isolate, DependentCode::kPropertyCellChangedGroup); | 18963 isolate, DependentCode::kPropertyCellChangedGroup); |
18993 } | 18964 } |
18994 } | 18965 } |
18995 | 18966 |
18996 } // namespace internal | 18967 } // namespace internal |
18997 } // namespace v8 | 18968 } // namespace v8 |
OLD | NEW |