// Copyright 2018 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/inspector/value-mirror.h"

#include <algorithm>
#include <cmath>

#include "src/base/optional.h"
#include "src/debug/debug-interface.h"
#include "src/inspector/v8-debugger.h"
#include "src/inspector/v8-inspector-impl.h"
#include "src/inspector/v8-value-utils.h"

namespace v8_inspector {

using protocol::Response;
using protocol::Runtime::EntryPreview;
using protocol::Runtime::ObjectPreview;
using protocol::Runtime::PropertyPreview;
using protocol::Runtime::RemoteObject;

namespace {
V8InspectorClient* clientFor(v8::Local<v8::Context> context) {
  return static_cast<V8InspectorImpl*>(
             v8::debug::GetInspector(context->GetIsolate()))
      ->client();
}

V8InternalValueType v8InternalValueTypeFrom(v8::Local<v8::Context> context,
                                            v8::Local<v8::Value> value) {
  if (!value->IsObject()) return V8InternalValueType::kNone;
  V8InspectorImpl* inspector = static_cast<V8InspectorImpl*>(
      v8::debug::GetInspector(context->GetIsolate()));
  int contextId = InspectedContext::contextId(context);
  InspectedContext* inspectedContext = inspector->getContext(contextId);
  if (!inspectedContext) return V8InternalValueType::kNone;
  return inspectedContext->getInternalType(value.As<v8::Object>());
}

template <typename ResultType>
ResultType unpackWasmValue(v8::Local<v8::Context> context,
                           v8::Local<v8::Array> array) {
  ResultType result;
  constexpr int kSize = sizeof(result);
  uint8_t buffer[kSize];
  for (int i = 0; i < kSize; i++) {
    v8::Local<v8::Int32> i32 =
        array->Get(context, i).ToLocalChecked().As<v8::Int32>();
    buffer[i] = static_cast<uint8_t>(i32->Value());
  }
  memcpy(&result, buffer, kSize);
  return result;
}

String16 descriptionForWasmS128(std::array<uint8_t, 16> arr) {
  String16Builder builder;
  for (int i = 0; i < 16; i++) {
    builder.appendUnsignedAsHex(arr.at(i));
    builder.append(" ");
  }
  return builder.toString();
}

// Partial list of Wasm's ValueType, copied here to avoid including internal
// header. Using an unscoped enumeration here to allow implicit conversions from
// int. Keep in sync with ValueType::Kind in wasm/value-type.h.
enum WasmValueType { kStmt, kI32, kI64, kF32, kF64, kS128, kExternRef };

Response toProtocolValue(v8::Local<v8::Context> context,
                         v8::Local<v8::Value> value, int maxDepth,
                         std::unique_ptr<protocol::Value>* result) {
  if (!maxDepth)
    return Response::ServerError("Object reference chain is too long");
  maxDepth--;

  if (value->IsNull() || value->IsUndefined()) {
    *result = protocol::Value::null();
    return Response::Success();
  }
  if (value->IsBoolean()) {
    *result =
        protocol::FundamentalValue::create(value.As<v8::Boolean>()->Value());
    return Response::Success();
  }
  if (value->IsNumber()) {
    double doubleValue = value.As<v8::Number>()->Value();
    if (doubleValue >= std::numeric_limits<int>::min() &&
        doubleValue <= std::numeric_limits<int>::max() &&
        bit_cast<int64_t>(doubleValue) != bit_cast<int64_t>(-0.0)) {
      int intValue = static_cast<int>(doubleValue);
      if (intValue == doubleValue) {
        *result = protocol::FundamentalValue::create(intValue);
        return Response::Success();
      }
    }
    *result = protocol::FundamentalValue::create(doubleValue);
    return Response::Success();
  }
  if (value->IsString()) {
    *result = protocol::StringValue::create(
        toProtocolString(context->GetIsolate(), value.As<v8::String>()));
    return Response::Success();
  }
  if (value->IsArray()) {
    v8::Local<v8::Array> array = value.As<v8::Array>();
    std::unique_ptr<protocol::ListValue> inspectorArray =
        protocol::ListValue::create();
    uint32_t length = array->Length();
    for (uint32_t i = 0; i < length; i++) {
      v8::Local<v8::Value> value;
      if (!array->Get(context, i).ToLocal(&value))
        return Response::InternalError();
      std::unique_ptr<protocol::Value> element;
      Response response = toProtocolValue(context, value, maxDepth, &element);
      if (!response.IsSuccess()) return response;
      inspectorArray->pushValue(std::move(element));
    }
    *result = std::move(inspectorArray);
    return Response::Success();
  }
  if (value->IsObject()) {
    std::unique_ptr<protocol::DictionaryValue> jsonObject =
        protocol::DictionaryValue::create();
    v8::Local<v8::Object> object = v8::Local<v8::Object>::Cast(value);
    v8::Local<v8::Array> propertyNames;
    if (!object->GetPropertyNames(context).ToLocal(&propertyNames))
      return Response::InternalError();
    uint32_t length = propertyNames->Length();
    for (uint32_t i = 0; i < length; i++) {
      v8::Local<v8::Value> name;
      if (!propertyNames->Get(context, i).ToLocal(&name))
        return Response::InternalError();
      // FIXME(yurys): v8::Object should support GetOwnPropertyNames
      if (name->IsString()) {
        v8::Maybe<bool> hasRealNamedProperty = object->HasRealNamedProperty(
            context, v8::Local<v8::String>::Cast(name));
        if (hasRealNamedProperty.IsNothing() ||
            !hasRealNamedProperty.FromJust())
          continue;
      }
      v8::Local<v8::String> propertyName;
      if (!name->ToString(context).ToLocal(&propertyName)) continue;
      v8::Local<v8::Value> property;
      if (!object->Get(context, name).ToLocal(&property))
        return Response::InternalError();
      if (property->IsUndefined()) continue;
      std::unique_ptr<protocol::Value> propertyValue;
      Response response =
          toProtocolValue(context, property, maxDepth, &propertyValue);
      if (!response.IsSuccess()) return response;
      jsonObject->setValue(
          toProtocolString(context->GetIsolate(), propertyName),
          std::move(propertyValue));
    }
    *result = std::move(jsonObject);
    return Response::Success();
  }

  if (v8::debug::WasmValue::IsWasmValue(value)) {
    auto wasmValue = value.As<v8::debug::WasmValue>();

    // Convert serializable Wasm values (i32, f32, f64) into protocol values.
    // Not all i64 values are representable by double, so always represent it as
    // a String here.
    switch (wasmValue->value_type()) {
      case kI32: {
        *result = protocol::FundamentalValue::create(
            unpackWasmValue<int32_t>(context, wasmValue->bytes()));
        break;
      }
      case kI64: {
        *result = protocol::StringValue::create(String16::fromInteger64(
            unpackWasmValue<int64_t>(context, wasmValue->bytes())));
        break;
      }
      case kF32: {
        *result = protocol::FundamentalValue::create(
            unpackWasmValue<float>(context, wasmValue->bytes()));
        break;
      }
      case kF64: {
        *result = protocol::FundamentalValue::create(
            unpackWasmValue<double>(context, wasmValue->bytes()));
        break;
      }
      case kS128: {
        auto bytes = wasmValue->bytes();
        DCHECK_EQ(16, bytes->Length());
        auto s128 = unpackWasmValue<std::array<uint8_t, 16>>(context, bytes);
        String16 desc = descriptionForWasmS128(s128);
        *result = protocol::StringValue::create(desc);
        break;
      }
      case kExternRef: {
        std::unique_ptr<protocol::Value> externrefValue;
        Response response = toProtocolValue(context, wasmValue->ref(), maxDepth,
                                            &externrefValue);
        if (!response.IsSuccess()) return response;
        *result = std::move(externrefValue);
        break;
      }
      default: {
        UNIMPLEMENTED();
      }
    }
    return Response::Success();
  }

  return Response::ServerError("Object couldn't be returned by value");
}

Response toProtocolValue(v8::Local<v8::Context> context,
                         v8::Local<v8::Value> value,
                         std::unique_ptr<protocol::Value>* result) {
  if (value->IsUndefined()) return Response::Success();
  return toProtocolValue(context, value, 1000, result);
}

enum AbbreviateMode { kMiddle, kEnd };

String16 abbreviateString(const String16& value, AbbreviateMode mode) {
  const size_t maxLength = 100;
  if (value.length() <= maxLength) return value;
  UChar ellipsis = static_cast<UChar>(0x2026);
  if (mode == kMiddle) {
    return String16::concat(
        value.substring(0, maxLength / 2), String16(&ellipsis, 1),
        value.substring(value.length() - maxLength / 2 + 1));
  }
  return String16::concat(value.substring(0, maxLength - 1), ellipsis);
}

String16 descriptionForSymbol(v8::Local<v8::Context> context,
                              v8::Local<v8::Symbol> symbol) {
  return String16::concat("Symbol(",
                          toProtocolStringWithTypeCheck(context->GetIsolate(),
                                                        symbol->Description()),
                          ")");
}

String16 descriptionForBigInt(v8::Local<v8::Context> context,
                              v8::Local<v8::BigInt> value) {
  v8::Isolate* isolate = context->GetIsolate();
  v8::TryCatch tryCatch(isolate);
  v8::Local<v8::String> description;
  if (!value->ToString(context).ToLocal(&description)) return String16();
  return toProtocolString(isolate, description) + "n";
}

String16 descriptionForPrimitiveType(v8::Local<v8::Context> context,
                                     v8::Local<v8::Value> value) {
  if (value->IsUndefined()) return RemoteObject::TypeEnum::Undefined;
  if (value->IsNull()) return RemoteObject::SubtypeEnum::Null;
  if (value->IsBoolean()) {
    return value.As<v8::Boolean>()->Value() ? "true" : "false";
  }
  if (value->IsString()) {
    return toProtocolString(context->GetIsolate(), value.As<v8::String>());
  }
  UNREACHABLE();
  return String16();
}

String16 descriptionForRegExp(v8::Isolate* isolate,
                              v8::Local<v8::RegExp> value) {
  String16Builder description;
  description.append('/');
  description.append(toProtocolString(isolate, value->GetSource()));
  description.append('/');
  v8::RegExp::Flags flags = value->GetFlags();
  if (flags & v8::RegExp::Flags::kGlobal) description.append('g');
  if (flags & v8::RegExp::Flags::kIgnoreCase) description.append('i');
  if (flags & v8::RegExp::Flags::kLinear) description.append('l');
  if (flags & v8::RegExp::Flags::kMultiline) description.append('m');
  if (flags & v8::RegExp::Flags::kDotAll) description.append('s');
  if (flags & v8::RegExp::Flags::kUnicode) description.append('u');
  if (flags & v8::RegExp::Flags::kSticky) description.append('y');
  return description.toString();
}

enum class ErrorType { kNative, kClient };

// Build a description from an exception using the following rules:
//   * Usually return the stack trace found in the {stack} property.
//   * If the stack trace does not start with the class name of the passed
//     exception, try to build a description from the class name, the
//     {message} property and the rest of the stack trace.
//     (The stack trace is only used if {message} was also found in
//     said stack trace).
String16 descriptionForError(v8::Local<v8::Context> context,
                             v8::Local<v8::Object> object, ErrorType type) {
  v8::Isolate* isolate = context->GetIsolate();
  v8::TryCatch tryCatch(isolate);
  String16 className = toProtocolString(isolate, object->GetConstructorName());

  v8::base::Optional<String16> stack;
  {
    v8::Local<v8::Value> stackValue;
    if (object->Get(context, toV8String(isolate, "stack"))
            .ToLocal(&stackValue) &&
        stackValue->IsString()) {
      stack = toProtocolString(isolate, stackValue.As<v8::String>());
    }
  }

  if (type == ErrorType::kNative && stack) return *stack;

  if (stack && stack->substring(0, className.length()) == className) {
    return *stack;
  }

  v8::base::Optional<String16> message;
  {
    v8::Local<v8::Value> messageValue;
    if (object->Get(context, toV8String(isolate, "message"))
            .ToLocal(&messageValue) &&
        messageValue->IsString()) {
      String16 msg = toProtocolStringWithTypeCheck(isolate, messageValue);
      if (!msg.isEmpty()) message = msg;
    }
  }

  if (!message) return stack ? *stack : className;

  String16 description = className + ": " + *message;
  if (!stack) return description;

  DCHECK(stack && message);
  size_t index = stack->find(*message);
  String16 stackWithoutMessage =
      index != String16::kNotFound ? stack->substring(index + message->length())
                                   : String16();
  return description + stackWithoutMessage;
}

String16 descriptionForObject(v8::Isolate* isolate,
                              v8::Local<v8::Object> object) {
  return toProtocolString(isolate, object->GetConstructorName());
}

String16 descriptionForDate(v8::Local<v8::Context> context,
                            v8::Local<v8::Date> date) {
  v8::Isolate* isolate = context->GetIsolate();
  v8::TryCatch tryCatch(isolate);
  v8::Local<v8::String> description;
  if (!date->ToString(context).ToLocal(&description)) {
    return descriptionForObject(isolate, date);
  }
  return toProtocolString(isolate, description);
}

String16 descriptionForScopeList(v8::Local<v8::Array> list) {
  return String16::concat(
      "Scopes[", String16::fromInteger(static_cast<size_t>(list->Length())),
      ']');
}

String16 descriptionForScope(v8::Local<v8::Context> context,
                             v8::Local<v8::Object> object) {
  v8::Isolate* isolate = context->GetIsolate();
  v8::Local<v8::Value> value;
  if (!object->GetRealNamedProperty(context, toV8String(isolate, "description"))
           .ToLocal(&value)) {
    return String16();
  }
  return toProtocolStringWithTypeCheck(isolate, value);
}

String16 descriptionForCollection(v8::Isolate* isolate,
                                  v8::Local<v8::Object> object, size_t length) {
  String16 className = toProtocolString(isolate, object->GetConstructorName());
  return String16::concat(className, '(', String16::fromInteger(length), ')');
}

String16 descriptionForEntry(v8::Local<v8::Context> context,
                             v8::Local<v8::Object> object) {
  v8::Isolate* isolate = context->GetIsolate();
  String16 key;
  v8::Local<v8::Value> tmp;
  if (object->GetRealNamedProperty(context, toV8String(isolate, "key"))
          .ToLocal(&tmp)) {
    auto wrapper = ValueMirror::create(context, tmp);
    if (wrapper) {
      std::unique_ptr<ObjectPreview> preview;
      int limit = 5;
      wrapper->buildEntryPreview(context, &limit, &limit, &preview);
      if (preview) {
        key = preview->getDescription(String16());
        if (preview->getType() == RemoteObject::TypeEnum::String) {
          key = String16::concat('\"', key, '\"');
        }
      }
    }
  }

  String16 value;
  if (object->GetRealNamedProperty(context, toV8String(isolate, "value"))
          .ToLocal(&tmp)) {
    auto wrapper = ValueMirror::create(context, tmp);
    if (wrapper) {
      std::unique_ptr<ObjectPreview> preview;
      int limit = 5;
      wrapper->buildEntryPreview(context, &limit, &limit, &preview);
      if (preview) {
        value = preview->getDescription(String16());
        if (preview->getType() == RemoteObject::TypeEnum::String) {
          value = String16::concat('\"', value, '\"');
        }
      }
    }
  }

  return key.length() ? ("{" + key + " => " + value + "}") : value;
}

String16 descriptionForFunction(v8::Local<v8::Context> context,
                                v8::Local<v8::Function> value) {
  v8::Isolate* isolate = context->GetIsolate();
  v8::TryCatch tryCatch(isolate);
  v8::Local<v8::String> description;
  if (!value->ToString(context).ToLocal(&description)) {
    return descriptionForObject(isolate, value);
  }
  return toProtocolString(isolate, description);
}

class PrimitiveValueMirror final : public ValueMirror {
 public:
  PrimitiveValueMirror(v8::Local<v8::Value> value, const String16& type)
      : m_value(value), m_type(type) {}

