// 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/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));

  // Eagerly format the stack trace and set the stack property.

  Handle<Object> stack_trace =
      isolate->CaptureSimpleStackTrace(object, mode, caller);
  if (!stack_trace->IsJSArray()) return isolate->heap()->undefined_value();

  Handle<Object> formatted_stack_trace;
  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
      isolate, formatted_stack_trace,
      ErrorUtils::FormatStackTrace(isolate, object, stack_trace));

  PropertyDescriptor desc;
  desc.set_configurable(true);
  desc.set_writable(true);
  desc.set_value(formatted_stack_trace);
  Maybe<bool> status = JSReceiver::DefineOwnProperty(
      isolate, object, isolate->factory()->stack_string(), &desc,
      Object::THROW_ON_ERROR);
  if (!status.IsJust()) return isolate->heap()->exception();
  CHECK(status.FromJust());
  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::cast(*template_index)->value(),
                                            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
