Line data Source code
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 :
5 : #include "src/inspector/v8-console-message.h"
6 :
7 : #include "src/debug/debug-interface.h"
8 : #include "src/inspector/inspected-context.h"
9 : #include "src/inspector/protocol/Protocol.h"
10 : #include "src/inspector/string-util.h"
11 : #include "src/inspector/v8-console-agent-impl.h"
12 : #include "src/inspector/v8-inspector-impl.h"
13 : #include "src/inspector/v8-inspector-session-impl.h"
14 : #include "src/inspector/v8-runtime-agent-impl.h"
15 : #include "src/inspector/v8-stack-trace-impl.h"
16 :
17 : #include "include/v8-inspector.h"
18 :
19 : namespace v8_inspector {
20 :
21 : namespace {
22 :
23 6380 : String16 consoleAPITypeValue(ConsoleAPIType type) {
24 6380 : switch (type) {
25 : case ConsoleAPIType::kLog:
26 5450 : return protocol::Runtime::ConsoleAPICalled::TypeEnum::Log;
27 : case ConsoleAPIType::kDebug:
28 20 : return protocol::Runtime::ConsoleAPICalled::TypeEnum::Debug;
29 : case ConsoleAPIType::kInfo:
30 20 : return protocol::Runtime::ConsoleAPICalled::TypeEnum::Info;
31 : case ConsoleAPIType::kError:
32 30 : return protocol::Runtime::ConsoleAPICalled::TypeEnum::Error;
33 : case ConsoleAPIType::kWarning:
34 20 : return protocol::Runtime::ConsoleAPICalled::TypeEnum::Warning;
35 : case ConsoleAPIType::kClear:
36 75 : return protocol::Runtime::ConsoleAPICalled::TypeEnum::Clear;
37 : case ConsoleAPIType::kDir:
38 65 : return protocol::Runtime::ConsoleAPICalled::TypeEnum::Dir;
39 : case ConsoleAPIType::kDirXML:
40 35 : return protocol::Runtime::ConsoleAPICalled::TypeEnum::Dirxml;
41 : case ConsoleAPIType::kTable:
42 115 : return protocol::Runtime::ConsoleAPICalled::TypeEnum::Table;
43 : case ConsoleAPIType::kTrace:
44 380 : return protocol::Runtime::ConsoleAPICalled::TypeEnum::Trace;
45 : case ConsoleAPIType::kStartGroup:
46 5 : return protocol::Runtime::ConsoleAPICalled::TypeEnum::StartGroup;
47 : case ConsoleAPIType::kStartGroupCollapsed:
48 5 : return protocol::Runtime::ConsoleAPICalled::TypeEnum::StartGroupCollapsed;
49 : case ConsoleAPIType::kEndGroup:
50 5 : return protocol::Runtime::ConsoleAPICalled::TypeEnum::EndGroup;
51 : case ConsoleAPIType::kAssert:
52 30 : return protocol::Runtime::ConsoleAPICalled::TypeEnum::Assert;
53 : case ConsoleAPIType::kTimeEnd:
54 60 : return protocol::Runtime::ConsoleAPICalled::TypeEnum::TimeEnd;
55 : case ConsoleAPIType::kCount:
56 65 : return protocol::Runtime::ConsoleAPICalled::TypeEnum::Count;
57 : }
58 0 : return protocol::Runtime::ConsoleAPICalled::TypeEnum::Log;
59 : }
60 :
61 : const unsigned maxConsoleMessageCount = 1000;
62 : const int maxConsoleMessageV8Size = 10 * 1024 * 1024;
63 : const unsigned maxArrayItemsLimit = 10000;
64 : const unsigned maxStackDepthLimit = 32;
65 :
66 12800 : class V8ValueStringBuilder {
67 : public:
68 6400 : static String16 toString(v8::Local<v8::Value> value,
69 : v8::Local<v8::Context> context) {
70 6400 : V8ValueStringBuilder builder(context);
71 6400 : if (!builder.append(value)) return String16();
72 6400 : return builder.toString();
73 : }
74 :
75 : private:
76 : enum {
77 : IgnoreNull = 1 << 0,
78 : IgnoreUndefined = 1 << 1,
79 : };
80 :
81 6400 : explicit V8ValueStringBuilder(v8::Local<v8::Context> context)
82 : : m_arrayLimit(maxArrayItemsLimit),
83 6400 : m_isolate(context->GetIsolate()),
84 : m_tryCatch(context->GetIsolate()),
85 19200 : m_context(context) {}
86 :
87 6480 : bool append(v8::Local<v8::Value> value, unsigned ignoreOptions = 0) {
88 6480 : if (value.IsEmpty()) return true;
89 6555 : if ((ignoreOptions & IgnoreNull) && value->IsNull()) return true;
90 6560 : if ((ignoreOptions & IgnoreUndefined) && value->IsUndefined()) return true;
91 6480 : if (value->IsString()) return append(v8::Local<v8::String>::Cast(value));
92 830 : if (value->IsStringObject())
93 5 : return append(v8::Local<v8::StringObject>::Cast(value)->ValueOf());
94 825 : if (value->IsSymbol()) return append(v8::Local<v8::Symbol>::Cast(value));
95 825 : if (value->IsSymbolObject())
96 5 : return append(v8::Local<v8::SymbolObject>::Cast(value)->ValueOf());
97 820 : if (value->IsNumberObject()) {
98 : m_builder.append(String16::fromDouble(
99 10 : v8::Local<v8::NumberObject>::Cast(value)->ValueOf(), 6));
100 5 : return true;
101 : }
102 815 : if (value->IsBooleanObject()) {
103 5 : m_builder.append(v8::Local<v8::BooleanObject>::Cast(value)->ValueOf()
104 : ? "true"
105 10 : : "false");
106 5 : return true;
107 : }
108 810 : if (value->IsArray()) return append(v8::Local<v8::Array>::Cast(value));
109 775 : if (value->IsProxy()) {
110 0 : m_builder.append("[object Proxy]");
111 0 : return true;
112 : }
113 1720 : if (value->IsObject() && !value->IsDate() && !value->IsFunction() &&
114 945 : !value->IsNativeError() && !value->IsRegExp()) {
115 : v8::Local<v8::Object> object = v8::Local<v8::Object>::Cast(value);
116 : v8::Local<v8::String> stringValue;
117 160 : if (object->ObjectProtoToString(m_isolate->GetCurrentContext())
118 80 : .ToLocal(&stringValue))
119 80 : return append(stringValue);
120 : }
121 : v8::Local<v8::String> stringValue;
122 1390 : if (!value->ToString(m_isolate->GetCurrentContext()).ToLocal(&stringValue))
123 : return false;
124 695 : return append(stringValue);
125 : }
126 :
127 35 : bool append(v8::Local<v8::Array> array) {
128 90 : for (const auto& it : m_visitedArrays) {
129 20 : if (it == array) return true;
130 : }
131 35 : uint32_t length = array->Length();
132 35 : if (length > m_arrayLimit) return false;
133 70 : if (m_visitedArrays.size() > maxStackDepthLimit) return false;
134 :
135 : bool result = true;
136 35 : m_arrayLimit -= length;
137 35 : m_visitedArrays.push_back(array);
138 110 : for (uint32_t i = 0; i < length; ++i) {
139 75 : if (i) m_builder.append(',');
140 : v8::Local<v8::Value> value;
141 150 : if (!array->Get(m_context, i).ToLocal(&value)) continue;
142 75 : if (!append(value, IgnoreNull | IgnoreUndefined)) {
143 : result = false;
144 0 : break;
145 : }
146 : }
147 : m_visitedArrays.pop_back();
148 35 : return result;
149 : }
150 :
151 5 : bool append(v8::Local<v8::Symbol> symbol) {
152 10 : m_builder.append("Symbol(");
153 5 : bool result = append(symbol->Name(), IgnoreUndefined);
154 5 : m_builder.append(')');
155 5 : return result;
156 : }
157 :
158 6430 : bool append(v8::Local<v8::String> string) {
159 6430 : if (m_tryCatch.HasCaught()) return false;
160 12860 : if (!string.IsEmpty()) m_builder.append(toProtocolString(string));
161 : return true;
162 : }
163 :
164 6400 : String16 toString() {
165 6400 : if (m_tryCatch.HasCaught()) return String16();
166 6400 : return m_builder.toString();
167 : }
168 :
169 : uint32_t m_arrayLimit;
170 : v8::Isolate* m_isolate;
171 : String16Builder m_builder;
172 : std::vector<v8::Local<v8::Array>> m_visitedArrays;
173 : v8::TryCatch m_tryCatch;
174 : v8::Local<v8::Context> m_context;
175 : };
176 :
177 : } // namespace
178 :
179 6695 : V8ConsoleMessage::V8ConsoleMessage(V8MessageOrigin origin, double timestamp,
180 : const String16& message)
181 : : m_origin(origin),
182 : m_timestamp(timestamp),
183 : m_message(message),
184 : m_lineNumber(0),
185 : m_columnNumber(0),
186 : m_scriptId(0),
187 : m_contextId(0),
188 : m_type(ConsoleAPIType::kLog),
189 : m_exceptionId(0),
190 13390 : m_revokedExceptionId(0) {}
191 :
192 20085 : V8ConsoleMessage::~V8ConsoleMessage() {}
193 :
194 215 : void V8ConsoleMessage::setLocation(const String16& url, unsigned lineNumber,
195 : unsigned columnNumber,
196 : std::unique_ptr<V8StackTraceImpl> stackTrace,
197 : int scriptId) {
198 215 : m_url = url;
199 215 : m_lineNumber = lineNumber;
200 215 : m_columnNumber = columnNumber;
201 : m_stackTrace = std::move(stackTrace);
202 215 : m_scriptId = scriptId;
203 215 : }
204 :
205 10 : void V8ConsoleMessage::reportToFrontend(
206 : protocol::Console::Frontend* frontend) const {
207 : DCHECK_EQ(V8MessageOrigin::kConsole, m_origin);
208 10 : String16 level = protocol::Console::ConsoleMessage::LevelEnum::Log;
209 10 : if (m_type == ConsoleAPIType::kDebug || m_type == ConsoleAPIType::kCount ||
210 : m_type == ConsoleAPIType::kTimeEnd)
211 0 : level = protocol::Console::ConsoleMessage::LevelEnum::Debug;
212 10 : else if (m_type == ConsoleAPIType::kError ||
213 : m_type == ConsoleAPIType::kAssert)
214 10 : level = protocol::Console::ConsoleMessage::LevelEnum::Error;
215 5 : else if (m_type == ConsoleAPIType::kWarning)
216 0 : level = protocol::Console::ConsoleMessage::LevelEnum::Warning;
217 5 : else if (m_type == ConsoleAPIType::kInfo)
218 0 : level = protocol::Console::ConsoleMessage::LevelEnum::Info;
219 : std::unique_ptr<protocol::Console::ConsoleMessage> result =
220 : protocol::Console::ConsoleMessage::create()
221 30 : .setSource(protocol::Console::ConsoleMessage::SourceEnum::ConsoleApi)
222 : .setLevel(level)
223 10 : .setText(m_message)
224 : .build();
225 10 : result->setLine(static_cast<int>(m_lineNumber));
226 10 : result->setColumn(static_cast<int>(m_columnNumber));
227 10 : result->setUrl(m_url);
228 20 : frontend->messageAdded(std::move(result));
229 10 : }
230 :
231 : std::unique_ptr<protocol::Array<protocol::Runtime::RemoteObject>>
232 6380 : V8ConsoleMessage::wrapArguments(V8InspectorSessionImpl* session,
233 : bool generatePreview) const {
234 : V8InspectorImpl* inspector = session->inspector();
235 : int contextGroupId = session->contextGroupId();
236 6380 : int contextId = m_contextId;
237 31805 : if (!m_arguments.size() || !contextId) return nullptr;
238 : InspectedContext* inspectedContext =
239 6380 : inspector->getContext(contextGroupId, contextId);
240 6380 : if (!inspectedContext) return nullptr;
241 :
242 6380 : v8::Isolate* isolate = inspectedContext->isolate();
243 6380 : v8::HandleScope handles(isolate);
244 6380 : v8::Local<v8::Context> context = inspectedContext->context();
245 :
246 : std::unique_ptr<protocol::Array<protocol::Runtime::RemoteObject>> args =
247 : protocol::Array<protocol::Runtime::RemoteObject>::create();
248 6380 : if (m_type == ConsoleAPIType::kTable && generatePreview) {
249 105 : v8::Local<v8::Value> table = m_arguments[0]->Get(isolate);
250 : v8::Local<v8::Value> columns = m_arguments.size() > 1
251 : ? m_arguments[1]->Get(isolate)
252 110 : : v8::Local<v8::Value>();
253 : std::unique_ptr<protocol::Runtime::RemoteObject> wrapped =
254 105 : session->wrapTable(context, table, columns);
255 105 : inspectedContext = inspector->getContext(contextGroupId, contextId);
256 105 : if (!inspectedContext) return nullptr;
257 105 : if (wrapped)
258 105 : args->addItem(std::move(wrapped));
259 : else
260 : args = nullptr;
261 : } else {
262 18835 : for (size_t i = 0; i < m_arguments.size(); ++i) {
263 : std::unique_ptr<protocol::Runtime::RemoteObject> wrapped =
264 : session->wrapObject(context, m_arguments[i]->Get(isolate), "console",
265 18840 : generatePreview);
266 6280 : inspectedContext = inspector->getContext(contextGroupId, contextId);
267 6280 : if (!inspectedContext) return nullptr;
268 6280 : if (!wrapped) {
269 : args = nullptr;
270 : break;
271 : }
272 6280 : args->addItem(std::move(wrapped));
273 : }
274 : }
275 6380 : return args;
276 : }
277 :
278 6625 : void V8ConsoleMessage::reportToFrontend(protocol::Runtime::Frontend* frontend,
279 6625 : V8InspectorSessionImpl* session,
280 : bool generatePreview) const {
281 : int contextGroupId = session->contextGroupId();
282 : V8InspectorImpl* inspector = session->inspector();
283 :
284 6625 : if (m_origin == V8MessageOrigin::kException) {
285 : std::unique_ptr<protocol::Runtime::RemoteObject> exception =
286 175 : wrapException(session, generatePreview);
287 175 : if (!inspector->hasConsoleMessageStorage(contextGroupId)) return;
288 : std::unique_ptr<protocol::Runtime::ExceptionDetails> exceptionDetails =
289 : protocol::Runtime::ExceptionDetails::create()
290 350 : .setExceptionId(m_exceptionId)
291 175 : .setText(exception ? m_message : m_detailedMessage)
292 175 : .setLineNumber(m_lineNumber ? m_lineNumber - 1 : 0)
293 175 : .setColumnNumber(m_columnNumber ? m_columnNumber - 1 : 0)
294 : .build();
295 175 : if (m_scriptId)
296 170 : exceptionDetails->setScriptId(String16::fromInteger(m_scriptId));
297 175 : if (!m_url.isEmpty()) exceptionDetails->setUrl(m_url);
298 175 : if (m_stackTrace)
299 250 : exceptionDetails->setStackTrace(m_stackTrace->buildInspectorObjectImpl());
300 175 : if (m_contextId) exceptionDetails->setExecutionContextId(m_contextId);
301 175 : if (exception) exceptionDetails->setException(std::move(exception));
302 350 : frontend->exceptionThrown(m_timestamp, std::move(exceptionDetails));
303 : return;
304 : }
305 6450 : if (m_origin == V8MessageOrigin::kRevokedException) {
306 70 : frontend->exceptionRevoked(m_message, m_revokedExceptionId);
307 70 : return;
308 : }
309 6380 : if (m_origin == V8MessageOrigin::kConsole) {
310 : std::unique_ptr<protocol::Array<protocol::Runtime::RemoteObject>>
311 6380 : arguments = wrapArguments(session, generatePreview);
312 6380 : if (!inspector->hasConsoleMessageStorage(contextGroupId)) return;
313 6380 : if (!arguments) {
314 : arguments = protocol::Array<protocol::Runtime::RemoteObject>::create();
315 0 : if (!m_message.isEmpty()) {
316 : std::unique_ptr<protocol::Runtime::RemoteObject> messageArg =
317 : protocol::Runtime::RemoteObject::create()
318 0 : .setType(protocol::Runtime::RemoteObject::TypeEnum::String)
319 : .build();
320 0 : messageArg->setValue(protocol::StringValue::create(m_message));
321 0 : arguments->addItem(std::move(messageArg));
322 : }
323 : }
324 : Maybe<String16> consoleContext;
325 6450 : if (!m_consoleContext.isEmpty()) consoleContext = m_consoleContext;
326 : frontend->consoleAPICalled(
327 : consoleAPITypeValue(m_type), std::move(arguments), m_contextId,
328 : m_timestamp,
329 : m_stackTrace ? m_stackTrace->buildInspectorObjectImpl() : nullptr,
330 51040 : std::move(consoleContext));
331 : return;
332 : }
333 0 : UNREACHABLE();
334 : }
335 :
336 : std::unique_ptr<protocol::Runtime::RemoteObject>
337 350 : V8ConsoleMessage::wrapException(V8InspectorSessionImpl* session,
338 : bool generatePreview) const {
339 525 : if (!m_arguments.size() || !m_contextId) return nullptr;
340 : DCHECK_EQ(1u, m_arguments.size());
341 : InspectedContext* inspectedContext =
342 350 : session->inspector()->getContext(session->contextGroupId(), m_contextId);
343 175 : if (!inspectedContext) return nullptr;
344 :
345 175 : v8::Isolate* isolate = inspectedContext->isolate();
346 175 : v8::HandleScope handles(isolate);
347 : // TODO(dgozman): should we use different object group?
348 : return session->wrapObject(inspectedContext->context(),
349 : m_arguments[0]->Get(isolate), "console",
350 525 : generatePreview);
351 : }
352 :
353 6780 : V8MessageOrigin V8ConsoleMessage::origin() const { return m_origin; }
354 :
355 6695 : ConsoleAPIType V8ConsoleMessage::type() const { return m_type; }
356 :
357 : // static
358 6400 : std::unique_ptr<V8ConsoleMessage> V8ConsoleMessage::createForConsoleAPI(
359 : v8::Local<v8::Context> v8Context, int contextId, int groupId,
360 6350 : V8InspectorImpl* inspector, double timestamp, ConsoleAPIType type,
361 12810 : const std::vector<v8::Local<v8::Value>>& arguments,
362 : const String16& consoleContext,
363 : std::unique_ptr<V8StackTraceImpl> stackTrace) {
364 6400 : v8::Isolate* isolate = v8Context->GetIsolate();
365 :
366 : std::unique_ptr<V8ConsoleMessage> message(
367 12800 : new V8ConsoleMessage(V8MessageOrigin::kConsole, timestamp, String16()));
368 6400 : if (stackTrace && !stackTrace->isEmpty()) {
369 19170 : message->m_url = toString16(stackTrace->topSourceURL());
370 6390 : message->m_lineNumber = stackTrace->topLineNumber();
371 6390 : message->m_columnNumber = stackTrace->topColumnNumber();
372 : }
373 : message->m_stackTrace = std::move(stackTrace);
374 6400 : message->m_consoleContext = consoleContext;
375 6400 : message->m_type = type;
376 6400 : message->m_contextId = contextId;
377 25620 : for (size_t i = 0; i < arguments.size(); ++i) {
378 : message->m_arguments.push_back(std::unique_ptr<v8::Global<v8::Value>>(
379 19230 : new v8::Global<v8::Value>(isolate, arguments.at(i))));
380 : message->m_v8Size +=
381 12820 : v8::debug::EstimatedValueSize(isolate, arguments.at(i));
382 : }
383 6400 : if (arguments.size())
384 19200 : message->m_message =
385 6400 : V8ValueStringBuilder::toString(arguments[0], v8Context);
386 :
387 : v8::Isolate::MessageErrorLevel clientLevel = v8::Isolate::kMessageInfo;
388 6400 : if (type == ConsoleAPIType::kDebug || type == ConsoleAPIType::kCount ||
389 : type == ConsoleAPIType::kTimeEnd) {
390 : clientLevel = v8::Isolate::kMessageDebug;
391 12530 : } else if (type == ConsoleAPIType::kError ||
392 6265 : type == ConsoleAPIType::kAssert) {
393 : clientLevel = v8::Isolate::kMessageError;
394 6165 : } else if (type == ConsoleAPIType::kWarning) {
395 : clientLevel = v8::Isolate::kMessageWarning;
396 : } else if (type == ConsoleAPIType::kInfo || type == ConsoleAPIType::kLog) {
397 : clientLevel = v8::Isolate::kMessageInfo;
398 : }
399 :
400 6400 : if (type != ConsoleAPIType::kClear) {
401 : inspector->client()->consoleAPIMessage(
402 6350 : groupId, clientLevel, toStringView(message->m_message),
403 6350 : toStringView(message->m_url), message->m_lineNumber,
404 25400 : message->m_columnNumber, message->m_stackTrace.get());
405 : }
406 :
407 6400 : return message;
408 : }
409 :
410 : // static
411 215 : std::unique_ptr<V8ConsoleMessage> V8ConsoleMessage::createForException(
412 : double timestamp, const String16& detailedMessage, const String16& url,
413 : unsigned lineNumber, unsigned columnNumber,
414 : std::unique_ptr<V8StackTraceImpl> stackTrace, int scriptId,
415 : v8::Isolate* isolate, const String16& message, int contextId,
416 : v8::Local<v8::Value> exception, unsigned exceptionId) {
417 : std::unique_ptr<V8ConsoleMessage> consoleMessage(
418 215 : new V8ConsoleMessage(V8MessageOrigin::kException, timestamp, message));
419 : consoleMessage->setLocation(url, lineNumber, columnNumber,
420 430 : std::move(stackTrace), scriptId);
421 215 : consoleMessage->m_exceptionId = exceptionId;
422 215 : consoleMessage->m_detailedMessage = detailedMessage;
423 430 : if (contextId && !exception.IsEmpty()) {
424 215 : consoleMessage->m_contextId = contextId;
425 : consoleMessage->m_arguments.push_back(
426 : std::unique_ptr<v8::Global<v8::Value>>(
427 645 : new v8::Global<v8::Value>(isolate, exception)));
428 : consoleMessage->m_v8Size +=
429 430 : v8::debug::EstimatedValueSize(isolate, exception);
430 : }
431 215 : return consoleMessage;
432 : }
433 :
434 : // static
435 80 : std::unique_ptr<V8ConsoleMessage> V8ConsoleMessage::createForRevokedException(
436 : double timestamp, const String16& messageText,
437 : unsigned revokedExceptionId) {
438 : std::unique_ptr<V8ConsoleMessage> message(new V8ConsoleMessage(
439 80 : V8MessageOrigin::kRevokedException, timestamp, messageText));
440 80 : message->m_revokedExceptionId = revokedExceptionId;
441 80 : return message;
442 : }
443 :
444 45 : void V8ConsoleMessage::contextDestroyed(int contextId) {
445 60 : if (contextId != m_contextId) return;
446 30 : m_contextId = 0;
447 30 : if (m_message.isEmpty()) m_message = "<message collected>";
448 : Arguments empty;
449 : m_arguments.swap(empty);
450 30 : m_v8Size = 0;
451 : }
452 :
453 : // ------------------------ V8ConsoleMessageStorage ----------------------------
454 :
455 345 : V8ConsoleMessageStorage::V8ConsoleMessageStorage(V8InspectorImpl* inspector,
456 : int contextGroupId)
457 690 : : m_inspector(inspector), m_contextGroupId(contextGroupId) {}
458 :
459 690 : V8ConsoleMessageStorage::~V8ConsoleMessageStorage() { clear(); }
460 :
461 6695 : void V8ConsoleMessageStorage::addMessage(
462 : std::unique_ptr<V8ConsoleMessage> message) {
463 6695 : int contextGroupId = m_contextGroupId;
464 6695 : V8InspectorImpl* inspector = m_inspector;
465 6695 : if (message->type() == ConsoleAPIType::kClear) clear();
466 :
467 : inspector->forEachSession(
468 6780 : contextGroupId, [&message](V8InspectorSessionImpl* session) {
469 13560 : if (message->origin() == V8MessageOrigin::kConsole)
470 6455 : session->consoleAgent()->messageAdded(message.get());
471 13560 : session->runtimeAgent()->messageAdded(message.get());
472 20170 : });
473 13390 : if (!inspector->hasConsoleMessageStorage(contextGroupId)) return;
474 :
475 : DCHECK(m_messages.size() <= maxConsoleMessageCount);
476 6695 : if (m_messages.size() == maxConsoleMessageCount) {
477 45 : m_estimatedSize -= m_messages.front()->estimatedSize();
478 45 : m_messages.pop_front();
479 : }
480 28450 : while (m_estimatedSize + message->estimatedSize() > maxConsoleMessageV8Size &&
481 : !m_messages.empty()) {
482 5020 : m_estimatedSize -= m_messages.front()->estimatedSize();
483 5020 : m_messages.pop_front();
484 : }
485 :
486 6695 : m_messages.push_back(std::move(message));
487 6695 : m_estimatedSize += m_messages.back()->estimatedSize();
488 : }
489 :
490 400 : void V8ConsoleMessageStorage::clear() {
491 400 : m_messages.clear();
492 400 : m_estimatedSize = 0;
493 : m_inspector->forEachSession(m_contextGroupId,
494 55 : [](V8InspectorSessionImpl* session) {
495 110 : session->releaseObjectGroup("console");
496 855 : });
497 : m_data.clear();
498 400 : }
499 :
500 25 : bool V8ConsoleMessageStorage::shouldReportDeprecationMessage(
501 : int contextId, const String16& method) {
502 : std::set<String16>& reportedDeprecationMessages =
503 25 : m_data[contextId].m_reportedDeprecationMessages;
504 : auto it = reportedDeprecationMessages.find(method);
505 25 : if (it != reportedDeprecationMessages.end()) return false;
506 : reportedDeprecationMessages.insert(it, method);
507 15 : return true;
508 : }
509 :
510 55 : int V8ConsoleMessageStorage::count(int contextId, const String16& id) {
511 55 : return ++m_data[contextId].m_count[id];
512 : }
513 :
514 70 : void V8ConsoleMessageStorage::time(int contextId, const String16& id) {
515 70 : m_data[contextId].m_time[id] = m_inspector->client()->currentTimeMS();
516 70 : }
517 :
518 60 : double V8ConsoleMessageStorage::timeEnd(int contextId, const String16& id) {
519 60 : std::map<String16, double>& time = m_data[contextId].m_time;
520 : auto it = time.find(id);
521 60 : if (it == time.end()) return 0.0;
522 60 : double elapsed = m_inspector->client()->currentTimeMS() - it->second;
523 : time.erase(it);
524 60 : return elapsed;
525 : }
526 :
527 20 : void V8ConsoleMessageStorage::contextDestroyed(int contextId) {
528 20 : m_estimatedSize = 0;
529 130 : for (size_t i = 0; i < m_messages.size(); ++i) {
530 90 : m_messages[i]->contextDestroyed(contextId);
531 45 : m_estimatedSize += m_messages[i]->estimatedSize();
532 : }
533 : auto it = m_data.find(contextId);
534 20 : if (it != m_data.end()) m_data.erase(contextId);
535 20 : }
536 :
537 : } // namespace v8_inspector
|