runtime-proxy.cc 6.03 KB
Newer Older
1 2 3 4
// Copyright 2014 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

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 14 15 16

namespace v8 {
namespace internal {


17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
// ES6 9.5.13 [[Call]] (thisArgument, argumentsList)
RUNTIME_FUNCTION(Runtime_JSProxyCall) {
  HandleScope scope(isolate);
  DCHECK_LE(2, args.length());
  // thisArgument == receiver
  CONVERT_ARG_HANDLE_CHECKED(Object, receiver, 0);
  CONVERT_ARG_HANDLE_CHECKED(JSProxy, proxy, args.length() - 1);
  Handle<String> trap_name = isolate->factory()->apply_string();
  // 1. Let handler be the value of the [[ProxyHandler]] internal slot of O.
  Handle<Object> handler(proxy->handler(), isolate);
  // 2. If handler is null, throw a TypeError exception.
  if (proxy->IsRevoked()) {
    THROW_NEW_ERROR_RETURN_FAILURE(
        isolate, NewTypeError(MessageTemplate::kProxyRevoked, trap_name));
  }
  // 3. Assert: Type(handler) is Object.
  DCHECK(handler->IsJSReceiver());
  // 4. Let target be the value of the [[ProxyTarget]] internal slot of O.
  Handle<JSReceiver> target(proxy->target(), isolate);
  // 5. Let trap be ? GetMethod(handler, "apply").
  Handle<Object> trap;
  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
      isolate, trap,
      Object::GetMethod(Handle<JSReceiver>::cast(handler), trap_name));
  // 6. If trap is undefined, then
  int const arguments_length = args.length() - 2;
43
  if (trap->IsUndefined(isolate)) {
44 45 46
    // 6.a. Return Call(target, thisArgument, argumentsList).
    ScopedVector<Handle<Object>> argv(arguments_length);
    for (int i = 0; i < arguments_length; ++i) {
47
      argv[i] = args.at(i + 1);
48
    }
49 50 51
    RETURN_RESULT_OR_FAILURE(
        isolate, Execution::Call(isolate, target, receiver, arguments_length,
                                 argv.start()));
52 53 54 55 56 57 58 59
  }
  // 7. Let argArray be CreateArrayFromList(argumentsList).
  Handle<JSArray> arg_array = isolate->factory()->NewJSArray(
      FAST_ELEMENTS, arguments_length, arguments_length);
  ElementsAccessor* accessor = arg_array->GetElementsAccessor();
  {
    DisallowHeapAllocation no_gc;
    for (int i = 0; i < arguments_length; i++) {
60
      accessor->Set(arg_array, i, args[i + 1]);
61 62 63 64
    }
  }
  // 8. Return Call(trap, handler, «target, thisArgument, argArray»).
  Handle<Object> trap_args[] = {target, receiver, arg_array};
65 66
  RETURN_RESULT_OR_FAILURE(
      isolate,
67 68 69
      Execution::Call(isolate, trap, handler, arraysize(trap_args), trap_args));
}

70

71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
// 9.5.14 [[Construct]] (argumentsList, newTarget)
RUNTIME_FUNCTION(Runtime_JSProxyConstruct) {
  HandleScope scope(isolate);
  DCHECK_LE(3, args.length());
  CONVERT_ARG_HANDLE_CHECKED(JSProxy, proxy, args.length() - 2);
  CONVERT_ARG_HANDLE_CHECKED(Object, new_target, args.length() - 1);
  Handle<String> trap_name = isolate->factory()->construct_string();

  // 1. Let handler be the value of the [[ProxyHandler]] internal slot of O.
  Handle<Object> handler(proxy->handler(), isolate);
  // 2. If handler is null, throw a TypeError exception.
  if (proxy->IsRevoked()) {
    THROW_NEW_ERROR_RETURN_FAILURE(
        isolate, NewTypeError(MessageTemplate::kProxyRevoked, trap_name));
  }
  // 3. Assert: Type(handler) is Object.
  DCHECK(handler->IsJSReceiver());
  // 4. Let target be the value of the [[ProxyTarget]] internal slot of O.
  Handle<JSReceiver> target(JSReceiver::cast(proxy->target()), isolate);
  // 5. Let trap be ? GetMethod(handler, "construct").
  Handle<Object> trap;
  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
      isolate, trap,
      Object::GetMethod(Handle<JSReceiver>::cast(handler), trap_name));
  // 6. If trap is undefined, then
  int const arguments_length = args.length() - 3;
97
  if (trap->IsUndefined(isolate)) {
98 99 100 101 102
    // 6.a. Assert: target has a [[Construct]] internal method.
    DCHECK(target->IsConstructor());
    // 6.b. Return Construct(target, argumentsList, newTarget).
    ScopedVector<Handle<Object>> argv(arguments_length);
    for (int i = 0; i < arguments_length; ++i) {
103
      argv[i] = args.at(i + 1);
104
    }
105 106 107
    RETURN_RESULT_OR_FAILURE(
        isolate, Execution::New(isolate, target, new_target, arguments_length,
                                argv.start()));
108 109 110 111 112 113 114 115
  }
  // 7. Let argArray be CreateArrayFromList(argumentsList).
  Handle<JSArray> arg_array = isolate->factory()->NewJSArray(
      FAST_ELEMENTS, arguments_length, arguments_length);
  ElementsAccessor* accessor = arg_array->GetElementsAccessor();
  {
    DisallowHeapAllocation no_gc;
    for (int i = 0; i < arguments_length; i++) {
116
      accessor->Set(arg_array, i, args[i + 1]);
117 118 119 120 121 122 123 124 125 126 127 128
    }
  }
  // 8. Let newObj be ? Call(trap, handler, «target, argArray, newTarget »).
  Handle<Object> new_object;
  Handle<Object> trap_args[] = {target, arg_array, new_target};
  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
      isolate, new_object,
      Execution::Call(isolate, trap, handler, arraysize(trap_args), trap_args));
  // 9. If Type(newObj) is not Object, throw a TypeError exception.
  if (!new_object->IsJSReceiver()) {
    THROW_NEW_ERROR_RETURN_FAILURE(
        isolate,
129
        NewTypeError(MessageTemplate::kProxyConstructNonObject, new_object));
130 131 132 133 134 135
  }
  // 10. Return newObj.
  return *new_object;
}


