Index: src/objects.cc |
=================================================================== |
--- src/objects.cc (revision 2114) |
+++ src/objects.cc (working copy) |
@@ -385,7 +385,9 @@ |
} |
-Object* JSObject::DeleteLazyProperty(LookupResult* result, String* name) { |
+Object* JSObject::DeleteLazyProperty(LookupResult* result, |
+ String* name, |
+ DeleteMode mode) { |
HandleScope scope; |
Handle<JSObject> this_handle(this); |
Handle<String> name_handle(name); |
@@ -393,7 +395,7 @@ |
LoadLazy(Handle<JSObject>(JSObject::cast(result->GetLazyValue())), |
&pending_exception); |
if (pending_exception) return Failure::Exception(); |
- return this_handle->DeleteProperty(*name_handle); |
+ return this_handle->DeleteProperty(*name_handle, mode); |
} |
@@ -2120,7 +2122,7 @@ |
} |
-Object* JSObject::DeletePropertyPostInterceptor(String* name) { |
+Object* JSObject::DeletePropertyPostInterceptor(String* name, DeleteMode mode) { |
// Check local property, ignore interceptor. |
LookupResult result; |
LocalLookupRealNamedProperty(name, &result); |
@@ -2134,7 +2136,7 @@ |
// Attempt to remove the property from the property dictionary. |
Dictionary* dictionary = property_dictionary(); |
int entry = dictionary->FindStringEntry(name); |
- if (entry != -1) return dictionary->DeleteProperty(entry); |
+ if (entry != -1) return dictionary->DeleteProperty(entry, mode); |
return Heap::true_value(); |
} |
@@ -2164,13 +2166,15 @@ |
return *v8::Utils::OpenHandle(*result); |
} |
} |
- Object* raw_result = this_handle->DeletePropertyPostInterceptor(*name_handle); |
+ Object* raw_result = |
+ this_handle->DeletePropertyPostInterceptor(*name_handle, NORMAL_DELETION); |
RETURN_IF_SCHEDULED_EXCEPTION(); |
return raw_result; |
} |
-Object* JSObject::DeleteElementPostInterceptor(uint32_t index) { |
+Object* JSObject::DeleteElementPostInterceptor(uint32_t index, |
+ DeleteMode mode) { |
if (HasFastElements()) { |
uint32_t length = IsJSArray() ? |
static_cast<uint32_t>(Smi::cast(JSArray::cast(this)->length())->value()) : |
@@ -2183,7 +2187,7 @@ |
ASSERT(!HasFastElements()); |
Dictionary* dictionary = element_dictionary(); |
int entry = dictionary->FindNumberEntry(index); |
- if (entry != -1) return dictionary->DeleteProperty(entry); |
+ if (entry != -1) return dictionary->DeleteProperty(entry, mode); |
return Heap::true_value(); |
} |
@@ -2214,13 +2218,14 @@ |
ASSERT(result->IsBoolean()); |
return *v8::Utils::OpenHandle(*result); |
} |
- Object* raw_result = this_handle->DeleteElementPostInterceptor(index); |
+ Object* raw_result = |
+ this_handle->DeleteElementPostInterceptor(index, NORMAL_DELETION); |
RETURN_IF_SCHEDULED_EXCEPTION(); |
return raw_result; |
} |
-Object* JSObject::DeleteElement(uint32_t index) { |
+Object* JSObject::DeleteElement(uint32_t index, DeleteMode mode) { |
// Check access rights if needed. |
if (IsAccessCheckNeeded() && |
!Top::MayIndexedAccess(this, index, v8::ACCESS_DELETE)) { |
@@ -2232,10 +2237,14 @@ |
Object* proto = GetPrototype(); |
if (proto->IsNull()) return Heap::false_value(); |
ASSERT(proto->IsJSGlobalObject()); |
- return JSGlobalObject::cast(proto)->DeleteElement(index); |
+ return JSGlobalObject::cast(proto)->DeleteElement(index, mode); |
} |
if (HasIndexedInterceptor()) { |
+ // Skip interceptor if forcing deletion. |
+ if (mode == FORCE_DELETION) { |
+ return DeleteElementPostInterceptor(index, mode); |
+ } |
return DeleteElementWithInterceptor(index); |
} |
@@ -2250,13 +2259,13 @@ |
} else { |
Dictionary* dictionary = element_dictionary(); |
int entry = dictionary->FindNumberEntry(index); |
- if (entry != -1) return dictionary->DeleteProperty(entry); |
+ if (entry != -1) return dictionary->DeleteProperty(entry, mode); |
} |
return Heap::true_value(); |
} |
-Object* JSObject::DeleteProperty(String* name) { |
+Object* JSObject::DeleteProperty(String* name, DeleteMode mode) { |
// ECMA-262, 3rd, 8.6.2.5 |
ASSERT(name->IsString()); |
@@ -2271,23 +2280,32 @@ |
Object* proto = GetPrototype(); |
if (proto->IsNull()) return Heap::false_value(); |
ASSERT(proto->IsJSGlobalObject()); |
- return JSGlobalObject::cast(proto)->DeleteProperty(name); |
+ return JSGlobalObject::cast(proto)->DeleteProperty(name, mode); |
} |
uint32_t index = 0; |
if (name->AsArrayIndex(&index)) { |
- return DeleteElement(index); |
+ return DeleteElement(index, mode); |
} else { |
LookupResult result; |
LocalLookup(name, &result); |
if (!result.IsValid()) return Heap::true_value(); |
- if (result.IsDontDelete()) return Heap::false_value(); |
+ // Ignore attributes if forcing a deletion. |
+ if (result.IsDontDelete() && mode != FORCE_DELETION) { |
+ return Heap::false_value(); |
+ } |
// Check for interceptor. |
if (result.type() == INTERCEPTOR) { |
+ // Skip interceptor if forcing a deletion. |
+ if (mode == FORCE_DELETION) { |
+ return DeletePropertyPostInterceptor(name, mode); |
+ } |
return DeletePropertyWithInterceptor(name); |
} |
if (!result.IsLoaded()) { |
- return JSObject::cast(this)->DeleteLazyProperty(&result, name); |
+ return JSObject::cast(this)->DeleteLazyProperty(&result, |
+ name, |
+ mode); |
} |
// Normalize object if needed. |
Object* obj = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES); |
@@ -2295,7 +2313,7 @@ |
// Make sure the properties are normalized before removing the entry. |
Dictionary* dictionary = property_dictionary(); |
int entry = dictionary->FindStringEntry(name); |
- if (entry != -1) return dictionary->DeleteProperty(entry); |
+ if (entry != -1) return dictionary->DeleteProperty(entry, mode); |
return Heap::true_value(); |
} |
} |
@@ -6943,9 +6961,12 @@ |
} |
-Object* Dictionary::DeleteProperty(int entry) { |
+Object* Dictionary::DeleteProperty(int entry, JSObject::DeleteMode mode) { |
PropertyDetails details = DetailsAt(entry); |
- if (details.IsDontDelete()) return Heap::false_value(); |
+ // Ignore attributes if forcing a deletion. |
+ if (details.IsDontDelete() && mode == JSObject::NORMAL_DELETION) { |
+ return Heap::false_value(); |
+ } |
SetEntry(entry, Heap::null_value(), Heap::null_value(), Smi::FromInt(0)); |
ElementRemoved(); |
return Heap::true_value(); |