// Copyright 2021 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-interface.h"

#include <stdint.h>

#include <span>
#include <vector>

#include "include/v8-function.h"
#include "src/api/api-inl.h"
#include "src/base/logging.h"
#include "src/base/utils/random-number-generator.h"
#include "src/codegen/compiler.h"
#include "src/codegen/script-details.h"
#include "src/date/date.h"
#include "src/debug/debug-coverage.h"
#include "src/debug/debug-evaluate.h"
#include "src/debug/debug-property-iterator.h"
#include "src/debug/debug-stack-trace-iterator.h"
#include "src/debug/debug.h"
#include "src/execution/vm-state-inl.h"
#include "src/heap/heap.h"
#include "src/objects/js-generator-inl.h"
#include "src/objects/script-inl.h"
#include "src/objects/shared-function-info-inl.h"
#include "src/objects/templates-inl.h"
#include "src/profiler/heap-profiler.h"
#include "src/strings/string-builder-inl.h"

#if V8_ENABLE_WEBASSEMBLY
#include "src/debug/debug-wasm-objects-inl.h"
#include "src/wasm/wasm-disassembler.h"
#include "src/wasm/wasm-engine.h"
#include "src/wasm/wasm-objects-inl.h"
#endif  // V8_ENABLE_WEBASSEMBLY

