Handle Delete of element with LookupIterator
BUG=v8:4137 LOG=n Review URL: https://codereview.chromium.org/1157093003 Cr-Commit-Position: refs/heads/master@{#28762}
This commit is contained in:
parent
d71009a564
commit
bda7fb2246
@ -669,9 +669,8 @@ class ElementsAccessorBase : public ElementsAccessor {
|
||||
UNIMPLEMENTED();
|
||||
}
|
||||
|
||||
MUST_USE_RESULT virtual MaybeHandle<Object> Delete(
|
||||
Handle<JSObject> obj, uint32_t key,
|
||||
LanguageMode language_mode) override = 0;
|
||||
virtual void Delete(Handle<JSObject> obj, uint32_t key,
|
||||
LanguageMode language_mode) override = 0;
|
||||
|
||||
static void CopyElementsImpl(FixedArrayBase* from, uint32_t from_start,
|
||||
FixedArrayBase* to, ElementsKind from_kind,
|
||||
@ -919,17 +918,16 @@ class FastElementsAccessor
|
||||
return length_object;
|
||||
}
|
||||
|
||||
static MaybeHandle<Object> DeleteCommon(Handle<JSObject> obj, uint32_t key,
|
||||
LanguageMode language_mode) {
|
||||
static void DeleteCommon(Handle<JSObject> obj, uint32_t key,
|
||||
LanguageMode language_mode) {
|
||||
DCHECK(obj->HasFastSmiOrObjectElements() ||
|
||||
obj->HasFastDoubleElements() ||
|
||||
obj->HasFastArgumentsElements());
|
||||
Isolate* isolate = obj->GetIsolate();
|
||||
Heap* heap = obj->GetHeap();
|
||||
Handle<FixedArrayBase> elements(obj->elements());
|
||||
if (*elements == heap->empty_fixed_array()) {
|
||||
return isolate->factory()->true_value();
|
||||
}
|
||||
if (*elements == heap->empty_fixed_array()) return;
|
||||
|
||||
Handle<BackingStore> backing_store = Handle<BackingStore>::cast(elements);
|
||||
bool is_sloppy_arguments_elements_map =
|
||||
backing_store->map() == heap->sloppy_arguments_elements_map();
|
||||
@ -943,16 +941,6 @@ class FastElementsAccessor
|
||||
? Smi::cast(Handle<JSArray>::cast(obj)->length())->value()
|
||||
: backing_store->length());
|
||||
if (key < length) {
|
||||
if (obj->map()->is_strong() && !backing_store->is_the_hole(key)) {
|
||||
if (is_strict(language_mode)) {
|
||||
Handle<Object> name = isolate->factory()->NewNumberFromUint(key);
|
||||
THROW_NEW_ERROR(
|
||||
isolate,
|
||||
NewTypeError(MessageTemplate::kStrongDeleteProperty, obj, name),
|
||||
Object);
|
||||
}
|
||||
return isolate->factory()->false_value();
|
||||
}
|
||||
if (!is_sloppy_arguments_elements_map) {
|
||||
ElementsKind kind = KindTraits::Kind;
|
||||
if (IsFastPackedElementsKind(kind)) {
|
||||
@ -984,12 +972,11 @@ class FastElementsAccessor
|
||||
}
|
||||
}
|
||||
}
|
||||
return isolate->factory()->true_value();
|
||||
}
|
||||
|
||||
virtual MaybeHandle<Object> Delete(Handle<JSObject> obj, uint32_t key,
|
||||
LanguageMode language_mode) final {
|
||||
return DeleteCommon(obj, key, language_mode);
|
||||
virtual void Delete(Handle<JSObject> obj, uint32_t key,
|
||||
LanguageMode language_mode) final {
|
||||
DeleteCommon(obj, key, language_mode);
|
||||
}
|
||||
|
||||
static bool HasElementImpl(
|
||||
@ -1306,10 +1293,9 @@ class TypedElementsAccessor
|
||||
return obj;
|
||||
}
|
||||
|
||||
MUST_USE_RESULT virtual MaybeHandle<Object> Delete(
|
||||
Handle<JSObject> obj, uint32_t key, LanguageMode language_mode) final {
|
||||
virtual void Delete(Handle<JSObject> obj, uint32_t key,
|
||||
LanguageMode language_mode) final {
|
||||
// External arrays always ignore deletes.
|
||||
return obj->GetIsolate()->factory()->true_value();
|
||||
}
|
||||
|
||||
static bool HasElementImpl(Handle<JSObject> holder, uint32_t key,
|
||||
@ -1409,8 +1395,8 @@ class DictionaryElementsAccessor
|
||||
return length_object;
|
||||
}
|
||||
|
||||
MUST_USE_RESULT static MaybeHandle<Object> DeleteCommon(
|
||||
Handle<JSObject> obj, uint32_t key, LanguageMode language_mode) {
|
||||
static void DeleteCommon(Handle<JSObject> obj, uint32_t key,
|
||||
LanguageMode language_mode) {
|
||||
Isolate* isolate = obj->GetIsolate();
|
||||
Handle<FixedArray> backing_store(FixedArray::cast(obj->elements()),
|
||||
isolate);
|
||||
@ -1423,28 +1409,10 @@ class DictionaryElementsAccessor
|
||||
Handle<SeededNumberDictionary>::cast(backing_store);
|
||||
int entry = dictionary->FindEntry(key);
|
||||
if (entry != SeededNumberDictionary::kNotFound) {
|
||||
Handle<Object> result;
|
||||
bool strong = obj->map()->is_strong();
|
||||
if (!strong) {
|
||||
result = SeededNumberDictionary::DeleteProperty(dictionary, entry);
|
||||
}
|
||||
if (strong || *result == *isolate->factory()->false_value()) {
|
||||
// Fail if the property is not configurable, or on a strong object.
|
||||
if (is_strict(language_mode)) {
|
||||
Handle<Object> name = isolate->factory()->NewNumberFromUint(key);
|
||||
if (strong) {
|
||||
THROW_NEW_ERROR(
|
||||
isolate,
|
||||
NewTypeError(MessageTemplate::kStrongDeleteProperty, obj, name),
|
||||
Object);
|
||||
}
|
||||
THROW_NEW_ERROR(
|
||||
isolate,
|
||||
NewTypeError(MessageTemplate::kStrictDeleteProperty, name, obj),
|
||||
Object);
|
||||
}
|
||||
return isolate->factory()->false_value();
|
||||
}
|
||||
Handle<Object> result =
|
||||
SeededNumberDictionary::DeleteProperty(dictionary, entry);
|
||||
USE(result);
|
||||
DCHECK(result->IsTrue());
|
||||
Handle<FixedArray> new_elements =
|
||||
SeededNumberDictionary::Shrink(dictionary, key);
|
||||
|
||||
@ -1454,7 +1422,6 @@ class DictionaryElementsAccessor
|
||||
obj->set_elements(*new_elements);
|
||||
}
|
||||
}
|
||||
return isolate->factory()->true_value();
|
||||
}
|
||||
|
||||
static void CopyElementsImpl(FixedArrayBase* from, uint32_t from_start,
|
||||
@ -1469,9 +1436,9 @@ class DictionaryElementsAccessor
|
||||
friend class ElementsAccessorBase<DictionaryElementsAccessor,
|
||||
ElementsKindTraits<DICTIONARY_ELEMENTS> >;
|
||||
|
||||
MUST_USE_RESULT virtual MaybeHandle<Object> Delete(
|
||||
Handle<JSObject> obj, uint32_t key, LanguageMode language_mode) final {
|
||||
return DeleteCommon(obj, key, language_mode);
|
||||
virtual void Delete(Handle<JSObject> obj, uint32_t key,
|
||||
LanguageMode language_mode) final {
|
||||
DeleteCommon(obj, key, language_mode);
|
||||
}
|
||||
|
||||
static Handle<Object> GetImpl(Handle<JSObject> obj, uint32_t key,
|
||||
@ -1631,8 +1598,8 @@ class SloppyArgumentsElementsAccessor : public ElementsAccessorBase<
|
||||
return obj;
|
||||
}
|
||||
|
||||
MUST_USE_RESULT virtual MaybeHandle<Object> Delete(
|
||||
Handle<JSObject> obj, uint32_t key, LanguageMode language_mode) final {
|
||||
virtual void Delete(Handle<JSObject> obj, uint32_t key,
|
||||
LanguageMode language_mode) final {
|
||||
Isolate* isolate = obj->GetIsolate();
|
||||
Handle<FixedArray> parameter_map(FixedArray::cast(obj->elements()));
|
||||
Handle<Object> probe(GetParameterMapArg(*parameter_map, key), isolate);
|
||||
@ -1644,17 +1611,14 @@ class SloppyArgumentsElementsAccessor : public ElementsAccessorBase<
|
||||
} else {
|
||||
Handle<FixedArray> arguments(FixedArray::cast(parameter_map->get(1)));
|
||||
if (arguments->IsDictionary()) {
|
||||
return DictionaryElementsAccessor::DeleteCommon(obj, key,
|
||||
language_mode);
|
||||
DictionaryElementsAccessor::DeleteCommon(obj, key, language_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,
|
||||
language_mode);
|
||||
FastHoleyObjectElementsAccessor::DeleteCommon(obj, key, language_mode);
|
||||
}
|
||||
}
|
||||
return isolate->factory()->true_value();
|
||||
}
|
||||
|
||||
static void CopyElementsImpl(FixedArrayBase* from, uint32_t from_start,
|
||||
|
@ -102,9 +102,9 @@ class ElementsAccessor {
|
||||
int capacity,
|
||||
int length) = 0;
|
||||
|
||||
// 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, LanguageMode language_mode) = 0;
|
||||
// Deletes an element in an object.
|
||||
virtual void Delete(Handle<JSObject> holder, uint32_t key,
|
||||
LanguageMode language_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.
|
||||
|
12
src/lookup.h
12
src/lookup.h
@ -59,6 +59,12 @@ class LookupIterator final BASE_EMBEDDED {
|
||||
holder_map_(holder_->map(), isolate_),
|
||||
initial_holder_(holder_),
|
||||
number_(DescriptorArray::kNotFound) {
|
||||
#if 0 // TODO(verwaest): Enable once blocking hacks are removed.
|
||||
#ifdef DEBUG
|
||||
uint32_t index; // Assert that the name is not an array index.
|
||||
DCHECK(!name->AsArrayIndex(&index));
|
||||
#endif // DEBUG
|
||||
#endif
|
||||
Next();
|
||||
}
|
||||
|
||||
@ -79,6 +85,12 @@ class LookupIterator final BASE_EMBEDDED {
|
||||
holder_map_(holder_->map(), isolate_),
|
||||
initial_holder_(holder_),
|
||||
number_(DescriptorArray::kNotFound) {
|
||||
#if 0 // TODO(verwaest): Enable once blocking hacks are removed.
|
||||
#ifdef DEBUG
|
||||
uint32_t index; // Assert that the name is not an array index.
|
||||
DCHECK(!name->AsArrayIndex(&index));
|
||||
#endif // DEBUG
|
||||
#endif
|
||||
Next();
|
||||
}
|
||||
|
||||
|
@ -1193,11 +1193,6 @@ MaybeHandle<Object> Object::GetProperty(Isolate* isolate,
|
||||
Handle<Object> object,
|
||||
const char* name) {
|
||||
Handle<String> str = isolate->factory()->InternalizeUtf8String(name);
|
||||
DCHECK(!str.is_null());
|
||||
#ifdef DEBUG
|
||||
uint32_t index; // Assert that the name is not an array index.
|
||||
DCHECK(!str->AsArrayIndex(&index));
|
||||
#endif // DEBUG
|
||||
return GetProperty(object, str);
|
||||
}
|
||||
|
||||
@ -1213,14 +1208,6 @@ MaybeHandle<Object> JSProxy::SetElementWithHandler(Handle<JSProxy> proxy,
|
||||
}
|
||||
|
||||
|
||||
Maybe<bool> JSProxy::HasElementWithHandler(Handle<JSProxy> proxy,
|
||||
uint32_t index) {
|
||||
Isolate* isolate = proxy->GetIsolate();
|
||||
Handle<String> name = isolate->factory()->Uint32ToString(index);
|
||||
return HasPropertyWithHandler(proxy, name);
|
||||
}
|
||||
|
||||
|
||||
#define FIELD_ADDR(p, offset) \
|
||||
(reinterpret_cast<byte*>(p) + offset - kHeapObjectTag)
|
||||
|
||||
|
280
src/objects.cc
280
src/objects.cc
@ -3941,14 +3941,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();
|
||||
@ -5031,23 +5023,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>();
|
||||
|
||||
@ -5059,116 +5068,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());
|
||||
@ -5198,121 +5097,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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1658,6 +1658,8 @@ class JSReceiver: public HeapObject {
|
||||
MUST_USE_RESULT static MaybeHandle<Object> DeleteProperty(
|
||||
Handle<JSReceiver> object, Handle<Name> name,
|
||||
LanguageMode language_mode = SLOPPY);
|
||||
MUST_USE_RESULT static MaybeHandle<Object> DeleteProperty(
|
||||
LookupIterator* it, LanguageMode language_mode);
|
||||
MUST_USE_RESULT static MaybeHandle<Object> DeleteElement(
|
||||
Handle<JSReceiver> object, uint32_t index,
|
||||
LanguageMode language_mode = SLOPPY);
|
||||
@ -2325,21 +2327,13 @@ class JSObject: public JSReceiver {
|
||||
Handle<Object> value,
|
||||
PropertyAttributes attributes);
|
||||
|
||||
MUST_USE_RESULT static MaybeHandle<Object> DeleteProperty(
|
||||
Handle<JSObject> object, Handle<Name> name, LanguageMode language_mode);
|
||||
MUST_USE_RESULT static MaybeHandle<Object> DeletePropertyWithInterceptor(
|
||||
Handle<JSObject> holder, Handle<JSObject> receiver, Handle<Name> name);
|
||||
LookupIterator* it);
|
||||
|
||||
// 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, LanguageMode language_mode);
|
||||
MUST_USE_RESULT static MaybeHandle<Object> DeleteElementWithInterceptor(
|
||||
Handle<JSObject> object,
|
||||
uint32_t index);
|
||||
|
||||
bool ReferencesObjectFromElements(FixedArray* elements,
|
||||
ElementsKind kind,
|
||||
Object* object);
|
||||
@ -10032,13 +10026,9 @@ class JSProxy: public JSReceiver {
|
||||
|
||||
MUST_USE_RESULT static Maybe<bool> HasPropertyWithHandler(
|
||||
Handle<JSProxy> proxy, Handle<Name> name);
|
||||
MUST_USE_RESULT static inline Maybe<bool> HasElementWithHandler(
|
||||
Handle<JSProxy> proxy, uint32_t index);
|
||||
|
||||
MUST_USE_RESULT static MaybeHandle<Object> DeletePropertyWithHandler(
|
||||
Handle<JSProxy> proxy, Handle<Name> name, LanguageMode language_mode);
|
||||
MUST_USE_RESULT static MaybeHandle<Object> DeleteElementWithHandler(
|
||||
Handle<JSProxy> proxy, uint32_t index, LanguageMode language_mode);
|
||||
|
||||
MUST_USE_RESULT Object* GetIdentityHash();
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user