Commit 73ac1d38 authored by kozyatinskiy's avatar kozyatinskiy Committed by Commit bot

[inspector] add async instrumentation for setTimeout in tests

BUG=v8:5738
R=dgozman@chromium.org

Review-Url: https://codereview.chromium.org/2574803002
Cr-Commit-Position: refs/heads/master@{#41680}
parent c22c70b6
Checks that async stack contains setTimeout
inner1 (test.js:11:4)
foo1 (test.js:14:2)
-- setTimeout --
inner2 (test.js:18:4)
foo2 (test.js:20:2)
-- setTimeout --
inner3 (test.js:25:4)
foo3 (test.js:27:2)
(anonymous) (expr.js:0:0)
// 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.
print('Checks that async stack contains setTimeout');
InspectorTest.addScript(`
var resolveCallback;
function foo1() {
function inner1() {
debugger;
resolveCallback();
}
inner1();
}
function foo2() {
function inner2() {
setTimeout(foo1, 0);
}
inner2();
}
function foo3() {
var promise = new Promise(resolve => resolveCallback = resolve);
function inner3() {
setTimeout(foo2, 0);
}
inner3();
return promise;
}
//# sourceURL=test.js`, 7, 26);
InspectorTest.setupScriptMap();
Protocol.Debugger.onPaused(message => {
InspectorTest.logCallFrames(message.params.callFrames);
var asyncStackTrace = message.params.asyncStackTrace;
while (asyncStackTrace) {
InspectorTest.log(`-- ${asyncStackTrace.description} --`);
InspectorTest.logCallFrames(asyncStackTrace.callFrames);
asyncStackTrace = asyncStackTrace.parent;
}
InspectorTest.log('');
Protocol.Debugger.resume();
});
Protocol.Debugger.enable();
Protocol.Debugger.setAsyncCallStackDepth({ maxDepth: 128 });
Protocol.Runtime.evaluate({ expression: "foo3()//# sourceURL=expr.js", awaitPromise: true })
.then(InspectorTest.completeTest);
...@@ -177,22 +177,23 @@ class UtilsExtension : public v8::Extension { ...@@ -177,22 +177,23 @@ class UtilsExtension : public v8::Extension {
backend_runner_->Append(new ExecuteStringTask( backend_runner_->Append(new ExecuteStringTask(
ToVector(args[0].As<v8::String>()), args[1].As<v8::String>(), ToVector(args[0].As<v8::String>()), args[1].As<v8::String>(),
args[2].As<v8::Int32>(), args[3].As<v8::Int32>())); args[2].As<v8::Int32>(), args[3].As<v8::Int32>(), nullptr, nullptr));
} }
}; };
TaskRunner* UtilsExtension::backend_runner_ = nullptr; TaskRunner* UtilsExtension::backend_runner_ = nullptr;
class SetTimeoutTask : public TaskRunner::Task { class SetTimeoutTask : public AsyncTask {
public: public:
SetTimeoutTask(v8::Isolate* isolate, v8::Local<v8::Function> function) SetTimeoutTask(v8::Isolate* isolate, v8::Local<v8::Function> function,
: function_(isolate, function) {} const char* task_name, v8_inspector::V8Inspector* inspector)
: AsyncTask(task_name, inspector), function_(isolate, function) {}
virtual ~SetTimeoutTask() {} virtual ~SetTimeoutTask() {}
bool is_inspector_task() final { return false; } bool is_inspector_task() final { return false; }
void Run(v8::Isolate* isolate, void AsyncRun(v8::Isolate* isolate,
const v8::Global<v8::Context>& global_context) override { const v8::Global<v8::Context>& global_context) override {
v8::MicrotasksScope microtasks_scope(isolate, v8::MicrotasksScope microtasks_scope(isolate,
v8::MicrotasksScope::kRunMicrotasks); v8::MicrotasksScope::kRunMicrotasks);
v8::HandleScope handle_scope(isolate); v8::HandleScope handle_scope(isolate);
...@@ -234,14 +235,20 @@ class SetTimeoutExtension : public v8::Extension { ...@@ -234,14 +235,20 @@ class SetTimeoutExtension : public v8::Extension {
} }
v8::Isolate* isolate = args.GetIsolate(); v8::Isolate* isolate = args.GetIsolate();
v8::Local<v8::Context> context = isolate->GetCurrentContext(); v8::Local<v8::Context> context = isolate->GetCurrentContext();
std::unique_ptr<TaskRunner::Task> task;
v8_inspector::V8Inspector* inspector =
InspectorClientImpl::InspectorFromContext(context);
if (args[0]->IsFunction()) { if (args[0]->IsFunction()) {
TaskRunner::FromContext(context)->Append( task.reset(new SetTimeoutTask(isolate,
new SetTimeoutTask(isolate, v8::Local<v8::Function>::Cast(args[0]))); v8::Local<v8::Function>::Cast(args[0]),
"setTimeout", inspector));
} else { } else {
TaskRunner::FromContext(context)->Append(new ExecuteStringTask( task.reset(new ExecuteStringTask(
ToVector(args[0].As<v8::String>()), v8::String::Empty(isolate), ToVector(args[0].As<v8::String>()), v8::String::Empty(isolate),
v8::Integer::New(isolate, 0), v8::Integer::New(isolate, 0))); v8::Integer::New(isolate, 0), v8::Integer::New(isolate, 0),
"setTimeout", inspector));
} }
TaskRunner::FromContext(context)->Append(task.release());
} }
}; };
...@@ -334,9 +341,10 @@ class FrontendChannelImpl : public InspectorClientImpl::FrontendChannel { ...@@ -334,9 +341,10 @@ class FrontendChannelImpl : public InspectorClientImpl::FrontendChannel {
v8::Local<v8::String> result = v8::String::Concat(prefix, message_string); v8::Local<v8::String> result = v8::String::Concat(prefix, message_string);
result = v8::String::Concat(result, suffix); result = v8::String::Concat(result, suffix);
frontend_task_runner_->Append(new ExecuteStringTask( frontend_task_runner_->Append(
ToVector(result), v8::String::Empty(isolate), new ExecuteStringTask(ToVector(result), v8::String::Empty(isolate),
v8::Integer::New(isolate, 0), v8::Integer::New(isolate, 0))); v8::Integer::New(isolate, 0),
v8::Integer::New(isolate, 0), nullptr, nullptr));
} }
private: private:
......
...@@ -101,6 +101,17 @@ InspectorTest.logObject = function(object, title) ...@@ -101,6 +101,17 @@ InspectorTest.logObject = function(object, title)
InspectorTest.log(lines.join("\n")); InspectorTest.log(lines.join("\n"));
} }
InspectorTest.logCallFrames = function(callFrames)
{
for (var frame of callFrames) {
var functionName = frame.functionName || '(anonymous)';
var url = frame.url ? frame.url : InspectorTest._scriptMap.get(frame.location.scriptId).url;
var lineNumber = frame.location ? frame.location.lineNumber : frame.lineNumber;
var columnNumber = frame.location ? frame.location.columnNumber : frame.columnNumber;
InspectorTest.log(`${functionName} (${url}:${lineNumber}:${columnNumber})`);
}
}
InspectorTest.completeTest = function() InspectorTest.completeTest = function()
{ {
Protocol.Debugger.disable().then(() => quit()); Protocol.Debugger.disable().then(() => quit());
...@@ -113,7 +124,7 @@ InspectorTest.completeTestAfterPendingTimeouts = function() ...@@ -113,7 +124,7 @@ InspectorTest.completeTestAfterPendingTimeouts = function()
awaitPromise: true }).then(InspectorTest.completeTest); awaitPromise: true }).then(InspectorTest.completeTest);
} }
InspectorTest.addScript = (string) => compileAndRunWithOrigin(string, "", 0, 0); InspectorTest.addScript = (string, lineOffset, columnOffset) => compileAndRunWithOrigin(string, "", lineOffset || 0, columnOffset || 0);
InspectorTest.addScriptWithUrl = (string, url) => compileAndRunWithOrigin(string, url, 0, 0); InspectorTest.addScriptWithUrl = (string, url) => compileAndRunWithOrigin(string, url, 0, 0);
InspectorTest.startDumpingProtocolMessages = function() InspectorTest.startDumpingProtocolMessages = function()
...@@ -143,6 +154,12 @@ InspectorTest.checkExpectation = function(fail, name, messageObject) ...@@ -143,6 +154,12 @@ InspectorTest.checkExpectation = function(fail, name, messageObject)
InspectorTest.expectedSuccess = InspectorTest.checkExpectation.bind(null, false); InspectorTest.expectedSuccess = InspectorTest.checkExpectation.bind(null, false);
InspectorTest.expectedError = InspectorTest.checkExpectation.bind(null, true); InspectorTest.expectedError = InspectorTest.checkExpectation.bind(null, true);
InspectorTest.setupScriptMap = function() {
if (InspectorTest._scriptMap)
return;
InspectorTest._scriptMap = new Map();
}
InspectorTest.runTestSuite = function(testSuite) InspectorTest.runTestSuite = function(testSuite)
{ {
function nextTest() function nextTest()
...@@ -194,6 +211,8 @@ InspectorTest._dispatchMessage = function(messageObject) ...@@ -194,6 +211,8 @@ InspectorTest._dispatchMessage = function(messageObject)
} else { } else {
var eventName = messageObject["method"]; var eventName = messageObject["method"];
var eventHandler = InspectorTest._eventHandler[eventName]; var eventHandler = InspectorTest._eventHandler[eventName];
if (InspectorTest._scriptMap && eventName === "Debugger.scriptParsed")
InspectorTest._scriptMap.set(messageObject.params.scriptId, JSON.parse(JSON.stringify(messageObject.params)));
if (eventHandler) if (eventHandler)
eventHandler(messageObject); eventHandler(messageObject);
} }
......
...@@ -4,6 +4,8 @@ ...@@ -4,6 +4,8 @@
#include "test/inspector/task-runner.h" #include "test/inspector/task-runner.h"
#include "test/inspector/inspector-impl.h"
#if !defined(_WIN32) && !defined(_WIN64) #if !defined(_WIN32) && !defined(_WIN64)
#include <unistd.h> // NOLINT #include <unistd.h> // NOLINT
#endif // !defined(_WIN32) && !defined(_WIN64) #endif // !defined(_WIN32) && !defined(_WIN64)
...@@ -134,21 +136,44 @@ v8::internal::Vector<uint16_t> ToVector(v8::Local<v8::String> str) { ...@@ -134,21 +136,44 @@ v8::internal::Vector<uint16_t> ToVector(v8::Local<v8::String> str) {
} // namespace } // namespace
AsyncTask::AsyncTask(const char* task_name,
v8_inspector::V8Inspector* inspector)
: inspector_(task_name ? inspector : nullptr) {
if (inspector_) {
inspector_->asyncTaskScheduled(
v8_inspector::StringView(reinterpret_cast<const uint8_t*>(task_name),
strlen(task_name)),
this, false);
}
}
void AsyncTask::Run(v8::Isolate* isolate,
const v8::Global<v8::Context>& context) {
if (inspector_) inspector_->asyncTaskStarted(this);
AsyncRun(isolate, context);
if (inspector_) inspector_->asyncTaskFinished(this);
}
ExecuteStringTask::ExecuteStringTask( ExecuteStringTask::ExecuteStringTask(
const v8::internal::Vector<uint16_t>& expression, const v8::internal::Vector<uint16_t>& expression,
v8::Local<v8::String> name, v8::Local<v8::Integer> line_offset, v8::Local<v8::String> name, v8::Local<v8::Integer> line_offset,
v8::Local<v8::Integer> column_offset) v8::Local<v8::Integer> column_offset, const char* task_name,
: expression_(expression), v8_inspector::V8Inspector* inspector)
: AsyncTask(task_name, inspector),
expression_(expression),
name_(ToVector(name)), name_(ToVector(name)),
line_offset_(line_offset.As<v8::Int32>()->Value()), line_offset_(line_offset.As<v8::Int32>()->Value()),
column_offset_(column_offset.As<v8::Int32>()->Value()) {} column_offset_(column_offset.As<v8::Int32>()->Value()) {}
ExecuteStringTask::ExecuteStringTask( ExecuteStringTask::ExecuteStringTask(
const v8::internal::Vector<const char>& expression) const v8::internal::Vector<const char>& expression)
: expression_utf8_(expression), line_offset_(0), column_offset_(0) {} : AsyncTask(nullptr, nullptr),
expression_utf8_(expression),
line_offset_(0),
column_offset_(0) {}
void ExecuteStringTask::Run(v8::Isolate* isolate, void ExecuteStringTask::AsyncRun(v8::Isolate* isolate,
const v8::Global<v8::Context>& context) { const v8::Global<v8::Context>& context) {
v8::MicrotasksScope microtasks_scope(isolate, v8::MicrotasksScope microtasks_scope(isolate,
v8::MicrotasksScope::kRunMicrotasks); v8::MicrotasksScope::kRunMicrotasks);
v8::HandleScope handle_scope(isolate); v8::HandleScope handle_scope(isolate);
......
...@@ -67,18 +67,33 @@ class TaskRunner : public v8::base::Thread { ...@@ -67,18 +67,33 @@ class TaskRunner : public v8::base::Thread {
DISALLOW_COPY_AND_ASSIGN(TaskRunner); DISALLOW_COPY_AND_ASSIGN(TaskRunner);
}; };
class ExecuteStringTask : public TaskRunner::Task { class AsyncTask : public TaskRunner::Task {
public:
AsyncTask(const char* task_name, v8_inspector::V8Inspector* inspector);
virtual ~AsyncTask() = default;
void Run(v8::Isolate* isolate,
const v8::Global<v8::Context>& context) override;
virtual void AsyncRun(v8::Isolate* isolate,
const v8::Global<v8::Context>& context) = 0;
private:
v8_inspector::V8Inspector* inspector_;
};
class ExecuteStringTask : public AsyncTask {
public: public:
ExecuteStringTask(const v8::internal::Vector<uint16_t>& expression, ExecuteStringTask(const v8::internal::Vector<uint16_t>& expression,
v8::Local<v8::String> name, v8::Local<v8::String> name,
v8::Local<v8::Integer> line_offset, v8::Local<v8::Integer> line_offset,
v8::Local<v8::Integer> column_offset); v8::Local<v8::Integer> column_offset, const char* task_name,
v8_inspector::V8Inspector* inspector);
explicit ExecuteStringTask( explicit ExecuteStringTask(
const v8::internal::Vector<const char>& expression); const v8::internal::Vector<const char>& expression);
bool is_inspector_task() override { return false; } bool is_inspector_task() override { return false; }
void Run(v8::Isolate* isolate, void AsyncRun(v8::Isolate* isolate,
const v8::Global<v8::Context>& context) override; const v8::Global<v8::Context>& context) override;
private: private:
v8::internal::Vector<uint16_t> expression_; v8::internal::Vector<uint16_t> expression_;
......
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