namespace v8 {
namespace debug {

void SetContextId(Local<Context> context, int id) {
  auto v8_context = Utils::OpenDirectHandle(*context);
  auto* i_isolate = i::Isolate::Current();
  i::DisallowJavascriptExecutionDebugOnly no_execution(i_isolate);
  i::DisallowExceptionsDebugOnly no_exceptions(i_isolate);
  v8_context->set_debug_context_id(i::Smi::FromInt(id));
}

int GetContextId(Local<Context> context) {
  auto v8_context = Utils::OpenDirectHandle(*context);
  auto* i_isolate = i::Isolate::Current();
  i::DisallowJavascriptExecutionDebugOnly no_execution(i_isolate);
  i::DisallowExceptionsDebugOnly no_exceptions(i_isolate);
  i::Tagged<i::Object> value = v8_context->debug_context_id();
  return (IsSmi(value)) ? i::Smi::ToInt(value) : 0;
}

void SetInspector(Isolate* isolate, v8_inspector::V8Inspector* inspector) {
  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
  i::DisallowJavascriptExecutionDebugOnly no_execution(i_isolate);
  i::DisallowExceptionsDebugOnly no_exceptions(i_isolate);
  if (inspector == nullptr) {
    i_isolate->set_inspector(nullptr);
  } else {
    i_isolate->set_inspector(inspector);
  }
}

v8_inspector::V8Inspector* GetInspector(Isolate* isolate) {
  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
  i::DisallowJavascriptExecutionDebugOnly no_execution(i_isolate);
  i::DisallowExceptionsDebugOnly no_exceptions(i_isolate);
  return i_isolate->inspector();
}

namespace {

i::Handle<i::String> GetBigIntStringPresentationHandle(
    i::Isolate* i_isolate, i::DirectHandle<i::BigInt> i_bigint) {
  // For large BigInts computing the decimal string representation
  // can take a long time, so we go with hexadecimal in that case.
  int radix = (i_bigint->Words64Count() > 100 * 1000) ? 16 : 10;
  i::Handle<i::String> string_value =
      i::BigInt::ToString(i_isolate, i_bigint, radix, i::kDontThrow)
          .ToHandleChecked();
  if (radix == 16) {
    if (i_bigint->IsNegative()) {
      string_value =
          i_isolate->factory()
              ->NewConsString(
                  i_isolate->factory()->NewStringFromAsciiChecked("-0x"),
                  i_isolate->factory()->NewProperSubString(
                      string_value, 1, string_value->length() - 1))
              .ToHandleChecked();
    } else {
      string_value =
          i_isolate->factory()
              ->NewConsString(
                  i_isolate->factory()->NewStringFromAsciiChecked("0x"),
                  string_value)
              .ToHandleChecked();
    }
  }
  return string_value;
}

}  // namespace

Local<String> GetBigIntStringValue(Isolate* isolate, Local<BigInt> bigint) {
  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
  EnterV8NoScriptNoExceptionScope api_scope(i_isolate);
  i::DirectHandle<i::BigInt> i_bigint = Utils::OpenDirectHandle(*bigint);

  i::DirectHandle<i::String> string_value =
      GetBigIntStringPresentationHandle(i_isolate, i_bigint);
  return Utils::ToLocal(string_value);
}

Local<String> GetBigIntDescription(Isolate* isolate, Local<BigInt> bigint) {
  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
  EnterV8NoScriptNoExceptionScope api_scope(i_isolate);
  i::DirectHandle<i::BigInt> i_bigint = Utils::OpenDirectHandle(*bigint);

  i::Handle<i::String> string_value =
      GetBigIntStringPresentationHandle(i_isolate, i_bigint);

  i::DirectHandle<i::String> description =
      i_isolate->factory()
          ->NewConsString(string_value, i_isolate->factory()->n_string())
          .ToHandleChecked();
  return Utils::ToLocal(description);
}

Local<String> GetDateDescription(Local<Date> date) {
  auto receiver = Utils::OpenDirectHandle(*date);
  auto jsdate = i::Cast<i::JSDate>(receiver);
  i::Isolate* i_isolate = i::Isolate::Current();
  EnterV8NoScriptNoExceptionScope api_scope(i_isolate);
  auto buffer = i::ToDateString(jsdate->value(), i_isolate->date_cache(),
                                i::ToDateStringMode::kLocalDateAndTime);
  return Utils::ToLocal(i_isolate->factory()
                            ->NewStringFromUtf8(base::VectorOf(buffer))
                            .ToHandleChecked());
}

Local<String> GetFunctionDescription(Local<Function> function) {
  auto receiver = Utils::OpenHandle(*function);
  auto i_isolate = i::Isolate::Current();
  EnterV8NoScriptNoExceptionScope api_scope(i_isolate);
  if (IsJSBoundFunction(*receiver)) {
    return Utils::ToLocal(i::JSBoundFunction::ToString(
        i_isolate, i::Cast<i::JSBoundFunction>(receiver)));
  }
  if (IsJSFunction(*receiver)) {
    auto js_function = i::Cast<i::JSFunction>(receiver);
#if V8_ENABLE_WEBASSEMBLY
    if (js_function->shared()->HasWasmExportedFunctionData(i_isolate)) {
      i::DirectHandle<i::WasmExportedFunctionData> function_data(
          js_function->shared()->wasm_exported_function_data(), i_isolate);
      int func_index = function_data->function_index();
      i::DirectHandle<i::WasmTrustedInstanceData> instance_data(
          function_data->instance_data(), i_isolate);
      auto debug_name =
          i::GetWasmFunctionDebugName(i_isolate, instance_data, func_index);
      i::IncrementalStringBuilder builder(i_isolate);
      builder.AppendCStringLiteral("function ");
      builder.AppendString(debug_name);
      builder.AppendCStringLiteral("() { [native code] }");
      return Utils::ToLocal(builder.Finish().ToHandleChecked());
    }
#endif  // V8_ENABLE_WEBASSEMBLY
    return Utils::ToLocal(i::JSFunction::ToString(i_isolate, js_function));
  }
  return Utils::ToLocal(i_isolate->factory()->function_native_code_string());
}

void SetBreakOnNextFunctionCall(Isolate* isolate) {
  auto i_isolate = reinterpret_cast<i::Isolate*>(isolate);
  i::DisallowJavascriptExecutionDebugOnly no_execution(i_isolate);
  i::DisallowExceptionsDebugOnly no_exceptions(i_isolate);
  i_isolate->debug()->SetBreakOnNextFunctionCall();
}

void ClearBreakOnNextFunctionCall(Isolate* isolate) {
  auto i_isolate = reinterpret_cast<i::Isolate*>(isolate);
  i::DisallowJavascriptExecutionDebugOnly no_execution(i_isolate);
  i::DisallowExceptionsDebugOnly no_exceptions(i_isolate);
  i_isolate->debug()->ClearBreakOnNextFunctionCall();
}

MaybeLocal<Array> GetInternalProperties(Isolate* v8_isolate,
                                        Local<Value> value) {
  i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
  EnterV8NoScriptNoExceptionScope api_scope(isolate);
  i::DirectHandle<i::Object> val = Utils::OpenDirectHandle(*value);
  i::DirectHandle<i::JSArray> result;
  if (!i::Runtime::GetInternalProperties(isolate, val).ToHandle(&result)) {
    return MaybeLocal<Array>();
  }
  return Utils::ToLocal(result);
}

namespace {

using FlagFilter = std::function<bool(i::IsStaticFlag)>;
using VariableModeFilter = std::function<bool(i::VariableMode)>;
using ContextLocalIterator = std::function<void(
    i::VariableMode, i::Handle<i::String>, i::Handle<i::Object>)>;

void ForEachContextLocal(i::Isolate* isolate,
                         i::DirectHandle<i::Context> context,
                         const VariableModeFilter& var_mode_filter,
                         const FlagFilter& flag_filter,
                         const ContextLocalIterator& context_local_it) {
  i::DisallowJavascriptExecutionDebugOnly no_execution(isolate);
  i::DisallowExceptionsDebugOnly no_exceptions(isolate);
  i::DirectHandle<i::ScopeInfo> scope_info(context->scope_info(), isolate);
  for (auto it : i::ScopeInfo::IterateLocalNames(scope_info)) {
    i::Handle<i::String> name(it->name(), isolate);
    i::VariableMode mode = scope_info->ContextLocalMode(it->index());
    if (!var_mode_filter(mode)) {
      continue;
    }
    i::IsStaticFlag flag = scope_info->ContextLocalIsStaticFlag(it->index());
    if (!flag_filter(flag)) {
      continue;
    }
    int context_index = scope_info->ContextHeaderLength() + it->index();
    i::Handle<i::Object> slot_value(context->GetNoCell(context_index), isolate);
    context_local_it(mode, name, slot_value);
  }
}

}  // namespace

bool GetPrivateMembers(Local<Context> context, Local<Object> object, int filter,
                       LocalVector<Value>* names_out,
                       LocalVector<Value>* values_out) {
  i::Isolate* isolate = i::Isolate::Current();
  ApiRuntimeCallStatsScope rcs_scope(
      isolate, i::RuntimeCallCounterId::kAPI_debug_GetPrivateMembers);
  EnterV8NoScriptNoExceptionScope api_scope(isolate);

  bool include_methods =
      filter & static_cast<int>(PrivateMemberFilter::kPrivateMethods);
  bool include_fields =
      filter & static_cast<int>(PrivateMemberFilter::kPrivateFields);
  bool include_accessors =
      filter & static_cast<int>(PrivateMemberFilter::kPrivateAccessors);
  bool include_methods_or_accessors = include_methods || include_accessors;

  auto var_mode_filter =
      include_methods
          ? (include_accessors ? i::IsPrivateMethodOrAccessorVariableMode
                               : i::IsPrivateMethodVariableMode)
          : i::IsPrivateAccessorVariableMode;
  auto constexpr instance_filter = [](i::IsStaticFlag flag) {
    return flag == i::IsStaticFlag::kNotStatic;
  };
  auto constexpr static_filter = [](i::IsStaticFlag flag) {
    return flag == i::IsStaticFlag::kStatic;
  };

  i::DirectHandle<i::JSReceiver> receiver = Utils::OpenDirectHandle(*object);

  i::PropertyFilter key_filter =
      static_cast<i::PropertyFilter>(i::PropertyFilter::PRIVATE_NAMES_ONLY);
  i::DirectHandle<i::FixedArray> keys;
  ASSIGN_RETURN_ON_EXCEPTION_VALUE(
      isolate, keys,
      i::KeyAccumulator::GetKeys(isolate, receiver,
                                 i::KeyCollectionMode::kOwnOnly, key_filter,
                                 i::GetKeysConversion::kConvertToString),
      false);

  // Estimate number of private fields and private instance methods/accessors.
  int private_entries_count = 0;
  auto count_private_entry =
      [&](i::VariableMode mode, i::DirectHandle<i::String>,
          i::DirectHandle<i::Object>) { private_entries_count++; };
  uint32_t keys_len = keys->ulength().value();
  for (uint32_t i = 0; i < keys_len; ++i) {
    // Exclude the private brand symbols.
    i::DirectHandle<i::Symbol> key(i::Cast<i::Symbol>(keys->get(i)), isolate);
    if (key->is_private_brand()) {
      if (include_methods_or_accessors) {
        i::DirectHandle<i::Object> value;
        ASSIGN_RETURN_ON_EXCEPTION_VALUE(
            isolate, value, i::Object::GetProperty(isolate, receiver, key),
            false);

        i::DirectHandle<i::Context> value_context(i::Cast<i::Context>(*value),
                                                  isolate);
        ForEachContextLocal(isolate, value_context, var_mode_filter,
                            instance_filter, count_private_entry);
      }
    } else if (include_fields) {
      private_entries_count++;
    }
  }

  // Estimate number of static private methods/accessors for classes.
  bool has_static_private_methods_or_accessors = false;
  if (include_methods_or_accessors) {
    if (IsJSFunction(*receiver)) {
      i::DirectHandle<i::JSFunction> func(i::Cast<i::JSFunction>(*receiver),
                                          isolate);
      i::DirectHandle<i::SharedFunctionInfo> shared(func->shared(), isolate);
      if (shared->is_class_constructor() &&
          shared->has_static_private_methods_or_accessors()) {
        has_static_private_methods_or_accessors = true;
        i::DirectHandle<i::Context> func_context(func->context(), isolate);
        ForEachContextLocal(isolate, func_context, var_mode_filter,
                            static_filter, count_private_entry);
      }
    }
  }

  DCHECK(names_out->empty());
  names_out->reserve(private_entries_count);
  DCHECK(values_out->empty());
  values_out->reserve(private_entries_count);

  auto add_private_entry = [&](i::VariableMode mode,
                               i::DirectHandle<i::String> name,
                               i::DirectHandle<i::Object> value) {
    DCHECK_IMPLIES(mode == i::VariableMode::kPrivateMethod,
                   IsJSFunction(*value));
    DCHECK_IMPLIES(mode != i::VariableMode::kPrivateMethod,
                   IsAccessorPair(*value));
    names_out->push_back(Utils::ToLocal(name));
    values_out->push_back(Utils::ToLocal(value));
  };
  if (has_static_private_methods_or_accessors) {
    i::DirectHandle<i::Context> receiver_context(
        i::Cast<i::JSFunction>(*receiver)->context(), isolate);
    ForEachContextLocal(isolate, receiver_context, var_mode_filter,
                        static_filter, add_private_entry);
  }

  for (uint32_t i = 0; i < keys_len; ++i) {
    i::DirectHandle<i::Object> obj_key(keys->get(i), isolate);
    i::DirectHandle<i::Symbol> key(i::Cast<i::Symbol>(*obj_key), isolate);
    CHECK(key->is_any_private_name());
    i::DirectHandle<i::Object> value;
    ASSIGN_RETURN_ON_EXCEPTION_VALUE(
        isolate, value, i::Object::GetProperty(isolate, receiver, key), false);
    if (key->is_private_brand()) {
      if (include_methods_or_accessors) {
        DCHECK(IsContext(*value));
        i::DirectHandle<i::Context> value_context(i::Cast<i::Context>(*value),
                                                  isolate);
        ForEachContextLocal(isolate, value_context, var_mode_filter,
                            instance_filter, add_private_entry);
      }
    } else if (include_fields) {  // Private fields
      i::DirectHandle<i::String> name(
          i::Cast<i::String>(i::Cast<i::Symbol>(*key)->description()), isolate);
      names_out->push_back(Utils::ToLocal(name));
      values_out->push_back(Utils::ToLocal(value));
    }
  }

  DCHECK_EQ(names_out->size(), values_out->size());
  DCHECK_LE(names_out->size(), private_entries_count);
  return true;
}

MaybeLocal<Context> GetCreationContext(Local<Object> value) {
  if (IsJSGlobalProxy(*Utils::OpenDirectHandle(*value))) {
    return MaybeLocal<Context>();
  }
  START_ALLOW_USE_DEPRECATED();
  return value->GetCreationContext();
  END_ALLOW_USE_DEPRECATED();
}

void ChangeBreakOnException(Isolate* isolate, ExceptionBreakState type) {
  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
  i::DisallowJavascriptExecutionDebugOnly no_execution(i_isolate);
  i::DisallowExceptionsDebugOnly no_exceptions(i_isolate);
  i_isolate->debug()->ChangeBreakOnException(
      i::BreakCaughtException,
      type == BreakOnCaughtException || type == BreakOnAnyException);
  i_isolate->debug()->ChangeBreakOnException(
      i::BreakUncaughtException,
      type == BreakOnUncaughtException || type == BreakOnAnyException);
}

void SetBreakPointsActive(Isolate* v8_isolate, bool is_active) {
  i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
  EnterV8NoScriptNoExceptionScope api_scope(isolate);
  isolate->debug()->set_break_points_active(is_active);
}

void PrepareStep(Isolate* v8_isolate, StepAction action) {
  i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
  EnterV8BasicScope api_scope(isolate);
  CHECK(isolate->debug()->CheckExecutionState());
  // Clear all current stepping setup.
  isolate->debug()->ClearStepping();
  // Prepare step.
  isolate->debug()->PrepareStep(static_cast<i::StepAction>(action));
}

bool PrepareRestartFrame(Isolate* v8_isolate, int callFrameOrdinal) {
  i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
  EnterV8BasicScope api_scope(isolate);
  CHECK(isolate->debug()->CheckExecutionState());

  i::DebugStackTraceIterator it(isolate, callFrameOrdinal);
  if (it.Done() || !it.CanBeRestarted()) return false;

  // Clear all current stepping setup.
  isolate->debug()->ClearStepping();
  it.PrepareRestart();
  return true;
}

void ClearStepping(Isolate* v8_isolate) {
  i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
  EnterV8NoScriptNoExceptionScope api_scope(isolate);
  // Clear all current stepping setup.
  isolate->debug()->ClearStepping();
}

void BreakRightNow(Isolate* v8_isolate,
                   base::EnumSet<debug::BreakReason> break_reasons) {
  i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
  EnterV8BasicScope api_scope(isolate);
  isolate->debug()->HandleDebugBreak(i::kIgnoreIfAllFramesBlackboxed,
                                     break_reasons);
}

void SetTerminateOnResume(Isolate* v8_isolate) {
  i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
  EnterV8NoScriptNoExceptionScope api_scope(isolate);
  isolate->debug()->SetTerminateOnResume();
}

bool CanBreakProgram(Isolate* v8_isolate) {
  i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
  EnterV8BasicScope api_scope(isolate);
  return !isolate->debug()->AllFramesOnStackAreBlackboxed();
}

size_t ScriptSource::Length() const {
  auto source = Utils::OpenDirectHandle(this);
  if (IsString(*source)) {
    return i::Cast<i::String>(source)->length();
  }
  return Size();
}

size_t ScriptSource::Size() const {
  auto source = Utils::OpenDirectHandle(this);
#if V8_ENABLE_WEBASSEMBLY
  if (i::Is<i::CppGCManaged<i::wasm::NativeModule>>(*source)) {
    return i::Cast<i::CppGCManaged<i::wasm::NativeModule>>(*source)
        ->ptr()
        ->wire_bytes()
        .size();
  }
#endif  // V8_ENABLE_WEBASSEMBLY
  if (!IsString(*source)) return 0;
  auto string = i::Cast<i::String>(source);
  return string->length() * (string->IsTwoByteRepresentation() ? 2 : 1);
}

MaybeLocal<String> ScriptSource::JavaScriptCode() const {
  i::DirectHandle<i::HeapObject> source = Utils::OpenDirectHandle(this);
  if (!IsString(*source)) return MaybeLocal<String>();
  return Utils::ToLocal(i::Cast<i::String>(source));
}

#if V8_ENABLE_WEBASSEMBLY
Maybe<std::vector<uint8_t>> ScriptSource::GetWasmBytecode(
    size_t max_size) const {
  auto source = Utils::OpenDirectHandle(this);
  if (!i::Is<i::CppGCManaged<i::wasm::NativeModule>>(*source)) return {};
  auto ptr = i::Cast<i::CppGCManaged<i::wasm::NativeModule>>(*source)->ptr();
  base::Vector<const uint8_t> wire_bytes = ptr->wire_bytes();
  if (wire_bytes.size() > max_size) return Just(std::vector<uint8_t>());
  return Just(std::vector<uint8_t>(wire_bytes.begin(), wire_bytes.end()));
}
#endif  // V8_ENABLE_WEBASSEMBLY

ScriptOriginOptions Script::OriginOptions() const {
  return Utils::OpenDirectHandle(this)->origin_options();
}

bool Script::WasCompiled() const {
  return Utils::OpenDirectHandle(this)->compilation_state() ==
         i::Script::CompilationState::kCompiled;
}

bool Script::IsEmbedded() const {
  auto script = Utils::OpenDirectHandle(this);
  return script->context_data() == i::GetReadOnlyRoots().uninitialized_symbol();
}

int Script::Id() const { return Utils::OpenDirectHandle(this)->id(); }

int Script::StartLine() const {
  return Utils::OpenDirectHandle(this)->line_offset();
}

int Script::StartColumn() const {
  return Utils::OpenDirectHandle(this)->column_offset();
}

int Script::EndLine() const {
  i::DirectHandle<i::Script> script = Utils::OpenDirectHandle(this);
#if V8_ENABLE_WEBASSEMBLY
  if (script->type() == i::Script::Type::kWasm) return 0;
#endif  // V8_ENABLE_WEBASSEMBLY
  if (!IsString(script->source())) {
    return script->line_offset();
  }
  i::Isolate* isolate = i::Isolate::Current();
  i::HandleScope scope(isolate);
  i::Script::PositionInfo info;
  i::Script::GetPositionInfo(
      script, i::Cast<i::String>(script->source())->length(), &info);
  return info.line;
}

int Script::EndColumn() const {
  i::DirectHandle<i::Script> script = Utils::OpenDirectHandle(this);
#if V8_ENABLE_WEBASSEMBLY
  if (script->type() == i::Script::Type::kWasm) {
    return script->wasm_native_module()->wire_bytes().length();
  }
#endif  // V8_ENABLE_WEBASSEMBLY
  if (!IsString(script->source())) {
    return script->column_offset();
  }
  i::Isolate* isolate = i::Isolate::Current();
  i::HandleScope scope(isolate);
  i::Script::PositionInfo info;
  i::Script::GetPositionInfo(
      script, i::Cast<i::String>(script->source())->length(), &info);
  return info.column;
}

MaybeLocal<String> Script::Name() const {
  auto script = Utils::OpenDirectHandle(this);
  i::Isolate* isolate = i::Isolate::Current();
  i::DirectHandle<i::Object> value(script->name(), isolate);
  if (!IsString(*value)) return MaybeLocal<String>();
  return Utils::ToLocal(i::Cast<i::String>(value));
}

MaybeLocal<String> Script::SourceURL() const {
  auto script = Utils::OpenDirectHandle(this);
  i::Isolate* isolate = i::Isolate::Current();
  i::DirectHandle<i::PrimitiveHeapObject> value(script->source_url(), isolate);
  if (!IsString(*value)) return MaybeLocal<String>();
  return Utils::ToLocal(i::Cast<i::String>(value));
}

MaybeLocal<String> Script::SourceMappingURL() const {
  auto script = Utils::OpenDirectHandle(this);
  i::Isolate* isolate = i::Isolate::Current();
  i::DirectHandle<i::Object> value(script->source_mapping_url(), isolate);
  if (!IsString(*value)) return MaybeLocal<String>();
  return Utils::ToLocal(i::Cast<i::String>(value));
}

MaybeLocal<String> Script::DebugId() const {
  auto script = Utils::OpenDirectHandle(this);
  i::Isolate* isolate = i::Isolate::Current();
  i::DirectHandle<i::Object> value(script->debug_id(), isolate);
  if (!IsString(*value)) return MaybeLocal<String>();
  return Utils::ToLocal(i::Cast<i::String>(value));
}

MaybeLocal<String> Script::GetSha256Hash() const {
  i::DirectHandle<i::Script> script = Utils::OpenDirectHandle(this);
  i::Isolate* isolate = i::Isolate::Current();
  i::DirectHandle<i::String> value =
      i::Script::GetScriptHash(isolate, script, /* forceForInspector: */ true);
  return Utils::ToLocal(value);
}

Maybe<int> Script::ContextId() const {
  auto script = Utils::OpenDirectHandle(this);
  i::Tagged<i::Object> value = script->context_data();
  if (IsSmi(value)) return Just(i::Smi::ToInt(value));
  return {};
}

Local<ScriptSource> Script::Source() const {
  auto script = Utils::OpenDirectHandle(this);
  i::Isolate* isolate = i::Isolate::Current();
#if V8_ENABLE_WEBASSEMBLY
  if (script->type() == i::Script::Type::kWasm) {
    i::DirectHandle<i::Object> wasm_native_module(
        script->wasm_managed_native_module(), isolate);
    return Utils::Convert<i::Object, ScriptSource>(wasm_native_module);
  }
#endif  // V8_ENABLE_WEBASSEMBLY
  i::DirectHandle<i::PrimitiveHeapObject> source(script->source(), isolate);
  return Utils::Convert<i::PrimitiveHeapObject, ScriptSource>(source);
}

#if V8_ENABLE_WEBASSEMBLY
bool Script::IsWasm() const {
  return Utils::OpenDirectHandle(this)->type() == i::Script::Type::kWasm;
}
#endif  // V8_ENABLE_WEBASSEMBLY

bool Script::IsModule() const {
  return Utils::OpenDirectHandle(this)->origin_options().IsModule();
}

namespace {

int GetSmiValue(i::DirectHandle<i::FixedArray> array, int index) {
  return i::Smi::ToInt(array->get(index));
}

bool CompareBreakLocation(const i::BreakLocation& loc1,
                          const i::BreakLocation& loc2) {
  return loc1.position() < loc2.position();
}

}  // namespace

bool Script::GetPossibleBreakpoints(
    const Location& start, const Location& end, bool restrict_to_function,
    std::vector<BreakLocation>* locations) const {
  CHECK(!start.IsEmpty());
  i::Handle<i::Script> script = Utils::OpenHandle(this);
#if V8_ENABLE_WEBASSEMBLY
  if (script->type() == i::Script::Type::kWasm) {
    i::CppGCManaged<i::wasm::NativeModule>::Ptr native_module =
        script->wasm_native_module();
    return i::WasmScript::GetPossibleBreakpoints(native_module.raw(), start,
                                                 end, locations);
  }
#endif  // V8_ENABLE_WEBASSEMBLY

  i::Isolate* isolate = i::Isolate::Current();

  int start_offset, end_offset;
  if (!GetSourceOffset(start, GetSourceOffsetMode::kClamp).To(&start_offset)) {
    return false;
  }
  if (end.IsEmpty()) {
    end_offset = std::numeric_limits<int>::max();
  } else if (!GetSourceOffset(end, GetSourceOffsetMode::kClamp)
                  .To(&end_offset)) {
    return false;
  }
  if (start_offset >= end_offset) return true;

  std::vector<i::BreakLocation> v8_locations;
  if (!isolate->debug()->GetPossibleBreakpoints(
          script, start_offset, end_offset, restrict_to_function,
          &v8_locations)) {
    return false;
  }

  std::sort(v8_locations.begin(), v8_locations.end(), CompareBreakLocation);
  for (const auto& v8_location : v8_locations) {
    Location location = GetSourceLocation(v8_location.position());
    locations->emplace_back(location.GetLineNumber(),
                            location.GetColumnNumber(), v8_location.type());
  }
  return true;
}

Maybe<int> Script::GetSourceOffset(const Location& location,
                                   GetSourceOffsetMode mode) const {
  i::DirectHandle<i::Script> script = Utils::OpenDirectHandle(this);
#if V8_ENABLE_WEBASSEMBLY
  if (script->type() == i::Script::Type::kWasm) {
    return location.GetLineNumber() == 0 ? Just(location.GetColumnNumber())
                                         : Nothing<int>();
  }
#endif  // V8_ENABLE_WEBASSEMBLY

  int line = location.GetLineNumber();
  int column = location.GetColumnNumber();
  if (!script->HasSourceURLComment()) {
    // Line/column number for inline <script>s with sourceURL annotation
    // are supposed to be related to the <script> tag, otherwise they
    // are relative to the parent file. Keep this in sync with the logic
    // in GetSourceLocation() below.
    line -= script->line_offset();
    if (line == 0) column -= script->column_offset();
  }

  i::Isolate* isolate = i::Isolate::Current();
  i::Script::InitLineEnds(isolate, script);
  auto line_ends =
      i::Cast<i::FixedArray>(i::direct_handle(script->line_ends(), isolate));
  if (line < 0) {
    if (mode == GetSourceOffsetMode::kClamp) {
      return Just(0);
    }
    return {};
  }
  uint32_t lines_end_len = line_ends->ulength().value();
  if (static_cast<uint32_t>(line) >= lines_end_len) {
    if (mode == GetSourceOffsetMode::kClamp) {
      DCHECK_GT(lines_end_len, 0);
      return Just(GetSmiValue(line_ends, lines_end_len - 1));
    }
    return {};
  }
  if (column < 0) {
    if (mode != GetSourceOffsetMode::kClamp) {
      return {};
    }
    column = 0;
  }
  int offset = column;
  if (line > 0) {
    int prev_line_end_offset = GetSmiValue(line_ends, line - 1);
    offset += prev_line_end_offset + 1;
  }
  int line_end_offset = GetSmiValue(line_ends, line);
  if (offset > line_end_offset) {
    // Be permissive with columns that don't exist,
    // as long as they are clearly within the range
    // of the script.
    DCHECK_GT(lines_end_len, 0);
    if (static_cast<uint32_t>(line) < lines_end_len - 1 ||
        mode == GetSourceOffsetMode::kClamp) {
      return Just(line_end_offset);
    }
    return {};
  }
  return Just(offset);
}

Location Script::GetSourceLocation(int offset) const {
  i::DirectHandle<i::Script> script = Utils::OpenDirectHandle(this);
  i::Script::PositionInfo info;
  i::Script::GetPositionInfo(script, offset, &info);
  if (script->HasSourceURLComment()) {
    // Line/column number for inline <script>s with sourceURL annotation
    // are supposed to be related to the <script> tag, otherwise they
    // are relative to the parent file. Keep this in sync with the logic
    // in GetSourceOffset() above.
    info.line -= script->line_offset();
    if (info.line == 0) info.column -= script->column_offset();
  }
  return Location(info.line, info.column);
}

bool Script::SetBreakpoint(Local<String> condition, Location* location,
                           BreakpointId* id) const {
  i::Handle<i::Script> script = Utils::OpenHandle(this);
  i::Isolate* isolate = i::Isolate::Current();
  int offset;
  if (!GetSourceOffset(*location).To(&offset)) {
    return false;
  }
  if (!isolate->debug()->SetBreakPointForScript(
          script, Utils::OpenDirectHandle(*condition), &offset, id)) {
    return false;
  }
  *location = GetSourceLocation(offset);
  return true;
}

bool Script::SetInstrumentationBreakpoint(BreakpointId* id) const {
  i::DirectHandle<i::Script> script = Utils::OpenDirectHandle(this);
  i::Isolate* isolate = i::Isolate::Current();
#if V8_ENABLE_WEBASSEMBLY
  if (script->type() == i::Script::Type::kWasm) {
    isolate->debug()->SetInstrumentationBreakpointForWasmScript(script, id);
    return true;
  }
#endif  // V8_ENABLE_WEBASSEMBLY
  i::SharedFunctionInfo::ScriptIterator it(isolate, *script);
  for (i::Tagged<i::SharedFunctionInfo> sfi = it.Next(); !sfi.is_null();
       sfi = it.Next()) {
    // Node.js compiles CJS modules via ScriptCompiler::CompileFunction so that
    // module-local bindings like __filename can be injected as function
    // parameters without leaking into the global scope. The resulting Script
    // carries two SFIs: a synthetic toplevel that just returns the wrapped
    // function, and the wrapped SFI that the embedder actually invokes. For
    // such scripts we should pick the wrapped SFI.
    if (script->is_wrapped() ? sfi->is_wrapped() : sfi->is_toplevel()) {
      return isolate->debug()->SetBreakpointForFunction(
          handle(sfi, isolate), isolate->factory()->empty_string(), id,
          internal::Debug::kInstrumentation);
    }
  }
  return false;
}

#if V8_ENABLE_WEBASSEMBLY
void Script::RemoveWasmBreakpoint(BreakpointId id) {
  i::DirectHandle<i::Script> script = Utils::OpenDirectHandle(this);
  i::Isolate* isolate = i::Isolate::Current();
  isolate->debug()->RemoveBreakpointForWasmScript(script, id);
}
#endif  //  V8_ENABLE_WEBASSEMBLY

void RemoveBreakpoint(Isolate* v8_isolate, BreakpointId id) {
  i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
  i::HandleScope handle_scope(isolate);
  isolate->debug()->RemoveBreakpoint(id);
}

Platform* GetCurrentPlatform() { return i::V8::GetCurrentPlatform(); }

void ForceGarbageCollection(Isolate* isolate, StackState embedder_stack_state) {
  i::EmbedderStackStateScope stack_scope(
      reinterpret_cast<i::Isolate*>(isolate)->heap(),
      i::EmbedderStackStateOrigin::kImplicitThroughTask, embedder_stack_state);
  isolate->LowMemoryNotification();
}

#if V8_ENABLE_WEBASSEMBLY
WasmScript* WasmScript::Cast(Script* script) {
  CHECK(script->IsWasm());
  return static_cast<WasmScript*>(script);
}

Maybe<WasmScript::DebugSymbols::Type> GetDebugSymbolType(
    i::wasm::WasmDebugSymbols::Type type) {
  switch (type) {
    case i::wasm::WasmDebugSymbols::Type::EmbeddedDWARF:
      return Just(WasmScript::DebugSymbols::Type::EmbeddedDWARF);
    case i::wasm::WasmDebugSymbols::Type::ExternalDWARF:
      return Just(WasmScript::DebugSymbols::Type::ExternalDWARF);
    case i::wasm::WasmDebugSymbols::Type::SourceMap:
      return Just(WasmScript::DebugSymbols::Type::SourceMap);
    case i::wasm::WasmDebugSymbols::Type::None:
      return {};
  }
  UNREACHABLE();
}

std::vector<WasmScript::DebugSymbols> WasmScript::GetDebugSymbols() const {
  auto script = Utils::OpenDirectHandle(this);
  DCHECK_EQ(i::Script::Type::kWasm, script->type());

  std::vector<WasmScript::DebugSymbols> debug_symbols;
  i::CppGCManaged<i::wasm::NativeModule>::Ptr native_module =
      script->wasm_native_module();
  auto symbols = native_module->module()->debug_symbols;
  for (size_t i = 0; i < symbols.size(); ++i) {
    const i::wasm::WasmDebugSymbols& symbol = symbols[i];
    Maybe<WasmScript::DebugSymbols::Type> type =
        GetDebugSymbolType(symbol.type);
    if (type.IsNothing()) continue;

    internal::wasm::ModuleWireBytes wire_bytes(native_module->wire_bytes());
    i::wasm::WasmName external_url =
        wire_bytes.GetNameOrNull(symbol.external_url);
    debug_symbols.push_back({type.FromJust(), external_url});
  }
  return debug_symbols;
}

int WasmScript::NumFunctions() const {
  i::DisallowGarbageCollection no_gc;
  auto script = Utils::OpenDirectHandle(this);
  DCHECK_EQ(i::Script::Type::kWasm, script->type());
  i::CppGCManaged<i::wasm::NativeModule>::Ptr native_module =
      script->wasm_native_module();
  const i::wasm::WasmModule* module = native_module->module();
  DCHECK_GE(i::kMaxInt, module->functions.size());
  return static_cast<int>(module->functions.size());
}

int WasmScript::NumImportedFunctions() const {
  i::DisallowGarbageCollection no_gc;
  auto script = Utils::OpenDirectHandle(this);
  DCHECK_EQ(i::Script::Type::kWasm, script->type());
  i::CppGCManaged<i::wasm::NativeModule>::Ptr native_module =
      script->wasm_native_module();
  const i::wasm::WasmModule* module = native_module->module();
  DCHECK_GE(i::kMaxInt, module->num_imported_functions);
  return static_cast<int>(module->num_imported_functions);
}

std::pair<int, int> WasmScript::GetFunctionRange(int function_index) const {
  i::DisallowGarbageCollection no_gc;
  auto script = Utils::OpenDirectHandle(this);
  DCHECK_EQ(i::Script::Type::kWasm, script->type());
  i::CppGCManaged<i::wasm::NativeModule>::Ptr native_module =
      script->wasm_native_module();
  const i::wasm::WasmModule* module = native_module->module();
  DCHECK_LE(0, function_index);
  DCHECK_GT(module->functions.size(), function_index);
  const i::wasm::WasmFunction& func = module->functions[function_index];
  DCHECK_GE(i::kMaxInt, func.code.offset());
  DCHECK_GE(i::kMaxInt, func.code.end_offset());
  return std::make_pair(static_cast<int>(func.code.offset()),
                        static_cast<int>(func.code.end_offset()));
}

int WasmScript::GetContainingFunction(int byte_offset) const {
  i::DisallowGarbageCollection no_gc;
  auto script = Utils::OpenDirectHandle(this);
  DCHECK_EQ(i::Script::Type::kWasm, script->type());
  i::CppGCManaged<i::wasm::NativeModule>::Ptr native_module =
      script->wasm_native_module();
  const i::wasm::WasmModule* module = native_module->module();
  DCHECK_LE(0, byte_offset);

  return i::wasm::GetContainingWasmFunction(module, byte_offset);
}

void WasmScript::Disassemble(DisassemblyCollector* collector,
                             std::vector<int>* function_body_offsets) {
  i::DisallowGarbageCollection no_gc;
  auto script = Utils::OpenDirectHandle(this);
  DCHECK_EQ(i::Script::Type::kWasm, script->type());
  i::CppGCManaged<i::wasm::NativeModule>::Ptr native_module =
      script->wasm_native_module();
  const i::wasm::WasmModule* module = native_module->module();
  i::wasm::ModuleWireBytes wire_bytes(native_module->wire_bytes());
  i::wasm::Disassemble(module, wire_bytes, native_module->GetNamesProvider(),
                       collector, function_body_offsets);
}

void Disassemble(base::Vector<const uint8_t> wire_bytes,
                 DisassemblyCollector* collector,
                 std::vector<int>* function_body_offsets) {
  i::wasm::Disassemble(wire_bytes, collector, function_body_offsets);
}

uint32_t WasmScript::GetFunctionHash(int function_index) {
  i::DisallowGarbageCollection no_gc;
  auto script = Utils::OpenDirectHandle(this);
  DCHECK_EQ(i::Script::Type::kWasm, script->type());
  i::CppGCManaged<i::wasm::NativeModule>::Ptr native_module =
      script->wasm_native_module();
  const i::wasm::WasmModule* module = native_module->module();
  DCHECK_LE(0, function_index);
  DCHECK_GT(module->functions.size(), function_index);
  const i::wasm::WasmFunction& func = module->functions[function_index];
  i::wasm::ModuleWireBytes wire_bytes(native_module->wire_bytes());
  base::Vector<const uint8_t> function_bytes =
      wire_bytes.GetFunctionBytes(&func);
  // TODO(herhut): Maybe also take module, name and signature into account.
  return i::StringHasher::HashSequentialString(function_bytes.begin(),
                                               function_bytes.length(),
                                               internal::HashSeed::Default());
}

Maybe<std::span<const uint8_t>> WasmScript::GetModuleBuildId() const {
  i::DisallowGarbageCollection no_gc;
  auto script = Utils::OpenDirectHandle(this);
  DCHECK_EQ(i::Script::Type::kWasm, script->type());
  i::CppGCManaged<i::wasm::NativeModule>::Ptr native_module =
      script->wasm_native_module();
  const i::wasm::WasmModule* wasm_module = native_module->module();
  const i::wasm::WireBytesRef& build_id = wasm_module->build_id;
  if (build_id.is_empty()) {
    return {};
  }
  return Just(std::span<const uint8_t>{
      native_module->wire_bytes().begin() + build_id.offset(),
      build_id.length()});
}

int WasmScript::CodeOffset() const {
  auto script = Utils::OpenDirectHandle(this);
  DCHECK_EQ(i::Script::Type::kWasm, script->type());
  i::CppGCManaged<i::wasm::NativeModule>::Ptr native_module =
      script->wasm_native_module();
  const i::wasm::WasmModule* module = native_module->module();

  // If the module contains at least one function, the code offset must have
  // been initialized, and it cannot be zero.
  DCHECK_IMPLIES(module->num_declared_functions > 0,
                 module->code.offset() != 0);
  return module->code.offset();
}
#endif  // V8_ENABLE_WEBASSEMBLY

Location::Location(int line_number, int column_number)
    : line_number_(line_number),
      column_number_(column_number),
      is_empty_(false) {}

Location::Location()
    : line_number_(Function::kLineOffsetNotFound),
      column_number_(Function::kLineOffsetNotFound),
      is_empty_(true) {}

int Location::GetLineNumber() const {
  DCHECK(!IsEmpty());
  return line_number_;
}

int Location::GetColumnNumber() const {
  DCHECK(!IsEmpty());
  return column_number_;
}

bool Location::IsEmpty() const { return is_empty_; }

void GetLoadedScripts(Isolate* v8_isolate,
                      std::vector<v8::Global<Script>>& scripts) {
  i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
  EnterV8NoScriptNoExceptionScope api_scope(isolate);
  {
    i::DisallowGarbageCollection no_gc;
    i::Script::Iterator iterator(isolate);
    for (i::Tagged<i::Script> script = iterator.Next(); !script.is_null();
         script = iterator.Next()) {
#if V8_ENABLE_WEBASSEMBLY
      if (script->type() != i::Script::Type::kNormal &&
          script->type() != i::Script::Type::kWasm) {
        continue;
      }
#else
      if (script->type() != i::Script::Type::kNormal) continue;
#endif  // V8_ENABLE_WEBASSEMBLY
      if (!script->HasValidSource()) continue;
      i::HandleScope handle_scope(isolate);
      i::DirectHandle<i::Script> script_handle(script, isolate);
      scripts.emplace_back(v8_isolate, ToApiHandle<Script>(script_handle));
    }
  }
}

std::optional<v8::ScriptOrigin> GetScriptOrigin(Isolate* v8_isolate,
                                                int script_id) {
  i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
  EnterV8NoScriptNoExceptionScope api_scope(isolate);
  {
    i::DisallowGarbageCollection no_gc;
    i::Script::Iterator iterator(isolate);
    for (i::Tagged<i::Script> script = iterator.Next(); !script.is_null();
         script = iterator.Next()) {
      if (script->id() == script_id) {
        i::DirectHandle<i::Object> scriptName(script->GetNameOrSourceURL(),
                                              isolate);
        i::DirectHandle<i::Object> source_map_url(script->source_mapping_url(),
                                                  isolate);
        i::DirectHandle<i::Object> host_defined_options(
            script->host_defined_options(), isolate);
        ScriptOriginOptions options(script->origin_options());
        bool is_wasm = false;
#if V8_ENABLE_WEBASSEMBLY
        is_wasm = script->type() == i::Script::Type::kWasm;
#endif  // V8_ENABLE_WEBASSEMBLY
        v8::ScriptOrigin origin(
            Utils::ToLocal(scriptName), script->line_offset(),
            script->column_offset(), options.IsSharedCrossOrigin(),
            script->id(), Utils::ToLocal(source_map_url), options.IsOpaque(),
            is_wasm, options.IsModule(), Utils::ToLocal(host_defined_options));
        return origin;
      }
    }
  }

  return std::nullopt;
}

MaybeLocal<UnboundScript> CompileInspectorScript(Isolate* v8_isolate,
                                                 Local<String> source) {
  i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
  v8::Local<v8::Context> context = Utils::ToLocal(isolate->native_context());
  PrepareForDebugInterfaceExecutionScope api_scope(isolate, context);
  i::Handle<i::String> str = Utils::OpenHandle(*source);
  i::DirectHandle<i::SharedFunctionInfo> result;
  {
    i::AlignedCachedData* cached_data = nullptr;
    ScriptCompiler::CompilationDetails compilation_details;
    i::MaybeDirectHandle<i::SharedFunctionInfo> maybe_function_info =
        i::Compiler::GetSharedFunctionInfoForScriptWithCachedData(
            isolate, str, i::ScriptDetails(), cached_data,
            ScriptCompiler::kNoCompileOptions,
            ScriptCompiler::kNoCacheBecauseInspector,
            i::v8_flags.expose_inspector_scripts ? i::NOT_NATIVES_CODE
                                                 : i::INSPECTOR_CODE,
            &compilation_details);
    bool has_exception = !maybe_function_info.ToHandle(&result);
    if (has_exception) return {};
  }
  return api_scope.Escape(ToApiHandle<UnboundScript>(result));
}

#if V8_ENABLE_WEBASSEMBLY
void EnterDebuggingForIsolate(Isolate* v8_isolate) {
  i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
  i::wasm::GetWasmEngine()->EnterDebuggingForIsolate(isolate);
}

void LeaveDebuggingForIsolate(Isolate* v8_isolate) {
  i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
  i::wasm::GetWasmEngine()->LeaveDebuggingForIsolate(isolate);
}
#endif  // V8_ENABLE_WEBASSEMBLY

void SetDebugDelegate(Isolate* v8_isolate, DebugDelegate* delegate) {
  i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
  isolate->debug()->SetDebugDelegate(delegate);
}

void SetAsyncEventDelegate(Isolate* v8_isolate, AsyncEventDelegate* delegate) {
  reinterpret_cast<i::Isolate*>(v8_isolate)->set_async_event_delegate(delegate);
}

void ResetBlackboxedStateCache(Isolate* v8_isolate, Local<Script> script) {
  i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
  EnterV8NoScriptNoExceptionScope api_scope(isolate);
  i::DisallowGarbageCollection no_gc;
  i::SharedFunctionInfo::ScriptIterator iter(isolate,
                                             *Utils::OpenDirectHandle(*script));
  for (i::Tagged<i::SharedFunctionInfo> info = iter.Next(); !info.is_null();
       info = iter.Next()) {
    if (auto debug_info = isolate->debug()->TryGetDebugInfo(info)) {
      debug_info.value()->set_computed_debug_is_blackboxed(false);
    }
  }
}

int EstimatedValueSize(Isolate* v8_isolate, Local<Value> value) {
  i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
  EnterV8NoScriptNoExceptionScope api_scope(isolate);
  auto object = Utils::OpenDirectHandle(*value);
  if (IsSmi(*object)) return i::kTaggedSize;
  CHECK(IsHeapObject(*object));
  return i::Cast<i::HeapObject>(object)->Size();
}

void AccessorPair::CheckCast(Value* that) {
  auto obj = Utils::OpenDirectHandle(that);
  Utils::ApiCheck(i::IsAccessorPair(*obj), "v8::debug::AccessorPair::Cast",
                  "Value is not a v8::debug::AccessorPair");
}

#if V8_ENABLE_WEBASSEMBLY
void WasmValueObject::CheckCast(Value* that) {
  auto obj = Utils::OpenDirectHandle(that);
  Utils::ApiCheck(i::IsWasmValueObject(*obj),
                  "v8::debug::WasmValueObject::Cast",
                  "Value is not a v8::debug::WasmValueObject");
}

bool WasmValueObject::IsWasmValueObject(Local<Value> that) {
  auto obj = Utils::OpenDirectHandle(*that);
  return i::IsWasmValueObject(*obj);
}

Local<String> WasmValueObject::type() const {
  auto object = i::Cast<i::WasmValueObject>(Utils::OpenDirectHandle(this));
  i::Isolate* isolate = i::Isolate::Current();
  i::DirectHandle<i::String> type(object->type(), isolate);
  return Utils::ToLocal(type);
}
#endif  // V8_ENABLE_WEBASSEMBLY

Local<Function> GetBuiltin(Isolate* v8_isolate, Builtin requested_builtin) {
  i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
  EnterV8NoScriptNoExceptionScope api_scope(isolate);
  i::HandleScope handle_scope(isolate);

  CHECK_EQ(requested_builtin, kStringToLowerCase);
  i::Builtin builtin = i::Builtin::kStringPrototypeToLocaleLowerCase;

  i::Factory* factory = isolate->factory();
  i::DirectHandle<i::String> name = isolate->factory()->empty_string();
  i::DirectHandle<i::NativeContext> context(isolate->native_context());
  i::DirectHandle<i::SharedFunctionInfo> info =
      factory->NewSharedFunctionInfoForBuiltin(name, builtin, 0, i::kAdapt);
  info->set_language_mode(i::LanguageMode::kStrict);
  i::Handle<i::JSFunction> fun =
      i::Factory::JSFunctionBuilder{isolate, info, context}
          .set_map(isolate->strict_function_without_prototype_map())
          .Build();

  return Utils::ToLocal(handle_scope.CloseAndEscape(fun));
}

void SetConsoleDelegate(Isolate* v8_isolate, ConsoleDelegate* delegate) {
  i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
  i::DisallowJavascriptExecutionDebugOnly no_execution(isolate);
  i::DisallowExceptionsDebugOnly no_exceptions(isolate);
  if (delegate == nullptr) {
    isolate->set_console_delegate(nullptr);
  } else {
    isolate->set_console_delegate(delegate);
  }
}

ConsoleCallArguments::ConsoleCallArguments(
    const v8::FunctionCallbackInfo<v8::Value>& info)
    : isolate_(info.GetIsolate()),
      values_(info.address_of_first_argument()),
      length_(info.Length()) {}

ConsoleCallArguments::ConsoleCallArguments(
    i::Isolate* isolate, const internal::BuiltinArguments& args)
    : isolate_(reinterpret_cast<v8::Isolate*>(isolate)),
      values_(args.length() > 1 ? args.address_of_first_argument() : nullptr),
      length_(args.length() - 1) {}

v8::Local<v8::Message> CreateMessageFromException(
    Isolate* v8_isolate, v8::Local<v8::Value> v8_error) {
  i::DirectHandle<i::Object> obj = Utils::OpenDirectHandle(*v8_error);
  i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
  EnterV8NoScriptNoExceptionScope api_scope(isolate);
  i::HandleScope scope(isolate);
  return Utils::MessageToLocal(
      scope.CloseAndEscape(isolate->CreateMessageFromException(obj)));
}

MaybeLocal<Script> GeneratorObject::Script() {
  auto obj = Utils::OpenDirectHandle(this);
  i::Tagged<i::Object> maybe_script = obj->function()->shared()->script();
  if (!IsScript(maybe_script)) return {};
  i::Isolate* isolate = i::Isolate::Current();
  i::DirectHandle<i::Script> script(i::Cast<i::Script>(maybe_script), isolate);
  return ToApiHandle<v8::debug::Script>(script);
}

Local<Function> GeneratorObject::Function() {
  auto obj = Utils::OpenDirectHandle(this);
  return Utils::ToLocal(direct_handle(obj->function(), i::Isolate::Current()));
}

Location GeneratorObject::SuspendedLocation() {
  auto obj = Utils::OpenDirectHandle(this);
  CHECK(obj->is_suspended());
  i::Tagged<i::Object> maybe_script = obj->function()->shared()->script();
  if (!IsScript(maybe_script)) return Location();
  i::Isolate* isolate = i::Isolate::Current();
  i::DirectHandle<i::Script> script(i::Cast<i::Script>(maybe_script), isolate);
  i::Script::PositionInfo info;
  i::SharedFunctionInfo::EnsureSourcePositionsAvailable(
      isolate, i::direct_handle(obj->function()->shared(), isolate));
  i::Script::GetPositionInfo(script, obj->source_position(), &info);
  return Location(info.line, info.column);
}

bool GeneratorObject::IsSuspended() {
  return Utils::OpenDirectHandle(this)->is_suspended();
}

v8::Local<GeneratorObject> GeneratorObject::Cast(v8::Local<v8::Value> value) {
  CHECK(value->IsGeneratorObject());
  return ToApiHandle<GeneratorObject>(Utils::OpenDirectHandle(*value));
}

MaybeLocal<Value> CallFunctionOn(Local<Context> context,
                                 Local<Function> function, Local<Value> recv,
                                 base::Vector<Local<Value>> args,
                                 bool throw_on_side_effect) {
  auto isolate = i::Isolate::Current();
  PrepareForDebugInterfaceExecutionScope api_scope(isolate, context);
  auto self = Utils::OpenHandle(*function);
  auto recv_obj = Utils::OpenHandle(*recv);
  static_assert(sizeof(v8::Global<v8::Value>) == sizeof(i::Handle<i::Object>));
  auto arguments = reinterpret_cast<i::DirectHandle<i::Object>*>(args.data());
  // Disable breaks in side-effect free mode.
  i::DisableBreak disable_break_scope(isolate->debug(), throw_on_side_effect);
  if (throw_on_side_effect) {
    isolate->debug()->StartSideEffectCheckMode();
  }
  MaybeLocal<Value> result = Utils::ToMaybeLocal(
      i::Execution::Call(isolate, self, recv_obj, {arguments, args.size()}));
  if (throw_on_side_effect) {
    isolate->debug()->StopSideEffectCheckMode();
  }
  return api_scope.EscapeMaybe(result);
}

MaybeLocal<v8::Value> EvaluateGlobal(v8::Isolate* isolate,
                                     v8::Local<v8::String> source,
                                     EvaluateGlobalMode mode, bool repl) {
  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
  v8::Local<v8::Context> context = Utils::ToLocal(i_isolate->native_context());
  PrepareForDebugInterfaceExecutionScope api_scope(i_isolate, context);
  i::REPLMode repl_mode = repl ? i::REPLMode::kYes : i::REPLMode::kNo;
  MaybeLocal<Value> result = Utils::ToMaybeLocal(i::DebugEvaluate::Global(
      i_isolate, Utils::OpenHandle(*source), mode, repl_mode));
  return api_scope.EscapeMaybe(result);
}

bool IsAPIFunctionWithSideEffects(v8::Local<v8::Value> value) {
  if (!value->IsFunction()) return false;
  auto function = v8::Utils::OpenDirectHandle(*value.As<v8::Function>());
  if (!i::IsJSFunction(*function)) return false;
  i::DirectHandle<i::JSFunction> js_function = i::Cast<i::JSFunction>(function);
  if (!js_function->shared()->IsApiFunction()) return false;
  i::Tagged<i::FunctionTemplateInfo> info =
      js_function->shared()->api_func_data();
  return info->has_side_effects();
}

void GlobalLexicalScopeNames(v8::Local<v8::Context> v8_context,
                             std::vector<v8::Global<v8::String>>* names) {
  auto context = Utils::OpenDirectHandle(*v8_context);
  i::Isolate* isolate = i::Isolate::Current();
  i::DirectHandle<i::ScriptContextTable> table(
      context->native_context()->script_context_table(), isolate);
  const uint32_t len = table->length(kAcquireLoad).value();
  for (uint32_t i = 0; i < len; i++) {
    i::DirectHandle<i::Context> script_context(table->get(i), isolate);
    DCHECK(script_context->IsScriptContext());
    i::DirectHandle<i::ScopeInfo> scope_info(script_context->scope_info(),
                                             isolate);
    for (auto it : i::ScopeInfo::IterateLocalNames(scope_info)) {
      if (i::ScopeInfo::VariableIsSynthetic(it->name())) continue;
      names->emplace_back(reinterpret_cast<Isolate*>(isolate),
                          Utils::ToLocal(direct_handle(it->name(), isolate)));
    }
  }
}

void SetReturnValue(v8::Isolate* v8_isolate, v8::Local<v8::Value> value) {
  i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
  isolate->debug()->set_return_value(*Utils::OpenDirectHandle(*value));
}

int64_t GetNextRandomInt64(v8::Isolate* v8_isolate) {
  return reinterpret_cast<i::Isolate*>(v8_isolate)
      ->random_number_generator()
      ->NextInt64();
}

int GetDebuggingId(v8::Local<v8::Function> function) {
  auto callable = v8::Utils::OpenDirectHandle(*function);
  if (!IsJSFunction(*callable)) return i::DebugInfo::kNoDebuggingId;
  auto func = i::Cast<i::JSFunction>(callable);
  int id = i::Isolate::Current()->debug()->GetFunctionDebuggingId(func);
  DCHECK_NE(i::DebugInfo::kNoDebuggingId, id);
  return id;
}

bool SetFunctionBreakpoint(v8::Local<v8::Function> function,
                           v8::Local<v8::String> condition, BreakpointId* id) {
  auto callable = Utils::OpenDirectHandle(*function);
  if (!IsJSFunction(*callable)) return false;
  auto jsfunction = i::Cast<i::JSFunction>(callable);
  i::Isolate* isolate = i::Isolate::Current();
  i::DirectHandle<i::String> condition_string =
      condition.IsEmpty()
          ? i::DirectHandle<i::String>(isolate->factory()->empty_string())
          : Utils::OpenDirectHandle(*condition);
  return isolate->debug()->SetBreakpointForFunction(
      handle(jsfunction->shared(), isolate), condition_string, id);
}

PostponeInterruptsScope::PostponeInterruptsScope(v8::Isolate* isolate)
    : scope_(
          new i::PostponeInterruptsScope(reinterpret_cast<i::Isolate*>(isolate),
                                         i::StackGuard::API_INTERRUPT)) {}

PostponeInterruptsScope::~PostponeInterruptsScope() = default;

DisallowGarbageCollectionScope::DisallowGarbageCollectionScope() {
  new (internal_) i::DisallowGarbageCollectionInRelease();
}

DisallowGarbageCollectionScope::~DisallowGarbageCollectionScope() {
  using i::DisallowGarbageCollectionInRelease;
  reinterpret_cast<DisallowGarbageCollectionInRelease*>(internal_)
      ->~DisallowGarbageCollectionInRelease();
}

DisableBreakScope::DisableBreakScope(v8::Isolate* isolate)
    : scope_(std::make_unique<i::DisableBreak>(
          reinterpret_cast<i::Isolate*>(isolate)->debug())) {}

DisableBreakScope::~DisableBreakScope() = default;

int Coverage::BlockData::StartOffset() const { return block_->start; }

int Coverage::BlockData::EndOffset() const { return block_->end; }

uint32_t Coverage::BlockData::Count() const { return block_->count; }

int Coverage::FunctionData::StartOffset() const { return function_->start; }

int Coverage::FunctionData::EndOffset() const { return function_->end; }

uint32_t Coverage::FunctionData::Count() const { return function_->count; }

MaybeLocal<String> Coverage::FunctionData::Name() const {
  return ToApiHandle<String>(function_->name);
}

size_t Coverage::FunctionData::BlockCount() const {
  return function_->blocks.size();
}

bool Coverage::FunctionData::HasBlockCoverage() const {
  return function_->has_block_coverage;
}

Coverage::BlockData Coverage::FunctionData::GetBlockData(size_t i) const {
  return BlockData(&function_->blocks.at(i), coverage_);
}

Local<Script> Coverage::ScriptData::GetScript() const {
  return ToApiHandle<Script>(script_->script);
}

size_t Coverage::ScriptData::FunctionCount() const {
  return script_->functions.size();
}

Coverage::FunctionData Coverage::ScriptData::GetFunctionData(size_t i) const {
  return FunctionData(&script_->functions.at(i), coverage_);
}

Coverage::ScriptData::ScriptData(size_t index,
                                 std::shared_ptr<i::Coverage> coverage)
    : script_(&coverage->at(index)), coverage_(std::move(coverage)) {}

size_t Coverage::ScriptCount() const { return coverage_->size(); }

Coverage::ScriptData Coverage::GetScriptData(size_t i) const {
  return ScriptData(i, coverage_);
}

Coverage Coverage::CollectPrecise(Isolate* isolate) {
  return Coverage(
      i::Coverage::CollectPrecise(reinterpret_cast<i::Isolate*>(isolate)));
}

Coverage Coverage::CollectBestEffort(Isolate* isolate) {
  return Coverage(
      i::Coverage::CollectBestEffort(reinterpret_cast<i::Isolate*>(isolate)));
}

#if V8_ENABLE_WEBASSEMBLY
Coverage Coverage::CollectWasmData(Isolate* isolate) {
  return Coverage(
      i::Coverage::CollectWasmData(reinterpret_cast<i::Isolate*>(isolate)));
}
#endif  // V8_ENABLE_WEBASSEMBLY

void Coverage::SelectMode(Isolate* isolate, CoverageMode mode) {
  i::Coverage::SelectMode(reinterpret_cast<i::Isolate*>(isolate), mode);
}

MaybeLocal<v8::Value> EphemeronTable::Get(v8::Isolate* isolate,
                                          v8::Local<v8::Value> key) {
  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
  auto self = i::Cast<i::EphemeronHashTable>(Utils::OpenDirectHandle(this));
  i::DirectHandle<i::Object> internal_key = Utils::OpenDirectHandle(*key);
  DCHECK(IsJSReceiver(*internal_key));

  i::DirectHandle<i::Object> value(self->Lookup(internal_key), i_isolate);

  if (IsTheHole(*value)) return {};
  return Utils::ToLocal(value);
}

Local<EphemeronTable> EphemeronTable::Set(v8::Isolate* isolate,
                                          v8::Local<v8::Value> key,
                                          v8::Local<v8::Value> value) {
  auto self = i::Cast<i::EphemeronHashTable>(Utils::OpenHandle(this));
  i::DirectHandle<i::Object> internal_key = Utils::OpenDirectHandle(*key);
  i::DirectHandle<i::Object> internal_value = Utils::OpenDirectHandle(*value);
  DCHECK(IsJSReceiver(*internal_key));

  i::DirectHandle<i::EphemeronHashTable> result(
      i::EphemeronHashTable::Put(reinterpret_cast<i::Isolate*>(isolate), self,
                                 internal_key, internal_value));

  return ToApiHandle<EphemeronTable>(result);
}

Local<EphemeronTable> EphemeronTable::New(v8::Isolate* isolate) {
  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
  EnterV8NoScriptNoExceptionScope api_scope(i_isolate);
  i::DirectHandle<i::EphemeronHashTable> table =
      i::EphemeronHashTable::New(i_isolate, 0);
  return ToApiHandle<EphemeronTable>(table);
}

Local<Value> AccessorPair::getter() {
  auto accessors = Utils::OpenDirectHandle(this);
  i::Isolate* isolate = i::Isolate::Current();
  i::DirectHandle<i::Object> getter(accessors->getter(), isolate);
  return Utils::ToLocal(getter);
}

Local<Value> AccessorPair::setter() {
  auto accessors = Utils::OpenDirectHandle(this);
  i::Isolate* isolate = i::Isolate::Current();
  i::DirectHandle<i::Object> setter(accessors->setter(), isolate);
  return Utils::ToLocal(setter);
}

bool AccessorPair::IsAccessorPair(Local<Value> that) {
  return i::IsAccessorPair(*Utils::OpenDirectHandle(*that));
}

MaybeLocal<Message> GetMessageFromPromise(Local<Promise> p) {
  i::DirectHandle<i::JSPromise> promise = Utils::OpenDirectHandle(*p);
  i::Isolate* isolate = i::Isolate::Current();

  i::DirectHandle<i::Symbol> key =
      isolate->factory()->promise_debug_message_symbol();
  i::DirectHandle<i::Object> maybeMessage =
      i::JSReceiver::GetDataProperty(isolate, promise, key);

  if (!IsJSMessageObject(*maybeMessage)) return MaybeLocal<Message>();
  return ToApiHandle<Message>(i::Cast<i::JSMessageObject>(maybeMessage));
}

void RecordAsyncStackTaggingCreateTaskCall(v8::Isolate* v8_isolate) {
  i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
  isolate->CountUsage(v8::Isolate::kAsyncStackTaggingCreateTaskCall);
}

uint64_t GetIsolateId(v8::Isolate* v8_isolate) {
  i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
  return isolate->debug()->IsolateId();
}

void SetIsolateId(v8::Isolate* v8_isolate, uint64_t id) {
  i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
  isolate->debug()->SetIsolateId(id);
}

std::unique_ptr<PropertyIterator> PropertyIterator::Create(
    Local<Context> context, Local<Object> object, bool skip_indices) {
  i::Isolate* isolate = reinterpret_cast<i::Isolate*>(i::Isolate::Current());
  if (isolate->is_execution_terminating()) {
    return nullptr;
  }
  CallDepthScope<false> call_depth_scope(isolate, context);

  return i::DebugPropertyIterator::Create(
      isolate, Utils::OpenDirectHandle(*object), skip_indices);
}

}  // namespace debug

namespace internal {

Maybe<bool> DebugPropertyIterator::Advance() {
  if (isolate_->is_execution_terminating()) {
    return {};
  }
  Local<v8::Context> context = Utils::ToLocal(
      direct_handle(isolate_->context()->native_context(), isolate_));
  CallDepthScope<false> call_depth_scope(isolate_, context);

  if (!AdvanceInternal()) {
    DCHECK(isolate_->has_exception());
    return {};
  }
  return Just(true);
}

}  // namespace internal
}  // namespace v8
