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 4625 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4636 return SetPropertyWithDefinedSetter( | 4636 return SetPropertyWithDefinedSetter( |
4637 receiver, Handle<JSReceiver>::cast(setter), value, should_throw); | 4637 receiver, Handle<JSReceiver>::cast(setter), value, should_throw); |
4638 } | 4638 } |
4639 | 4639 |
4640 RETURN_FAILURE( | 4640 RETURN_FAILURE( |
4641 isolate, should_throw, | 4641 isolate, should_throw, |
4642 NewTypeError(MessageTemplate::kNoSetterInCallback, name, proxy)); | 4642 NewTypeError(MessageTemplate::kNoSetterInCallback, name, proxy)); |
4643 } | 4643 } |
4644 | 4644 |
4645 | 4645 |
4646 MaybeHandle<Object> JSProxy::DeletePropertyWithHandler( | 4646 Maybe<bool> JSProxy::DeletePropertyOrElement(Handle<JSProxy> proxy, |
4647 Handle<JSProxy> proxy, Handle<Name> name, LanguageMode language_mode) { | 4647 Handle<Name> name, |
| 4648 LanguageMode language_mode) { |
| 4649 ShouldThrow should_throw = |
| 4650 is_sloppy(language_mode) ? DONT_THROW : THROW_ON_ERROR; |
4648 Isolate* isolate = proxy->GetIsolate(); | 4651 Isolate* isolate = proxy->GetIsolate(); |
| 4652 Factory* factory = isolate->factory(); |
| 4653 Handle<String> trap_name = factory->deleteProperty_string(); |
4649 | 4654 |
4650 // TODO(rossberg): adjust once there is a story for symbols vs proxies. | 4655 if (IsRevoked(proxy)) { |
4651 if (name->IsSymbol()) return isolate->factory()->false_value(); | 4656 isolate->Throw( |
| 4657 *factory->NewTypeError(MessageTemplate::kProxyRevoked, trap_name)); |
| 4658 return Nothing<bool>(); |
| 4659 } |
4652 | 4660 |
4653 Handle<Object> args[] = { name }; | 4661 Handle<JSReceiver> target(JSReceiver::cast(proxy->target()), isolate); |
4654 Handle<Object> result; | 4662 Handle<JSReceiver> handler(JSReceiver::cast(proxy->handler()), isolate); |
4655 ASSIGN_RETURN_ON_EXCEPTION( | |
4656 isolate, result, | |
4657 CallTrap(proxy, | |
4658 "delete", | |
4659 Handle<Object>(), | |
4660 arraysize(args), | |
4661 args), | |
4662 Object); | |
4663 | 4663 |
4664 bool result_bool = result->BooleanValue(); | 4664 Handle<Object> trap; |
4665 if (is_strict(language_mode) && !result_bool) { | 4665 ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, trap, GetTrap(proxy, trap_name), |
4666 Handle<Object> handler(proxy->handler(), isolate); | 4666 Nothing<bool>()); |
4667 THROW_NEW_ERROR( | 4667 if (trap->IsUndefined()) { |
4668 isolate, | 4668 return JSReceiver::DeletePropertyOrElement(target, name, language_mode); |
4669 NewTypeError(MessageTemplate::kProxyHandlerDeleteFailed, handler), | |
4670 Object); | |
4671 } | 4669 } |
4672 return isolate->factory()->ToBoolean(result_bool); | 4670 |
| 4671 Handle<Object> trap_result; |
| 4672 Handle<Object> args[] = {target, name}; |
| 4673 ASSIGN_RETURN_ON_EXCEPTION_VALUE( |
| 4674 isolate, trap_result, |
| 4675 Execution::Call(isolate, trap, handler, arraysize(args), args), |
| 4676 Nothing<bool>()); |
| 4677 if (!trap_result->BooleanValue()) { |
| 4678 RETURN_FAILURE(isolate, should_throw, |
| 4679 NewTypeError(MessageTemplate::kProxyHandlerReturned, handler, |
| 4680 factory->false_string(), trap_name)); |
| 4681 } |
| 4682 |
| 4683 // Enforce the invariant. |
| 4684 PropertyDescriptor target_desc; |
| 4685 bool owned = |
| 4686 JSReceiver::GetOwnPropertyDescriptor(isolate, target, name, &target_desc); |
| 4687 if (isolate->has_pending_exception()) return Nothing<bool>(); |
| 4688 if (owned && !target_desc.configurable()) { |
| 4689 isolate->Throw(*factory->NewTypeError( |
| 4690 MessageTemplate::kProxyDeletePropertyViolatesInvariant, name)); |
| 4691 return Nothing<bool>(); |
| 4692 } |
| 4693 return Just(true); |
4673 } | 4694 } |
4674 | 4695 |
4675 | 4696 |
4676 Maybe<PropertyAttributes> JSProxy::GetPropertyAttributes(LookupIterator* it) { | 4697 Maybe<PropertyAttributes> JSProxy::GetPropertyAttributes(LookupIterator* it) { |
4677 Isolate* isolate = it->isolate(); | 4698 Isolate* isolate = it->isolate(); |
4678 HandleScope scope(isolate); | 4699 HandleScope scope(isolate); |
4679 PropertyDescriptor desc; | 4700 PropertyDescriptor desc; |
4680 bool found = JSProxy::GetOwnPropertyDescriptor(it, &desc); | 4701 bool found = JSProxy::GetOwnPropertyDescriptor(it, &desc); |
4681 if (isolate->has_pending_exception()) return Nothing<PropertyAttributes>(); | 4702 if (isolate->has_pending_exception()) return Nothing<PropertyAttributes>(); |
4682 if (!found) return Just(ABSENT); | 4703 if (!found) return Just(ABSENT); |
(...skipping 1072 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5755 Handle<Object> JSObject::SetHiddenPropertiesHashTable(Handle<JSObject> object, | 5776 Handle<Object> JSObject::SetHiddenPropertiesHashTable(Handle<JSObject> object, |
5756 Handle<Object> value) { | 5777 Handle<Object> value) { |
5757 DCHECK(!object->IsJSGlobalProxy()); | 5778 DCHECK(!object->IsJSGlobalProxy()); |
5758 Isolate* isolate = object->GetIsolate(); | 5779 Isolate* isolate = object->GetIsolate(); |
5759 Handle<Name> name = isolate->factory()->hidden_string(); | 5780 Handle<Name> name = isolate->factory()->hidden_string(); |
5760 SetOwnPropertyIgnoreAttributes(object, name, value, DONT_ENUM).Assert(); | 5781 SetOwnPropertyIgnoreAttributes(object, name, value, DONT_ENUM).Assert(); |
5761 return object; | 5782 return object; |
5762 } | 5783 } |
5763 | 5784 |
5764 | 5785 |
5765 MaybeHandle<Object> JSObject::DeletePropertyWithInterceptor( | 5786 Maybe<bool> JSObject::DeletePropertyWithInterceptor(LookupIterator* it) { |
5766 LookupIterator* it) { | |
5767 Isolate* isolate = it->isolate(); | 5787 Isolate* isolate = it->isolate(); |
5768 // Make sure that the top context does not change when doing callbacks or | 5788 // Make sure that the top context does not change when doing callbacks or |
5769 // interceptor calls. | 5789 // interceptor calls. |
5770 AssertNoContextChange ncc(isolate); | 5790 AssertNoContextChange ncc(isolate); |
5771 | 5791 |
5772 DCHECK_EQ(LookupIterator::INTERCEPTOR, it->state()); | 5792 DCHECK_EQ(LookupIterator::INTERCEPTOR, it->state()); |
5773 Handle<InterceptorInfo> interceptor(it->GetInterceptor()); | 5793 Handle<InterceptorInfo> interceptor(it->GetInterceptor()); |
5774 if (interceptor->deleter()->IsUndefined()) return MaybeHandle<Object>(); | 5794 if (interceptor->deleter()->IsUndefined()) return Nothing<bool>(); |
5775 | 5795 |
5776 Handle<JSObject> holder = it->GetHolder<JSObject>(); | 5796 Handle<JSObject> holder = it->GetHolder<JSObject>(); |
5777 | 5797 |
5778 PropertyCallbackArguments args(isolate, interceptor->data(), | 5798 PropertyCallbackArguments args(isolate, interceptor->data(), |
5779 *it->GetReceiver(), *holder); | 5799 *it->GetReceiver(), *holder); |
5780 v8::Local<v8::Boolean> result; | 5800 v8::Local<v8::Boolean> result; |
5781 if (it->IsElement()) { | 5801 if (it->IsElement()) { |
5782 uint32_t index = it->index(); | 5802 uint32_t index = it->index(); |
5783 v8::IndexedPropertyDeleterCallback deleter = | 5803 v8::IndexedPropertyDeleterCallback deleter = |
5784 v8::ToCData<v8::IndexedPropertyDeleterCallback>(interceptor->deleter()); | 5804 v8::ToCData<v8::IndexedPropertyDeleterCallback>(interceptor->deleter()); |
5785 LOG(isolate, | 5805 LOG(isolate, |
5786 ApiIndexedPropertyAccess("interceptor-indexed-delete", *holder, index)); | 5806 ApiIndexedPropertyAccess("interceptor-indexed-delete", *holder, index)); |
5787 result = args.Call(deleter, index); | 5807 result = args.Call(deleter, index); |
5788 } else if (it->name()->IsSymbol() && !interceptor->can_intercept_symbols()) { | 5808 } else if (it->name()->IsSymbol() && !interceptor->can_intercept_symbols()) { |
5789 return MaybeHandle<Object>(); | 5809 return Nothing<bool>(); |
5790 } else { | 5810 } else { |
5791 Handle<Name> name = it->name(); | 5811 Handle<Name> name = it->name(); |
5792 v8::GenericNamedPropertyDeleterCallback deleter = | 5812 v8::GenericNamedPropertyDeleterCallback deleter = |
5793 v8::ToCData<v8::GenericNamedPropertyDeleterCallback>( | 5813 v8::ToCData<v8::GenericNamedPropertyDeleterCallback>( |
5794 interceptor->deleter()); | 5814 interceptor->deleter()); |
5795 LOG(isolate, | 5815 LOG(isolate, |
5796 ApiNamedPropertyAccess("interceptor-named-delete", *holder, *name)); | 5816 ApiNamedPropertyAccess("interceptor-named-delete", *holder, *name)); |
5797 result = args.Call(deleter, v8::Utils::ToLocal(name)); | 5817 result = args.Call(deleter, v8::Utils::ToLocal(name)); |
5798 } | 5818 } |
5799 | 5819 |
5800 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object); | 5820 RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<bool>()); |
5801 if (result.IsEmpty()) return MaybeHandle<Object>(); | 5821 if (result.IsEmpty()) return Nothing<bool>(); |
5802 | 5822 |
5803 DCHECK(result->IsBoolean()); | 5823 DCHECK(result->IsBoolean()); |
5804 Handle<Object> result_internal = v8::Utils::OpenHandle(*result); | 5824 Handle<Object> result_internal = v8::Utils::OpenHandle(*result); |
5805 result_internal->VerifyApiCallResultType(); | 5825 result_internal->VerifyApiCallResultType(); |
5806 // Rebox CustomArguments::kReturnValueOffset before returning. | 5826 // Rebox CustomArguments::kReturnValueOffset before returning. |
5807 return handle(*result_internal, isolate); | 5827 return Just(result_internal->BooleanValue()); |
5808 } | 5828 } |
5809 | 5829 |
5810 | 5830 |
5811 void JSObject::DeleteNormalizedProperty(Handle<JSObject> object, | 5831 void JSObject::DeleteNormalizedProperty(Handle<JSObject> object, |
5812 Handle<Name> name, int entry) { | 5832 Handle<Name> name, int entry) { |
5813 DCHECK(!object->HasFastProperties()); | 5833 DCHECK(!object->HasFastProperties()); |
5814 Isolate* isolate = object->GetIsolate(); | 5834 Isolate* isolate = object->GetIsolate(); |
5815 | 5835 |
5816 if (object->IsJSGlobalObject()) { | 5836 if (object->IsJSGlobalObject()) { |
5817 // If we have a global object, invalidate the cell and swap in a new one. | 5837 // If we have a global object, invalidate the cell and swap in a new one. |
(...skipping 10 matching lines...) Expand all Loading... |
5828 DCHECK_NE(NameDictionary::kNotFound, entry); | 5848 DCHECK_NE(NameDictionary::kNotFound, entry); |
5829 | 5849 |
5830 NameDictionary::DeleteProperty(dictionary, entry); | 5850 NameDictionary::DeleteProperty(dictionary, entry); |
5831 Handle<NameDictionary> new_properties = | 5851 Handle<NameDictionary> new_properties = |
5832 NameDictionary::Shrink(dictionary, name); | 5852 NameDictionary::Shrink(dictionary, name); |
5833 object->set_properties(*new_properties); | 5853 object->set_properties(*new_properties); |
5834 } | 5854 } |
5835 } | 5855 } |
5836 | 5856 |
5837 | 5857 |
5838 // ECMA-262, 3rd, 8.6.2.5 | 5858 Maybe<bool> JSReceiver::DeleteProperty(LookupIterator* it, |
5839 MaybeHandle<Object> JSReceiver::DeleteProperty(LookupIterator* it, | 5859 LanguageMode language_mode) { |
5840 LanguageMode language_mode) { | |
5841 Isolate* isolate = it->isolate(); | 5860 Isolate* isolate = it->isolate(); |
| 5861 |
5842 if (it->state() == LookupIterator::JSPROXY) { | 5862 if (it->state() == LookupIterator::JSPROXY) { |
5843 return JSProxy::DeletePropertyWithHandler(it->GetHolder<JSProxy>(), | 5863 return JSProxy::DeletePropertyOrElement(it->GetHolder<JSProxy>(), |
5844 it->GetName(), language_mode); | 5864 it->GetName(), language_mode); |
5845 } | 5865 } |
5846 | 5866 |
5847 Handle<JSObject> receiver = Handle<JSObject>::cast(it->GetReceiver()); | 5867 Handle<JSObject> receiver = Handle<JSObject>::cast(it->GetReceiver()); |
5848 | 5868 |
5849 bool is_observed = | 5869 bool is_observed = |
5850 receiver->map()->is_observed() && | 5870 receiver->map()->is_observed() && |
5851 (it->IsElement() || !isolate->IsInternallyUsedPropertyName(it->name())); | 5871 (it->IsElement() || !isolate->IsInternallyUsedPropertyName(it->name())); |
5852 | 5872 |
5853 Handle<Object> old_value = it->factory()->the_hole_value(); | 5873 Handle<Object> old_value = it->factory()->the_hole_value(); |
5854 | 5874 |
5855 for (; it->IsFound(); it->Next()) { | 5875 for (; it->IsFound(); it->Next()) { |
5856 switch (it->state()) { | 5876 switch (it->state()) { |
5857 case LookupIterator::JSPROXY: | 5877 case LookupIterator::JSPROXY: |
5858 case LookupIterator::NOT_FOUND: | 5878 case LookupIterator::NOT_FOUND: |
5859 case LookupIterator::TRANSITION: | 5879 case LookupIterator::TRANSITION: |
5860 UNREACHABLE(); | 5880 UNREACHABLE(); |
5861 case LookupIterator::ACCESS_CHECK: | 5881 case LookupIterator::ACCESS_CHECK: |
5862 if (it->HasAccess()) break; | 5882 if (it->HasAccess()) break; |
5863 isolate->ReportFailedAccessCheck(it->GetHolder<JSObject>()); | 5883 isolate->ReportFailedAccessCheck(it->GetHolder<JSObject>()); |
5864 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object); | 5884 RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<bool>()); |
5865 return it->factory()->false_value(); | 5885 return Just(false); |
5866 case LookupIterator::INTERCEPTOR: { | 5886 case LookupIterator::INTERCEPTOR: { |
5867 MaybeHandle<Object> maybe_result = | 5887 Maybe<bool> result = JSObject::DeletePropertyWithInterceptor(it); |
5868 JSObject::DeletePropertyWithInterceptor(it); | 5888 // An exception was thrown in the interceptor. Propagate. |
| 5889 if (isolate->has_pending_exception()) return Nothing<bool>(); |
5869 // Delete with interceptor succeeded. Return result. | 5890 // Delete with interceptor succeeded. Return result. |
5870 if (!maybe_result.is_null()) return maybe_result; | 5891 // TODO(neis): In strict mode, we should probably throw if the |
5871 // An exception was thrown in the interceptor. Propagate. | 5892 // interceptor returns false. |
5872 if (isolate->has_pending_exception()) return maybe_result; | 5893 if (result.IsJust()) return result; |
5873 break; | 5894 break; |
5874 } | 5895 } |
5875 case LookupIterator::INTEGER_INDEXED_EXOTIC: | 5896 case LookupIterator::INTEGER_INDEXED_EXOTIC: |
5876 return it->factory()->true_value(); | 5897 return Just(true); |
5877 case LookupIterator::DATA: | 5898 case LookupIterator::DATA: |
5878 if (is_observed) { | 5899 if (is_observed) { |
5879 old_value = it->GetDataValue(); | 5900 old_value = it->GetDataValue(); |
5880 } | 5901 } |
5881 // Fall through. | 5902 // Fall through. |
5882 case LookupIterator::ACCESSOR: { | 5903 case LookupIterator::ACCESSOR: { |
5883 if (!it->IsConfigurable() || receiver->map()->is_strong()) { | 5904 if (!it->IsConfigurable() || receiver->map()->is_strong()) { |
5884 // Fail if the property is not configurable, or on a strong object. | 5905 // Fail if the property is not configurable, or on a strong object. |
5885 if (is_strict(language_mode)) { | 5906 if (is_strict(language_mode)) { |
5886 MessageTemplate::Template templ = | 5907 MessageTemplate::Template templ = |
5887 receiver->map()->is_strong() | 5908 receiver->map()->is_strong() |
5888 ? MessageTemplate::kStrongDeleteProperty | 5909 ? MessageTemplate::kStrongDeleteProperty |
5889 : MessageTemplate::kStrictDeleteProperty; | 5910 : MessageTemplate::kStrictDeleteProperty; |
5890 THROW_NEW_ERROR( | 5911 isolate->Throw(*isolate->factory()->NewTypeError( |
5891 isolate, NewTypeError(templ, it->GetName(), receiver), Object); | 5912 templ, it->GetName(), receiver)); |
| 5913 return Nothing<bool>(); |
5892 } | 5914 } |
5893 return it->factory()->false_value(); | 5915 return Just(false); |
5894 } | 5916 } |
5895 | 5917 |
5896 it->Delete(); | 5918 it->Delete(); |
5897 | 5919 |
5898 if (is_observed) { | 5920 if (is_observed) { |
5899 RETURN_ON_EXCEPTION(isolate, | 5921 RETURN_ON_EXCEPTION_VALUE( |
5900 JSObject::EnqueueChangeRecord( | 5922 isolate, JSObject::EnqueueChangeRecord(receiver, "delete", |
5901 receiver, "delete", it->GetName(), old_value), | 5923 it->GetName(), old_value), |
5902 Object); | 5924 Nothing<bool>()); |
5903 } | 5925 } |
5904 | 5926 |
5905 return it->factory()->true_value(); | 5927 return Just(true); |
5906 } | 5928 } |
5907 } | 5929 } |
5908 } | 5930 } |
5909 | 5931 |
5910 return it->factory()->true_value(); | 5932 return Just(true); |
5911 } | 5933 } |
5912 | 5934 |
5913 | 5935 |
5914 MaybeHandle<Object> JSReceiver::DeleteElement(Handle<JSReceiver> object, | 5936 Maybe<bool> JSReceiver::DeleteElement(Handle<JSReceiver> object, uint32_t index, |
5915 uint32_t index, | 5937 LanguageMode language_mode) { |
5916 LanguageMode language_mode) { | |
5917 LookupIterator it(object->GetIsolate(), object, index, | 5938 LookupIterator it(object->GetIsolate(), object, index, |
5918 LookupIterator::HIDDEN); | 5939 LookupIterator::HIDDEN); |
5919 return DeleteProperty(&it, language_mode); | 5940 return DeleteProperty(&it, language_mode); |
5920 } | 5941 } |
5921 | 5942 |
5922 | 5943 |
5923 MaybeHandle<Object> JSReceiver::DeleteProperty(Handle<JSReceiver> object, | 5944 Maybe<bool> JSReceiver::DeleteProperty(Handle<JSReceiver> object, |
5924 Handle<Name> name, | 5945 Handle<Name> name, |
5925 LanguageMode language_mode) { | 5946 LanguageMode language_mode) { |
5926 LookupIterator it(object, name, LookupIterator::HIDDEN); | 5947 LookupIterator it(object, name, LookupIterator::HIDDEN); |
5927 return DeleteProperty(&it, language_mode); | 5948 return DeleteProperty(&it, language_mode); |
5928 } | 5949 } |
5929 | 5950 |
5930 | 5951 |
5931 MaybeHandle<Object> JSReceiver::DeletePropertyOrElement( | 5952 Maybe<bool> JSReceiver::DeletePropertyOrElement(Handle<JSReceiver> object, |
5932 Handle<JSReceiver> object, Handle<Name> name, LanguageMode language_mode) { | 5953 Handle<Name> name, |
| 5954 LanguageMode language_mode) { |
5933 LookupIterator it = LookupIterator::PropertyOrElement( | 5955 LookupIterator it = LookupIterator::PropertyOrElement( |
5934 name->GetIsolate(), object, name, LookupIterator::HIDDEN); | 5956 name->GetIsolate(), object, name, LookupIterator::HIDDEN); |
5935 return DeleteProperty(&it, language_mode); | 5957 return DeleteProperty(&it, language_mode); |
5936 } | 5958 } |
5937 | 5959 |
5938 | 5960 |
5939 // ES6 7.1.14 | 5961 // ES6 7.1.14 |
5940 MaybeHandle<Object> ToPropertyKey(Isolate* isolate, Handle<Object> value) { | 5962 MaybeHandle<Object> ToPropertyKey(Isolate* isolate, Handle<Object> value) { |
5941 // 1. Let key be ToPrimitive(argument, hint String). | 5963 // 1. Let key be ToPrimitive(argument, hint String). |
5942 MaybeHandle<Object> maybe_key = | 5964 MaybeHandle<Object> maybe_key = |
(...skipping 12631 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
18574 if (cell->value() != *new_value) { | 18596 if (cell->value() != *new_value) { |
18575 cell->set_value(*new_value); | 18597 cell->set_value(*new_value); |
18576 Isolate* isolate = cell->GetIsolate(); | 18598 Isolate* isolate = cell->GetIsolate(); |
18577 cell->dependent_code()->DeoptimizeDependentCodeGroup( | 18599 cell->dependent_code()->DeoptimizeDependentCodeGroup( |
18578 isolate, DependentCode::kPropertyCellChangedGroup); | 18600 isolate, DependentCode::kPropertyCellChangedGroup); |
18579 } | 18601 } |
18580 } | 18602 } |
18581 | 18603 |
18582 } // namespace internal | 18604 } // namespace internal |
18583 } // namespace v8 | 18605 } // namespace v8 |
OLD | NEW |