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

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

Issue 1859293002: [DevTools] Move Console to v8_inspector (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: added missing tests Created 4 years, 8 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/V8Console.h"
6
7 #include "platform/inspector_protocol/String16.h"
8 #include "platform/v8_inspector/V8DebuggerImpl.h"
9 #include "platform/v8_inspector/V8ProfilerAgentImpl.h"
10 #include "platform/v8_inspector/V8StackTraceImpl.h"
11 #include "platform/v8_inspector/V8StringUtil.h"
12 #include "platform/v8_inspector/public/ConsoleAPITypes.h"
13 #include "platform/v8_inspector/public/ConsoleTypes.h"
14 #include "platform/v8_inspector/public/V8DebuggerClient.h"
15
16 namespace blink {
17
18 namespace {
19
20 v8::MaybeLocal<v8::Object> consoleObjectFromInfo(const v8::FunctionCallbackInfo< v8::Value>& info)
21 {
22 if (info.Data().IsEmpty() || !info.Data()->IsObject())
23 return v8::MaybeLocal<v8::Object>();
24 return info.Data().As<v8::Object>();
25 }
26
27 v8::Local<v8::Private> debuggerPrivateKey(v8::Isolate* isolate)
28 {
29 return v8::Private::ForApi(isolate, toV8StringInternalized(isolate, "V8Conso le#V8DebuggerImpl"));
30 }
31
32 V8DebuggerImpl* debuggerFromConsoleObject(v8::Isolate* isolate, v8::Local<v8::Ob ject> console)
33 {
34 v8::Local<v8::Value> value;
35 if (!console->GetPrivate(isolate->GetCurrentContext(), debuggerPrivateKey(is olate)).ToLocal(&value))
36 return nullptr;
37 ASSERT(!value->IsExternal());
38 return static_cast<V8DebuggerImpl*>(value.As<v8::External>()->Value());
39 }
40
41 V8DebuggerClient* clientFromConsoleObject(v8::Isolate* isolate, v8::Local<v8::Ob ject> console)
42 {
43 V8DebuggerImpl* debugger = debuggerFromConsoleObject(isolate, console);
44 return debugger ? debugger->client() : nullptr;
45 }
46
47 void internalAddMessage(MessageType type, MessageLevel level, const v8::Function CallbackInfo<v8::Value>& info, bool allowEmptyArguments, int skipArgumentCount)
48 {
49 if (!allowEmptyArguments && !info.Length())
50 return;
51 v8::Local<v8::Object> consoleObject;
52 if (!consoleObjectFromInfo(info).ToLocal(&consoleObject))
53 return;
54 v8::Isolate* isolate = info.GetIsolate();
55 V8DebuggerClient* client = clientFromConsoleObject(isolate, consoleObject);
56 if (!client)
57 return;
58 client->reportMessageToConsole(isolate->GetCurrentContext(), type, level, in fo, skipArgumentCount);
59 }
60
61 void createBoundFunctionProperty(v8::Local<v8::Context> context, v8::Local<v8::O bject> obj, v8::Local<v8::Object> prototype, const char* name, v8::FunctionCallb ack callback)
62 {
63 v8::Local<v8::String> funcName = toV8StringInternalized(context->GetIsolate( ), name);
64 v8::Local<v8::Function> func;
65 if (!v8::Function::New(context, callback, obj).ToLocal(&func))
66 return;
67 func->SetName(funcName);
68 if (!prototype->Set(context, funcName, func).FromMaybe(false))
69 return;
70 }
71
72 v8::MaybeLocal<v8::Map> privateMapFromConsoleObject(v8::Isolate* isolate, v8::Lo cal<v8::Object> console, const char* name)
73 {
74 v8::Local<v8::Context> context = isolate->GetCurrentContext();
75
76 v8::Local<v8::Private> privateKey = v8::Private::ForApi(isolate, toV8StringI nternalized(isolate, name));
77 v8::Local<v8::Value> mapValue;
78 if (!console->GetPrivate(context, privateKey).ToLocal(&mapValue))
79 return v8::MaybeLocal<v8::Map>();
80 if (mapValue->IsUndefined()) {
81 v8::Local<v8::Map> map = v8::Map::New(isolate);
82 if (!console->SetPrivate(context, privateKey, map).FromMaybe(false))
83 return v8::MaybeLocal<v8::Map>();
84 return map;
85 }
86 return mapValue->IsMap() ? mapValue.As<v8::Map>() : v8::MaybeLocal<v8::Map>( );
87 }
88
89 v8::MaybeLocal<v8::Object> createObjectWithClassName(v8::Isolate* isolate, v8::L ocal<v8::Context> context, const char* className)
90 {
91 v8::Local<v8::FunctionTemplate> functionTemplate = v8::FunctionTemplate::New (isolate);
dgozman 2016/04/12 03:32:16 Store it per-isolate in V8DebuggerImpl instance. F
kozy 2016/04/12 21:58:32 Done.
92 functionTemplate->SetClassName(toV8StringInternalized(isolate, className));
93 v8::Local<v8::Function> constructor;
94 if (!functionTemplate->GetFunction(context).ToLocal(&constructor))
95 return v8::MaybeLocal<v8::Object>();
96 return constructor->NewInstance(context, 0, nullptr);
97 }
98
99 } // namespace
100
101 void V8Console::debugCallback(const v8::FunctionCallbackInfo<v8::Value>& info)
102 {
103 internalAddMessage(LogMessageType, DebugMessageLevel, info, false, 0);
104 }
105
106 void V8Console::errorCallback(const v8::FunctionCallbackInfo<v8::Value>& info)
107 {
108 internalAddMessage(LogMessageType, ErrorMessageLevel, info, false, 0);
109 }
110
111 void V8Console::infoCallback(const v8::FunctionCallbackInfo<v8::Value>& info)
112 {
113 internalAddMessage(LogMessageType, InfoMessageLevel, info, false, 0);
114 }
115
116 void V8Console::logCallback(const v8::FunctionCallbackInfo<v8::Value>& info)
117 {
118 internalAddMessage(LogMessageType, LogMessageLevel, info, false, 0);
119 }
120
121 void V8Console::warnCallback(const v8::FunctionCallbackInfo<v8::Value>& info)
122 {
123 internalAddMessage(LogMessageType, WarningMessageLevel, info, false, 0);
124 }
125
126 void V8Console::dirCallback(const v8::FunctionCallbackInfo<v8::Value>& info)
127 {
128 internalAddMessage(DirMessageType, LogMessageLevel, info, false, 0);
129 }
130
131 void V8Console::dirxmlCallback(const v8::FunctionCallbackInfo<v8::Value>& info)
132 {
133 internalAddMessage(DirXMLMessageType, LogMessageLevel, info, false, 0);
134 }
135
136 void V8Console::tableCallback(const v8::FunctionCallbackInfo<v8::Value>& info)
137 {
138 internalAddMessage(TableMessageType, LogMessageLevel, info, false, 0);
139 }
140
141 void V8Console::traceCallback(const v8::FunctionCallbackInfo<v8::Value>& info)
142 {
143 internalAddMessage(TraceMessageType, LogMessageLevel, info, true, 0);
144 }
145
146 void V8Console::groupCallback(const v8::FunctionCallbackInfo<v8::Value>& info)
147 {
148 internalAddMessage(StartGroupMessageType, LogMessageLevel, info, true, 0);
149 }
150
151 void V8Console::groupCollapsedCallback(const v8::FunctionCallbackInfo<v8::Value> & info)
152 {
153 internalAddMessage(StartGroupCollapsedMessageType, LogMessageLevel, info, tr ue, 0);
154 }
155
156 void V8Console::groupEndCallback(const v8::FunctionCallbackInfo<v8::Value>& info )
157 {
158 internalAddMessage(EndGroupMessageType, LogMessageLevel, info, true, 0);
159 }
160
161 void V8Console::clearCallback(const v8::FunctionCallbackInfo<v8::Value>& info)
162 {
163 internalAddMessage(ClearMessageType, LogMessageLevel, info, true, 0);
164 }
165
166 void V8Console::countCallback(const v8::FunctionCallbackInfo<v8::Value>& info)
167 {
168 v8::Isolate* isolate = info.GetIsolate();
169 v8::Local<v8::Context> context = isolate->GetCurrentContext();
170
171 v8::Local<v8::Object> consoleObject;
172 if (!consoleObjectFromInfo(info).ToLocal(&consoleObject))
173 return;
174 V8DebuggerClient* client = clientFromConsoleObject(isolate, consoleObject);
175 if (!client)
176 return;
177
178 // Follow Firebug's behavior of counting with null and undefined title in
179 // the same bucket as no argument
180 String16 title;
181 if (info.Length() > 0 && (!info[0]->IsNull() || !info[0]->IsUndefined())) {
182 v8::Local<v8::String> titleValue;
183 if (info[0]->IsObject()) {
184 if (!info[0].As<v8::Object>()->ObjectProtoToString(context).ToLocal( &titleValue))
185 return;
186 } else {
187 if (!info[0]->ToString(context).ToLocal(&titleValue))
188 return;
189 }
190 title = toProtocolString(titleValue);
191 }
192
193 String16 identifier;
194 if (title.isEmpty()) {
195 OwnPtr<V8StackTraceImpl> stackTrace = V8StackTraceImpl::capture(nullptr, 1);
196 if (stackTrace)
197 identifier = stackTrace->topSourceURL() + ":" + String16::number(sta ckTrace->topLineNumber());
198 } else {
199 identifier = title + "@";
200 }
201
202 v8::Local<v8::Map> countMap;
203 if (!privateMapFromConsoleObject(info.GetIsolate(), consoleObject, "V8Consol e#countMap").ToLocal(&countMap))
204 return;
205
206 v8::Local<v8::String> key = toV8String(isolate, identifier);
207 int64_t count = 0;
208 if (countMap->Has(context, key).FromMaybe(false)) {
209 v8::Local<v8::Value> countValue;
210 if (!countMap->Get(context, key).ToLocal(&countValue))
211 return;
212 count = countValue.As<v8::Integer>()->Value();
213 }
214 ++count;
215 if (!countMap->Set(context, key, v8::Integer::New(isolate, count)).ToLocal(& countMap))
216 return;
217 String16 message = title + ": " + String16::number(count);
218 client->reportMessageToConsole(context, CountMessageType, DebugMessageLevel, message);
dgozman 2016/04/12 03:32:15 Use internalAddMessage instead?
kozy 2016/04/12 21:58:32 Done.
219 }
220
221 void V8Console::assertCallback(const v8::FunctionCallbackInfo<v8::Value>& info)
222 {
223 bool condition = false;
224 if (info.Length() > 0) {
225 if (info[0]->IsBoolean())
226 condition = info[0].As<v8::Boolean>()->Value();
227 else
228 condition = info[0]->BooleanValue(info.GetIsolate()->GetCurrentConte xt()).FromMaybe(false);
229 }
230 if (condition)
231 return;
232 internalAddMessage(AssertMessageType, ErrorMessageLevel, info, true, 1);
233 }
234
235 void V8Console::markTimelineCallback(const v8::FunctionCallbackInfo<v8::Value>& info)
236 {
237 if (!info.Data()->IsObject())
238 return;
239 v8::Local<v8::Object> consoleObject = info.Data().As<v8::Object>();
240 V8DebuggerClient* client = clientFromConsoleObject(info.GetIsolate(), consol eObject);
241 if (!client)
242 return;
243 client->reportMessageToConsole(info.GetIsolate()->GetCurrentContext(), LogMe ssageType, WarningMessageLevel, "'console.markTimeline' is deprecated. Please us e 'console.timeStamp' instead.");
dgozman 2016/04/12 03:32:15 Use internalAddMessage instead?
kozy 2016/04/12 21:58:32 Done.
244 }
245
246 void V8Console::profileCallback(const v8::FunctionCallbackInfo<v8::Value>& info)
247 {
248 v8::Local<v8::Object> consoleObject;
249 if (!consoleObjectFromInfo(info).ToLocal(&consoleObject))
250 return;
251 V8DebuggerImpl* debugger = debuggerFromConsoleObject(info.GetIsolate(), cons oleObject);
252 if (!debugger)
253 return;
254 V8ProfilerAgentImpl* profileAgent = debugger->findEnabledProfilerAgent(info. GetIsolate()->GetCurrentContext());
255 if (!profileAgent)
256 return;
257 String16 title = info.Length() > 0 ? toProtocolStringWithTypeCheck(info[0]) : String16();
258 profileAgent->consoleProfile(title);
259 }
260
261 void V8Console::profileEndCallback(const v8::FunctionCallbackInfo<v8::Value>& in fo)
262 {
263 v8::Local<v8::Object> consoleObject;
264 if (!consoleObjectFromInfo(info).ToLocal(&consoleObject))
265 return;
266 V8DebuggerImpl* debugger = debuggerFromConsoleObject(info.GetIsolate(), cons oleObject);
267 if (!debugger)
268 return;
269 V8ProfilerAgentImpl* profileAgent = debugger->findEnabledProfilerAgent(info. GetIsolate()->GetCurrentContext());
270 if (!profileAgent)
271 return;
272 String16 title = info.Length() > 0 ? toProtocolStringWithTypeCheck(info[0]) : String16();
273 profileAgent->consoleProfileEnd(title);
dgozman 2016/04/12 03:32:16 I'd move as much code to helper methods as possibl
kozy 2016/04/12 21:58:32 Done.
274 }
275
276 void V8Console::timelineCallback(const v8::FunctionCallbackInfo<v8::Value>& info )
277 {
278 v8::Local<v8::Object> consoleObject;
279 if (!consoleObjectFromInfo(info).ToLocal(&consoleObject))
280 return;
281 V8DebuggerClient* client = clientFromConsoleObject(info.GetIsolate(), consol eObject);
282 if (!client)
283 return;
284 client->reportMessageToConsole(info.GetIsolate()->GetCurrentContext(), LogMe ssageType, WarningMessageLevel, "'console.timeline' is deprecated. Please use 'c onsole.time' instead.");
dgozman 2016/04/12 03:32:16 Use internalAddMessage instead?
kozy 2016/04/12 21:58:32 Done.
285 }
286
287 void V8Console::timelineEndCallback(const v8::FunctionCallbackInfo<v8::Value>& i nfo)
288 {
289 v8::Local<v8::Object> consoleObject;
290 if (!consoleObjectFromInfo(info).ToLocal(&consoleObject))
291 return;
292 V8DebuggerClient* client = clientFromConsoleObject(info.GetIsolate(), consol eObject);
293 if (!client)
294 return;
295 client->reportMessageToConsole(info.GetIsolate()->GetCurrentContext(), LogMe ssageType, WarningMessageLevel, "'console.timelineEnd' is deprecated. Please use 'console.timeEnd' instead.");
dgozman 2016/04/12 03:32:15 Use internalAddMessage instead?
kozy 2016/04/12 21:58:32 Done.
296 }
297
298 void V8Console::timeCallback(const v8::FunctionCallbackInfo<v8::Value>& info)
dgozman 2016/04/12 03:32:15 I'd go for more helpers here as well: v8::Local<v
kozy 2016/04/12 21:58:32 Moved partially.
299 {
300 v8::Isolate* isolate = info.GetIsolate();
301 v8::Local<v8::Context> context = isolate->GetCurrentContext();
302 v8::Local<v8::Object> consoleObject;
303 if (!consoleObjectFromInfo(info).ToLocal(&consoleObject))
304 return;
305 V8DebuggerClient* client = clientFromConsoleObject(isolate, consoleObject);
306 if (!client)
307 return;
308 String16 protocolTitle = info.Length() > 0 ? toProtocolStringWithTypeCheck(i nfo[0]) : String16();
309 client->consoleTime(isolate, protocolTitle);
310
311 v8::Local<v8::Map> timeMap;
312 if (!privateMapFromConsoleObject(isolate, consoleObject, "V8Console#timeMap" ).ToLocal(&timeMap))
313 return;
314 v8::Local<v8::String> title;
315 if (!info[0]->ToString(context).ToLocal(&title))
316 return;
317 if (!timeMap->Set(context, title, v8::Number::New(isolate, client->currentTi meMS())).ToLocal(&timeMap))
318 return;
319 }
320
321 void V8Console::timeEndCallback(const v8::FunctionCallbackInfo<v8::Value>& info)
322 {
323 v8::Isolate* isolate = info.GetIsolate();
324 v8::Local<v8::Context> context = isolate->GetCurrentContext();
325 v8::Local<v8::Object> consoleObject;
326 if (!consoleObjectFromInfo(info).ToLocal(&consoleObject))
327 return;
328 V8DebuggerClient* client = clientFromConsoleObject(isolate, consoleObject);
dgozman 2016/04/12 03:32:15 I think we can replace many places with more reada
kozy 2016/04/12 21:58:32 Done.
329 if (!client)
330 return;
331 String16 protocolTitle = info.Length() > 0 ? toProtocolStringWithTypeCheck(i nfo[0]) : String16();
332 client->consoleTimeEnd(isolate, protocolTitle);
333
334 v8::Local<v8::Map> timeMap;
335 if (!privateMapFromConsoleObject(isolate, consoleObject, "V8Console#timeMap" ).ToLocal(&timeMap))
336 return;
337 v8::Local<v8::String> title;
338 if (!info[0]->ToString(context).ToLocal(&title))
339 return;
340 v8::Local<v8::Value> timeValue;
341 if (!timeMap->Get(context, title).ToLocal(&timeValue) || !timeValue->IsNumbe r())
342 return;
343 double elapsed = client->currentTimeMS() - timeValue.As<v8::Number>()->Value ();
344 String16 message = toProtocolString(title) + ": " + String16::fromDoubleFixe dPrecision(elapsed, 3) + "ms";
345 client->reportMessageToConsole(info.GetIsolate()->GetCurrentContext(), TimeE ndMessageType, DebugMessageLevel, message);
346 }
347
348 void V8Console::timeStampCallback(const v8::FunctionCallbackInfo<v8::Value>& inf o)
349 {
350 v8::Local<v8::Object> consoleObject;
351 if (!consoleObjectFromInfo(info).ToLocal(&consoleObject))
352 return;
353 V8DebuggerClient* client = clientFromConsoleObject(info.GetIsolate(), consol eObject);
354 if (!client)
355 return;
356 String16 title = info.Length() > 0 ? toProtocolStringWithTypeCheck(info[0]) : String16();
357 client->consoleTimeStamp(info.GetIsolate(), title);
358 }
359
360 void V8Console::memoryGetterCallback(const v8::FunctionCallbackInfo<v8::Value>& info)
361 {
362 v8::Local<v8::Object> consoleObject;
363 if (!consoleObjectFromInfo(info).ToLocal(&consoleObject))
364 return;
365 V8DebuggerClient* client = clientFromConsoleObject(info.GetIsolate(), consol eObject);
366 if (!client)
367 return;
368 v8::Local<v8::Value> memoryValue;
369 if (!client->memoryInfo(info.GetIsolate(), info.GetIsolate()->GetCurrentCont ext(), info.Holder()).ToLocal(&memoryValue))
370 return;
371 info.GetReturnValue().Set(memoryValue);
372 }
373
374 void V8Console::memorySetterCallback(const v8::FunctionCallbackInfo<v8::Value>& info)
375 {
376 // We can't make the attribute readonly as it breaks existing code that reli es on being able to assign to console.memory in strict mode. Instead, the setter just ignores the passed value. http://crbug.com/468611
377 }
378
379 v8::MaybeLocal<v8::Object> V8Console::create(v8::Local<v8::Context> context, V8D ebuggerImpl* debugger, bool hasMemoryAttribute)
380 {
381 v8::Isolate* isolate = context->GetIsolate();
382
383 v8::Local<v8::Object> console;
384 if (!createObjectWithClassName(isolate, context, "Console").ToLocal(&console ))
385 return v8::MaybeLocal<v8::Object>();
386
387 v8::Local<v8::Object> prototype;
388 if (!createObjectWithClassName(isolate, context, "ConsolePrototype").ToLocal (&prototype))
389 return v8::MaybeLocal<v8::Object>();
390
391 createBoundFunctionProperty(context, console, prototype, "debug", V8Console: :debugCallback);
392 createBoundFunctionProperty(context, console, prototype, "error", V8Console: :errorCallback);
393 createBoundFunctionProperty(context, console, prototype, "info", V8Console:: infoCallback);
394 createBoundFunctionProperty(context, console, prototype, "log", V8Console::l ogCallback);
395 createBoundFunctionProperty(context, console, prototype, "warn", V8Console:: warnCallback);
396 createBoundFunctionProperty(context, console, prototype, "dir", V8Console::d irCallback);
397 createBoundFunctionProperty(context, console, prototype, "dirxml", V8Console ::dirxmlCallback);
398 createBoundFunctionProperty(context, console, prototype, "table", V8Console: :tableCallback);
399 createBoundFunctionProperty(context, console, prototype, "trace", V8Console: :traceCallback);
400 createBoundFunctionProperty(context, console, prototype, "group", V8Console: :groupCallback);
401 createBoundFunctionProperty(context, console, prototype, "groupCollapsed", V 8Console::groupCollapsedCallback);
402 createBoundFunctionProperty(context, console, prototype, "groupEnd", V8Conso le::groupEndCallback);
403 createBoundFunctionProperty(context, console, prototype, "clear", V8Console: :clearCallback);
404 createBoundFunctionProperty(context, console, prototype, "count", V8Console: :countCallback);
405 createBoundFunctionProperty(context, console, prototype, "assert", V8Console ::assertCallback);
406 createBoundFunctionProperty(context, console, prototype, "markTimeline", V8C onsole::markTimelineCallback);
407 createBoundFunctionProperty(context, console, prototype, "profile", V8Consol e::profileCallback);
408 createBoundFunctionProperty(context, console, prototype, "profileEnd", V8Con sole::profileEndCallback);
409 createBoundFunctionProperty(context, console, prototype, "timeline", V8Conso le::timelineCallback);
410 createBoundFunctionProperty(context, console, prototype, "timelineEnd", V8Co nsole::timelineEndCallback);
411 createBoundFunctionProperty(context, console, prototype, "time", V8Console:: timeCallback);
412 createBoundFunctionProperty(context, console, prototype, "timeEnd", V8Consol e::timeEndCallback);
413 createBoundFunctionProperty(context, console, prototype, "timeStamp", V8Cons ole::timeStampCallback);
414
415 if (!console->SetPrototype(context, prototype).FromMaybe(false))
416 return v8::MaybeLocal<v8::Object>();
417
418 if (hasMemoryAttribute)
419 console->SetAccessorProperty(toV8StringInternalized(isolate, "memory"), v8::Function::New(isolate, V8Console::memoryGetterCallback, console), v8::Functi on::New(isolate, V8Console::memorySetterCallback), static_cast<v8::PropertyAttri bute>(v8::None), v8::DEFAULT);
420
421 console->SetPrivate(context, debuggerPrivateKey(isolate), v8::External::New( isolate, debugger));
dgozman 2016/04/12 03:32:16 I think it's better to store InspectedContext* poi
kozy 2016/04/12 21:58:32 Done.
422 return console;
423 }
424
425 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698