Index: src/objects.cc |
diff --git a/src/objects.cc b/src/objects.cc |
index f20a56690cf184d0ef9edd725128a7ed22ea0429..c87e962bcfffbc2dc6c811903a418faec3ffa51c 100644 |
--- a/src/objects.cc |
+++ b/src/objects.cc |
@@ -654,8 +654,8 @@ Maybe<bool> JSReceiver::HasProperty(LookupIterator* it) { |
UNREACHABLE(); |
case LookupIterator::JSPROXY: |
// Call the "has" trap on proxies. |
- return JSProxy::HasPropertyWithHandler(it->GetHolder<JSProxy>(), |
- it->GetName()); |
+ return JSProxy::HasProperty(it->isolate(), it->GetHolder<JSProxy>(), |
+ it->GetName()); |
case LookupIterator::INTERCEPTOR: { |
Maybe<PropertyAttributes> result = |
JSObject::GetPropertyAttributesWithInterceptor(it); |
@@ -4523,21 +4523,69 @@ Handle<Map> JSObject::GetElementsTransitionMap(Handle<JSObject> object, |
} |
-Maybe<bool> JSProxy::HasPropertyWithHandler(Handle<JSProxy> proxy, |
- Handle<Name> name) { |
- Isolate* isolate = proxy->GetIsolate(); |
- |
- // TODO(rossberg): adjust once there is a story for symbols vs proxies. |
- if (name->IsSymbol()) return Just(false); |
- |
- Handle<Object> args[] = { name }; |
- Handle<Object> result; |
+Maybe<bool> JSProxy::HasProperty(Isolate* isolate, Handle<JSProxy> proxy, |
+ Handle<Name> name) { |
+ // 1. (Assert) |
+ // 2. Let handler be the value of the [[ProxyHandler]] internal slot of O. |
+ Handle<Object> handler(proxy->handler(), isolate); |
+ // 3. If handler is null, throw a TypeError exception. |
+ if (JSProxy::IsRevoked(proxy)) { |
+ isolate->Throw(*isolate->factory()->NewTypeError( |
+ MessageTemplate::kProxyRevoked, isolate->factory()->has_string())); |
+ return Nothing<bool>(); |
+ } |
+ // 4. Assert: Type(handler) is Object. |
+ DCHECK(handler->IsJSReceiver()); |
+ DCHECK(proxy->target()->IsJSReceiver()); |
+ // 5. Let target be the value of the [[ProxyTarget]] internal slot of O. |
+ Handle<JSReceiver> target(JSReceiver::cast(proxy->target()), isolate); |
+ // 6. Let trap be ? GetMethod(handler, "has"). |
+ Handle<Object> trap; |
ASSIGN_RETURN_ON_EXCEPTION_VALUE( |
- isolate, result, CallTrap(proxy, "has", isolate->derived_has_trap(), |
- arraysize(args), args), |
+ isolate, trap, Object::GetMethod(Handle<JSReceiver>::cast(handler), |
+ isolate->factory()->has_string()), |
Nothing<bool>()); |
- |
- return Just(result->BooleanValue()); |
+ // 7. If trap is undefined, then |
+ if (trap->IsUndefined()) { |
+ // 7a. Return target.[[HasProperty]](P). |
+ return JSReceiver::HasProperty(target, name); |
+ } |
+ // 8. Let booleanTrapResult be ToBoolean(? Call(trap, handler, «target, P»)). |
+ Handle<Object> trap_result_obj; |
+ Handle<Object> args[] = {target, name}; |
+ ASSIGN_RETURN_ON_EXCEPTION_VALUE( |
+ isolate, trap_result_obj, |
+ Execution::Call(isolate, trap, handler, arraysize(args), args), |
+ Nothing<bool>()); |
+ bool boolean_trap_result = trap_result_obj->BooleanValue(); |
+ // 9. If booleanTrapResult is false, then: |
+ if (!boolean_trap_result) { |
+ // 9a. Let targetDesc be ? target.[[GetOwnProperty]](P). |
+ PropertyDescriptor target_desc; |
+ bool target_found = JSReceiver::GetOwnPropertyDescriptor( |
+ isolate, target, name, &target_desc); |
+ // 9b. If targetDesc is not undefined, then: |
+ if (target_found) { |
+ // 9b i. If targetDesc.[[Configurable]] is false, throw a TypeError |
+ // exception. |
+ if (!target_desc.configurable()) { |
+ isolate->Throw(*isolate->factory()->NewTypeError( |
+ MessageTemplate::kProxyTargetPropNotConfigurable, name)); |
+ return Nothing<bool>(); |
+ } |
+ // 9b ii. Let extensibleTarget be ? IsExtensible(target). |
+ Maybe<bool> maybe_extensible = JSReceiver::IsExtensible(target); |
+ if (maybe_extensible.IsNothing()) return maybe_extensible; |
+ bool extensible_target = maybe_extensible.FromJust(); |
+ // 9b iii. If extensibleTarget is false, throw a TypeError exception. |
+ if (!extensible_target) { |
+ isolate->Throw(*isolate->factory()->NewTypeError( |
+ MessageTemplate::kProxyTargetNotExtensible)); |
+ } |
+ } |
+ } |
+ // 10. Return booleanTrapResult. |
+ return Just(boolean_trap_result); |
} |