  v8::Local<v8::Value> v8Value() const override { return m_value; }
  Response buildRemoteObject(
      v8::Local<v8::Context> context, WrapMode mode,
      std::unique_ptr<RemoteObject>* result) const override {
    std::unique_ptr<protocol::Value> protocolValue;
    toProtocolValue(context, m_value, &protocolValue);
    *result = RemoteObject::create()
                  .setType(m_type)
                  .setValue(std::move(protocolValue))
                  .build();
    if (m_value->IsNull())
      (*result)->setSubtype(RemoteObject::SubtypeEnum::Null);
    return Response::Success();
  }

  void buildEntryPreview(
      v8::Local<v8::Context> context, int* nameLimit, int* indexLimit,
      std::unique_ptr<ObjectPreview>* preview) const override {
    *preview =
        ObjectPreview::create()
            .setType(m_type)
            .setDescription(descriptionForPrimitiveType(context, m_value))
            .setOverflow(false)
            .setProperties(std::make_unique<protocol::Array<PropertyPreview>>())
            .build();
    if (m_value->IsNull())
      (*preview)->setSubtype(RemoteObject::SubtypeEnum::Null);
  }

  void buildPropertyPreview(
      v8::Local<v8::Context> context, const String16& name,
      std::unique_ptr<PropertyPreview>* preview) const override {
    *preview = PropertyPreview::create()
                   .setName(name)
                   .setValue(abbreviateString(
                       descriptionForPrimitiveType(context, m_value), kMiddle))
                   .setType(m_type)
                   .build();
    if (m_value->IsNull())
      (*preview)->setSubtype(RemoteObject::SubtypeEnum::Null);
  }

 private:
  v8::Local<v8::Value> m_value;
  String16 m_type;
  String16 m_subtype;
};

class WasmValueMirror final : public ValueMirror {
 public:
  explicit WasmValueMirror(v8::Local<v8::debug::WasmValue> value)
      : m_value(value) {}

  v8::Local<v8::Value> v8Value() const override { return m_value; }

  Response buildRemoteObject(
      v8::Local<v8::Context> context, WrapMode mode,
      std::unique_ptr<RemoteObject>* result) const override {
    bool serializable;
    String16 descriptionValue = description(context, &serializable);
    *result = RemoteObject::create()
                  .setType(RemoteObject::TypeEnum::Wasm)
                  .setSubtype(subtype())
                  .setDescription(descriptionValue)
                  .build();
    if (serializable) {
      std::unique_ptr<protocol::Value> protocolValue;
      toProtocolValue(context, m_value, &protocolValue);
      (*result)->setValue(std::move(protocolValue));
    } else {
      (*result)->setUnserializableValue(descriptionValue);
    }
    return Response::Success();
  }

