| // 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; |
| } |