Remove ForceDelete

This method circumvented JS semantics, and should not be used.

BUG=

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

Cr-Commit-Position: refs/heads/master@{#26157}
This commit is contained in:
verwaest 2015-01-20 05:41:17 -08:00 committed by Commit bot
parent 3eb589976a
commit e99faf93ff
10 changed files with 107 additions and 377 deletions

View File

@ -2432,10 +2432,6 @@ class V8_EXPORT Object : public Value {
bool Delete(Handle<Value> key);
// Delete a property on this object bypassing interceptors and
// ignoring dont-delete attributes.
bool ForceDelete(Handle<Value> key);
bool Has(uint32_t index);
bool Delete(uint32_t index);

View File

@ -3011,7 +3011,7 @@ bool v8::Object::SetPrivate(v8::Handle<Private> key, v8::Handle<Value> value) {
i::MaybeHandle<i::Object> DeleteObjectProperty(
i::Isolate* isolate, i::Handle<i::JSReceiver> receiver,
i::Handle<i::Object> key, i::JSReceiver::DeleteMode mode) {
i::Handle<i::Object> key, i::StrictMode strict_mode) {
// Check if the given key is an array index.
uint32_t index;
if (key->ToArrayIndex(&index)) {
@ -3025,7 +3025,7 @@ i::MaybeHandle<i::Object> DeleteObjectProperty(
return isolate->factory()->true_value();
}
return i::JSReceiver::DeleteElement(receiver, index, mode);
return i::JSReceiver::DeleteElement(receiver, index, strict_mode);
}
i::Handle<i::Name> name;
@ -3043,25 +3043,7 @@ i::MaybeHandle<i::Object> DeleteObjectProperty(
if (name->IsString()) {
name = i::String::Flatten(i::Handle<i::String>::cast(name));
}
return i::JSReceiver::DeleteProperty(receiver, name, mode);
}
bool v8::Object::ForceDelete(v8::Handle<Value> key) {
i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
ON_BAILOUT(isolate, "v8::Object::ForceDelete()", return false);
ENTER_V8(isolate);
i::HandleScope scope(isolate);
i::Handle<i::JSObject> self = Utils::OpenHandle(this);
i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
EXCEPTION_PREAMBLE(isolate);
i::Handle<i::Object> obj;
has_pending_exception =
!DeleteObjectProperty(isolate, self, key_obj,
i::JSReceiver::FORCE_DELETION).ToHandle(&obj);
EXCEPTION_BAILOUT_CHECK(isolate, false);
return obj->IsTrue();
return i::JSReceiver::DeleteProperty(receiver, name, strict_mode);
}
@ -3365,8 +3347,7 @@ bool v8::Object::Delete(v8::Handle<Value> key) {
EXCEPTION_PREAMBLE(isolate);
i::Handle<i::Object> obj;
has_pending_exception =
!DeleteObjectProperty(isolate, self, key_obj,
i::JSReceiver::NORMAL_DELETION).ToHandle(&obj);
!DeleteObjectProperty(isolate, self, key_obj, i::SLOPPY).ToHandle(&obj);
EXCEPTION_BAILOUT_CHECK(isolate, false);
return obj->IsTrue();
}

View File

@ -691,9 +691,7 @@ class ElementsAccessorBase : public ElementsAccessor {
}
MUST_USE_RESULT virtual MaybeHandle<Object> Delete(
Handle<JSObject> obj,
uint32_t key,
JSReceiver::DeleteMode mode) OVERRIDE = 0;
Handle<JSObject> obj, uint32_t key, StrictMode strict_mode) OVERRIDE = 0;
static void CopyElementsImpl(FixedArrayBase* from, uint32_t from_start,
FixedArrayBase* to, ElementsKind from_kind,
@ -915,9 +913,8 @@ class FastElementsAccessor
return length_object;
}
static Handle<Object> DeleteCommon(Handle<JSObject> obj,
uint32_t key,
JSReceiver::DeleteMode mode) {
static Handle<Object> DeleteCommon(Handle<JSObject> obj, uint32_t key,
StrictMode strict_mode) {
DCHECK(obj->HasFastSmiOrObjectElements() ||
obj->HasFastDoubleElements() ||
obj->HasFastArgumentsElements());
@ -975,8 +972,8 @@ class FastElementsAccessor
}
virtual MaybeHandle<Object> Delete(Handle<JSObject> obj, uint32_t key,
JSReceiver::DeleteMode mode) FINAL {
return DeleteCommon(obj, key, mode);
StrictMode strict_mode) FINAL {
return DeleteCommon(obj, key, strict_mode);
}
static bool HasElementImpl(
@ -1298,7 +1295,7 @@ class TypedElementsAccessor
}
MUST_USE_RESULT virtual MaybeHandle<Object> Delete(
Handle<JSObject> obj, uint32_t key, JSReceiver::DeleteMode mode) FINAL {
Handle<JSObject> obj, uint32_t key, StrictMode strict_mode) FINAL {
// External arrays always ignore deletes.
return obj->GetIsolate()->factory()->true_value();
}
@ -1397,9 +1394,7 @@ class DictionaryElementsAccessor
}
MUST_USE_RESULT static MaybeHandle<Object> DeleteCommon(
Handle<JSObject> obj,
uint32_t key,
JSReceiver::DeleteMode mode) {
Handle<JSObject> obj, uint32_t key, StrictMode strict_mode) {
Isolate* isolate = obj->GetIsolate();
Handle<FixedArray> backing_store(FixedArray::cast(obj->elements()),
isolate);
@ -1413,9 +1408,9 @@ class DictionaryElementsAccessor
int entry = dictionary->FindEntry(key);
if (entry != SeededNumberDictionary::kNotFound) {
Handle<Object> result =
SeededNumberDictionary::DeleteProperty(dictionary, entry, mode);
SeededNumberDictionary::DeleteProperty(dictionary, entry);
if (*result == *isolate->factory()->false_value()) {
if (mode == JSObject::STRICT_DELETION) {
if (strict_mode == STRICT) {
// Deleting a non-configurable property in strict mode.
Handle<Object> name = isolate->factory()->NewNumberFromUint(key);
Handle<Object> args[2] = { name, obj };
@ -1450,8 +1445,8 @@ class DictionaryElementsAccessor
ElementsKindTraits<DICTIONARY_ELEMENTS> >;
MUST_USE_RESULT virtual MaybeHandle<Object> Delete(
Handle<JSObject> obj, uint32_t key, JSReceiver::DeleteMode mode) FINAL {
return DeleteCommon(obj, key, mode);
Handle<JSObject> obj, uint32_t key, StrictMode strict_mode) FINAL {
return DeleteCommon(obj, key, strict_mode);
}
MUST_USE_RESULT static MaybeHandle<Object> GetImpl(
@ -1622,7 +1617,7 @@ class SloppyArgumentsElementsAccessor : public ElementsAccessorBase<
}
MUST_USE_RESULT virtual MaybeHandle<Object> Delete(
Handle<JSObject> obj, uint32_t key, JSReceiver::DeleteMode mode) FINAL {
Handle<JSObject> obj, uint32_t key, StrictMode strict_mode) FINAL {
Isolate* isolate = obj->GetIsolate();
Handle<FixedArray> parameter_map(FixedArray::cast(obj->elements()));
Handle<Object> probe = GetParameterMapArg(obj, parameter_map, key);
@ -1634,12 +1629,13 @@ class SloppyArgumentsElementsAccessor : public ElementsAccessorBase<
} else {
Handle<FixedArray> arguments(FixedArray::cast(parameter_map->get(1)));
if (arguments->IsDictionary()) {
return DictionaryElementsAccessor::DeleteCommon(obj, key, mode);
return DictionaryElementsAccessor::DeleteCommon(obj, key, strict_mode);
} else {
// It's difficult to access the version of DeleteCommon that is declared
// in the templatized super class, call the concrete implementation in
// the class for the most generalized ElementsKind subclass.
return FastHoleyObjectElementsAccessor::DeleteCommon(obj, key, mode);
return FastHoleyObjectElementsAccessor::DeleteCommon(obj, key,
strict_mode);
}
}
return isolate->factory()->true_value();

View File

@ -121,9 +121,7 @@ class ElementsAccessor {
// Deletes an element in an object, returning a new elements backing store.
MUST_USE_RESULT virtual MaybeHandle<Object> Delete(
Handle<JSObject> holder,
uint32_t key,
JSReceiver::DeleteMode mode) = 0;
Handle<JSObject> holder, uint32_t key, StrictMode strict_mode) = 0;
// If kCopyToEnd is specified as the copy_size to CopyElements, it copies all
// of elements from source after source_start to the destination array.

View File

@ -530,56 +530,6 @@ void JSObject::SetNormalizedProperty(Handle<JSObject> object,
}
Handle<Object> JSObject::DeleteNormalizedProperty(Handle<JSObject> object,
Handle<Name> name,
DeleteMode mode) {
DCHECK(!object->HasFastProperties());
Isolate* isolate = object->GetIsolate();
Handle<NameDictionary> dictionary(object->property_dictionary());
int entry = dictionary->FindEntry(name);
if (entry != NameDictionary::kNotFound) {
// If we have a global object set the cell to the hole.
if (object->IsGlobalObject()) {
PropertyDetails details = dictionary->DetailsAt(entry);
if (!details.IsConfigurable()) {
if (mode != FORCE_DELETION) return isolate->factory()->false_value();
// When forced to delete global properties, we have to make a
// map change to invalidate any ICs that think they can load
// from the non-configurable cell without checking if it contains
// the hole value.
Handle<Map> new_map = Map::CopyDropDescriptors(handle(object->map()));
DCHECK(new_map->is_dictionary_map());
#if TRACE_MAPS
if (FLAG_trace_maps) {
PrintF("[TraceMaps: GlobalDeleteNormalized from= %p to= %p ]\n",
reinterpret_cast<void*>(object->map()),
reinterpret_cast<void*>(*new_map));
}
#endif
JSObject::MigrateToMap(object, new_map);
// Optimized code does not check for the hole value for non-configurable
// properties.
Deoptimizer::DeoptimizeGlobalObject(*object);
}
Handle<PropertyCell> cell(PropertyCell::cast(dictionary->ValueAt(entry)));
Handle<Object> value = isolate->factory()->the_hole_value();
PropertyCell::SetValueInferType(cell, value);
dictionary->DetailsAtPut(entry, details.AsDeleted());
} else {
Handle<Object> deleted(
NameDictionary::DeleteProperty(dictionary, entry, mode));
if (*deleted == isolate->heap()->true_value()) {
Handle<NameDictionary> new_properties =
NameDictionary::Shrink(dictionary, name);
object->set_properties(*new_properties);
}
return deleted;
}
}
return isolate->factory()->true_value();
}
MaybeHandle<Object> Object::GetElementWithReceiver(Isolate* isolate,
Handle<Object> object,
Handle<Object> receiver,
@ -3551,8 +3501,9 @@ MaybeHandle<Object> JSProxy::SetPropertyViaPrototypesWithHandler(
}
MaybeHandle<Object> JSProxy::DeletePropertyWithHandler(
Handle<JSProxy> proxy, Handle<Name> name, DeleteMode mode) {
MaybeHandle<Object> JSProxy::DeletePropertyWithHandler(Handle<JSProxy> proxy,
Handle<Name> name,
StrictMode strict_mode) {
Isolate* isolate = proxy->GetIsolate();
// TODO(rossberg): adjust once there is a story for symbols vs proxies.
@ -3570,7 +3521,7 @@ MaybeHandle<Object> JSProxy::DeletePropertyWithHandler(
Object);
bool result_bool = result->BooleanValue();
if (mode == STRICT_DELETION && !result_bool) {
if (strict_mode == STRICT && !result_bool) {
Handle<Object> handler(proxy->handler(), isolate);
Handle<String> trap_name = isolate->factory()->InternalizeOneByteString(
STATIC_CHAR_VECTOR("delete"));
@ -3583,11 +3534,12 @@ MaybeHandle<Object> JSProxy::DeletePropertyWithHandler(
}
MaybeHandle<Object> JSProxy::DeleteElementWithHandler(
Handle<JSProxy> proxy, uint32_t index, DeleteMode mode) {
MaybeHandle<Object> JSProxy::DeleteElementWithHandler(Handle<JSProxy> proxy,
uint32_t index,
StrictMode strict_mode) {
Isolate* isolate = proxy->GetIsolate();
Handle<String> name = isolate->factory()->Uint32ToString(index);
return JSProxy::DeletePropertyWithHandler(proxy, name, mode);
return JSProxy::DeletePropertyWithHandler(proxy, name, strict_mode);
}
@ -4867,15 +4819,16 @@ MaybeHandle<Object> JSObject::DeleteElementWithInterceptor(
// Rebox CustomArguments::kReturnValueOffset before returning.
return handle(*result_internal, isolate);
}
MaybeHandle<Object> delete_result = object->GetElementsAccessor()->Delete(
object, index, NORMAL_DELETION);
// 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,
DeleteMode mode) {
StrictMode strict_mode) {
Isolate* isolate = object->GetIsolate();
Factory* factory = isolate->factory();
@ -4888,7 +4841,7 @@ MaybeHandle<Object> JSObject::DeleteElement(Handle<JSObject> object,
}
if (object->IsStringObjectWithCharacterAt(index)) {
if (mode == STRICT_DELETION) {
if (strict_mode == STRICT) {
// Deleting a non-configurable property in strict mode.
Handle<Object> name = factory->NewNumberFromUint(index);
Handle<Object> args[2] = { name, object };
@ -4905,7 +4858,7 @@ MaybeHandle<Object> JSObject::DeleteElement(Handle<JSObject> object,
DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject());
return DeleteElement(
Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)), index,
mode);
strict_mode);
}
Handle<Object> old_value;
@ -4926,10 +4879,11 @@ MaybeHandle<Object> JSObject::DeleteElement(Handle<JSObject> object,
// Skip interceptor if forcing deletion.
MaybeHandle<Object> maybe_result;
if (object->HasIndexedInterceptor() && mode != FORCE_DELETION) {
if (object->HasIndexedInterceptor()) {
maybe_result = DeleteElementWithInterceptor(object, index);
} else {
maybe_result = object->GetElementsAccessor()->Delete(object, index, mode);
maybe_result =
object->GetElementsAccessor()->Delete(object, index, strict_mode);
}
Handle<Object> result;
ASSIGN_RETURN_ON_EXCEPTION(isolate, result, maybe_result, Object);
@ -4949,23 +4903,44 @@ MaybeHandle<Object> JSObject::DeleteElement(Handle<JSObject> object,
}
void JSObject::DeleteNormalizedProperty(Handle<JSObject> object,
Handle<Name> name) {
DCHECK(!object->HasFastProperties());
Isolate* isolate = object->GetIsolate();
Handle<NameDictionary> dictionary(object->property_dictionary());
int entry = dictionary->FindEntry(name);
DCHECK_NE(NameDictionary::kNotFound, entry);
// If we have a global object set the cell to the hole.
if (object->IsGlobalObject()) {
PropertyDetails details = dictionary->DetailsAt(entry);
DCHECK(details.IsConfigurable());
Handle<PropertyCell> cell(PropertyCell::cast(dictionary->ValueAt(entry)));
Handle<Object> value = isolate->factory()->the_hole_value();
PropertyCell::SetValueInferType(cell, value);
dictionary->DetailsAtPut(entry, details.AsDeleted());
return;
}
NameDictionary::DeleteProperty(dictionary, entry);
Handle<NameDictionary> new_properties =
NameDictionary::Shrink(dictionary, name);
object->set_properties(*new_properties);
}
MaybeHandle<Object> JSObject::DeleteProperty(Handle<JSObject> object,
Handle<Name> name,
DeleteMode delete_mode) {
StrictMode strict_mode) {
// ECMA-262, 3rd, 8.6.2.5
DCHECK(name->IsName());
uint32_t index = 0;
if (name->AsArrayIndex(&index)) {
return DeleteElement(object, index, delete_mode);
return DeleteElement(object, index, strict_mode);
}
// Skip interceptors on FORCE_DELETION.
LookupIterator::Configuration config =
delete_mode == FORCE_DELETION ? LookupIterator::HIDDEN_SKIP_INTERCEPTOR
: LookupIterator::HIDDEN;
LookupIterator it(object, name, config);
LookupIterator it(object, name, LookupIterator::HIDDEN);
bool is_observed = object->map()->is_observed() &&
!it.isolate()->IsInternallyUsedPropertyName(name);
@ -4999,9 +4974,9 @@ MaybeHandle<Object> JSObject::DeleteProperty(Handle<JSObject> object,
}
// Fall through.
case LookupIterator::ACCESSOR: {
if (delete_mode != FORCE_DELETION && !it.IsConfigurable()) {
if (!it.IsConfigurable()) {
// Fail if the property is not configurable.
if (delete_mode == STRICT_DELETION) {
if (strict_mode == STRICT) {
Handle<Object> args[2] = {name, object};
THROW_NEW_ERROR(it.isolate(),
NewTypeError("strict_delete_property",
@ -5021,9 +4996,9 @@ MaybeHandle<Object> JSObject::DeleteProperty(Handle<JSObject> object,
!(object->IsJSGlobalProxy() && holder->IsJSGlobalObject())) {
return it.isolate()->factory()->true_value();
}
NormalizeProperties(holder, mode, 0, "DeletingProperty");
Handle<Object> result =
DeleteNormalizedProperty(holder, name, delete_mode);
DeleteNormalizedProperty(holder, name);
ReoptimizeIfPrototype(holder);
if (is_observed) {
@ -5032,7 +5007,7 @@ MaybeHandle<Object> JSObject::DeleteProperty(Handle<JSObject> object,
EnqueueChangeRecord(object, "delete", name, old_value), Object);
}
return result;
return it.isolate()->factory()->true_value();
}
}
}
@ -5043,23 +5018,25 @@ MaybeHandle<Object> JSObject::DeleteProperty(Handle<JSObject> object,
MaybeHandle<Object> JSReceiver::DeleteElement(Handle<JSReceiver> object,
uint32_t index,
DeleteMode mode) {
StrictMode strict_mode) {
if (object->IsJSProxy()) {
return JSProxy::DeleteElementWithHandler(
Handle<JSProxy>::cast(object), index, mode);
return JSProxy::DeleteElementWithHandler(Handle<JSProxy>::cast(object),
index, strict_mode);
}
return JSObject::DeleteElement(Handle<JSObject>::cast(object), index, mode);
return JSObject::DeleteElement(Handle<JSObject>::cast(object), index,
strict_mode);
}
MaybeHandle<Object> JSReceiver::DeleteProperty(Handle<JSReceiver> object,
Handle<Name> name,
DeleteMode mode) {
StrictMode strict_mode) {
if (object->IsJSProxy()) {
return JSProxy::DeletePropertyWithHandler(
Handle<JSProxy>::cast(object), name, mode);
return JSProxy::DeletePropertyWithHandler(Handle<JSProxy>::cast(object),
name, strict_mode);
}
return JSObject::DeleteProperty(Handle<JSObject>::cast(object), name, mode);
return JSObject::DeleteProperty(Handle<JSObject>::cast(object), name,
strict_mode);
}
@ -14473,11 +14450,11 @@ Dictionary<SeededNumberDictionary, SeededNumberDictionaryShape, uint32_t>::
template Handle<Object>
Dictionary<NameDictionary, NameDictionaryShape, Handle<Name> >::DeleteProperty(
Handle<NameDictionary>, int, JSObject::DeleteMode);
Handle<NameDictionary>, int);
template Handle<Object>
Dictionary<SeededNumberDictionary, SeededNumberDictionaryShape, uint32_t>::
DeleteProperty(Handle<SeededNumberDictionary>, int, JSObject::DeleteMode);
Dictionary<SeededNumberDictionary, SeededNumberDictionaryShape,
uint32_t>::DeleteProperty(Handle<SeededNumberDictionary>, int);
template Handle<NameDictionary>
HashTable<NameDictionary, NameDictionaryShape, Handle<Name> >::
@ -15455,17 +15432,12 @@ Handle<Derived> Dictionary<Derived, Shape, Key>::EnsureCapacity(
}
template<typename Derived, typename Shape, typename Key>
template <typename Derived, typename Shape, typename Key>
Handle<Object> Dictionary<Derived, Shape, Key>::DeleteProperty(
Handle<Derived> dictionary,
int entry,
JSObject::DeleteMode mode) {
Handle<Derived> dictionary, int entry) {
Factory* factory = dictionary->GetIsolate()->factory();
PropertyDetails details = dictionary->DetailsAt(entry);
// Ignore attributes if forcing a deletion.
if (!details.IsConfigurable() && mode != JSReceiver::FORCE_DELETION) {
return factory->false_value();
}
if (!details.IsConfigurable()) return factory->false_value();
dictionary->SetEntry(
entry, factory->the_hole_value(), factory->the_hole_value());

View File

@ -1589,12 +1589,6 @@ enum AccessorComponent {
// JSObject and JSProxy.
class JSReceiver: public HeapObject {
public:
enum DeleteMode {
NORMAL_DELETION,
STRICT_DELETION,
FORCE_DELETION
};
DECLARE_CAST(JSReceiver)
MUST_USE_RESULT static MaybeHandle<Object> SetElement(
@ -1616,13 +1610,11 @@ class JSReceiver: public HeapObject {
// Implementation of [[Delete]], ECMA-262 5th edition, section 8.12.7.
MUST_USE_RESULT static MaybeHandle<Object> DeleteProperty(
Handle<JSReceiver> object,
Handle<Name> name,
DeleteMode mode = NORMAL_DELETION);
Handle<JSReceiver> object, Handle<Name> name,
StrictMode strict_mode = SLOPPY);
MUST_USE_RESULT static MaybeHandle<Object> DeleteElement(
Handle<JSReceiver> object,
uint32_t index,
DeleteMode mode = NORMAL_DELETION);
Handle<JSReceiver> object, uint32_t index,
StrictMode strict_mode = SLOPPY);
// Tests for the fast common case for property enumeration.
bool IsSimpleEnum();
@ -2341,21 +2333,16 @@ class JSObject: public JSReceiver {
PropertyAttributes attributes);
MUST_USE_RESULT static MaybeHandle<Object> DeleteProperty(
Handle<JSObject> object,
Handle<Name> name,
DeleteMode mode);
Handle<JSObject> object, Handle<Name> name, StrictMode strict_mode);
MUST_USE_RESULT static MaybeHandle<Object> DeletePropertyWithInterceptor(
Handle<JSObject> holder, Handle<JSObject> receiver, Handle<Name> name);
// Deletes the named property in a normalized object.
static Handle<Object> DeleteNormalizedProperty(Handle<JSObject> object,
Handle<Name> name,
DeleteMode mode);
// Deletes an existing named property in a normalized object.
static void DeleteNormalizedProperty(Handle<JSObject> object,
Handle<Name> name);
MUST_USE_RESULT static MaybeHandle<Object> DeleteElement(
Handle<JSObject> object,
uint32_t index,
DeleteMode mode);
Handle<JSObject> object, uint32_t index, StrictMode strict_mode);
MUST_USE_RESULT static MaybeHandle<Object> DeleteElementWithInterceptor(
Handle<JSObject> object,
uint32_t index);
@ -3556,10 +3543,7 @@ class Dictionary: public HashTable<Derived, Shape, Key> {
void CopyValuesTo(FixedArray* elements);
// Delete a property from the dictionary.
static Handle<Object> DeleteProperty(
Handle<Derived> dictionary,
int entry,
JSObject::DeleteMode mode);
static Handle<Object> DeleteProperty(Handle<Derived> dictionary, int entry);
// Attempt to shrink the dictionary after deletion of key.
MUST_USE_RESULT static inline Handle<Derived> Shrink(
@ -9843,13 +9827,9 @@ class JSProxy: public JSReceiver {
Handle<JSProxy> proxy, uint32_t index);
MUST_USE_RESULT static MaybeHandle<Object> DeletePropertyWithHandler(
Handle<JSProxy> proxy,
Handle<Name> name,
DeleteMode mode);
Handle<JSProxy> proxy, Handle<Name> name, StrictMode strict_mode);
MUST_USE_RESULT static MaybeHandle<Object> DeleteElementWithHandler(
Handle<JSProxy> proxy,
uint32_t index,
DeleteMode mode);
Handle<JSProxy> proxy, uint32_t index, StrictMode strict_mode);
MUST_USE_RESULT Object* GetIdentityHash();

View File

@ -765,12 +765,9 @@ RUNTIME_FUNCTION(Runtime_DeleteProperty) {
CONVERT_ARG_HANDLE_CHECKED(JSReceiver, object, 0);
CONVERT_ARG_HANDLE_CHECKED(Name, key, 1);
CONVERT_STRICT_MODE_ARG_CHECKED(strict_mode, 2);
JSReceiver::DeleteMode delete_mode = strict_mode == STRICT
? JSReceiver::STRICT_DELETION
: JSReceiver::NORMAL_DELETION;
Handle<Object> result;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
isolate, result, JSReceiver::DeleteProperty(object, key, delete_mode));
isolate, result, JSReceiver::DeleteProperty(object, key, strict_mode));
return *result;
}

View File

@ -16221,139 +16221,6 @@ TEST(ForceSetWithInterceptor) {
}
THREADED_TEST(ForceDelete) {
v8::Isolate* isolate = CcTest::isolate();
v8::HandleScope scope(isolate);
v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
LocalContext context(NULL, templ);
v8::Handle<v8::Object> global = context->Global();
// Ordinary properties
v8::Handle<v8::String> simple_property =
v8::String::NewFromUtf8(isolate, "p");
global->ForceSet(simple_property, v8::Int32::New(isolate, 4), v8::DontDelete);
CHECK_EQ(4, global->Get(simple_property)->Int32Value());
// This should fail because the property is dont-delete.
CHECK(!global->Delete(simple_property));
CHECK_EQ(4, global->Get(simple_property)->Int32Value());
// This should succeed even though the property is dont-delete.
CHECK(global->ForceDelete(simple_property));
CHECK(global->Get(simple_property)->IsUndefined());
}
static int force_delete_interceptor_count = 0;
static bool pass_on_delete = false;
static void ForceDeleteDeleter(
v8::Local<v8::Name> name,
const v8::PropertyCallbackInfo<v8::Boolean>& info) {
force_delete_interceptor_count++;
if (pass_on_delete) return;
info.GetReturnValue().Set(true);
}
THREADED_TEST(ForceDeleteWithInterceptor) {
force_delete_interceptor_count = 0;
pass_on_delete = false;
v8::Isolate* isolate = CcTest::isolate();
v8::HandleScope scope(isolate);
v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
templ->SetHandler(
v8::NamedPropertyHandlerConfiguration(0, 0, 0, ForceDeleteDeleter));
LocalContext context(NULL, templ);
v8::Handle<v8::Object> global = context->Global();
v8::Handle<v8::String> some_property =
v8::String::NewFromUtf8(isolate, "a");
global->ForceSet(some_property, v8::Integer::New(isolate, 42),
v8::DontDelete);
// Deleting a property should get intercepted and nothing should
// happen.
CHECK_EQ(0, force_delete_interceptor_count);
CHECK(global->Delete(some_property));
CHECK_EQ(1, force_delete_interceptor_count);
CHECK_EQ(42, global->Get(some_property)->Int32Value());
// Deleting the property when the interceptor returns an empty
// handle should not delete the property since it is DontDelete.
pass_on_delete = true;
CHECK(!global->Delete(some_property));
CHECK_EQ(2, force_delete_interceptor_count);
CHECK_EQ(42, global->Get(some_property)->Int32Value());
// Forcing the property to be deleted should delete the value
// without calling the interceptor.
CHECK(global->ForceDelete(some_property));
CHECK(global->Get(some_property)->IsUndefined());
CHECK_EQ(2, force_delete_interceptor_count);
}
// Make sure that forcing a delete invalidates any IC stubs, so we
// don't read the hole value.
THREADED_TEST(ForceDeleteIC) {
LocalContext context;
v8::HandleScope scope(context->GetIsolate());
// Create a DontDelete variable on the global object.
CompileRun("this.__proto__ = { foo: 'horse' };"
"var foo = 'fish';"
"function f() { return foo.length; }");
// Initialize the IC for foo in f.
CompileRun("for (var i = 0; i < 4; i++) f();");
// Make sure the value of foo is correct before the deletion.
CHECK_EQ(4, CompileRun("f()")->Int32Value());
// Force the deletion of foo.
CHECK(context->Global()->ForceDelete(v8_str("foo")));
// Make sure the value for foo is read from the prototype, and that
// we don't get in trouble with reading the deleted cell value
// sentinel.
CHECK_EQ(5, CompileRun("f()")->Int32Value());
}
TEST(InlinedFunctionAcrossContexts) {
i::FLAG_allow_natives_syntax = true;
v8::Isolate* isolate = CcTest::isolate();
v8::HandleScope outer_scope(isolate);
v8::Local<v8::Context> ctx1 = v8::Context::New(isolate);
v8::Local<v8::Context> ctx2 = v8::Context::New(isolate);
ctx1->Enter();
{
v8::HandleScope inner_scope(CcTest::isolate());
CompileRun("var G = 42; function foo() { return G; }");
v8::Local<v8::Value> foo = ctx1->Global()->Get(v8_str("foo"));
ctx2->Enter();
ctx2->Global()->Set(v8_str("o"), foo);
v8::Local<v8::Value> res = CompileRun(
"function f() { return o(); }"
"for (var i = 0; i < 10; ++i) f();"
"%OptimizeFunctionOnNextCall(f);"
"f();");
CHECK_EQ(42, res->Int32Value());
ctx2->Exit();
v8::Handle<v8::String> G_property =
v8::String::NewFromUtf8(CcTest::isolate(), "G");
CHECK(ctx1->Global()->ForceDelete(G_property));
ctx2->Enter();
ExpectString(
"(function() {"
" try {"
" return f();"
" } catch(e) {"
" return e.toString();"
" }"
" })()",
"ReferenceError: G is not defined");
ctx2->Exit();
ctx1->Exit();
}
}
static v8::Local<Context> calling_context0;
static v8::Local<Context> calling_context1;
static v8::Local<Context> calling_context2;
@ -20821,62 +20688,6 @@ TEST(DontDeleteCellLoadIC) {
}
TEST(DontDeleteCellLoadICForceDelete) {
const char* function_code =
"function readCell() { while (true) { return cell; } }";
// Run the code twice to initialize the load IC for a don't delete
// cell.
LocalContext context;
v8::HandleScope scope(context->GetIsolate());
CompileRun("var cell = \"value\";");
ExpectBoolean("delete cell", false);
CompileRun(function_code);
ExpectString("readCell()", "value");
ExpectString("readCell()", "value");
// Delete the cell using the API and check the inlined code works
// correctly.
CHECK(context->Global()->ForceDelete(v8_str("cell")));
ExpectString("(function() {"
" try {"
" return readCell();"
" } catch(e) {"
" return e.toString();"
" }"
"})()",
"ReferenceError: cell is not defined");
}
TEST(DontDeleteCellLoadICAPI) {
const char* function_code =
"function readCell() { while (true) { return cell; } }";
// Run the code twice to initialize the load IC for a don't delete
// cell created using the API.
LocalContext context;
v8::HandleScope scope(context->GetIsolate());
context->Global()->ForceSet(v8_str("cell"), v8_str("value"), v8::DontDelete);
ExpectBoolean("delete cell", false);
CompileRun(function_code);
ExpectString("readCell()", "value");
ExpectString("readCell()", "value");
// Delete the cell using the API and check the inlined code works
// correctly.
CHECK(context->Global()->ForceDelete(v8_str("cell")));
ExpectString("(function() {"
" try {"
" return readCell();"
" } catch(e) {"
" return e.toString();"
" }"
"})()",
"ReferenceError: cell is not defined");
}
class Visitor42 : public v8::PersistentHandleVisitor {
public:
explicit Visitor42(v8::Persistent<v8::Object>* object)

View File

@ -650,7 +650,7 @@ TEST(ObjectProperties) {
CHECK(maybe.value);
// delete first
JSReceiver::DeleteProperty(obj, first, JSReceiver::NORMAL_DELETION).Check();
JSReceiver::DeleteProperty(obj, first, SLOPPY).Check();
maybe = JSReceiver::HasOwnProperty(obj, first);
CHECK(maybe.has_value);
CHECK(!maybe.value);
@ -666,11 +666,11 @@ TEST(ObjectProperties) {
CHECK(maybe.value);
// delete first and then second
JSReceiver::DeleteProperty(obj, first, JSReceiver::NORMAL_DELETION).Check();
JSReceiver::DeleteProperty(obj, first, SLOPPY).Check();
maybe = JSReceiver::HasOwnProperty(obj, second);
CHECK(maybe.has_value);
CHECK(maybe.value);
JSReceiver::DeleteProperty(obj, second, JSReceiver::NORMAL_DELETION).Check();
JSReceiver::DeleteProperty(obj, second, SLOPPY).Check();
maybe = JSReceiver::HasOwnProperty(obj, first);
CHECK(maybe.has_value);
CHECK(!maybe.value);
@ -689,11 +689,11 @@ TEST(ObjectProperties) {
CHECK(maybe.value);
// delete second and then first
JSReceiver::DeleteProperty(obj, second, JSReceiver::NORMAL_DELETION).Check();
JSReceiver::DeleteProperty(obj, second, SLOPPY).Check();
maybe = JSReceiver::HasOwnProperty(obj, first);
CHECK(maybe.has_value);
CHECK(maybe.value);
JSReceiver::DeleteProperty(obj, first, JSReceiver::NORMAL_DELETION).Check();
JSReceiver::DeleteProperty(obj, first, SLOPPY).Check();
maybe = JSReceiver::HasOwnProperty(obj, first);
CHECK(maybe.has_value);
CHECK(!maybe.value);

View File

@ -328,11 +328,10 @@ TEST(APITestBasicMutation) {
// Setting an indexed element via the property setting method
obj->Set(Number::New(v8_isolate, 1), Number::New(v8_isolate, 5));
// Setting with a non-String, non-uint32 key
obj->ForceSet(Number::New(v8_isolate, 1.1), Number::New(v8_isolate, 6),
DontDelete);
obj->Set(Number::New(v8_isolate, 1.1), Number::New(v8_isolate, 6));
obj->Delete(String::NewFromUtf8(v8_isolate, "foo"));
obj->Delete(1);
obj->ForceDelete(Number::New(v8_isolate, 1.1));
obj->Delete(Number::New(v8_isolate, 1.1));
// Force delivery
// TODO(adamk): Should the above set methods trigger delivery themselves?