Chromium Code Reviews| Index: third_party/WebKit/Source/platform/v8_inspector/V8Console.cpp | 
| diff --git a/third_party/WebKit/Source/platform/v8_inspector/V8Console.cpp b/third_party/WebKit/Source/platform/v8_inspector/V8Console.cpp | 
| new file mode 100644 | 
| index 0000000000000000000000000000000000000000..d7931e2eca827b97fffa6ca093634522653b03a4 | 
| --- /dev/null | 
| +++ b/third_party/WebKit/Source/platform/v8_inspector/V8Console.cpp | 
| @@ -0,0 +1,425 @@ | 
| +// Copyright 2016 The Chromium Authors. All rights reserved. | 
| +// Use of this source code is governed by a BSD-style license that can be | 
| +// found in the LICENSE file. | 
| + | 
| +#include "platform/v8_inspector/V8Console.h" | 
| + | 
| +#include "platform/inspector_protocol/String16.h" | 
| +#include "platform/v8_inspector/V8DebuggerImpl.h" | 
| +#include "platform/v8_inspector/V8ProfilerAgentImpl.h" | 
| +#include "platform/v8_inspector/V8StackTraceImpl.h" | 
| +#include "platform/v8_inspector/V8StringUtil.h" | 
| +#include "platform/v8_inspector/public/ConsoleAPITypes.h" | 
| +#include "platform/v8_inspector/public/ConsoleTypes.h" | 
| +#include "platform/v8_inspector/public/V8DebuggerClient.h" | 
| + | 
| +namespace blink { | 
| + | 
| +namespace { | 
| + | 
| +v8::MaybeLocal<v8::Object> consoleObjectFromInfo(const v8::FunctionCallbackInfo<v8::Value>& info) | 
| +{ | 
| + if (info.Data().IsEmpty() || !info.Data()->IsObject()) | 
| + return v8::MaybeLocal<v8::Object>(); | 
| + return info.Data().As<v8::Object>(); | 
| +} | 
| + | 
| +v8::Local<v8::Private> debuggerPrivateKey(v8::Isolate* isolate) | 
| +{ | 
| + return v8::Private::ForApi(isolate, toV8StringInternalized(isolate, "V8Console#V8DebuggerImpl")); | 
| +} | 
| + | 
| +V8DebuggerImpl* debuggerFromConsoleObject(v8::Isolate* isolate, v8::Local<v8::Object> console) | 
| +{ | 
| + v8::Local<v8::Value> value; | 
| + if (!console->GetPrivate(isolate->GetCurrentContext(), debuggerPrivateKey(isolate)).ToLocal(&value)) | 
| + return nullptr; | 
| + ASSERT(!value->IsExternal()); | 
| + return static_cast<V8DebuggerImpl*>(value.As<v8::External>()->Value()); | 
| +} | 
| + | 
| +V8DebuggerClient* clientFromConsoleObject(v8::Isolate* isolate, v8::Local<v8::Object> console) | 
| +{ | 
| + V8DebuggerImpl* debugger = debuggerFromConsoleObject(isolate, console); | 
| + return debugger ? debugger->client() : nullptr; | 
| +} | 
| + | 
| +void internalAddMessage(MessageType type, MessageLevel level, const v8::FunctionCallbackInfo<v8::Value>& info, bool allowEmptyArguments, int skipArgumentCount) | 
| +{ | 
| + if (!allowEmptyArguments && !info.Length()) | 
| + return; | 
| + v8::Local<v8::Object> consoleObject; | 
| + if (!consoleObjectFromInfo(info).ToLocal(&consoleObject)) | 
| + return; | 
| + v8::Isolate* isolate = info.GetIsolate(); | 
| + V8DebuggerClient* client = clientFromConsoleObject(isolate, consoleObject); | 
| + if (!client) | 
| + return; | 
| + client->reportMessageToConsole(isolate->GetCurrentContext(), type, level, info, skipArgumentCount); | 
| +} | 
| + | 
| +void createBoundFunctionProperty(v8::Local<v8::Context> context, v8::Local<v8::Object> obj, v8::Local<v8::Object> prototype, const char* name, v8::FunctionCallback callback) | 
| +{ | 
| + v8::Local<v8::String> funcName = toV8StringInternalized(context->GetIsolate(), name); | 
| + v8::Local<v8::Function> func; | 
| + if (!v8::Function::New(context, callback, obj).ToLocal(&func)) | 
| + return; | 
| + func->SetName(funcName); | 
| + if (!prototype->Set(context, funcName, func).FromMaybe(false)) | 
| + return; | 
| +} | 
| + | 
| +v8::MaybeLocal<v8::Map> privateMapFromConsoleObject(v8::Isolate* isolate, v8::Local<v8::Object> console, const char* name) | 
| +{ | 
| + v8::Local<v8::Context> context = isolate->GetCurrentContext(); | 
| + | 
| + v8::Local<v8::Private> privateKey = v8::Private::ForApi(isolate, toV8StringInternalized(isolate, name)); | 
| + v8::Local<v8::Value> mapValue; | 
| + if (!console->GetPrivate(context, privateKey).ToLocal(&mapValue)) | 
| + return v8::MaybeLocal<v8::Map>(); | 
| + if (mapValue->IsUndefined()) { | 
| + v8::Local<v8::Map> map = v8::Map::New(isolate); | 
| + if (!console->SetPrivate(context, privateKey, map).FromMaybe(false)) | 
| + return v8::MaybeLocal<v8::Map>(); | 
| + return map; | 
| + } | 
| + return mapValue->IsMap() ? mapValue.As<v8::Map>() : v8::MaybeLocal<v8::Map>(); | 
| +} | 
| + | 
| +v8::MaybeLocal<v8::Object> createObjectWithClassName(v8::Isolate* isolate, v8::Local<v8::Context> context, const char* className) | 
| +{ | 
| + 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.
 
 | 
| + functionTemplate->SetClassName(toV8StringInternalized(isolate, className)); | 
| + v8::Local<v8::Function> constructor; | 
| + if (!functionTemplate->GetFunction(context).ToLocal(&constructor)) | 
| + return v8::MaybeLocal<v8::Object>(); | 
| + return constructor->NewInstance(context, 0, nullptr); | 
| +} | 
| + | 
| +} // namespace | 
| + | 
| +void V8Console::debugCallback(const v8::FunctionCallbackInfo<v8::Value>& info) | 
| +{ | 
| + internalAddMessage(LogMessageType, DebugMessageLevel, info, false, 0); | 
| +} | 
| + | 
| +void V8Console::errorCallback(const v8::FunctionCallbackInfo<v8::Value>& info) | 
| +{ | 
| + internalAddMessage(LogMessageType, ErrorMessageLevel, info, false, 0); | 
| +} | 
| + | 
| +void V8Console::infoCallback(const v8::FunctionCallbackInfo<v8::Value>& info) | 
| +{ | 
| + internalAddMessage(LogMessageType, InfoMessageLevel, info, false, 0); | 
| +} | 
| + | 
| +void V8Console::logCallback(const v8::FunctionCallbackInfo<v8::Value>& info) | 
| +{ | 
| + internalAddMessage(LogMessageType, LogMessageLevel, info, false, 0); | 
| +} | 
| + | 
| +void V8Console::warnCallback(const v8::FunctionCallbackInfo<v8::Value>& info) | 
| +{ | 
| + internalAddMessage(LogMessageType, WarningMessageLevel, info, false, 0); | 
| +} | 
| + | 
| +void V8Console::dirCallback(const v8::FunctionCallbackInfo<v8::Value>& info) | 
| +{ | 
| + internalAddMessage(DirMessageType, LogMessageLevel, info, false, 0); | 
| +} | 
| + | 
| +void V8Console::dirxmlCallback(const v8::FunctionCallbackInfo<v8::Value>& info) | 
| +{ | 
| + internalAddMessage(DirXMLMessageType, LogMessageLevel, info, false, 0); | 
| +} | 
| + | 
| +void V8Console::tableCallback(const v8::FunctionCallbackInfo<v8::Value>& info) | 
| +{ | 
| + internalAddMessage(TableMessageType, LogMessageLevel, info, false, 0); | 
| +} | 
| + | 
| +void V8Console::traceCallback(const v8::FunctionCallbackInfo<v8::Value>& info) | 
| +{ | 
| + internalAddMessage(TraceMessageType, LogMessageLevel, info, true, 0); | 
| +} | 
| + | 
| +void V8Console::groupCallback(const v8::FunctionCallbackInfo<v8::Value>& info) | 
| +{ | 
| + internalAddMessage(StartGroupMessageType, LogMessageLevel, info, true, 0); | 
| +} | 
| + | 
| +void V8Console::groupCollapsedCallback(const v8::FunctionCallbackInfo<v8::Value>& info) | 
| +{ | 
| + internalAddMessage(StartGroupCollapsedMessageType, LogMessageLevel, info, true, 0); | 
| +} | 
| + | 
| +void V8Console::groupEndCallback(const v8::FunctionCallbackInfo<v8::Value>& info) | 
| +{ | 
| + internalAddMessage(EndGroupMessageType, LogMessageLevel, info, true, 0); | 
| +} | 
| + | 
| +void V8Console::clearCallback(const v8::FunctionCallbackInfo<v8::Value>& info) | 
| +{ | 
| + internalAddMessage(ClearMessageType, LogMessageLevel, info, true, 0); | 
| +} | 
| + | 
| +void V8Console::countCallback(const v8::FunctionCallbackInfo<v8::Value>& info) | 
| +{ | 
| + v8::Isolate* isolate = info.GetIsolate(); | 
| + v8::Local<v8::Context> context = isolate->GetCurrentContext(); | 
| + | 
| + v8::Local<v8::Object> consoleObject; | 
| + if (!consoleObjectFromInfo(info).ToLocal(&consoleObject)) | 
| + return; | 
| + V8DebuggerClient* client = clientFromConsoleObject(isolate, consoleObject); | 
| + if (!client) | 
| + return; | 
| + | 
| + // Follow Firebug's behavior of counting with null and undefined title in | 
| + // the same bucket as no argument | 
| + String16 title; | 
| + if (info.Length() > 0 && (!info[0]->IsNull() || !info[0]->IsUndefined())) { | 
| + v8::Local<v8::String> titleValue; | 
| + if (info[0]->IsObject()) { | 
| + if (!info[0].As<v8::Object>()->ObjectProtoToString(context).ToLocal(&titleValue)) | 
| + return; | 
| + } else { | 
| + if (!info[0]->ToString(context).ToLocal(&titleValue)) | 
| + return; | 
| + } | 
| + title = toProtocolString(titleValue); | 
| + } | 
| + | 
| + String16 identifier; | 
| + if (title.isEmpty()) { | 
| + OwnPtr<V8StackTraceImpl> stackTrace = V8StackTraceImpl::capture(nullptr, 1); | 
| + if (stackTrace) | 
| + identifier = stackTrace->topSourceURL() + ":" + String16::number(stackTrace->topLineNumber()); | 
| + } else { | 
| + identifier = title + "@"; | 
| + } | 
| + | 
| + v8::Local<v8::Map> countMap; | 
| + if (!privateMapFromConsoleObject(info.GetIsolate(), consoleObject, "V8Console#countMap").ToLocal(&countMap)) | 
| + return; | 
| + | 
| + v8::Local<v8::String> key = toV8String(isolate, identifier); | 
| + int64_t count = 0; | 
| + if (countMap->Has(context, key).FromMaybe(false)) { | 
| + v8::Local<v8::Value> countValue; | 
| + if (!countMap->Get(context, key).ToLocal(&countValue)) | 
| + return; | 
| + count = countValue.As<v8::Integer>()->Value(); | 
| + } | 
| + ++count; | 
| + if (!countMap->Set(context, key, v8::Integer::New(isolate, count)).ToLocal(&countMap)) | 
| + return; | 
| + String16 message = title + ": " + String16::number(count); | 
| + client->reportMessageToConsole(context, CountMessageType, DebugMessageLevel, message); | 
| 
 
dgozman
2016/04/12 03:32:15
Use internalAddMessage instead?
 
kozy
2016/04/12 21:58:32
Done.
 
 | 
| +} | 
| + | 
| +void V8Console::assertCallback(const v8::FunctionCallbackInfo<v8::Value>& info) | 
| +{ | 
| + bool condition = false; | 
| + if (info.Length() > 0) { | 
| + if (info[0]->IsBoolean()) | 
| + condition = info[0].As<v8::Boolean>()->Value(); | 
| + else | 
| + condition = info[0]->BooleanValue(info.GetIsolate()->GetCurrentContext()).FromMaybe(false); | 
| + } | 
| + if (condition) | 
| + return; | 
| + internalAddMessage(AssertMessageType, ErrorMessageLevel, info, true, 1); | 
| +} | 
| + | 
| +void V8Console::markTimelineCallback(const v8::FunctionCallbackInfo<v8::Value>& info) | 
| +{ | 
| + if (!info.Data()->IsObject()) | 
| + return; | 
| + v8::Local<v8::Object> consoleObject = info.Data().As<v8::Object>(); | 
| + V8DebuggerClient* client = clientFromConsoleObject(info.GetIsolate(), consoleObject); | 
| + if (!client) | 
| + return; | 
| + client->reportMessageToConsole(info.GetIsolate()->GetCurrentContext(), LogMessageType, WarningMessageLevel, "'console.markTimeline' is deprecated. Please use 'console.timeStamp' instead."); | 
| 
 
dgozman
2016/04/12 03:32:15
Use internalAddMessage instead?
 
kozy
2016/04/12 21:58:32
Done.
 
 | 
| +} | 
| + | 
| +void V8Console::profileCallback(const v8::FunctionCallbackInfo<v8::Value>& info) | 
| +{ | 
| + v8::Local<v8::Object> consoleObject; | 
| + if (!consoleObjectFromInfo(info).ToLocal(&consoleObject)) | 
| + return; | 
| + V8DebuggerImpl* debugger = debuggerFromConsoleObject(info.GetIsolate(), consoleObject); | 
| + if (!debugger) | 
| + return; | 
| + V8ProfilerAgentImpl* profileAgent = debugger->findEnabledProfilerAgent(info.GetIsolate()->GetCurrentContext()); | 
| + if (!profileAgent) | 
| + return; | 
| + String16 title = info.Length() > 0 ? toProtocolStringWithTypeCheck(info[0]) : String16(); | 
| + profileAgent->consoleProfile(title); | 
| +} | 
| + | 
| +void V8Console::profileEndCallback(const v8::FunctionCallbackInfo<v8::Value>& info) | 
| +{ | 
| + v8::Local<v8::Object> consoleObject; | 
| + if (!consoleObjectFromInfo(info).ToLocal(&consoleObject)) | 
| + return; | 
| + V8DebuggerImpl* debugger = debuggerFromConsoleObject(info.GetIsolate(), consoleObject); | 
| + if (!debugger) | 
| + return; | 
| + V8ProfilerAgentImpl* profileAgent = debugger->findEnabledProfilerAgent(info.GetIsolate()->GetCurrentContext()); | 
| + if (!profileAgent) | 
| + return; | 
| + String16 title = info.Length() > 0 ? toProtocolStringWithTypeCheck(info[0]) : String16(); | 
| + 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.
 
 | 
| +} | 
| + | 
| +void V8Console::timelineCallback(const v8::FunctionCallbackInfo<v8::Value>& info) | 
| +{ | 
| + v8::Local<v8::Object> consoleObject; | 
| + if (!consoleObjectFromInfo(info).ToLocal(&consoleObject)) | 
| + return; | 
| + V8DebuggerClient* client = clientFromConsoleObject(info.GetIsolate(), consoleObject); | 
| + if (!client) | 
| + return; | 
| + client->reportMessageToConsole(info.GetIsolate()->GetCurrentContext(), LogMessageType, WarningMessageLevel, "'console.timeline' is deprecated. Please use 'console.time' instead."); | 
| 
 
dgozman
2016/04/12 03:32:16
Use internalAddMessage instead?
 
kozy
2016/04/12 21:58:32
Done.
 
 | 
| +} | 
| + | 
| +void V8Console::timelineEndCallback(const v8::FunctionCallbackInfo<v8::Value>& info) | 
| +{ | 
| + v8::Local<v8::Object> consoleObject; | 
| + if (!consoleObjectFromInfo(info).ToLocal(&consoleObject)) | 
| + return; | 
| + V8DebuggerClient* client = clientFromConsoleObject(info.GetIsolate(), consoleObject); | 
| + if (!client) | 
| + return; | 
| + client->reportMessageToConsole(info.GetIsolate()->GetCurrentContext(), LogMessageType, 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.
 
 | 
| +} | 
| + | 
| +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.
 
 | 
| +{ | 
| + v8::Isolate* isolate = info.GetIsolate(); | 
| + v8::Local<v8::Context> context = isolate->GetCurrentContext(); | 
| + v8::Local<v8::Object> consoleObject; | 
| + if (!consoleObjectFromInfo(info).ToLocal(&consoleObject)) | 
| + return; | 
| + V8DebuggerClient* client = clientFromConsoleObject(isolate, consoleObject); | 
| + if (!client) | 
| + return; | 
| + String16 protocolTitle = info.Length() > 0 ? toProtocolStringWithTypeCheck(info[0]) : String16(); | 
| + client->consoleTime(isolate, protocolTitle); | 
| + | 
| + v8::Local<v8::Map> timeMap; | 
| + if (!privateMapFromConsoleObject(isolate, consoleObject, "V8Console#timeMap").ToLocal(&timeMap)) | 
| + return; | 
| + v8::Local<v8::String> title; | 
| + if (!info[0]->ToString(context).ToLocal(&title)) | 
| + return; | 
| + if (!timeMap->Set(context, title, v8::Number::New(isolate, client->currentTimeMS())).ToLocal(&timeMap)) | 
| + return; | 
| +} | 
| + | 
| +void V8Console::timeEndCallback(const v8::FunctionCallbackInfo<v8::Value>& info) | 
| +{ | 
| + v8::Isolate* isolate = info.GetIsolate(); | 
| + v8::Local<v8::Context> context = isolate->GetCurrentContext(); | 
| + v8::Local<v8::Object> consoleObject; | 
| + if (!consoleObjectFromInfo(info).ToLocal(&consoleObject)) | 
| + return; | 
| + 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.
 
 | 
| + if (!client) | 
| + return; | 
| + String16 protocolTitle = info.Length() > 0 ? toProtocolStringWithTypeCheck(info[0]) : String16(); | 
| + client->consoleTimeEnd(isolate, protocolTitle); | 
| + | 
| + v8::Local<v8::Map> timeMap; | 
| + if (!privateMapFromConsoleObject(isolate, consoleObject, "V8Console#timeMap").ToLocal(&timeMap)) | 
| + return; | 
| + v8::Local<v8::String> title; | 
| + if (!info[0]->ToString(context).ToLocal(&title)) | 
| + return; | 
| + v8::Local<v8::Value> timeValue; | 
| + if (!timeMap->Get(context, title).ToLocal(&timeValue) || !timeValue->IsNumber()) | 
| + return; | 
| + double elapsed = client->currentTimeMS() - timeValue.As<v8::Number>()->Value(); | 
| + String16 message = toProtocolString(title) + ": " + String16::fromDoubleFixedPrecision(elapsed, 3) + "ms"; | 
| + client->reportMessageToConsole(info.GetIsolate()->GetCurrentContext(), TimeEndMessageType, DebugMessageLevel, message); | 
| +} | 
| + | 
| +void V8Console::timeStampCallback(const v8::FunctionCallbackInfo<v8::Value>& info) | 
| +{ | 
| + v8::Local<v8::Object> consoleObject; | 
| + if (!consoleObjectFromInfo(info).ToLocal(&consoleObject)) | 
| + return; | 
| + V8DebuggerClient* client = clientFromConsoleObject(info.GetIsolate(), consoleObject); | 
| + if (!client) | 
| + return; | 
| + String16 title = info.Length() > 0 ? toProtocolStringWithTypeCheck(info[0]) : String16(); | 
| + client->consoleTimeStamp(info.GetIsolate(), title); | 
| +} | 
| + | 
| +void V8Console::memoryGetterCallback(const v8::FunctionCallbackInfo<v8::Value>& info) | 
| +{ | 
| + v8::Local<v8::Object> consoleObject; | 
| + if (!consoleObjectFromInfo(info).ToLocal(&consoleObject)) | 
| + return; | 
| + V8DebuggerClient* client = clientFromConsoleObject(info.GetIsolate(), consoleObject); | 
| + if (!client) | 
| + return; | 
| + v8::Local<v8::Value> memoryValue; | 
| + if (!client->memoryInfo(info.GetIsolate(), info.GetIsolate()->GetCurrentContext(), info.Holder()).ToLocal(&memoryValue)) | 
| + return; | 
| + info.GetReturnValue().Set(memoryValue); | 
| +} | 
| + | 
| +void V8Console::memorySetterCallback(const v8::FunctionCallbackInfo<v8::Value>& info) | 
| +{ | 
| + // We can't make the attribute readonly as it breaks existing code that relies on being able to assign to console.memory in strict mode. Instead, the setter just ignores the passed value. http://crbug.com/468611 | 
| +} | 
| + | 
| +v8::MaybeLocal<v8::Object> V8Console::create(v8::Local<v8::Context> context, V8DebuggerImpl* debugger, bool hasMemoryAttribute) | 
| +{ | 
| + v8::Isolate* isolate = context->GetIsolate(); | 
| + | 
| + v8::Local<v8::Object> console; | 
| + if (!createObjectWithClassName(isolate, context, "Console").ToLocal(&console)) | 
| + return v8::MaybeLocal<v8::Object>(); | 
| + | 
| + v8::Local<v8::Object> prototype; | 
| + if (!createObjectWithClassName(isolate, context, "ConsolePrototype").ToLocal(&prototype)) | 
| + return v8::MaybeLocal<v8::Object>(); | 
| + | 
| + createBoundFunctionProperty(context, console, prototype, "debug", V8Console::debugCallback); | 
| + createBoundFunctionProperty(context, console, prototype, "error", V8Console::errorCallback); | 
| + createBoundFunctionProperty(context, console, prototype, "info", V8Console::infoCallback); | 
| + createBoundFunctionProperty(context, console, prototype, "log", V8Console::logCallback); | 
| + createBoundFunctionProperty(context, console, prototype, "warn", V8Console::warnCallback); | 
| + createBoundFunctionProperty(context, console, prototype, "dir", V8Console::dirCallback); | 
| + createBoundFunctionProperty(context, console, prototype, "dirxml", V8Console::dirxmlCallback); | 
| + createBoundFunctionProperty(context, console, prototype, "table", V8Console::tableCallback); | 
| + createBoundFunctionProperty(context, console, prototype, "trace", V8Console::traceCallback); | 
| + createBoundFunctionProperty(context, console, prototype, "group", V8Console::groupCallback); | 
| + createBoundFunctionProperty(context, console, prototype, "groupCollapsed", V8Console::groupCollapsedCallback); | 
| + createBoundFunctionProperty(context, console, prototype, "groupEnd", V8Console::groupEndCallback); | 
| + createBoundFunctionProperty(context, console, prototype, "clear", V8Console::clearCallback); | 
| + createBoundFunctionProperty(context, console, prototype, "count", V8Console::countCallback); | 
| + createBoundFunctionProperty(context, console, prototype, "assert", V8Console::assertCallback); | 
| + createBoundFunctionProperty(context, console, prototype, "markTimeline", V8Console::markTimelineCallback); | 
| + createBoundFunctionProperty(context, console, prototype, "profile", V8Console::profileCallback); | 
| + createBoundFunctionProperty(context, console, prototype, "profileEnd", V8Console::profileEndCallback); | 
| + createBoundFunctionProperty(context, console, prototype, "timeline", V8Console::timelineCallback); | 
| + createBoundFunctionProperty(context, console, prototype, "timelineEnd", V8Console::timelineEndCallback); | 
| + createBoundFunctionProperty(context, console, prototype, "time", V8Console::timeCallback); | 
| + createBoundFunctionProperty(context, console, prototype, "timeEnd", V8Console::timeEndCallback); | 
| + createBoundFunctionProperty(context, console, prototype, "timeStamp", V8Console::timeStampCallback); | 
| + | 
| + if (!console->SetPrototype(context, prototype).FromMaybe(false)) | 
| + return v8::MaybeLocal<v8::Object>(); | 
| + | 
| + if (hasMemoryAttribute) | 
| + console->SetAccessorProperty(toV8StringInternalized(isolate, "memory"), v8::Function::New(isolate, V8Console::memoryGetterCallback, console), v8::Function::New(isolate, V8Console::memorySetterCallback), static_cast<v8::PropertyAttribute>(v8::None), v8::DEFAULT); | 
| + | 
| + 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.
 
 | 
| + return console; | 
| +} | 
| + | 
| +} // namespace blink |