// Copyright 2006-2008 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.

// The infrastructure used for (localized) message reporting in V8.
//
// Note: there's a big unresolved issue about ownership of the data
// structures used by this framework.

#ifndef V8_EXECUTION_MESSAGES_H_
#define V8_EXECUTION_MESSAGES_H_

#include <memory>

#include "src/base/optional.h"
#include "src/common/message-template.h"
#include "src/handles/handles.h"

namespace v8 {
namespace internal {
namespace wasm {
class WasmCode;
}  // namespace wasm

// Forward declarations.
class AbstractCode;
class FrameArray;
class JSMessageObject;
class LookupIterator;
class PrimitiveHeapObject;
class SharedFunctionInfo;
class SourceInfo;
class WasmInstanceObject;

class V8_EXPORT_PRIVATE MessageLocation {
 public:
  // Constructors for when source positions are already known.
  // TODO(delphick): Collapse to a single constructor with a default parameter
  // when we stop using the GCC that requires this separation.
  MessageLocation(Handle<Script> script, int start_pos, int end_pos);
  MessageLocation(Handle<Script> script, int start_pos, int end_pos,
                  Handle<SharedFunctionInfo> shared);
  // Constructor for when source positions were not collected but which can be
  // reconstructed from the SharedFuncitonInfo and bytecode offset.
  MessageLocation(Handle<Script> script, Handle<SharedFunctionInfo> shared,
                  int bytecode_offset);
  MessageLocation();

  Handle<Script> script() const { return script_; }
  int start_pos() const { return start_pos_; }
  int end_pos() const { return end_pos_; }
  int bytecode_offset() const { return bytecode_offset_; }
  Handle<SharedFunctionInfo> shared() const { return shared_; }

 private:
  Handle<Script> script_;
  int start_pos_;
  int end_pos_;
  int bytecode_offset_;
  Handle<SharedFunctionInfo> shared_;
};

class StackFrameBase {
 public:
  virtual ~StackFrameBase() = default;

  virtual Handle<Object> GetReceiver() const = 0;
  virtual Handle<Object> GetFunction() const = 0;

  virtual Handle<Object> GetFileName() = 0;
  virtual Handle<PrimitiveHeapObject> GetFunctionName() = 0;
  virtual Handle<Object> GetScriptNameOrSourceUrl() = 0;
  virtual Handle<PrimitiveHeapObject> GetMethodName() = 0;
  virtual Handle<PrimitiveHeapObject> GetTypeName() = 0;
  virtual Handle<PrimitiveHeapObject> GetEvalOrigin();
  virtual Handle<PrimitiveHeapObject> GetWasmModuleName();
  virtual Handle<HeapObject> GetWasmInstance();

  // Returns the script ID if one is attached, -1 otherwise.
  int GetScriptId() const;

  virtual int GetPosition() const = 0;
  // Return 1-based line number, including line offset.
  virtual int GetLineNumber() = 0;
  // Return 1-based column number, including column offset if first line.
  virtual int GetColumnNumber() = 0;
  // Return 0-based Wasm function index. Returns -1 for non-Wasm frames.
  virtual int GetWasmFunctionIndex();

  // Returns the index of the rejected promise in the Promise combinator input,
  // or -1 if this frame is not a Promise combinator frame.
  virtual int GetPromiseIndex() const = 0;

  virtual bool IsNative() = 0;
  virtual bool IsToplevel() = 0;
  virtual bool IsEval();
  virtual bool IsAsync() const = 0;
  virtual bool IsPromiseAll() const = 0;
  virtual bool IsPromiseAny() const = 0;
  virtual bool IsConstructor() = 0;
  virtual bool IsStrict() const = 0;

  // Used to signal that the requested field is unknown.
  static const int kNone = -1;

 protected:
  StackFrameBase() = default;
  explicit StackFrameBase(Isolate* isolate) : isolate_(isolate) {}
  Isolate* isolate_;

 private:
  virtual bool HasScript() const = 0;
  virtual Handle<Script> GetScript() const = 0;
};

class JSStackFrame : public StackFrameBase {
 public:
  JSStackFrame(Isolate* isolate, Handle<Object> receiver,
               Handle<JSFunction> function, Handle<AbstractCode> code,
               int offset);
  ~JSStackFrame() override = default;

  Handle<Object> GetReceiver() const override { return receiver_; }
  Handle<Object> GetFunction() const override;

