// Copyright 2016 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "src/inspector/v8-console-message.h"

#include "src/debug/debug-interface.h"
#include "src/inspector/inspected-context.h"
#include "src/inspector/protocol/Protocol.h"
#include "src/inspector/string-util.h"
#include "src/inspector/v8-console-agent-impl.h"
#include "src/inspector/v8-inspector-impl.h"
#include "src/inspector/v8-inspector-session-impl.h"
#include "src/inspector/v8-runtime-agent-impl.h"
#include "src/inspector/v8-stack-trace-impl.h"
#include "src/tracing/trace-event.h"

#include "include/v8-inspector.h"

namespace v8_inspector {

namespace {

String16 consoleAPITypeValue(ConsoleAPIType type) {
  switch (type) {
    case ConsoleAPIType::kLog:
      return protocol::Runtime::ConsoleAPICalled::TypeEnum::Log;
    case ConsoleAPIType::kDebug:
      return protocol::Runtime::ConsoleAPICalled::TypeEnum::Debug;
    case ConsoleAPIType::kInfo:
      return protocol::Runtime::ConsoleAPICalled::TypeEnum::Info;
    case ConsoleAPIType::kError:
      return protocol::Runtime::ConsoleAPICalled::TypeEnum::Error;
    case ConsoleAPIType::kWarning:
      return protocol::Runtime::ConsoleAPICalled::TypeEnum::Warning;
    case ConsoleAPIType::kClear:
      return protocol::Runtime::ConsoleAPICalled::TypeEnum::Clear;
    case ConsoleAPIType::kDir:
      return protocol::Runtime::ConsoleAPICalled::TypeEnum::Dir;
    case ConsoleAPIType::kDirXML:
      return protocol::Runtime::ConsoleAPICalled::TypeEnum::Dirxml;
    case ConsoleAPIType::kTable:
      return protocol::Runtime::ConsoleAPICalled::TypeEnum::Table;
    case ConsoleAPIType::kTrace:
      return protocol::Runtime::ConsoleAPICalled::TypeEnum::Trace;
    case ConsoleAPIType::kStartGroup:
      return protocol::Runtime::ConsoleAPICalled::TypeEnum::StartGroup;
    case ConsoleAPIType::kStartGroupCollapsed:
      return protocol::Runtime::ConsoleAPICalled::TypeEnum::StartGroupCollapsed;
    case ConsoleAPIType::kEndGroup:
      return protocol::Runtime::ConsoleAPICalled::TypeEnum::EndGroup;
    case ConsoleAPIType::kAssert:
      return protocol::Runtime::ConsoleAPICalled::TypeEnum::Assert;
    case ConsoleAPIType::kTimeEnd:
      return protocol::Runtime::ConsoleAPICalled::TypeEnum::TimeEnd;
    case ConsoleAPIType::kCount:
      return protocol::Runtime::ConsoleAPICalled::TypeEnum::Count;
  }
  return protocol::Runtime::ConsoleAPICalled::TypeEnum::Log;
}

const char kGlobalConsoleMessageHandleLabel[] = "DevTools console";
const unsigned maxConsoleMessageCount = 1000;
const int maxConsoleMessageV8Size = 10 * 1024 * 1024;
const unsigned maxArrayItemsLimit = 10000;
const unsigned maxStackDepthLimit = 32;

class V8ValueStringBuilder {
 public:
  static String16 toString(v8::Local<v8::Value> value,
                           v8::Local<v8::Context> context) {
    V8ValueStringBuilder builder(context);
    if (!builder.append(value)) return String16();
    return builder.toString();
  }

 private:
  enum {
    IgnoreNull = 1 << 0,
    IgnoreUndefined = 1 << 1,
  };

  explicit V8ValueStringBuilder(v8::Local<v8::Context> context)
      : m_arrayLimit(maxArrayItemsLimit),
        m_isolate(context->GetIsolate()),
        m_tryCatch(context->GetIsolate()),
        m_context(context) {}

  bool append(v8::Local<v8::Value> value, unsigned ignoreOptions = 0) {
    if (value.IsEmpty()) return true;
    if ((ignoreOptions & IgnoreNull) && value->IsNull()) return true;
    if ((ignoreOptions & IgnoreUndefined) && value->IsUndefined()) return true;
    if (value->IsString()) return append(v8::Local<v8::String>::Cast(value));
    if (value->IsStringObject())
      return append(v8::Local<v8::StringObject>::Cast(value)->ValueOf());
    if (value->IsBigInt()) return append(v8::Local<v8::BigInt>::Cast(value));
    if (value->IsBigIntObject())
      return append(v8::Local<v8::BigIntObject>::Cast(value)->ValueOf());
    if (value->IsSymbol()) return append(v8::Local<v8::Symbol>::Cast(value));
    if (value->IsSymbolObject())
      return append(v8::Local<v8::SymbolObject>::Cast(value)->ValueOf());
    if (value->IsNumberObject()) {
      m_builder.append(String16::fromDouble(
          v8::Local<v8::NumberObject>::Cast(value)->ValueOf(), 6));
      return true;
    }
    if (value->IsBooleanObject()) {
      m_builder.append(v8::Local<v8::BooleanObject>::Cast(value)->ValueOf()
                           ? "true"
                           : "false");
      return true;
    }
    if (value->IsArray()) return append(v8::Local<v8::Array>::Cast(value));
    if (value->IsProxy()) {
      m_builder.append("[object Proxy]");
      return true;
    }
    if (value->IsObject() && !value->IsDate() && !value->IsFunction() &&
        !value->IsNativeError() && !value->IsRegExp()) {
      v8::Local<v8::Object> object = v8::Local<v8::Object>::Cast(value);
      v8::Local<v8::String> stringValue;
      if (object->ObjectProtoToString(m_context).ToLocal(&stringValue))
        return append(stringValue);
    }
    v8::Local<v8::String> stringValue;
    if (!value->ToString(m_context).ToLocal(&stringValue)) return false;
    return append(stringValue);
  }

  bool append(v8::Local<v8::Array> array) {
    for (const auto& it : m_visitedArrays) {
      if (it == array) return true;
    }
    uint32_t length = array->Length();
    if (length > m_arrayLimit) return false;
    if (m_visitedArrays.size() > maxStackDepthLimit) return false;

    bool result = true;
    m_arrayLimit -= length;
    m_visitedArrays.push_back(array);
    for (uint32_t i = 0; i < length; ++i) {
      if (i) m_builder.append(',');
      v8::Local<v8::Value> value;
      if (!array->Get(m_context, i).ToLocal(&value)) continue;
      if (!append(value, IgnoreNull | IgnoreUndefined)) {
        result = false;
        break;
      }
    }
    m_visitedArrays.pop_back();
    return result;
  }

  bool append(v8::Local<v8::Symbol> symbol) {
    m_builder.append("Symbol(");
    bool result = append(symbol->Name(), IgnoreUndefined);
    m_builder.append(')');
    return result;
  }

  bool append(v8::Local<v8::BigInt> bigint) {
    v8::Local<v8::String> bigint_string;
    if (!bigint->ToString(m_context).ToLocal(&bigint_string)) return false;
    bool result = append(bigint_string);
    if (m_tryCatch.HasCaught()) return false;
    m_builder.append('n');
    return result;
  }

  bool append(v8::Local<v8::String> string) {
    if (m_tryCatch.HasCaught()) return false;
    if (!string.IsEmpty()) {
      m_builder.append(toProtocolString(m_isolate, string));
    }
    return true;
  }

  String16 toString() {
    if (m_tryCatch.HasCaught()) return String16();
    return m_builder.toString();
  }

