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