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 4837 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4848 Handle<Object> JSObject::SetHiddenPropertiesHashTable(Handle<JSObject> object, | 4848 Handle<Object> JSObject::SetHiddenPropertiesHashTable(Handle<JSObject> object, |
4849 Handle<Object> value) { | 4849 Handle<Object> value) { |
4850 DCHECK(!object->IsJSGlobalProxy()); | 4850 DCHECK(!object->IsJSGlobalProxy()); |
4851 Isolate* isolate = object->GetIsolate(); | 4851 Isolate* isolate = object->GetIsolate(); |
4852 Handle<Name> name = isolate->factory()->hidden_string(); | 4852 Handle<Name> name = isolate->factory()->hidden_string(); |
4853 SetOwnPropertyIgnoreAttributes(object, name, value, DONT_ENUM); | 4853 SetOwnPropertyIgnoreAttributes(object, name, value, DONT_ENUM); |
4854 return object; | 4854 return object; |
4855 } | 4855 } |
4856 | 4856 |
4857 | 4857 |
4858 Handle<Object> JSObject::DeletePropertyPostInterceptor(Handle<JSObject> object, | 4858 Handle<Object> JSObject::DeletePropertyPostInterceptor(Handle<JSObject> object, |
Jakob Kummerow
2014/08/13 12:07:25
This seems to have become dead code now.
| |
4859 Handle<Name> name, | 4859 Handle<Name> name, |
4860 DeleteMode delete_mode) { | 4860 DeleteMode delete_mode) { |
4861 // Check own property, ignore interceptor. | 4861 // Check own property, ignore interceptor. |
4862 Isolate* isolate = object->GetIsolate(); | 4862 Isolate* isolate = object->GetIsolate(); |
4863 LookupResult lookup(isolate); | 4863 LookupResult lookup(isolate); |
4864 object->LookupOwnRealNamedProperty(name, &lookup); | 4864 object->LookupOwnRealNamedProperty(name, &lookup); |
4865 if (!lookup.IsFound()) return isolate->factory()->true_value(); | 4865 if (!lookup.IsFound()) return isolate->factory()->true_value(); |
4866 | 4866 |
4867 PropertyNormalizationMode mode = object->map()->is_prototype_map() | 4867 PropertyNormalizationMode mode = object->map()->is_prototype_map() |
4868 ? KEEP_INOBJECT_PROPERTIES | 4868 ? KEEP_INOBJECT_PROPERTIES |
4869 : CLEAR_INOBJECT_PROPERTIES; | 4869 : CLEAR_INOBJECT_PROPERTIES; |
4870 // Normalize object if needed. | 4870 // Normalize object if needed. |
4871 NormalizeProperties(object, mode, 0); | 4871 NormalizeProperties(object, mode, 0); |
4872 | 4872 |
4873 Handle<Object> result = DeleteNormalizedProperty(object, name, delete_mode); | 4873 Handle<Object> result = DeleteNormalizedProperty(object, name, delete_mode); |
4874 ReoptimizeIfPrototype(object); | 4874 ReoptimizeIfPrototype(object); |
4875 return result; | 4875 return result; |
4876 } | 4876 } |
4877 | 4877 |
4878 | 4878 |
4879 MaybeHandle<Object> JSObject::DeletePropertyWithInterceptor( | 4879 MaybeHandle<Object> JSObject::DeletePropertyWithInterceptor( |
4880 Handle<JSObject> object, Handle<Name> name) { | 4880 Handle<JSObject> holder, Handle<JSObject> receiver, Handle<Name> name) { |
4881 Isolate* isolate = object->GetIsolate(); | 4881 Isolate* isolate = holder->GetIsolate(); |
4882 | 4882 |
4883 // TODO(rossberg): Support symbols in the API. | 4883 // TODO(rossberg): Support symbols in the API. |
4884 if (name->IsSymbol()) return isolate->factory()->false_value(); | 4884 if (name->IsSymbol()) return MaybeHandle<Object>(); |
4885 | 4885 |
4886 Handle<InterceptorInfo> interceptor(object->GetNamedInterceptor()); | 4886 Handle<InterceptorInfo> interceptor(holder->GetNamedInterceptor()); |
4887 if (!interceptor->deleter()->IsUndefined()) { | 4887 if (interceptor->deleter()->IsUndefined()) return MaybeHandle<Object>(); |
4888 v8::NamedPropertyDeleterCallback deleter = | 4888 |
4889 v8::ToCData<v8::NamedPropertyDeleterCallback>(interceptor->deleter()); | 4889 v8::NamedPropertyDeleterCallback deleter = |
4890 LOG(isolate, | 4890 v8::ToCData<v8::NamedPropertyDeleterCallback>(interceptor->deleter()); |
4891 ApiNamedPropertyAccess("interceptor-named-delete", *object, *name)); | 4891 LOG(isolate, |
4892 PropertyCallbackArguments args( | 4892 ApiNamedPropertyAccess("interceptor-named-delete", *holder, *name)); |
4893 isolate, interceptor->data(), *object, *object); | 4893 PropertyCallbackArguments args(isolate, interceptor->data(), *receiver, |
4894 v8::Handle<v8::Boolean> result = | 4894 *holder); |
4895 args.Call(deleter, v8::Utils::ToLocal(Handle<String>::cast(name))); | 4895 v8::Handle<v8::Boolean> result = |
4896 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object); | 4896 args.Call(deleter, v8::Utils::ToLocal(Handle<String>::cast(name))); |
4897 if (!result.IsEmpty()) { | 4897 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object); |
4898 DCHECK(result->IsBoolean()); | 4898 if (result.IsEmpty()) return MaybeHandle<Object>(); |
4899 Handle<Object> result_internal = v8::Utils::OpenHandle(*result); | 4899 |
4900 result_internal->VerifyApiCallResultType(); | 4900 DCHECK(result->IsBoolean()); |
4901 // Rebox CustomArguments::kReturnValueOffset before returning. | 4901 Handle<Object> result_internal = v8::Utils::OpenHandle(*result); |
4902 return handle(*result_internal, isolate); | 4902 result_internal->VerifyApiCallResultType(); |
4903 } | 4903 // Rebox CustomArguments::kReturnValueOffset before returning. |
4904 } | 4904 return handle(*result_internal, isolate); |
4905 Handle<Object> result = | |
4906 DeletePropertyPostInterceptor(object, name, NORMAL_DELETION); | |
4907 return result; | |
4908 } | 4905 } |
4909 | 4906 |
4910 | 4907 |
4911 MaybeHandle<Object> JSObject::DeleteElementWithInterceptor( | 4908 MaybeHandle<Object> JSObject::DeleteElementWithInterceptor( |
4912 Handle<JSObject> object, | 4909 Handle<JSObject> object, |
4913 uint32_t index) { | 4910 uint32_t index) { |
4914 Isolate* isolate = object->GetIsolate(); | 4911 Isolate* isolate = object->GetIsolate(); |
4915 Factory* factory = isolate->factory(); | 4912 Factory* factory = isolate->factory(); |
4916 | 4913 |
4917 // Make sure that the top context does not change when doing | 4914 // Make sure that the top context does not change when doing |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5013 } | 5010 } |
5014 } | 5011 } |
5015 | 5012 |
5016 return result; | 5013 return result; |
5017 } | 5014 } |
5018 | 5015 |
5019 | 5016 |
5020 MaybeHandle<Object> JSObject::DeleteProperty(Handle<JSObject> object, | 5017 MaybeHandle<Object> JSObject::DeleteProperty(Handle<JSObject> object, |
5021 Handle<Name> name, | 5018 Handle<Name> name, |
5022 DeleteMode delete_mode) { | 5019 DeleteMode delete_mode) { |
5023 Isolate* isolate = object->GetIsolate(); | |
5024 // ECMA-262, 3rd, 8.6.2.5 | 5020 // ECMA-262, 3rd, 8.6.2.5 |
5025 DCHECK(name->IsName()); | 5021 DCHECK(name->IsName()); |
5026 | 5022 |
5027 // Check access rights if needed. | |
5028 if (object->IsAccessCheckNeeded() && | |
5029 !isolate->MayNamedAccess(object, name, v8::ACCESS_DELETE)) { | |
5030 isolate->ReportFailedAccessCheck(object, v8::ACCESS_DELETE); | |
5031 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object); | |
5032 return isolate->factory()->false_value(); | |
5033 } | |
5034 | |
5035 if (object->IsJSGlobalProxy()) { | |
5036 PrototypeIterator iter(isolate, object); | |
5037 if (iter.IsAtEnd()) return isolate->factory()->false_value(); | |
5038 DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject()); | |
5039 return JSGlobalObject::DeleteProperty( | |
5040 Handle<JSGlobalObject>::cast(PrototypeIterator::GetCurrent(iter)), name, | |
5041 delete_mode); | |
5042 } | |
5043 | |
5044 uint32_t index = 0; | 5023 uint32_t index = 0; |
5045 if (name->AsArrayIndex(&index)) { | 5024 if (name->AsArrayIndex(&index)) { |
5046 return DeleteElement(object, index, delete_mode); | 5025 return DeleteElement(object, index, delete_mode); |
5047 } | 5026 } |
5048 | 5027 |
5049 LookupResult lookup(isolate); | 5028 // Skip interceptors on FORCE_DELETION. |
5050 object->LookupOwn(name, &lookup, true); | 5029 LookupIterator::Configuration config = |
5051 if (!lookup.IsFound()) return isolate->factory()->true_value(); | 5030 delete_mode == FORCE_DELETION ? LookupIterator::CHECK_HIDDEN_ACCESS |
5052 // Ignore attributes if forcing a deletion. | 5031 : LookupIterator::CHECK_OWN; |
5053 if (lookup.IsDontDelete() && delete_mode != FORCE_DELETION) { | |
5054 if (delete_mode == STRICT_DELETION) { | |
5055 // Deleting a non-configurable property in strict mode. | |
5056 Handle<Object> args[2] = { name, object }; | |
5057 Handle<Object> error = isolate->factory()->NewTypeError( | |
5058 "strict_delete_property", HandleVector(args, ARRAY_SIZE(args))); | |
5059 isolate->Throw(*error); | |
5060 return Handle<Object>(); | |
5061 } | |
5062 return isolate->factory()->false_value(); | |
5063 } | |
5064 | 5032 |
5065 Handle<Object> old_value = isolate->factory()->the_hole_value(); | 5033 LookupIterator it(object, name, config); |
5034 | |
5066 bool is_observed = object->map()->is_observed() && | 5035 bool is_observed = object->map()->is_observed() && |
5067 *name != isolate->heap()->hidden_string(); | 5036 *name != it.isolate()->heap()->hidden_string(); |
5068 if (is_observed && lookup.IsDataProperty()) { | |
5069 old_value = Object::GetPropertyOrElement(object, name).ToHandleChecked(); | |
5070 } | |
5071 Handle<Object> result; | |
5072 | 5037 |
5073 // Check for interceptor. | 5038 for (; it.IsFound(); it.Next()) { |
5074 if (lookup.IsInterceptor()) { | 5039 switch (it.state()) { |
5075 // Skip interceptor if forcing a deletion. | 5040 case LookupIterator::NOT_FOUND: |
5076 if (delete_mode == FORCE_DELETION) { | 5041 case LookupIterator::JSPROXY: |
5077 result = DeletePropertyPostInterceptor(object, name, delete_mode); | 5042 UNREACHABLE(); |
5078 } else { | 5043 case LookupIterator::ACCESS_CHECK: |
5079 ASSIGN_RETURN_ON_EXCEPTION( | 5044 if (it.HasAccess(v8::ACCESS_DELETE)) break; |
5080 isolate, result, | 5045 it.isolate()->ReportFailedAccessCheck(it.GetHolder<JSObject>(), |
5081 DeletePropertyWithInterceptor(object, name), | 5046 v8::ACCESS_DELETE); |
5082 Object); | 5047 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(it.isolate(), Object); |
5083 } | 5048 return it.isolate()->factory()->false_value(); |
5084 } else { | 5049 case LookupIterator::INTERCEPTOR: { |
5085 PropertyNormalizationMode mode = object->map()->is_prototype_map() | 5050 MaybeHandle<Object> maybe_result = |
5086 ? KEEP_INOBJECT_PROPERTIES | 5051 JSObject::DeletePropertyWithInterceptor(it.GetHolder<JSObject>(), |
5087 : CLEAR_INOBJECT_PROPERTIES; | 5052 object, it.name()); |
5088 // Normalize object if needed. | 5053 // Delete with interceptor succeeded. Return result. |
5089 NormalizeProperties(object, mode, 0); | 5054 if (!maybe_result.is_null()) return maybe_result; |
5090 // Make sure the properties are normalized before removing the entry. | 5055 // An exception was thrown in the interceptor. Propagate. |
5091 result = DeleteNormalizedProperty(object, name, delete_mode); | 5056 if (it.isolate()->has_pending_exception()) return maybe_result; |
5092 ReoptimizeIfPrototype(object); | 5057 break; |
5093 } | 5058 } |
5059 case LookupIterator::PROPERTY: { | |
5060 if (!it.HasProperty()) continue; | |
5061 if (delete_mode != FORCE_DELETION && !it.IsConfigurable()) { | |
5062 // Fail if the property is not configurable. | |
5063 if (delete_mode == STRICT_DELETION) { | |
5064 Handle<Object> args[2] = {name, object}; | |
5065 Handle<Object> error = it.isolate()->factory()->NewTypeError( | |
5066 "strict_delete_property", HandleVector(args, ARRAY_SIZE(args))); | |
5067 it.isolate()->Throw(*error); | |
5068 return Handle<Object>(); | |
5069 } | |
5070 return it.isolate()->factory()->false_value(); | |
5071 } | |
5094 | 5072 |
5095 if (is_observed) { | 5073 Handle<Object> old_value; |
5096 Maybe<bool> maybe = HasOwnProperty(object, name); | 5074 if (is_observed) { |
5097 if (!maybe.has_value) return MaybeHandle<Object>(); | 5075 switch (it.property_kind()) { |
5098 if (!maybe.value) { | 5076 case LookupIterator::ACCESSOR: |
5099 EnqueueChangeRecord(object, "delete", name, old_value); | 5077 old_value = it.isolate()->factory()->the_hole_value(); |
5078 break; | |
5079 case LookupIterator::DATA: | |
5080 old_value = it.GetDataValue(); | |
5081 } | |
5082 } | |
5083 | |
5084 PropertyNormalizationMode mode = object->map()->is_prototype_map() | |
5085 ? KEEP_INOBJECT_PROPERTIES | |
5086 : CLEAR_INOBJECT_PROPERTIES; | |
5087 Handle<JSObject> holder = it.GetHolder<JSObject>(); | |
5088 NormalizeProperties(holder, mode, 0); | |
5089 Handle<Object> result = | |
5090 DeleteNormalizedProperty(holder, name, delete_mode); | |
5091 ReoptimizeIfPrototype(holder); | |
5092 | |
5093 if (is_observed) { | |
5094 EnqueueChangeRecord(object, "delete", name, old_value); | |
5095 } | |
5096 | |
5097 return result; | |
5098 } | |
5100 } | 5099 } |
5101 } | 5100 } |
5102 | 5101 |
5103 return result; | 5102 return it.isolate()->factory()->true_value(); |
5104 } | 5103 } |
5105 | 5104 |
5106 | 5105 |
5107 MaybeHandle<Object> JSReceiver::DeleteElement(Handle<JSReceiver> object, | 5106 MaybeHandle<Object> JSReceiver::DeleteElement(Handle<JSReceiver> object, |
5108 uint32_t index, | 5107 uint32_t index, |
5109 DeleteMode mode) { | 5108 DeleteMode mode) { |
5110 if (object->IsJSProxy()) { | 5109 if (object->IsJSProxy()) { |
5111 return JSProxy::DeleteElementWithHandler( | 5110 return JSProxy::DeleteElementWithHandler( |
5112 Handle<JSProxy>::cast(object), index, mode); | 5111 Handle<JSProxy>::cast(object), index, mode); |
5113 } | 5112 } |
(...skipping 11565 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
16679 #define ERROR_MESSAGES_TEXTS(C, T) T, | 16678 #define ERROR_MESSAGES_TEXTS(C, T) T, |
16680 static const char* error_messages_[] = { | 16679 static const char* error_messages_[] = { |
16681 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS) | 16680 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS) |
16682 }; | 16681 }; |
16683 #undef ERROR_MESSAGES_TEXTS | 16682 #undef ERROR_MESSAGES_TEXTS |
16684 return error_messages_[reason]; | 16683 return error_messages_[reason]; |
16685 } | 16684 } |
16686 | 16685 |
16687 | 16686 |
16688 } } // namespace v8::internal | 16687 } } // namespace v8::internal |
OLD | NEW |