  Handle<Object> GetFileName() override;
  Handle<PrimitiveHeapObject> GetFunctionName() override;
  Handle<Object> GetScriptNameOrSourceUrl() override;
  Handle<PrimitiveHeapObject> GetMethodName() override;
  Handle<PrimitiveHeapObject> GetTypeName() override;

  int GetPosition() const override;
  int GetLineNumber() override;
  int GetColumnNumber() override;

  int GetPromiseIndex() const override;

  bool IsNative() override;
  bool IsToplevel() override;
  bool IsAsync() const override { return is_async_; }
  bool IsPromiseAll() const override { return is_promise_all_; }
  bool IsPromiseAny() const override { return is_promise_any_; }
  bool IsConstructor() override { return is_constructor_; }
  bool IsStrict() const override { return is_strict_; }

 private:
  JSStackFrame() = default;
  void FromFrameArray(Isolate* isolate, Handle<FrameArray> array, int frame_ix);

  bool HasScript() const override;
  Handle<Script> GetScript() const override;

  Handle<Object> receiver_;
  Handle<JSFunction> function_;
  Handle<AbstractCode> code_;
  int offset_;
  mutable base::Optional<int> cached_position_;

  bool is_async_ : 1;
  bool is_constructor_ : 1;
  bool is_promise_all_ : 1;
  bool is_promise_any_ : 1;
  bool is_strict_ : 1;

  friend class FrameArrayIterator;
};

class WasmStackFrame : public StackFrameBase {
 public:
  ~WasmStackFrame() override = default;

  Handle<Object> GetReceiver() const override;
  Handle<Object> GetFunction() const override;

  Handle<Object> GetFileName() override;
  Handle<PrimitiveHeapObject> GetFunctionName() override;
  Handle<Object> GetScriptNameOrSourceUrl() override;
  Handle<PrimitiveHeapObject> GetMethodName() override { return Null(); }
  Handle<PrimitiveHeapObject> GetTypeName() override { return Null(); }
  Handle<PrimitiveHeapObject> GetWasmModuleName() override;
  Handle<HeapObject> GetWasmInstance() override;

  int GetPosition() const override;
  int GetLineNumber() override { return 0; }
  int GetColumnNumber() override;
  int GetWasmFunctionIndex() override { return wasm_func_index_; }

  int GetPromiseIndex() const override { return GetPosition(); }

  bool IsNative() override { return false; }
  bool IsToplevel() override { return false; }
  bool IsAsync() const override { return false; }
  bool IsPromiseAll() const override { return false; }
  bool IsPromiseAny() const override { return false; }
  bool IsConstructor() override { return false; }
  bool IsStrict() const override { return false; }
  bool IsInterpreted() const { return code_ == nullptr; }

 protected:
  Handle<PrimitiveHeapObject> Null() const;

  bool HasScript() const override;
  Handle<Script> GetScript() const override;

  Handle<WasmInstanceObject> wasm_instance_;
  uint32_t wasm_func_index_;
  wasm::WasmCode* code_;  // null for interpreted frames.
  int offset_;

 private:
  int GetModuleOffset() const;

  WasmStackFrame() = default;
  void FromFrameArray(Isolate* isolate, Handle<FrameArray> array, int frame_ix);

  friend class FrameArrayIterator;
  friend class AsmJsWasmStackFrame;
};

class AsmJsWasmStackFrame : public WasmStackFrame {
 public:
  ~AsmJsWasmStackFrame() override = default;

  Handle<Object> GetReceiver() const override;
  Handle<Object> GetFunction() const override;

  Handle<Object> GetFileName() override;
  Handle<Object> GetScriptNameOrSourceUrl() override;

  int GetPosition() const override;
  int GetLineNumber() override;
  int GetColumnNumber() override;

 private:
  friend class FrameArrayIterator;
  AsmJsWasmStackFrame() = default;
  void FromFrameArray(Isolate* isolate, Handle<FrameArray> array, int frame_ix);

  bool is_at_number_conversion_;
};

class FrameArrayIterator {
 public:
  FrameArrayIterator(Isolate* isolate, Handle<FrameArray> array,
                     int frame_ix = 0);

  StackFrameBase* Frame();

  bool HasFrame() const;
  void Advance();

 private:
  Isolate* isolate_;

  Handle<FrameArray> array_;
  int frame_ix_;

