// Copyright 2016 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/builtins/builtins.h"
#include "src/builtins/builtins-utils.h"

#include "src/accessors.h"
#include "src/counters.h"
#include "src/messages.h"
#include "src/objects-inl.h"
#include "src/property-descriptor.h"
#include "src/string-builder.h"

namespace v8 {
namespace internal {

// ES6 section 19.5.1.1 Error ( message )
BUILTIN(ErrorConstructor) {
  HandleScope scope(isolate);

  FrameSkipMode mode = SKIP_FIRST;
  Handle<Object> caller;

  // When we're passed a JSFunction as new target, we can skip frames until that
  // specific function is seen instead of unconditionally skipping the first
  // frame.
  if (args.new_target()->IsJSFunction()) {
    mode = SKIP_UNTIL_SEEN;
    caller = args.new_target();
  }

  RETURN_RESULT_OR_FAILURE(
      isolate, ErrorUtils::Construct(isolate, args.target(),
                                     Handle<Object>::cast(args.new_target()),
                                     args.atOrUndefined(isolate, 1), mode,
                                     caller, false));
}

// static
BUILTIN(ErrorCaptureStackTrace) {
  HandleScope scope(isolate);
  Handle<Object> object_obj = args.atOrUndefined(isolate, 1);

  if (!object_obj->IsJSObject()) {
    THROW_NEW_ERROR_RETURN_FAILURE(
        isolate, NewTypeError(MessageTemplate::kInvalidArgument, object_obj));
  }

  Handle<JSObject> object = Handle<JSObject>::cast(object_obj);
  Handle<Object> caller = args.atOrUndefined(isolate, 2);
  FrameSkipMode mode = caller->IsJSFunction() ? SKIP_UNTIL_SEEN : SKIP_FIRST;

  // Collect the stack trace.

  RETURN_FAILURE_ON_EXCEPTION(isolate,
                              isolate->CaptureAndSetDetailedStackTrace(object));
  RETURN_FAILURE_ON_EXCEPTION(
      isolate, isolate->CaptureAndSetSimpleStackTrace(object, mode, caller));

  // Add the stack accessors.

  Handle<AccessorInfo> error_stack =
      Accessors::ErrorStackInfo(isolate, DONT_ENUM);

  // Explicitly check for frozen objects. Other access checks are performed by
  // the LookupIterator in SetAccessor below.
  if (!JSObject::IsExtensible(object)) {
    return isolate->Throw(*isolate->factory()->NewTypeError(
        MessageTemplate::kDefineDisallowed,
        handle(error_stack->name(), isolate)));
  }

  RETURN_FAILURE_ON_EXCEPTION(isolate,
                              JSObject::SetAccessor(object, error_stack));
  return isolate->heap()->undefined_value();
}

// ES6 section 19.5.3.4 Error.prototype.toString ( )
BUILTIN(ErrorPrototypeToString) {
  HandleScope scope(isolate);
  RETURN_RESULT_OR_FAILURE(isolate,
                           ErrorUtils::ToString(isolate, args.receiver()));
}

namespace {

Object* MakeGenericError(Isolate* isolate, BuiltinArguments args,
                         Handle<JSFunction> constructor) {
  Handle<Object> template_index = args.atOrUndefined(isolate, 1);
  Handle<Object> arg0 = args.atOrUndefined(isolate, 2);
  Handle<Object> arg1 = args.atOrUndefined(isolate, 3);
  Handle<Object> arg2 = args.atOrUndefined(isolate, 4);

  DCHECK(template_index->IsSmi());

  RETURN_RESULT_OR_FAILURE(
      isolate, ErrorUtils::MakeGenericError(isolate, constructor,
                                            Smi::ToInt(*template_index), arg0,
                                            arg1, arg2, SKIP_NONE));
}

}  // namespace

BUILTIN(MakeError) {
  HandleScope scope(isolate);
  return MakeGenericError(isolate, args, isolate->error_function());
}

BUILTIN(MakeRangeError) {
  HandleScope scope(isolate);
  return MakeGenericError(isolate, args, isolate->range_error_function());
}

BUILTIN(MakeSyntaxError) {
  HandleScope scope(isolate);
  return MakeGenericError(isolate, args, isolate->syntax_error_function());
}

BUILTIN(MakeTypeError) {
  HandleScope scope(isolate);
  return MakeGenericError(isolate, args, isolate->type_error_function());
}

BUILTIN(MakeURIError) {
  HandleScope scope(isolate);
  Handle<JSFunction> constructor = isolate->uri_error_function();
  Handle<Object> undefined = isolate->factory()->undefined_value();
  const int template_index = MessageTemplate::kURIMalformed;
  RETURN_RESULT_OR_FAILURE(
      isolate,
      ErrorUtils::MakeGenericError(isolate, constructor, template_index,
                                   undefined, undefined, undefined, SKIP_NONE));
}

}  // namespace internal
}  // namespace v8
