1958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// Copyright 2014 the V8 project authors. All rights reserved. 2958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// Use of this source code is governed by a BSD-style license that can be 3958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// found in the LICENSE file. 4958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 5014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/runtime/runtime-utils.h" 6958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 7958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#include "src/arguments.h" 8014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/elements.h" 9014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/factory.h" 10014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/isolate-inl.h" 11014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/objects-inl.h" 12958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 13958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniernamespace v8 { 14958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniernamespace internal { 15958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 16014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 17014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// ES6 9.5.13 [[Call]] (thisArgument, argumentsList) 18014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochRUNTIME_FUNCTION(Runtime_JSProxyCall) { 19958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier HandleScope scope(isolate); 20014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK_LE(2, args.length()); 21014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // thisArgument == receiver 22014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch CONVERT_ARG_HANDLE_CHECKED(Object, receiver, 0); 23014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch CONVERT_ARG_HANDLE_CHECKED(JSProxy, proxy, args.length() - 1); 24014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Handle<String> trap_name = isolate->factory()->apply_string(); 25014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // 1. Let handler be the value of the [[ProxyHandler]] internal slot of O. 26014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Handle<Object> handler(proxy->handler(), isolate); 27014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // 2. If handler is null, throw a TypeError exception. 28014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (proxy->IsRevoked()) { 29014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch THROW_NEW_ERROR_RETURN_FAILURE( 30014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch isolate, NewTypeError(MessageTemplate::kProxyRevoked, trap_name)); 31014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 32014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // 3. Assert: Type(handler) is Object. 33014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(handler->IsJSReceiver()); 34014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // 4. Let target be the value of the [[ProxyTarget]] internal slot of O. 35014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Handle<JSReceiver> target(proxy->target(), isolate); 36014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // 5. Let trap be ? GetMethod(handler, "apply"). 37014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Handle<Object> trap; 38014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 39014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch isolate, trap, 40014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Object::GetMethod(Handle<JSReceiver>::cast(handler), trap_name)); 41014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // 6. If trap is undefined, then 42014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch int const arguments_length = args.length() - 2; 4321efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch if (trap->IsUndefined(isolate)) { 44014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // 6.a. Return Call(target, thisArgument, argumentsList). 45014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ScopedVector<Handle<Object>> argv(arguments_length); 46014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch for (int i = 0; i < arguments_length; ++i) { 47014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch argv[i] = args.at<Object>(i + 1); 48014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 4921efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch RETURN_RESULT_OR_FAILURE( 5021efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch isolate, Execution::Call(isolate, target, receiver, arguments_length, 5121efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch argv.start())); 52014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 53014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // 7. Let argArray be CreateArrayFromList(argumentsList). 54014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Handle<JSArray> arg_array = isolate->factory()->NewJSArray( 55014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch FAST_ELEMENTS, arguments_length, arguments_length); 56014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ElementsAccessor* accessor = arg_array->GetElementsAccessor(); 57014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch { 58014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DisallowHeapAllocation no_gc; 59014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch for (int i = 0; i < arguments_length; i++) { 60342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch accessor->Set(arg_array, i, args[i + 1]); 61014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 62014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 63014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // 8. Return Call(trap, handler, «target, thisArgument, argArray»). 64014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Handle<Object> trap_args[] = {target, receiver, arg_array}; 6521efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch RETURN_RESULT_OR_FAILURE( 6621efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch isolate, 67014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Execution::Call(isolate, trap, handler, arraysize(trap_args), trap_args)); 68958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 69958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 70958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 71014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// 9.5.14 [[Construct]] (argumentsList, newTarget) 72014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochRUNTIME_FUNCTION(Runtime_JSProxyConstruct) { 73958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier HandleScope scope(isolate); 74014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK_LE(3, args.length()); 75014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch CONVERT_ARG_HANDLE_CHECKED(JSProxy, proxy, args.length() - 2); 76014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch CONVERT_ARG_HANDLE_CHECKED(Object, new_target, args.length() - 1); 77014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Handle<String> trap_name = isolate->factory()->construct_string(); 78014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 79014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // 1. Let handler be the value of the [[ProxyHandler]] internal slot of O. 80014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Handle<Object> handler(proxy->handler(), isolate); 81014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // 2. If handler is null, throw a TypeError exception. 82014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (proxy->IsRevoked()) { 83014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch THROW_NEW_ERROR_RETURN_FAILURE( 84014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch isolate, NewTypeError(MessageTemplate::kProxyRevoked, trap_name)); 85014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 86014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // 3. Assert: Type(handler) is Object. 87014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(handler->IsJSReceiver()); 88014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // 4. Let target be the value of the [[ProxyTarget]] internal slot of O. 89014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Handle<JSReceiver> target(JSReceiver::cast(proxy->target()), isolate); 90014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // 5. Let trap be ? GetMethod(handler, "construct"). 91014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Handle<Object> trap; 92014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 93014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch isolate, trap, 94014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Object::GetMethod(Handle<JSReceiver>::cast(handler), trap_name)); 95014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // 6. If trap is undefined, then 96014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch int const arguments_length = args.length() - 3; 9721efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch if (trap->IsUndefined(isolate)) { 98014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // 6.a. Assert: target has a [[Construct]] internal method. 99014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(target->IsConstructor()); 100014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // 6.b. Return Construct(target, argumentsList, newTarget). 101014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ScopedVector<Handle<Object>> argv(arguments_length); 102014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch for (int i = 0; i < arguments_length; ++i) { 103014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch argv[i] = args.at<Object>(i + 1); 104014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 10521efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch RETURN_RESULT_OR_FAILURE( 10621efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch isolate, Execution::New(isolate, target, new_target, arguments_length, 10721efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch argv.start())); 108014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 109014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // 7. Let argArray be CreateArrayFromList(argumentsList). 110014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Handle<JSArray> arg_array = isolate->factory()->NewJSArray( 111014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch FAST_ELEMENTS, arguments_length, arguments_length); 112014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ElementsAccessor* accessor = arg_array->GetElementsAccessor(); 113014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch { 114014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DisallowHeapAllocation no_gc; 115014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch for (int i = 0; i < arguments_length; i++) { 116342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch accessor->Set(arg_array, i, args[i + 1]); 117014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 118014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 119014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // 8. Let newObj be ? Call(trap, handler, «target, argArray, newTarget »). 120014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Handle<Object> new_object; 121014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Handle<Object> trap_args[] = {target, arg_array, new_target}; 122014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 123014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch isolate, new_object, 124014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Execution::Call(isolate, trap, handler, arraysize(trap_args), trap_args)); 125014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // 9. If Type(newObj) is not Object, throw a TypeError exception. 126014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (!new_object->IsJSReceiver()) { 127014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch THROW_NEW_ERROR_RETURN_FAILURE( 128014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch isolate, 129014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch NewTypeError(MessageTemplate::kProxyConstructNonObject, new_object)); 130014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 131014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // 10. Return newObj. 132014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return *new_object; 133958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 134958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 135958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 136014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochRUNTIME_FUNCTION(Runtime_IsJSProxy) { 137958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier SealHandleScope shs(isolate); 138958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(args.length() == 1); 139958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier CONVERT_ARG_CHECKED(Object, obj, 0); 140958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier return isolate->heap()->ToBoolean(obj->IsJSProxy()); 141958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 142958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 143958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 144014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochRUNTIME_FUNCTION(Runtime_JSProxyGetHandler) { 145958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier SealHandleScope shs(isolate); 146958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(args.length() == 1); 147958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier CONVERT_ARG_CHECKED(JSProxy, proxy, 0); 148958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier return proxy->handler(); 149958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 150958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 151958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 152014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochRUNTIME_FUNCTION(Runtime_JSProxyGetTarget) { 153958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier SealHandleScope shs(isolate); 154958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(args.length() == 1); 155014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch CONVERT_ARG_CHECKED(JSProxy, proxy, 0); 156014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return proxy->target(); 157958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 158958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 159958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 160014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochRUNTIME_FUNCTION(Runtime_JSProxyRevoke) { 161958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier HandleScope scope(isolate); 162958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(args.length() == 1); 163958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier CONVERT_ARG_HANDLE_CHECKED(JSProxy, proxy, 0); 164014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch JSProxy::Revoke(proxy); 165958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier return isolate->heap()->undefined_value(); 166958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 167014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 168014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} // namespace internal 169014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} // namespace v8 170