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

#ifndef V8_INSPECTOR_V8_DEBUGGER_H_
#define V8_INSPECTOR_V8_DEBUGGER_H_

#include <list>
#include <memory>
#include <unordered_map>
#include <unordered_set>
#include <vector>

#include "src/base/macros.h"
#include "src/inspector/inspected-context.h"
#include "src/inspector/protocol/Debugger.h"
#include "src/inspector/protocol/Forward.h"
#include "src/inspector/protocol/Runtime.h"
#include "src/inspector/v8-debugger-script.h"

#include "include/v8-inspector.h"

namespace v8_inspector {

class AsyncStackTrace;
class StackFrame;
class V8Debugger;
class V8DebuggerAgentImpl;
class V8InspectorImpl;
class V8StackTraceImpl;
struct V8StackTraceId;

enum class WrapMode { kForceValue, kNoPreview, kWithPreview };

using protocol::Response;
using TerminateExecutionCallback =
    protocol::Runtime::Backend::TerminateExecutionCallback;

// This debugger id tries to be unique by generating two random
// numbers, which should most likely avoid collisions.
// Debugger id has a 1:1 mapping to context group. It is used to
// attribute stack traces to a particular debugging, when doing any
// cross-debugger operations (e.g. async step in).
// See also Runtime.UniqueDebuggerId in the protocol.
class V8DebuggerId {
 public:
  V8DebuggerId() = default;
  explicit V8DebuggerId(std::pair<int64_t, int64_t>);
  explicit V8DebuggerId(const String16&);
  V8DebuggerId(const V8DebuggerId&) V8_NOEXCEPT = default;
  ~V8DebuggerId() = default;

  static V8DebuggerId generate(v8::Isolate*);

  String16 toString() const;
  bool isValid() const;
  std::pair<int64_t, int64_t> pair() const;

