OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 5012 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5023 return handle(*result_internal, isolate); | 5023 return handle(*result_internal, isolate); |
5024 } | 5024 } |
5025 } | 5025 } |
5026 Handle<Object> result = | 5026 Handle<Object> result = |
5027 DeletePropertyPostInterceptor(object, name, NORMAL_DELETION); | 5027 DeletePropertyPostInterceptor(object, name, NORMAL_DELETION); |
5028 RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object); | 5028 RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object); |
5029 return result; | 5029 return result; |
5030 } | 5030 } |
5031 | 5031 |
5032 | 5032 |
5033 MaybeObject* JSObject::DeleteElementWithInterceptor(uint32_t index) { | 5033 // TODO(mstarzinger): Temporary wrapper until handlified. |
5034 Isolate* isolate = GetIsolate(); | 5034 static Handle<Object> AccessorDelete(Handle<JSObject> object, |
5035 Heap* heap = isolate->heap(); | 5035 uint32_t index, |
5036 HandleScope scope(isolate); | 5036 JSObject::DeleteMode mode) { |
| 5037 CALL_HEAP_FUNCTION(object->GetIsolate(), |
| 5038 object->GetElementsAccessor()->Delete(*object, |
| 5039 index, |
| 5040 mode), |
| 5041 Object); |
| 5042 } |
| 5043 |
| 5044 |
| 5045 Handle<Object> JSObject::DeleteElementWithInterceptor(Handle<JSObject> object, |
| 5046 uint32_t index) { |
| 5047 Isolate* isolate = object->GetIsolate(); |
| 5048 Factory* factory = isolate->factory(); |
5037 | 5049 |
5038 // Make sure that the top context does not change when doing | 5050 // Make sure that the top context does not change when doing |
5039 // callbacks or interceptor calls. | 5051 // callbacks or interceptor calls. |
5040 AssertNoContextChange ncc; | 5052 AssertNoContextChange ncc; |
5041 | 5053 |
5042 Handle<InterceptorInfo> interceptor(GetIndexedInterceptor()); | 5054 Handle<InterceptorInfo> interceptor(object->GetIndexedInterceptor()); |
5043 if (interceptor->deleter()->IsUndefined()) return heap->false_value(); | 5055 if (interceptor->deleter()->IsUndefined()) return factory->false_value(); |
5044 v8::IndexedPropertyDeleterCallback deleter = | 5056 v8::IndexedPropertyDeleterCallback deleter = |
5045 v8::ToCData<v8::IndexedPropertyDeleterCallback>(interceptor->deleter()); | 5057 v8::ToCData<v8::IndexedPropertyDeleterCallback>(interceptor->deleter()); |
5046 Handle<JSObject> this_handle(this); | |
5047 LOG(isolate, | 5058 LOG(isolate, |
5048 ApiIndexedPropertyAccess("interceptor-indexed-delete", this, index)); | 5059 ApiIndexedPropertyAccess("interceptor-indexed-delete", *object, index)); |
5049 PropertyCallbackArguments args(isolate, interceptor->data(), this, this); | 5060 PropertyCallbackArguments args( |
| 5061 isolate, interceptor->data(), *object, *object); |
5050 v8::Handle<v8::Boolean> result = args.Call(deleter, index); | 5062 v8::Handle<v8::Boolean> result = args.Call(deleter, index); |
5051 RETURN_IF_SCHEDULED_EXCEPTION(isolate); | 5063 RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object); |
5052 if (!result.IsEmpty()) { | 5064 if (!result.IsEmpty()) { |
5053 ASSERT(result->IsBoolean()); | 5065 ASSERT(result->IsBoolean()); |
5054 Handle<Object> result_internal = v8::Utils::OpenHandle(*result); | 5066 Handle<Object> result_internal = v8::Utils::OpenHandle(*result); |
5055 result_internal->VerifyApiCallResultType(); | 5067 result_internal->VerifyApiCallResultType(); |
5056 return *result_internal; | 5068 // Rebox CustomArguments::kReturnValueOffset before returning. |
| 5069 return handle(*result_internal, isolate); |
5057 } | 5070 } |
5058 MaybeObject* raw_result = this_handle->GetElementsAccessor()->Delete( | 5071 Handle<Object> delete_result = AccessorDelete(object, index, NORMAL_DELETION); |
5059 *this_handle, | 5072 RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object); |
5060 index, | 5073 return delete_result; |
5061 NORMAL_DELETION); | |
5062 RETURN_IF_SCHEDULED_EXCEPTION(isolate); | |
5063 return raw_result; | |
5064 } | 5074 } |
5065 | 5075 |
5066 | 5076 |
5067 Handle<Object> JSObject::DeleteElement(Handle<JSObject> obj, | 5077 Handle<Object> JSObject::DeleteElement(Handle<JSObject> object, |
5068 uint32_t index, | 5078 uint32_t index, |
5069 DeleteMode mode) { | 5079 DeleteMode mode) { |
5070 CALL_HEAP_FUNCTION(obj->GetIsolate(), | 5080 Isolate* isolate = object->GetIsolate(); |
5071 obj->DeleteElement(index, mode), | 5081 Factory* factory = isolate->factory(); |
5072 Object); | 5082 |
| 5083 // Check access rights if needed. |
| 5084 if (object->IsAccessCheckNeeded() && |
| 5085 !isolate->MayIndexedAccess(*object, index, v8::ACCESS_DELETE)) { |
| 5086 isolate->ReportFailedAccessCheck(*object, v8::ACCESS_DELETE); |
| 5087 RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object); |
| 5088 return factory->false_value(); |
| 5089 } |
| 5090 |
| 5091 if (object->IsStringObjectWithCharacterAt(index)) { |
| 5092 if (mode == STRICT_DELETION) { |
| 5093 // Deleting a non-configurable property in strict mode. |
| 5094 Handle<Object> name = factory->NewNumberFromUint(index); |
| 5095 Handle<Object> args[2] = { name, object }; |
| 5096 Handle<Object> error = |
| 5097 factory->NewTypeError("strict_delete_property", |
| 5098 HandleVector(args, 2)); |
| 5099 isolate->Throw(*error); |
| 5100 return Handle<Object>(); |
| 5101 } |
| 5102 return factory->false_value(); |
| 5103 } |
| 5104 |
| 5105 if (object->IsJSGlobalProxy()) { |
| 5106 Handle<Object> proto(object->GetPrototype(), isolate); |
| 5107 if (proto->IsNull()) return factory->false_value(); |
| 5108 ASSERT(proto->IsJSGlobalObject()); |
| 5109 return DeleteElement(Handle<JSObject>::cast(proto), index, mode); |
| 5110 } |
| 5111 |
| 5112 Handle<Object> old_value; |
| 5113 bool should_enqueue_change_record = false; |
| 5114 if (FLAG_harmony_observation && object->map()->is_observed()) { |
| 5115 should_enqueue_change_record = object->HasLocalElement(index); |
| 5116 if (should_enqueue_change_record) { |
| 5117 old_value = object->GetLocalElementAccessorPair(index) != NULL |
| 5118 ? Handle<Object>::cast(factory->the_hole_value()) |
| 5119 : Object::GetElement(object, index); |
| 5120 } |
| 5121 } |
| 5122 |
| 5123 // Skip interceptor if forcing deletion. |
| 5124 Handle<Object> result; |
| 5125 if (object->HasIndexedInterceptor() && mode != FORCE_DELETION) { |
| 5126 result = DeleteElementWithInterceptor(object, index); |
| 5127 } else { |
| 5128 result = AccessorDelete(object, index, mode); |
| 5129 } |
| 5130 |
| 5131 if (should_enqueue_change_record && !object->HasLocalElement(index)) { |
| 5132 Handle<String> name = factory->Uint32ToString(index); |
| 5133 EnqueueChangeRecord(object, "deleted", name, old_value); |
| 5134 } |
| 5135 |
| 5136 return result; |
5073 } | 5137 } |
5074 | 5138 |
5075 | 5139 |
5076 MaybeObject* JSObject::DeleteElement(uint32_t index, DeleteMode mode) { | |
5077 Isolate* isolate = GetIsolate(); | |
5078 // Check access rights if needed. | |
5079 if (IsAccessCheckNeeded() && | |
5080 !isolate->MayIndexedAccess(this, index, v8::ACCESS_DELETE)) { | |
5081 isolate->ReportFailedAccessCheck(this, v8::ACCESS_DELETE); | |
5082 RETURN_IF_SCHEDULED_EXCEPTION(isolate); | |
5083 return isolate->heap()->false_value(); | |
5084 } | |
5085 | |
5086 if (IsStringObjectWithCharacterAt(index)) { | |
5087 if (mode == STRICT_DELETION) { | |
5088 // Deleting a non-configurable property in strict mode. | |
5089 HandleScope scope(isolate); | |
5090 Handle<Object> holder(this, isolate); | |
5091 Handle<Object> name = isolate->factory()->NewNumberFromUint(index); | |
5092 Handle<Object> args[2] = { name, holder }; | |
5093 Handle<Object> error = | |
5094 isolate->factory()->NewTypeError("strict_delete_property", | |
5095 HandleVector(args, 2)); | |
5096 return isolate->Throw(*error); | |
5097 } | |
5098 return isolate->heap()->false_value(); | |
5099 } | |
5100 | |
5101 if (IsJSGlobalProxy()) { | |
5102 Object* proto = GetPrototype(); | |
5103 if (proto->IsNull()) return isolate->heap()->false_value(); | |
5104 ASSERT(proto->IsJSGlobalObject()); | |
5105 return JSGlobalObject::cast(proto)->DeleteElement(index, mode); | |
5106 } | |
5107 | |
5108 // From this point on everything needs to be handlified. | |
5109 HandleScope scope(isolate); | |
5110 Handle<JSObject> self(this); | |
5111 | |
5112 Handle<Object> old_value; | |
5113 bool should_enqueue_change_record = false; | |
5114 if (FLAG_harmony_observation && self->map()->is_observed()) { | |
5115 should_enqueue_change_record = self->HasLocalElement(index); | |
5116 if (should_enqueue_change_record) { | |
5117 old_value = self->GetLocalElementAccessorPair(index) != NULL | |
5118 ? Handle<Object>::cast(isolate->factory()->the_hole_value()) | |
5119 : Object::GetElement(self, index); | |
5120 } | |
5121 } | |
5122 | |
5123 MaybeObject* result; | |
5124 // Skip interceptor if forcing deletion. | |
5125 if (self->HasIndexedInterceptor() && mode != FORCE_DELETION) { | |
5126 result = self->DeleteElementWithInterceptor(index); | |
5127 } else { | |
5128 result = self->GetElementsAccessor()->Delete(*self, index, mode); | |
5129 } | |
5130 | |
5131 Handle<Object> hresult; | |
5132 if (!result->ToHandle(&hresult, isolate)) return result; | |
5133 | |
5134 if (should_enqueue_change_record && !self->HasLocalElement(index)) { | |
5135 Handle<String> name = isolate->factory()->Uint32ToString(index); | |
5136 EnqueueChangeRecord(self, "deleted", name, old_value); | |
5137 } | |
5138 | |
5139 return *hresult; | |
5140 } | |
5141 | |
5142 | |
5143 Handle<Object> JSObject::DeleteProperty(Handle<JSObject> object, | 5140 Handle<Object> JSObject::DeleteProperty(Handle<JSObject> object, |
5144 Handle<Name> name, | 5141 Handle<Name> name, |
5145 DeleteMode mode) { | 5142 DeleteMode mode) { |
5146 Isolate* isolate = object->GetIsolate(); | 5143 Isolate* isolate = object->GetIsolate(); |
5147 // ECMA-262, 3rd, 8.6.2.5 | 5144 // ECMA-262, 3rd, 8.6.2.5 |
5148 ASSERT(name->IsName()); | 5145 ASSERT(name->IsName()); |
5149 | 5146 |
5150 // Check access rights if needed. | 5147 // Check access rights if needed. |
5151 if (object->IsAccessCheckNeeded() && | 5148 if (object->IsAccessCheckNeeded() && |
5152 !isolate->MayNamedAccess(*object, *name, v8::ACCESS_DELETE)) { | 5149 !isolate->MayNamedAccess(*object, *name, v8::ACCESS_DELETE)) { |
(...skipping 10841 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
15994 #define ERROR_MESSAGES_TEXTS(C, T) T, | 15991 #define ERROR_MESSAGES_TEXTS(C, T) T, |
15995 static const char* error_messages_[] = { | 15992 static const char* error_messages_[] = { |
15996 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS) | 15993 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS) |
15997 }; | 15994 }; |
15998 #undef ERROR_MESSAGES_TEXTS | 15995 #undef ERROR_MESSAGES_TEXTS |
15999 return error_messages_[reason]; | 15996 return error_messages_[reason]; |
16000 } | 15997 } |
16001 | 15998 |
16002 | 15999 |
16003 } } // namespace v8::internal | 16000 } } // namespace v8::internal |
OLD | NEW |