  void buildPropertyPreview(
      v8::Local<v8::Context> context, const String16& name,
      std::unique_ptr<PropertyPreview>* result) const override {
    bool serializable;
    *result = PropertyPreview::create()
                  .setName(name)
                  .setType(RemoteObject::TypeEnum::Wasm)
                  .setSubtype(subtype())
                  .setValue(description(context, &serializable))
                  .build();
  }

  void buildEntryPreview(
      v8::Local<v8::Context> context, int* nameLimit, int* indexLimit,
      std::unique_ptr<ObjectPreview>* preview) const override {
    bool serializable;
    *preview =
        ObjectPreview::create()
            .setType(RemoteObject::TypeEnum::Wasm)
            .setSubtype(subtype())
            .setDescription(description(context, &serializable))
            .setOverflow(false)
            .setProperties(std::make_unique<protocol::Array<PropertyPreview>>())
            .build();
  }

 private:
  String16 subtype() const {
    switch (m_value->value_type()) {
      case kI32:
        return RemoteObject::SubtypeEnum::I32;
      case kI64:
        return RemoteObject::SubtypeEnum::I64;
      case kF32:
        return RemoteObject::SubtypeEnum::F32;
      case kF64:
        return RemoteObject::SubtypeEnum::F64;
      case kS128:
        return RemoteObject::SubtypeEnum::V128;
      case kExternRef:
        return RemoteObject::SubtypeEnum::Externref;
      default:
        UNREACHABLE();
    }
  }

  String16 description(v8::Local<v8::Context> context,
                       bool* serializable) const {
    *serializable = true;
    switch (m_value->value_type()) {
      case kI32: {
        return String16::fromInteger(
            unpackWasmValue<int32_t>(context, m_value->bytes()));
      }
      case kI64: {
        *serializable = false;
        return String16::fromInteger64(
            unpackWasmValue<int64_t>(context, m_value->bytes()));
      }
      case kF32: {
        return String16::fromDouble(
            unpackWasmValue<float>(context, m_value->bytes()));
      }
      case kF64: {
        return String16::fromDouble(
            unpackWasmValue<double>(context, m_value->bytes()));
      }
      case kS128: {
        *serializable = false;
        auto bytes = m_value->bytes();
        DCHECK_EQ(16, bytes->Length());
        auto s128 = unpackWasmValue<std::array<uint8_t, 16>>(context, bytes);
        return descriptionForWasmS128(s128);
      }
      case kExternRef: {
        return descriptionForObject(context->GetIsolate(),
                                    m_value->ref().As<v8::Object>());
      }
      default: {
        *serializable = false;
        return String16("Unknown");
      }
    }
  }

  v8::Local<v8::debug::WasmValue> m_value;
};

class NumberMirror final : public ValueMirror {
 public:
  explicit NumberMirror(v8::Local<v8::Number> value) : m_value(value) {}
  v8::Local<v8::Value> v8Value() const override { return m_value; }

  Response buildRemoteObject(
      v8::Local<v8::Context> context, WrapMode mode,
      std::unique_ptr<RemoteObject>* result) const override {
    bool unserializable = false;
    String16 descriptionValue = description(&unserializable);
    *result = RemoteObject::create()
                  .setType(RemoteObject::TypeEnum::Number)
                  .setDescription(descriptionValue)
                  .build();
    if (unserializable) {
      (*result)->setUnserializableValue(descriptionValue);
    } else {
      (*result)->setValue(protocol::FundamentalValue::create(m_value->Value()));
    }
    return Response::Success();
  }
  void buildPropertyPreview(
      v8::Local<v8::Context> context, const String16& name,
      std::unique_ptr<PropertyPreview>* result) const override {
    bool unserializable = false;
    *result = PropertyPreview::create()
                  .setName(name)
                  .setType(RemoteObject::TypeEnum::Number)
                  .setValue(description(&unserializable))
                  .build();
  }
  void buildEntryPreview(
      v8::Local<v8::Context> context, int* nameLimit, int* indexLimit,
      std::unique_ptr<ObjectPreview>* preview) const override {
    bool unserializable = false;
    *preview =
        ObjectPreview::create()
            .setType(RemoteObject::TypeEnum::Number)
            .setDescription(description(&unserializable))
            .setOverflow(false)
            .setProperties(std::make_unique<protocol::Array<PropertyPreview>>())
            .build();
  }

 private:
  String16 description(bool* unserializable) const {
    *unserializable = true;
    double rawValue = m_value->Value();
    if (std::isnan(rawValue)) return "NaN";
    if (rawValue == 0.0 && std::signbit(rawValue)) return "-0";
    if (std::isinf(rawValue)) {
      return std::signbit(rawValue) ? "-Infinity" : "Infinity";
    }
    *unserializable = false;
    return String16::fromDouble(rawValue);
  }

  v8::Local<v8::Number> m_value;
};

class BigIntMirror final : public ValueMirror {
 public:
  explicit BigIntMirror(v8::Local<v8::BigInt> value) : m_value(value) {}

  Response buildRemoteObject(
      v8::Local<v8::Context> context, WrapMode mode,
      std::unique_ptr<RemoteObject>* result) const override {
    String16 description = descriptionForBigInt(context, m_value);
    *result = RemoteObject::create()
                  .setType(RemoteObject::TypeEnum::Bigint)
                  .setUnserializableValue(description)
                  .setDescription(description)
                  .build();
    return Response::Success();
  }

  void buildPropertyPreview(v8::Local<v8::Context> context,
                            const String16& name,
                            std::unique_ptr<protocol::Runtime::PropertyPreview>*
                                preview) const override {
    *preview = PropertyPreview::create()
                   .setName(name)
                   .setType(RemoteObject::TypeEnum::Bigint)
                   .setValue(abbreviateString(
                       descriptionForBigInt(context, m_value), kMiddle))
                   .build();
  }

  void buildEntryPreview(v8::Local<v8::Context> context, int* nameLimit,
                         int* indexLimit,
                         std::unique_ptr<protocol::Runtime::ObjectPreview>*
                             preview) const override {
    *preview =
        ObjectPreview::create()
            .setType(RemoteObject::TypeEnum::Bigint)
            .setDescription(descriptionForBigInt(context, m_value))
            .setOverflow(false)
            .setProperties(std::make_unique<protocol::Array<PropertyPreview>>())
            .build();
  }

  v8::Local<v8::Value> v8Value() const override { return m_value; }

 private:
  v8::Local<v8::BigInt> m_value;
};

class SymbolMirror final : public ValueMirror {
 public:
  explicit SymbolMirror(v8::Local<v8::Value> value)
      : m_symbol(value.As<v8::Symbol>()) {}

  Response buildRemoteObject(
      v8::Local<v8::Context> context, WrapMode mode,
      std::unique_ptr<RemoteObject>* result) const override {
    if (mode == WrapMode::kForceValue) {
      return Response::ServerError("Object couldn't be returned by value");
    }
    *result = RemoteObject::create()
                  .setType(RemoteObject::TypeEnum::Symbol)
                  .setDescription(descriptionForSymbol(context, m_symbol))
                  .build();
    return Response::Success();
  }

  void buildPropertyPreview(v8::Local<v8::Context> context,
                            const String16& name,
                            std::unique_ptr<protocol::Runtime::PropertyPreview>*
                                preview) const override {
    *preview = PropertyPreview::create()
                   .setName(name)
                   .setType(RemoteObject::TypeEnum::Symbol)
                   .setValue(abbreviateString(
                       descriptionForSymbol(context, m_symbol), kEnd))
                   .build();
  }

  v8::Local<v8::Value> v8Value() const override { return m_symbol; }

 private:
  v8::Local<v8::Symbol> m_symbol;
};

class LocationMirror final : public ValueMirror {
 public:
  static std::unique_ptr<LocationMirror> create(
      v8::Local<v8::Function> function) {
    return create(function, function->ScriptId(),
                  function->GetScriptLineNumber(),
                  function->GetScriptColumnNumber());
  }
  static std::unique_ptr<LocationMirror> createForGenerator(
      v8::Local<v8::Value> value) {
    v8::Local<v8::debug::GeneratorObject> generatorObject =
        v8::debug::GeneratorObject::Cast(value);
    if (!generatorObject->IsSuspended()) {
      return create(generatorObject->Function());
    }
    v8::Local<v8::debug::Script> script;
    if (!generatorObject->Script().ToLocal(&script)) return nullptr;
    v8::debug::Location suspendedLocation =
        generatorObject->SuspendedLocation();
    return create(value, script->Id(), suspendedLocation.GetLineNumber(),
                  suspendedLocation.GetColumnNumber());
  }

  Response buildRemoteObject(
      v8::Local<v8::Context> context, WrapMode mode,
      std::unique_ptr<RemoteObject>* result) const override {
    auto location = protocol::DictionaryValue::create();
    location->setString("scriptId", String16::fromInteger(m_scriptId));
    location->setInteger("lineNumber", m_lineNumber);
    location->setInteger("columnNumber", m_columnNumber);
    *result = RemoteObject::create()
                  .setType(RemoteObject::TypeEnum::Object)
                  .setSubtype("internal#location")
                  .setDescription("Object")
                  .setValue(std::move(location))
                  .build();
    return Response::Success();
  }
  v8::Local<v8::Value> v8Value() const override { return m_value; }