 private:
  int64_t m_first = 0;
  int64_t m_second = 0;
};

class V8Debugger : public v8::debug::DebugDelegate,
                   public v8::debug::AsyncEventDelegate {
 public:
  V8Debugger(v8::Isolate*, V8InspectorImpl*);
  ~V8Debugger() override;

  bool enabled() const;
  v8::Isolate* isolate() const { return m_isolate; }

  void setBreakpointsActive(bool);

  v8::debug::ExceptionBreakState getPauseOnExceptionsState();
  void setPauseOnExceptionsState(v8::debug::ExceptionBreakState);
  bool canBreakProgram();
  void breakProgram(int targetContextGroupId);
  void interruptAndBreak(int targetContextGroupId);
  void continueProgram(int targetContextGroupId,
                       bool terminateOnResume = false);
  void breakProgramOnAssert(int targetContextGroupId);

  void setPauseOnNextCall(bool, int targetContextGroupId);
  void stepIntoStatement(int targetContextGroupId, bool breakOnAsyncCall);
  void stepOverStatement(int targetContextGroupId);
  void stepOutOfFunction(int targetContextGroupId);

  void terminateExecution(std::unique_ptr<TerminateExecutionCallback> callback);

  Response continueToLocation(int targetContextGroupId,
                              V8DebuggerScript* script,
                              std::unique_ptr<protocol::Debugger::Location>,
                              const String16& targetCallFramess);

  // Each script inherits debug data from v8::Context where it has been
  // compiled.
  // Only scripts whose debug data matches |contextGroupId| will be reported.
  // Passing 0 will result in reporting all scripts.
  std::vector<std::unique_ptr<V8DebuggerScript>> getCompiledScripts(
      int contextGroupId, V8DebuggerAgentImpl* agent);
  void enable();
  void disable();

  bool isPaused() const { return m_pausedContextGroupId; }
  bool isPausedInContextGroup(int contextGroupId) const;

  int maxAsyncCallChainDepth() { return m_maxAsyncCallStackDepth; }
  void setAsyncCallStackDepth(V8DebuggerAgentImpl*, int);

  std::shared_ptr<AsyncStackTrace> currentAsyncParent();
  V8StackTraceId currentExternalParent();

  std::shared_ptr<StackFrame> symbolize(v8::Local<v8::StackFrame> v8Frame);

  std::unique_ptr<V8StackTraceImpl> createStackTrace(v8::Local<v8::StackTrace>);
  std::unique_ptr<V8StackTraceImpl> captureStackTrace(bool fullStack);

  v8::MaybeLocal<v8::Array> internalProperties(v8::Local<v8::Context>,
                                               v8::Local<v8::Value>);

  v8::Local<v8::Array> queryObjects(v8::Local<v8::Context> context,
                                    v8::Local<v8::Object> prototype);

  void asyncTaskScheduled(const StringView& taskName, void* task,
                          bool recurring);
  void asyncTaskCanceled(void* task);
  void asyncTaskStarted(void* task);
  void asyncTaskFinished(void* task);
  void allAsyncTasksCanceled();

  V8StackTraceId storeCurrentStackTrace(const StringView& description);
  void externalAsyncTaskStarted(const V8StackTraceId& parent);
  void externalAsyncTaskFinished(const V8StackTraceId& parent);

  uintptr_t storeStackTrace(std::shared_ptr<AsyncStackTrace> stack);

  void muteScriptParsedEvents();
  void unmuteScriptParsedEvents();

  V8InspectorImpl* inspector() { return m_inspector; }

  void setMaxAsyncTaskStacksForTest(int limit);
  void dumpAsyncTaskStacksStateForTest();

  V8DebuggerId debuggerIdFor(int contextGroupId);
  std::shared_ptr<AsyncStackTrace> stackTraceFor(int contextGroupId,
                                                 const V8StackTraceId& id);

  void reportTermination();

 private:
  bool addInternalObject(v8::Local<v8::Context> context,
                         v8::Local<v8::Object> object,
                         V8InternalValueType type);

  void clearContinueToLocation();
  bool shouldContinueToCurrentLocation();

  static size_t nearHeapLimitCallback(void* data, size_t current_heap_limit,
                                      size_t initial_heap_limit);
  static void terminateExecutionCompletedCallback(v8::Isolate* isolate);
  static void terminateExecutionCompletedCallbackIgnoringData(
      v8::Isolate* isolate, void*);
  void handleProgramBreak(
      v8::Local<v8::Context> pausedContext, v8::Local<v8::Value> exception,
      const std::vector<v8::debug::BreakpointId>& hitBreakpoints,
      v8::debug::ExceptionType exception_type = v8::debug::kException,
      bool isUncaught = false);

  enum ScopeTargetKind {
    FUNCTION,
    GENERATOR,
  };
  v8::MaybeLocal<v8::Value> getTargetScopes(v8::Local<v8::Context>,
                                            v8::Local<v8::Value>,
                                            ScopeTargetKind);

  v8::MaybeLocal<v8::Value> functionScopes(v8::Local<v8::Context>,
                                           v8::Local<v8::Function>);
  v8::MaybeLocal<v8::Value> generatorScopes(v8::Local<v8::Context>,
                                            v8::Local<v8::Value>);
  v8::MaybeLocal<v8::Array> collectionsEntries(v8::Local<v8::Context> context,
                                               v8::Local<v8::Value> value);

  void asyncTaskScheduledForStack(const String16& taskName, void* task,
                                  bool recurring);
  void asyncTaskCanceledForStack(void* task);
  void asyncTaskStartedForStack(void* task);
  void asyncTaskFinishedForStack(void* task);

  void asyncTaskCandidateForStepping(void* task);
  void asyncTaskStartedForStepping(void* task);
  void asyncTaskFinishedForStepping(void* task);
  void asyncTaskCanceledForStepping(void* task);

  // v8::debug::DebugEventListener implementation.
  void AsyncEventOccurred(v8::debug::DebugAsyncActionType type, int id,
                          bool isBlackboxed) override;
  void ScriptCompiled(v8::Local<v8::debug::Script> script, bool is_live_edited,
                      bool has_compile_error) override;
  void BreakProgramRequested(
      v8::Local<v8::Context> paused_context,
      const std::vector<v8::debug::BreakpointId>& break_points_hit) override;
  void ExceptionThrown(v8::Local<v8::Context> paused_context,
                       v8::Local<v8::Value> exception,
                       v8::Local<v8::Value> promise, bool is_uncaught,
                       v8::debug::ExceptionType exception_type) override;
  bool IsFunctionBlackboxed(v8::Local<v8::debug::Script> script,
                            const v8::debug::Location& start,
                            const v8::debug::Location& end) override;

  bool ShouldBeSkipped(v8::Local<v8::debug::Script> script, int line,
                       int column) override;

  int currentContextGroupId();
  bool asyncStepOutOfFunction(int targetContextGroupId, bool onlyAtReturn);

  bool hasScheduledBreakOnNextFunctionCall() const;

  v8::Isolate* m_isolate;
  V8InspectorImpl* m_inspector;
  int m_enableCount;

  int m_breakpointsActiveCount = 0;
  int m_ignoreScriptParsedEventsCounter;
  size_t m_originalHeapLimit = 0;
  bool m_scheduledOOMBreak = false;
  bool m_scheduledAssertBreak = false;
  int m_targetContextGroupId = 0;
  int m_pausedContextGroupId = 0;
  int m_continueToLocationBreakpointId;
  String16 m_continueToLocationTargetCallFrames;
  std::unique_ptr<V8StackTraceImpl> m_continueToLocationStack;

  using AsyncTaskToStackTrace =
      std::unordered_map<void*, std::weak_ptr<AsyncStackTrace>>;
  AsyncTaskToStackTrace m_asyncTaskStacks;
  std::unordered_set<void*> m_recurringTasks;

  int m_maxAsyncCallStacks;
  int m_maxAsyncCallStackDepth;

  std::vector<void*> m_currentTasks;
  std::vector<std::shared_ptr<AsyncStackTrace>> m_currentAsyncParent;
  std::vector<V8StackTraceId> m_currentExternalParent;

  void collectOldAsyncStacksIfNeeded();
  int m_asyncStacksCount = 0;
  // V8Debugger owns all the async stacks, while most of the other references
  // are weak, which allows to collect some stacks when there are too many.
  std::list<std::shared_ptr<AsyncStackTrace>> m_allAsyncStacks;

  std::unordered_map<V8DebuggerAgentImpl*, int> m_maxAsyncCallStackDepthMap;
  void* m_taskWithScheduledBreak = nullptr;

  // If any of the following three is true, we schedule pause on next JS
  // execution using SetBreakOnNextFunctionCall.
  bool m_externalAsyncTaskPauseRequested = false;       // External async task.
  bool m_taskWithScheduledBreakPauseRequested = false;  // Local async task.
  bool m_pauseOnNextCallRequested = false;  // setPauseOnNextCall API call.

  v8::debug::ExceptionBreakState m_pauseOnExceptionsState;
  // Whether we should pause on async call execution (if any) while stepping in.
  // See Debugger.stepInto for details.
  bool m_pauseOnAsyncCall = false;

  using StackTraceIdToStackTrace =
      std::unordered_map<uintptr_t, std::weak_ptr<AsyncStackTrace>>;
  StackTraceIdToStackTrace m_storedStackTraces;
  uintptr_t m_lastStackTraceId = 0;

  std::unordered_map<int, V8DebuggerId> m_contextGroupIdToDebuggerId;

  std::unique_ptr<TerminateExecutionCallback> m_terminateExecutionCallback;

  DISALLOW_COPY_AND_ASSIGN(V8Debugger);
};

}  // namespace v8_inspector

#endif  // V8_INSPECTOR_V8_DEBUGGER_H_
