// 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.

#include "src/runtime/runtime-utils.h"

#include "src/arguments.h"
#include "src/elements.h"
#include "src/factory.h"
#include "src/isolate-inl.h"
#include "src/objects-inl.h"

namespace v8 {
namespace internal {


// 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;
  if (trap->IsUndefined()) {
    // 6.a. Return Call(target, thisArgument, argumentsList).
    ScopedVector<Handle<Object>> argv(arguments_length);
    for (int i = 0; i < arguments_length; ++i) {
      argv[i] = args.at<Object>(i + 1);
    }
    Handle<Object> result;
    ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
        isolate, result, Execution::Call(isolate, target, receiver,
                                         arguments_length, argv.start()));
    return *result;
  }
  // 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;
    FixedArrayBase* elements = arg_array->elements();
    for (int i = 0; i < arguments_length; i++) {
      accessor->Set(elements, i, args[i + 1]);
    }
  }
  // 8. Return Call(trap, handler, «target, thisArgument, argArray»).
  Handle<Object> trap_result;
  Handle<Object> trap_args[] = {target, receiver, arg_array};
  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
      isolate, trap_result,
      Execution::Call(isolate, trap, handler, arraysize(trap_args), trap_args));
  return *trap_result;
}


// 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;
  if (trap->IsUndefined()) {
    // 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) {
      argv[i] = args.at<Object>(i + 1);
    }
    Handle<Object> result;
    ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
        isolate, result, Execution::New(isolate, target, new_target,
                                        arguments_length, argv.start()));
    return *result;
  }
  // 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;
    FixedArrayBase* elements = arg_array->elements();
    for (int i = 0; i < arguments_length; i++) {
      accessor->Set(elements, i, args[i + 1]);
    }
  }
  // 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,
        NewTypeError(MessageTemplate::kProxyConstructNonObject, new_object));
  }
  // 10. Return newObj.
  return *new_object;
}


RUNTIME_FUNCTION(Runtime_IsJSProxy) {
  SealHandleScope shs(isolate);
  DCHECK(args.length() == 1);
  CONVERT_ARG_CHECKED(Object, obj, 0);
  return isolate->heap()->ToBoolean(obj->IsJSProxy());
}


RUNTIME_FUNCTION(Runtime_JSProxyGetHandler) {
  SealHandleScope shs(isolate);
  DCHECK(args.length() == 1);
  CONVERT_ARG_CHECKED(JSProxy, proxy, 0);
  return proxy->handler();
}


RUNTIME_FUNCTION(Runtime_JSProxyGetTarget) {
  SealHandleScope shs(isolate);
  DCHECK(args.length() == 1);
  CONVERT_ARG_CHECKED(JSProxy, proxy, 0);
  return proxy->target();
}


RUNTIME_FUNCTION(Runtime_JSProxyRevoke) {
  HandleScope scope(isolate);
  DCHECK(args.length() == 1);
  CONVERT_ARG_HANDLE_CHECKED(JSProxy, proxy, 0);
  JSProxy::Revoke(proxy);
  return isolate->heap()->undefined_value();
}

}  // namespace internal
}  // namespace v8
