Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(87)

Side by Side Diff: third_party/WebKit/Source/platform/v8_inspector/V8ConsoleMessage.cpp

Issue 2295913003: [DevTools] Switch from platform/v8_inspector to v8/v8-inspector.h. (Closed)
Patch Set: rebase Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698