  WasmStackFrame wasm_frame_;
  AsmJsWasmStackFrame asm_wasm_frame_;
  JSStackFrame js_frame_;
};

// Determines how stack trace collection skips frames.
enum FrameSkipMode {
  // Unconditionally skips the first frame. Used e.g. when the Error constructor
  // is called, in which case the first frame is always a BUILTIN_EXIT frame.
  SKIP_FIRST,
  // Skip all frames until a specified caller function is seen.
  SKIP_UNTIL_SEEN,
  SKIP_NONE,
};

class ErrorUtils : public AllStatic {
 public:
  // |kNone| is useful when you don't need the stack information at all, for
  // example when creating a deserialized error.
  enum class StackTraceCollection { kDetailed, kSimple, kNone };
  static MaybeHandle<JSObject> Construct(Isolate* isolate,
                                         Handle<JSFunction> target,
                                         Handle<Object> new_target,
                                         Handle<Object> message);
  static MaybeHandle<JSObject> Construct(
      Isolate* isolate, Handle<JSFunction> target, Handle<Object> new_target,
      Handle<Object> message, FrameSkipMode mode, Handle<Object> caller,
      StackTraceCollection stack_trace_collection);

  static MaybeHandle<String> ToString(Isolate* isolate, Handle<Object> recv);

  static Handle<JSObject> MakeGenericError(
      Isolate* isolate, Handle<JSFunction> constructor, MessageTemplate index,
      Handle<Object> arg0, Handle<Object> arg1, Handle<Object> arg2,
      FrameSkipMode mode);

  // Formats a textual stack trace from the given structured stack trace.
  // Note that this can call arbitrary JS code through Error.prepareStackTrace.
  static MaybeHandle<Object> FormatStackTrace(Isolate* isolate,
                                              Handle<JSObject> error,
                                              Handle<Object> stack_trace);

  static Handle<JSObject> NewIteratorError(Isolate* isolate,
                                           Handle<Object> source);
  static Handle<JSObject> NewCalledNonCallableError(Isolate* isolate,
                                                    Handle<Object> source);
  static Handle<JSObject> NewConstructedNonConstructable(Isolate* isolate,
                                                         Handle<Object> source);
  // Returns the Exception sentinel.
  static Object ThrowSpreadArgError(Isolate* isolate, MessageTemplate id,
                                    Handle<Object> object);
  // Returns the Exception sentinel.
  static Object ThrowLoadFromNullOrUndefined(Isolate* isolate,
                                             Handle<Object> object,
                                             MaybeHandle<Object> key);
};

class MessageFormatter {
 public:
  V8_EXPORT_PRIVATE static const char* TemplateString(MessageTemplate index);

  V8_EXPORT_PRIVATE static MaybeHandle<String> Format(Isolate* isolate,
                                                      MessageTemplate index,
                                                      Handle<String> arg0,
                                                      Handle<String> arg1,
                                                      Handle<String> arg2);

  static Handle<String> Format(Isolate* isolate, MessageTemplate index,
                               Handle<Object> arg0,
                               Handle<Object> arg1 = Handle<Object>(),
                               Handle<Object> arg2 = Handle<Object>());
};

// A message handler is a convenience interface for accessing the list
// of message listeners registered in an environment
class MessageHandler {
 public:
  // Returns a message object for the API to use.
  V8_EXPORT_PRIVATE static Handle<JSMessageObject> MakeMessageObject(
      Isolate* isolate, MessageTemplate type, const MessageLocation* location,
      Handle<Object> argument, Handle<FixedArray> stack_frames);

  // Report a formatted message (needs JS allocation).
  V8_EXPORT_PRIVATE static void ReportMessage(Isolate* isolate,
                                              const MessageLocation* loc,
                                              Handle<JSMessageObject> message);

  static void DefaultMessageReport(Isolate* isolate, const MessageLocation* loc,
                                   Handle<Object> message_obj);
  static Handle<String> GetMessage(Isolate* isolate, Handle<Object> data);
  static std::unique_ptr<char[]> GetLocalizedMessage(Isolate* isolate,
                                                     Handle<Object> data);

 private:
  static void ReportMessageNoExceptions(Isolate* isolate,
                                        const MessageLocation* loc,
                                        Handle<Object> message_obj,
                                        v8::Local<v8::Value> api_exception_obj);
};

}  // namespace internal
}  // namespace v8

#endif  // V8_EXECUTION_MESSAGES_H_
