Home | History | Annotate | Download | only in runtime
      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 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(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)
     72 RUNTIME_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 
    136 RUNTIME_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 
    144 RUNTIME_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 
    152 RUNTIME_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 
    160 RUNTIME_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