136
RUNTIME_FUNCTION(Runtime_IsJSProxy) {
137
  SealHandleScope shs(isolate);
138
  DCHECK_EQ(1, args.length());
139
  CONVERT_ARG_CHECKED(Object, obj, 0);
140 141 142 143
  return isolate->heap()->ToBoolean(obj->IsJSProxy());
}


144
RUNTIME_FUNCTION(Runtime_JSProxyGetHandler) {
145
  SealHandleScope shs(isolate);
146
  DCHECK_EQ(1, args.length());
147 148 149 150 151
  CONVERT_ARG_CHECKED(JSProxy, proxy, 0);
  return proxy->handler();
}


152 153
RUNTIME_FUNCTION(Runtime_JSProxyGetTarget) {
  SealHandleScope shs(isolate);
154
  DCHECK_EQ(1, args.length());
155 156 157 158 159 160
  CONVERT_ARG_CHECKED(JSProxy, proxy, 0);
  return proxy->target();
}


RUNTIME_FUNCTION(Runtime_JSProxyRevoke) {
161
  HandleScope scope(isolate);
162
  DCHECK_EQ(1, args.length());
163 164 165 166 167
  CONVERT_ARG_HANDLE_CHECKED(JSProxy, proxy, 0);
  JSProxy::Revoke(proxy);
  return isolate->heap()->undefined_value();
}

168 169
}  // namespace internal
}  // namespace v8