• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
13 namespace v8 {
14 namespace internal {
15 
16 
17 // ES6 9.5.13 [[Call]] (thisArgument, argumentsList)
RUNTIME_FUNCTION(Runtime_JSProxyCall)18 RUNTIME_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()) {
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<Object>(i + 1);
48     }
49     Handle<Object> result;
50     ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
51         isolate, result, Execution::Call(isolate, target, receiver,
52                                          arguments_length, argv.start()));
53     return *result;
54   }
55   // 7. Let argArray be CreateArrayFromList(argumentsList).
56   Handle<JSArray> arg_array = isolate->factory()->NewJSArray(
57       FAST_ELEMENTS, arguments_length, arguments_length);
58   ElementsAccessor* accessor = arg_array->GetElementsAccessor();
59   {
60     DisallowHeapAllocation no_gc;
61     FixedArrayBase* elements = arg_array->elements();
62     for (int i = 0; i < arguments_length; i++) {
63       accessor->Set(elements, i, args[i + 1]);
64     }
65   }
66   // 8. Return Call(trap, handler, «target, thisArgument, argArray»).
67   Handle<Object> trap_result;
68   Handle<Object> trap_args[] = {target, receiver, arg_array};
69   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
70       isolate, trap_result,
71       Execution::Call(isolate, trap, handler, arraysize(trap_args), trap_args));
72   return *trap_result;
73 }
74 
75 
76 // 9.5.14 [[Construct]] (argumentsList, newTarget)
RUNTIME_FUNCTION(Runtime_JSProxyConstruct)77 RUNTIME_FUNCTION(Runtime_JSProxyConstruct) {
78   HandleScope scope(isolate);
79   DCHECK_LE(3, args.length());
80   CONVERT_ARG_HANDLE_CHECKED(JSProxy, proxy, args.length() - 2);
81   CONVERT_ARG_HANDLE_CHECKED(Object, new_target, args.length() - 1);
82   Handle<String> trap_name = isolate->factory()->construct_string();
83 
84   // 1. Let handler be the value of the [[ProxyHandler]] internal slot of O.
85   Handle<Object> handler(proxy->handler(), isolate);
86   // 2. If handler is null, throw a TypeError exception.
87   if (proxy->IsRevoked()) {
88     THROW_NEW_ERROR_RETURN_FAILURE(
89         isolate, NewTypeError(MessageTemplate::kProxyRevoked, trap_name));
90   }
91   // 3. Assert: Type(handler) is Object.
92   DCHECK(handler->IsJSReceiver());
93   // 4. Let target be the value of the [[ProxyTarget]] internal slot of O.
94   Handle<JSReceiver> target(JSReceiver::cast(proxy->target()), isolate);
95   // 5. Let trap be ? GetMethod(handler, "construct").
96   Handle<Object> trap;
97   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
98       isolate, trap,
99       Object::GetMethod(Handle<JSReceiver>::cast(handler), trap_name));
100   // 6. If trap is undefined, then
101   int const arguments_length = args.length() - 3;
102   if (trap->IsUndefined()) {
103     // 6.a. Assert: target has a [[Construct]] internal method.
104     DCHECK(target->IsConstructor());
105     // 6.b. Return Construct(target, argumentsList, newTarget).
106     ScopedVector<Handle<Object>> argv(arguments_length);
107     for (int i = 0; i < arguments_length; ++i) {
108       argv[i] = args.at<Object>(i + 1);
109     }
110     Handle<Object> result;
111     ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
112         isolate, result, Execution::New(isolate, target, new_target,
113                                         arguments_length, argv.start()));
114     return *result;
115   }
116   // 7. Let argArray be CreateArrayFromList(argumentsList).
117   Handle<JSArray> arg_array = isolate->factory()->NewJSArray(
118       FAST_ELEMENTS, arguments_length, arguments_length);
119   ElementsAccessor* accessor = arg_array->GetElementsAccessor();
120   {
121     DisallowHeapAllocation no_gc;
122     FixedArrayBase* elements = arg_array->elements();
123     for (int i = 0; i < arguments_length; i++) {
124       accessor->Set(elements, i, args[i + 1]);
125     }
126   }
127   // 8. Let newObj be ? Call(trap, handler, «target, argArray, newTarget »).
128   Handle<Object> new_object;
129   Handle<Object> trap_args[] = {target, arg_array, new_target};
130   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
131       isolate, new_object,
132       Execution::Call(isolate, trap, handler, arraysize(trap_args), trap_args));
133   // 9. If Type(newObj) is not Object, throw a TypeError exception.
134   if (!new_object->IsJSReceiver()) {
135     THROW_NEW_ERROR_RETURN_FAILURE(
136         isolate,
137         NewTypeError(MessageTemplate::kProxyConstructNonObject, new_object));
138   }
139   // 10. Return newObj.
140   return *new_object;
141 }
142 
143 
RUNTIME_FUNCTION(Runtime_IsJSProxy)144 RUNTIME_FUNCTION(Runtime_IsJSProxy) {
145   SealHandleScope shs(isolate);
146   DCHECK(args.length() == 1);
147   CONVERT_ARG_CHECKED(Object, obj, 0);
148   return isolate->heap()->ToBoolean(obj->IsJSProxy());
149 }
150 
151 
RUNTIME_FUNCTION(Runtime_JSProxyGetHandler)152 RUNTIME_FUNCTION(Runtime_JSProxyGetHandler) {
153   SealHandleScope shs(isolate);
154   DCHECK(args.length() == 1);
155   CONVERT_ARG_CHECKED(JSProxy, proxy, 0);
156   return proxy->handler();
157 }
158 
159 
RUNTIME_FUNCTION(Runtime_JSProxyGetTarget)160 RUNTIME_FUNCTION(Runtime_JSProxyGetTarget) {
161   SealHandleScope shs(isolate);
162   DCHECK(args.length() == 1);
163   CONVERT_ARG_CHECKED(JSProxy, proxy, 0);
164   return proxy->target();
165 }
166 
167 
RUNTIME_FUNCTION(Runtime_JSProxyRevoke)168 RUNTIME_FUNCTION(Runtime_JSProxyRevoke) {
169   HandleScope scope(isolate);
170   DCHECK(args.length() == 1);
171   CONVERT_ARG_HANDLE_CHECKED(JSProxy, proxy, 0);
172   JSProxy::Revoke(proxy);
173   return isolate->heap()->undefined_value();
174 }
175 
176 }  // namespace internal
177 }  // namespace v8
178