1// Copyright 2014 the V8 project authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "src/runtime/runtime-utils.h" 6 7#include "src/arguments.h" 8#include "src/elements.h" 9#include "src/factory.h" 10#include "src/isolate-inl.h" 11#include "src/objects-inl.h" 12 13namespace v8 { 14namespace internal { 15 16 17// ES6 9.5.13 [[Call]] (thisArgument, argumentsList) 18RUNTIME_FUNCTION(Runtime_JSProxyCall) { 19 HandleScope scope(isolate); 20 DCHECK_LE(2, args.length()); 21 // thisArgument == receiver 22 CONVERT_ARG_HANDLE_CHECKED(Object, receiver, 0); 23 CONVERT_ARG_HANDLE_CHECKED(JSProxy, proxy, args.length() - 1); 24 Handle<String> trap_name = isolate->factory()->apply_string(); 25 // 1. Let handler be the value of the [[ProxyHandler]] internal slot of O. 26 Handle<Object> handler(proxy->handler(), isolate); 27 // 2. If handler is null, throw a TypeError exception. 28 if (proxy->IsRevoked()) { 29 THROW_NEW_ERROR_RETURN_FAILURE( 30 isolate, NewTypeError(MessageTemplate::kProxyRevoked, trap_name)); 31 } 32 // 3. Assert: Type(handler) is Object. 33 DCHECK(handler->IsJSReceiver()); 34 // 4. Let target be the value of the [[ProxyTarget]] internal slot of O. 35 Handle<JSReceiver> target(proxy->target(), isolate); 36 // 5. Let trap be ? GetMethod(handler, "apply"). 37 Handle<Object> trap; 38 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 39 isolate, trap, 40 Object::GetMethod(Handle<JSReceiver>::cast(handler), trap_name)); 41 // 6. If trap is undefined, then 42 int const arguments_length = args.length() - 2; 43 if (trap->IsUndefined(isolate)) { 44 // 6.a. Return Call(target, thisArgument, argumentsList). 45 ScopedVector<Handle<Object>> argv(arguments_length); 46 for (int i = 0; i < arguments_length; ++i) { 47 argv[i] = args.at(i + 1); 48 } 49 RETURN_RESULT_OR_FAILURE( 50 isolate, Execution::Call(isolate, target, receiver, arguments_length, 51 argv.start())); 52 } 53 // 7. Let argArray be CreateArrayFromList(argumentsList). 54 Handle<JSArray> arg_array = isolate->factory()->NewJSArray( 55 FAST_ELEMENTS, arguments_length, arguments_length); 56 ElementsAccessor* accessor = arg_array->GetElementsAccessor(); 57 { 58 DisallowHeapAllocation no_gc; 59 for (int i = 0; i < arguments_length; i++) { 60 accessor->Set(arg_array, i, args[i + 1]); 61 } 62 } 63 // 8. Return Call(trap, handler, «target, thisArgument, argArray»). 64 Handle<Object> trap_args[] = {target, receiver, arg_array}; 65 RETURN_RESULT_OR_FAILURE( 66 isolate, 67 Execution::Call(isolate, trap, handler, arraysize(trap_args), trap_args)); 68} 69 70 71// 9.5.14 [[Construct]] (argumentsList, newTarget) 72RUNTIME_FUNCTION(Runtime_JSProxyConstruct) { 73 HandleScope scope(isolate); 74 DCHECK_LE(3, args.length()); 75 CONVERT_ARG_HANDLE_CHECKED(JSProxy, proxy, args.length() - 2); 76 CONVERT_ARG_HANDLE_CHECKED(Object, new_target, args.length() - 1); 77 Handle<String> trap_name = isolate->factory()->construct_string(); 78 79 // 1. Let handler be the value of the [[ProxyHandler]] internal slot of O. 80 Handle<Object> handler(proxy->handler(), isolate); 81 // 2. If handler is null, throw a TypeError exception. 82 if (proxy->IsRevoked()) { 83 THROW_NEW_ERROR_RETURN_FAILURE( 84 isolate, NewTypeError(MessageTemplate::kProxyRevoked, trap_name)); 85 } 86 // 3. Assert: Type(handler) is Object. 87 DCHECK(handler->IsJSReceiver()); 88 // 4. Let target be the value of the [[ProxyTarget]] internal slot of O. 89 Handle<JSReceiver> target(JSReceiver::cast(proxy->target()), isolate); 90 // 5. Let trap be ? GetMethod(handler, "construct"). 91 Handle<Object> trap; 92 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 93 isolate, trap, 94 Object::GetMethod(Handle<JSReceiver>::cast(handler), trap_name)); 95 // 6. If trap is undefined, then 96 int const arguments_length = args.length() - 3; 97 if (trap->IsUndefined(isolate)) { 98 // 6.a. Assert: target has a [[Construct]] internal method. 99 DCHECK(target->IsConstructor()); 100 // 6.b. Return Construct(target, argumentsList, newTarget). 101 ScopedVector<Handle<Object>> argv(arguments_length); 102 for (int i = 0; i < arguments_length; ++i) { 103 argv[i] = args.at(i + 1); 104 } 105 RETURN_RESULT_OR_FAILURE( 106 isolate, Execution::New(isolate, target, new_target, arguments_length, 107 argv.start())); 108 } 109 // 7. Let argArray be CreateArrayFromList(argumentsList). 110 Handle<JSArray> arg_array = isolate->factory()->NewJSArray( 111 FAST_ELEMENTS, arguments_length, arguments_length); 112 ElementsAccessor* accessor = arg_array->GetElementsAccessor(); 113 { 114 DisallowHeapAllocation no_gc; 115 for (int i = 0; i < arguments_length; i++) { 116 accessor->Set(arg_array, i, args[i + 1]); 117 } 118 } 119 // 8. Let newObj be ? Call(trap, handler, «target, argArray, newTarget »). 120 Handle<Object> new_object; 121 Handle<Object> trap_args[] = {target, arg_array, new_target}; 122 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 123 isolate, new_object, 124 Execution::Call(isolate, trap, handler, arraysize(trap_args), trap_args)); 125 // 9. If Type(newObj) is not Object, throw a TypeError exception. 126 if (!new_object->IsJSReceiver()) { 127 THROW_NEW_ERROR_RETURN_FAILURE( 128 isolate, 129 NewTypeError(MessageTemplate::kProxyConstructNonObject, new_object)); 130 } 131 // 10. Return newObj. 132 return *new_object; 133} 134 135 136RUNTIME_FUNCTION(Runtime_IsJSProxy) { 137 SealHandleScope shs(isolate); 138 DCHECK_EQ(1, args.length()); 139 CONVERT_ARG_CHECKED(Object, obj, 0); 140 return isolate->heap()->ToBoolean(obj->IsJSProxy()); 141} 142 143 144RUNTIME_FUNCTION(Runtime_JSProxyGetHandler) { 145 SealHandleScope shs(isolate); 146 DCHECK_EQ(1, args.length()); 147 CONVERT_ARG_CHECKED(JSProxy, proxy, 0); 148 return proxy->handler(); 149} 150 151 152RUNTIME_FUNCTION(Runtime_JSProxyGetTarget) { 153 SealHandleScope shs(isolate); 154 DCHECK_EQ(1, args.length()); 155 CONVERT_ARG_CHECKED(JSProxy, proxy, 0); 156 return proxy->target(); 157} 158 159 160RUNTIME_FUNCTION(Runtime_JSProxyRevoke) { 161 HandleScope scope(isolate); 162 DCHECK_EQ(1, args.length()); 163 CONVERT_ARG_HANDLE_CHECKED(JSProxy, proxy, 0); 164 JSProxy::Revoke(proxy); 165 return isolate->heap()->undefined_value(); 166} 167 168} // namespace internal 169} // namespace v8 170