// 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>());
}

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

  if (value->IsNull() || value->IsUndefined()) {
    *result = protocol::Value::null();
    return Response::OK();
  }
  if (value->IsBoolean()) {
    *result =
        protocol::FundamentalValue::create(value.As<v8::Boolean>()->Value());
    return Response::OK();
  }
  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::OK();
      }
    }
    *result = protocol::FundamentalValue::create(doubleValue);
    return Response::OK();
  }
  if (value->IsString()) {
    *result = protocol::StringValue::create(
        toProtocolString(context->GetIsolate(), value.As<v8::String>()));
    return Response::OK();
  }
  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::OK();
  }
  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::OK();
  }
  return Response::Error("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::OK();
  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::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::OK();
  }

  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 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::OK();
  }
  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::OK();
  }

  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::Error("Object couldn't be returned by value");
    }
    *result = RemoteObject::create()
                  .setType(RemoteObject::TypeEnum::Symbol)
                  .setDescription(descriptionForSymbol(context, m_symbol))
                  .build();
    return Response::OK();
  }

  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::OK();
  }
  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::OK();
  }

  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>& blacklist,
                             int skipIndex, int* nameLimit, int* indexLimit,
                             bool* overflow,
                             std::vector<PropertyMirror>* mirrors)
      : m_blacklist(blacklist),
        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_blacklist.begin(), m_blacklist.end(), mirror.name) !=
        m_blacklist.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_blacklist;
  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> blacklist;
  size_t length = 0;
  if (object->IsArray() || isArrayLike(context, object, &length) ||
      object->IsStringObject()) {
    blacklist.push_back("length");
  } else {
    auto clientSubtype = clientFor(context)->valueSubtype(object);
    if (clientSubtype && toString16(clientSubtype->string()) == "array") {
      blacklist.push_back("length");
    }
  }
  if (object->IsArrayBuffer() || object->IsSharedArrayBuffer()) {
    blacklist.push_back("[[Int8Array]]");
    blacklist.push_back("[[Uint8Array]]");
    blacklist.push_back("[[Int16Array]]");
    blacklist.push_back("[[Int32Array]]");
  }
  int skipIndex = object->IsStringObject()
                      ? object.As<v8::StringObject>()->ValueOf()->Length() + 1
                      : -1;
  PreviewPropertyAccumulator accumulator(blacklist, 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> whitelist;
  if (object->IsBooleanObject() || object->IsNumberObject() ||
      object->IsStringObject() || object->IsSymbolObject() ||
      object->IsBigIntObject()) {
    whitelist.emplace_back("[[PrimitiveValue]]");
  } else if (object->IsPromise()) {
    whitelist.emplace_back("[[PromiseStatus]]");
    whitelist.emplace_back("[[PromiseValue]]");
  } else if (object->IsGeneratorObject()) {
    whitelist.emplace_back("[[GeneratorStatus]]");
  }
  for (auto& mirror : mirrors) {
    if (std::find(whitelist.begin(), whitelist.end(), mirror.name) ==
        whitelist.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);
  std::vector<String16> whitelist;
  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::OK();
  }

  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;
}

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.
  if (subtype == "node") {
    return std::make_unique<ObjectMirror>(value, subtype,
                                          descriptionForNode(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>());
  }
  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
