| OLD | NEW |
| (Empty) |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "platform/v8_inspector/V8ConsoleMessage.h" | |
| 6 | |
| 7 #include "platform/v8_inspector/InspectedContext.h" | |
| 8 #include "platform/v8_inspector/StringUtil.h" | |
| 9 #include "platform/v8_inspector/V8ConsoleAgentImpl.h" | |
| 10 #include "platform/v8_inspector/V8InspectorImpl.h" | |
| 11 #include "platform/v8_inspector/V8InspectorSessionImpl.h" | |
| 12 #include "platform/v8_inspector/V8RuntimeAgentImpl.h" | |
| 13 #include "platform/v8_inspector/V8StackTraceImpl.h" | |
| 14 #include "platform/v8_inspector/protocol/Protocol.h" | |
| 15 #include "platform/v8_inspector/public/V8InspectorClient.h" | |
| 16 | |
| 17 namespace v8_inspector { | |
| 18 | |
| 19 namespace { | |
| 20 | |
| 21 String16 consoleAPITypeValue(ConsoleAPIType type) | |
| 22 { | |
| 23 switch (type) { | |
| 24 case ConsoleAPIType::kLog: return protocol::Runtime::ConsoleAPICalled::TypeE
num::Log; | |
| 25 case ConsoleAPIType::kDebug: return protocol::Runtime::ConsoleAPICalled::Typ
eEnum::Debug; | |
| 26 case ConsoleAPIType::kInfo: return protocol::Runtime::ConsoleAPICalled::Type
Enum::Info; | |
| 27 case ConsoleAPIType::kError: return protocol::Runtime::ConsoleAPICalled::Typ
eEnum::Error; | |
| 28 case ConsoleAPIType::kWarning: return protocol::Runtime::ConsoleAPICalled::T
ypeEnum::Warning; | |
| 29 case ConsoleAPIType::kClear: return protocol::Runtime::ConsoleAPICalled::Typ
eEnum::Clear; | |
| 30 case ConsoleAPIType::kDir: return protocol::Runtime::ConsoleAPICalled::TypeE
num::Dir; | |
| 31 case ConsoleAPIType::kDirXML: return protocol::Runtime::ConsoleAPICalled::Ty
peEnum::Dirxml; | |
| 32 case ConsoleAPIType::kTable: return protocol::Runtime::ConsoleAPICalled::Typ
eEnum::Table; | |
| 33 case ConsoleAPIType::kTrace: return protocol::Runtime::ConsoleAPICalled::Typ
eEnum::Trace; | |
| 34 case ConsoleAPIType::kStartGroup: return protocol::Runtime::ConsoleAPICalled
::TypeEnum::StartGroup; | |
| 35 case ConsoleAPIType::kStartGroupCollapsed: return protocol::Runtime::Console
APICalled::TypeEnum::StartGroupCollapsed; | |
| 36 case ConsoleAPIType::kEndGroup: return protocol::Runtime::ConsoleAPICalled::
TypeEnum::EndGroup; | |
| 37 case ConsoleAPIType::kAssert: return protocol::Runtime::ConsoleAPICalled::Ty
peEnum::Assert; | |
| 38 case ConsoleAPIType::kTimeEnd: return protocol::Runtime::ConsoleAPICalled::T
ypeEnum::Debug; | |
| 39 case ConsoleAPIType::kCount: return protocol::Runtime::ConsoleAPICalled::Typ
eEnum::Debug; | |
| 40 } | |
| 41 return protocol::Runtime::ConsoleAPICalled::TypeEnum::Log; | |
| 42 } | |
| 43 | |
| 44 const unsigned maxConsoleMessageCount = 1000; | |
| 45 const unsigned maxArrayItemsLimit = 10000; | |
| 46 const unsigned maxStackDepthLimit = 32; | |
| 47 | |
| 48 class V8ValueStringBuilder { | |
| 49 public: | |
| 50 static String16 toString(v8::Local<v8::Value> value, v8::Isolate* isolate) | |
| 51 { | |
| 52 V8ValueStringBuilder builder(isolate); | |
| 53 if (!builder.append(value)) | |
| 54 return String16(); | |
| 55 return builder.toString(); | |
| 56 } | |
| 57 | |
| 58 private: | |
| 59 enum { | |
| 60 IgnoreNull = 1 << 0, | |
| 61 IgnoreUndefined = 1 << 1, | |
| 62 }; | |
| 63 | |
| 64 V8ValueStringBuilder(v8::Isolate* isolate) | |
| 65 : m_arrayLimit(maxArrayItemsLimit) | |
| 66 , m_isolate(isolate) | |
| 67 , m_tryCatch(isolate) | |
| 68 { | |
| 69 } | |
| 70 | |
| 71 bool append(v8::Local<v8::Value> value, unsigned ignoreOptions = 0) | |
| 72 { | |
| 73 if (value.IsEmpty()) | |
| 74 return true; | |
| 75 if ((ignoreOptions & IgnoreNull) && value->IsNull()) | |
| 76 return true; | |
| 77 if ((ignoreOptions & IgnoreUndefined) && value->IsUndefined()) | |
| 78 return true; | |
| 79 if (value->IsString()) | |
| 80 return append(v8::Local<v8::String>::Cast(value)); | |
| 81 if (value->IsStringObject()) | |
| 82 return append(v8::Local<v8::StringObject>::Cast(value)->ValueOf()); | |
| 83 if (value->IsSymbol()) | |
| 84 return append(v8::Local<v8::Symbol>::Cast(value)); | |
| 85 if (value->IsSymbolObject()) | |
| 86 return append(v8::Local<v8::SymbolObject>::Cast(value)->ValueOf()); | |
| 87 if (value->IsNumberObject()) { | |
| 88 m_builder.append(String16::fromDoublePrecision6(v8::Local<v8::Number
Object>::Cast(value)->ValueOf())); | |
| 89 return true; | |
| 90 } | |
| 91 if (value->IsBooleanObject()) { | |
| 92 m_builder.append(v8::Local<v8::BooleanObject>::Cast(value)->ValueOf(
) ? "true" : "false"); | |
| 93 return true; | |
| 94 } | |
| 95 if (value->IsArray()) | |
| 96 return append(v8::Local<v8::Array>::Cast(value)); | |
| 97 if (value->IsProxy()) { | |
| 98 m_builder.append("[object Proxy]"); | |
| 99 return true; | |
| 100 } | |
| 101 if (value->IsObject() | |
| 102 && !value->IsDate() | |
| 103 && !value->IsFunction() | |
| 104 && !value->IsNativeError() | |
| 105 && !value->IsRegExp()) { | |
| 106 v8::Local<v8::Object> object = v8::Local<v8::Object>::Cast(value); | |
| 107 v8::Local<v8::String> stringValue; | |
| 108 if (object->ObjectProtoToString(m_isolate->GetCurrentContext()).ToLo
cal(&stringValue)) | |
| 109 return append(stringValue); | |
| 110 } | |
| 111 v8::Local<v8::String> stringValue; | |
| 112 if (!value->ToString(m_isolate->GetCurrentContext()).ToLocal(&stringValu
e)) | |
| 113 return false; | |
| 114 return append(stringValue); | |
| 115 } | |
| 116 | |
| 117 bool append(v8::Local<v8::Array> array) | |
| 118 { | |
| 119 for (const auto& it : m_visitedArrays) { | |
| 120 if (it == array) | |
| 121 return true; | |
| 122 } | |
| 123 uint32_t length = array->Length(); | |
| 124 if (length > m_arrayLimit) | |
| 125 return false; | |
| 126 if (m_visitedArrays.size() > maxStackDepthLimit) | |
| 127 return false; | |
| 128 | |
| 129 bool result = true; | |
| 130 m_arrayLimit -= length; | |
| 131 m_visitedArrays.push_back(array); | |
| 132 for (uint32_t i = 0; i < length; ++i) { | |
| 133 if (i) | |
| 134 m_builder.append(','); | |
| 135 if (!append(array->Get(i), IgnoreNull | IgnoreUndefined)) { | |
| 136 result = false; | |
| 137 break; | |
| 138 } | |
| 139 } | |
| 140 m_visitedArrays.pop_back(); | |
| 141 return result; | |
| 142 } | |
| 143 | |
| 144 bool append(v8::Local<v8::Symbol> symbol) | |
| 145 { | |
| 146 m_builder.append("Symbol("); | |
| 147 bool result = append(symbol->Name(), IgnoreUndefined); | |
| 148 m_builder.append(')'); | |
| 149 return result; | |
| 150 } | |
| 151 | |
| 152 bool append(v8::Local<v8::String> string) | |
| 153 { | |
| 154 if (m_tryCatch.HasCaught()) | |
| 155 return false; | |
| 156 if (!string.IsEmpty()) | |
| 157 m_builder.append(toProtocolString(string)); | |
| 158 return true; | |
| 159 } | |
| 160 | |
| 161 String16 toString() | |
| 162 { | |
| 163 if (m_tryCatch.HasCaught()) | |
| 164 return String16(); | |
| 165 return m_builder.toString(); | |
| 166 } | |
| 167 | |
| 168 uint32_t m_arrayLimit; | |
| 169 v8::Isolate* m_isolate; | |
| 170 String16Builder m_builder; | |
| 171 std::vector<v8::Local<v8::Array>> m_visitedArrays; | |
| 172 v8::TryCatch m_tryCatch; | |
| 173 }; | |
| 174 | |
| 175 } // namespace | |
| 176 | |
| 177 V8ConsoleMessage::V8ConsoleMessage(V8MessageOrigin origin, double timestamp, con
st String16& message) | |
| 178 : m_origin(origin) | |
| 179 , m_timestamp(timestamp) | |
| 180 , m_message(message) | |
| 181 , m_lineNumber(0) | |
| 182 , m_columnNumber(0) | |
| 183 , m_scriptId(0) | |
| 184 , m_contextId(0) | |
| 185 , m_type(ConsoleAPIType::kLog) | |
| 186 , m_exceptionId(0) | |
| 187 , m_revokedExceptionId(0) | |
| 188 { | |
| 189 } | |
| 190 | |
| 191 V8ConsoleMessage::~V8ConsoleMessage() | |
| 192 { | |
| 193 } | |
| 194 | |
| 195 void V8ConsoleMessage::setLocation(const String16& url, unsigned lineNumber, uns
igned columnNumber, std::unique_ptr<V8StackTraceImpl> stackTrace, int scriptId) | |
| 196 { | |
| 197 m_url = url; | |
| 198 m_lineNumber = lineNumber; | |
| 199 m_columnNumber = columnNumber; | |
| 200 m_stackTrace = std::move(stackTrace); | |
| 201 m_scriptId = scriptId; | |
| 202 } | |
| 203 | |
| 204 void V8ConsoleMessage::reportToFrontend(protocol::Console::Frontend* frontend) c
onst | |
| 205 { | |
| 206 DCHECK(m_origin == V8MessageOrigin::kConsole); | |
| 207 String16 level = protocol::Console::ConsoleMessage::LevelEnum::Log; | |
| 208 if (m_type == ConsoleAPIType::kDebug || m_type == ConsoleAPIType::kCount ||
m_type == ConsoleAPIType::kTimeEnd) | |
| 209 level = protocol::Console::ConsoleMessage::LevelEnum::Debug; | |
| 210 else if (m_type == ConsoleAPIType::kError || m_type == ConsoleAPIType::kAsse
rt) | |
| 211 level = protocol::Console::ConsoleMessage::LevelEnum::Error; | |
| 212 else if (m_type == ConsoleAPIType::kWarning) | |
| 213 level = protocol::Console::ConsoleMessage::LevelEnum::Warning; | |
| 214 else if (m_type == ConsoleAPIType::kInfo) | |
| 215 level = protocol::Console::ConsoleMessage::LevelEnum::Info; | |
| 216 std::unique_ptr<protocol::Console::ConsoleMessage> result = | |
| 217 protocol::Console::ConsoleMessage::create() | |
| 218 .setSource(protocol::Console::ConsoleMessage::SourceEnum::ConsoleApi) | |
| 219 .setLevel(level) | |
| 220 .setText(m_message) | |
| 221 .build(); | |
| 222 result->setLine(static_cast<int>(m_lineNumber)); | |
| 223 result->setColumn(static_cast<int>(m_columnNumber)); | |
| 224 result->setUrl(m_url); | |
| 225 frontend->messageAdded(std::move(result)); | |
| 226 } | |
| 227 | |
| 228 std::unique_ptr<protocol::Array<protocol::Runtime::RemoteObject>> V8ConsoleMessa
ge::wrapArguments(V8InspectorSessionImpl* session, bool generatePreview) const | |
| 229 { | |
| 230 if (!m_arguments.size() || !m_contextId) | |
| 231 return nullptr; | |
| 232 InspectedContext* inspectedContext = session->inspector()->getContext(sessio
n->contextGroupId(), m_contextId); | |
| 233 if (!inspectedContext) | |
| 234 return nullptr; | |
| 235 | |
| 236 v8::Isolate* isolate = inspectedContext->isolate(); | |
| 237 v8::HandleScope handles(isolate); | |
| 238 v8::Local<v8::Context> context = inspectedContext->context(); | |
| 239 | |
| 240 std::unique_ptr<protocol::Array<protocol::Runtime::RemoteObject>> args = pro
tocol::Array<protocol::Runtime::RemoteObject>::create(); | |
| 241 if (m_type == ConsoleAPIType::kTable && generatePreview) { | |
| 242 v8::Local<v8::Value> table = m_arguments[0]->Get(isolate); | |
| 243 v8::Local<v8::Value> columns = m_arguments.size() > 1 ? m_arguments[1]->
Get(isolate) : v8::Local<v8::Value>(); | |
| 244 std::unique_ptr<protocol::Runtime::RemoteObject> wrapped = session->wrap
Table(context, table, columns); | |
| 245 if (wrapped) | |
| 246 args->addItem(std::move(wrapped)); | |
| 247 else | |
| 248 args = nullptr; | |
| 249 } else { | |
| 250 for (size_t i = 0; i < m_arguments.size(); ++i) { | |
| 251 std::unique_ptr<protocol::Runtime::RemoteObject> wrapped = session->
wrapObject(context, m_arguments[i]->Get(isolate), "console", generatePreview); | |
| 252 if (!wrapped) { | |
| 253 args = nullptr; | |
| 254 break; | |
| 255 } | |
| 256 args->addItem(std::move(wrapped)); | |
| 257 } | |
| 258 } | |
| 259 return args; | |
| 260 } | |
| 261 | |
| 262 void V8ConsoleMessage::reportToFrontend(protocol::Runtime::Frontend* frontend, V
8InspectorSessionImpl* session, bool generatePreview) const | |
| 263 { | |
| 264 if (m_origin == V8MessageOrigin::kException) { | |
| 265 std::unique_ptr<protocol::Runtime::RemoteObject> exception = wrapExcepti
on(session, generatePreview); | |
| 266 std::unique_ptr<protocol::Runtime::ExceptionDetails> exceptionDetails =
protocol::Runtime::ExceptionDetails::create() | |
| 267 .setExceptionId(m_exceptionId) | |
| 268 .setText(exception ? m_message : m_detailedMessage) | |
| 269 .setLineNumber(m_lineNumber ? m_lineNumber - 1 : 0) | |
| 270 .setColumnNumber(m_columnNumber ? m_columnNumber - 1 : 0) | |
| 271 .build(); | |
| 272 if (m_scriptId) | |
| 273 exceptionDetails->setScriptId(String16::fromInteger(m_scriptId)); | |
| 274 if (!m_url.isEmpty()) | |
| 275 exceptionDetails->setUrl(m_url); | |
| 276 if (m_stackTrace) | |
| 277 exceptionDetails->setStackTrace(m_stackTrace->buildInspectorObjectIm
pl()); | |
| 278 if (m_contextId) | |
| 279 exceptionDetails->setExecutionContextId(m_contextId); | |
| 280 if (exception) | |
| 281 exceptionDetails->setException(std::move(exception)); | |
| 282 frontend->exceptionThrown(m_timestamp, std::move(exceptionDetails)); | |
| 283 return; | |
| 284 } | |
| 285 if (m_origin == V8MessageOrigin::kRevokedException) { | |
| 286 frontend->exceptionRevoked(m_message, m_revokedExceptionId); | |
| 287 return; | |
| 288 } | |
| 289 if (m_origin == V8MessageOrigin::kConsole) { | |
| 290 std::unique_ptr<protocol::Array<protocol::Runtime::RemoteObject>> argume
nts = wrapArguments(session, generatePreview); | |
| 291 if (!arguments) { | |
| 292 arguments = protocol::Array<protocol::Runtime::RemoteObject>::create
(); | |
| 293 if (!m_message.isEmpty()) { | |
| 294 std::unique_ptr<protocol::Runtime::RemoteObject> messageArg = pr
otocol::Runtime::RemoteObject::create().setType(protocol::Runtime::RemoteObject:
:TypeEnum::String).build(); | |
| 295 messageArg->setValue(protocol::StringValue::create(m_message)); | |
| 296 arguments->addItem(std::move(messageArg)); | |
| 297 } | |
| 298 } | |
| 299 frontend->consoleAPICalled(consoleAPITypeValue(m_type), std::move(argume
nts), m_contextId, m_timestamp, m_stackTrace ? m_stackTrace->buildInspectorObjec
tImpl() : nullptr); | |
| 300 return; | |
| 301 } | |
| 302 NOTREACHED(); | |
| 303 } | |
| 304 | |
| 305 std::unique_ptr<protocol::Runtime::RemoteObject> V8ConsoleMessage::wrapException
(V8InspectorSessionImpl* session, bool generatePreview) const | |
| 306 { | |
| 307 if (!m_arguments.size() || !m_contextId) | |
| 308 return nullptr; | |
| 309 DCHECK_EQ(1u, m_arguments.size()); | |
| 310 InspectedContext* inspectedContext = session->inspector()->getContext(sessio
n->contextGroupId(), m_contextId); | |
| 311 if (!inspectedContext) | |
| 312 return nullptr; | |
| 313 | |
| 314 v8::Isolate* isolate = inspectedContext->isolate(); | |
| 315 v8::HandleScope handles(isolate); | |
| 316 // TODO(dgozman): should we use different object group? | |
| 317 return session->wrapObject(inspectedContext->context(), m_arguments[0]->Get(
isolate), "console", generatePreview); | |
| 318 } | |
| 319 | |
| 320 V8MessageOrigin V8ConsoleMessage::origin() const | |
| 321 { | |
| 322 return m_origin; | |
| 323 } | |
| 324 | |
| 325 ConsoleAPIType V8ConsoleMessage::type() const | |
| 326 { | |
| 327 return m_type; | |
| 328 } | |
| 329 | |
| 330 // static | |
| 331 std::unique_ptr<V8ConsoleMessage> V8ConsoleMessage::createForConsoleAPI(double t
imestamp, ConsoleAPIType type, const std::vector<v8::Local<v8::Value>>& argument
s, std::unique_ptr<V8StackTraceImpl> stackTrace, InspectedContext* context) | |
| 332 { | |
| 333 std::unique_ptr<V8ConsoleMessage> message = wrapUnique(new V8ConsoleMessage(
V8MessageOrigin::kConsole, timestamp, String16())); | |
| 334 if (stackTrace && !stackTrace->isEmpty()) { | |
| 335 message->m_url = toString16(stackTrace->topSourceURL()); | |
| 336 message->m_lineNumber = stackTrace->topLineNumber(); | |
| 337 message->m_columnNumber = stackTrace->topColumnNumber(); | |
| 338 } | |
| 339 message->m_stackTrace = std::move(stackTrace); | |
| 340 message->m_type = type; | |
| 341 message->m_contextId = context->contextId(); | |
| 342 for (size_t i = 0; i < arguments.size(); ++i) | |
| 343 message->m_arguments.push_back(wrapUnique(new v8::Global<v8::Value>(cont
ext->isolate(), arguments.at(i)))); | |
| 344 if (arguments.size()) | |
| 345 message->m_message = V8ValueStringBuilder::toString(arguments[0], contex
t->isolate()); | |
| 346 | |
| 347 V8ConsoleAPIType clientType = V8ConsoleAPIType::kLog; | |
| 348 if (type == ConsoleAPIType::kDebug || type == ConsoleAPIType::kCount || type
== ConsoleAPIType::kTimeEnd) | |
| 349 clientType = V8ConsoleAPIType::kDebug; | |
| 350 else if (type == ConsoleAPIType::kError || type == ConsoleAPIType::kAssert) | |
| 351 clientType = V8ConsoleAPIType::kError; | |
| 352 else if (type == ConsoleAPIType::kWarning) | |
| 353 clientType = V8ConsoleAPIType::kWarning; | |
| 354 else if (type == ConsoleAPIType::kInfo) | |
| 355 clientType = V8ConsoleAPIType::kInfo; | |
| 356 else if (type == ConsoleAPIType::kClear) | |
| 357 clientType = V8ConsoleAPIType::kClear; | |
| 358 context->inspector()->client()->consoleAPIMessage(context->contextGroupId(),
clientType, toStringView(message->m_message), toStringView(message->m_url), mes
sage->m_lineNumber, message->m_columnNumber, message->m_stackTrace.get()); | |
| 359 | |
| 360 return message; | |
| 361 } | |
| 362 | |
| 363 // static | |
| 364 std::unique_ptr<V8ConsoleMessage> V8ConsoleMessage::createForException(double ti
mestamp, const String16& detailedMessage, const String16& url, unsigned lineNumb
er, unsigned columnNumber, std::unique_ptr<V8StackTraceImpl> stackTrace, int scr
iptId, v8::Isolate* isolate, const String16& message, int contextId, v8::Local<v
8::Value> exception, unsigned exceptionId) | |
| 365 { | |
| 366 std::unique_ptr<V8ConsoleMessage> consoleMessage = wrapUnique(new V8ConsoleM
essage(V8MessageOrigin::kException, timestamp, message)); | |
| 367 consoleMessage->setLocation(url, lineNumber, columnNumber, std::move(stackTr
ace), scriptId); | |
| 368 consoleMessage->m_exceptionId = exceptionId; | |
| 369 consoleMessage->m_detailedMessage = detailedMessage; | |
| 370 if (contextId && !exception.IsEmpty()) { | |
| 371 consoleMessage->m_contextId = contextId; | |
| 372 consoleMessage->m_arguments.push_back(wrapUnique(new v8::Global<v8::Valu
e>(isolate, exception))); | |
| 373 } | |
| 374 return consoleMessage; | |
| 375 } | |
| 376 | |
| 377 // static | |
| 378 std::unique_ptr<V8ConsoleMessage> V8ConsoleMessage::createForRevokedException(do
uble timestamp, const String16& messageText, unsigned revokedExceptionId) | |
| 379 { | |
| 380 std::unique_ptr<V8ConsoleMessage> message = wrapUnique(new V8ConsoleMessage(
V8MessageOrigin::kRevokedException, timestamp, messageText)); | |
| 381 message->m_revokedExceptionId = revokedExceptionId; | |
| 382 return message; | |
| 383 } | |
| 384 | |
| 385 void V8ConsoleMessage::contextDestroyed(int contextId) | |
| 386 { | |
| 387 if (contextId != m_contextId) | |
| 388 return; | |
| 389 m_contextId = 0; | |
| 390 if (m_message.isEmpty()) | |
| 391 m_message = "<message collected>"; | |
| 392 Arguments empty; | |
| 393 m_arguments.swap(empty); | |
| 394 } | |
| 395 | |
| 396 // ------------------------ V8ConsoleMessageStorage ---------------------------- | |
| 397 | |
| 398 V8ConsoleMessageStorage::V8ConsoleMessageStorage(V8InspectorImpl* inspector, int
contextGroupId) | |
| 399 : m_inspector(inspector) | |
| 400 , m_contextGroupId(contextGroupId) | |
| 401 , m_expiredCount(0) | |
| 402 { | |
| 403 } | |
| 404 | |
| 405 V8ConsoleMessageStorage::~V8ConsoleMessageStorage() | |
| 406 { | |
| 407 clear(); | |
| 408 } | |
| 409 | |
| 410 void V8ConsoleMessageStorage::addMessage(std::unique_ptr<V8ConsoleMessage> messa
ge) | |
| 411 { | |
| 412 if (message->type() == ConsoleAPIType::kClear) | |
| 413 clear(); | |
| 414 | |
| 415 V8InspectorSessionImpl* session = m_inspector->sessionForContextGroup(m_cont
extGroupId); | |
| 416 if (session) { | |
| 417 if (message->origin() == V8MessageOrigin::kConsole) | |
| 418 session->consoleAgent()->messageAdded(message.get()); | |
| 419 session->runtimeAgent()->messageAdded(message.get()); | |
| 420 } | |
| 421 | |
| 422 DCHECK(m_messages.size() <= maxConsoleMessageCount); | |
| 423 if (m_messages.size() == maxConsoleMessageCount) { | |
| 424 ++m_expiredCount; | |
| 425 m_messages.pop_front(); | |
| 426 } | |
| 427 m_messages.push_back(std::move(message)); | |
| 428 } | |
| 429 | |
| 430 void V8ConsoleMessageStorage::clear() | |
| 431 { | |
| 432 m_messages.clear(); | |
| 433 m_expiredCount = 0; | |
| 434 if (V8InspectorSessionImpl* session = m_inspector->sessionForContextGroup(m_
contextGroupId)) | |
| 435 session->releaseObjectGroup("console"); | |
| 436 } | |
| 437 | |
| 438 void V8ConsoleMessageStorage::contextDestroyed(int contextId) | |
| 439 { | |
| 440 for (size_t i = 0; i < m_messages.size(); ++i) | |
| 441 m_messages[i]->contextDestroyed(contextId); | |
| 442 } | |
| 443 | |
| 444 } // namespace v8_inspector | |
| OLD | NEW |