Chromium Code Reviews| OLD | NEW |
|---|---|
| (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/V8StackTraceImpl.h" | |
| 9 #include "platform/v8_inspector/V8StringUtil.h" | |
| 10 #include "platform/v8_inspector/public/ConsoleAPITypes.h" | |
| 11 #include "platform/v8_inspector/public/ConsoleTypes.h" | |
| 12 #include "platform/v8_inspector/public/V8DebuggerClient.h" | |
| 13 | |
| 14 namespace blink { | |
| 15 | |
| 16 namespace { | |
| 17 | |
| 18 v8::MaybeLocal<v8::Object> consoleObjectFromInfo(const v8::FunctionCallbackInfo< v8::Value>& info) | |
| 19 { | |
| 20 if (info.Data().IsEmpty() || !info.Data()->IsObject()) | |
| 21 return v8::MaybeLocal<v8::Object>(); | |
| 22 return info.Data().As<v8::Object>(); | |
| 23 } | |
| 24 | |
| 25 v8::Local<v8::Private> clientPrivateKey(v8::Isolate* isolate) | |
| 26 { | |
| 27 return v8::Private::ForApi(isolate, toV8StringInternalized(isolate, "V8Conso le#V8DebuggerClient")); | |
| 28 } | |
| 29 | |
| 30 V8DebuggerClient* clientFromConsoleObject(v8::Isolate* isolate, v8::Local<v8::Ob ject> console) | |
| 31 { | |
| 32 v8::Local<v8::Value> value; | |
| 33 if (!console->GetPrivate(isolate->GetCurrentContext(), clientPrivateKey(isol ate)).ToLocal(&value)) | |
| 34 return nullptr; | |
| 35 if (!value->IsExternal()) | |
|
dgozman
2016/04/08 18:18:46
ASSERT
kozy
2016/04/08 23:56:51
Done.
| |
| 36 return nullptr; | |
| 37 V8DebuggerClient* client = static_cast<V8DebuggerClient*>(value.As<v8::Exter nal>()->Value()); | |
| 38 return client; | |
| 39 } | |
| 40 | |
| 41 void internalAddMessage(MessageType type, MessageLevel level, const v8::Function CallbackInfo<v8::Value>& info, bool allowEmptyArguments, int firstArg) | |
|
dgozman
2016/04/08 18:18:46
skipArgumentCount
kozy
2016/04/08 23:56:51
Done.
| |
| 42 { | |
| 43 if (!allowEmptyArguments && !info.Length()) | |
| 44 return; | |
| 45 v8::Local<v8::Object> consoleObject; | |
| 46 if (!consoleObjectFromInfo(info).ToLocal(&consoleObject)) | |
| 47 return; | |
| 48 v8::Isolate* isolate = info.GetIsolate(); | |
| 49 V8DebuggerClient* client = clientFromConsoleObject(isolate, consoleObject); | |
| 50 if (!client) | |
| 51 return; | |
| 52 client->reportMessageToConsole(isolate->GetCurrentContext(), type, level, in fo, firstArg); | |
| 53 } | |
| 54 | |
| 55 bool createBoundFunctionProperty(v8::Local<v8::Context> context, v8::Local<v8::O bject> obj, const char* name, v8::FunctionCallback callback) | |
| 56 { | |
| 57 v8::Local<v8::String> funcName = toV8StringInternalized(context->GetIsolate( ), name); | |
| 58 v8::Local<v8::Function> func; | |
| 59 if (!v8::Function::New(context, callback, obj).ToLocal(&func)) | |
| 60 return false; | |
| 61 func->SetName(funcName); | |
| 62 return obj->CreateDataProperty(context, funcName, func).FromMaybe(false); | |
|
dgozman
2016/04/08 18:18:46
ASSERT
kozy
2016/04/08 23:56:51
Done.
| |
| 63 } | |
| 64 | |
| 65 v8::MaybeLocal<v8::Map> privateMapFromConsoleObject(v8::Isolate* isolate, v8::Lo cal<v8::Object> console, const char* name) | |
| 66 { | |
| 67 v8::Local<v8::Context> context = isolate->GetCurrentContext(); | |
| 68 | |
| 69 v8::Local<v8::Private> privateKey = v8::Private::ForApi(isolate, toV8StringI nternalized(isolate, name)); | |
| 70 v8::Local<v8::Value> mapValue; | |
| 71 if (!console->GetPrivate(context, privateKey).ToLocal(&mapValue)) | |
| 72 return v8::MaybeLocal<v8::Map>(); | |
| 73 if (mapValue->IsUndefined()) { | |
| 74 v8::Local<v8::Map> map = v8::Map::New(isolate); | |
| 75 if (!console->SetPrivate(context, privateKey, map).FromMaybe(false)) | |
| 76 return v8::MaybeLocal<v8::Map>(); | |
| 77 return map; | |
| 78 } | |
| 79 return mapValue->IsMap() ? mapValue.As<v8::Map>() : v8::MaybeLocal<v8::Map>( ); | |
| 80 } | |
| 81 | |
| 82 } // namespace | |
| 83 | |
| 84 void V8Console::debugCallback(const v8::FunctionCallbackInfo<v8::Value>& info) | |
| 85 { | |
| 86 internalAddMessage(LogMessageType, DebugMessageLevel, info, false, 0); | |
| 87 } | |
| 88 | |
| 89 void V8Console::errorCallback(const v8::FunctionCallbackInfo<v8::Value>& info) | |
| 90 { | |
| 91 internalAddMessage(LogMessageType, ErrorMessageLevel, info, false, 0); | |
| 92 } | |
| 93 | |
| 94 void V8Console::infoCallback(const v8::FunctionCallbackInfo<v8::Value>& info) | |
| 95 { | |
| 96 internalAddMessage(LogMessageType, InfoMessageLevel, info, false, 0); | |
| 97 } | |
| 98 | |
| 99 void V8Console::logCallback(const v8::FunctionCallbackInfo<v8::Value>& info) | |
| 100 { | |
| 101 internalAddMessage(LogMessageType, LogMessageLevel, info, false, 0); | |
| 102 } | |
| 103 | |
| 104 void V8Console::warnCallback(const v8::FunctionCallbackInfo<v8::Value>& info) | |
| 105 { | |
| 106 internalAddMessage(LogMessageType, WarningMessageLevel, info, false, 0); | |
| 107 } | |
| 108 | |
| 109 void V8Console::dirCallback(const v8::FunctionCallbackInfo<v8::Value>& info) | |
| 110 { | |
| 111 internalAddMessage(DirMessageType, LogMessageLevel, info, false, 0); | |
| 112 } | |
| 113 | |
| 114 void V8Console::dirxmlCallback(const v8::FunctionCallbackInfo<v8::Value>& info) | |
| 115 { | |
| 116 internalAddMessage(DirXMLMessageType, LogMessageLevel, info, false, 0); | |
| 117 } | |
| 118 | |
| 119 void V8Console::tableCallback(const v8::FunctionCallbackInfo<v8::Value>& info) | |
| 120 { | |
| 121 internalAddMessage(TableMessageType, LogMessageLevel, info, false, 0); | |
| 122 } | |
| 123 | |
| 124 void V8Console::traceCallback(const v8::FunctionCallbackInfo<v8::Value>& info) | |
| 125 { | |
| 126 internalAddMessage(TraceMessageType, LogMessageLevel, info, true, 0); | |
| 127 } | |
| 128 | |
| 129 void V8Console::groupCallback(const v8::FunctionCallbackInfo<v8::Value>& info) | |
| 130 { | |
| 131 internalAddMessage(StartGroupMessageType, LogMessageLevel, info, true, 0); | |
| 132 } | |
| 133 | |
| 134 void V8Console::groupCollapsedCallback(const v8::FunctionCallbackInfo<v8::Value> & info) | |
| 135 { | |
| 136 internalAddMessage(StartGroupCollapsedMessageType, LogMessageLevel, info, tr ue, 0); | |
| 137 } | |
| 138 | |
| 139 void V8Console::groupEndCallback(const v8::FunctionCallbackInfo<v8::Value>& info ) | |
| 140 { | |
| 141 internalAddMessage(EndGroupMessageType, LogMessageLevel, info, true, 0); | |
| 142 } | |
| 143 | |
| 144 void V8Console::clearCallback(const v8::FunctionCallbackInfo<v8::Value>& info) | |
| 145 { | |
| 146 internalAddMessage(ClearMessageType, LogMessageLevel, info, true, 0); | |
| 147 } | |
| 148 | |
| 149 void V8Console::countCallback(const v8::FunctionCallbackInfo<v8::Value>& info) | |
| 150 { | |
| 151 v8::Isolate* isolate = info.GetIsolate(); | |
| 152 v8::Local<v8::Context> context = isolate->GetCurrentContext(); | |
| 153 | |
| 154 v8::Local<v8::Object> consoleObject; | |
| 155 if (!consoleObjectFromInfo(info).ToLocal(&consoleObject)) | |
| 156 return; | |
| 157 V8DebuggerClient* client = clientFromConsoleObject(isolate, consoleObject); | |
| 158 if (!client) | |
| 159 return; | |
| 160 | |
| 161 // Follow Firebug's behavior of counting with null and undefined title in | |
| 162 // the same bucket as no argument | |
| 163 String16 title; | |
| 164 if (info.Length() > 0 && (!info[0]->IsNull() || !info[0]->IsUndefined())) { | |
| 165 v8::Local<v8::String> titleValue; | |
| 166 if (info[0]->IsObject()) { | |
| 167 if (!info[0].As<v8::Object>()->ObjectProtoToString(context).ToLocal( &titleValue)) | |
| 168 return; | |
| 169 } else { | |
| 170 if (!info[0]->ToString(context).ToLocal(&titleValue)) | |
| 171 return; | |
| 172 } | |
| 173 title = toProtocolString(titleValue); | |
| 174 } | |
| 175 | |
| 176 String16 identifier; | |
| 177 if (title.isEmpty()) { | |
| 178 OwnPtr<V8StackTraceImpl> stackTrace = V8StackTraceImpl::capture(nullptr, 1); | |
| 179 if (stackTrace) | |
| 180 identifier = stackTrace->topSourceURL() + ":" + String16::number(sta ckTrace->topLineNumber()); | |
| 181 } else { | |
| 182 identifier = title + "@"; | |
| 183 } | |
| 184 | |
| 185 v8::Local<v8::Map> countMap; | |
| 186 if (!privateMapFromConsoleObject(info.GetIsolate(), consoleObject, "V8Consol e#countMap").ToLocal(&countMap)) | |
| 187 return; | |
| 188 | |
| 189 v8::Local<v8::String> key = toV8String(isolate, identifier); | |
| 190 int64_t count = 0; | |
| 191 if (countMap->Has(context, key).FromMaybe(false)) { | |
| 192 v8::Local<v8::Value> countValue; | |
| 193 if (!countMap->Get(context, key).ToLocal(&countValue)) | |
| 194 return; | |
| 195 count = countValue.As<v8::Integer>()->Value(); | |
| 196 } | |
| 197 ++count; | |
| 198 if (!countMap->Set(context, key, v8::Integer::New(isolate, count)).ToLocal(& countMap)) | |
| 199 return; | |
| 200 String16 message = title + ": " + String16::number(count); | |
| 201 client->reportMessageToConsole(context, CountMessageType, DebugMessageLevel, message); | |
| 202 } | |
| 203 | |
| 204 void V8Console::assertCallback(const v8::FunctionCallbackInfo<v8::Value>& info) | |
| 205 { | |
| 206 bool condition = false; | |
| 207 if (info.Length() > 0) { | |
| 208 if (info[0]->IsBoolean()) | |
| 209 condition = info[0].As<v8::Boolean>()->Value(); | |
| 210 else | |
| 211 condition = info[0]->BooleanValue(info.GetIsolate()->GetCurrentConte xt()).FromMaybe(false); | |
| 212 } | |
| 213 if (condition) | |
| 214 return; | |
| 215 internalAddMessage(AssertMessageType, ErrorMessageLevel, info, true, 1); | |
| 216 } | |
| 217 | |
| 218 void V8Console::markTimelineCallback(const v8::FunctionCallbackInfo<v8::Value>& info) | |
| 219 { | |
| 220 if (!info.Data()->IsObject()) | |
| 221 return; | |
| 222 v8::Local<v8::Object> consoleObject = info.Data().As<v8::Object>(); | |
| 223 V8DebuggerClient* client = clientFromConsoleObject(info.GetIsolate(), consol eObject); | |
| 224 if (!client) | |
| 225 return; | |
| 226 client->reportMessageToConsole(info.GetIsolate()->GetCurrentContext(), LogMe ssageType, WarningMessageLevel, "console.markTimeline method was removed."); | |
| 227 } | |
| 228 | |
| 229 void V8Console::profileCallback(const v8::FunctionCallbackInfo<v8::Value>& info) | |
| 230 { | |
| 231 v8::Local<v8::Object> consoleObject; | |
| 232 if (!consoleObjectFromInfo(info).ToLocal(&consoleObject)) | |
| 233 return; | |
| 234 V8DebuggerClient* client = clientFromConsoleObject(info.GetIsolate(), consol eObject); | |
| 235 if (!client) | |
| 236 return; | |
| 237 String16 title = info.Length() > 0 ? toProtocolStringWithTypeCheck(info[0]) : String16(); | |
| 238 client->profile(info.GetIsolate()->GetCurrentContext(), title); | |
| 239 } | |
| 240 | |
| 241 void V8Console::profileEndCallback(const v8::FunctionCallbackInfo<v8::Value>& in fo) | |
| 242 { | |
| 243 v8::Local<v8::Object> consoleObject; | |
| 244 if (!consoleObjectFromInfo(info).ToLocal(&consoleObject)) | |
| 245 return; | |
| 246 V8DebuggerClient* client = clientFromConsoleObject(info.GetIsolate(), consol eObject); | |
| 247 if (!client) | |
| 248 return; | |
| 249 String16 title = info.Length() > 0 ? toProtocolStringWithTypeCheck(info[0]) : String16(); | |
| 250 client->profileEnd(info.GetIsolate()->GetCurrentContext(), title); | |
| 251 } | |
| 252 | |
| 253 void V8Console::timelineCallback(const v8::FunctionCallbackInfo<v8::Value>& info ) | |
| 254 { | |
| 255 v8::Local<v8::Object> consoleObject; | |
| 256 if (!consoleObjectFromInfo(info).ToLocal(&consoleObject)) | |
| 257 return; | |
| 258 V8DebuggerClient* client = clientFromConsoleObject(info.GetIsolate(), consol eObject); | |
| 259 if (!client) | |
| 260 return; | |
| 261 client->reportMessageToConsole(info.GetIsolate()->GetCurrentContext(), LogMe ssageType, WarningMessageLevel, "console.timeline method was removed. Please use console.time imstead."); | |
| 262 } | |
| 263 | |
| 264 void V8Console::timelineEndCallback(const v8::FunctionCallbackInfo<v8::Value>& i nfo) | |
| 265 { | |
| 266 v8::Local<v8::Object> consoleObject; | |
| 267 if (!consoleObjectFromInfo(info).ToLocal(&consoleObject)) | |
| 268 return; | |
| 269 V8DebuggerClient* client = clientFromConsoleObject(info.GetIsolate(), consol eObject); | |
| 270 if (!client) | |
| 271 return; | |
| 272 client->reportMessageToConsole(info.GetIsolate()->GetCurrentContext(), LogMe ssageType, WarningMessageLevel, "console.timelineEnd method was removed. Please use console.timeEnd imstead."); | |
| 273 } | |
| 274 | |
| 275 void V8Console::timeCallback(const v8::FunctionCallbackInfo<v8::Value>& info) | |
| 276 { | |
| 277 v8::Isolate* isolate = info.GetIsolate(); | |
| 278 v8::Local<v8::Context> context = isolate->GetCurrentContext(); | |
| 279 v8::Local<v8::Object> consoleObject; | |
| 280 if (!consoleObjectFromInfo(info).ToLocal(&consoleObject)) | |
| 281 return; | |
| 282 V8DebuggerClient* client = clientFromConsoleObject(isolate, consoleObject); | |
| 283 if (!client) | |
| 284 return; | |
| 285 v8::Local<v8::Map> timeMap; | |
| 286 if (!privateMapFromConsoleObject(isolate, consoleObject, "V8Console#timeMap" ).ToLocal(&timeMap)) | |
| 287 return; | |
| 288 v8::Local<v8::String> title; | |
| 289 if (!info[0]->ToString(context).ToLocal(&title)) | |
| 290 return; | |
| 291 if (!timeMap->Set(context, title, v8::Number::New(isolate, client->currentTi meMS())).ToLocal(&timeMap)) | |
| 292 return; | |
| 293 } | |
| 294 | |
| 295 void V8Console::timeEndCallback(const v8::FunctionCallbackInfo<v8::Value>& info) | |
| 296 { | |
| 297 v8::Isolate* isolate = info.GetIsolate(); | |
| 298 v8::Local<v8::Context> context = isolate->GetCurrentContext(); | |
| 299 v8::Local<v8::Object> consoleObject; | |
| 300 if (!consoleObjectFromInfo(info).ToLocal(&consoleObject)) | |
| 301 return; | |
| 302 V8DebuggerClient* client = clientFromConsoleObject(isolate, consoleObject); | |
| 303 if (!client) | |
| 304 return; | |
| 305 v8::Local<v8::Map> timeMap; | |
| 306 if (!privateMapFromConsoleObject(isolate, consoleObject, "V8Console#timeMap" ).ToLocal(&timeMap)) | |
| 307 return; | |
| 308 v8::Local<v8::String> title; | |
| 309 if (!info[0]->ToString(context).ToLocal(&title)) | |
| 310 return; | |
| 311 v8::Local<v8::Value> timeValue; | |
| 312 if (!timeMap->Get(context, title).ToLocal(&timeValue) || !timeValue->IsNumbe r()) | |
| 313 return; | |
| 314 double elapsed = client->currentTimeMS() - timeValue.As<v8::Number>()->Value (); | |
| 315 String16 message = toProtocolString(title) + ": " + String16::fromDouble(ela psed, 3) + "ms"; | |
| 316 client->reportMessageToConsole(info.GetIsolate()->GetCurrentContext(), TimeE ndMessageType, DebugMessageLevel, message); | |
| 317 } | |
| 318 | |
| 319 void V8Console::timeStampCallback(const v8::FunctionCallbackInfo<v8::Value>& inf o) | |
| 320 { | |
| 321 v8::Local<v8::Object> consoleObject; | |
| 322 if (!consoleObjectFromInfo(info).ToLocal(&consoleObject)) | |
| 323 return; | |
| 324 V8DebuggerClient* client = clientFromConsoleObject(info.GetIsolate(), consol eObject); | |
| 325 if (!client) | |
| 326 return; | |
| 327 String16 title = info.Length() > 0 ? toProtocolStringWithTypeCheck(info[0]) : String16(); | |
| 328 client->timeStamp(info.GetIsolate(), title); | |
| 329 } | |
| 330 | |
| 331 void V8Console::memoryGetterCallback(const v8::FunctionCallbackInfo<v8::Value>& info) | |
| 332 { | |
| 333 v8::Local<v8::Object> consoleObject; | |
| 334 if (!consoleObjectFromInfo(info).ToLocal(&consoleObject)) | |
| 335 return; | |
| 336 V8DebuggerClient* client = clientFromConsoleObject(info.GetIsolate(), consol eObject); | |
| 337 if (!client) | |
| 338 return; | |
| 339 v8::Local<v8::Value> memoryValue; | |
| 340 if (!client->memoryInfo(info.GetIsolate(), info.GetIsolate()->GetCurrentCont ext(), info.Holder()).ToLocal(&memoryValue)) | |
| 341 return; | |
| 342 info.GetReturnValue().Set(memoryValue); | |
| 343 } | |
| 344 | |
| 345 v8::Local<v8::Object> V8Console::create(v8::Local<v8::Context> context, V8Debugg erClient* client) | |
| 346 { | |
| 347 v8::Isolate* isolate = context->GetIsolate(); | |
| 348 v8::Local<v8::Object> console = v8::Object::New(isolate); | |
| 349 createBoundFunctionProperty(context, console, "debug", V8Console::debugCallb ack); | |
| 350 createBoundFunctionProperty(context, console, "error", V8Console::errorCallb ack); | |
| 351 createBoundFunctionProperty(context, console, "info", V8Console::infoCallbac k); | |
| 352 createBoundFunctionProperty(context, console, "log", V8Console::logCallback) ; | |
| 353 createBoundFunctionProperty(context, console, "warn", V8Console::warnCallbac k); | |
| 354 createBoundFunctionProperty(context, console, "dir", V8Console::dirCallback) ; | |
| 355 createBoundFunctionProperty(context, console, "dirxml", V8Console::dirxmlCal lback); | |
| 356 createBoundFunctionProperty(context, console, "table", V8Console::tableCallb ack); | |
| 357 createBoundFunctionProperty(context, console, "trace", V8Console::traceCallb ack); | |
| 358 createBoundFunctionProperty(context, console, "group", V8Console::groupCallb ack); | |
| 359 createBoundFunctionProperty(context, console, "groupCollapsed", V8Console::g roupCollapsedCallback); | |
| 360 createBoundFunctionProperty(context, console, "groupEnd", V8Console::groupEn dCallback); | |
| 361 createBoundFunctionProperty(context, console, "clear", V8Console::clearCallb ack); | |
| 362 createBoundFunctionProperty(context, console, "count", V8Console::countCallb ack); | |
| 363 createBoundFunctionProperty(context, console, "assert", V8Console::assertCal lback); | |
| 364 createBoundFunctionProperty(context, console, "markTimeline", V8Console::mar kTimelineCallback); | |
| 365 createBoundFunctionProperty(context, console, "profile", V8Console::profileC allback); | |
| 366 createBoundFunctionProperty(context, console, "profileEnd", V8Console::profi leEndCallback); | |
| 367 createBoundFunctionProperty(context, console, "timeline", V8Console::timelin eCallback); | |
| 368 createBoundFunctionProperty(context, console, "timelineEnd", V8Console::time lineEndCallback); | |
| 369 createBoundFunctionProperty(context, console, "time", V8Console::timeCallbac k); | |
| 370 createBoundFunctionProperty(context, console, "timeEnd", V8Console::timeEndC allback); | |
| 371 createBoundFunctionProperty(context, console, "timeStamp", V8Console::timeSt ampCallback); | |
| 372 if (client->hasMemoryOnConsole(context)) | |
| 373 console->SetAccessorProperty(toV8StringInternalized(isolate, "memory"), v8::Function::New(isolate, V8Console::memoryGetterCallback, console), v8::Local< v8::Function>(), static_cast<v8::PropertyAttribute>(v8::None), v8::DEFAULT); | |
| 374 | |
| 375 console->SetPrivate(context, clientPrivateKey(isolate), v8::External::New(is olate, client)); | |
| 376 return console; | |
| 377 } | |
| 378 | |
| 379 } // namespace blink | |
| OLD | NEW |