Index: src/objects.cc |
diff --git a/src/objects.cc b/src/objects.cc |
index b547128a1be3098946a935e218e4476e707b115d..63dd59071091ad5303a9a4e8b0d602e85427297a 100644 |
--- a/src/objects.cc |
+++ b/src/objects.cc |
@@ -3939,14 +3939,6 @@ MaybeHandle<Object> JSProxy::DeletePropertyWithHandler( |
} |
-MaybeHandle<Object> JSProxy::DeleteElementWithHandler( |
- Handle<JSProxy> proxy, uint32_t index, LanguageMode language_mode) { |
- Isolate* isolate = proxy->GetIsolate(); |
- Handle<String> name = isolate->factory()->Uint32ToString(index); |
- return JSProxy::DeletePropertyWithHandler(proxy, name, language_mode); |
-} |
- |
- |
Maybe<PropertyAttributes> JSProxy::GetPropertyAttributesWithHandler( |
Handle<JSProxy> proxy, Handle<Object> receiver, Handle<Name> name) { |
Isolate* isolate = proxy->GetIsolate(); |
@@ -5029,23 +5021,40 @@ Handle<Object> JSObject::SetHiddenPropertiesHashTable(Handle<JSObject> object, |
MaybeHandle<Object> JSObject::DeletePropertyWithInterceptor( |
- Handle<JSObject> holder, Handle<JSObject> receiver, Handle<Name> name) { |
- Isolate* isolate = holder->GetIsolate(); |
+ LookupIterator* it) { |
+ Isolate* isolate = it->isolate(); |
+ // Make sure that the top context does not change when doing callbacks or |
+ // interceptor calls. |
+ AssertNoContextChange ncc(isolate); |
- Handle<InterceptorInfo> interceptor(holder->GetNamedInterceptor()); |
- if (interceptor->deleter()->IsUndefined() || |
- (name->IsSymbol() && !interceptor->can_intercept_symbols())) { |
+ DCHECK_EQ(LookupIterator::INTERCEPTOR, it->state()); |
+ Handle<InterceptorInfo> interceptor(it->GetInterceptor()); |
+ if (interceptor->deleter()->IsUndefined()) return MaybeHandle<Object>(); |
+ |
+ Handle<JSObject> holder = it->GetHolder<JSObject>(); |
+ |
+ PropertyCallbackArguments args(isolate, interceptor->data(), |
+ *it->GetReceiver(), *holder); |
+ v8::Handle<v8::Boolean> result; |
+ if (it->IsElement()) { |
+ uint32_t index = it->index(); |
+ v8::IndexedPropertyDeleterCallback deleter = |
+ v8::ToCData<v8::IndexedPropertyDeleterCallback>(interceptor->deleter()); |
+ LOG(isolate, |
+ ApiIndexedPropertyAccess("interceptor-indexed-delete", *holder, index)); |
+ result = args.Call(deleter, index); |
+ } else if (it->name()->IsSymbol() && !interceptor->can_intercept_symbols()) { |
return MaybeHandle<Object>(); |
+ } else { |
+ Handle<Name> name = it->name(); |
+ v8::GenericNamedPropertyDeleterCallback deleter = |
+ v8::ToCData<v8::GenericNamedPropertyDeleterCallback>( |
+ interceptor->deleter()); |
+ LOG(isolate, |
+ ApiNamedPropertyAccess("interceptor-named-delete", *holder, *name)); |
+ result = args.Call(deleter, v8::Utils::ToLocal(name)); |
} |
- v8::GenericNamedPropertyDeleterCallback deleter = |
- v8::ToCData<v8::GenericNamedPropertyDeleterCallback>( |
- interceptor->deleter()); |
- LOG(isolate, |
- ApiNamedPropertyAccess("interceptor-named-delete", *holder, *name)); |
- PropertyCallbackArguments args(isolate, interceptor->data(), *receiver, |
- *holder); |
- v8::Handle<v8::Boolean> result = args.Call(deleter, v8::Utils::ToLocal(name)); |
RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object); |
if (result.IsEmpty()) return MaybeHandle<Object>(); |
@@ -5057,116 +5066,6 @@ MaybeHandle<Object> JSObject::DeletePropertyWithInterceptor( |
} |
-MaybeHandle<Object> JSObject::DeleteElementWithInterceptor( |
- Handle<JSObject> object, |
- uint32_t index) { |
- Isolate* isolate = object->GetIsolate(); |
- Factory* factory = isolate->factory(); |
- |
- // Make sure that the top context does not change when doing |
- // callbacks or interceptor calls. |
- AssertNoContextChange ncc(isolate); |
- |
- Handle<InterceptorInfo> interceptor(object->GetIndexedInterceptor()); |
- if (interceptor->deleter()->IsUndefined()) return factory->false_value(); |
- v8::IndexedPropertyDeleterCallback deleter = |
- v8::ToCData<v8::IndexedPropertyDeleterCallback>(interceptor->deleter()); |
- LOG(isolate, |
- ApiIndexedPropertyAccess("interceptor-indexed-delete", *object, index)); |
- PropertyCallbackArguments args( |
- isolate, interceptor->data(), *object, *object); |
- v8::Handle<v8::Boolean> result = args.Call(deleter, index); |
- RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object); |
- if (!result.IsEmpty()) { |
- DCHECK(result->IsBoolean()); |
- Handle<Object> result_internal = v8::Utils::OpenHandle(*result); |
- result_internal->VerifyApiCallResultType(); |
- // Rebox CustomArguments::kReturnValueOffset before returning. |
- return handle(*result_internal, isolate); |
- } |
- // TODO(verwaest): Shouldn't this be the mode that was passed in? |
- MaybeHandle<Object> delete_result = |
- object->GetElementsAccessor()->Delete(object, index, SLOPPY); |
- return delete_result; |
-} |
- |
- |
-MaybeHandle<Object> JSObject::DeleteElement(Handle<JSObject> object, |
- uint32_t index, |
- LanguageMode language_mode) { |
- Isolate* isolate = object->GetIsolate(); |
- Factory* factory = isolate->factory(); |
- |
- // Check access rights if needed. |
- if (object->IsAccessCheckNeeded() && !isolate->MayAccess(object)) { |
- isolate->ReportFailedAccessCheck(object); |
- RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object); |
- return factory->false_value(); |
- } |
- |
- if (object->IsStringObjectWithCharacterAt(index)) { |
- if (is_strict(language_mode)) { |
- // Deleting a non-configurable property in strict mode. |
- Handle<Object> name = factory->NewNumberFromUint(index); |
- THROW_NEW_ERROR( |
- isolate, |
- NewTypeError(MessageTemplate::kStrictDeleteProperty, name, object), |
- Object); |
- } |
- return factory->false_value(); |
- } |
- |
- if (object->IsJSGlobalProxy()) { |
- PrototypeIterator iter(isolate, object); |
- if (iter.IsAtEnd()) return factory->false_value(); |
- DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject()); |
- return DeleteElement( |
- Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)), index, |
- language_mode); |
- } |
- |
- Handle<Object> old_value; |
- bool should_enqueue_change_record = false; |
- if (object->map()->is_observed()) { |
- Maybe<bool> maybe = HasOwnElement(object, index); |
- if (!maybe.IsJust()) return MaybeHandle<Object>(); |
- should_enqueue_change_record = maybe.FromJust(); |
- if (should_enqueue_change_record) { |
- if (!GetOwnElementAccessorPair(object, index).is_null()) { |
- old_value = Handle<Object>::cast(factory->the_hole_value()); |
- } else { |
- old_value = Object::GetElement( |
- isolate, object, index).ToHandleChecked(); |
- } |
- } |
- } |
- |
- // Skip interceptor if forcing deletion. |
- MaybeHandle<Object> maybe_result; |
- if (object->HasIndexedInterceptor()) { |
- maybe_result = DeleteElementWithInterceptor(object, index); |
- } else { |
- maybe_result = |
- object->GetElementsAccessor()->Delete(object, index, language_mode); |
- } |
- Handle<Object> result; |
- ASSIGN_RETURN_ON_EXCEPTION(isolate, result, maybe_result, Object); |
- |
- if (should_enqueue_change_record) { |
- Maybe<bool> maybe = HasOwnElement(object, index); |
- if (!maybe.IsJust()) return MaybeHandle<Object>(); |
- if (!maybe.FromJust()) { |
- Handle<String> name = factory->Uint32ToString(index); |
- RETURN_ON_EXCEPTION( |
- isolate, EnqueueChangeRecord(object, "delete", name, old_value), |
- Object); |
- } |
- } |
- |
- return result; |
-} |
- |
- |
void JSObject::DeleteNormalizedProperty(Handle<JSObject> object, |
Handle<Name> name) { |
DCHECK(!object->HasFastProperties()); |
@@ -5196,121 +5095,122 @@ void JSObject::DeleteNormalizedProperty(Handle<JSObject> object, |
} |
-MaybeHandle<Object> JSObject::DeleteProperty(Handle<JSObject> object, |
- Handle<Name> name, |
- LanguageMode language_mode) { |
- // ECMA-262, 3rd, 8.6.2.5 |
- DCHECK(name->IsName()); |
- |
- uint32_t index = 0; |
- if (name->AsArrayIndex(&index)) { |
- return DeleteElement(object, index, language_mode); |
+// ECMA-262, 3rd, 8.6.2.5 |
+MaybeHandle<Object> JSReceiver::DeleteProperty(LookupIterator* it, |
+ LanguageMode language_mode) { |
+ Isolate* isolate = it->isolate(); |
+ if (it->state() == LookupIterator::JSPROXY) { |
+ return JSProxy::DeletePropertyWithHandler(it->GetHolder<JSProxy>(), |
+ it->GetName(), language_mode); |
} |
- LookupIterator it(object, name, LookupIterator::HIDDEN); |
+ Handle<JSObject> receiver = Handle<JSObject>::cast(it->GetReceiver()); |
- bool is_observed = object->map()->is_observed() && |
- !it.isolate()->IsInternallyUsedPropertyName(name); |
- Handle<Object> old_value = it.isolate()->factory()->the_hole_value(); |
+ bool is_observed = |
+ receiver->map()->is_observed() && |
+ (it->IsElement() || !isolate->IsInternallyUsedPropertyName(it->name())); |
- for (; it.IsFound(); it.Next()) { |
- switch (it.state()) { |
+ Handle<Object> old_value = it->factory()->the_hole_value(); |
+ |
+ for (; it->IsFound(); it->Next()) { |
+ switch (it->state()) { |
case LookupIterator::JSPROXY: |
case LookupIterator::NOT_FOUND: |
case LookupIterator::TRANSITION: |
UNREACHABLE(); |
case LookupIterator::ACCESS_CHECK: |
- if (it.HasAccess()) break; |
- it.isolate()->ReportFailedAccessCheck(it.GetHolder<JSObject>()); |
- RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(it.isolate(), Object); |
- return it.isolate()->factory()->false_value(); |
+ if (it->HasAccess()) break; |
+ isolate->ReportFailedAccessCheck(it->GetHolder<JSObject>()); |
+ RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object); |
+ return it->factory()->false_value(); |
case LookupIterator::INTERCEPTOR: { |
MaybeHandle<Object> maybe_result = |
- JSObject::DeletePropertyWithInterceptor(it.GetHolder<JSObject>(), |
- object, it.name()); |
+ JSObject::DeletePropertyWithInterceptor(it); |
// Delete with interceptor succeeded. Return result. |
if (!maybe_result.is_null()) return maybe_result; |
// An exception was thrown in the interceptor. Propagate. |
- if (it.isolate()->has_pending_exception()) return maybe_result; |
+ if (isolate->has_pending_exception()) return maybe_result; |
break; |
} |
case LookupIterator::INTEGER_INDEXED_EXOTIC: |
- return it.isolate()->factory()->true_value(); |
+ return it->factory()->true_value(); |
case LookupIterator::DATA: |
if (is_observed) { |
- old_value = it.GetDataValue(); |
+ old_value = it->GetDataValue(); |
} |
// Fall through. |
case LookupIterator::ACCESSOR: { |
- if (!it.IsConfigurable() || object->map()->is_strong()) { |
+ if (!it->IsConfigurable() || receiver->map()->is_strong()) { |
// Fail if the property is not configurable, or on a strong object. |
if (is_strict(language_mode)) { |
- if (object->map()->is_strong()) { |
+ if (receiver->map()->is_strong()) { |
THROW_NEW_ERROR( |
- it.isolate(), |
- NewTypeError(MessageTemplate::kStrongDeleteProperty, object, |
- name), |
+ isolate, NewTypeError(MessageTemplate::kStrongDeleteProperty, |
+ receiver, it->GetName()), |
Object); |
} |
- THROW_NEW_ERROR(it.isolate(), |
+ THROW_NEW_ERROR(isolate, |
NewTypeError(MessageTemplate::kStrictDeleteProperty, |
- name, object), |
+ it->GetName(), receiver), |
Object); |
} |
- return it.isolate()->factory()->false_value(); |
+ return it->factory()->false_value(); |
} |
- PropertyNormalizationMode mode = object->map()->is_prototype_map() |
- ? KEEP_INOBJECT_PROPERTIES |
- : CLEAR_INOBJECT_PROPERTIES; |
- Handle<JSObject> holder = it.GetHolder<JSObject>(); |
+ Handle<JSObject> holder = it->GetHolder<JSObject>(); |
// TODO(verwaest): Remove this temporary compatibility hack when blink |
// tests are updated. |
- if (!holder.is_identical_to(object) && |
- !(object->IsJSGlobalProxy() && holder->IsJSGlobalObject())) { |
- return it.isolate()->factory()->true_value(); |
+ if (!holder.is_identical_to(receiver) && |
+ !(receiver->IsJSGlobalProxy() && holder->IsJSGlobalObject())) { |
+ return it->factory()->true_value(); |
} |
- NormalizeProperties(holder, mode, 0, "DeletingProperty"); |
- DeleteNormalizedProperty(holder, name); |
- ReoptimizeIfPrototype(holder); |
+ if (it->IsElement()) { |
+ ElementsAccessor* accessor = holder->GetElementsAccessor(); |
+ accessor->Delete(holder, it->index(), language_mode); |
+ } else { |
+ PropertyNormalizationMode mode = holder->map()->is_prototype_map() |
+ ? KEEP_INOBJECT_PROPERTIES |
+ : CLEAR_INOBJECT_PROPERTIES; |
+ |
+ JSObject::NormalizeProperties(holder, mode, 0, "DeletingProperty"); |
+ JSObject::DeleteNormalizedProperty(holder, it->name()); |
+ JSObject::ReoptimizeIfPrototype(holder); |
+ } |
if (is_observed) { |
- RETURN_ON_EXCEPTION( |
- it.isolate(), |
- EnqueueChangeRecord(object, "delete", name, old_value), Object); |
+ RETURN_ON_EXCEPTION(isolate, |
+ JSObject::EnqueueChangeRecord( |
+ receiver, "delete", it->GetName(), old_value), |
+ Object); |
} |
- return it.isolate()->factory()->true_value(); |
+ return it->factory()->true_value(); |
} |
} |
} |
- return it.isolate()->factory()->true_value(); |
+ return it->factory()->true_value(); |
} |
MaybeHandle<Object> JSReceiver::DeleteElement(Handle<JSReceiver> object, |
uint32_t index, |
LanguageMode language_mode) { |
- if (object->IsJSProxy()) { |
- return JSProxy::DeleteElementWithHandler(Handle<JSProxy>::cast(object), |
- index, language_mode); |
- } |
- return JSObject::DeleteElement(Handle<JSObject>::cast(object), index, |
- language_mode); |
+ LookupIterator it(object->GetIsolate(), object, index); |
+ return DeleteProperty(&it, language_mode); |
} |
MaybeHandle<Object> JSReceiver::DeleteProperty(Handle<JSReceiver> object, |
Handle<Name> name, |
LanguageMode language_mode) { |
- if (object->IsJSProxy()) { |
- return JSProxy::DeletePropertyWithHandler(Handle<JSProxy>::cast(object), |
- name, language_mode); |
- } |
- return JSObject::DeleteProperty(Handle<JSObject>::cast(object), name, |
- language_mode); |
+ uint32_t index; |
+ LookupIterator::Configuration c = LookupIterator::HIDDEN; |
+ LookupIterator it = name->AsArrayIndex(&index) |
+ ? LookupIterator(name->GetIsolate(), object, index, c) |
+ : LookupIterator(object, name, c); |
+ return JSObject::DeleteProperty(&it, language_mode); |
} |