Commit 6867595c authored by verwaest@chromium.org's avatar verwaest@chromium.org

Rewrite DeleteProperty using the LookupIterator

BUG=
R=jkummerow@chromium.org

Review URL: https://codereview.chromium.org/468073002

git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@23166 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 41a970c5
...@@ -4855,56 +4855,32 @@ Handle<Object> JSObject::SetHiddenPropertiesHashTable(Handle<JSObject> object, ...@@ -4855,56 +4855,32 @@ Handle<Object> JSObject::SetHiddenPropertiesHashTable(Handle<JSObject> object,
} }
Handle<Object> JSObject::DeletePropertyPostInterceptor(Handle<JSObject> object,
Handle<Name> name,
DeleteMode delete_mode) {
// Check own property, ignore interceptor.
Isolate* isolate = object->GetIsolate();
LookupResult lookup(isolate);
object->LookupOwnRealNamedProperty(name, &lookup);
if (!lookup.IsFound()) return isolate->factory()->true_value();
PropertyNormalizationMode mode = object->map()->is_prototype_map()
? KEEP_INOBJECT_PROPERTIES
: CLEAR_INOBJECT_PROPERTIES;
// Normalize object if needed.
NormalizeProperties(object, mode, 0);
Handle<Object> result = DeleteNormalizedProperty(object, name, delete_mode);
ReoptimizeIfPrototype(object);
return result;
}
MaybeHandle<Object> JSObject::DeletePropertyWithInterceptor( MaybeHandle<Object> JSObject::DeletePropertyWithInterceptor(
Handle<JSObject> object, Handle<Name> name) { Handle<JSObject> holder, Handle<JSObject> receiver, Handle<Name> name) {
Isolate* isolate = object->GetIsolate(); Isolate* isolate = holder->GetIsolate();
// TODO(rossberg): Support symbols in the API. // TODO(rossberg): Support symbols in the API.
if (name->IsSymbol()) return isolate->factory()->false_value(); if (name->IsSymbol()) return MaybeHandle<Object>();
Handle<InterceptorInfo> interceptor(object->GetNamedInterceptor()); Handle<InterceptorInfo> interceptor(holder->GetNamedInterceptor());
if (!interceptor->deleter()->IsUndefined()) { if (interceptor->deleter()->IsUndefined()) return MaybeHandle<Object>();
v8::NamedPropertyDeleterCallback deleter =
v8::ToCData<v8::NamedPropertyDeleterCallback>(interceptor->deleter()); v8::NamedPropertyDeleterCallback deleter =
LOG(isolate, v8::ToCData<v8::NamedPropertyDeleterCallback>(interceptor->deleter());
ApiNamedPropertyAccess("interceptor-named-delete", *object, *name)); LOG(isolate,
PropertyCallbackArguments args( ApiNamedPropertyAccess("interceptor-named-delete", *holder, *name));
isolate, interceptor->data(), *object, *object); PropertyCallbackArguments args(isolate, interceptor->data(), *receiver,
v8::Handle<v8::Boolean> result = *holder);
args.Call(deleter, v8::Utils::ToLocal(Handle<String>::cast(name))); v8::Handle<v8::Boolean> result =
RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object); args.Call(deleter, v8::Utils::ToLocal(Handle<String>::cast(name)));
if (!result.IsEmpty()) { RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
DCHECK(result->IsBoolean()); if (result.IsEmpty()) return MaybeHandle<Object>();
Handle<Object> result_internal = v8::Utils::OpenHandle(*result);
result_internal->VerifyApiCallResultType(); DCHECK(result->IsBoolean());
// Rebox CustomArguments::kReturnValueOffset before returning. Handle<Object> result_internal = v8::Utils::OpenHandle(*result);
return handle(*result_internal, isolate); result_internal->VerifyApiCallResultType();
} // Rebox CustomArguments::kReturnValueOffset before returning.
} return handle(*result_internal, isolate);
Handle<Object> result =
DeletePropertyPostInterceptor(object, name, NORMAL_DELETION);
return result;
} }
...@@ -5020,87 +4996,89 @@ MaybeHandle<Object> JSObject::DeleteElement(Handle<JSObject> object, ...@@ -5020,87 +4996,89 @@ MaybeHandle<Object> JSObject::DeleteElement(Handle<JSObject> object,
MaybeHandle<Object> JSObject::DeleteProperty(Handle<JSObject> object, MaybeHandle<Object> JSObject::DeleteProperty(Handle<JSObject> object,
Handle<Name> name, Handle<Name> name,
DeleteMode delete_mode) { DeleteMode delete_mode) {
Isolate* isolate = object->GetIsolate();
// ECMA-262, 3rd, 8.6.2.5 // ECMA-262, 3rd, 8.6.2.5
DCHECK(name->IsName()); DCHECK(name->IsName());
// Check access rights if needed.
if (object->IsAccessCheckNeeded() &&
!isolate->MayNamedAccess(object, name, v8::ACCESS_DELETE)) {
isolate->ReportFailedAccessCheck(object, v8::ACCESS_DELETE);
RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
return isolate->factory()->false_value();
}
if (object->IsJSGlobalProxy()) {
PrototypeIterator iter(isolate, object);
if (iter.IsAtEnd()) return isolate->factory()->false_value();
DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject());
return JSGlobalObject::DeleteProperty(
Handle<JSGlobalObject>::cast(PrototypeIterator::GetCurrent(iter)), name,
delete_mode);
}
uint32_t index = 0; uint32_t index = 0;
if (name->AsArrayIndex(&index)) { if (name->AsArrayIndex(&index)) {
return DeleteElement(object, index, delete_mode); return DeleteElement(object, index, delete_mode);
} }
LookupResult lookup(isolate); // Skip interceptors on FORCE_DELETION.
object->LookupOwn(name, &lookup, true); LookupIterator::Configuration config =
if (!lookup.IsFound()) return isolate->factory()->true_value(); delete_mode == FORCE_DELETION ? LookupIterator::CHECK_HIDDEN_ACCESS
// Ignore attributes if forcing a deletion. : LookupIterator::CHECK_OWN;
if (lookup.IsDontDelete() && delete_mode != FORCE_DELETION) {
if (delete_mode == STRICT_DELETION) { LookupIterator it(object, name, config);
// Deleting a non-configurable property in strict mode.
Handle<Object> args[2] = { name, object };
Handle<Object> error = isolate->factory()->NewTypeError(
"strict_delete_property", HandleVector(args, ARRAY_SIZE(args)));
isolate->Throw(*error);
return Handle<Object>();
}
return isolate->factory()->false_value();
}
Handle<Object> old_value = isolate->factory()->the_hole_value();
bool is_observed = object->map()->is_observed() && bool is_observed = object->map()->is_observed() &&
*name != isolate->heap()->hidden_string(); *name != it.isolate()->heap()->hidden_string();
if (is_observed && lookup.IsDataProperty()) {
old_value = Object::GetPropertyOrElement(object, name).ToHandleChecked();
}
Handle<Object> result;
// Check for interceptor. for (; it.IsFound(); it.Next()) {
if (lookup.IsInterceptor()) { switch (it.state()) {
// Skip interceptor if forcing a deletion. case LookupIterator::NOT_FOUND:
if (delete_mode == FORCE_DELETION) { case LookupIterator::JSPROXY:
result = DeletePropertyPostInterceptor(object, name, delete_mode); UNREACHABLE();
} else { case LookupIterator::ACCESS_CHECK:
ASSIGN_RETURN_ON_EXCEPTION( if (it.HasAccess(v8::ACCESS_DELETE)) break;
isolate, result, it.isolate()->ReportFailedAccessCheck(it.GetHolder<JSObject>(),
DeletePropertyWithInterceptor(object, name), v8::ACCESS_DELETE);
Object); RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(it.isolate(), Object);
} return it.isolate()->factory()->false_value();
} else { case LookupIterator::INTERCEPTOR: {
PropertyNormalizationMode mode = object->map()->is_prototype_map() MaybeHandle<Object> maybe_result =
? KEEP_INOBJECT_PROPERTIES JSObject::DeletePropertyWithInterceptor(it.GetHolder<JSObject>(),
: CLEAR_INOBJECT_PROPERTIES; object, it.name());
// Normalize object if needed. // Delete with interceptor succeeded. Return result.
NormalizeProperties(object, mode, 0); if (!maybe_result.is_null()) return maybe_result;
// Make sure the properties are normalized before removing the entry. // An exception was thrown in the interceptor. Propagate.
result = DeleteNormalizedProperty(object, name, delete_mode); if (it.isolate()->has_pending_exception()) return maybe_result;
ReoptimizeIfPrototype(object); break;
} }
case LookupIterator::PROPERTY: {
if (!it.HasProperty()) continue;
if (delete_mode != FORCE_DELETION && !it.IsConfigurable()) {
// Fail if the property is not configurable.
if (delete_mode == STRICT_DELETION) {
Handle<Object> args[2] = {name, object};
Handle<Object> error = it.isolate()->factory()->NewTypeError(
"strict_delete_property", HandleVector(args, ARRAY_SIZE(args)));
it.isolate()->Throw(*error);
return Handle<Object>();
}
return it.isolate()->factory()->false_value();
}
if (is_observed) { Handle<Object> old_value;
Maybe<bool> maybe = HasOwnProperty(object, name); if (is_observed) {
if (!maybe.has_value) return MaybeHandle<Object>(); switch (it.property_kind()) {
if (!maybe.value) { case LookupIterator::ACCESSOR:
EnqueueChangeRecord(object, "delete", name, old_value); old_value = it.isolate()->factory()->the_hole_value();
break;
case LookupIterator::DATA:
old_value = it.GetDataValue();
}
}
PropertyNormalizationMode mode = object->map()->is_prototype_map()
? KEEP_INOBJECT_PROPERTIES
: CLEAR_INOBJECT_PROPERTIES;
Handle<JSObject> holder = it.GetHolder<JSObject>();
NormalizeProperties(holder, mode, 0);
Handle<Object> result =
DeleteNormalizedProperty(holder, name, delete_mode);
ReoptimizeIfPrototype(holder);
if (is_observed) {
EnqueueChangeRecord(object, "delete", name, old_value);
}
return result;
}
} }
} }
return result; return it.isolate()->factory()->true_value();
} }
......
...@@ -2692,12 +2692,8 @@ class JSObject: public JSReceiver { ...@@ -2692,12 +2692,8 @@ class JSObject: public JSReceiver {
Handle<JSObject> object, Handle<JSObject> object,
Handle<Name> name, Handle<Name> name,
DeleteMode mode); DeleteMode mode);
static Handle<Object> DeletePropertyPostInterceptor(Handle<JSObject> object,
Handle<Name> name,
DeleteMode mode);
MUST_USE_RESULT static MaybeHandle<Object> DeletePropertyWithInterceptor( MUST_USE_RESULT static MaybeHandle<Object> DeletePropertyWithInterceptor(
Handle<JSObject> object, Handle<JSObject> holder, Handle<JSObject> receiver, Handle<Name> name);
Handle<Name> name);
// Deletes the named property in a normalized object. // Deletes the named property in a normalized object.
static Handle<Object> DeleteNormalizedProperty(Handle<JSObject> object, static Handle<Object> DeleteNormalizedProperty(Handle<JSObject> object,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment