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