 private:
  static std::unique_ptr<LocationMirror> create(v8::Local<v8::Value> value,
                                                int scriptId, int lineNumber,
                                                int columnNumber) {
    if (scriptId == v8::UnboundScript::kNoScriptId) return nullptr;
    if (lineNumber == v8::Function::kLineOffsetNotFound ||
        columnNumber == v8::Function::kLineOffsetNotFound) {
      return nullptr;
    }
    return std::unique_ptr<LocationMirror>(
        new LocationMirror(value, scriptId, lineNumber, columnNumber));
  }

  LocationMirror(v8::Local<v8::Value> value, int scriptId, int lineNumber,
                 int columnNumber)
      : m_value(value),
        m_scriptId(scriptId),
        m_lineNumber(lineNumber),
        m_columnNumber(columnNumber) {}

  v8::Local<v8::Value> m_value;
  int m_scriptId;
  int m_lineNumber;
  int m_columnNumber;
};

class FunctionMirror final : public ValueMirror {
 public:
  explicit FunctionMirror(v8::Local<v8::Value> value)
      : m_value(value.As<v8::Function>()) {}

  v8::Local<v8::Value> v8Value() const override { return m_value; }

  Response buildRemoteObject(
      v8::Local<v8::Context> context, WrapMode mode,
      std::unique_ptr<RemoteObject>* result) const override {
    // TODO(alph): drop this functionality.
    if (mode == WrapMode::kForceValue) {
      std::unique_ptr<protocol::Value> protocolValue;
      Response response = toProtocolValue(context, m_value, &protocolValue);
      if (!response.IsSuccess()) return response;
      *result = RemoteObject::create()
                    .setType(RemoteObject::TypeEnum::Function)
                    .setValue(std::move(protocolValue))
                    .build();
    } else {
      *result = RemoteObject::create()
                    .setType(RemoteObject::TypeEnum::Function)
                    .setClassName(toProtocolStringWithTypeCheck(
                        context->GetIsolate(), m_value->GetConstructorName()))
                    .setDescription(descriptionForFunction(context, m_value))
                    .build();
    }
    return Response::Success();
  }

  void buildPropertyPreview(
      v8::Local<v8::Context> context, const String16& name,
      std::unique_ptr<PropertyPreview>* result) const override {
    *result = PropertyPreview::create()
                  .setName(name)
                  .setType(RemoteObject::TypeEnum::Function)
                  .setValue(String16())
                  .build();
  }
  void buildEntryPreview(
      v8::Local<v8::Context> context, int* nameLimit, int* indexLimit,
      std::unique_ptr<ObjectPreview>* preview) const override {
    *preview =
        ObjectPreview::create()
            .setType(RemoteObject::TypeEnum::Function)
            .setDescription(descriptionForFunction(context, m_value))
            .setOverflow(false)
            .setProperties(std::make_unique<protocol::Array<PropertyPreview>>())
            .build();
  }

 private:
  v8::Local<v8::Function> m_value;
};

bool isArrayLike(v8::Local<v8::Context> context, v8::Local<v8::Value> value,
                 size_t* length) {
  if (!value->IsObject()) return false;
  v8::Isolate* isolate = context->GetIsolate();
  v8::TryCatch tryCatch(isolate);
  v8::MicrotasksScope microtasksScope(isolate,
                                      v8::MicrotasksScope::kDoNotRunMicrotasks);
  v8::Local<v8::Object> object = value.As<v8::Object>();
  v8::Local<v8::Value> spliceValue;
  if (!object->IsArgumentsObject() &&
      (!object->GetRealNamedProperty(context, toV8String(isolate, "splice"))
            .ToLocal(&spliceValue) ||
       !spliceValue->IsFunction())) {
    return false;
  }
  v8::Local<v8::Value> lengthValue;
  v8::Maybe<bool> result =
      object->HasOwnProperty(context, toV8String(isolate, "length"));
  if (result.IsNothing()) return false;
  if (!result.FromJust() ||
      !object->Get(context, toV8String(isolate, "length"))
           .ToLocal(&lengthValue) ||
      !lengthValue->IsUint32()) {
    return false;
  }
  *length = v8::Local<v8::Uint32>::Cast(lengthValue)->Value();
  return true;
}

struct EntryMirror {
  std::unique_ptr<ValueMirror> key;
  std::unique_ptr<ValueMirror> value;

  static bool getEntries(v8::Local<v8::Context> context,
                         v8::Local<v8::Object> object, size_t limit,
                         bool* overflow, std::vector<EntryMirror>* mirrors) {
    bool isKeyValue = false;
    v8::Local<v8::Array> entries;
    if (!object->PreviewEntries(&isKeyValue).ToLocal(&entries)) return false;
    for (uint32_t i = 0; i < entries->Length(); i += isKeyValue ? 2 : 1) {
      v8::Local<v8::Value> tmp;

      std::unique_ptr<ValueMirror> keyMirror;
      if (isKeyValue && entries->Get(context, i).ToLocal(&tmp)) {
        keyMirror = ValueMirror::create(context, tmp);
      }
      std::unique_ptr<ValueMirror> valueMirror;
      if (entries->Get(context, isKeyValue ? i + 1 : i).ToLocal(&tmp)) {
        valueMirror = ValueMirror::create(context, tmp);
      } else {
        continue;
      }
      if (mirrors->size() == limit) {
        *overflow = true;
        return true;
      }
      mirrors->emplace_back(
          EntryMirror{std::move(keyMirror), std::move(valueMirror)});
    }
    return mirrors->size() > 0;
  }
};

class PreviewPropertyAccumulator : public ValueMirror::PropertyAccumulator {
 public:
  PreviewPropertyAccumulator(const std::vector<String16>& blocklist,
                             int skipIndex, int* nameLimit, int* indexLimit,
                             bool* overflow,
                             std::vector<PropertyMirror>* mirrors)
      : m_blocklist(blocklist),
        m_skipIndex(skipIndex),
        m_nameLimit(nameLimit),
        m_indexLimit(indexLimit),
        m_overflow(overflow),
        m_mirrors(mirrors) {}

  bool Add(PropertyMirror mirror) override {
    if (mirror.exception) return true;
    if ((!mirror.getter || !mirror.getter->v8Value()->IsFunction()) &&
        !mirror.value) {
      return true;
    }
    if (!mirror.isOwn) return true;
    if (std::find(m_blocklist.begin(), m_blocklist.end(), mirror.name) !=
        m_blocklist.end()) {
      return true;
    }
    if (mirror.isIndex && m_skipIndex > 0) {
      --m_skipIndex;
      if (m_skipIndex > 0) return true;
    }
    int* limit = mirror.isIndex ? m_indexLimit : m_nameLimit;
    if (!*limit) {
      *m_overflow = true;
      return false;
    }
    --*limit;
    m_mirrors->push_back(std::move(mirror));
    return true;
  }

 private:
  std::vector<String16> m_blocklist;
  int m_skipIndex;
  int* m_nameLimit;
  int* m_indexLimit;
  bool* m_overflow;
  std::vector<PropertyMirror>* m_mirrors;
};

bool getPropertiesForPreview(v8::Local<v8::Context> context,
                             v8::Local<v8::Object> object, int* nameLimit,
                             int* indexLimit, bool* overflow,
                             std::vector<PropertyMirror>* properties) {
  std::vector<String16> blocklist;
  size_t length = 0;
  if (object->IsArray() || isArrayLike(context, object, &length) ||
      object->IsStringObject()) {
    blocklist.push_back("length");
  } else {
    auto clientSubtype = clientFor(context)->valueSubtype(object);
    if (clientSubtype && toString16(clientSubtype->string()) == "array") {
      blocklist.push_back("length");
    }
  }
  if (object->IsArrayBuffer() || object->IsSharedArrayBuffer()) {
    blocklist.push_back("[[Int8Array]]");
    blocklist.push_back("[[Uint8Array]]");
    blocklist.push_back("[[Int16Array]]");
    blocklist.push_back("[[Int32Array]]");
  }
  int skipIndex = object->IsStringObject()
                      ? object.As<v8::StringObject>()->ValueOf()->Length() + 1
                      : -1;
  PreviewPropertyAccumulator accumulator(blocklist, skipIndex, nameLimit,
                                         indexLimit, overflow, properties);
  return ValueMirror::getProperties(context, object, false, false,
                                    &accumulator);
}

void getInternalPropertiesForPreview(
    v8::Local<v8::Context> context, v8::Local<v8::Object> object,
    int* nameLimit, bool* overflow,
    std::vector<InternalPropertyMirror>* properties) {
  std::vector<InternalPropertyMirror> mirrors;
  ValueMirror::getInternalProperties(context, object, &mirrors);
  std::vector<String16> allowlist;
  if (object->IsBooleanObject() || object->IsNumberObject() ||
      object->IsStringObject() || object->IsSymbolObject() ||
      object->IsBigIntObject()) {
    allowlist.emplace_back("[[PrimitiveValue]]");
  } else if (object->IsPromise()) {
    allowlist.emplace_back("[[PromiseState]]");
    allowlist.emplace_back("[[PromiseResult]]");
  } else if (object->IsGeneratorObject()) {
    allowlist.emplace_back("[[GeneratorState]]");
  }
  for (auto& mirror : mirrors) {
    if (std::find(allowlist.begin(), allowlist.end(), mirror.name) ==
        allowlist.end()) {
      continue;
    }
    if (!*nameLimit) {
      *overflow = true;
      return;
    }
    --*nameLimit;
    properties->push_back(std::move(mirror));
  }
}

void getPrivatePropertiesForPreview(
    v8::Local<v8::Context> context, v8::Local<v8::Object> object,
    int* nameLimit, bool* overflow,
    protocol::Array<PropertyPreview>* privateProperties) {
  std::vector<PrivatePropertyMirror> mirrors =
      ValueMirror::getPrivateProperties(context, object);
  for (auto& mirror : mirrors) {
    std::unique_ptr<PropertyPreview> propertyPreview;
    if (mirror.value) {
      mirror.value->buildPropertyPreview(context, mirror.name,
                                         &propertyPreview);
    } else {
      propertyPreview = PropertyPreview::create()
                            .setName(mirror.name)
                            .setType(PropertyPreview::TypeEnum::Accessor)
                            .build();
    }
    if (!propertyPreview) continue;
    if (!*nameLimit) {
      *overflow = true;
      return;
    }
    --*nameLimit;
    privateProperties->emplace_back(std::move(propertyPreview));
  }
}

class ObjectMirror final : public ValueMirror {
 public:
  ObjectMirror(v8::Local<v8::Value> value, const String16& description)
      : m_value(value.As<v8::Object>()),
        m_description(description),
        m_hasSubtype(false) {}
  ObjectMirror(v8::Local<v8::Value> value, const String16& subtype,
               const String16& description)
      : m_value(value.As<v8::Object>()),
        m_description(description),
        m_hasSubtype(true),
        m_subtype(subtype) {}

