Commit c3688c1a authored by jkummerow's avatar jkummerow Committed by Commit bot

Implement JSProxy::GetOwnPropertyDescriptor.

Next step: expose it to JS and test it.

BUG=v8:1543
LOG=n
R=cbruni@chromium.org

Review URL: https://codereview.chromium.org/1439353004

Cr-Commit-Position: refs/heads/master@{#32006}
parent dffecf31
......@@ -192,7 +192,10 @@ class CallSite {
"Proxy handler % returned non-configurable descriptor for property '%' " \
"from '%' trap") \
T(ProxyRepeatedPropName, "Trap '%' returned repeated property name '%'") \
T(ProxyTargetNotExtensible, "Proxy target is not extensible") \
T(ProxyTargetNonObject, "Proxy.% called with non-object as target") \
T(ProxyTargetPropNotConfigurable, \
"Proxy target property '%' is not configurable") \
T(ProxyTrapFunctionExpected, \
"Proxy.createFunction called with non-function for '%' trap") \
T(RedefineDisallowed, "Cannot redefine property: %") \
......
......@@ -6717,14 +6717,16 @@ bool JSReceiver::GetOwnPropertyDescriptor(Isolate* isolate,
// TODO(jkummerow): Any chance to unify this with
// "MaybeHandle<Object> GetOwnProperty()" in runtime-object.cc?
// TODO(jkummerow/verwaest): Proxy support: call getOwnPropertyDescriptor trap
// and convert the result (if it's an object) with ToPropertyDescriptor.
// ES6 9.1.5.1
// Returns true on success; false if there was an exception or no property.
// static
bool JSReceiver::GetOwnPropertyDescriptor(LookupIterator* it,
PropertyDescriptor* desc) {
// "Virtual" dispatch.
if (it->IsFound() && it->GetHolder<JSReceiver>()->IsJSProxy()) {
return JSProxy::GetOwnPropertyDescriptor(it, desc);
}
Isolate* isolate = it->isolate();
// 1. (Assert)
// 2. If O does not have an own property with key P, return undefined.
......@@ -6772,6 +6774,122 @@ bool JSReceiver::GetOwnPropertyDescriptor(LookupIterator* it,
}
// ES6 9.5.5
// static
bool JSProxy::GetOwnPropertyDescriptor(LookupIterator* it,
PropertyDescriptor* desc) {
DCHECK(it->GetHolder<Object>()->IsJSProxy());
Isolate* isolate = it->isolate();
Handle<Name> property_name = it->GetName();
// 1. (Assert)
// 2. Let handler be the value of the [[ProxyHandler]] internal slot of O.
Handle<Object> handler(it->GetHolder<JSProxy>()->handler(), isolate);
// 3. If handler is null, throw a TypeError exception.
if (handler->IsNull()) {
isolate->Throw(*isolate->factory()->NewTypeError(
MessageTemplate::kProxyHandlerNonObject));
return false;
}
// 4. Assert: Type(handler) is Object.
DCHECK(handler->IsSpecObject());
// If the handler is not null, the target can't be null either.
DCHECK(it->GetHolder<JSProxy>()->target()->IsSpecObject());
// 5. Let target be the value of the [[ProxyTarget]] internal slot of O.
Handle<JSReceiver> target(
JSReceiver::cast(it->GetHolder<JSProxy>()->target()), isolate);
// 6. Let trap be ? GetMethod(handler, "getOwnPropertyDescriptor").
Handle<Object> trap;
ASSIGN_RETURN_ON_EXCEPTION_VALUE(
isolate, trap,
Object::GetMethod(Handle<JSReceiver>::cast(handler),
isolate->factory()->getOwnPropertyDescriptor_string()),
false);
// 7. If trap is undefined, then
if (trap->IsUndefined()) {
// 7a. Return target.[[GetOwnProperty]](P).
return JSReceiver::GetOwnPropertyDescriptor(isolate, target, property_name,
desc);
}
// 8. Let trapResultObj be ? Call(trap, handler, «target, P»).
Handle<Object> trap_result_obj;
Handle<Object> args[] = {target, property_name};
ASSIGN_RETURN_ON_EXCEPTION_VALUE(
isolate, trap_result_obj,
Execution::Call(isolate, trap, handler, arraysize(args), args), false);
// 9. If Type(trapResultObj) is neither Object nor Undefined, throw a
// TypeError exception.
if (!trap_result_obj->IsSpecObject() && !trap_result_obj->IsUndefined()) {
isolate->Throw(*isolate->factory()->NewTypeError(
MessageTemplate::kProxyHandlerReturned, handler, trap_result_obj,
property_name));
return false;
}
// 10. Let targetDesc be ? target.[[GetOwnProperty]](P).
PropertyDescriptor target_desc;
JSReceiver::GetOwnPropertyDescriptor(isolate, target, property_name,
&target_desc);
if (isolate->has_pending_exception()) return false;
// 11. If trapResultObj is undefined, then
if (trap_result_obj->IsUndefined()) {
// 11a. If targetDesc is undefined, return undefined.
if (target_desc.is_empty()) return false;
// 11b. If targetDesc.[[Configurable]] is false, throw a TypeError
// exception.
if (!target_desc.configurable()) {
isolate->Throw(*isolate->factory()->NewTypeError(
MessageTemplate::kProxyTargetPropNotConfigurable, property_name));
return false;
}
// 11c. Let extensibleTarget be ? IsExtensible(target).
Maybe<bool> maybe_extensible = JSReceiver::IsExtensible(target);
if (maybe_extensible.IsNothing()) return false;
bool extensible_target = maybe_extensible.FromJust();
// 11d. (Assert)
// 11e. If extensibleTarget is false, throw a TypeError exception.
if (!extensible_target) {
isolate->Throw(*isolate->factory()->NewTypeError(
MessageTemplate::kProxyTargetNotExtensible));
return false;
}
// 11f. Return undefined.
return false; // |desc->is_empty()| is what JavaScript calls "undefined".
}
// 12. Let extensibleTarget be ? IsExtensible(target).
Maybe<bool> maybe_extensible = JSReceiver::IsExtensible(target);
if (maybe_extensible.IsNothing()) return false;
bool extensible_target = maybe_extensible.FromJust();
// 13. Let resultDesc be ? ToPropertyDescriptor(trapResultObj).
if (!PropertyDescriptor::ToPropertyDescriptor(isolate, trap_result_obj,
desc)) {
DCHECK(isolate->has_pending_exception());
return false;
}
// 14. Call CompletePropertyDescriptor(resultDesc).
PropertyDescriptor::CompletePropertyDescriptor(isolate, desc);
// 15. Let valid be IsCompatiblePropertyDescriptor (extensibleTarget,
// resultDesc, targetDesc).
bool valid = IsCompatiblePropertyDescriptor(extensible_target, desc,
&target_desc, property_name);
// 16. If valid is false, throw a TypeError exception.
if (!valid) {
DCHECK(isolate->has_pending_exception());
return false;
}
// 17. If resultDesc.[[Configurable]] is false, then
if (!desc->configurable()) {
// 17a. If targetDesc is undefined or targetDesc.[[Configurable]] is true:
if (target_desc.is_empty() || target_desc.configurable()) {
// 17a i. Throw a TypeError exception.
isolate->Throw(*isolate->factory()->NewTypeError(
MessageTemplate::kRedefineDisallowed, property_name));
return false;
}
}
// 18. Return resultDesc.
return true;
}
bool JSObject::ReferencesObjectFromElements(FixedArray* elements,
ElementsKind kind,
Object* object) {
......
......@@ -9513,8 +9513,13 @@ class JSProxy: public JSReceiver {
DECLARE_CAST(JSProxy)
// ES6 9.5.1
static MaybeHandle<Object> GetPrototype(Handle<JSProxy> receiver);
// ES6 9.5.5
static bool GetOwnPropertyDescriptor(LookupIterator* it,
PropertyDescriptor* desc);
MUST_USE_RESULT static MaybeHandle<Object> GetPropertyWithHandler(
Handle<JSProxy> proxy,
Handle<Object> receiver,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment