Commit 3ab26277 authored by kozyatinskiy's avatar kozyatinskiy Committed by Commit bot

[inspector] console get all information from inspector when needed

With this CL we don't need to store reference to InspectedContext inside of JavaScript console object and able to get all required information from callback data.
It allows us to implement console methods without taking in account how and where we create and store these methods:
- later we can move console object implementation to builtins..
- ..and install command line API methods smarter.

BUG=chromium:588893
R=dgozman@chromium.org

Review-Url: https://codereview.chromium.org/2784713002
Cr-Original-Original-Commit-Position: refs/heads/master@{#44212}
Committed: https://chromium.googlesource.com/v8/v8/+/908cd38123df33ce293e4c8d25e407f7ca915f4c
Review-Url: https://codereview.chromium.org/2784713002
Cr-Original-Commit-Position: refs/heads/master@{#44238}
Committed: https://chromium.googlesource.com/v8/v8/+/88f71126a5c067f98c75044bc26778f2e8ea2e79
Review-Url: https://codereview.chromium.org/2784713002
Cr-Commit-Position: refs/heads/master@{#44251}
parent f2531acb
......@@ -14,23 +14,6 @@
namespace v8_inspector {
namespace {
void clearContext(const v8::WeakCallbackInfo<v8::Global<v8::Context>>& data) {
// Inspected context is created in V8InspectorImpl::contextCreated method
// and destroyed in V8InspectorImpl::contextDestroyed.
// Both methods takes valid v8::Local<v8::Context> handle to the same context,
// it means that context is created before InspectedContext constructor and is
// always destroyed after InspectedContext destructor therefore this callback
// should be never called.
// It's possible only if inspector client doesn't call contextDestroyed which
// is considered an error.
CHECK(false);
data.GetParameter()->Reset();
}
} // namespace
InspectedContext::InspectedContext(V8InspectorImpl* inspector,
const V8ContextInfo& info, int contextId)
: m_inspector(inspector),
......@@ -44,27 +27,18 @@ InspectedContext::InspectedContext(V8InspectorImpl* inspector,
v8::Isolate* isolate = m_inspector->isolate();
info.context->SetEmbedderData(static_cast<int>(v8::Context::kDebugIdIndex),
v8::Int32::New(isolate, contextId));
m_context.SetWeak(&m_context, &clearContext,
v8::WeakCallbackType::kParameter);
v8::Local<v8::Object> global = info.context->Global();
v8::Local<v8::Object> console =
V8Console::createConsole(this, info.hasMemoryOnConsole);
if (!global
->Set(info.context, toV8StringInternalized(isolate, "console"),
console)
.FromMaybe(false))
.FromMaybe(false)) {
return;
m_console.Reset(isolate, console);
m_console.SetWeak();
}
}
InspectedContext::~InspectedContext() {
if (!m_console.IsEmpty()) {
v8::HandleScope scope(isolate());
V8Console::clearInspectedContextIfNeeded(context(),
m_console.Get(isolate()));
}
}
// static
......
......@@ -53,7 +53,6 @@ class InspectedContext {
const String16 m_auxData;
bool m_reported;
std::unique_ptr<InjectedScript> m_injectedScript;
v8::Global<v8::Object> m_console;
DISALLOW_COPY_AND_ASSIGN(InspectedContext);
};
......
......@@ -353,15 +353,11 @@ ConsoleAPIType V8ConsoleMessage::type() const { return m_type; }
// static
std::unique_ptr<V8ConsoleMessage> V8ConsoleMessage::createForConsoleAPI(
double timestamp, ConsoleAPIType type,
v8::Local<v8::Context> v8Context, int contextId, int groupId,
V8InspectorImpl* inspector, double timestamp, ConsoleAPIType type,
const std::vector<v8::Local<v8::Value>>& arguments,
std::unique_ptr<V8StackTraceImpl> stackTrace,
InspectedContext* inspectedContext) {
v8::Isolate* isolate = inspectedContext->isolate();
int contextId = inspectedContext->contextId();
int contextGroupId = inspectedContext->contextGroupId();
V8InspectorImpl* inspector = inspectedContext->inspector();
v8::Local<v8::Context> context = inspectedContext->context();
std::unique_ptr<V8StackTraceImpl> stackTrace) {
v8::Isolate* isolate = v8Context->GetIsolate();
std::unique_ptr<V8ConsoleMessage> message(
new V8ConsoleMessage(V8MessageOrigin::kConsole, timestamp, String16()));
......@@ -380,7 +376,8 @@ std::unique_ptr<V8ConsoleMessage> V8ConsoleMessage::createForConsoleAPI(
v8::debug::EstimatedValueSize(isolate, arguments.at(i));
}
if (arguments.size())
message->m_message = V8ValueStringBuilder::toString(arguments[0], context);
message->m_message =
V8ValueStringBuilder::toString(arguments[0], v8Context);
v8::Isolate::MessageErrorLevel clientLevel = v8::Isolate::kMessageInfo;
if (type == ConsoleAPIType::kDebug || type == ConsoleAPIType::kCount ||
......@@ -397,7 +394,7 @@ std::unique_ptr<V8ConsoleMessage> V8ConsoleMessage::createForConsoleAPI(
if (type != ConsoleAPIType::kClear) {
inspector->client()->consoleAPIMessage(
contextGroupId, clientLevel, toStringView(message->m_message),
groupId, clientLevel, toStringView(message->m_message),
toStringView(message->m_url), message->m_lineNumber,
message->m_columnNumber, message->m_stackTrace.get());
}
......@@ -490,8 +487,37 @@ void V8ConsoleMessageStorage::clear() {
m_messages.clear();
m_estimatedSize = 0;
if (V8InspectorSessionImpl* session =
m_inspector->sessionForContextGroup(m_contextGroupId))
m_inspector->sessionForContextGroup(m_contextGroupId)) {
session->releaseObjectGroup("console");
}
m_data.clear();
}
bool V8ConsoleMessageStorage::shouldReportDeprecationMessage(
int contextId, const String16& method) {
std::set<String16>& reportedDeprecationMessages =
m_data[contextId].m_reportedDeprecationMessages;
auto it = reportedDeprecationMessages.find(method);
if (it != reportedDeprecationMessages.end()) return false;
reportedDeprecationMessages.insert(it, method);
return true;
}
int V8ConsoleMessageStorage::count(int contextId, const String16& id) {
return ++m_data[contextId].m_count[id];
}
void V8ConsoleMessageStorage::time(int contextId, const String16& id) {
m_data[contextId].m_time[id] = m_inspector->client()->currentTimeMS();
}
double V8ConsoleMessageStorage::timeEnd(int contextId, const String16& id) {
std::map<String16, double>& time = m_data[contextId].m_time;
auto it = time.find(id);
if (it == time.end()) return 0.0;
double elapsed = m_inspector->client()->currentTimeMS() - it->second;
time.erase(it);
return elapsed;
}
void V8ConsoleMessageStorage::contextDestroyed(int contextId) {
......@@ -500,6 +526,8 @@ void V8ConsoleMessageStorage::contextDestroyed(int contextId) {
m_messages[i]->contextDestroyed(contextId);
m_estimatedSize += m_messages[i]->estimatedSize();
}
auto it = m_data.find(contextId);
if (it != m_data.end()) m_data.erase(contextId);
}
} // namespace v8_inspector
......@@ -6,6 +6,8 @@
#define V8_INSPECTOR_V8CONSOLEMESSAGE_H_
#include <deque>
#include <map>
#include <set>
#include "include/v8.h"
#include "src/inspector/protocol/Console.h"
#include "src/inspector/protocol/Forward.h"
......@@ -44,9 +46,10 @@ class V8ConsoleMessage {
~V8ConsoleMessage();
static std::unique_ptr<V8ConsoleMessage> createForConsoleAPI(
double timestamp, ConsoleAPIType,
v8::Local<v8::Context> v8Context, int contextId, int groupId,
V8InspectorImpl* inspector, double timestamp, ConsoleAPIType,
const std::vector<v8::Local<v8::Value>>& arguments,
std::unique_ptr<V8StackTraceImpl>, InspectedContext*);
std::unique_ptr<V8StackTraceImpl>);
static std::unique_ptr<V8ConsoleMessage> createForException(
double timestamp, const String16& detailedMessage, const String16& url,
......@@ -112,11 +115,23 @@ class V8ConsoleMessageStorage {
void contextDestroyed(int contextId);
void clear();
bool shouldReportDeprecationMessage(int contextId, const String16& method);
int count(int contextId, const String16& id);
void time(int contextId, const String16& id);
double timeEnd(int contextId, const String16& id);
private:
V8InspectorImpl* m_inspector;
int m_contextGroupId;
int m_estimatedSize = 0;
std::deque<std::unique_ptr<V8ConsoleMessage>> m_messages;
struct PerContextData {
std::set<String16> m_reportedDeprecationMessages;
std::map<String16, int> m_count;
std::map<String16, double> m_time;
};
std::map<int, PerContextData> m_data;
};
} // namespace v8_inspector
......
......@@ -23,49 +23,31 @@ namespace v8_inspector {
namespace {
v8::Local<v8::Private> inspectedContextPrivateKey(v8::Isolate* isolate) {
return v8::Private::ForApi(
isolate, toV8StringInternalized(isolate, "V8Console#InspectedContext"));
}
class ConsoleHelper {
public:
explicit ConsoleHelper(const v8::FunctionCallbackInfo<v8::Value>& info)
: m_info(info),
m_isolate(info.GetIsolate()),
m_context(info.GetIsolate()->GetCurrentContext()),
m_inspectedContext(nullptr),
m_inspectorClient(nullptr) {}
v8::Local<v8::Object> ensureConsole() {
if (m_console.IsEmpty()) {
DCHECK(!m_info.Data().IsEmpty());
DCHECK(!m_info.Data()->IsUndefined());
m_console = m_info.Data().As<v8::Object>();
}
return m_console;
m_contextId(InspectedContext::contextId(m_context)) {
m_inspector = static_cast<V8InspectorImpl*>(
m_info.Data().As<v8::External>()->Value());
m_groupId = m_inspector->contextGroupId(m_contextId);
}
InspectedContext* ensureInspectedContext() {
if (m_inspectedContext) return m_inspectedContext;
v8::Local<v8::Object> console = ensureConsole();
v8::Local<v8::Private> key = inspectedContextPrivateKey(m_isolate);
v8::Local<v8::Value> inspectedContextValue;
if (!console->GetPrivate(m_context, key).ToLocal(&inspectedContextValue))
return nullptr;
DCHECK(inspectedContextValue->IsExternal());
m_inspectedContext = static_cast<InspectedContext*>(
inspectedContextValue.As<v8::External>()->Value());
return m_inspectedContext;
V8InspectorImpl* inspector() { return m_inspector; }
int contextId() const { return m_contextId; }
int groupId() const { return m_groupId; }
InjectedScript* injectedScript() {
InspectedContext* context = m_inspector->getContext(m_groupId, m_contextId);
if (!context) return nullptr;
return context->getInjectedScript();
}
V8InspectorClient* ensureDebuggerClient() {
if (m_inspectorClient) return m_inspectorClient;
InspectedContext* inspectedContext = ensureInspectedContext();
if (!inspectedContext) return nullptr;
m_inspectorClient = inspectedContext->inspector()->client();
return m_inspectorClient;
V8ConsoleMessageStorage* consoleMessageStorage() {
return inspector()->ensureConsoleMessageStorage(m_groupId);
}
void reportCall(ConsoleAPIType type) {
......@@ -91,20 +73,20 @@ class ConsoleHelper {
void reportCall(ConsoleAPIType type,
const std::vector<v8::Local<v8::Value>>& arguments) {
InspectedContext* inspectedContext = ensureInspectedContext();
if (!inspectedContext) return;
int contextGroupId = inspectedContext->contextGroupId();
V8InspectorImpl* inspector = inspectedContext->inspector();
if (!m_groupId) return;
std::unique_ptr<V8ConsoleMessage> message =
V8ConsoleMessage::createForConsoleAPI(
inspector->client()->currentTimeMS(), type, arguments,
inspector->debugger()->captureStackTrace(false), inspectedContext);
inspector->ensureConsoleMessageStorage(contextGroupId)
->addMessage(std::move(message));
m_context, m_contextId, m_groupId, m_inspector,
m_inspector->client()->currentTimeMS(), type, arguments,
m_inspector->debugger()->captureStackTrace(false));
consoleMessageStorage()->addMessage(std::move(message));
}
void reportDeprecatedCall(const char* id, const String16& message) {
if (checkAndSetPrivateFlagOnConsole(id, false)) return;
if (!consoleMessageStorage()->shouldReportDeprecationMessage(m_contextId,
id)) {
return;
}
std::vector<v8::Local<v8::Value>> arguments(1,
toV8String(m_isolate, message));
reportCall(ConsoleAPIType::kWarning, arguments);
......@@ -145,56 +127,6 @@ class ConsoleHelper {
return func;
}
v8::MaybeLocal<v8::Map> privateMap(const char* name) {
v8::Local<v8::Object> console = ensureConsole();
v8::Local<v8::Private> privateKey =
v8::Private::ForApi(m_isolate, toV8StringInternalized(m_isolate, name));
v8::Local<v8::Value> mapValue;
if (!console->GetPrivate(m_context, privateKey).ToLocal(&mapValue))
return v8::MaybeLocal<v8::Map>();
if (mapValue->IsUndefined()) {
v8::Local<v8::Map> map = v8::Map::New(m_isolate);
if (!console->SetPrivate(m_context, privateKey, map).FromMaybe(false))
return v8::MaybeLocal<v8::Map>();
return map;
}
return mapValue->IsMap() ? mapValue.As<v8::Map>()
: v8::MaybeLocal<v8::Map>();
}
int32_t getIntFromMap(v8::Local<v8::Map> map, const String16& key,
int32_t defaultValue) {
v8::Local<v8::String> v8Key = toV8String(m_isolate, key);
if (!map->Has(m_context, v8Key).FromMaybe(false)) return defaultValue;
v8::Local<v8::Value> intValue;
if (!map->Get(m_context, v8Key).ToLocal(&intValue)) return defaultValue;
return static_cast<int32_t>(intValue.As<v8::Integer>()->Value());
}
void setIntOnMap(v8::Local<v8::Map> map, const String16& key, int32_t value) {
v8::Local<v8::String> v8Key = toV8String(m_isolate, key);
if (!map->Set(m_context, v8Key, v8::Integer::New(m_isolate, value))
.ToLocal(&map))
return;
}
double getDoubleFromMap(v8::Local<v8::Map> map, const String16& key,
double defaultValue) {
v8::Local<v8::String> v8Key = toV8String(m_isolate, key);
if (!map->Has(m_context, v8Key).FromMaybe(false)) return defaultValue;
v8::Local<v8::Value> intValue;
if (!map->Get(m_context, v8Key).ToLocal(&intValue)) return defaultValue;
return intValue.As<v8::Number>()->Value();
}
void setDoubleOnMap(v8::Local<v8::Map> map, const String16& key,
double value) {
v8::Local<v8::String> v8Key = toV8String(m_isolate, key);
if (!map->Set(m_context, v8Key, v8::Number::New(m_isolate, value))
.ToLocal(&map))
return;
}
V8ProfilerAgentImpl* profilerAgent() {
if (V8InspectorSessionImpl* session = currentSession()) {
if (session && session->profilerAgent()->enabled())
......@@ -212,10 +144,7 @@ class ConsoleHelper {
}
V8InspectorSessionImpl* currentSession() {
InspectedContext* inspectedContext = ensureInspectedContext();
if (!inspectedContext) return nullptr;
return inspectedContext->inspector()->sessionForContextGroup(
inspectedContext->contextGroupId());
return m_inspector->sessionForContextGroup(m_groupId);
}
private:
......@@ -223,26 +152,9 @@ class ConsoleHelper {
v8::Isolate* m_isolate;
v8::Local<v8::Context> m_context;
v8::Local<v8::Object> m_console;
InspectedContext* m_inspectedContext;
V8InspectorClient* m_inspectorClient;
bool checkAndSetPrivateFlagOnConsole(const char* name, bool defaultValue) {
v8::Local<v8::Object> console = ensureConsole();
v8::Local<v8::Private> key =
v8::Private::ForApi(m_isolate, toV8StringInternalized(m_isolate, name));
v8::Local<v8::Value> flagValue;
if (!console->GetPrivate(m_context, key).ToLocal(&flagValue))
return defaultValue;
DCHECK(flagValue->IsUndefined() || flagValue->IsBoolean());
if (flagValue->IsBoolean()) {
DCHECK(flagValue.As<v8::Boolean>()->Value());
return true;
}
if (!console->SetPrivate(m_context, key, v8::True(m_isolate))
.FromMaybe(false))
return defaultValue;
return false;
}
V8InspectorImpl* m_inspector = nullptr;
int m_contextId;
int m_groupId;
DISALLOW_COPY_AND_ASSIGN(ConsoleHelper);
};
......@@ -253,13 +165,13 @@ void returnDataCallback(const v8::FunctionCallbackInfo<v8::Value>& info) {
void createBoundFunctionProperty(v8::Local<v8::Context> context,
v8::Local<v8::Object> console,
const char* name,
v8::Local<v8::Value> data, const char* name,
v8::FunctionCallback callback,
const char* description = nullptr) {
v8::Local<v8::String> funcName =
toV8StringInternalized(context->GetIsolate(), name);
v8::Local<v8::Function> func;
if (!v8::Function::New(context, callback, console, 0,
if (!v8::Function::New(context, callback, data, 0,
v8::ConstructorBehavior::kThrow)
.ToLocal(&func))
return;
......@@ -337,18 +249,14 @@ void V8Console::groupEndCallback(
void V8Console::clearCallback(const v8::FunctionCallbackInfo<v8::Value>& info) {
ConsoleHelper helper(info);
InspectedContext* context = helper.ensureInspectedContext();
if (!context) return;
int contextGroupId = context->contextGroupId();
if (V8InspectorClient* client = helper.ensureDebuggerClient())
client->consoleClear(contextGroupId);
if (!helper.groupId()) return;
helper.inspector()->client()->consoleClear(helper.groupId());
helper.reportCallWithDefaultArgument(ConsoleAPIType::kClear,
String16("console.clear"));
}
void V8Console::countCallback(const v8::FunctionCallbackInfo<v8::Value>& info) {
ConsoleHelper helper(info);
String16 title = helper.firstArgToString(String16());
String16 identifier;
if (title.isEmpty()) {
......@@ -362,10 +270,8 @@ void V8Console::countCallback(const v8::FunctionCallbackInfo<v8::Value>& info) {
identifier = title + "@";
}
v8::Local<v8::Map> countMap;
if (!helper.privateMap("V8Console#countMap").ToLocal(&countMap)) return;
int32_t count = helper.getIntFromMap(countMap, identifier, 0) + 1;
helper.setIntOnMap(countMap, identifier, count);
int count =
helper.consoleMessageStorage()->count(helper.contextId(), identifier);
String16 countString = String16::fromInteger(count);
helper.reportCallWithArgument(
ConsoleAPIType::kCount,
......@@ -415,33 +321,25 @@ void V8Console::profileEndCallback(
static void timeFunction(const v8::FunctionCallbackInfo<v8::Value>& info,
bool timelinePrefix) {
ConsoleHelper helper(info);
if (V8InspectorClient* client = helper.ensureDebuggerClient()) {
String16 protocolTitle = helper.firstArgToString("default");
if (timelinePrefix) protocolTitle = "Timeline '" + protocolTitle + "'";
client->consoleTime(toStringView(protocolTitle));
v8::Local<v8::Map> timeMap;
if (!helper.privateMap("V8Console#timeMap").ToLocal(&timeMap)) return;
helper.setDoubleOnMap(timeMap, protocolTitle, client->currentTimeMS());
}
V8InspectorClient* client = helper.inspector()->client();
String16 protocolTitle = helper.firstArgToString("default");
if (timelinePrefix) protocolTitle = "Timeline '" + protocolTitle + "'";
client->consoleTime(toStringView(protocolTitle));
helper.consoleMessageStorage()->time(helper.contextId(), protocolTitle);
}
static void timeEndFunction(const v8::FunctionCallbackInfo<v8::Value>& info,
bool timelinePrefix) {
ConsoleHelper helper(info);
if (V8InspectorClient* client = helper.ensureDebuggerClient()) {
String16 protocolTitle = helper.firstArgToString("default");
if (timelinePrefix) protocolTitle = "Timeline '" + protocolTitle + "'";
client->consoleTimeEnd(toStringView(protocolTitle));
v8::Local<v8::Map> timeMap;
if (!helper.privateMap("V8Console#timeMap").ToLocal(&timeMap)) return;
double elapsed = client->currentTimeMS() -
helper.getDoubleFromMap(timeMap, protocolTitle, 0.0);
String16 message =
protocolTitle + ": " + String16::fromDouble(elapsed) + "ms";
helper.reportCallWithArgument(ConsoleAPIType::kTimeEnd, message);
}
V8InspectorClient* client = helper.inspector()->client();
String16 protocolTitle = helper.firstArgToString("default");
if (timelinePrefix) protocolTitle = "Timeline '" + protocolTitle + "'";
client->consoleTimeEnd(toStringView(protocolTitle));
double elapsed = helper.consoleMessageStorage()->timeEnd(helper.contextId(),
protocolTitle);
String16 message =
protocolTitle + ": " + String16::fromDouble(elapsed) + "ms";
helper.reportCallWithArgument(ConsoleAPIType::kTimeEnd, message);
}
void V8Console::timelineCallback(
......@@ -473,23 +371,20 @@ void V8Console::timeEndCallback(
void V8Console::timeStampCallback(
const v8::FunctionCallbackInfo<v8::Value>& info) {
ConsoleHelper helper(info);
if (V8InspectorClient* client = helper.ensureDebuggerClient()) {
String16 title = helper.firstArgToString(String16());
client->consoleTimeStamp(toStringView(title));
}
String16 title = helper.firstArgToString(String16());
helper.inspector()->client()->consoleTimeStamp(toStringView(title));
}
void V8Console::memoryGetterCallback(
const v8::FunctionCallbackInfo<v8::Value>& info) {
if (V8InspectorClient* client = ConsoleHelper(info).ensureDebuggerClient()) {
v8::Local<v8::Value> memoryValue;
if (!client
->memoryInfo(info.GetIsolate(),
info.GetIsolate()->GetCurrentContext())
.ToLocal(&memoryValue))
return;
info.GetReturnValue().Set(memoryValue);
}
V8InspectorClient* client = ConsoleHelper(info).inspector()->client();
v8::Local<v8::Value> memoryValue;
if (!client
->memoryInfo(info.GetIsolate(),
info.GetIsolate()->GetCurrentContext())
.ToLocal(&memoryValue))
return;
info.GetReturnValue().Set(memoryValue);
}
void V8Console::memorySetterCallback(
......@@ -610,10 +505,9 @@ void V8Console::unmonitorFunctionCallback(
void V8Console::lastEvaluationResultCallback(
const v8::FunctionCallbackInfo<v8::Value>& info) {
ConsoleHelper helper(info);
InspectedContext* context = helper.ensureInspectedContext();
if (!context) return;
if (InjectedScript* injectedScript = context->getInjectedScript())
info.GetReturnValue().Set(injectedScript->lastEvaluationResult());
InjectedScript* injectedScript = helper.injectedScript();
if (!injectedScript) return;
info.GetReturnValue().Set(injectedScript->lastEvaluationResult());
}
static void inspectImpl(const v8::FunctionCallbackInfo<v8::Value>& info,
......@@ -622,9 +516,7 @@ static void inspectImpl(const v8::FunctionCallbackInfo<v8::Value>& info,
if (!copyToClipboard) info.GetReturnValue().Set(info[0]);
ConsoleHelper helper(info);
InspectedContext* context = helper.ensureInspectedContext();
if (!context) return;
InjectedScript* injectedScript = context->getInjectedScript();
InjectedScript* injectedScript = helper.injectedScript();
if (!injectedScript) return;
std::unique_ptr<protocol::Runtime::RemoteObject> wrappedObject;
protocol::Response response =
......@@ -635,9 +527,10 @@ static void inspectImpl(const v8::FunctionCallbackInfo<v8::Value>& info,
std::unique_ptr<protocol::DictionaryValue> hints =
protocol::DictionaryValue::create();
if (copyToClipboard) hints->setBoolean("copyToClipboard", true);
if (V8InspectorSessionImpl* session = helper.currentSession())
if (V8InspectorSessionImpl* session = helper.currentSession()) {
session->runtimeAgent()->inspect(std::move(wrappedObject),
std::move(hints));
}
}
void V8Console::inspectCallback(
......@@ -677,49 +570,53 @@ v8::Local<v8::Object> V8Console::createConsole(
DCHECK(success);
USE(success);
createBoundFunctionProperty(context, console, "debug",
v8::Local<v8::External> data =
v8::External::New(isolate, inspectedContext->inspector());
createBoundFunctionProperty(context, console, data, "debug",
V8Console::debugCallback);
createBoundFunctionProperty(context, console, "error",
createBoundFunctionProperty(context, console, data, "error",
V8Console::errorCallback);
createBoundFunctionProperty(context, console, "info",
createBoundFunctionProperty(context, console, data, "info",
V8Console::infoCallback);
createBoundFunctionProperty(context, console, "log", V8Console::logCallback);
createBoundFunctionProperty(context, console, "warn",
createBoundFunctionProperty(context, console, data, "log",
V8Console::logCallback);
createBoundFunctionProperty(context, console, data, "warn",
V8Console::warnCallback);
createBoundFunctionProperty(context, console, "dir", V8Console::dirCallback);
createBoundFunctionProperty(context, console, "dirxml",
createBoundFunctionProperty(context, console, data, "dir",
V8Console::dirCallback);
createBoundFunctionProperty(context, console, data, "dirxml",
V8Console::dirxmlCallback);
createBoundFunctionProperty(context, console, "table",
createBoundFunctionProperty(context, console, data, "table",
V8Console::tableCallback);
createBoundFunctionProperty(context, console, "trace",
createBoundFunctionProperty(context, console, data, "trace",
V8Console::traceCallback);
createBoundFunctionProperty(context, console, "group",
createBoundFunctionProperty(context, console, data, "group",
V8Console::groupCallback);
createBoundFunctionProperty(context, console, "groupCollapsed",
createBoundFunctionProperty(context, console, data, "groupCollapsed",
V8Console::groupCollapsedCallback);
createBoundFunctionProperty(context, console, "groupEnd",
createBoundFunctionProperty(context, console, data, "groupEnd",
V8Console::groupEndCallback);
createBoundFunctionProperty(context, console, "clear",
createBoundFunctionProperty(context, console, data, "clear",
V8Console::clearCallback);
createBoundFunctionProperty(context, console, "count",
createBoundFunctionProperty(context, console, data, "count",
V8Console::countCallback);
createBoundFunctionProperty(context, console, "assert",
createBoundFunctionProperty(context, console, data, "assert",
V8Console::assertCallback);
createBoundFunctionProperty(context, console, "markTimeline",
createBoundFunctionProperty(context, console, data, "markTimeline",
V8Console::markTimelineCallback);
createBoundFunctionProperty(context, console, "profile",
createBoundFunctionProperty(context, console, data, "profile",
V8Console::profileCallback);
createBoundFunctionProperty(context, console, "profileEnd",
createBoundFunctionProperty(context, console, data, "profileEnd",
V8Console::profileEndCallback);
createBoundFunctionProperty(context, console, "timeline",
createBoundFunctionProperty(context, console, data, "timeline",
V8Console::timelineCallback);
createBoundFunctionProperty(context, console, "timelineEnd",
createBoundFunctionProperty(context, console, data, "timelineEnd",
V8Console::timelineEndCallback);
createBoundFunctionProperty(context, console, "time",
createBoundFunctionProperty(context, console, data, "time",
V8Console::timeCallback);
createBoundFunctionProperty(context, console, "timeEnd",
createBoundFunctionProperty(context, console, data, "timeEnd",
V8Console::timeEndCallback);
createBoundFunctionProperty(context, console, "timeStamp",
createBoundFunctionProperty(context, console, data, "timeStamp",
V8Console::timeStampCallback);
const char* jsConsoleAssert =
......@@ -747,30 +644,21 @@ v8::Local<v8::Object> V8Console::createConsole(
->Call(context, console, 0, nullptr);
}
if (hasMemoryAttribute)
if (hasMemoryAttribute) {
console->SetAccessorProperty(
toV8StringInternalized(isolate, "memory"),
v8::Function::New(context, V8Console::memoryGetterCallback, console, 0,
v8::Function::New(context, V8Console::memoryGetterCallback, data, 0,
v8::ConstructorBehavior::kThrow)
.ToLocalChecked(),
v8::Function::New(context, V8Console::memorySetterCallback,
v8::Local<v8::Value>(), 0,
v8::Function::New(context, V8Console::memorySetterCallback, data, 0,
v8::ConstructorBehavior::kThrow)
.ToLocalChecked(),
static_cast<v8::PropertyAttribute>(v8::None), v8::DEFAULT);
}
console->SetPrivate(context, inspectedContextPrivateKey(isolate),
v8::External::New(isolate, inspectedContext));
return console;
}
void V8Console::clearInspectedContextIfNeeded(v8::Local<v8::Context> context,
v8::Local<v8::Object> console) {
v8::Isolate* isolate = context->GetIsolate();
console->SetPrivate(context, inspectedContextPrivateKey(isolate),
v8::External::New(isolate, nullptr));
}
v8::Local<v8::Object> V8Console::createCommandLineAPI(
InspectedContext* inspectedContext) {
v8::Local<v8::Context> context = inspectedContext->context();
......@@ -784,68 +672,70 @@ v8::Local<v8::Object> V8Console::createCommandLineAPI(
DCHECK(success);
USE(success);
createBoundFunctionProperty(context, commandLineAPI, "dir",
v8::Local<v8::External> data =
v8::External::New(isolate, inspectedContext->inspector());
createBoundFunctionProperty(context, commandLineAPI, data, "dir",
V8Console::dirCallback,
"function dir(value) { [Command Line API] }");
createBoundFunctionProperty(context, commandLineAPI, "dirxml",
createBoundFunctionProperty(context, commandLineAPI, data, "dirxml",
V8Console::dirxmlCallback,
"function dirxml(value) { [Command Line API] }");
createBoundFunctionProperty(context, commandLineAPI, "profile",
createBoundFunctionProperty(context, commandLineAPI, data, "profile",
V8Console::profileCallback,
"function profile(title) { [Command Line API] }");
createBoundFunctionProperty(
context, commandLineAPI, "profileEnd", V8Console::profileEndCallback,
context, commandLineAPI, data, "profileEnd",
V8Console::profileEndCallback,
"function profileEnd(title) { [Command Line API] }");
createBoundFunctionProperty(context, commandLineAPI, "clear",
createBoundFunctionProperty(context, commandLineAPI, data, "clear",
V8Console::clearCallback,
"function clear() { [Command Line API] }");
createBoundFunctionProperty(
context, commandLineAPI, "table", V8Console::tableCallback,
context, commandLineAPI, data, "table", V8Console::tableCallback,
"function table(data, [columns]) { [Command Line API] }");
createBoundFunctionProperty(context, commandLineAPI, "keys",
createBoundFunctionProperty(context, commandLineAPI, data, "keys",
V8Console::keysCallback,
"function keys(object) { [Command Line API] }");
createBoundFunctionProperty(context, commandLineAPI, "values",
createBoundFunctionProperty(context, commandLineAPI, data, "values",
V8Console::valuesCallback,
"function values(object) { [Command Line API] }");
createBoundFunctionProperty(
context, commandLineAPI, "debug", V8Console::debugFunctionCallback,
context, commandLineAPI, data, "debug", V8Console::debugFunctionCallback,
"function debug(function) { [Command Line API] }");
createBoundFunctionProperty(
context, commandLineAPI, "undebug", V8Console::undebugFunctionCallback,
context, commandLineAPI, data, "undebug",
V8Console::undebugFunctionCallback,
"function undebug(function) { [Command Line API] }");
createBoundFunctionProperty(
context, commandLineAPI, "monitor", V8Console::monitorFunctionCallback,
context, commandLineAPI, data, "monitor",
V8Console::monitorFunctionCallback,
"function monitor(function) { [Command Line API] }");
createBoundFunctionProperty(
context, commandLineAPI, "unmonitor",
context, commandLineAPI, data, "unmonitor",
V8Console::unmonitorFunctionCallback,
"function unmonitor(function) { [Command Line API] }");
createBoundFunctionProperty(
context, commandLineAPI, "inspect", V8Console::inspectCallback,
context, commandLineAPI, data, "inspect", V8Console::inspectCallback,
"function inspect(object) { [Command Line API] }");
createBoundFunctionProperty(context, commandLineAPI, "copy",
createBoundFunctionProperty(context, commandLineAPI, data, "copy",
V8Console::copyCallback,
"function copy(value) { [Command Line API] }");
createBoundFunctionProperty(context, commandLineAPI, "$_",
createBoundFunctionProperty(context, commandLineAPI, data, "$_",
V8Console::lastEvaluationResultCallback);
createBoundFunctionProperty(context, commandLineAPI, "$0",
createBoundFunctionProperty(context, commandLineAPI, data, "$0",
V8Console::inspectedObject0);
createBoundFunctionProperty(context, commandLineAPI, "$1",
createBoundFunctionProperty(context, commandLineAPI, data, "$1",
V8Console::inspectedObject1);
createBoundFunctionProperty(context, commandLineAPI, "$2",
createBoundFunctionProperty(context, commandLineAPI, data, "$2",
V8Console::inspectedObject2);
createBoundFunctionProperty(context, commandLineAPI, "$3",
createBoundFunctionProperty(context, commandLineAPI, data, "$3",
V8Console::inspectedObject3);
createBoundFunctionProperty(context, commandLineAPI, "$4",
createBoundFunctionProperty(context, commandLineAPI, data, "$4",
V8Console::inspectedObject4);
inspectedContext->inspector()->client()->installAdditionalCommandLineAPI(
context, commandLineAPI);
commandLineAPI->SetPrivate(context, inspectedContextPrivateKey(isolate),
v8::External::New(isolate, inspectedContext));
return commandLineAPI;
}
......
......@@ -19,8 +19,6 @@ class V8Console {
public:
static v8::Local<v8::Object> createConsole(InspectedContext*,
bool hasMemoryAttribute);
static void clearInspectedContextIfNeeded(v8::Local<v8::Context>,
v8::Local<v8::Object> console);
static v8::Local<v8::Object> createCommandLineAPI(InspectedContext*);
class CommandLineAPIScope {
......
Tests checks that console.memory property can be set in strict mode (crbug.com/468611).
{
id : <messageId>
result : {
result : {
type : undefined
}
}
}
\ No newline at end of file
// Copyright 2016 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.
InspectorTest.log("Tests checks that console.memory property can be set in strict mode (crbug.com/468611).")
Protocol.Runtime.evaluate({ expression: "\"use strict\"\nconsole.memory = {};undefined" }).then(dumpResult);
function dumpResult(result)
{
InspectorTest.logMessage(result);
InspectorTest.completeTest();
}
......@@ -174,8 +174,10 @@ void InspectorClientImpl::connect(v8::Local<v8::Context> context) {
sessions_[context_group_id] =
inspector_->connect(context_group_id, channel_.get(), state);
context->SetAlignedPointerInEmbedderData(kInspectorClientIndex, this);
inspector_->contextCreated(v8_inspector::V8ContextInfo(
context, context_group_id, v8_inspector::StringView()));
v8_inspector::V8ContextInfo info(context, context_group_id,
v8_inspector::StringView());
info.hasMemoryOnConsole = true;
inspector_->contextCreated(info);
} else {
for (const auto& it : states_) {
int context_group_id = it.first;
......@@ -185,8 +187,10 @@ void InspectorClientImpl::connect(v8::Local<v8::Context> context) {
sessions_[context_group_id] =
inspector_->connect(context_group_id, channel_.get(), state);
context->SetAlignedPointerInEmbedderData(kInspectorClientIndex, this);
inspector_->contextCreated(v8_inspector::V8ContextInfo(
context, context_group_id, v8_inspector::StringView()));
v8_inspector::V8ContextInfo info(context, context_group_id,
v8_inspector::StringView());
info.hasMemoryOnConsole = true;
inspector_->contextCreated(info);
}
}
states_.clear();
......@@ -256,6 +260,17 @@ double InspectorClientImpl::currentTimeMS() {
return v8::base::OS::TimeCurrentMillis();
}
void InspectorClientImpl::setMemoryInfoForTest(
v8::Local<v8::Value> memory_info) {
memory_info_.Reset(isolate_, memory_info);
}
v8::MaybeLocal<v8::Value> InspectorClientImpl::memoryInfo(
v8::Isolate* isolate, v8::Local<v8::Context>) {
if (memory_info_.IsEmpty()) return v8::MaybeLocal<v8::Value>();
return memory_info_.Get(isolate);
}
void InspectorClientImpl::runMessageLoopOnPause(int) {
task_runner_->RunMessageLoop(true);
}
......
......@@ -39,6 +39,7 @@ class InspectorClientImpl : public v8_inspector::V8InspectorClient {
v8_inspector::V8InspectorSession* session(int context_group_id = 0);
void setCurrentTimeMSForTest(double time);
void setMemoryInfoForTest(v8::Local<v8::Value> memory_info);
private:
// V8InspectorClient implementation.
......@@ -46,6 +47,8 @@ class InspectorClientImpl : public v8_inspector::V8InspectorClient {
v8::Local<v8::Context> ensureDefaultContextInGroup(
int context_group_id) override;
double currentTimeMS() override;
v8::MaybeLocal<v8::Value> memoryInfo(v8::Isolate* isolate,
v8::Local<v8::Context>) override;
void runMessageLoopOnPause(int context_group_id) override;
void quitMessageLoopOnPause() override;
......@@ -65,6 +68,7 @@ class InspectorClientImpl : public v8_inspector::V8InspectorClient {
std::map<int, std::unique_ptr<v8_inspector::StringBuffer>> states_;
v8::Isolate* isolate_;
v8::Global<v8::Value> memory_info_;
TaskRunner* task_runner_;
FrontendChannel* frontend_channel_;
......
......@@ -57,6 +57,7 @@ class UtilsExtension : public v8::Extension {
"native function load();"
"native function compileAndRunWithOrigin();"
"native function setCurrentTimeMSForTest();"
"native function setMemoryInfoForTest();"
"native function schedulePauseOnNextStatement();"
"native function cancelPauseOnNextStatement();"
"native function reconnect();"
......@@ -107,6 +108,13 @@ class UtilsExtension : public v8::Extension {
.FromJust()) {
return v8::FunctionTemplate::New(isolate,
UtilsExtension::SetCurrentTimeMSForTest);
} else if (name->Equals(context, v8::String::NewFromUtf8(
isolate, "setMemoryInfoForTest",
v8::NewStringType::kNormal)
.ToLocalChecked())
.FromJust()) {
return v8::FunctionTemplate::New(isolate,
UtilsExtension::SetMemoryInfoForTest);
} else if (name->Equals(context,
v8::String::NewFromUtf8(
isolate, "schedulePauseOnNextStatement",
......@@ -266,6 +274,15 @@ class UtilsExtension : public v8::Extension {
args[0].As<v8::Number>()->Value());
}
static void SetMemoryInfoForTest(
const v8::FunctionCallbackInfo<v8::Value>& args) {
if (args.Length() != 1) {
fprintf(stderr, "Internal error: setMemoryInfoForTest(value).");
Exit();
}
inspector_client_->setMemoryInfoForTest(args[0]);
}
static void SchedulePauseOnNextStatement(
const v8::FunctionCallbackInfo<v8::Value>& args) {
if (args.Length() != 2 || !args[0]->IsString() || !args[1]->IsString()) {
......
......@@ -49,6 +49,8 @@ var utils = {};
this.setlocale = null;
utils.setCurrentTimeMSForTest = setCurrentTimeMSForTest;
this.setCurrentTimeMSForTest = null;
utils.setMemoryInfoForTest = setMemoryInfoForTest;
this.setMemoryInfoForTest = null;
utils.schedulePauseOnNextStatement = schedulePauseOnNextStatement;
this.schedulePauseOnNextStatement = null;
utils.cancelPauseOnNextStatement = cancelPauseOnNextStatement;
......@@ -75,6 +77,8 @@ InspectorTest.logMessage = function(originalMessage)
for (var key in object) {
if (nonStableFields.has(key))
object[key] = `<${key}>`;
else if (typeof object[key] === "string" && object[key].match(/\d+:\d+:\d+:debug/))
object[key] = object[key].replace(/\d+/, '<scriptId>');
else if (typeof object[key] === "object")
objects.push(object[key]);
}
......
Checks command line API.
Running test: testKeys
{
id : <messageId>
result : {
result : {
className : Function
description : function keys(object) { [Command Line API] }
objectId : <objectId>
type : function
}
}
}
{
id : <messageId>
result : {
result : {
type : object
value : [
[0] : a
]
}
}
}
{
id : <messageId>
result : {
result : {
type : object
value : [
[0] : a
]
}
}
}
Running test: testInspect
[object Object]
{
method : Runtime.inspectRequested
params : {
hints : {
}
object : {
className : Object
description : Object
objectId : <objectId>
type : object
}
}
}
{
method : Runtime.inspectRequested
params : {
hints : {
}
object : {
description : 239
type : number
value : 239
}
}
}
{
method : Runtime.inspectRequested
params : {
hints : {
}
object : {
description : -0
type : number
unserializableValue : -0
}
}
}
{
method : Runtime.inspectRequested
params : {
hints : {
copyToClipboard : true
}
object : {
type : string
value : hello
}
}
}
{
id : <messageId>
result : {
result : {
type : undefined
}
}
}
{
method : Runtime.inspectRequested
params : {
hints : {
}
object : {
className : Object
description : Object
objectId : <objectId>
type : object
}
}
}
Running test: testEvaluationResult
{
id : <messageId>
result : {
result : {
type : undefined
}
}
}
{
id : <messageId>
result : {
result : {
description : 42
type : number
value : 42
}
}
}
{
id : <messageId>
result : {
result : {
description : 42
type : number
value : 42
}
}
}
{
id : <messageId>
result : {
result : {
description : -0
type : number
unserializableValue : -0
}
}
}
{
id : <messageId>
result : {
result : {
type : object
value : {
}
}
}
}
Running test: testDebug
{
id : <messageId>
result : {
result : {
className : Function
description : function debug(function) { [Command Line API] }
objectId : <objectId>
type : function
}
}
}
{
id : <messageId>
result : {
result : {
className : Function
description : function undebug(function) { [Command Line API] }
objectId : <objectId>
type : function
}
}
}
foo (:0:16)
(anonymous) (:0:0)
[
[0] : <scriptId>:0:12:debug
]
foo (:0:16)
(anonymous) (:0:0)
[
[0] : <scriptId>:0:12:debug
]
Running test: testMonitor
{
id : <messageId>
result : {
result : {
className : Function
description : function monitor(function) { [Command Line API] }
objectId : <objectId>
type : function
}
}
}
{
id : <messageId>
result : {
result : {
className : Function
description : function unmonitor(function) { [Command Line API] }
objectId : <objectId>
type : function
}
}
}
function foo called
after first call
store functions..
function foo called
after first call
Running test: testProfile
{
id : <messageId>
result : {
result : {
className : Function
description : function profile(title) { [Command Line API] }
objectId : <objectId>
type : function
}
}
}
{
id : <messageId>
result : {
result : {
className : Function
description : function profileEnd(title) { [Command Line API] }
objectId : <objectId>
type : function
}
}
}
{
method : Profiler.consoleProfileStarted
params : {
id : 1
location : {
columnNumber : 1
lineNumber : 1
scriptId : <scriptId>
}
title : 42
}
}
{
method : Profiler.consoleProfileFinished
params : {
id : 1
location : {
columnNumber : 1
lineNumber : 1
scriptId : <scriptId>
}
profile : <profile>
title : 42
}
}
{
method : Profiler.consoleProfileStarted
params : {
id : 2
location : {
columnNumber : 6
lineNumber : 1
scriptId : <scriptId>
}
title : 239
}
}
{
method : Profiler.consoleProfileFinished
params : {
id : 2
location : {
columnNumber : 6
lineNumber : 1
scriptId : <scriptId>
}
profile : <profile>
title : 239
}
}
Running test: testDir
{
id : <messageId>
result : {
result : {
className : Function
description : function dir(value) { [Command Line API] }
objectId : <objectId>
type : function
}
}
}
{
method : Runtime.consoleAPICalled
params : {
args : [
[0] : {
className : Object
description : Object
objectId : <objectId>
preview : {
description : Object
overflow : false
properties : [
]
type : object
}
type : object
}
]
executionContextId : <executionContextId>
stackTrace : {
callFrames : [
[0] : {
columnNumber : 0
functionName :
lineNumber : 0
scriptId : <scriptId>
url :
}
]
}
timestamp : <timestamp>
type : dir
}
}
{
method : Runtime.consoleAPICalled
params : {
args : [
[0] : {
description : 42
type : number
value : 42
}
]
executionContextId : <executionContextId>
stackTrace : {
callFrames : [
[0] : {
columnNumber : 0
functionName :
lineNumber : 0
scriptId : <scriptId>
url :
}
]
}
timestamp : <timestamp>
type : dir
}
}
{
method : Runtime.consoleAPICalled
params : {
args : [
[0] : {
className : Object
description : Object
objectId : <objectId>
preview : {
description : Object
overflow : false
properties : [
]
type : object
}
type : object
}
]
executionContextId : <executionContextId>
stackTrace : {
callFrames : [
[0] : {
columnNumber : 5
functionName :
lineNumber : 0
scriptId : <scriptId>
url :
}
]
}
timestamp : <timestamp>
type : dir
}
}
Running test: testDirXML
{
id : <messageId>
result : {
result : {
className : Function
description : function dirxml(value) { [Command Line API] }
objectId : <objectId>
type : function
}
}
}
{
method : Runtime.consoleAPICalled
params : {
args : [
[0] : {
className : Object
description : Object
objectId : <objectId>
preview : {
description : Object
overflow : false
properties : [
]
type : object
}
type : object
}
]
executionContextId : <executionContextId>
stackTrace : {
callFrames : [
[0] : {
columnNumber : 0
functionName :
lineNumber : 0
scriptId : <scriptId>
url :
}
]
}
timestamp : <timestamp>
type : dirxml
}
}
{
method : Runtime.consoleAPICalled
params : {
args : [
[0] : {
description : 42
type : number
value : 42
}
]
executionContextId : <executionContextId>
stackTrace : {
callFrames : [
[0] : {
columnNumber : 0
functionName :
lineNumber : 0
scriptId : <scriptId>
url :
}
]
}
timestamp : <timestamp>
type : dirxml
}
}
Running test: testTable
{
id : <messageId>
result : {
result : {
className : Function
description : function table(data, [columns]) { [Command Line API] }
objectId : <objectId>
type : function
}
}
}
{
method : Runtime.consoleAPICalled
params : {
args : [
[0] : {
className : Object
description : Object
objectId : <objectId>
preview : {
description : Object
overflow : false
properties : [
]
type : object
}
type : object
}
]
executionContextId : <executionContextId>
stackTrace : {
callFrames : [
[0] : {
columnNumber : 0
functionName :
lineNumber : 0
scriptId : <scriptId>
url :
}
]
}
timestamp : <timestamp>
type : table
}
}
{
method : Runtime.consoleAPICalled
params : {
args : [
[0] : {
description : 42
type : number
value : 42
}
]
executionContextId : <executionContextId>
stackTrace : {
callFrames : [
[0] : {
columnNumber : 0
functionName :
lineNumber : 0
scriptId : <scriptId>
url :
}
]
}
timestamp : <timestamp>
type : table
}
}
Running test: testClear
{
id : <messageId>
result : {
result : {
className : Function
description : function clear() { [Command Line API] }
objectId : <objectId>
type : function
}
}
}
{
method : Runtime.consoleAPICalled
params : {
args : [
[0] : {
type : string
value : console.clear
}
]
executionContextId : <executionContextId>
stackTrace : {
callFrames : [
[0] : {
columnNumber : 0
functionName :
lineNumber : 0
scriptId : <scriptId>
url :
}
]
}
timestamp : <timestamp>
type : clear
}
}
{
method : Runtime.consoleAPICalled
params : {
args : [
[0] : {
type : string
value : console.clear
}
]
executionContextId : <executionContextId>
stackTrace : {
callFrames : [
[0] : {
columnNumber : 5
functionName :
lineNumber : 0
scriptId : <scriptId>
url :
}
]
}
timestamp : <timestamp>
type : clear
}
}
// 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.
InspectorTest.log('Checks command line API.');
InspectorTest.runAsyncTestSuite([
async function testKeys() {
InspectorTest.logMessage(await Protocol.Runtime.evaluate({
expression: 'keys', includeCommandLineAPI: true}));
InspectorTest.logMessage(await Protocol.Runtime.evaluate({
expression: 'keys({a : 1})', includeCommandLineAPI: true, returnByValue: true}));
Protocol.Runtime.evaluate({expression: 'this.keys = keys', includeCommandLineAPI: true});
InspectorTest.logMessage(await Protocol.Runtime.evaluate({
expression: 'this.keys({a : 1})', returnByValue: true}));
},
async function testInspect() {
InspectorTest.log(await Protocol.Runtime.evaluate({expression: 'inspect', includeCommandLineAPI: true}));
await Protocol.Runtime.enable();
Protocol.Runtime.onInspectRequested(InspectorTest.logMessage);
await Protocol.Runtime.evaluate({expression: 'inspect({})', includeCommandLineAPI: true});
await Protocol.Runtime.evaluate({expression: 'inspect(239)', includeCommandLineAPI: true});
await Protocol.Runtime.evaluate({expression: 'inspect(-0)', includeCommandLineAPI: true});
await Protocol.Runtime.evaluate({expression: 'copy(\'hello\')', includeCommandLineAPI: true});
InspectorTest.logMessage(await Protocol.Runtime.evaluate({expression: '$0', includeCommandLineAPI: true}));
Protocol.Runtime.evaluate({expression: 'this.inspect = inspect', includeCommandLineAPI: true});
await Protocol.Runtime.evaluate({expression: 'this.inspect({})'});
Protocol.Runtime.onInspectRequested(null);
await Protocol.Runtime.disable();
},
async function testEvaluationResult() {
InspectorTest.logMessage(await Protocol.Runtime.evaluate({expression: '$_', includeCommandLineAPI: true}));
await Protocol.Runtime.evaluate({expression: '42', objectGroup: 'console', includeCommandLineAPI: true});
InspectorTest.logMessage(await Protocol.Runtime.evaluate({expression: '$_', includeCommandLineAPI: true}));
await Protocol.Runtime.evaluate({expression: '239', includeCommandLineAPI: true});
InspectorTest.logMessage(await Protocol.Runtime.evaluate({expression: '$_', includeCommandLineAPI: true}));
await Protocol.Runtime.evaluate({expression: '-0', objectGroup: 'console', includeCommandLineAPI: true});
InspectorTest.logMessage(await Protocol.Runtime.evaluate({expression: '$_', includeCommandLineAPI: true}));
await Protocol.Runtime.evaluate({expression: '({})', objectGroup: 'console', includeCommandLineAPI: true});
InspectorTest.logMessage(await Protocol.Runtime.evaluate({expression: '$_', includeCommandLineAPI: true, returnByValue: true}));
},
async function testDebug() {
InspectorTest.setupScriptMap();
await Protocol.Debugger.enable();
InspectorTest.logMessage(await Protocol.Runtime.evaluate({expression: 'debug', includeCommandLineAPI: true}));
InspectorTest.logMessage(await Protocol.Runtime.evaluate({expression: 'undebug', includeCommandLineAPI: true}));
await Protocol.Runtime.evaluate({expression: 'function foo() {}'});
await Protocol.Runtime.evaluate({expression: 'debug(foo)', includeCommandLineAPI: true});
Protocol.Runtime.evaluate({ expression: 'foo()'});
let message = await Protocol.Debugger.oncePaused();
InspectorTest.logCallFrames(message.params.callFrames);
InspectorTest.logMessage(message.params.hitBreakpoints);
await Protocol.Debugger.resume();
await Protocol.Runtime.evaluate({expression: 'undebug(foo)', includeCommandLineAPI: true});
await Protocol.Runtime.evaluate({ expression: 'foo()'});
Protocol.Runtime.evaluate({
expression: 'this.debug = debug; this.undebug = undebug;', includeCommandLineAPI: true});
await Protocol.Runtime.evaluate({expression: 'this.debug(foo)'});
Protocol.Runtime.evaluate({ expression: 'foo()'});
message = await Protocol.Debugger.oncePaused();
InspectorTest.logCallFrames(message.params.callFrames);
InspectorTest.logMessage(message.params.hitBreakpoints);
await Protocol.Debugger.resume();
await Protocol.Runtime.evaluate({expression: 'this.undebug(foo)'});
await Protocol.Runtime.evaluate({expression: 'foo()'});
await Protocol.Debugger.disable();
},
async function testMonitor() {
await Protocol.Debugger.enable();
await Protocol.Runtime.enable();
Protocol.Runtime.onConsoleAPICalled(message => InspectorTest.log(message.params.args[0].value));
InspectorTest.logMessage(await Protocol.Runtime.evaluate({expression: 'monitor', includeCommandLineAPI: true}));
InspectorTest.logMessage(await Protocol.Runtime.evaluate({expression: 'unmonitor', includeCommandLineAPI: true}));
await Protocol.Runtime.evaluate({expression: 'function foo() {}'});
await Protocol.Runtime.evaluate({expression: 'monitor(foo)', includeCommandLineAPI: true});
Protocol.Runtime.evaluate({ expression: 'foo(); console.log(\'after first call\')'});
await Protocol.Runtime.evaluate({expression: 'unmonitor(foo)', includeCommandLineAPI: true});
await Protocol.Runtime.evaluate({ expression: 'foo()'});
Protocol.Runtime.evaluate({
expression: 'console.log(\'store functions..\'); this.monitor = monitor; this.unmonitor = unmonitor;', includeCommandLineAPI: true});
await Protocol.Runtime.evaluate({expression: 'this.monitor(foo)'});
Protocol.Runtime.evaluate({ expression: 'foo(); console.log(\'after first call\')'});
await Protocol.Runtime.evaluate({expression: 'this.unmonitor(foo)'});
await Protocol.Runtime.evaluate({ expression: 'foo()'});
Protocol.Runtime.onConsoleAPICalled(null);
await Protocol.Debugger.disable();
await Protocol.Runtime.disable();
},
async function testProfile() {
await Protocol.Profiler.enable();
InspectorTest.logMessage(await Protocol.Runtime.evaluate({expression: 'profile', includeCommandLineAPI: true}));
InspectorTest.logMessage(await Protocol.Runtime.evaluate({expression: 'profileEnd', includeCommandLineAPI: true}));
Protocol.Runtime.evaluate({expression: 'profile(42)', includeCommandLineAPI: true});
InspectorTest.logMessage(await Protocol.Profiler.onceConsoleProfileStarted());
Protocol.Runtime.evaluate({expression: 'profileEnd(42)', includeCommandLineAPI: true});
let message = await Protocol.Profiler.onceConsoleProfileFinished();
message.params.profile = '<profile>';
InspectorTest.logMessage(message);
Protocol.Runtime.evaluate({
expression: 'this.profile = profile; this.profileEnd = profileEnd;', includeCommandLineAPI: true});
Protocol.Runtime.evaluate({expression: 'this.profile(239)'});
InspectorTest.logMessage(await Protocol.Profiler.onceConsoleProfileStarted());
Protocol.Runtime.evaluate({expression: 'this.profileEnd(239)'});
message = await Protocol.Profiler.onceConsoleProfileFinished();
message.params.profile = '<profile>';
InspectorTest.logMessage(message);
await Protocol.Profiler.disable();
},
async function testDir() {
InspectorTest.logMessage(await Protocol.Runtime.evaluate({expression: 'dir', includeCommandLineAPI: true}));
await Protocol.Runtime.enable();
Protocol.Runtime.evaluate({expression: 'dir({})', includeCommandLineAPI: true});
InspectorTest.logMessage(await Protocol.Runtime.onceConsoleAPICalled());
Protocol.Runtime.evaluate({expression: 'dir(42)', includeCommandLineAPI: true});
InspectorTest.logMessage(await Protocol.Runtime.onceConsoleAPICalled());
Protocol.Runtime.evaluate({expression: 'this.dir = dir', includeCommandLineAPI: true});
Protocol.Runtime.evaluate({expression: 'this.dir({})'});
InspectorTest.logMessage(await Protocol.Runtime.onceConsoleAPICalled());
await Protocol.Runtime.disable();
},
async function testDirXML() {
InspectorTest.logMessage(await Protocol.Runtime.evaluate({expression: 'dirxml', includeCommandLineAPI: true}));
await Protocol.Runtime.enable();
Protocol.Runtime.evaluate({expression: 'dirxml({})', includeCommandLineAPI: true});
InspectorTest.logMessage(await Protocol.Runtime.onceConsoleAPICalled());
Protocol.Runtime.evaluate({expression: 'dirxml(42)', includeCommandLineAPI: true});
InspectorTest.logMessage(await Protocol.Runtime.onceConsoleAPICalled());
await Protocol.Runtime.disable();
},
async function testTable() {
InspectorTest.logMessage(await Protocol.Runtime.evaluate({expression: 'table', includeCommandLineAPI: true}));
await Protocol.Runtime.enable();
Protocol.Runtime.evaluate({expression: 'table({})', includeCommandLineAPI: true});
InspectorTest.logMessage(await Protocol.Runtime.onceConsoleAPICalled());
Protocol.Runtime.evaluate({expression: 'table(42)', includeCommandLineAPI: true});
InspectorTest.logMessage(await Protocol.Runtime.onceConsoleAPICalled());
await Protocol.Runtime.disable();
},
async function testClear() {
InspectorTest.logMessage(await Protocol.Runtime.evaluate({expression: 'clear', includeCommandLineAPI: true}));
await Protocol.Runtime.enable();
Protocol.Runtime.evaluate({expression: 'clear()', includeCommandLineAPI: true});
InspectorTest.logMessage(await Protocol.Runtime.onceConsoleAPICalled());
Protocol.Runtime.evaluate({expression: 'this.clear = clear', includeCommandLineAPI: true});
Protocol.Runtime.evaluate({expression: 'this.clear()'});
InspectorTest.logMessage(await Protocol.Runtime.onceConsoleAPICalled());
await Protocol.Runtime.disable();
}
]);
Checks console.memory
Running test: testWithoutMemory
{
id : <messageId>
result : {
result : {
type : undefined
}
}
}
Running test: testSetterInStrictMode
{
id : <messageId>
result : {
result : {
type : undefined
}
}
}
Running test: testWithMemory
{
id : <messageId>
result : {
result : {
description : 239
type : number
value : 239
}
}
}
Running test: testSetterDoesntOverride
{
id : <messageId>
result : {
result : {
description : 42
type : number
value : 42
}
}
}
// 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.
InspectorTest.log('Checks console.memory');
InspectorTest.runAsyncTestSuite([
async function testWithoutMemory() {
InspectorTest.logMessage(
await Protocol.Runtime.evaluate({expression: 'console.memory'}));
},
async function testSetterInStrictMode() {
// crbug.com/468611
InspectorTest.logMessage(
await Protocol.Runtime.evaluate({
expression: '"use strict"\nconsole.memory = {};undefined' }));
},
async function testWithMemory() {
utils.setMemoryInfoForTest(239);
InspectorTest.logMessage(
await Protocol.Runtime.evaluate({expression: 'console.memory'}));
},
async function testSetterDoesntOverride() {
utils.setMemoryInfoForTest(42);
await Protocol.Runtime.evaluate({expression: 'console.memory = 0'});
InspectorTest.logMessage(
await Protocol.Runtime.evaluate({expression: 'console.memory'}));
}
]);
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