Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(650)

Unified Diff: src/objects.cc

Issue 1456613002: [proxies] Update Object.defineProperty/ies for JSProxies (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: addressed comments Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/objects.h ('k') | test/mjsunit/harmony/proxies-define-property.js » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/objects.cc
diff --git a/src/objects.cc b/src/objects.cc
index 9f639c52dc68f88dfc1d296857cf4ae49e018ecb..fea27b7462bdd3137faace208837ea5a297639e3 100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -4664,75 +4664,14 @@ MaybeHandle<Object> JSProxy::DeletePropertyWithHandler(
}
-Maybe<PropertyAttributes> JSProxy::GetPropertyAttributesWithHandler(
- Handle<JSProxy> proxy, Handle<Object> receiver, Handle<Name> name) {
- Isolate* isolate = proxy->GetIsolate();
+Maybe<PropertyAttributes> JSProxy::GetPropertyAttributes(LookupIterator* it) {
+ Isolate* isolate = it->isolate();
HandleScope scope(isolate);
-
- // TODO(rossberg): adjust once there is a story for symbols vs proxies.
- if (name->IsSymbol()) return Just(ABSENT);
-
- Handle<Object> args[] = { name };
- Handle<Object> result;
- ASSIGN_RETURN_ON_EXCEPTION_VALUE(
- isolate, result, proxy->CallTrap(proxy, "getPropertyDescriptor",
- Handle<Object>(), arraysize(args), args),
- Nothing<PropertyAttributes>());
-
- if (result->IsUndefined()) return Just(ABSENT);
-
- Handle<Object> argv[] = { result };
- Handle<Object> desc;
- ASSIGN_RETURN_ON_EXCEPTION_VALUE(
- isolate, desc,
- Execution::Call(isolate, isolate->to_complete_property_descriptor(),
- result, arraysize(argv), argv),
- Nothing<PropertyAttributes>());
-
- // Convert result to PropertyAttributes.
- Handle<String> enum_n = isolate->factory()->InternalizeOneByteString(
- STATIC_CHAR_VECTOR("enumerable_"));
- Handle<Object> enumerable;
- ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, enumerable,
- Object::GetProperty(desc, enum_n),
- Nothing<PropertyAttributes>());
- Handle<String> conf_n = isolate->factory()->InternalizeOneByteString(
- STATIC_CHAR_VECTOR("configurable_"));
- Handle<Object> configurable;
- ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, configurable,
- Object::GetProperty(desc, conf_n),
- Nothing<PropertyAttributes>());
- Handle<String> writ_n = isolate->factory()->InternalizeOneByteString(
- STATIC_CHAR_VECTOR("writable_"));
- Handle<Object> writable;
- ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, writable,
- Object::GetProperty(desc, writ_n),
- Nothing<PropertyAttributes>());
- if (!writable->BooleanValue()) {
- Handle<String> set_n = isolate->factory()->InternalizeOneByteString(
- STATIC_CHAR_VECTOR("set_"));
- Handle<Object> setter;
- ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, setter,
- Object::GetProperty(desc, set_n),
- Nothing<PropertyAttributes>());
- writable = isolate->factory()->ToBoolean(!setter->IsUndefined());
- }
-
- if (configurable->IsFalse()) {
- Handle<Object> handler(proxy->handler(), isolate);
- Handle<String> trap = isolate->factory()->InternalizeOneByteString(
- STATIC_CHAR_VECTOR("getPropertyDescriptor"));
- Handle<Object> error = isolate->factory()->NewTypeError(
- MessageTemplate::kProxyPropNotConfigurable, handler, name, trap);
- isolate->Throw(*error);
- return Nothing<PropertyAttributes>();
- }
-
- int attributes = NONE;
- if (!enumerable->BooleanValue()) attributes |= DONT_ENUM;
- if (!configurable->BooleanValue()) attributes |= DONT_DELETE;
- if (!writable->BooleanValue()) attributes |= READ_ONLY;
- return Just(static_cast<PropertyAttributes>(attributes));
+ PropertyDescriptor desc;
+ bool found = JSProxy::GetOwnPropertyDescriptor(it, &desc);
+ if (isolate->has_pending_exception()) return Nothing<PropertyAttributes>();
+ if (!found) return Just(ABSENT);
+ return Just(desc.ToAttributes());
}
@@ -5115,8 +5054,7 @@ Maybe<PropertyAttributes> JSReceiver::GetPropertyAttributes(
case LookupIterator::TRANSITION:
UNREACHABLE();
case LookupIterator::JSPROXY:
- return JSProxy::GetPropertyAttributesWithHandler(
- it->GetHolder<JSProxy>(), it->GetReceiver(), it->GetName());
+ return JSProxy::GetPropertyAttributes(it);
case LookupIterator::INTERCEPTOR: {
Maybe<PropertyAttributes> result =
JSObject::GetPropertyAttributesWithInterceptor(it);
@@ -6014,8 +5952,7 @@ Object* JSReceiver::DefineProperty(Isolate* isolate, Handle<Object> object,
Handle<Object> key,
Handle<Object> attributes) {
// 1. If Type(O) is not Object, throw a TypeError exception.
- // TODO(jkummerow): Implement Proxy support, change to "IsSpecObject".
- if (!object->IsJSObject()) {
+ if (!object->IsSpecObject()) {
Handle<String> fun_name =
isolate->factory()->InternalizeUtf8String("Object.defineProperty");
THROW_NEW_ERROR_RETURN_FAILURE(
@@ -6031,8 +5968,8 @@ Object* JSReceiver::DefineProperty(Isolate* isolate, Handle<Object> object,
return isolate->heap()->exception();
}
// 6. Let success be DefinePropertyOrThrow(O,key, desc).
- bool success = DefineOwnProperty(isolate, Handle<JSObject>::cast(object), key,
- &desc, THROW_ON_ERROR);
+ bool success = DefineOwnProperty(isolate, Handle<JSReceiver>::cast(object),
+ key, &desc, THROW_ON_ERROR);
// 7. ReturnIfAbrupt(success).
if (isolate->has_pending_exception()) return isolate->heap()->exception();
CHECK(success == true);
@@ -6046,8 +5983,7 @@ Object* JSReceiver::DefineProperty(Isolate* isolate, Handle<Object> object,
Object* JSReceiver::DefineProperties(Isolate* isolate, Handle<Object> object,
Handle<Object> properties) {
// 1. If Type(O) is not Object, throw a TypeError exception.
- // TODO(jkummerow): Implement Proxy support, change to "IsSpecObject".
- if (!object->IsJSObject()) {
+ if (!object->IsSpecObject()) {
Handle<String> fun_name =
isolate->factory()->InternalizeUtf8String("Object.defineProperties");
THROW_NEW_ERROR_RETURN_FAILURE(
@@ -6078,10 +6014,7 @@ Object* JSReceiver::DefineProperties(Isolate* isolate, Handle<Object> object,
LookupIterator it = LookupIterator::PropertyOrElement(
isolate, props, next_key, &success, LookupIterator::HIDDEN);
DCHECK(success);
- // TODO(jkummerow): Support JSProxies. Make sure we call the correct
- // getOwnPropertyDescriptor trap, and convert the result object to a
- // PropertyDescriptor.
- Maybe<PropertyAttributes> maybe = JSObject::GetPropertyAttributes(&it);
+ Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it);
if (!maybe.IsJust()) return isolate->heap()->exception();
PropertyAttributes attrs = maybe.FromJust();
// 7c. If propDesc is not undefined and propDesc.[[Enumerable]] is true:
@@ -6092,7 +6025,7 @@ Object* JSReceiver::DefineProperties(Isolate* isolate, Handle<Object> object,
// 7c ii. ReturnIfAbrupt(descObj).
Handle<Object> desc_obj;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, desc_obj,
- JSObject::GetProperty(&it));
+ Object::GetProperty(&it));
// 7c iii. Let desc be ToPropertyDescriptor(descObj).
success = PropertyDescriptor::ToPropertyDescriptor(isolate, desc_obj,
&descriptors[i]);
@@ -6108,7 +6041,7 @@ Object* JSReceiver::DefineProperties(Isolate* isolate, Handle<Object> object,
// 8a. Let P be the first element of pair.
// 8b. Let desc be the second element of pair.
// 8c. Let status be DefinePropertyOrThrow(O, P, desc).
- bool status = DefineOwnProperty(isolate, Handle<JSObject>::cast(object),
+ bool status = DefineOwnProperty(isolate, Handle<JSReceiver>::cast(object),
desc->name(), desc, THROW_ON_ERROR);
// 8d. ReturnIfAbrupt(status).
if (isolate->has_pending_exception()) return isolate->heap()->exception();
@@ -6127,9 +6060,11 @@ bool JSReceiver::DefineOwnProperty(Isolate* isolate, Handle<JSReceiver> object,
return JSArray::DefineOwnProperty(isolate, Handle<JSArray>::cast(object),
key, desc, should_throw);
}
+ if (object->IsJSProxy()) {
+ return JSProxy::DefineOwnProperty(isolate, Handle<JSProxy>::cast(object),
+ key, desc, should_throw);
+ }
// TODO(jkummerow): Support Modules (ES6 9.4.6.6)
- // TODO(jkummerow): Support Proxies (ES6 9.5.6)
- if (!object->IsJSObject()) return true;
// OrdinaryDefineOwnProperty, by virtue of calling
// DefineOwnPropertyIgnoreAttributes, can handle arguments (ES6 9.4.4.2)
@@ -6710,6 +6645,117 @@ bool JSArray::ArraySetLength(Isolate* isolate, Handle<JSArray> a,
}
+// ES6 9.5.6
+// static
+bool JSProxy::DefineOwnProperty(Isolate* isolate, Handle<JSProxy> object,
+ Handle<Object> key, PropertyDescriptor* desc,
+ ShouldThrow should_throw) {
+ // 1. Assert: IsPropertyKey(P) is true.
+ DCHECK(key->IsName() || key->IsNumber());
+ // 2. Let handler be the value of the [[ProxyHandler]] internal slot of O.
+ Handle<Object> handler(object->handler(), isolate);
+ // 3. If handler is null, throw a TypeError exception.
+ // TODO(jkummerow): Use "IsRevoked()" instead once we have it.
+ if (handler->IsNull()) {
+ isolate->Throw(*isolate->factory()->NewTypeError(
+ MessageTemplate::kProxyHandlerNonObject));
+ return false;
+ }
+ // 4. Assert: Type(handler) is Object.
+ DCHECK(handler->IsJSReceiver());
+ // If the handler is not null, the target can't be null either.
+ DCHECK(object->target()->IsSpecObject());
+ // 5. Let target be the value of the [[ProxyTarget]] internal slot of O.
+ Handle<JSReceiver> target(JSReceiver::cast(object->target()), isolate);
+ // 6. Let trap be ? GetMethod(handler, "defineProperty").
+ Handle<Object> trap;
+ ASSIGN_RETURN_ON_EXCEPTION_VALUE(
+ isolate, trap,
+ Object::GetMethod(Handle<JSReceiver>::cast(handler),
+ isolate->factory()->defineProperty_string()),
+ false);
+ // 7. If trap is undefined, then:
+ if (trap->IsUndefined()) {
+ // 7a. Return target.[[DefineOwnProperty]](P, Desc).
+ return JSReceiver::DefineOwnProperty(isolate, target, key, desc,
+ should_throw);
+ }
+ // 8. Let descObj be FromPropertyDescriptor(Desc).
+ Handle<Object> desc_obj = desc->ToObject(isolate);
+ // 9. Let booleanTrapResult be
+ // ToBoolean(? Call(trap, handler, «target, P, descObj»)).
+ Handle<Name> property_name =
+ key->IsName()
+ ? Handle<Name>::cast(key)
+ : Handle<Name>::cast(isolate->factory()->NumberToString(key));
+ Handle<Object> trap_result_obj;
+ Handle<Object> args[] = {target, property_name, desc_obj};
+ ASSIGN_RETURN_ON_EXCEPTION_VALUE(
+ isolate, trap_result_obj,
+ Execution::Call(isolate, trap, handler, arraysize(args), args), false);
+ // 10. If booleanTrapResult is false, return false.
+ if (!trap_result_obj->BooleanValue()) {
+ if (should_throw == THROW_ON_ERROR) {
+ // TODO(jkummerow): Better error message?
+ isolate->Throw(*isolate->factory()->NewTypeError(
+ MessageTemplate::kProxyHandlerReturned, handler, trap_result_obj,
+ key));
+ }
+ return false;
+ }
+ // 11. Let targetDesc be ? target.[[GetOwnProperty]](P).
+ PropertyDescriptor target_desc;
+ bool target_found =
+ JSReceiver::GetOwnPropertyDescriptor(isolate, target, key, &target_desc);
+ if (isolate->has_pending_exception()) return false;
+ // 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. If Desc has a [[Configurable]] field and if Desc.[[Configurable]]
+ // is false, then:
+ // 13a. Let settingConfigFalse be true.
+ // 14. Else let settingConfigFalse be false.
+ bool setting_config_false = desc->has_configurable() && !desc->configurable();
+ // 15. If targetDesc is undefined, then
+ if (!target_found) {
+ // 15a. If extensibleTarget is false, throw a TypeError exception.
+ if (!extensible_target) {
+ isolate->Throw(*isolate->factory()->NewTypeError(
+ MessageTemplate::kProxyTargetNotExtensible));
+ return false;
+ }
+ // 15b. If settingConfigFalse is true, throw a TypeError exception.
+ if (setting_config_false) {
+ // TODO(jkummerow): Better error message?
+ isolate->Throw(*isolate->factory()->NewTypeError(
+ MessageTemplate::kRedefineDisallowed, key));
+ return false;
+ }
+ } else {
+ // 16. Else targetDesc is not undefined,
+ // 16a. If IsCompatiblePropertyDescriptor(extensibleTarget, Desc,
+ // targetDesc) is false, throw a TypeError exception.
+ bool valid = IsCompatiblePropertyDescriptor(
+ isolate, extensible_target, desc, &target_desc, property_name);
+ if (!valid) {
+ DCHECK(isolate->has_pending_exception());
+ return false;
+ }
+ // 16b. If settingConfigFalse is true and targetDesc.[[Configurable]] is
+ // true, throw a TypeError exception.
+ if (setting_config_false && target_desc.configurable()) {
+ // TODO(jkummerow): Better error message?
+ isolate->Throw(*isolate->factory()->NewTypeError(
+ MessageTemplate::kRedefineDisallowed, key));
+ return false;
+ }
+ }
+ // 17. Return true.
+ return true;
+}
+
+
// static
bool JSReceiver::GetOwnPropertyDescriptor(Isolate* isolate,
Handle<JSReceiver> object,
« no previous file with comments | « src/objects.h ('k') | test/mjsunit/harmony/proxies-define-property.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698