blob: f3a66f7bc5439861fa4486271eca398082511b7d [file] [log] [blame]
// Copyright 2015 the V8 project authors. All rights reserved.
// // Use of this source code is governed by a BSD-style license that can be
// // found in the LICENSE file.
// static
MaybeHandle<Object> JSProxy::GetProperty(Isolate* isolate,
Handle<JSProxy> proxy,
Handle<Name> name,
Handle<Object> receiver,
bool* was_found) {
*was_found = true;
if (receiver->IsJSGlobalObject()) {
THROW_NEW_ERROR(
isolate,
NewTypeError(MessageTemplate::kReadGlobalReferenceThroughProxy, name),
Object);
}
DCHECK(!name->IsPrivate());
STACK_CHECK(isolate, MaybeHandle<Object>());
Handle<Name> trap_name = isolate->factory()->get_string();
// 1. Assert: IsPropertyKey(P) is true.
// 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.
// 4. Assert: Type(handler) is Object.
if (proxy->IsRevoked()) {
THROW_NEW_ERROR(isolate,
NewTypeError(MessageTemplate::kProxyRevoked, trap_name),
Object);
}
// 5. Let target be the value of the [[ProxyTarget]] internal slot of O.
Handle<JSReceiver> target(proxy->target(), isolate);
// 6. Let trap be ? GetMethod(handler, "get").
Handle<Object> trap;
ASSIGN_RETURN_ON_EXCEPTION(
isolate, trap,
Object::GetMethod(Handle<JSReceiver>::cast(handler), trap_name), Object);
// 7. If trap is undefined, then
if (trap->IsUndefined(isolate)) {
// 7.a Return target.[[Get]](P, Receiver).
LookupIterator it =
LookupIterator::PropertyOrElement(isolate, receiver, name, target);
MaybeHandle<Object> result = Object::GetProperty(&it);
*was_found = it.IsFound();
return result;
}
// 8. Let trapResult be ? Call(trap, handler, «target, P, Receiver»).
Handle<Object> trap_result;
Handle<Object> args[] = {target, name, receiver};
ASSIGN_RETURN_ON_EXCEPTION(
isolate, trap_result,
Execution::Call(isolate, trap, handler, arraysize(args), args), Object);
// 9. Let targetDesc be ? target.[[GetOwnProperty]](P).
PropertyDescriptor target_desc;
Maybe<bool> target_found =
JSReceiver::GetOwnPropertyDescriptor(isolate, target, name, &target_desc);
MAYBE_RETURN_NULL(target_found);
// 10. If targetDesc is not undefined, then
if (target_found.FromJust()) {
// 10.a. If IsDataDescriptor(targetDesc) and targetDesc.[[Configurable]] is
// false and targetDesc.[[Writable]] is false, then
// 10.a.i. If SameValue(trapResult, targetDesc.[[Value]]) is false,
// throw a TypeError exception.
bool inconsistent = PropertyDescriptor::IsDataDescriptor(&target_desc) &&
!target_desc.configurable() &&
!target_desc.writable() &&
!trap_result->SameValue(*target_desc.value());
if (inconsistent) {
THROW_NEW_ERROR(
isolate, NewTypeError(MessageTemplate::kProxyGetNonConfigurableData,
name, target_desc.value(), trap_result),
Object);
}
// 10.b. If IsAccessorDescriptor(targetDesc) and targetDesc.[[Configurable]]
// is false and targetDesc.[[Get]] is undefined, then
// 10.b.i. If trapResult is not undefined, throw a TypeError exception.
inconsistent = PropertyDescriptor::IsAccessorDescriptor(&target_desc) &&
!target_desc.configurable() &&
target_desc.get()->IsUndefined(isolate) &&
!trap_result->IsUndefined(isolate);
if (inconsistent) {
THROW_NEW_ERROR(
isolate,
NewTypeError(MessageTemplate::kProxyGetNonConfigurableAccessor, name,
trap_result),
Object);
}
}
// 11. Return trap_result
return trap_result;
}