Line data Source code
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)
18 20488 : RUNTIME_FUNCTION(Runtime_JSProxyCall) {
19 10244 : HandleScope scope(isolate);
20 : DCHECK_LE(2, args.length());
21 : // thisArgument == receiver
22 10244 : CONVERT_ARG_HANDLE_CHECKED(Object, receiver, 0);
23 20488 : CONVERT_ARG_HANDLE_CHECKED(JSProxy, proxy, args.length() - 1);
24 10244 : Handle<String> trap_name = isolate->factory()->apply_string();
25 : // 1. Let handler be the value of the [[ProxyHandler]] internal slot of O.
26 10244 : Handle<Object> handler(proxy->handler(), isolate);
27 : // 2. If handler is null, throw a TypeError exception.
28 10244 : if (proxy->IsRevoked()) {
29 0 : 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 10244 : Handle<JSReceiver> target(proxy->target(), isolate);
36 : // 5. Let trap be ? GetMethod(handler, "apply").
37 : Handle<Object> trap;
38 20488 : 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 10202 : int const arguments_length = args.length() - 2;
43 10202 : if (trap->IsUndefined(isolate)) {
44 : // 6.a. Return Call(target, thisArgument, argumentsList).
45 3888 : ScopedVector<Handle<Object>> argv(arguments_length);
46 14531 : for (int i = 0; i < arguments_length; ++i) {
47 10643 : argv[i] = args.at(i + 1);
48 : }
49 11664 : RETURN_RESULT_OR_FAILURE(
50 : isolate, Execution::Call(isolate, target, receiver, arguments_length,
51 3888 : argv.start()));
52 : }
53 : // 7. Let argArray be CreateArrayFromList(argumentsList).
54 : Handle<JSArray> arg_array = isolate->factory()->NewJSArray(
55 6314 : FAST_ELEMENTS, arguments_length, arguments_length);
56 : ElementsAccessor* accessor = arg_array->GetElementsAccessor();
57 : {
58 : DisallowHeapAllocation no_gc;
59 15512 : for (int i = 0; i < arguments_length; i++) {
60 18396 : accessor->Set(arg_array, i, args[i + 1]);
61 : }
62 : }
63 : // 8. Return Call(trap, handler, «target, thisArgument, argArray»).
64 6314 : Handle<Object> trap_args[] = {target, receiver, arg_array};
65 12628 : RETURN_RESULT_OR_FAILURE(
66 : isolate,
67 10244 : Execution::Call(isolate, trap, handler, arraysize(trap_args), trap_args));
68 : }
69 :
70 :
71 : // 9.5.14 [[Construct]] (argumentsList, newTarget)
72 1544 : RUNTIME_FUNCTION(Runtime_JSProxyConstruct) {
73 772 : HandleScope scope(isolate);
74 : DCHECK_LE(3, args.length());
75 1544 : CONVERT_ARG_HANDLE_CHECKED(JSProxy, proxy, args.length() - 2);
76 772 : CONVERT_ARG_HANDLE_CHECKED(Object, new_target, args.length() - 1);
77 772 : Handle<String> trap_name = isolate->factory()->construct_string();
78 :
79 : // 1. Let handler be the value of the [[ProxyHandler]] internal slot of O.
80 772 : Handle<Object> handler(proxy->handler(), isolate);
81 : // 2. If handler is null, throw a TypeError exception.
82 772 : if (proxy->IsRevoked()) {
83 28 : 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 758 : Handle<JSReceiver> target(JSReceiver::cast(proxy->target()), isolate);
90 : // 5. Let trap be ? GetMethod(handler, "construct").
91 : Handle<Object> trap;
92 1516 : 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 744 : int const arguments_length = args.length() - 3;
97 744 : 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 114 : ScopedVector<Handle<Object>> argv(arguments_length);
102 114 : for (int i = 0; i < arguments_length; ++i) {
103 0 : argv[i] = args.at(i + 1);
104 : }
105 342 : RETURN_RESULT_OR_FAILURE(
106 : isolate, Execution::New(isolate, target, new_target, arguments_length,
107 114 : argv.start()));
108 : }
109 : // 7. Let argArray be CreateArrayFromList(argumentsList).
110 : Handle<JSArray> arg_array = isolate->factory()->NewJSArray(
111 630 : FAST_ELEMENTS, arguments_length, arguments_length);
112 630 : ElementsAccessor* accessor = arg_array->GetElementsAccessor();
113 : {
114 : DisallowHeapAllocation no_gc;
115 1540 : for (int i = 0; i < arguments_length; i++) {
116 1820 : 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 630 : Handle<Object> trap_args[] = {target, arg_array, new_target};
122 1260 : 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 546 : if (!new_object->IsJSReceiver()) {
127 0 : THROW_NEW_ERROR_RETURN_FAILURE(
128 : isolate,
129 : NewTypeError(MessageTemplate::kProxyConstructNonObject, new_object));
130 : }
131 : // 10. Return newObj.
132 772 : return *new_object;
133 : }
134 :
135 :
136 0 : RUNTIME_FUNCTION(Runtime_IsJSProxy) {
137 : SealHandleScope shs(isolate);
138 : DCHECK_EQ(1, args.length());
139 0 : CONVERT_ARG_CHECKED(Object, obj, 0);
140 0 : return isolate->heap()->ToBoolean(obj->IsJSProxy());
141 : }
142 :
143 :
144 0 : RUNTIME_FUNCTION(Runtime_JSProxyGetHandler) {
145 : SealHandleScope shs(isolate);
146 : DCHECK_EQ(1, args.length());
147 0 : CONVERT_ARG_CHECKED(JSProxy, proxy, 0);
148 0 : return proxy->handler();
149 : }
150 :
151 :
152 0 : RUNTIME_FUNCTION(Runtime_JSProxyGetTarget) {
153 : SealHandleScope shs(isolate);
154 : DCHECK_EQ(1, args.length());
155 0 : CONVERT_ARG_CHECKED(JSProxy, proxy, 0);
156 0 : return proxy->target();
157 : }
158 :
159 :
160 364 : RUNTIME_FUNCTION(Runtime_JSProxyRevoke) {
161 182 : HandleScope scope(isolate);
162 : DCHECK_EQ(1, args.length());
163 364 : CONVERT_ARG_HANDLE_CHECKED(JSProxy, proxy, 0);
164 182 : JSProxy::Revoke(proxy);
165 182 : return isolate->heap()->undefined_value();
166 : }
167 :
168 : } // namespace internal
169 : } // namespace v8
|