// Copyright 2017 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/debug/debug-stack-trace-iterator.h"

#include "src/api/api-inl.h"
#include "src/debug/debug-evaluate.h"
#include "src/debug/debug-scope-iterator.h"
#include "src/debug/debug.h"
#include "src/debug/liveedit.h"
#include "src/execution/frames-inl.h"
#include "src/execution/isolate.h"

namespace v8 {

std::unique_ptr<debug::StackTraceIterator> debug::StackTraceIterator::Create(
    v8::Isolate* isolate, int index) {
  return std::unique_ptr<debug::StackTraceIterator>(
      new internal::DebugStackTraceIterator(
          reinterpret_cast<internal::Isolate*>(isolate), index));
}

namespace internal {

DebugStackTraceIterator::DebugStackTraceIterator(Isolate* isolate, int index)
    : isolate_(isolate),
      iterator_(isolate, isolate->debug()->break_frame_id()),
      is_top_frame_(true) {
  if (iterator_.done()) return;
  std::vector<FrameSummary> frames;
  iterator_.frame()->Summarize(&frames);
  inlined_frame_index_ = static_cast<int>(frames.size());
  Advance();
  for (; !Done() && index > 0; --index) Advance();
}

DebugStackTraceIterator::~DebugStackTraceIterator() = default;

bool DebugStackTraceIterator::Done() const { return iterator_.done(); }

void DebugStackTraceIterator::Advance() {
  while (true) {
    --inlined_frame_index_;
    for (; inlined_frame_index_ >= 0; --inlined_frame_index_) {
      // Omit functions from native and extension scripts.
      if (FrameSummary::Get(iterator_.frame(), inlined_frame_index_)
              .is_subject_to_debugging()) {
        break;
      }
      is_top_frame_ = false;
    }
    if (inlined_frame_index_ >= 0) {
      frame_inspector_.reset(new FrameInspector(
          iterator_.frame(), inlined_frame_index_, isolate_));
      break;
    }
    is_top_frame_ = false;
    frame_inspector_.reset();
    iterator_.Advance();
    if (iterator_.done()) break;
    std::vector<FrameSummary> frames;
    iterator_.frame()->Summarize(&frames);
    inlined_frame_index_ = static_cast<int>(frames.size());
  }
}

int DebugStackTraceIterator::GetContextId() const {
  DCHECK(!Done());
  Handle<Object> context = frame_inspector_->GetContext();
  if (context->IsContext()) {
    Object value = Context::cast(*context).native_context().debug_context_id();
    if (value.IsSmi()) return Smi::ToInt(value);
  }
  return 0;
}

v8::MaybeLocal<v8::Value> DebugStackTraceIterator::GetReceiver() const {
  DCHECK(!Done());
  if (frame_inspector_->IsJavaScript() &&
      frame_inspector_->GetFunction()->shared().kind() == kArrowFunction) {
    // FrameInspector is not able to get receiver for arrow function.
    // So let's try to fetch it using same logic as is used to retrieve 'this'
    // during DebugEvaluate::Local.
    Handle<JSFunction> function = frame_inspector_->GetFunction();
    Handle<Context> context(function->context(), isolate_);
    // Arrow function defined in top level function without references to
    // variables may have NativeContext as context.
    if (!context->IsFunctionContext()) return v8::MaybeLocal<v8::Value>();
    ScopeIterator scope_iterator(isolate_, frame_inspector_.get(),
                                 ScopeIterator::COLLECT_NON_LOCALS);
    // We lookup this variable in function context only when it is used in arrow
    // function otherwise V8 can optimize it out.
    if (!scope_iterator.GetNonLocals()->Has(isolate_,
                                            isolate_->factory()->this_string()))
      return v8::MaybeLocal<v8::Value>();
    DisallowHeapAllocation no_gc;
    VariableMode mode;
    InitializationFlag flag;
    MaybeAssignedFlag maybe_assigned_flag;
    RequiresBrandCheckFlag requires_brand_check;
    int slot_index = ScopeInfo::ContextSlotIndex(
        context->scope_info(), ReadOnlyRoots(isolate_->heap()).this_string(),
        &mode, &flag, &maybe_assigned_flag, &requires_brand_check);
    if (slot_index < 0) return v8::MaybeLocal<v8::Value>();
    Handle<Object> value = handle(context->get(slot_index), isolate_);
    if (value->IsTheHole(isolate_)) return v8::MaybeLocal<v8::Value>();
    return Utils::ToLocal(value);
  }
  Handle<Object> value = frame_inspector_->GetReceiver();
  if (value.is_null() || (value->IsSmi() || !value->IsTheHole(isolate_))) {
    return Utils::ToLocal(value);
  }
  return v8::MaybeLocal<v8::Value>();
}

v8::Local<v8::Value> DebugStackTraceIterator::GetReturnValue() const {
  DCHECK(!Done());
  if (frame_inspector_ && frame_inspector_->IsWasm()) {
    return v8::Local<v8::Value>();
  }
  bool is_optimized = iterator_.frame()->is_optimized();
  if (is_optimized || !is_top_frame_ ||
      !isolate_->debug()->IsBreakAtReturn(iterator_.javascript_frame())) {
    return v8::Local<v8::Value>();
  }
  return Utils::ToLocal(isolate_->debug()->return_value_handle());
}

v8::Local<v8::String> DebugStackTraceIterator::GetFunctionDebugName() const {
  DCHECK(!Done());
  return Utils::ToLocal(frame_inspector_->GetFunctionName());
}

v8::Local<v8::debug::Script> DebugStackTraceIterator::GetScript() const {
  DCHECK(!Done());
  Handle<Object> value = frame_inspector_->GetScript();
  if (!value->IsScript()) return v8::Local<v8::debug::Script>();
  return ToApiHandle<debug::Script>(Handle<Script>::cast(value));
}

debug::Location DebugStackTraceIterator::GetSourceLocation() const {
  DCHECK(!Done());
  v8::Local<v8::debug::Script> script = GetScript();
  if (script.IsEmpty()) return v8::debug::Location();
  return script->GetSourceLocation(frame_inspector_->GetSourcePosition());
}

v8::Local<v8::Function> DebugStackTraceIterator::GetFunction() const {
  DCHECK(!Done());
  if (!frame_inspector_->IsJavaScript()) return v8::Local<v8::Function>();
  return Utils::ToLocal(frame_inspector_->GetFunction());
}

std::unique_ptr<v8::debug::ScopeIterator>
DebugStackTraceIterator::GetScopeIterator() const {
  DCHECK(!Done());
  StandardFrame* frame = iterator_.frame();
  if (frame->is_wasm_interpreter_entry()) {
    return std::unique_ptr<v8::debug::ScopeIterator>(new DebugWasmScopeIterator(
        isolate_, iterator_.frame(), inlined_frame_index_));
  }
  return std::unique_ptr<v8::debug::ScopeIterator>(
      new DebugScopeIterator(isolate_, frame_inspector_.get()));
}

bool DebugStackTraceIterator::Restart() {
  DCHECK(!Done());
  if (iterator_.is_wasm()) return false;
  return LiveEdit::RestartFrame(iterator_.javascript_frame());
}

v8::MaybeLocal<v8::Value> DebugStackTraceIterator::Evaluate(
    v8::Local<v8::String> source, bool throw_on_side_effect) {
  DCHECK(!Done());
  Handle<Object> value;
  i::SafeForInterruptsScope safe_for_interrupt_scope(isolate_);
  if (!DebugEvaluate::Local(isolate_, iterator_.frame()->id(),
                            inlined_frame_index_, Utils::OpenHandle(*source),
                            throw_on_side_effect)
           .ToHandle(&value)) {
    isolate_->OptionalRescheduleException(false);
    return v8::MaybeLocal<v8::Value>();
  }
  return Utils::ToLocal(value);
}
}  // namespace internal
}  // namespace v8