  uint32_t m_arrayLimit;
  v8::Isolate* m_isolate;
  String16Builder m_builder;
  std::vector<v8::Local<v8::Array>> m_visitedArrays;
  v8::TryCatch m_tryCatch;
  v8::Local<v8::Context> m_context;
};

}  // namespace

V8ConsoleMessage::V8ConsoleMessage(V8MessageOrigin origin, double timestamp,
                                   const String16& message)
    : m_origin(origin),
      m_timestamp(timestamp),
      m_message(message),
      m_lineNumber(0),
      m_columnNumber(0),
      m_scriptId(0),
      m_contextId(0),
      m_type(ConsoleAPIType::kLog),
      m_exceptionId(0),
      m_revokedExceptionId(0) {}

V8ConsoleMessage::~V8ConsoleMessage() = default;

void V8ConsoleMessage::setLocation(const String16& url, unsigned lineNumber,
                                   unsigned columnNumber,
                                   std::unique_ptr<V8StackTraceImpl> stackTrace,
                                   int scriptId) {
  m_url = url;
  m_lineNumber = lineNumber;
  m_columnNumber = columnNumber;
  m_stackTrace = std::move(stackTrace);
  m_scriptId = scriptId;
}

void V8ConsoleMessage::reportToFrontend(
    protocol::Console::Frontend* frontend) const {
  DCHECK_EQ(V8MessageOrigin::kConsole, m_origin);
  String16 level = protocol::Console::ConsoleMessage::LevelEnum::Log;
  if (m_type == ConsoleAPIType::kDebug || m_type == ConsoleAPIType::kCount ||
      m_type == ConsoleAPIType::kTimeEnd)
    level = protocol::Console::ConsoleMessage::LevelEnum::Debug;
  else if (m_type == ConsoleAPIType::kError ||
           m_type == ConsoleAPIType::kAssert)
    level = protocol::Console::ConsoleMessage::LevelEnum::Error;
  else if (m_type == ConsoleAPIType::kWarning)
    level = protocol::Console::ConsoleMessage::LevelEnum::Warning;
  else if (m_type == ConsoleAPIType::kInfo)
    level = protocol::Console::ConsoleMessage::LevelEnum::Info;
  std::unique_ptr<protocol::Console::ConsoleMessage> result =
      protocol::Console::ConsoleMessage::create()
          .setSource(protocol::Console::ConsoleMessage::SourceEnum::ConsoleApi)
          .setLevel(level)
          .setText(m_message)
          .build();
  result->setLine(static_cast<int>(m_lineNumber));
  result->setColumn(static_cast<int>(m_columnNumber));
  result->setUrl(m_url);
  frontend->messageAdded(std::move(result));
}

std::unique_ptr<protocol::Array<protocol::Runtime::RemoteObject>>
V8ConsoleMessage::wrapArguments(V8InspectorSessionImpl* session,
                                bool generatePreview) const {
  V8InspectorImpl* inspector = session->inspector();
  int contextGroupId = session->contextGroupId();
  int contextId = m_contextId;
  if (!m_arguments.size() || !contextId) return nullptr;
  InspectedContext* inspectedContext =
      inspector->getContext(contextGroupId, contextId);
  if (!inspectedContext) return nullptr;

  v8::Isolate* isolate = inspectedContext->isolate();
  v8::HandleScope handles(isolate);
  v8::Local<v8::Context> context = inspectedContext->context();

  auto args =
      v8::base::make_unique<protocol::Array<protocol::Runtime::RemoteObject>>();

  v8::Local<v8::Value> value = m_arguments[0]->Get(isolate);
  if (value->IsObject() && m_type == ConsoleAPIType::kTable &&
      generatePreview) {
    v8::MaybeLocal<v8::Array> columns;
    if (m_arguments.size() > 1) {
      v8::Local<v8::Value> secondArgument = m_arguments[1]->Get(isolate);
      if (secondArgument->IsArray()) {
        columns = v8::Local<v8::Array>::Cast(secondArgument);
      } else if (secondArgument->IsString()) {
        v8::TryCatch tryCatch(isolate);
        v8::Local<v8::Array> array = v8::Array::New(isolate);
        if (array->Set(context, 0, secondArgument).IsJust()) {
          columns = array;
        }
      }
    }
    std::unique_ptr<protocol::Runtime::RemoteObject> wrapped =
        session->wrapTable(context, v8::Local<v8::Object>::Cast(value),
                           columns);
    inspectedContext = inspector->getContext(contextGroupId, contextId);
    if (!inspectedContext) return nullptr;
    if (wrapped) {
      args->emplace_back(std::move(wrapped));
    } else {
      args = nullptr;
    }
  } else {
    for (size_t i = 0; i < m_arguments.size(); ++i) {
      std::unique_ptr<protocol::Runtime::RemoteObject> wrapped =
          session->wrapObject(context, m_arguments[i]->Get(isolate), "console",
                              generatePreview);
      inspectedContext = inspector->getContext(contextGroupId, contextId);
      if (!inspectedContext) return nullptr;
      if (!wrapped) {
        args = nullptr;
        break;
      }
      args->emplace_back(std::move(wrapped));
    }
  }
  return args;
}

void V8ConsoleMessage::reportToFrontend(protocol::Runtime::Frontend* frontend,
                                        V8InspectorSessionImpl* session,
                                        bool generatePreview) const {
  int contextGroupId = session->contextGroupId();
  V8InspectorImpl* inspector = session->inspector();

  if (m_origin == V8MessageOrigin::kException) {
    std::unique_ptr<protocol::Runtime::RemoteObject> exception =
        wrapException(session, generatePreview);
    if (!inspector->hasConsoleMessageStorage(contextGroupId)) return;
    std::unique_ptr<protocol::Runtime::ExceptionDetails> exceptionDetails =
        protocol::Runtime::ExceptionDetails::create()
            .setExceptionId(m_exceptionId)
            .setText(exception ? m_message : m_detailedMessage)
            .setLineNumber(m_lineNumber ? m_lineNumber - 1 : 0)
            .setColumnNumber(m_columnNumber ? m_columnNumber - 1 : 0)
            .build();
    if (m_scriptId)
      exceptionDetails->setScriptId(String16::fromInteger(m_scriptId));
    if (!m_url.isEmpty()) exceptionDetails->setUrl(m_url);
    if (m_stackTrace) {
      exceptionDetails->setStackTrace(
          m_stackTrace->buildInspectorObjectImpl(inspector->debugger()));
    }
    if (m_contextId) exceptionDetails->setExecutionContextId(m_contextId);
    if (exception) exceptionDetails->setException(std::move(exception));
    frontend->exceptionThrown(m_timestamp, std::move(exceptionDetails));
    return;
  }
  if (m_origin == V8MessageOrigin::kRevokedException) {
    frontend->exceptionRevoked(m_message, m_revokedExceptionId);
    return;
  }
  if (m_origin == V8MessageOrigin::kConsole) {
    std::unique_ptr<protocol::Array<protocol::Runtime::RemoteObject>>
        arguments = wrapArguments(session, generatePreview);
    if (!inspector->hasConsoleMessageStorage(contextGroupId)) return;
    if (!arguments) {
      arguments = v8::base::make_unique<
          protocol::Array<protocol::Runtime::RemoteObject>>();
      if (!m_message.isEmpty()) {
        std::unique_ptr<protocol::Runtime::RemoteObject> messageArg =
            protocol::Runtime::RemoteObject::create()
                .setType(protocol::Runtime::RemoteObject::TypeEnum::String)
                .build();
        messageArg->setValue(protocol::StringValue::create(m_message));
        arguments->emplace_back(std::move(messageArg));
      }
    }
    Maybe<String16> consoleContext;
    if (!m_consoleContext.isEmpty()) consoleContext = m_consoleContext;
    std::unique_ptr<protocol::Runtime::StackTrace> stackTrace;
    if (m_stackTrace) {
      switch (m_type) {
        case ConsoleAPIType::kAssert:
        case ConsoleAPIType::kError:
        case ConsoleAPIType::kTrace:
        case ConsoleAPIType::kWarning:
          stackTrace =
              m_stackTrace->buildInspectorObjectImpl(inspector->debugger());
          break;
        default:
          stackTrace =
              m_stackTrace->buildInspectorObjectImpl(inspector->debugger(), 0);
          break;
      }
    }
    frontend->consoleAPICalled(
        consoleAPITypeValue(m_type), std::move(arguments), m_contextId,
        m_timestamp, std::move(stackTrace), std::move(consoleContext));
    return;
  }
  UNREACHABLE();
}

std::unique_ptr<protocol::Runtime::RemoteObject>
V8ConsoleMessage::wrapException(V8InspectorSessionImpl* session,
                                bool generatePreview) const {
  if (!m_arguments.size() || !m_contextId) return nullptr;
  DCHECK_EQ(1u, m_arguments.size());
  InspectedContext* inspectedContext =
      session->inspector()->getContext(session->contextGroupId(), m_contextId);
  if (!inspectedContext) return nullptr;

  v8::Isolate* isolate = inspectedContext->isolate();
  v8::HandleScope handles(isolate);
  // TODO(dgozman): should we use different object group?
  return session->wrapObject(inspectedContext->context(),
                             m_arguments[0]->Get(isolate), "console",
                             generatePreview);
}

V8MessageOrigin V8ConsoleMessage::origin() const { return m_origin; }

ConsoleAPIType V8ConsoleMessage::type() const { return m_type; }

// static
std::unique_ptr<V8ConsoleMessage> V8ConsoleMessage::createForConsoleAPI(
    v8::Local<v8::Context> v8Context, int contextId, int groupId,
    V8InspectorImpl* inspector, double timestamp, ConsoleAPIType type,
    const std::vector<v8::Local<v8::Value>>& arguments,
    const String16& consoleContext,
    std::unique_ptr<V8StackTraceImpl> stackTrace) {
  v8::Isolate* isolate = v8Context->GetIsolate();

  std::unique_ptr<V8ConsoleMessage> message(
      new V8ConsoleMessage(V8MessageOrigin::kConsole, timestamp, String16()));
  if (stackTrace && !stackTrace->isEmpty()) {
    message->m_url = toString16(stackTrace->topSourceURL());
    message->m_lineNumber = stackTrace->topLineNumber();
    message->m_columnNumber = stackTrace->topColumnNumber();
  }
  message->m_stackTrace = std::move(stackTrace);
  message->m_consoleContext = consoleContext;
  message->m_type = type;
  message->m_contextId = contextId;
  for (size_t i = 0; i < arguments.size(); ++i) {
    std::unique_ptr<v8::Global<v8::Value>> argument(
        new v8::Global<v8::Value>(isolate, arguments.at(i)));
    argument->AnnotateStrongRetainer(kGlobalConsoleMessageHandleLabel);
    message->m_arguments.push_back(std::move(argument));
    message->m_v8Size +=
        v8::debug::EstimatedValueSize(isolate, arguments.at(i));
  }
  for (size_t i = 0, num_args = arguments.size(); i < num_args; ++i) {
    if (i) message->m_message += String16(" ");
    message->m_message +=
        V8ValueStringBuilder::toString(arguments[i], v8Context);
  }

  v8::Isolate::MessageErrorLevel clientLevel = v8::Isolate::kMessageInfo;
  if (type == ConsoleAPIType::kDebug || type == ConsoleAPIType::kCount ||
      type == ConsoleAPIType::kTimeEnd) {
    clientLevel = v8::Isolate::kMessageDebug;
  } else if (type == ConsoleAPIType::kError ||
             type == ConsoleAPIType::kAssert) {
    clientLevel = v8::Isolate::kMessageError;
  } else if (type == ConsoleAPIType::kWarning) {
    clientLevel = v8::Isolate::kMessageWarning;
  } else if (type == ConsoleAPIType::kInfo || type == ConsoleAPIType::kLog) {
    clientLevel = v8::Isolate::kMessageInfo;
  }

  if (type != ConsoleAPIType::kClear) {
    inspector->client()->consoleAPIMessage(
        groupId, clientLevel, toStringView(message->m_message),
        toStringView(message->m_url), message->m_lineNumber,
        message->m_columnNumber, message->m_stackTrace.get());
  }

  return message;
}

// static
std::unique_ptr<V8ConsoleMessage> V8ConsoleMessage::createForException(
    double timestamp, const String16& detailedMessage, const String16& url,
    unsigned lineNumber, unsigned columnNumber,
    std::unique_ptr<V8StackTraceImpl> stackTrace, int scriptId,
    v8::Isolate* isolate, const String16& message, int contextId,
    v8::Local<v8::Value> exception, unsigned exceptionId) {
  std::unique_ptr<V8ConsoleMessage> consoleMessage(
      new V8ConsoleMessage(V8MessageOrigin::kException, timestamp, message));
  consoleMessage->setLocation(url, lineNumber, columnNumber,
                              std::move(stackTrace), scriptId);
  consoleMessage->m_exceptionId = exceptionId;
  consoleMessage->m_detailedMessage = detailedMessage;
  if (contextId && !exception.IsEmpty()) {
    consoleMessage->m_contextId = contextId;
    consoleMessage->m_arguments.push_back(
        std::unique_ptr<v8::Global<v8::Value>>(
            new v8::Global<v8::Value>(isolate, exception)));
    consoleMessage->m_v8Size +=
        v8::debug::EstimatedValueSize(isolate, exception);
  }
  return consoleMessage;
}

// static
std::unique_ptr<V8ConsoleMessage> V8ConsoleMessage::createForRevokedException(
    double timestamp, const String16& messageText,
    unsigned revokedExceptionId) {
  std::unique_ptr<V8ConsoleMessage> message(new V8ConsoleMessage(
      V8MessageOrigin::kRevokedException, timestamp, messageText));
  message->m_revokedExceptionId = revokedExceptionId;
  return message;
}

void V8ConsoleMessage::contextDestroyed(int contextId) {
  if (contextId != m_contextId) return;
  m_contextId = 0;
  if (m_message.isEmpty()) m_message = "<message collected>";
  Arguments empty;
  m_arguments.swap(empty);
  m_v8Size = 0;
}

// ------------------------ V8ConsoleMessageStorage ----------------------------

V8ConsoleMessageStorage::V8ConsoleMessageStorage(V8InspectorImpl* inspector,
                                                 int contextGroupId)
    : m_inspector(inspector), m_contextGroupId(contextGroupId) {}

V8ConsoleMessageStorage::~V8ConsoleMessageStorage() { clear(); }

namespace {

void TraceV8ConsoleMessageEvent(V8MessageOrigin origin, ConsoleAPIType type) {
  // Change in this function requires adjustment of Catapult/Telemetry metric
  // tracing/tracing/metrics/console_error_metric.html.
  // See https://crbug.com/880432
  if (origin == V8MessageOrigin::kException) {
    TRACE_EVENT_INSTANT0("v8.console", "V8ConsoleMessage::Exception",
                         TRACE_EVENT_SCOPE_THREAD);
  } else if (type == ConsoleAPIType::kError) {
    TRACE_EVENT_INSTANT0("v8.console", "V8ConsoleMessage::Error",
                         TRACE_EVENT_SCOPE_THREAD);
  } else if (type == ConsoleAPIType::kAssert) {
    TRACE_EVENT_INSTANT0("v8.console", "V8ConsoleMessage::Assert",
                         TRACE_EVENT_SCOPE_THREAD);
  }
}

}  // anonymous namespace

void V8ConsoleMessageStorage::addMessage(
    std::unique_ptr<V8ConsoleMessage> message) {
  int contextGroupId = m_contextGroupId;
  V8InspectorImpl* inspector = m_inspector;
  if (message->type() == ConsoleAPIType::kClear) clear();

  TraceV8ConsoleMessageEvent(message->origin(), message->type());

  inspector->forEachSession(
      contextGroupId, [&message](V8InspectorSessionImpl* session) {
        if (message->origin() == V8MessageOrigin::kConsole)
          session->consoleAgent()->messageAdded(message.get());
        session->runtimeAgent()->messageAdded(message.get());
      });
  if (!inspector->hasConsoleMessageStorage(contextGroupId)) return;

  DCHECK(m_messages.size() <= maxConsoleMessageCount);
  if (m_messages.size() == maxConsoleMessageCount) {
    m_estimatedSize -= m_messages.front()->estimatedSize();
    m_messages.pop_front();
  }
  while (m_estimatedSize + message->estimatedSize() > maxConsoleMessageV8Size &&
         !m_messages.empty()) {
    m_estimatedSize -= m_messages.front()->estimatedSize();
    m_messages.pop_front();
  }

  m_messages.push_back(std::move(message));
  m_estimatedSize += m_messages.back()->estimatedSize();
}

void V8ConsoleMessageStorage::clear() {
  m_messages.clear();
  m_estimatedSize = 0;
  m_inspector->forEachSession(m_contextGroupId,
                              [](V8InspectorSessionImpl* session) {
                                session->releaseObjectGroup("console");
                              });
  m_data.clear();
}

bool V8ConsoleMessageStorage::shouldReportDeprecationMessage(
    int contextId, const String16& method) {
  std::set<String16>& reportedDeprecationMessages =
      m_data[contextId].m_reportedDeprecationMessages;
  auto it = reportedDeprecationMessages.find(method);
  if (it != reportedDeprecationMessages.end()) return false;
  reportedDeprecationMessages.insert(it, method);
  return true;
}

int V8ConsoleMessageStorage::count(int contextId, const String16& id) {
  return ++m_data[contextId].m_count[id];
}

void V8ConsoleMessageStorage::time(int contextId, const String16& id) {
  m_data[contextId].m_time[id] = m_inspector->client()->currentTimeMS();
}

bool V8ConsoleMessageStorage::countReset(int contextId, const String16& id) {
  std::map<String16, int>& count_map = m_data[contextId].m_count;
  if (count_map.find(id) == count_map.end()) return false;

  count_map[id] = 0;
  return true;
}

double V8ConsoleMessageStorage::timeLog(int contextId, const String16& id) {
  std::map<String16, double>& time = m_data[contextId].m_time;
  auto it = time.find(id);
  if (it == time.end()) return 0.0;
  return m_inspector->client()->currentTimeMS() - it->second;
}

double V8ConsoleMessageStorage::timeEnd(int contextId, const String16& id) {
  std::map<String16, double>& time = m_data[contextId].m_time;
  auto it = time.find(id);
  if (it == time.end()) return 0.0;
  double elapsed = m_inspector->client()->currentTimeMS() - it->second;
  time.erase(it);
  return elapsed;
}

bool V8ConsoleMessageStorage::hasTimer(int contextId, const String16& id) {
  const std::map<String16, double>& time = m_data[contextId].m_time;
  return time.find(id) != time.end();
}

void V8ConsoleMessageStorage::contextDestroyed(int contextId) {
  m_estimatedSize = 0;
  for (size_t i = 0; i < m_messages.size(); ++i) {
    m_messages[i]->contextDestroyed(contextId);
    m_estimatedSize += m_messages[i]->estimatedSize();
  }
  auto it = m_data.find(contextId);
  if (it != m_data.end()) m_data.erase(contextId);
}

}  // namespace v8_inspector