  v8::Local<v8::Value> v8Value() const override { return m_value; }

  Response buildRemoteObject(
      v8::Local<v8::Context> context, WrapMode mode,
      std::unique_ptr<RemoteObject>* result) const override {
    if (mode == WrapMode::kForceValue) {
      std::unique_ptr<protocol::Value> protocolValue;
      Response response = toProtocolValue(context, m_value, &protocolValue);
      if (!response.IsSuccess()) return response;
      *result = RemoteObject::create()
                    .setType(RemoteObject::TypeEnum::Object)
                    .setValue(std::move(protocolValue))
                    .build();
    } else {
      v8::Isolate* isolate = context->GetIsolate();
      *result = RemoteObject::create()
                    .setType(RemoteObject::TypeEnum::Object)
                    .setClassName(toProtocolString(
                        isolate, m_value->GetConstructorName()))
                    .setDescription(m_description)
                    .build();
      if (m_hasSubtype) (*result)->setSubtype(m_subtype);
      if (mode == WrapMode::kWithPreview) {
        std::unique_ptr<ObjectPreview> previewValue;
        int nameLimit = 5;
        int indexLimit = 100;
        buildObjectPreview(context, false, &nameLimit, &indexLimit,
                           &previewValue);
        (*result)->setPreview(std::move(previewValue));
      }
    }
    return Response::Success();
  }

  void buildObjectPreview(
      v8::Local<v8::Context> context, bool generatePreviewForTable,
      int* nameLimit, int* indexLimit,
      std::unique_ptr<ObjectPreview>* result) const override {
    buildObjectPreviewInternal(context, false /* forEntry */,
                               generatePreviewForTable, nameLimit, indexLimit,
                               result);
  }

  void buildEntryPreview(
      v8::Local<v8::Context> context, int* nameLimit, int* indexLimit,
      std::unique_ptr<ObjectPreview>* result) const override {
    buildObjectPreviewInternal(context, true /* forEntry */,
                               false /* generatePreviewForTable */, nameLimit,
                               indexLimit, result);
  }

  void buildPropertyPreview(
      v8::Local<v8::Context> context, const String16& name,
      std::unique_ptr<PropertyPreview>* result) const override {
    *result = PropertyPreview::create()
                  .setName(name)
                  .setType(RemoteObject::TypeEnum::Object)
                  .setValue(abbreviateString(
                      m_description,
                      m_subtype == RemoteObject::SubtypeEnum::Regexp ? kMiddle
                                                                     : kEnd))
                  .build();
    if (m_hasSubtype) (*result)->setSubtype(m_subtype);
  }

 private:
  void buildObjectPreviewInternal(
      v8::Local<v8::Context> context, bool forEntry,
      bool generatePreviewForTable, int* nameLimit, int* indexLimit,
      std::unique_ptr<ObjectPreview>* result) const {
    auto properties = std::make_unique<protocol::Array<PropertyPreview>>();
    std::unique_ptr<protocol::Array<EntryPreview>> entriesPreview;
    bool overflow = false;

    v8::Local<v8::Value> value = m_value;
    while (value->IsProxy()) value = value.As<v8::Proxy>()->GetTarget();

    if (value->IsObject() && !value->IsProxy()) {
      v8::Local<v8::Object> objectForPreview = value.As<v8::Object>();
      std::vector<InternalPropertyMirror> internalProperties;
      getInternalPropertiesForPreview(context, objectForPreview, nameLimit,
                                      &overflow, &internalProperties);
      for (size_t i = 0; i < internalProperties.size(); ++i) {
        std::unique_ptr<PropertyPreview> propertyPreview;
        internalProperties[i].value->buildPropertyPreview(
            context, internalProperties[i].name, &propertyPreview);
        if (propertyPreview) {
          properties->emplace_back(std::move(propertyPreview));
        }
      }

      getPrivatePropertiesForPreview(context, objectForPreview, nameLimit,
                                     &overflow, properties.get());

      std::vector<PropertyMirror> mirrors;
      if (getPropertiesForPreview(context, objectForPreview, nameLimit,
                                  indexLimit, &overflow, &mirrors)) {
        for (size_t i = 0; i < mirrors.size(); ++i) {
          std::unique_ptr<PropertyPreview> preview;
          std::unique_ptr<ObjectPreview> valuePreview;
          if (mirrors[i].value) {
            mirrors[i].value->buildPropertyPreview(context, mirrors[i].name,
                                                   &preview);
            if (generatePreviewForTable) {
              int tableLimit = 1000;
              mirrors[i].value->buildObjectPreview(context, false, &tableLimit,
                                                   &tableLimit, &valuePreview);
            }
          } else {
            preview = PropertyPreview::create()
                          .setName(mirrors[i].name)
                          .setType(PropertyPreview::TypeEnum::Accessor)
                          .build();
          }
          if (valuePreview) {
            preview->setValuePreview(std::move(valuePreview));
          }
          properties->emplace_back(std::move(preview));
        }
      }

      std::vector<EntryMirror> entries;
      if (EntryMirror::getEntries(context, objectForPreview, 5, &overflow,
                                  &entries)) {
        if (forEntry) {
          overflow = true;
        } else {
          entriesPreview = std::make_unique<protocol::Array<EntryPreview>>();
          for (const auto& entry : entries) {
            std::unique_ptr<ObjectPreview> valuePreview;
            entry.value->buildEntryPreview(context, nameLimit, indexLimit,
                                           &valuePreview);
            if (!valuePreview) continue;
            std::unique_ptr<ObjectPreview> keyPreview;
            if (entry.key) {
              entry.key->buildEntryPreview(context, nameLimit, indexLimit,
                                           &keyPreview);
              if (!keyPreview) continue;
            }
            std::unique_ptr<EntryPreview> entryPreview =
                EntryPreview::create()
                    .setValue(std::move(valuePreview))
                    .build();
            if (keyPreview) entryPreview->setKey(std::move(keyPreview));
            entriesPreview->emplace_back(std::move(entryPreview));
          }
        }
      }
    }
    *result = ObjectPreview::create()
                  .setType(RemoteObject::TypeEnum::Object)
                  .setDescription(m_description)
                  .setOverflow(overflow)
                  .setProperties(std::move(properties))
                  .build();
    if (m_hasSubtype) (*result)->setSubtype(m_subtype);
    if (entriesPreview) (*result)->setEntries(std::move(entriesPreview));
  }

