Index: src/objects.cc |
diff --git a/src/objects.cc b/src/objects.cc |
index f298711d46da1ef235372d474aaae72012ca350c..877c46127431f4f9256d98d28544f62e8a9578e6 100644 |
--- a/src/objects.cc |
+++ b/src/objects.cc |
@@ -906,6 +906,15 @@ MaybeHandle<Object> JSProxy::GetPrototype(Handle<JSProxy> proxy) { |
} |
+bool JSProxy::IsRevoked(Handle<JSProxy> proxy) { |
+ // TODO(neis): Decide on how to represent revocation. For now, revocation is |
+ // unsupported. |
+ DCHECK(proxy->target()->IsJSReceiver()); |
+ DCHECK(proxy->handler()->IsJSReceiver()); |
+ return false; |
+} |
+ |
+ |
MaybeHandle<Object> JSProxy::GetPropertyWithHandler(Handle<JSProxy> proxy, |
Handle<Object> receiver, |
Handle<Name> name) { |
@@ -4675,6 +4684,15 @@ Maybe<PropertyAttributes> JSProxy::GetPropertyAttributes(LookupIterator* it) { |
} |
+MaybeHandle<Object> JSProxy::GetTrap(Handle<JSProxy> proxy, |
+ Handle<String> trap) { |
+ DCHECK(!IsRevoked(proxy)); |
+ Isolate* isolate = proxy->GetIsolate(); |
+ Handle<JSReceiver> handler(JSReceiver::cast(proxy->handler()), isolate); |
+ return Object::GetMethod(handler, trap); |
+} |
+ |
+ |
MaybeHandle<Object> JSProxy::CallTrap(Handle<JSProxy> proxy, |
const char* name, |
Handle<Object> derived, |
@@ -4682,13 +4700,9 @@ MaybeHandle<Object> JSProxy::CallTrap(Handle<JSProxy> proxy, |
Handle<Object> argv[]) { |
Isolate* isolate = proxy->GetIsolate(); |
Handle<Object> handler(proxy->handler(), isolate); |
- |
Handle<String> trap_name = isolate->factory()->InternalizeUtf8String(name); |
Handle<Object> trap; |
- ASSIGN_RETURN_ON_EXCEPTION( |
- isolate, trap, |
- Object::GetPropertyOrElement(handler, trap_name), |
- Object); |
+ ASSIGN_RETURN_ON_EXCEPTION(isolate, trap, GetTrap(proxy, trap_name), Object); |
if (trap->IsUndefined()) { |
if (derived.is_null()) { |
@@ -7083,13 +7097,62 @@ bool JSObject::ReferencesObject(Object* obj) { |
Maybe<bool> JSReceiver::PreventExtensions(Handle<JSReceiver> object, |
ShouldThrow should_throw) { |
- if (!object->IsJSObject()) return Just(false); |
- // TODO(neis): Deal with proxies. |
+ if (object->IsJSProxy()) { |
+ return JSProxy::PreventExtensions(Handle<JSProxy>::cast(object), |
+ should_throw); |
+ } |
+ DCHECK(object->IsJSObject()); |
return JSObject::PreventExtensions(Handle<JSObject>::cast(object), |
should_throw); |
} |
+Maybe<bool> JSProxy::PreventExtensions(Handle<JSProxy> proxy, |
+ ShouldThrow should_throw) { |
+ Isolate* isolate = proxy->GetIsolate(); |
+ Factory* factory = isolate->factory(); |
+ Handle<String> trap_name = factory->preventExtensions_string(); |
+ |
+ if (IsRevoked(proxy)) { |
+ isolate->Throw( |
+ *factory->NewTypeError(MessageTemplate::kProxyRevoked, trap_name)); |
+ return Nothing<bool>(); |
+ } |
+ |
+ Handle<JSReceiver> target(JSReceiver::cast(proxy->target()), isolate); |
+ Handle<JSReceiver> handler(JSReceiver::cast(proxy->handler()), isolate); |
+ |
+ Handle<Object> trap; |
+ ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, trap, GetTrap(proxy, trap_name), |
+ Nothing<bool>()); |
+ if (trap->IsUndefined()) { |
+ return JSReceiver::PreventExtensions(target, should_throw); |
+ } |
+ |
+ Handle<Object> trap_result; |
+ Handle<Object> args[] = {target}; |
+ ASSIGN_RETURN_ON_EXCEPTION_VALUE( |
+ isolate, trap_result, |
+ Execution::Call(isolate, trap, handler, arraysize(args), args), |
+ Nothing<bool>()); |
+ if (!trap_result->BooleanValue()) { |
+ RETURN_FAILURE(isolate, should_throw, |
+ NewTypeError(MessageTemplate::kProxyHandlerReturned, handler, |
+ factory->false_string(), trap_name)); |
+ } |
+ |
+ // Enforce the invariant. |
+ Maybe<bool> target_result = JSReceiver::IsExtensible(target); |
+ MAYBE_RETURN(target_result, Nothing<bool>()); |
+ if (target_result.FromJust()) { |
+ isolate->Throw(*factory->NewTypeError( |
+ MessageTemplate::kProxyPreventExtensionsViolatesInvariant)); |
+ return Nothing<bool>(); |
+ } |
+ return Just(true); |
+} |
+ |
+ |
Maybe<bool> JSObject::PreventExtensions(Handle<JSObject> object, |
ShouldThrow should_throw) { |
Isolate* isolate = object->GetIsolate(); |
@@ -7147,16 +7210,54 @@ Maybe<bool> JSObject::PreventExtensions(Handle<JSObject> object, |
} |
-// static |
Maybe<bool> JSReceiver::IsExtensible(Handle<JSReceiver> object) { |
if (object->IsJSProxy()) { |
- // TODO(neis,cbruni): Redirect to the trap on JSProxy. |
- return Just(true); |
+ return JSProxy::IsExtensible(Handle<JSProxy>::cast(object)); |
} |
return Just(JSObject::IsExtensible(Handle<JSObject>::cast(object))); |
} |
+Maybe<bool> JSProxy::IsExtensible(Handle<JSProxy> proxy) { |
+ Isolate* isolate = proxy->GetIsolate(); |
+ Factory* factory = isolate->factory(); |
+ Handle<String> trap_name = factory->isExtensible_string(); |
+ |
+ if (IsRevoked(proxy)) { |
+ isolate->Throw( |
+ *factory->NewTypeError(MessageTemplate::kProxyRevoked, trap_name)); |
+ return Nothing<bool>(); |
+ } |
+ |
+ Handle<JSReceiver> target(JSReceiver::cast(proxy->target()), isolate); |
+ Handle<JSReceiver> handler(JSReceiver::cast(proxy->handler()), isolate); |
+ |
+ Handle<Object> trap; |
+ ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, trap, GetTrap(proxy, trap_name), |
+ Nothing<bool>()); |
+ if (trap->IsUndefined()) { |
+ return JSReceiver::IsExtensible(target); |
+ } |
+ |
+ Handle<Object> trap_result; |
+ Handle<Object> args[] = {target}; |
+ ASSIGN_RETURN_ON_EXCEPTION_VALUE( |
+ isolate, trap_result, |
+ Execution::Call(isolate, trap, handler, arraysize(args), args), |
+ Nothing<bool>()); |
+ |
+ // Enforce the invariant. |
+ Maybe<bool> target_result = JSReceiver::IsExtensible(target); |
+ MAYBE_RETURN(target_result, Nothing<bool>()); |
+ if (target_result.FromJust() != trap_result->BooleanValue()) { |
+ isolate->Throw(*factory->NewTypeError( |
+ MessageTemplate::kProxyIsExtensibleViolatesInvariant)); |
+ return Nothing<bool>(); |
+ } |
+ return target_result; |
+} |
+ |
+ |
bool JSObject::IsExtensible(Handle<JSObject> object) { |
Isolate* isolate = object->GetIsolate(); |
if (object->IsAccessCheckNeeded() && |