Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(117)

Side by Side Diff: src/objects.cc

Issue 1479543002: [proxies] Implement [[Delete]]. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Fix typo Created 5 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698