Index: src/objects.cc |
diff --git a/src/objects.cc b/src/objects.cc |
index dbabe93e752e28cb3890e1f03455adabe697b545..39048b0e4c61784d1888f40b03050f29c672d27a 100644 |
--- a/src/objects.cc |
+++ b/src/objects.cc |
@@ -4643,33 +4643,54 @@ Maybe<bool> JSProxy::SetPropertyViaPrototypesWithHandler( |
} |
-MaybeHandle<Object> JSProxy::DeletePropertyWithHandler( |
- Handle<JSProxy> proxy, Handle<Name> name, LanguageMode language_mode) { |
+Maybe<bool> JSProxy::DeletePropertyOrElement(Handle<JSProxy> proxy, |
+ Handle<Name> name, |
+ LanguageMode language_mode) { |
+ ShouldThrow should_throw = |
+ is_sloppy(language_mode) ? DONT_THROW : THROW_ON_ERROR; |
Isolate* isolate = proxy->GetIsolate(); |
+ Factory* factory = isolate->factory(); |
+ Handle<String> trap_name = factory->deleteProperty_string(); |
- // TODO(rossberg): adjust once there is a story for symbols vs proxies. |
- if (name->IsSymbol()) return isolate->factory()->false_value(); |
+ if (IsRevoked(proxy)) { |
+ isolate->Throw( |
+ *factory->NewTypeError(MessageTemplate::kProxyRevoked, trap_name)); |
+ return Nothing<bool>(); |
+ } |
- Handle<Object> args[] = { name }; |
- Handle<Object> result; |
- ASSIGN_RETURN_ON_EXCEPTION( |
- isolate, result, |
- CallTrap(proxy, |
- "delete", |
- Handle<Object>(), |
- arraysize(args), |
- args), |
- Object); |
- |
- bool result_bool = result->BooleanValue(); |
- if (is_strict(language_mode) && !result_bool) { |
- Handle<Object> handler(proxy->handler(), isolate); |
- THROW_NEW_ERROR( |
- isolate, |
- NewTypeError(MessageTemplate::kProxyHandlerDeleteFailed, handler), |
- Object); |
+ Handle<JSReceiver> target(JSReceiver::cast(proxy->target()), isolate); |
+ Handle<JSReceiver> handler(JSReceiver::cast(proxy->handler()), isolate); |
+ |
+ Handle<Object> trap; |
+ ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, trap, GetTrap(proxy, trap_name), |
+ Nothing<bool>()); |
+ if (trap->IsUndefined()) { |
+ return JSReceiver::DeletePropertyOrElement(target, name, language_mode); |
} |
- return isolate->factory()->ToBoolean(result_bool); |
+ |
+ Handle<Object> trap_result; |
+ Handle<Object> args[] = {target, name}; |
+ ASSIGN_RETURN_ON_EXCEPTION_VALUE( |
+ isolate, trap_result, |
+ Execution::Call(isolate, trap, handler, arraysize(args), args), |
+ Nothing<bool>()); |
+ if (!trap_result->BooleanValue()) { |
+ RETURN_FAILURE(isolate, should_throw, |
+ NewTypeError(MessageTemplate::kProxyHandlerReturned, handler, |
+ factory->false_string(), trap_name)); |
+ } |
+ |
+ // Enforce the invariant. |
+ PropertyDescriptor target_desc; |
+ bool owned = |
+ JSReceiver::GetOwnPropertyDescriptor(isolate, target, name, &target_desc); |
+ if (isolate->has_pending_exception()) return Nothing<bool>(); |
+ if (owned && !target_desc.configurable()) { |
+ isolate->Throw(*factory->NewTypeError( |
+ MessageTemplate::kProxyDeletePropertyViolatesInvariant, name)); |
+ return Nothing<bool>(); |
+ } |
+ return Just(true); |
} |
@@ -5762,8 +5783,7 @@ Handle<Object> JSObject::SetHiddenPropertiesHashTable(Handle<JSObject> object, |
} |
-MaybeHandle<Object> JSObject::DeletePropertyWithInterceptor( |
- LookupIterator* it) { |
+Maybe<bool> JSObject::DeletePropertyWithInterceptor(LookupIterator* it) { |
Isolate* isolate = it->isolate(); |
// Make sure that the top context does not change when doing callbacks or |
// interceptor calls. |
@@ -5771,7 +5791,7 @@ MaybeHandle<Object> JSObject::DeletePropertyWithInterceptor( |
DCHECK_EQ(LookupIterator::INTERCEPTOR, it->state()); |
Handle<InterceptorInfo> interceptor(it->GetInterceptor()); |
- if (interceptor->deleter()->IsUndefined()) return MaybeHandle<Object>(); |
+ if (interceptor->deleter()->IsUndefined()) return Nothing<bool>(); |
Handle<JSObject> holder = it->GetHolder<JSObject>(); |
@@ -5786,7 +5806,7 @@ MaybeHandle<Object> JSObject::DeletePropertyWithInterceptor( |
ApiIndexedPropertyAccess("interceptor-indexed-delete", *holder, index)); |
result = args.Call(deleter, index); |
} else if (it->name()->IsSymbol() && !interceptor->can_intercept_symbols()) { |
- return MaybeHandle<Object>(); |
+ return Nothing<bool>(); |
} else { |
Handle<Name> name = it->name(); |
v8::GenericNamedPropertyDeleterCallback deleter = |
@@ -5797,14 +5817,14 @@ MaybeHandle<Object> JSObject::DeletePropertyWithInterceptor( |
result = args.Call(deleter, v8::Utils::ToLocal(name)); |
} |
- RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object); |
- if (result.IsEmpty()) return MaybeHandle<Object>(); |
+ RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<bool>()); |
+ if (result.IsEmpty()) return Nothing<bool>(); |
DCHECK(result->IsBoolean()); |
Handle<Object> result_internal = v8::Utils::OpenHandle(*result); |
result_internal->VerifyApiCallResultType(); |
// Rebox CustomArguments::kReturnValueOffset before returning. |
- return handle(*result_internal, isolate); |
+ return Just(result_internal->BooleanValue()); |
} |
@@ -5835,13 +5855,13 @@ void JSObject::DeleteNormalizedProperty(Handle<JSObject> object, |
} |
-// ECMA-262, 3rd, 8.6.2.5 |
-MaybeHandle<Object> JSReceiver::DeleteProperty(LookupIterator* it, |
- LanguageMode language_mode) { |
+Maybe<bool> 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); |
+ return JSProxy::DeletePropertyOrElement(it->GetHolder<JSProxy>(), |
+ it->GetName(), language_mode); |
} |
Handle<JSObject> receiver = Handle<JSObject>::cast(it->GetReceiver()); |
@@ -5861,19 +5881,20 @@ MaybeHandle<Object> JSReceiver::DeleteProperty(LookupIterator* it, |
case LookupIterator::ACCESS_CHECK: |
if (it->HasAccess()) break; |
isolate->ReportFailedAccessCheck(it->GetHolder<JSObject>()); |
- RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object); |
- return it->factory()->false_value(); |
+ RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<bool>()); |
+ return Just(false); |
case LookupIterator::INTERCEPTOR: { |
- MaybeHandle<Object> maybe_result = |
- JSObject::DeletePropertyWithInterceptor(it); |
- // Delete with interceptor succeeded. Return result. |
- if (!maybe_result.is_null()) return maybe_result; |
+ Maybe<bool> result = JSObject::DeletePropertyWithInterceptor(it); |
// An exception was thrown in the interceptor. Propagate. |
- if (isolate->has_pending_exception()) return maybe_result; |
+ if (isolate->has_pending_exception()) return Nothing<bool>(); |
+ // Delete with interceptor succeeded. Return result. |
+ // TODO(neis): In strict mode, we should probably throw if the |
+ // interceptor returns false. |
+ if (result.IsJust()) return result; |
break; |
} |
case LookupIterator::INTEGER_INDEXED_EXOTIC: |
- return it->factory()->true_value(); |
+ return Just(true); |
case LookupIterator::DATA: |
if (is_observed) { |
old_value = it->GetDataValue(); |
@@ -5887,49 +5908,50 @@ MaybeHandle<Object> JSReceiver::DeleteProperty(LookupIterator* it, |
receiver->map()->is_strong() |
? MessageTemplate::kStrongDeleteProperty |
: MessageTemplate::kStrictDeleteProperty; |
- THROW_NEW_ERROR( |
- isolate, NewTypeError(templ, it->GetName(), receiver), Object); |
+ isolate->Throw(*isolate->factory()->NewTypeError( |
+ templ, it->GetName(), receiver)); |
+ return Nothing<bool>(); |
} |
- return it->factory()->false_value(); |
+ return Just(false); |
} |
it->Delete(); |
if (is_observed) { |
- RETURN_ON_EXCEPTION(isolate, |
- JSObject::EnqueueChangeRecord( |
- receiver, "delete", it->GetName(), old_value), |
- Object); |
+ RETURN_ON_EXCEPTION_VALUE( |
+ isolate, JSObject::EnqueueChangeRecord(receiver, "delete", |
+ it->GetName(), old_value), |
+ Nothing<bool>()); |
} |
- return it->factory()->true_value(); |
+ return Just(true); |
} |
} |
} |
- return it->factory()->true_value(); |
+ return Just(true); |
} |
-MaybeHandle<Object> JSReceiver::DeleteElement(Handle<JSReceiver> object, |
- uint32_t index, |
- LanguageMode language_mode) { |
+Maybe<bool> JSReceiver::DeleteElement(Handle<JSReceiver> object, uint32_t index, |
+ LanguageMode language_mode) { |
LookupIterator it(object->GetIsolate(), object, index, |
LookupIterator::HIDDEN); |
return DeleteProperty(&it, language_mode); |
} |
-MaybeHandle<Object> JSReceiver::DeleteProperty(Handle<JSReceiver> object, |
- Handle<Name> name, |
- LanguageMode language_mode) { |
+Maybe<bool> JSReceiver::DeleteProperty(Handle<JSReceiver> object, |
+ Handle<Name> name, |
+ LanguageMode language_mode) { |
LookupIterator it(object, name, LookupIterator::HIDDEN); |
return DeleteProperty(&it, language_mode); |
} |
-MaybeHandle<Object> JSReceiver::DeletePropertyOrElement( |
- Handle<JSReceiver> object, Handle<Name> name, LanguageMode language_mode) { |
+Maybe<bool> JSReceiver::DeletePropertyOrElement(Handle<JSReceiver> object, |
+ Handle<Name> name, |
+ LanguageMode language_mode) { |
LookupIterator it = LookupIterator::PropertyOrElement( |
name->GetIsolate(), object, name, LookupIterator::HIDDEN); |
return DeleteProperty(&it, language_mode); |