  v8::Local<v8::Object> m_value;
  String16 m_description;
  bool m_hasSubtype;
  String16 m_subtype;
};

void nativeGetterCallback(const v8::FunctionCallbackInfo<v8::Value>& info) {
  v8::Local<v8::Object> data = info.Data().As<v8::Object>();
  v8::Isolate* isolate = info.GetIsolate();
  v8::Local<v8::Context> context = isolate->GetCurrentContext();
  v8::Local<v8::Value> name;
  if (!data->GetRealNamedProperty(context, toV8String(isolate, "name"))
           .ToLocal(&name)) {
    return;
  }
  v8::Local<v8::Value> object;
  if (!data->GetRealNamedProperty(context, toV8String(isolate, "object"))
           .ToLocal(&object) ||
      !object->IsObject()) {
    return;
  }
  v8::Local<v8::Value> value;
  if (!object.As<v8::Object>()->Get(context, name).ToLocal(&value)) return;
  info.GetReturnValue().Set(value);
}

std::unique_ptr<ValueMirror> createNativeGetter(v8::Local<v8::Context> context,
                                                v8::Local<v8::Value> object,
                                                v8::Local<v8::Name> name) {
  v8::Isolate* isolate = context->GetIsolate();
  v8::TryCatch tryCatch(isolate);

  v8::Local<v8::Object> data = v8::Object::New(isolate);
  if (data->Set(context, toV8String(isolate, "name"), name).IsNothing()) {
    return nullptr;
  }
  if (data->Set(context, toV8String(isolate, "object"), object).IsNothing()) {
    return nullptr;
  }

  v8::Local<v8::Function> function;
  if (!v8::Function::New(context, nativeGetterCallback, data, 0,
                         v8::ConstructorBehavior::kThrow)
           .ToLocal(&function)) {
    return nullptr;
  }
  return ValueMirror::create(context, function);
}

void nativeSetterCallback(const v8::FunctionCallbackInfo<v8::Value>& info) {
  if (info.Length() < 1) return;
  v8::Local<v8::Object> data = info.Data().As<v8::Object>();
  v8::Isolate* isolate = info.GetIsolate();
  v8::Local<v8::Context> context = isolate->GetCurrentContext();
  v8::Local<v8::Value> name;
  if (!data->GetRealNamedProperty(context, toV8String(isolate, "name"))
           .ToLocal(&name)) {
    return;
  }
  v8::Local<v8::Value> object;
  if (!data->GetRealNamedProperty(context, toV8String(isolate, "object"))
           .ToLocal(&object) ||
      !object->IsObject()) {
    return;
  }
  v8::Local<v8::Value> value;
  if (!object.As<v8::Object>()->Set(context, name, info[0]).IsNothing()) return;
}

std::unique_ptr<ValueMirror> createNativeSetter(v8::Local<v8::Context> context,
                                                v8::Local<v8::Value> object,
                                                v8::Local<v8::Name> name) {
  v8::Isolate* isolate = context->GetIsolate();
  v8::TryCatch tryCatch(isolate);

  v8::Local<v8::Object> data = v8::Object::New(isolate);
  if (data->Set(context, toV8String(isolate, "name"), name).IsNothing()) {
    return nullptr;
  }
  if (data->Set(context, toV8String(isolate, "object"), object).IsNothing()) {
    return nullptr;
  }

  v8::Local<v8::Function> function;
  if (!v8::Function::New(context, nativeSetterCallback, data, 1,
                         v8::ConstructorBehavior::kThrow)
           .ToLocal(&function)) {
    return nullptr;
  }
  return ValueMirror::create(context, function);
}

bool doesAttributeHaveObservableSideEffectOnGet(v8::Local<v8::Context> context,
                                                v8::Local<v8::Object> object,
                                                v8::Local<v8::Name> name) {
  // TODO(dgozman): we should remove this, annotate more embedder properties as
  // side-effect free, and call all getters which do not produce side effects.
  if (!name->IsString()) return false;
  v8::Isolate* isolate = context->GetIsolate();
  if (!name.As<v8::String>()->StringEquals(toV8String(isolate, "body"))) {
    return false;
  }

  v8::TryCatch tryCatch(isolate);
  v8::Local<v8::Value> request;
  if (context->Global()
          ->GetRealNamedProperty(context, toV8String(isolate, "Request"))
          .ToLocal(&request)) {
    if (request->IsObject() &&
        object->InstanceOf(context, request.As<v8::Object>())
            .FromMaybe(false)) {
      return true;
    }
  }
  if (tryCatch.HasCaught()) tryCatch.Reset();

  v8::Local<v8::Value> response;
  if (context->Global()
          ->GetRealNamedProperty(context, toV8String(isolate, "Response"))
          .ToLocal(&response)) {
    if (response->IsObject() &&
        object->InstanceOf(context, response.As<v8::Object>())
            .FromMaybe(false)) {
      return true;
    }
  }
  return false;
}
template <typename ArrayView, typename ArrayBuffer>
void addTypedArrayView(v8::Local<v8::Context> context,
                       v8::Local<ArrayBuffer> buffer, size_t length,
                       const char* name,
                       ValueMirror::PropertyAccumulator* accumulator) {
  accumulator->Add(PropertyMirror{
      String16(name), false, false, false, true, false,
      ValueMirror::create(context, ArrayView::New(buffer, 0, length)), nullptr,
      nullptr, nullptr, nullptr});
}

template <typename ArrayBuffer>
void addTypedArrayViews(v8::Local<v8::Context> context,
                        v8::Local<ArrayBuffer> buffer,
                        ValueMirror::PropertyAccumulator* accumulator) {
  // TODO(alph): these should be internal properties.
  // TODO(v8:9308): Reconsider how large arrays are previewed.
  const size_t byte_length = buffer->ByteLength();

  size_t length = byte_length;
  if (length > v8::TypedArray::kMaxLength) return;

  addTypedArrayView<v8::Int8Array>(context, buffer, length, "[[Int8Array]]",
                                   accumulator);
  addTypedArrayView<v8::Uint8Array>(context, buffer, length, "[[Uint8Array]]",
                                    accumulator);

  length = byte_length / 2;
  if (length > v8::TypedArray::kMaxLength || (byte_length % 2) != 0) return;

  addTypedArrayView<v8::Int16Array>(context, buffer, length, "[[Int16Array]]",
                                    accumulator);

  length = byte_length / 4;
  if (length > v8::TypedArray::kMaxLength || (byte_length % 4) != 0) return;

  addTypedArrayView<v8::Int32Array>(context, buffer, length, "[[Int32Array]]",
                                    accumulator);
}
}  // anonymous namespace

ValueMirror::~ValueMirror() = default;

// static
bool ValueMirror::getProperties(v8::Local<v8::Context> context,
                                v8::Local<v8::Object> object,
                                bool ownProperties, bool accessorPropertiesOnly,
                                PropertyAccumulator* accumulator) {
  v8::Isolate* isolate = context->GetIsolate();
  v8::TryCatch tryCatch(isolate);
  v8::Local<v8::Set> set = v8::Set::New(isolate);

  v8::MicrotasksScope microtasksScope(isolate,
                                      v8::MicrotasksScope::kDoNotRunMicrotasks);
  V8InternalValueType internalType = v8InternalValueTypeFrom(context, object);
  if (internalType == V8InternalValueType::kScope) {
    v8::Local<v8::Value> value;
    if (!object->Get(context, toV8String(isolate, "object")).ToLocal(&value) ||
        !value->IsObject()) {
      return false;
    } else {
      object = value.As<v8::Object>();
    }
  }
  if (internalType == V8InternalValueType::kScopeList) {
    if (!set->Add(context, toV8String(isolate, "length")).ToLocal(&set)) {
      return false;
    }
  }
  bool shouldSkipProto = internalType == V8InternalValueType::kScopeList;

  bool formatAccessorsAsProperties =
      clientFor(context)->formatAccessorsAsProperties(object);

  if (object->IsArrayBuffer()) {
    addTypedArrayViews(context, object.As<v8::ArrayBuffer>(), accumulator);
  }
  if (object->IsSharedArrayBuffer()) {
    addTypedArrayViews(context, object.As<v8::SharedArrayBuffer>(),
                       accumulator);
  }

  for (auto iterator = v8::debug::PropertyIterator::Create(object);
       !iterator->Done(); iterator->Advance()) {
    bool isOwn = iterator->is_own();
    if (!isOwn && ownProperties) break;
    v8::Local<v8::Name> v8Name = iterator->name();
    v8::Maybe<bool> result = set->Has(context, v8Name);
    if (result.IsNothing()) return false;
    if (result.FromJust()) continue;
    if (!set->Add(context, v8Name).ToLocal(&set)) return false;

    String16 name;
    std::unique_ptr<ValueMirror> symbolMirror;
    if (v8Name->IsString()) {
      name = toProtocolString(isolate, v8Name.As<v8::String>());
    } else {
      v8::Local<v8::Symbol> symbol = v8Name.As<v8::Symbol>();
      name = descriptionForSymbol(context, symbol);
      symbolMirror = ValueMirror::create(context, symbol);
    }

    v8::PropertyAttribute attributes;
    std::unique_ptr<ValueMirror> valueMirror;
    std::unique_ptr<ValueMirror> getterMirror;
    std::unique_ptr<ValueMirror> setterMirror;
    std::unique_ptr<ValueMirror> exceptionMirror;
    bool writable = false;
    bool enumerable = false;
    bool configurable = false;

    bool isAccessorProperty = false;
    v8::TryCatch tryCatch(isolate);
    if (!iterator->attributes().To(&attributes)) {
      exceptionMirror = ValueMirror::create(context, tryCatch.Exception());
    } else {
      if (iterator->is_native_accessor()) {
        if (iterator->has_native_getter()) {
          getterMirror = createNativeGetter(context, object, v8Name);
        }
        if (iterator->has_native_setter()) {
          setterMirror = createNativeSetter(context, object, v8Name);
        }
        writable = !(attributes & v8::PropertyAttribute::ReadOnly);
        enumerable = !(attributes & v8::PropertyAttribute::DontEnum);
        configurable = !(attributes & v8::PropertyAttribute::DontDelete);
        isAccessorProperty = getterMirror || setterMirror;
      } else {
        v8::TryCatch tryCatch(isolate);
        v8::debug::PropertyDescriptor descriptor;
        if (!iterator->descriptor().To(&descriptor)) {
          exceptionMirror = ValueMirror::create(context, tryCatch.Exception());
        } else {
          writable = descriptor.has_writable ? descriptor.writable : false;
          enumerable =
              descriptor.has_enumerable ? descriptor.enumerable : false;
          configurable =
              descriptor.has_configurable ? descriptor.configurable : false;
          if (!descriptor.value.IsEmpty()) {
            valueMirror = ValueMirror::create(context, descriptor.value);
          }
          bool getterIsNativeFunction = false;
          if (!descriptor.get.IsEmpty()) {
            v8::Local<v8::Value> get = descriptor.get;
            getterMirror = ValueMirror::create(context, get);
            getterIsNativeFunction =
                get->IsFunction() && get.As<v8::Function>()->ScriptId() ==
                                         v8::UnboundScript::kNoScriptId;
          }
          if (!descriptor.set.IsEmpty()) {
            setterMirror = ValueMirror::create(context, descriptor.set);
          }
          isAccessorProperty = getterMirror || setterMirror;
          bool isSymbolDescription =
              object->IsSymbol() && name == "description";
          if (isSymbolDescription ||
              (name != "__proto__" && getterIsNativeFunction &&
               formatAccessorsAsProperties &&
               !doesAttributeHaveObservableSideEffectOnGet(context, object,
                                                           v8Name))) {
            v8::TryCatch tryCatch(isolate);
            v8::Local<v8::Value> value;
            if (object->Get(context, v8Name).ToLocal(&value)) {
              valueMirror = ValueMirror::create(context, value);
              isOwn = true;
              setterMirror = nullptr;
              getterMirror = nullptr;
            }
          }
        }
      }
    }
    if (accessorPropertiesOnly && !isAccessorProperty) continue;
    auto mirror = PropertyMirror{name,
                                 writable,
                                 configurable,
                                 enumerable,
                                 isOwn,
                                 iterator->is_array_index(),
                                 std::move(valueMirror),
                                 std::move(getterMirror),
                                 std::move(setterMirror),
                                 std::move(symbolMirror),
                                 std::move(exceptionMirror)};
    if (!accumulator->Add(std::move(mirror))) return true;
  }
  if (!shouldSkipProto && ownProperties && !object->IsProxy() &&
      !accessorPropertiesOnly) {
    v8::Local<v8::Value> prototype = object->GetPrototype();
    if (prototype->IsObject()) {
      accumulator->Add(PropertyMirror{String16("__proto__"), true, true, false,
                                      true, false,
                                      ValueMirror::create(context, prototype),
                                      nullptr, nullptr, nullptr, nullptr});
    }
  }
  return true;
}

// static
void ValueMirror::getInternalProperties(
    v8::Local<v8::Context> context, v8::Local<v8::Object> object,
    std::vector<InternalPropertyMirror>* mirrors) {
  v8::Isolate* isolate = context->GetIsolate();
  v8::MicrotasksScope microtasksScope(isolate,
                                      v8::MicrotasksScope::kDoNotRunMicrotasks);
  v8::TryCatch tryCatch(isolate);
  if (object->IsFunction()) {
    v8::Local<v8::Function> function = object.As<v8::Function>();
    auto location = LocationMirror::create(function);
    if (location) {
      mirrors->emplace_back(InternalPropertyMirror{
          String16("[[FunctionLocation]]"), std::move(location)});
    }
    if (function->IsGeneratorFunction()) {
      mirrors->emplace_back(InternalPropertyMirror{
          String16("[[IsGenerator]]"),
          ValueMirror::create(context, v8::True(context->GetIsolate()))});
    }
  }
  if (object->IsGeneratorObject()) {
    auto location = LocationMirror::createForGenerator(object);
    if (location) {
      mirrors->emplace_back(InternalPropertyMirror{
          String16("[[GeneratorLocation]]"), std::move(location)});
    }
  }
  V8Debugger* debugger =
      static_cast<V8InspectorImpl*>(v8::debug::GetInspector(isolate))
          ->debugger();
  v8::Local<v8::Array> properties;
  if (debugger->internalProperties(context, object).ToLocal(&properties)) {
    for (uint32_t i = 0; i < properties->Length(); i += 2) {
      v8::Local<v8::Value> name;
      if (!properties->Get(context, i).ToLocal(&name) || !name->IsString()) {
        tryCatch.Reset();
        continue;
      }
      v8::Local<v8::Value> value;
      if (!properties->Get(context, i + 1).ToLocal(&value)) {
        tryCatch.Reset();
        continue;
      }
      auto wrapper = ValueMirror::create(context, value);
      if (wrapper) {
        mirrors->emplace_back(InternalPropertyMirror{
            toProtocolStringWithTypeCheck(context->GetIsolate(), name),
            std::move(wrapper)});
      }
    }
  }
}

// static
std::vector<PrivatePropertyMirror> ValueMirror::getPrivateProperties(
    v8::Local<v8::Context> context, v8::Local<v8::Object> object) {
  std::vector<PrivatePropertyMirror> mirrors;
  v8::Isolate* isolate = context->GetIsolate();
  v8::MicrotasksScope microtasksScope(isolate,
                                      v8::MicrotasksScope::kDoNotRunMicrotasks);
  v8::TryCatch tryCatch(isolate);
  v8::Local<v8::Array> privateProperties;

  std::vector<v8::Local<v8::Value>> names;
  std::vector<v8::Local<v8::Value>> values;
  if (!v8::debug::GetPrivateMembers(context, object, &names, &values))
    return mirrors;

  size_t len = values.size();
  for (size_t i = 0; i < len; i++) {
    v8::Local<v8::Value> name = names[i];
    DCHECK(name->IsString());
    v8::Local<v8::Value> value = values[i];

    std::unique_ptr<ValueMirror> valueMirror;
    std::unique_ptr<ValueMirror> getterMirror;
    std::unique_ptr<ValueMirror> setterMirror;
    if (v8::debug::AccessorPair::IsAccessorPair(value)) {
      v8::Local<v8::debug::AccessorPair> accessors =
          value.As<v8::debug::AccessorPair>();
      v8::Local<v8::Value> getter = accessors->getter();
      v8::Local<v8::Value> setter = accessors->setter();
      if (!getter->IsNull()) {
        getterMirror = ValueMirror::create(context, getter);
      }
      if (!setter->IsNull()) {
        setterMirror = ValueMirror::create(context, setter);
      }
    } else {
      valueMirror = ValueMirror::create(context, value);
    }

    mirrors.emplace_back(PrivatePropertyMirror{
        toProtocolStringWithTypeCheck(context->GetIsolate(), name),
        std::move(valueMirror), std::move(getterMirror),
        std::move(setterMirror)});
  }
  return mirrors;
}

String16 descriptionForNode(v8::Local<v8::Context> context,
                            v8::Local<v8::Value> value) {
  if (!value->IsObject()) return String16();
  v8::Local<v8::Object> object = value.As<v8::Object>();
  v8::Isolate* isolate = context->GetIsolate();
  v8::TryCatch tryCatch(isolate);
  v8::Local<v8::Value> nodeName;
  if (!object->Get(context, toV8String(isolate, "nodeName"))
           .ToLocal(&nodeName)) {
    return String16();
  }
  String16 description;
  v8::Local<v8::Function> toLowerCase =
      v8::debug::GetBuiltin(isolate, v8::debug::kStringToLowerCase);
  if (nodeName->IsString()) {
    if (!toLowerCase->Call(context, nodeName, 0, nullptr).ToLocal(&nodeName))
      return String16();
    if (nodeName->IsString()) {
      description = toProtocolString(isolate, nodeName.As<v8::String>());
    }
  }
  if (!description.length()) {
    v8::Local<v8::Value> value;
    if (!object->Get(context, toV8String(isolate, "constructor"))
             .ToLocal(&value) ||
        !value->IsObject()) {
      return String16();
    }
    if (!value.As<v8::Object>()
             ->Get(context, toV8String(isolate, "name"))
             .ToLocal(&value) ||
        !value->IsString()) {
      return String16();
    }
    description = toProtocolString(isolate, value.As<v8::String>());
  }
  v8::Local<v8::Value> nodeType;
  if (!object->Get(context, toV8String(isolate, "nodeType"))
           .ToLocal(&nodeType) ||
      !nodeType->IsInt32()) {
    return description;
  }
  if (nodeType.As<v8::Int32>()->Value() == 1) {
    v8::Local<v8::Value> idValue;
    if (!object->Get(context, toV8String(isolate, "id")).ToLocal(&idValue)) {
      return description;
    }
    if (idValue->IsString()) {
      String16 id = toProtocolString(isolate, idValue.As<v8::String>());
      if (id.length()) {
        description = String16::concat(description, '#', id);
      }
    }
    v8::Local<v8::Value> classNameValue;
    if (!object->Get(context, toV8String(isolate, "className"))
             .ToLocal(&classNameValue)) {
      return description;
    }
    if (classNameValue->IsString() &&
        classNameValue.As<v8::String>()->Length()) {
      String16 classes =
          toProtocolString(isolate, classNameValue.As<v8::String>());
      String16Builder output;
      bool previousIsDot = false;
      for (size_t i = 0; i < classes.length(); ++i) {
        if (classes[i] == ' ') {
          if (!previousIsDot) {
            output.append('.');
            previousIsDot = true;
          }
        } else {
          output.append(classes[i]);
          previousIsDot = classes[i] == '.';
        }
      }
      description = String16::concat(description, '.', output.toString());
    }
  } else if (nodeType.As<v8::Int32>()->Value() == 1) {
    return String16::concat("<!DOCTYPE ", description, '>');
  }
  return description;
}

String16 descriptionForTrustedType(v8::Local<v8::Context> context,
                                   v8::Local<v8::Value> value) {
  if (!value->IsObject()) return String16();
  v8::Local<v8::Object> object = value.As<v8::Object>();
  v8::Isolate* isolate = context->GetIsolate();
  v8::TryCatch tryCatch(isolate);

  v8::Local<v8::String> description;
  if (!object->ToString(context).ToLocal(&description)) return String16();
  return toProtocolString(isolate, description);
}

std::unique_ptr<ValueMirror> clientMirror(v8::Local<v8::Context> context,
                                          v8::Local<v8::Value> value,
                                          const String16& subtype) {
  // TODO(alph): description and length retrieval should move to embedder.
  auto descriptionForValueSubtype =
      clientFor(context)->descriptionForValueSubtype(context, value);
  if (descriptionForValueSubtype) {
    return std::make_unique<ObjectMirror>(
        value, subtype, toString16(descriptionForValueSubtype->string()));
  }
  if (subtype == "node") {
    return std::make_unique<ObjectMirror>(value, subtype,
                                          descriptionForNode(context, value));
  }
  if (subtype == "trustedtype") {
    return std::make_unique<ObjectMirror>(
        value, subtype, descriptionForTrustedType(context, value));
  }
  if (subtype == "error") {
    return std::make_unique<ObjectMirror>(
        value, RemoteObject::SubtypeEnum::Error,
        descriptionForError(context, value.As<v8::Object>(),
                            ErrorType::kClient));
  }
  if (subtype == "array" && value->IsObject()) {
    v8::Isolate* isolate = context->GetIsolate();
    v8::TryCatch tryCatch(isolate);
    v8::Local<v8::Object> object = value.As<v8::Object>();
    v8::Local<v8::Value> lengthValue;
    if (object->Get(context, toV8String(isolate, "length"))
            .ToLocal(&lengthValue)) {
      if (lengthValue->IsInt32()) {
        return std::make_unique<ObjectMirror>(
            value, RemoteObject::SubtypeEnum::Array,
            descriptionForCollection(isolate, object,
                                     lengthValue.As<v8::Int32>()->Value()));
      }
    }
  }
  return std::make_unique<ObjectMirror>(
      value,
      descriptionForObject(context->GetIsolate(), value.As<v8::Object>()));
}

std::unique_ptr<ValueMirror> ValueMirror::create(v8::Local<v8::Context> context,
                                                 v8::Local<v8::Value> value) {
  if (value->IsNull()) {
    return std::make_unique<PrimitiveValueMirror>(
        value, RemoteObject::TypeEnum::Object);
  }
  if (value->IsBoolean()) {
    return std::make_unique<PrimitiveValueMirror>(
        value, RemoteObject::TypeEnum::Boolean);
  }
  if (value->IsNumber()) {
    return std::make_unique<NumberMirror>(value.As<v8::Number>());
  }
  v8::Isolate* isolate = context->GetIsolate();
  if (value->IsString()) {
    return std::make_unique<PrimitiveValueMirror>(
        value, RemoteObject::TypeEnum::String);
  }
  if (value->IsBigInt()) {
    return std::make_unique<BigIntMirror>(value.As<v8::BigInt>());
  }
  if (value->IsSymbol()) {
    return std::make_unique<SymbolMirror>(value.As<v8::Symbol>());
  }
  if (v8::debug::WasmValue::IsWasmValue(value)) {
    return std::make_unique<WasmValueMirror>(value.As<v8::debug::WasmValue>());
  }
  auto clientSubtype = (value->IsUndefined() || value->IsObject())
                           ? clientFor(context)->valueSubtype(value)
                           : nullptr;
  if (clientSubtype) {
    String16 subtype = toString16(clientSubtype->string());
    return clientMirror(context, value, subtype);
  }
  if (value->IsUndefined()) {
    return std::make_unique<PrimitiveValueMirror>(
        value, RemoteObject::TypeEnum::Undefined);
  }
  if (value->IsRegExp()) {
    return std::make_unique<ObjectMirror>(
        value, RemoteObject::SubtypeEnum::Regexp,
        descriptionForRegExp(isolate, value.As<v8::RegExp>()));
  }
  if (value->IsProxy()) {
    return std::make_unique<ObjectMirror>(
        value, RemoteObject::SubtypeEnum::Proxy, "Proxy");
  }
  if (value->IsFunction()) {
    return std::make_unique<FunctionMirror>(value);
  }
  if (value->IsDate()) {
    return std::make_unique<ObjectMirror>(
        value, RemoteObject::SubtypeEnum::Date,
        descriptionForDate(context, value.As<v8::Date>()));
  }
  if (value->IsPromise()) {
    v8::Local<v8::Promise> promise = value.As<v8::Promise>();
    return std::make_unique<ObjectMirror>(
        promise, RemoteObject::SubtypeEnum::Promise,
        descriptionForObject(isolate, promise));
  }
  if (value->IsNativeError()) {
    return std::make_unique<ObjectMirror>(
        value, RemoteObject::SubtypeEnum::Error,
        descriptionForError(context, value.As<v8::Object>(),
                            ErrorType::kNative));
  }
  if (value->IsMap()) {
    v8::Local<v8::Map> map = value.As<v8::Map>();
    return std::make_unique<ObjectMirror>(
        value, RemoteObject::SubtypeEnum::Map,
        descriptionForCollection(isolate, map, map->Size()));
  }
  if (value->IsSet()) {
    v8::Local<v8::Set> set = value.As<v8::Set>();
    return std::make_unique<ObjectMirror>(
        value, RemoteObject::SubtypeEnum::Set,
        descriptionForCollection(isolate, set, set->Size()));
  }
  if (value->IsWeakMap()) {
    return std::make_unique<ObjectMirror>(
        value, RemoteObject::SubtypeEnum::Weakmap,
        descriptionForObject(isolate, value.As<v8::Object>()));
  }
  if (value->IsWeakSet()) {
    return std::make_unique<ObjectMirror>(
        value, RemoteObject::SubtypeEnum::Weakset,
        descriptionForObject(isolate, value.As<v8::Object>()));
  }
  if (value->IsMapIterator() || value->IsSetIterator()) {
    return std::make_unique<ObjectMirror>(
        value, RemoteObject::SubtypeEnum::Iterator,
        descriptionForObject(isolate, value.As<v8::Object>()));
  }
  if (value->IsGeneratorObject()) {
    v8::Local<v8::Object> object = value.As<v8::Object>();
    return std::make_unique<ObjectMirror>(
        object, RemoteObject::SubtypeEnum::Generator,
        descriptionForObject(isolate, object));
  }
  if (value->IsTypedArray()) {
    v8::Local<v8::TypedArray> array = value.As<v8::TypedArray>();
    return std::make_unique<ObjectMirror>(
        value, RemoteObject::SubtypeEnum::Typedarray,
        descriptionForCollection(isolate, array, array->Length()));
  }
  if (value->IsArrayBuffer()) {
    v8::Local<v8::ArrayBuffer> buffer = value.As<v8::ArrayBuffer>();
    return std::make_unique<ObjectMirror>(
        value, RemoteObject::SubtypeEnum::Arraybuffer,
        descriptionForCollection(isolate, buffer, buffer->ByteLength()));
  }
  if (value->IsSharedArrayBuffer()) {
    v8::Local<v8::SharedArrayBuffer> buffer = value.As<v8::SharedArrayBuffer>();
    return std::make_unique<ObjectMirror>(
        value, RemoteObject::SubtypeEnum::Arraybuffer,
        descriptionForCollection(isolate, buffer, buffer->ByteLength()));
  }
  if (value->IsDataView()) {
    v8::Local<v8::DataView> view = value.As<v8::DataView>();
    return std::make_unique<ObjectMirror>(
        value, RemoteObject::SubtypeEnum::Dataview,
        descriptionForCollection(isolate, view, view->ByteLength()));
  }
  V8InternalValueType internalType =
      v8InternalValueTypeFrom(context, v8::Local<v8::Object>::Cast(value));
  if (value->IsArray() && internalType == V8InternalValueType::kScopeList) {
    return std::make_unique<ObjectMirror>(
        value, "internal#scopeList",
        descriptionForScopeList(value.As<v8::Array>()));
  }
  if (value->IsObject() && internalType == V8InternalValueType::kEntry) {
    return std::make_unique<ObjectMirror>(
        value, "internal#entry",
        descriptionForEntry(context, value.As<v8::Object>()));
  }
  if (value->IsObject() && internalType == V8InternalValueType::kScope) {
    return std::make_unique<ObjectMirror>(
        value, "internal#scope",
        descriptionForScope(context, value.As<v8::Object>()));
  }
  size_t length = 0;
  if (value->IsArray() || isArrayLike(context, value, &length)) {
    length = value->IsArray() ? value.As<v8::Array>()->Length() : length;
    return std::make_unique<ObjectMirror>(
        value, RemoteObject::SubtypeEnum::Array,
        descriptionForCollection(isolate, value.As<v8::Object>(), length));
  }
  if (value->IsObject()) {
    return std::make_unique<ObjectMirror>(
        value, descriptionForObject(isolate, value.As<v8::Object>()));
  }
  return nullptr;
}
}  // namespace v8_inspector
