Commit 701d79d0 authored by Alexey Kozyatinskiy's avatar Alexey Kozyatinskiy Committed by Commit Bot

[inspector] introduced console.context

console.context(name:string) method returns console instance, this console instance fully implements console interface (including fact that any method can be called without console as receiver).
Protocol.Runtime.consoleAPICalled notification contains additional context:string field:
- "anonymous#unique-id" for any method call on unnamed console context,
- "name#unique-id" for any method call on named console context.

console.count and console.timeEnd have context as a scope.
console.clear clear all messages regardless on what context instance it was called.

console calls is ~10% slower with this CL since we need to store and then fetch console_context_id and console_context_name from function object.
We recently (in April) made console calls twice faster so 10% doesn't sound critical and existing of console.log call in hot code is problem by itself.

R=pfeldman@chromium.org

Bug: chromium:728767
Change-Id: I5fc73216fb8b28bfe1e8c2c1b393ebfbe43cd02e
Reviewed-on: https://chromium-review.googlesource.com/522128Reviewed-by: 's avatarIgor Sheludko <ishell@chromium.org>
Reviewed-by: 's avatarJakob Gruber <jgruber@chromium.org>
Reviewed-by: 's avatarDmitry Gozman <dgozman@chromium.org>
Commit-Queue: Aleksey Kozyatinskiy <kozyatinskiy@chromium.org>
Cr-Commit-Position: refs/heads/master@{#45864}
parent 33871053
...@@ -2627,6 +2627,8 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object, ...@@ -2627,6 +2627,8 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object,
false, NONE); false, NONE);
SimpleInstallFunction(console, "timeStamp", Builtins::kConsoleTimeStamp, 1, SimpleInstallFunction(console, "timeStamp", Builtins::kConsoleTimeStamp, 1,
false, NONE); false, NONE);
SimpleInstallFunction(console, "context", Builtins::kConsoleContext, 1,
true, NONE);
JSObject::AddProperty( JSObject::AddProperty(
console, factory->to_string_tag_symbol(), console, factory->to_string_tag_symbol(),
factory->NewStringFromAsciiChecked("Object"), factory->NewStringFromAsciiChecked("Object"),
......
...@@ -14,45 +14,113 @@ namespace internal { ...@@ -14,45 +14,113 @@ namespace internal {
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// Console // Console
#define CONSOLE_METHOD_LIST(V) \ #define CONSOLE_METHOD_LIST(V) \
V(Debug) \ V(Debug, debug) \
V(Error) \ V(Error, error) \
V(Info) \ V(Info, info) \
V(Log) \ V(Log, log) \
V(Warn) \ V(Warn, warn) \
V(Dir) \ V(Dir, dir) \
V(DirXml) \ V(DirXml, dirXml) \
V(Table) \ V(Table, table) \
V(Trace) \ V(Trace, trace) \
V(Group) \ V(Group, group) \
V(GroupCollapsed) \ V(GroupCollapsed, groupCollapsed) \
V(GroupEnd) \ V(GroupEnd, groupEnd) \
V(Clear) \ V(Clear, clear) \
V(Count) \ V(Count, count) \
V(Assert) \ V(Assert, assert) \
V(MarkTimeline) \ V(MarkTimeline, markTimeline) \
V(Profile) \ V(Profile, profile) \
V(ProfileEnd) \ V(ProfileEnd, profileEnd) \
V(Timeline) \ V(Timeline, timeline) \
V(TimelineEnd) \ V(TimelineEnd, timelineEnd) \
V(Time) \ V(Time, time) \
V(TimeEnd) \ V(TimeEnd, timeEnd) \
V(TimeStamp) V(TimeStamp, timeStamp)
#define CONSOLE_BUILTIN_IMPLEMENTATION(name) \ namespace {
BUILTIN(Console##name) { \ void ConsoleCall(
HandleScope scope(isolate); \ Isolate* isolate, internal::BuiltinArguments& args,
if (isolate->console_delegate()) { \ void (debug::ConsoleDelegate::*func)(const v8::debug::ConsoleCallArguments&,
debug::ConsoleCallArguments wrapper(args); \ const v8::debug::ConsoleContext&)) {
isolate->console_delegate()->name(wrapper); \ HandleScope scope(isolate);
CHECK(!isolate->has_pending_exception()); \ if (!isolate->console_delegate()) return;
CHECK(!isolate->has_scheduled_exception()); \ debug::ConsoleCallArguments wrapper(args);
} \ Handle<Object> context_id_obj = JSObject::GetDataProperty(
return isolate->heap()->undefined_value(); \ args.target(), isolate->factory()->console_context_id_symbol());
int context_id =
context_id_obj->IsSmi() ? Handle<Smi>::cast(context_id_obj)->value() : 0;
Handle<Object> context_name_obj = JSObject::GetDataProperty(
args.target(), isolate->factory()->console_context_name_symbol());
Handle<String> context_name = context_name_obj->IsString()
? Handle<String>::cast(context_name_obj)
: isolate->factory()->anonymous_string();
(isolate->console_delegate()->*func)(
wrapper,
v8::debug::ConsoleContext(context_id, Utils::ToLocal(context_name)));
CHECK(!isolate->has_pending_exception());
CHECK(!isolate->has_scheduled_exception());
}
} // namespace
#define CONSOLE_BUILTIN_IMPLEMENTATION(call, name) \
BUILTIN(Console##call) { \
ConsoleCall(isolate, args, &debug::ConsoleDelegate::call); \
return isolate->heap()->undefined_value(); \
} }
CONSOLE_METHOD_LIST(CONSOLE_BUILTIN_IMPLEMENTATION) CONSOLE_METHOD_LIST(CONSOLE_BUILTIN_IMPLEMENTATION)
#undef CONSOLE_BUILTIN_IMPLEMENTATION #undef CONSOLE_BUILTIN_IMPLEMENTATION
namespace {
void InstallContextFunction(Handle<JSObject> target, const char* name,
Builtins::Name call, int context_id,
Object* context_name) {
Factory* const factory = target->GetIsolate()->factory();
Handle<Code> call_code(target->GetIsolate()->builtins()->builtin(call));
Handle<String> name_string =
Name::ToFunctionName(factory->InternalizeUtf8String(name))
.ToHandleChecked();
Handle<JSFunction> fun =
factory->NewFunctionWithoutPrototype(name_string, call_code, false);
fun->shared()->set_native(true);
fun->shared()->DontAdaptArguments();
fun->shared()->set_length(1);
JSObject::AddProperty(fun, factory->console_context_id_symbol(),
handle(Smi::FromInt(context_id), target->GetIsolate()),
NONE);
if (context_name->IsString()) {
JSObject::AddProperty(fun, factory->console_context_name_symbol(),
handle(context_name, target->GetIsolate()), NONE);
}
JSObject::AddProperty(target, name_string, fun, NONE);
}
} // namespace
BUILTIN(ConsoleContext) {
HandleScope scope(isolate);
Factory* const factory = isolate->factory();
Handle<String> name = factory->InternalizeUtf8String("Context");
Handle<JSFunction> cons = factory->NewFunction(name);
Handle<JSObject> empty = factory->NewJSObject(isolate->object_function());
JSFunction::SetPrototype(cons, empty);
Handle<JSObject> context = factory->NewJSObject(cons, TENURED);
DCHECK(context->IsJSObject());
int id = isolate->last_console_context_id() + 1;
isolate->set_last_console_context_id(id);
#define CONSOLE_BUILTIN_SETUP(call, name) \
InstallContextFunction(context, #name, Builtins::kConsole##call, id, args[1]);
CONSOLE_METHOD_LIST(CONSOLE_BUILTIN_SETUP)
#undef CONSOLE_BUILTIN_SETUP
return *context;
}
#undef CONSOLE_METHOD_LIST #undef CONSOLE_METHOD_LIST
} // namespace internal } // namespace internal
......
...@@ -405,6 +405,7 @@ namespace internal { ...@@ -405,6 +405,7 @@ namespace internal {
CPP(ConsoleTime) \ CPP(ConsoleTime) \
CPP(ConsoleTimeEnd) \ CPP(ConsoleTimeEnd) \
CPP(ConsoleTimeStamp) \ CPP(ConsoleTimeStamp) \
CPP(ConsoleContext) \
\ \
/* DataView */ \ /* DataView */ \
CPP(DataViewConstructor) \ CPP(DataViewConstructor) \
......
...@@ -40,27 +40,33 @@ D8Console::D8Console(Isolate* isolate) : isolate_(isolate) { ...@@ -40,27 +40,33 @@ D8Console::D8Console(Isolate* isolate) : isolate_(isolate) {
default_timer_ = base::TimeTicks::HighResolutionNow(); default_timer_ = base::TimeTicks::HighResolutionNow();
} }
void D8Console::Log(const debug::ConsoleCallArguments& args) { void D8Console::Log(const debug::ConsoleCallArguments& args,
const v8::debug::ConsoleContext&) {
WriteToFile(stdout, isolate_, args); WriteToFile(stdout, isolate_, args);
} }
void D8Console::Error(const debug::ConsoleCallArguments& args) { void D8Console::Error(const debug::ConsoleCallArguments& args,
const v8::debug::ConsoleContext&) {
WriteToFile(stderr, isolate_, args); WriteToFile(stderr, isolate_, args);
} }
void D8Console::Warn(const debug::ConsoleCallArguments& args) { void D8Console::Warn(const debug::ConsoleCallArguments& args,
const v8::debug::ConsoleContext&) {
WriteToFile(stdout, isolate_, args); WriteToFile(stdout, isolate_, args);
} }
void D8Console::Info(const debug::ConsoleCallArguments& args) { void D8Console::Info(const debug::ConsoleCallArguments& args,
const v8::debug::ConsoleContext&) {
WriteToFile(stdout, isolate_, args); WriteToFile(stdout, isolate_, args);
} }
void D8Console::Debug(const debug::ConsoleCallArguments& args) { void D8Console::Debug(const debug::ConsoleCallArguments& args,
const v8::debug::ConsoleContext&) {
WriteToFile(stdout, isolate_, args); WriteToFile(stdout, isolate_, args);
} }
void D8Console::Time(const debug::ConsoleCallArguments& args) { void D8Console::Time(const debug::ConsoleCallArguments& args,
const v8::debug::ConsoleContext&) {
if (args.Length() == 0) { if (args.Length() == 0) {
default_timer_ = base::TimeTicks::HighResolutionNow(); default_timer_ = base::TimeTicks::HighResolutionNow();
} else { } else {
...@@ -83,7 +89,8 @@ void D8Console::Time(const debug::ConsoleCallArguments& args) { ...@@ -83,7 +89,8 @@ void D8Console::Time(const debug::ConsoleCallArguments& args) {
} }
} }
void D8Console::TimeEnd(const debug::ConsoleCallArguments& args) { void D8Console::TimeEnd(const debug::ConsoleCallArguments& args,
const v8::debug::ConsoleContext&) {
base::TimeDelta delta; base::TimeDelta delta;
base::TimeTicks now = base::TimeTicks::HighResolutionNow(); base::TimeTicks now = base::TimeTicks::HighResolutionNow();
if (args.Length() == 0) { if (args.Length() == 0) {
......
...@@ -16,13 +16,20 @@ class D8Console : public debug::ConsoleDelegate { ...@@ -16,13 +16,20 @@ class D8Console : public debug::ConsoleDelegate {
explicit D8Console(Isolate* isolate); explicit D8Console(Isolate* isolate);
private: private:
void Log(const debug::ConsoleCallArguments& args) override; void Log(const debug::ConsoleCallArguments& args,
void Error(const debug::ConsoleCallArguments& args) override; const v8::debug::ConsoleContext&) override;
void Warn(const debug::ConsoleCallArguments& args) override; void Error(const debug::ConsoleCallArguments& args,
void Info(const debug::ConsoleCallArguments& args) override; const v8::debug::ConsoleContext&) override;
void Debug(const debug::ConsoleCallArguments& args) override; void Warn(const debug::ConsoleCallArguments& args,
void Time(const debug::ConsoleCallArguments& args) override; const v8::debug::ConsoleContext&) override;
void TimeEnd(const debug::ConsoleCallArguments& args) override; void Info(const debug::ConsoleCallArguments& args,
const v8::debug::ConsoleContext&) override;
void Debug(const debug::ConsoleCallArguments& args,
const v8::debug::ConsoleContext&) override;
void Time(const debug::ConsoleCallArguments& args,
const v8::debug::ConsoleContext&) override;
void TimeEnd(const debug::ConsoleCallArguments& args,
const v8::debug::ConsoleContext&) override;
Isolate* isolate_; Isolate* isolate_;
std::map<std::string, base::TimeTicks> timers_; std::map<std::string, base::TimeTicks> timers_;
......
...@@ -106,33 +106,67 @@ class ConsoleCallArguments : private v8::FunctionCallbackInfo<v8::Value> { ...@@ -106,33 +106,67 @@ class ConsoleCallArguments : private v8::FunctionCallbackInfo<v8::Value> {
explicit ConsoleCallArguments(internal::BuiltinArguments&); explicit ConsoleCallArguments(internal::BuiltinArguments&);
}; };
// v8::FunctionCallbackInfo could be used for getting arguments only. Calling class ConsoleContext {
// of any other getter will produce a crash. public:
ConsoleContext(int id, v8::Local<v8::String> name) : id_(id), name_(name) {}
ConsoleContext() : id_(0) {}
int id() const { return id_; }
v8::Local<v8::String> name() const { return name_; }
private:
int id_;
v8::Local<v8::String> name_;
};
class ConsoleDelegate { class ConsoleDelegate {
public: public:
virtual void Debug(const ConsoleCallArguments& args) {} virtual void Debug(const ConsoleCallArguments& args,
virtual void Error(const ConsoleCallArguments& args) {} const ConsoleContext& context) {}
virtual void Info(const ConsoleCallArguments& args) {} virtual void Error(const ConsoleCallArguments& args,
virtual void Log(const ConsoleCallArguments& args) {} const ConsoleContext& context) {}
virtual void Warn(const ConsoleCallArguments& args) {} virtual void Info(const ConsoleCallArguments& args,
virtual void Dir(const ConsoleCallArguments& args) {} const ConsoleContext& context) {}
virtual void DirXml(const ConsoleCallArguments& args) {} virtual void Log(const ConsoleCallArguments& args,
virtual void Table(const ConsoleCallArguments& args) {} const ConsoleContext& context) {}
virtual void Trace(const ConsoleCallArguments& args) {} virtual void Warn(const ConsoleCallArguments& args,
virtual void Group(const ConsoleCallArguments& args) {} const ConsoleContext& context) {}
virtual void GroupCollapsed(const ConsoleCallArguments& args) {} virtual void Dir(const ConsoleCallArguments& args,
virtual void GroupEnd(const ConsoleCallArguments& args) {} const ConsoleContext& context) {}
virtual void Clear(const ConsoleCallArguments& args) {} virtual void DirXml(const ConsoleCallArguments& args,
virtual void Count(const ConsoleCallArguments& args) {} const ConsoleContext& context) {}
virtual void Assert(const ConsoleCallArguments& args) {} virtual void Table(const ConsoleCallArguments& args,
virtual void MarkTimeline(const ConsoleCallArguments& args) {} const ConsoleContext& context) {}
virtual void Profile(const ConsoleCallArguments& args) {} virtual void Trace(const ConsoleCallArguments& args,
virtual void ProfileEnd(const ConsoleCallArguments& args) {} const ConsoleContext& context) {}
virtual void Timeline(const ConsoleCallArguments& args) {} virtual void Group(const ConsoleCallArguments& args,
virtual void TimelineEnd(const ConsoleCallArguments& args) {} const ConsoleContext& context) {}
virtual void Time(const ConsoleCallArguments& args) {} virtual void GroupCollapsed(const ConsoleCallArguments& args,
virtual void TimeEnd(const ConsoleCallArguments& args) {} const ConsoleContext& context) {}
virtual void TimeStamp(const ConsoleCallArguments& args) {} virtual void GroupEnd(const ConsoleCallArguments& args,
const ConsoleContext& context) {}
virtual void Clear(const ConsoleCallArguments& args,
const ConsoleContext& context) {}
virtual void Count(const ConsoleCallArguments& args,
const ConsoleContext& context) {}
virtual void Assert(const ConsoleCallArguments& args,
const ConsoleContext& context) {}
virtual void MarkTimeline(const ConsoleCallArguments& args,
const ConsoleContext& context) {}
virtual void Profile(const ConsoleCallArguments& args,
const ConsoleContext& context) {}
virtual void ProfileEnd(const ConsoleCallArguments& args,
const ConsoleContext& context) {}
virtual void Timeline(const ConsoleCallArguments& args,
const ConsoleContext& context) {}
virtual void TimelineEnd(const ConsoleCallArguments& args,
const ConsoleContext& context) {}
virtual void Time(const ConsoleCallArguments& args,
const ConsoleContext& context) {}
virtual void TimeEnd(const ConsoleCallArguments& args,
const ConsoleContext& context) {}
virtual void TimeStamp(const ConsoleCallArguments& args,
const ConsoleContext& context) {}
virtual ~ConsoleDelegate() = default; virtual ~ConsoleDelegate() = default;
}; };
......
...@@ -201,6 +201,8 @@ ...@@ -201,6 +201,8 @@
V(array_iterator_object_symbol) \ V(array_iterator_object_symbol) \
V(call_site_frame_array_symbol) \ V(call_site_frame_array_symbol) \
V(call_site_frame_index_symbol) \ V(call_site_frame_index_symbol) \
V(console_context_id_symbol) \
V(console_context_name_symbol) \
V(class_end_position_symbol) \ V(class_end_position_symbol) \
V(class_start_position_symbol) \ V(class_start_position_symbol) \
V(detailed_stack_trace_symbol) \ V(detailed_stack_trace_symbol) \
......
...@@ -388,7 +388,8 @@ ...@@ -388,7 +388,8 @@
{ "name": "args", "type": "array", "items": { "$ref": "RemoteObject" }, "description": "Call arguments." }, { "name": "args", "type": "array", "items": { "$ref": "RemoteObject" }, "description": "Call arguments." },
{ "name": "executionContextId", "$ref": "ExecutionContextId", "description": "Identifier of the context where the call was made." }, { "name": "executionContextId", "$ref": "ExecutionContextId", "description": "Identifier of the context where the call was made." },
{ "name": "timestamp", "$ref": "Timestamp", "description": "Call timestamp." }, { "name": "timestamp", "$ref": "Timestamp", "description": "Call timestamp." },
{ "name": "stackTrace", "$ref": "StackTrace", "optional": true, "description": "Stack trace captured when the call was made." } { "name": "stackTrace", "$ref": "StackTrace", "optional": true, "description": "Stack trace captured when the call was made." },
{ "name": "context", "type": "string", "optional": true, "experimental": true, "description": "Console context descriptor for calls on non-default console context (not console.*): 'anonymous#unique-logger-id' for call on unnamed context, 'name#unique-logger-id' for call on named context." }
] ]
}, },
{ {
......
...@@ -321,10 +321,13 @@ void V8ConsoleMessage::reportToFrontend(protocol::Runtime::Frontend* frontend, ...@@ -321,10 +321,13 @@ void V8ConsoleMessage::reportToFrontend(protocol::Runtime::Frontend* frontend,
arguments->addItem(std::move(messageArg)); arguments->addItem(std::move(messageArg));
} }
} }
Maybe<String16> consoleContext;
if (!m_consoleContext.isEmpty()) consoleContext = m_consoleContext;
frontend->consoleAPICalled( frontend->consoleAPICalled(
consoleAPITypeValue(m_type), std::move(arguments), m_contextId, consoleAPITypeValue(m_type), std::move(arguments), m_contextId,
m_timestamp, m_timestamp,
m_stackTrace ? m_stackTrace->buildInspectorObjectImpl() : nullptr); m_stackTrace ? m_stackTrace->buildInspectorObjectImpl() : nullptr,
std::move(consoleContext));
return; return;
} }
UNREACHABLE(); UNREACHABLE();
...@@ -356,6 +359,7 @@ std::unique_ptr<V8ConsoleMessage> V8ConsoleMessage::createForConsoleAPI( ...@@ -356,6 +359,7 @@ std::unique_ptr<V8ConsoleMessage> V8ConsoleMessage::createForConsoleAPI(
v8::Local<v8::Context> v8Context, int contextId, int groupId, v8::Local<v8::Context> v8Context, int contextId, int groupId,
V8InspectorImpl* inspector, double timestamp, ConsoleAPIType type, V8InspectorImpl* inspector, double timestamp, ConsoleAPIType type,
const std::vector<v8::Local<v8::Value>>& arguments, const std::vector<v8::Local<v8::Value>>& arguments,
const String16& consoleContext,
std::unique_ptr<V8StackTraceImpl> stackTrace) { std::unique_ptr<V8StackTraceImpl> stackTrace) {
v8::Isolate* isolate = v8Context->GetIsolate(); v8::Isolate* isolate = v8Context->GetIsolate();
...@@ -367,6 +371,7 @@ std::unique_ptr<V8ConsoleMessage> V8ConsoleMessage::createForConsoleAPI( ...@@ -367,6 +371,7 @@ std::unique_ptr<V8ConsoleMessage> V8ConsoleMessage::createForConsoleAPI(
message->m_columnNumber = stackTrace->topColumnNumber(); message->m_columnNumber = stackTrace->topColumnNumber();
} }
message->m_stackTrace = std::move(stackTrace); message->m_stackTrace = std::move(stackTrace);
message->m_consoleContext = consoleContext;
message->m_type = type; message->m_type = type;
message->m_contextId = contextId; message->m_contextId = contextId;
for (size_t i = 0; i < arguments.size(); ++i) { for (size_t i = 0; i < arguments.size(); ++i) {
......
...@@ -49,7 +49,7 @@ class V8ConsoleMessage { ...@@ -49,7 +49,7 @@ class V8ConsoleMessage {
v8::Local<v8::Context> v8Context, int contextId, int groupId, v8::Local<v8::Context> v8Context, int contextId, int groupId,
V8InspectorImpl* inspector, double timestamp, ConsoleAPIType, V8InspectorImpl* inspector, double timestamp, ConsoleAPIType,
const std::vector<v8::Local<v8::Value>>& arguments, const std::vector<v8::Local<v8::Value>>& arguments,
std::unique_ptr<V8StackTraceImpl>); const String16& consoleContext, std::unique_ptr<V8StackTraceImpl>);
static std::unique_ptr<V8ConsoleMessage> createForException( static std::unique_ptr<V8ConsoleMessage> createForException(
double timestamp, const String16& detailedMessage, const String16& url, double timestamp, const String16& detailedMessage, const String16& url,
...@@ -99,6 +99,7 @@ class V8ConsoleMessage { ...@@ -99,6 +99,7 @@ class V8ConsoleMessage {
int m_v8Size = 0; int m_v8Size = 0;
Arguments m_arguments; Arguments m_arguments;
String16 m_detailedMessage; String16 m_detailedMessage;
String16 m_consoleContext;
}; };
class V8ConsoleMessageStorage { class V8ConsoleMessageStorage {
......
This diff is collapsed.
...@@ -50,29 +50,52 @@ class V8Console : public v8::debug::ConsoleDelegate { ...@@ -50,29 +50,52 @@ class V8Console : public v8::debug::ConsoleDelegate {
explicit V8Console(V8InspectorImpl* inspector); explicit V8Console(V8InspectorImpl* inspector);
private: private:
void Debug(const v8::debug::ConsoleCallArguments&) override; void Debug(const v8::debug::ConsoleCallArguments&,
void Error(const v8::debug::ConsoleCallArguments&) override; const v8::debug::ConsoleContext& consoleContext) override;
void Info(const v8::debug::ConsoleCallArguments&) override; void Error(const v8::debug::ConsoleCallArguments&,
void Log(const v8::debug::ConsoleCallArguments&) override; const v8::debug::ConsoleContext& consoleContext) override;
void Warn(const v8::debug::ConsoleCallArguments&) override; void Info(const v8::debug::ConsoleCallArguments&,
void Dir(const v8::debug::ConsoleCallArguments&) override; const v8::debug::ConsoleContext& consoleContext) override;
void DirXml(const v8::debug::ConsoleCallArguments&) override; void Log(const v8::debug::ConsoleCallArguments&,
void Table(const v8::debug::ConsoleCallArguments&) override; const v8::debug::ConsoleContext& consoleContext) override;
void Trace(const v8::debug::ConsoleCallArguments&) override; void Warn(const v8::debug::ConsoleCallArguments&,
void Group(const v8::debug::ConsoleCallArguments&) override; const v8::debug::ConsoleContext& consoleContext) override;
void GroupCollapsed(const v8::debug::ConsoleCallArguments&) override; void Dir(const v8::debug::ConsoleCallArguments&,
void GroupEnd(const v8::debug::ConsoleCallArguments&) override; const v8::debug::ConsoleContext& consoleContext) override;
void Clear(const v8::debug::ConsoleCallArguments&) override; void DirXml(const v8::debug::ConsoleCallArguments&,
void Count(const v8::debug::ConsoleCallArguments&) override; const v8::debug::ConsoleContext& consoleContext) override;
void Assert(const v8::debug::ConsoleCallArguments&) override; void Table(const v8::debug::ConsoleCallArguments&,
void MarkTimeline(const v8::debug::ConsoleCallArguments&) override; const v8::debug::ConsoleContext& consoleContext) override;
void Profile(const v8::debug::ConsoleCallArguments&) override; void Trace(const v8::debug::ConsoleCallArguments&,
void ProfileEnd(const v8::debug::ConsoleCallArguments&) override; const v8::debug::ConsoleContext& consoleContext) override;
void Timeline(const v8::debug::ConsoleCallArguments&) override; void Group(const v8::debug::ConsoleCallArguments&,
void TimelineEnd(const v8::debug::ConsoleCallArguments&) override; const v8::debug::ConsoleContext& consoleContext) override;
void Time(const v8::debug::ConsoleCallArguments&) override; void GroupCollapsed(const v8::debug::ConsoleCallArguments&,
void TimeEnd(const v8::debug::ConsoleCallArguments&) override; const v8::debug::ConsoleContext& consoleContext) override;
void TimeStamp(const v8::debug::ConsoleCallArguments&) override; void GroupEnd(const v8::debug::ConsoleCallArguments&,
const v8::debug::ConsoleContext& consoleContext) override;
void Clear(const v8::debug::ConsoleCallArguments&,
const v8::debug::ConsoleContext& consoleContext) override;
void Count(const v8::debug::ConsoleCallArguments&,
const v8::debug::ConsoleContext& consoleContext) override;
void Assert(const v8::debug::ConsoleCallArguments&,
const v8::debug::ConsoleContext& consoleContext) override;
void MarkTimeline(const v8::debug::ConsoleCallArguments&,
const v8::debug::ConsoleContext& consoleContext) override;
void Profile(const v8::debug::ConsoleCallArguments&,
const v8::debug::ConsoleContext& consoleContext) override;
void ProfileEnd(const v8::debug::ConsoleCallArguments&,
const v8::debug::ConsoleContext& consoleContext) override;
void Timeline(const v8::debug::ConsoleCallArguments&,
const v8::debug::ConsoleContext& consoleContext) override;
void TimelineEnd(const v8::debug::ConsoleCallArguments&,
const v8::debug::ConsoleContext& consoleContext) override;
void Time(const v8::debug::ConsoleCallArguments&,
const v8::debug::ConsoleContext& consoleContext) override;
void TimeEnd(const v8::debug::ConsoleCallArguments&,
const v8::debug::ConsoleContext& consoleContext) override;
void TimeStamp(const v8::debug::ConsoleCallArguments&,
const v8::debug::ConsoleContext& consoleContext) override;
template <void (V8Console::*func)(const v8::FunctionCallbackInfo<v8::Value>&)> template <void (V8Console::*func)(const v8::FunctionCallbackInfo<v8::Value>&)>
static void call(const v8::FunctionCallbackInfo<v8::Value>& info) { static void call(const v8::FunctionCallbackInfo<v8::Value>& info) {
...@@ -88,12 +111,13 @@ class V8Console : public v8::debug::ConsoleDelegate { ...@@ -88,12 +111,13 @@ class V8Console : public v8::debug::ConsoleDelegate {
info.Data().As<v8::External>()->Value()); info.Data().As<v8::External>()->Value());
(data->first->*func)(info, data->second); (data->first->*func)(info, data->second);
} }
template <void (V8Console::*func)(const v8::debug::ConsoleCallArguments&)> template <void (V8Console::*func)(const v8::debug::ConsoleCallArguments&,
const v8::debug::ConsoleContext&)>
static void call(const v8::FunctionCallbackInfo<v8::Value>& info) { static void call(const v8::FunctionCallbackInfo<v8::Value>& info) {
CommandLineAPIData* data = static_cast<CommandLineAPIData*>( CommandLineAPIData* data = static_cast<CommandLineAPIData*>(
info.Data().As<v8::External>()->Value()); info.Data().As<v8::External>()->Value());
v8::debug::ConsoleCallArguments args(info); v8::debug::ConsoleCallArguments args(info);
(data->first->*func)(args); (data->first->*func)(args, v8::debug::ConsoleContext());
} }
// TODO(foolip): There is no spec for the Memory Info API, see blink-dev: // TODO(foolip): There is no spec for the Memory Info API, see blink-dev:
......
...@@ -439,6 +439,7 @@ typedef std::vector<HeapObject*> DebugObjectCache; ...@@ -439,6 +439,7 @@ typedef std::vector<HeapObject*> DebugObjectCache;
/* Current code coverage mode */ \ /* Current code coverage mode */ \
V(debug::Coverage::Mode, code_coverage_mode, debug::Coverage::kBestEffort) \ V(debug::Coverage::Mode, code_coverage_mode, debug::Coverage::kBestEffort) \
V(int, last_stack_frame_info_id, 0) \ V(int, last_stack_frame_info_id, 0) \
V(int, last_console_context_id, 0) \
ISOLATE_INIT_SIMULATOR_LIST(V) ISOLATE_INIT_SIMULATOR_LIST(V)
#define THREAD_LOCAL_TOP_ACCESSOR(type, name) \ #define THREAD_LOCAL_TOP_ACCESSOR(type, name) \
......
Tests console.context
Running test: testConsoleContextMethod
console.context description:
{
className : Function
description : function context() { [native code] }
objectId : <objectId>
type : function
}
console.context() methods:
[
[0] : debug
[1] : error
[2] : info
[3] : log
[4] : warn
[5] : dir
[6] : dirXml
[7] : table
[8] : trace
[9] : group
[10] : groupCollapsed
[11] : groupEnd
[12] : clear
[13] : count
[14] : assert
[15] : markTimeline
[16] : profile
[17] : profileEnd
[18] : timeline
[19] : timelineEnd
[20] : time
[21] : timeEnd
[22] : timeStamp
]
Running test: testDefaultConsoleContext
undefined
undefined
undefined
Running test: testAnonymousConsoleContext
anonymous#2
anonymous#3
anonymous#4
Running test: testNamedConsoleContext
named-context#6
named-context#6
named-context#6
Running test: testTwoConsoleContextsWithTheSameName
named-context#7
named-context#8
Running test: testConsoleCountInDifferentConsoleContexts
[
[0] : {
type : string
value : 239: 1
}
]
[
[0] : {
type : string
value : 239: 1
}
]
Running test: testConsoleCountForNamedConsoleContext
[
[0] : {
type : string
value : 239: 1
}
]
[
[0] : {
type : string
value : 239: 2
}
]
// Copyright 2017 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
let {session, contextGroup, Protocol} = InspectorTest.start('Tests console.context');
InspectorTest.runAsyncTestSuite([
async function testConsoleContextMethod() {
InspectorTest.log('console.context description:');
var {result:{result}} = await Protocol.Runtime.evaluate({
expression: 'console.context'});
InspectorTest.logMessage(result);
InspectorTest.log('console.context() methods:');
var {result:{result:{value}}} = await Protocol.Runtime.evaluate({
expression: 'Object.keys(console.context())', returnByValue: true});
InspectorTest.logMessage(value);
},
async function testDefaultConsoleContext() {
await Protocol.Runtime.enable();
Protocol.Runtime.evaluate({expression: 'console.log(239)'});
var {params:{context}} = await Protocol.Runtime.onceConsoleAPICalled();
InspectorTest.log(context);
Protocol.Runtime.evaluate({expression: 'console.info(239)'});
var {params:{context}} = await Protocol.Runtime.onceConsoleAPICalled();
InspectorTest.log(context);
Protocol.Runtime.evaluate({expression: 'console.debug(239)'});
var {params:{context}} = await Protocol.Runtime.onceConsoleAPICalled();
InspectorTest.log(context);
await Protocol.Runtime.evaluate({expression: 'console.clear()'});
await Protocol.Runtime.disable();
},
async function testAnonymousConsoleContext() {
await Protocol.Runtime.enable();
Protocol.Runtime.evaluate({expression: 'console.context().log(239)'});
var {params:{context}} = await Protocol.Runtime.onceConsoleAPICalled();
InspectorTest.log(context);
Protocol.Runtime.evaluate({expression: 'console.context().info(239)'});
var {params:{context}} = await Protocol.Runtime.onceConsoleAPICalled();
InspectorTest.log(context);
Protocol.Runtime.evaluate({expression: 'console.context().debug(239)'});
var {params:{context}} = await Protocol.Runtime.onceConsoleAPICalled();
InspectorTest.log(context);
await Protocol.Runtime.evaluate({expression: 'console.context().clear()'});
await Protocol.Runtime.disable();
},
async function testNamedConsoleContext() {
await Protocol.Runtime.enable();
Protocol.Runtime.evaluate({expression: `
var context = console.context('named-context');
context.log(239);
context.info(239);
context.debug(239);
`});
var {params:{context}} = await Protocol.Runtime.onceConsoleAPICalled();
InspectorTest.log(context);
var {params:{context}} = await Protocol.Runtime.onceConsoleAPICalled();
InspectorTest.log(context);
var {params:{context}} = await Protocol.Runtime.onceConsoleAPICalled();
InspectorTest.log(context);
await Protocol.Runtime.evaluate({expression: 'console.clear()'});
await Protocol.Runtime.disable();
},
async function testTwoConsoleContextsWithTheSameName() {
await Protocol.Runtime.enable();
Protocol.Runtime.evaluate({expression: 'console.context(\'named-context\').log(239)'});
var {params:{context}} = await Protocol.Runtime.onceConsoleAPICalled();
InspectorTest.log(context);
Protocol.Runtime.evaluate({expression: 'console.context(\'named-context\').log(239)'});
var {params:{context}} = await Protocol.Runtime.onceConsoleAPICalled();
InspectorTest.log(context);
await Protocol.Runtime.evaluate({expression: 'console.clear()'});
await Protocol.Runtime.disable();
},
async function testConsoleCountInDifferentConsoleContexts() {
await Protocol.Runtime.enable();
Protocol.Runtime.evaluate({expression: 'console.context(\'named-context\').count(239)'});
var {params:{args}} = await Protocol.Runtime.onceConsoleAPICalled();
InspectorTest.logMessage(args);
Protocol.Runtime.evaluate({expression: 'console.context(\'named-context\').count(239)'});
var {params:{args}} = await Protocol.Runtime.onceConsoleAPICalled();
InspectorTest.logMessage(args);
await Protocol.Runtime.evaluate({expression: 'console.clear()'});
await Protocol.Runtime.disable();
},
async function testConsoleCountForNamedConsoleContext() {
await Protocol.Runtime.enable();
Protocol.Runtime.evaluate({expression: `
var context = console.context('named-context');
context.count(239);
context.count(239);
`});
var {params:{args}} = await Protocol.Runtime.onceConsoleAPICalled();
InspectorTest.logMessage(args);
var {params:{args}} = await Protocol.Runtime.onceConsoleAPICalled();
InspectorTest.logMessage(args);
await Protocol.Runtime.evaluate({expression: 'console.clear()'});
await Protocol.Runtime.disable();
}
]);
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment