v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
v8-console-message.cc
Go to the documentation of this file.
1// Copyright 2016 the V8 project 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
6
14#include "src/inspector/protocol/Protocol.h"
23
24namespace v8_inspector {
25
26namespace {
27
28String16 consoleAPITypeValue(ConsoleAPIType type) {
29 switch (type) {
31 return protocol::Runtime::ConsoleAPICalled::TypeEnum::Log;
33 return protocol::Runtime::ConsoleAPICalled::TypeEnum::Debug;
35 return protocol::Runtime::ConsoleAPICalled::TypeEnum::Info;
37 return protocol::Runtime::ConsoleAPICalled::TypeEnum::Error;
39 return protocol::Runtime::ConsoleAPICalled::TypeEnum::Warning;
41 return protocol::Runtime::ConsoleAPICalled::TypeEnum::Clear;
43 return protocol::Runtime::ConsoleAPICalled::TypeEnum::Dir;
45 return protocol::Runtime::ConsoleAPICalled::TypeEnum::Dirxml;
47 return protocol::Runtime::ConsoleAPICalled::TypeEnum::Table;
49 return protocol::Runtime::ConsoleAPICalled::TypeEnum::Trace;
51 return protocol::Runtime::ConsoleAPICalled::TypeEnum::StartGroup;
53 return protocol::Runtime::ConsoleAPICalled::TypeEnum::StartGroupCollapsed;
55 return protocol::Runtime::ConsoleAPICalled::TypeEnum::EndGroup;
57 return protocol::Runtime::ConsoleAPICalled::TypeEnum::Assert;
59 return protocol::Runtime::ConsoleAPICalled::TypeEnum::TimeEnd;
61 return protocol::Runtime::ConsoleAPICalled::TypeEnum::Count;
62 }
63 return protocol::Runtime::ConsoleAPICalled::TypeEnum::Log;
64}
65
66const char kGlobalConsoleMessageHandleLabel[] = "DevTools console";
67const unsigned maxConsoleMessageCount = 1000;
68const int maxConsoleMessageV8Size = 10 * 1024 * 1024;
69const unsigned maxArrayItemsLimit = 10000;
70const unsigned maxStackDepthLimit = 32;
71
72class V8ValueStringBuilder {
73 public:
74 static String16 toString(v8::Local<v8::Value> value,
75 v8::Local<v8::Context> context) {
76 V8ValueStringBuilder builder(context);
77 if (!builder.append(value)) return String16();
78 return builder.toString();
79 }
80
81 private:
82 enum {
83 IgnoreNull = 1 << 0,
84 IgnoreUndefined = 1 << 1,
85 };
86
87 explicit V8ValueStringBuilder(v8::Local<v8::Context> context)
88 : m_arrayLimit(maxArrayItemsLimit),
89 m_isolate(context->GetIsolate()),
90 m_visitedArrays(context->GetIsolate()),
91 m_tryCatch(context->GetIsolate()),
92 m_context(context) {}
93
94 bool append(v8::Local<v8::Value> value, unsigned ignoreOptions = 0) {
95 if (value.IsEmpty()) return true;
96 if ((ignoreOptions & IgnoreNull) && value->IsNull()) return true;
97 if ((ignoreOptions & IgnoreUndefined) && value->IsUndefined()) return true;
98 if (value->IsBigIntObject()) {
99 value = value.As<v8::BigIntObject>()->ValueOf();
100 } else if (value->IsBooleanObject()) {
101 value =
102 v8::Boolean::New(m_isolate, value.As<v8::BooleanObject>()->ValueOf());
103 } else if (value->IsNumberObject()) {
104 value =
105 v8::Number::New(m_isolate, value.As<v8::NumberObject>()->ValueOf());
106 } else if (value->IsStringObject()) {
107 value = value.As<v8::StringObject>()->ValueOf();
108 } else if (value->IsSymbolObject()) {
109 value = value.As<v8::SymbolObject>()->ValueOf();
110 }
111 if (value->IsString()) return append(value.As<v8::String>());
112 if (value->IsBigInt()) return append(value.As<v8::BigInt>());
113 if (value->IsSymbol()) return append(value.As<v8::Symbol>());
114 if (value->IsArray()) return append(value.As<v8::Array>());
115 if (value->IsProxy()) {
116 m_builder.append("[object Proxy]");
117 return true;
118 }
119 if (value->IsObject() && !value->IsDate() && !value->IsFunction() &&
120 !value->IsNativeError() && !value->IsRegExp()) {
121 v8::Local<v8::Object> object = value.As<v8::Object>();
122 v8::Local<v8::String> stringValue;
123 if (object->ObjectProtoToString(m_context).ToLocal(&stringValue))
124 return append(stringValue);
125 }
126 v8::Local<v8::String> stringValue;
127 if (!value->ToString(m_context).ToLocal(&stringValue)) return false;
128 return append(stringValue);
129 }
130
131 bool append(v8::Local<v8::Array> array) {
132 for (const auto& it : m_visitedArrays) {
133 if (it == array) return true;
134 }
135 uint32_t length = array->Length();
136 if (length > m_arrayLimit) return false;
137 if (m_visitedArrays.size() > maxStackDepthLimit) return false;
138
139 bool result = true;
141 m_visitedArrays.push_back(array);
142 for (uint32_t i = 0; i < length; ++i) {
143 if (i) m_builder.append(',');
145 if (!array->Get(m_context, i).ToLocal(&value)) continue;
146 if (!append(value, IgnoreNull | IgnoreUndefined)) {
147 result = false;
148 break;
149 }
150 }
151 m_visitedArrays.pop_back();
152 return result;
153 }
154
155 bool append(v8::Local<v8::Symbol> symbol) {
156 m_builder.append("Symbol(");
157 bool result = append(symbol->Description(m_isolate), IgnoreUndefined);
158 m_builder.append(')');
159 return result;
160 }
161
162 bool append(v8::Local<v8::BigInt> bigint) {
163 v8::Local<v8::String> bigint_string;
164 if (!bigint->ToString(m_context).ToLocal(&bigint_string)) return false;
165 bool result = append(bigint_string);
166 if (m_tryCatch.HasCaught()) return false;
167 m_builder.append('n');
168 return result;
169 }
170
171 bool append(v8::Local<v8::String> string) {
172 if (m_tryCatch.HasCaught()) return false;
173 if (!string.IsEmpty()) {
174 m_builder.append(toProtocolString(m_isolate, string));
175 }
176 return true;
177 }
178
179 String16 toString() {
180 if (m_tryCatch.HasCaught()) return String16();
181 return m_builder.toString();
182 }
183
184 uint32_t m_arrayLimit;
186 String16Builder m_builder;
190};
191
192} // namespace
193
195 const String16& message)
196 : m_origin(origin),
197 m_timestamp(timestamp),
198 m_message(message),
199 m_lineNumber(0),
201 m_scriptId(0),
202 m_contextId(0),
204 m_exceptionId(0),
205 m_revokedExceptionId(0) {}
206
208
209void V8ConsoleMessage::setLocation(const String16& url, unsigned lineNumber,
210 unsigned columnNumber,
211 std::unique_ptr<V8StackTraceImpl> stackTrace,
212 int scriptId) {
213 const char* dataURIPrefix = "data:";
214 if (url.substring(0, strlen(dataURIPrefix)) == dataURIPrefix) {
215 m_url = String16();
216 } else {
217 m_url = url;
218 }
219 m_lineNumber = lineNumber;
220 m_columnNumber = columnNumber;
221 m_stackTrace = std::move(stackTrace);
222 m_scriptId = scriptId;
223}
224
226 protocol::Console::Frontend* frontend) const {
228 String16 level = protocol::Console::ConsoleMessage::LevelEnum::Log;
231 level = protocol::Console::ConsoleMessage::LevelEnum::Debug;
232 else if (m_type == ConsoleAPIType::kError ||
234 level = protocol::Console::ConsoleMessage::LevelEnum::Error;
236 level = protocol::Console::ConsoleMessage::LevelEnum::Warning;
237 else if (m_type == ConsoleAPIType::kInfo)
238 level = protocol::Console::ConsoleMessage::LevelEnum::Info;
239 std::unique_ptr<protocol::Console::ConsoleMessage> result =
240 protocol::Console::ConsoleMessage::create()
241 .setSource(protocol::Console::ConsoleMessage::SourceEnum::ConsoleApi)
242 .setLevel(level)
243 .setText(m_message)
244 .build();
245 if (m_lineNumber) result->setLine(m_lineNumber);
246 if (m_columnNumber) result->setColumn(m_columnNumber);
247 if (!m_url.isEmpty()) result->setUrl(m_url);
248 frontend->messageAdded(std::move(result));
249}
250
251std::unique_ptr<protocol::Array<protocol::Runtime::RemoteObject>>
253 bool generatePreview) const {
254 V8InspectorImpl* inspector = session->inspector();
255 int contextGroupId = session->contextGroupId();
256 int contextId = m_contextId;
257 if (m_arguments.empty() || !contextId) return nullptr;
258 InspectedContext* inspectedContext =
259 inspector->getContext(contextGroupId, contextId);
260 if (!inspectedContext) return nullptr;
261
262 v8::Isolate* isolate = inspectedContext->isolate();
263 v8::HandleScope handles(isolate);
264 v8::Local<v8::Context> context = inspectedContext->context();
265
266 auto args =
267 std::make_unique<protocol::Array<protocol::Runtime::RemoteObject>>();
268
269 v8::Local<v8::Value> value = m_arguments[0]->Get(isolate);
270 if (value->IsObject() && m_type == ConsoleAPIType::kTable &&
271 generatePreview) {
273 if (m_arguments.size() > 1) {
274 v8::Local<v8::Value> secondArgument = m_arguments[1]->Get(isolate);
275 if (secondArgument->IsArray()) {
276 columns = secondArgument.As<v8::Array>();
277 } else if (secondArgument->IsString()) {
278 v8::TryCatch tryCatch(isolate);
279 v8::Local<v8::Array> array = v8::Array::New(isolate);
280 if (array->Set(context, 0, secondArgument).IsJust()) {
281 columns = array;
282 }
283 }
284 }
285 std::unique_ptr<protocol::Runtime::RemoteObject> wrapped =
286 session->wrapTable(context, value.As<v8::Object>(), columns);
287 inspectedContext = inspector->getContext(contextGroupId, contextId);
288 if (!inspectedContext) return nullptr;
289 if (wrapped) {
290 args->emplace_back(std::move(wrapped));
291 } else {
292 args = nullptr;
293 }
294 } else {
295 for (size_t i = 0; i < m_arguments.size(); ++i) {
296 std::unique_ptr<protocol::Runtime::RemoteObject> wrapped =
297 session->wrapObject(context, m_arguments[i]->Get(isolate), "console",
298 generatePreview);
299 inspectedContext = inspector->getContext(contextGroupId, contextId);
300 if (!inspectedContext) return nullptr;
301 if (!wrapped) {
302 args = nullptr;
303 break;
304 }
305 args->emplace_back(std::move(wrapped));
306 }
307 }
308 return args;
309}
310
311void V8ConsoleMessage::reportToFrontend(protocol::Runtime::Frontend* frontend,
312 V8InspectorSessionImpl* session,
313 bool generatePreview) const {
314 int contextGroupId = session->contextGroupId();
315 V8InspectorImpl* inspector = session->inspector();
316 // Protect against reentrant debugger calls via interrupts.
317 v8::debug::PostponeInterruptsScope no_interrupts(inspector->isolate());
318
320 std::unique_ptr<protocol::Runtime::RemoteObject> exception =
321 wrapException(session, generatePreview);
322 if (!inspector->hasConsoleMessageStorage(contextGroupId)) return;
323 std::unique_ptr<protocol::Runtime::ExceptionDetails> exceptionDetails =
324 protocol::Runtime::ExceptionDetails::create()
325 .setExceptionId(m_exceptionId)
326 .setText(exception ? m_message : m_detailedMessage)
327 .setLineNumber(m_lineNumber ? m_lineNumber - 1 : 0)
328 .setColumnNumber(m_columnNumber ? m_columnNumber - 1 : 0)
329 .build();
330 if (m_scriptId)
331 exceptionDetails->setScriptId(String16::fromInteger(m_scriptId));
332 if (!m_url.isEmpty()) exceptionDetails->setUrl(m_url);
333 if (m_stackTrace) {
334 exceptionDetails->setStackTrace(
335 m_stackTrace->buildInspectorObjectImpl(inspector->debugger()));
336 }
337 if (m_contextId) exceptionDetails->setExecutionContextId(m_contextId);
338 if (exception) exceptionDetails->setException(std::move(exception));
339 std::unique_ptr<protocol::DictionaryValue> data =
340 getAssociatedExceptionData(inspector, session);
341 if (data) exceptionDetails->setExceptionMetaData(std::move(data));
342 frontend->exceptionThrown(m_timestamp, std::move(exceptionDetails));
343 return;
344 }
346 frontend->exceptionRevoked(m_message, m_revokedExceptionId);
347 return;
348 }
350 std::unique_ptr<protocol::Array<protocol::Runtime::RemoteObject>>
351 arguments = wrapArguments(session, generatePreview);
352 if (!inspector->hasConsoleMessageStorage(contextGroupId)) return;
353 if (!arguments) {
354 arguments =
355 std::make_unique<protocol::Array<protocol::Runtime::RemoteObject>>();
356 if (!m_message.isEmpty()) {
357 std::unique_ptr<protocol::Runtime::RemoteObject> messageArg =
358 protocol::Runtime::RemoteObject::create()
359 .setType(protocol::Runtime::RemoteObject::TypeEnum::String)
360 .build();
361 messageArg->setValue(protocol::StringValue::create(m_message));
362 arguments->emplace_back(std::move(messageArg));
363 }
364 }
365 std::optional<String16> consoleContext;
366 if (!m_consoleContext.isEmpty()) consoleContext = m_consoleContext;
367 std::unique_ptr<protocol::Runtime::StackTrace> stackTrace;
368 if (m_stackTrace) {
369 switch (m_type) {
374 stackTrace =
375 m_stackTrace->buildInspectorObjectImpl(inspector->debugger());
376 break;
377 default:
378 stackTrace =
379 m_stackTrace->buildInspectorObjectImpl(inspector->debugger(), 0);
380 break;
381 }
382 }
383 frontend->consoleAPICalled(
384 consoleAPITypeValue(m_type), std::move(arguments), m_contextId,
385 m_timestamp, std::move(stackTrace), std::move(consoleContext));
386 return;
387 }
388 UNREACHABLE();
389}
390
391std::unique_ptr<protocol::DictionaryValue>
393 V8InspectorImpl* inspector, V8InspectorSessionImpl* session) const {
394 if (m_arguments.empty() || !m_contextId) return nullptr;
395 DCHECK_EQ(1u, m_arguments.size());
396
397 v8::Isolate* isolate = inspector->isolate();
398 v8::HandleScope handles(isolate);
399 v8::MaybeLocal<v8::Value> maybe_exception = m_arguments[0]->Get(isolate);
400 v8::Local<v8::Value> exception;
401 if (!maybe_exception.ToLocal(&exception)) return nullptr;
402
403 return inspector->getAssociatedExceptionDataForProtocol(exception);
404}
405
406std::unique_ptr<protocol::Runtime::RemoteObject>
408 bool generatePreview) const {
409 if (m_arguments.empty() || !m_contextId) return nullptr;
410 DCHECK_EQ(1u, m_arguments.size());
411 InspectedContext* inspectedContext =
412 session->inspector()->getContext(session->contextGroupId(), m_contextId);
413 if (!inspectedContext) return nullptr;
414
415 v8::Isolate* isolate = inspectedContext->isolate();
416 v8::HandleScope handles(isolate);
417 // TODO(dgozman): should we use different object group?
418 return session->wrapObject(inspectedContext->context(),
419 m_arguments[0]->Get(isolate), "console",
420 generatePreview);
421}
422
424
426
427// static
428std::unique_ptr<V8ConsoleMessage> V8ConsoleMessage::createForConsoleAPI(
429 v8::Local<v8::Context> v8Context, int contextId, int groupId,
430 V8InspectorImpl* inspector, double timestamp, ConsoleAPIType type,
431 v8::MemorySpan<const v8::Local<v8::Value>> arguments,
432 const String16& consoleContext,
433 std::unique_ptr<V8StackTraceImpl> stackTrace) {
434 v8::Isolate* isolate = v8Context->GetIsolate();
435
436 std::unique_ptr<V8ConsoleMessage> message(
438 if (stackTrace && !stackTrace->isEmpty()) {
439 message->m_url = toString16(stackTrace->topSourceURL());
440 message->m_lineNumber = stackTrace->topLineNumber();
441 message->m_columnNumber = stackTrace->topColumnNumber();
442 }
443 message->m_stackTrace = std::move(stackTrace);
444 message->m_consoleContext = consoleContext;
445 message->m_type = type;
446 message->m_contextId = contextId;
447 for (v8::Local<v8::Value> arg : arguments) {
448 std::unique_ptr<v8::Global<v8::Value>> argument(
449 new v8::Global<v8::Value>(isolate, arg));
450 argument->AnnotateStrongRetainer(kGlobalConsoleMessageHandleLabel);
451 message->m_arguments.push_back(std::move(argument));
452 message->m_v8Size += v8::debug::EstimatedValueSize(isolate, arg);
453 }
454 bool sep = false;
455 for (v8::Local<v8::Value> arg : arguments) {
456 if (sep) {
457 message->m_message += String16(" ");
458 } else {
459 sep = true;
460 }
461 message->m_message += V8ValueStringBuilder::toString(arg, v8Context);
462 }
463
465 if (type == ConsoleAPIType::kDebug || type == ConsoleAPIType::kCount ||
466 type == ConsoleAPIType::kTimeEnd) {
467 clientLevel = v8::Isolate::kMessageDebug;
468 } else if (type == ConsoleAPIType::kError ||
469 type == ConsoleAPIType::kAssert) {
470 clientLevel = v8::Isolate::kMessageError;
471 } else if (type == ConsoleAPIType::kWarning) {
472 clientLevel = v8::Isolate::kMessageWarning;
473 } else if (type == ConsoleAPIType::kInfo) {
474 clientLevel = v8::Isolate::kMessageInfo;
475 } else if (type == ConsoleAPIType::kLog) {
476 clientLevel = v8::Isolate::kMessageLog;
477 }
478
479 if (type != ConsoleAPIType::kClear) {
480 inspector->client()->consoleAPIMessage(
481 groupId, clientLevel, toStringView(message->m_message),
482 toStringView(message->m_url), message->m_lineNumber,
483 message->m_columnNumber, message->m_stackTrace.get());
484 }
485
486 return message;
487}
488
489// static
490std::unique_ptr<V8ConsoleMessage> V8ConsoleMessage::createForException(
491 double timestamp, const String16& detailedMessage, const String16& url,
492 unsigned lineNumber, unsigned columnNumber,
493 std::unique_ptr<V8StackTraceImpl> stackTrace, int scriptId,
494 v8::Isolate* isolate, const String16& message, int contextId,
495 v8::Local<v8::Value> exception, unsigned exceptionId) {
496 std::unique_ptr<V8ConsoleMessage> consoleMessage(
497 new V8ConsoleMessage(V8MessageOrigin::kException, timestamp, message));
498 consoleMessage->setLocation(url, lineNumber, columnNumber,
499 std::move(stackTrace), scriptId);
500 consoleMessage->m_exceptionId = exceptionId;
501 consoleMessage->m_detailedMessage = detailedMessage;
502 if (contextId && !exception.IsEmpty()) {
503 consoleMessage->m_contextId = contextId;
504 consoleMessage->m_arguments.push_back(
505 std::unique_ptr<v8::Global<v8::Value>>(
506 new v8::Global<v8::Value>(isolate, exception)));
507 consoleMessage->m_v8Size +=
508 v8::debug::EstimatedValueSize(isolate, exception);
509 }
510 return consoleMessage;
511}
512
513// static
514std::unique_ptr<V8ConsoleMessage> V8ConsoleMessage::createForRevokedException(
515 double timestamp, const String16& messageText,
516 unsigned revokedExceptionId) {
517 std::unique_ptr<V8ConsoleMessage> message(new V8ConsoleMessage(
518 V8MessageOrigin::kRevokedException, timestamp, messageText));
519 message->m_revokedExceptionId = revokedExceptionId;
520 return message;
521}
522
524 if (contextId != m_contextId) return;
525 m_contextId = 0;
526 if (m_message.isEmpty()) m_message = "<message collected>";
527 Arguments empty;
528 m_arguments.swap(empty);
529 m_v8Size = 0;
530}
531
532// ------------------------ V8ConsoleMessageStorage
533// ----------------------------
534
536 int contextGroupId)
537 : m_inspector(inspector), m_contextGroupId(contextGroupId) {}
538
540
541namespace {
542
543void TraceV8ConsoleMessageEvent(V8MessageOrigin origin, ConsoleAPIType type) {
544 // Change in this function requires adjustment of Catapult/Telemetry metric
545 // tracing/tracing/metrics/console_error_metric.html.
546 // See https://crbug.com/880432
547 if (origin == V8MessageOrigin::kException) {
548 TRACE_EVENT_INSTANT0("v8.console", "V8ConsoleMessage::Exception",
550 } else if (type == ConsoleAPIType::kError) {
551 TRACE_EVENT_INSTANT0("v8.console", "V8ConsoleMessage::Error",
553 } else if (type == ConsoleAPIType::kAssert) {
554 TRACE_EVENT_INSTANT0("v8.console", "V8ConsoleMessage::Assert",
556 }
557}
558
559} // anonymous namespace
560
562 std::unique_ptr<V8ConsoleMessage> message) {
564 V8InspectorImpl* inspector = m_inspector;
565 if (message->type() == ConsoleAPIType::kClear) clear();
566
567 TraceV8ConsoleMessageEvent(message->origin(), message->type());
568
569 inspector->forEachSession(
570 contextGroupId, [&message](V8InspectorSessionImpl* session) {
571 if (message->origin() == V8MessageOrigin::kConsole)
572 session->consoleAgent()->messageAdded(message.get());
573 session->runtimeAgent()->messageAdded(message.get());
574 });
575 if (!inspector->hasConsoleMessageStorage(contextGroupId)) return;
576
577 DCHECK(m_messages.size() <= maxConsoleMessageCount);
578 if (m_messages.size() == maxConsoleMessageCount) {
579 m_estimatedSize -= m_messages.front()->estimatedSize();
580 m_messages.pop_front();
581 }
582 while (m_estimatedSize + message->estimatedSize() > maxConsoleMessageV8Size &&
583 !m_messages.empty()) {
584 m_estimatedSize -= m_messages.front()->estimatedSize();
585 m_messages.pop_front();
586 }
587
588 m_messages.push_back(std::move(message));
589 m_estimatedSize += m_messages.back()->estimatedSize();
590}
591
593 m_messages.clear();
594 m_estimatedSize = 0;
596 [](V8InspectorSessionImpl* session) {
597 session->releaseObjectGroup("console");
598 });
599 for (auto& data : m_data) {
600 data.second.m_counters.clear();
601 data.second.m_reportedDeprecationMessages.clear();
602 }
603}
604
606 int contextId, const String16& method) {
607 std::set<String16>& reportedDeprecationMessages =
608 m_data[contextId].m_reportedDeprecationMessages;
609 auto it = reportedDeprecationMessages.find(method);
610 if (it != reportedDeprecationMessages.end()) return false;
611 reportedDeprecationMessages.insert(it, method);
612 return true;
613}
614
615int V8ConsoleMessageStorage::count(int contextId, int consoleContextId,
616 const String16& label) {
617 return ++m_data[contextId].m_counters[LabelKey{consoleContextId, label}];
618}
619
620bool V8ConsoleMessageStorage::countReset(int contextId, int consoleContextId,
621 const String16& label) {
622 std::map<LabelKey, int>& counters = m_data[contextId].m_counters;
623 auto it = counters.find(LabelKey{consoleContextId, label});
624 if (it == counters.end()) return false;
625 counters.erase(it);
626 return true;
627}
628
629bool V8ConsoleMessageStorage::time(int contextId, int consoleContextId,
630 const String16& label) {
631 return m_data[contextId]
632 .m_timers
633 .try_emplace(LabelKey{consoleContextId, label},
634 m_inspector->client()->currentTimeMS())
635 .second;
636}
637
638std::optional<double> V8ConsoleMessageStorage::timeLog(int contextId,
639 int consoleContextId,
640 const String16& label) {
641 auto& timers = m_data[contextId].m_timers;
642 auto it = timers.find(std::make_pair(consoleContextId, label));
643 if (it == timers.end()) return std::nullopt;
644 return m_inspector->client()->currentTimeMS() - it->second;
645}
646
647std::optional<double> V8ConsoleMessageStorage::timeEnd(int contextId,
648 int consoleContextId,
649 const String16& label) {
650 auto& timers = m_data[contextId].m_timers;
651 auto it = timers.find(std::make_pair(consoleContextId, label));
652 if (it == timers.end()) return std::nullopt;
653 double result = m_inspector->client()->currentTimeMS() - it->second;
654 timers.erase(it);
655 return result;
656}
657
659 m_estimatedSize = 0;
660 for (size_t i = 0; i < m_messages.size(); ++i) {
661 m_messages[i]->contextDestroyed(contextId);
662 m_estimatedSize += m_messages[i]->estimatedSize();
663 }
664 {
665 auto it = m_data.find(contextId);
666 if (it != m_data.end()) m_data.erase(contextId);
667 }
668}
669
670} // namespace v8_inspector
static Local< Array > New(Isolate *isolate, int length=0)
Definition api.cc:8119
bool ValueOf() const
Definition api.cc:7918
static V8_INLINE Local< Boolean > New(Isolate *isolate, bool value)
V8_INLINE Local< S > As() const
V8_WARN_UNUSED_RESULT V8_INLINE bool ToLocal(Local< S > *out) const
double ValueOf() const
Definition api.cc:7881
static Local< Number > New(Isolate *isolate, double value)
Definition api.cc:9557
bool HasCaught() const
Definition api.cc:2781
v8::Local< v8::Context > context() const
String16 substring(size_t pos, size_t len=UINT_MAX) const
Definition string-16.h:61
static String16 fromInteger(int)
Definition string-16.cc:71
bool isEmpty() const
Definition string-16.h:59
bool countReset(int contextId, int consoleContextId, const String16 &id)
bool time(int contextId, int consoleContextId, const String16 &label)
bool shouldReportDeprecationMessage(int contextId, const String16 &method)
int count(int contextId, int consoleContextId, const String16 &id)
void addMessage(std::unique_ptr< V8ConsoleMessage >)
std::optional< double > timeLog(int contextId, int consoleContextId, const String16 &label)
V8ConsoleMessageStorage(V8InspectorImpl *, int contextGroupId)
std::map< int, PerContextData > m_data
std::optional< double > timeEnd(int contextId, int consoleContextId, const String16 &label)
std::deque< std::unique_ptr< V8ConsoleMessage > > m_messages
static std::unique_ptr< V8ConsoleMessage > createForConsoleAPI(v8::Local< v8::Context > v8Context, int contextId, int groupId, V8InspectorImpl *inspector, double timestamp, ConsoleAPIType, v8::MemorySpan< const v8::Local< v8::Value > > arguments, const String16 &consoleContext, std::unique_ptr< V8StackTraceImpl >)
void reportToFrontend(protocol::Console::Frontend *) const
std::unique_ptr< V8StackTraceImpl > m_stackTrace
std::unique_ptr< protocol::DictionaryValue > getAssociatedExceptionData(V8InspectorImpl *inspector, V8InspectorSessionImpl *session) const
static std::unique_ptr< V8ConsoleMessage > createForRevokedException(double timestamp, const String16 &message, unsigned revokedExceptionId)
std::vector< std::unique_ptr< v8::Global< v8::Value > > > Arguments
static std::unique_ptr< V8ConsoleMessage > createForException(double timestamp, const String16 &detailedMessage, const String16 &url, unsigned lineNumber, unsigned columnNumber, std::unique_ptr< V8StackTraceImpl >, int scriptId, v8::Isolate *, const String16 &message, int contextId, v8::Local< v8::Value > exception, unsigned exceptionId)
std::unique_ptr< protocol::Runtime::RemoteObject > wrapException(V8InspectorSessionImpl *, bool generatePreview) const
std::unique_ptr< protocol::Array< protocol::Runtime::RemoteObject > > wrapArguments(V8InspectorSessionImpl *, bool generatePreview) const
void setLocation(const String16 &url, unsigned lineNumber, unsigned columnNumber, std::unique_ptr< V8StackTraceImpl >, int scriptId)
V8ConsoleMessage(V8MessageOrigin, double timestamp, const String16 &message)
virtual void consoleAPIMessage(int contextGroupId, v8::Isolate::MessageErrorLevel level, const StringView &message, const StringView &url, unsigned lineNumber, unsigned columnNumber, V8StackTrace *)
std::unique_ptr< protocol::DictionaryValue > getAssociatedExceptionDataForProtocol(v8::Local< v8::Value > exception)
v8::Isolate * isolate() const
InspectedContext * getContext(int groupId, int contextId) const
bool hasConsoleMessageStorage(int contextGroupId)
void forEachSession(int contextGroupId, const std::function< void(V8InspectorSessionImpl *)> &callback)
std::unique_ptr< protocol::Runtime::RemoteObject > wrapObject(v8::Local< v8::Context >, v8::Local< v8::Value >, const String16 &groupName, bool generatePreview)
void releaseObjectGroup(const String16 &objectGroup)
std::unique_ptr< protocol::Runtime::RemoteObject > wrapTable(v8::Local< v8::Context >, v8::Local< v8::Object > table, v8::MaybeLocal< v8::Array > columns)
base::Vector< const DirectHandle< Object > > args
Definition execution.cc:74
Label label
ZoneVector< RpoNumber > & result
int EstimatedValueSize(Isolate *v8_isolate, Local< Value > value)
String16 toProtocolString(v8::Isolate *isolate, v8::Local< v8::String > value)
StringView toStringView(const String16 &string)
String16 toString16(const StringView &string)
#define UNREACHABLE()
Definition logging.h:67
#define DCHECK(condition)
Definition logging.h:482
#define DCHECK_EQ(v1, v2)
Definition logging.h:485
Symbol method
#define TRACE_EVENT_INSTANT0(category_group, name, scope)
#define TRACE_EVENT_SCOPE_THREAD
v8::TryCatch m_tryCatch
v8::LocalVector< v8::Array > m_visitedArrays
v8::Local< v8::Context > m_context
String16Builder m_builder
v8::Isolate * m_isolate
uint32_t m_arrayLimit
V8InspectorImpl * m_inspector
std::unique_ptr< ValueMirror > value
String16 m_type
int m_lineNumber
int m_columnNumber
int m_scriptId