Commit 55849b16 authored by dgozman's avatar dgozman Committed by Commit bot

[inspector] Refactor inspector test

- moved all extensions to inspector_test.cc;
- properly supported multiple context groups and sessions;
- better isolation between components;
- better infrastructure in protocol-test.

BUG=chromium:590878

Review-Url: https://codereview.chromium.org/2890463004
Cr-Commit-Position: refs/heads/master@{#45409}
parent c9756be9
......@@ -10,11 +10,11 @@ const expression = `
delete Object.prototype.RemoteObject;
this.RemoteObject = v;
inspector.detachInspector();
inspector.fireContextDestroyed();
setTimeout(function() {
// Attach the inspector again for the sake of establishing a
// communication channel with the frontend test runner.
inspector.attachInspector();
inspector.fireContextCreated();
console.log("End of test");
}, 0);
},
......@@ -23,8 +23,8 @@ const expression = `
// Before the whole script runs, the inspector is already attached.
// Re-attach the inspector and trigger the console API to make sure that the
// injected inspector script runs again (and triggers the above setter).
inspector.detachInspector();
inspector.attachInspector();
inspector.fireContextDestroyed();
inspector.fireContextCreated();
console.log("First inspector activity after attaching inspector");
console.log("End of test");
`;
......
......@@ -8,6 +8,6 @@ InspectorTest.log('Check destroying agent inside of breakProgram');
await Protocol.Debugger.enable();
Protocol.Runtime.evaluate({expression: 'inspector.breakProgram(\'\', \'{}\')'});
await Protocol.Debugger.oncePaused();
utils.disconnect();
InspectorTest.session.disconnect();
utils.quit();
})();
......@@ -188,16 +188,16 @@ InspectorTest.runTestSuite([
},
function testAsyncDOMBreakpoint(next) {
utils.schedulePauseOnNextStatement('', '');
InspectorTest.contextGroup.schedulePauseOnNextStatement('', '');
InspectorTest.log('> all frames in framework:');
Protocol.Runtime
.evaluate(
{expression: 'asyncDOMBreakpoint()//# sourceURL=framework.js'})
.then(() => utils.cancelPauseOnNextStatement())
.then(() => InspectorTest.contextGroup.cancelPauseOnNextStatement())
.then(
() => Protocol.Runtime.evaluate(
{expression: '42//# sourceURL=user.js'}))
.then(() => utils.schedulePauseOnNextStatement('', ''))
.then(() => InspectorTest.contextGroup.schedulePauseOnNextStatement('', ''))
.then(
() => Protocol.Runtime.evaluate(
{expression: 'asyncDOMBreakpoint()//# sourceURL=user.js'}))
......
......@@ -64,7 +64,7 @@ var testSuite = [
];
function testPositions(positions) {
utils.schedulePauseOnNextStatement('', '');
InspectorTest.contextGroup.schedulePauseOnNextStatement('', '');
return Protocol.Debugger
.setBlackboxedRanges({scriptId: scriptId, positions: positions})
.then(InspectorTest.logMessage)
......
......@@ -47,7 +47,7 @@ Protocol.Debugger.enable()
var testSuite = [
function testStepIntoFromUser(next) {
utils.schedulePauseOnNextStatement('', '');
InspectorTest.contextGroup.schedulePauseOnNextStatement('', '');
test('testStepFromUser()', [
'print', // before testStepFromUser call
'stepInto', 'stepInto', 'print', // userFoo
......@@ -57,7 +57,7 @@ var testSuite = [
},
function testStepOverFromUser(next) {
utils.schedulePauseOnNextStatement('', '');
InspectorTest.contextGroup.schedulePauseOnNextStatement('', '');
test('testStepFromUser()', [
'print', // before testStepFromUser call
'stepInto', 'stepInto', 'print', // userFoo
......@@ -67,7 +67,7 @@ var testSuite = [
},
function testStepOutFromUser(next) {
utils.schedulePauseOnNextStatement('', '');
InspectorTest.contextGroup.schedulePauseOnNextStatement('', '');
test('testStepFromUser()', [
'print', // before testStepFromUser call
'stepInto', 'stepInto', 'print', // userFoo
......
......@@ -153,7 +153,7 @@ function foo6() { Promise.resolve().then(() => 42) }`;
function compileScript(source, origin) {
var promise = Protocol.Debugger.onceScriptParsed().then(message => message.params.scriptId);
if (!origin) origin = { name: '', line_offset: 0, column_offset: 0 };
utils.compileAndRunWithOrigin(source, origin.name, origin.line_offset, origin.column_offset, false);
InspectorTest.addScript(source, origin.line_offset, origin.column_offset, origin.name);
return promise;
}
......
......@@ -33,17 +33,17 @@ InspectorTest.runTestSuite([
},
function testSchedulePauseOnNextStatement(next) {
utils.schedulePauseOnNextStatement('reason', JSON.stringify({a: 42}));
InspectorTest.contextGroup.schedulePauseOnNextStatement('reason', JSON.stringify({a: 42}));
Protocol.Runtime.evaluate({ expression: 'foo()//# sourceURL=expr1.js'})
.then(() => Protocol.Runtime.evaluate({
expression: 'foo()//# sourceURL=expr2.js'}))
.then(() => utils.cancelPauseOnNextStatement())
.then(() => InspectorTest.contextGroup.cancelPauseOnNextStatement())
.then(next);
},
function testCancelPauseOnNextStatement(next) {
utils.schedulePauseOnNextStatement('reason', JSON.stringify({a: 42}));
utils.cancelPauseOnNextStatement();
InspectorTest.contextGroup.schedulePauseOnNextStatement('reason', JSON.stringify({a: 42}));
InspectorTest.contextGroup.cancelPauseOnNextStatement();
Protocol.Runtime.evaluate({ expression: 'foo()'})
.then(next);
}
......
......@@ -24,50 +24,53 @@ InspectorTest.runAsyncTestSuite([
},
async function testSkipOtherContext1() {
let contextGroupId = utils.createContextGroup();
Protocol.Debugger.enable({}, contextGroupId);
let contextGroup = InspectorTest.createContextGroup();
let session = InspectorTest.createSession(contextGroup);
session.Protocol.Debugger.enable({});
Protocol.Debugger.pause();
Protocol.Runtime.evaluate({expression: 'var a = 42; //# sourceURL=framework.js'});
Protocol.Runtime.evaluate({expression: 'var a = 239;'}, contextGroupId);
session.Protocol.Runtime.evaluate({expression: 'var a = 239;'});
Protocol.Runtime.evaluate({expression: 'var a = 1;'});
await waitPauseAndDumpLocation();
await Protocol.Debugger.resume();
await Protocol.Debugger.disable({}, contextGroupId);
await session.Protocol.Debugger.disable({});
},
async function testSkipOtherContext2() {
let contextGroupId = utils.createContextGroup();
Protocol.Debugger.enable({}, contextGroupId);
Protocol.Debugger.pause({}, contextGroupId);
let contextGroup = InspectorTest.createContextGroup();
let session = InspectorTest.createSession(contextGroup);
InspectorTest.setupScriptMap(session);
session.Protocol.Debugger.enable({});
session.Protocol.Debugger.pause({});
Protocol.Runtime.evaluate({expression: 'var a = 42; //# sourceURL=framework.js'});
Protocol.Runtime.evaluate({expression: 'var a = 239;'}, contextGroupId);
session.Protocol.Runtime.evaluate({expression: 'var a = 239;'});
Protocol.Runtime.evaluate({expression: 'var a = 1;'});
await waitPauseAndDumpLocation();
await waitPauseAndDumpLocation(session);
// should not resume pause from different context group id.
Protocol.Debugger.resume();
Protocol.Debugger.stepOver({}, contextGroupId);
await waitPauseAndDumpLocation();
await Protocol.Debugger.resume({}, contextGroupId);
await Protocol.Debugger.disable({}, contextGroupId);
session.Protocol.Debugger.stepOver({});
await waitPauseAndDumpLocation(session);
await session.Protocol.Debugger.resume({});
await session.Protocol.Debugger.disable({});
},
async function testWithNativeBreakpoint() {
utils.schedulePauseOnNextStatement('', '');
InspectorTest.contextGroup.schedulePauseOnNextStatement('', '');
await Protocol.Debugger.pause();
utils.cancelPauseOnNextStatement();
InspectorTest.contextGroup.cancelPauseOnNextStatement();
Protocol.Runtime.evaluate({expression: 'var a = 42;'});
await waitPauseAndDumpLocation();
await Protocol.Debugger.resume();
await Protocol.Debugger.pause();
utils.schedulePauseOnNextStatement('', '');
utils.cancelPauseOnNextStatement();
InspectorTest.contextGroup.schedulePauseOnNextStatement('', '');
InspectorTest.contextGroup.cancelPauseOnNextStatement();
Protocol.Runtime.evaluate({expression: 'var a = 42;'});
await waitPauseAndDumpLocation();
await Protocol.Debugger.resume();
utils.schedulePauseOnNextStatement('', '');
utils.cancelPauseOnNextStatement();
InspectorTest.contextGroup.schedulePauseOnNextStatement('', '');
InspectorTest.contextGroup.cancelPauseOnNextStatement();
await Protocol.Debugger.pause();
Protocol.Runtime.evaluate({expression: 'var a = 42;'});
await waitPauseAndDumpLocation();
......@@ -85,9 +88,10 @@ InspectorTest.runAsyncTestSuite([
}
]);
async function waitPauseAndDumpLocation() {
var message = await Protocol.Debugger.oncePaused();
async function waitPauseAndDumpLocation(session) {
session = session || InspectorTest.session;
var message = await session.Protocol.Debugger.oncePaused();
InspectorTest.log('paused at:');
await InspectorTest.logSourceLocation(message.params.callFrames[0].location);
await InspectorTest.logSourceLocation(message.params.callFrames[0].location, session);
return message;
}
......@@ -7,24 +7,26 @@ InspectorTest.log('Checks stepping with more then one context group.');
(async function test() {
InspectorTest.setupScriptMap();
await Protocol.Debugger.enable();
let contextGroupId = utils.createContextGroup();
await Protocol.Debugger.enable({}, contextGroupId);
let contextGroup = InspectorTest.createContextGroup();
let session = InspectorTest.createSession(contextGroup);
InspectorTest.setupScriptMap(session);
await session.Protocol.Debugger.enable({});
Protocol.Runtime.evaluate({expression: 'debugger'});
Protocol.Runtime.evaluate({expression: 'setTimeout(() => { debugger }, 0)'}, contextGroupId);
session.Protocol.Runtime.evaluate({expression: 'setTimeout(() => { debugger }, 0)'});
Protocol.Runtime.evaluate({expression: 'setTimeout(() => 42, 0)'});
await waitPauseAndDumpLocation();
await waitPauseAndDumpLocation(InspectorTest.session);
Protocol.Debugger.stepOver();
await Protocol.Debugger.oncePaused();
Protocol.Debugger.stepOver();
await waitPauseAndDumpLocation();
await Protocol.Debugger.disable({}, contextGroupId);
await waitPauseAndDumpLocation(InspectorTest.session);
await session.Protocol.Debugger.disable({});
await Protocol.Debugger.disable();
InspectorTest.completeTest();
})();
async function waitPauseAndDumpLocation() {
var message = await Protocol.Debugger.oncePaused();
async function waitPauseAndDumpLocation(session) {
var message = await session.Protocol.Debugger.oncePaused();
InspectorTest.log('paused at:');
await InspectorTest.logSourceLocation(message.params.callFrames[0].location);
await InspectorTest.logSourceLocation(message.params.callFrames[0].location, session);
return message;
}
......@@ -3,7 +3,7 @@
// found in the LICENSE file.
Protocol.Debugger.onPaused(message => {
let url = InspectorTest._scriptMap.get(message.params.callFrames[0].location.scriptId).url;
let url = InspectorTest.session._scriptMap.get(message.params.callFrames[0].location.scriptId).url;
if (url !== 'test.js') {
InspectorTest.log('InjectedSciptSource on stack.');
InspectorTest.completeTest();
......
......@@ -4,7 +4,7 @@
// Flags: --expose-inspector-scripts
Protocol.Debugger.onPaused(message => {
let url = InspectorTest._scriptMap.get(message.params.callFrames[0].location.scriptId).url;
let url = InspectorTest.session._scriptMap.get(message.params.callFrames[0].location.scriptId).url;
if (url !== 'test.js') {
InspectorTest.log('InjectedSciptSource on stack.');
InspectorTest.completeTest();
......
......@@ -27,8 +27,7 @@ function testFunction(bytes) {
new WebAssembly.Module(buffer);
}
InspectorTest.addScriptWithUrl(
testFunction.toString(), 'v8://test/testFunction');
InspectorTest.addScript(testFunction.toString(), 0, 0, 'v8://test/testFunction');
InspectorTest.addScript('var module_bytes = ' + JSON.stringify(module_bytes));
Protocol.Debugger.enable();
......
This diff is collapsed.
......@@ -5,11 +5,15 @@
#ifndef V8_TEST_INSPECTOR_PROTOCOL_INSPECTOR_IMPL_H_
#define V8_TEST_INSPECTOR_PROTOCOL_INSPECTOR_IMPL_H_
#include <map>
#include <vector>
#include "include/v8-inspector.h"
#include "include/v8.h"
#include "src/base/macros.h"
#include "src/base/platform/platform.h"
#include "test/inspector/task-runner.h"
class TaskRunner;
class InspectorClientImpl : public v8_inspector::V8InspectorClient {
public:
......@@ -17,31 +21,30 @@ class InspectorClientImpl : public v8_inspector::V8InspectorClient {
public:
virtual ~FrontendChannel() = default;
virtual void SendMessageToFrontend(
const v8_inspector::StringView& message) = 0;
int session_id, const v8_inspector::StringView& message) = 0;
};
InspectorClientImpl(TaskRunner* task_runner,
FrontendChannel* frontend_channel,
v8::base::Semaphore* ready_semaphore);
InspectorClientImpl(v8::Isolate* isolate, TaskRunner* task_runner,
FrontendChannel* frontend_channel);
virtual ~InspectorClientImpl();
void scheduleReconnect(v8::base::Semaphore* ready_semaphore);
void scheduleDisconnect(v8::base::Semaphore* ready_semaphore);
void scheduleCreateContextGroup(
IsolateData::SetupGlobalTasks setup_global_tasks,
v8::base::Semaphore* ready_semaphore, int* context_group_id);
static v8_inspector::V8Inspector* InspectorFromContext(
v8::Local<v8::Context> context);
static v8_inspector::V8InspectorSession* SessionFromContext(
v8::Local<v8::Context> context);
// context_group_id = 0 means default context group.
v8_inspector::V8InspectorSession* session(int context_group_id = 0);
void setCurrentTimeMSForTest(double time);
void setMemoryInfoForTest(v8::Local<v8::Value> memory_info);
void setLogConsoleApiMessageCalls(bool log);
v8_inspector::V8Inspector* inspector() const { return inspector_.get(); }
int ConnectSession(int context_group_id,
const v8_inspector::StringView& state);
std::unique_ptr<v8_inspector::StringBuffer> DisconnectSession(int session_id);
void SendMessage(int session_id, const v8_inspector::StringView& message);
void BreakProgram(int context_group_id,
const v8_inspector::StringView& reason,
const v8_inspector::StringView& details);
void SchedulePauseOnNextStatement(int context_group_id,
const v8_inspector::StringView& reason,
const v8_inspector::StringView& details);
void CancelPauseOnNextStatement(int context_group_id);
void SetCurrentTimeMSForTest(double time);
void SetMemoryInfoForTest(v8::Local<v8::Value> memory_info);
void SetLogConsoleApiMessageCalls(bool log);
void ContextCreated(v8::Local<v8::Context> context, int context_group_id);
void ContextDestroyed(v8::Local<v8::Context> context);
private:
// V8InspectorClient implementation.
......@@ -59,30 +62,18 @@ class InspectorClientImpl : public v8_inspector::V8InspectorClient {
const v8_inspector::StringView& url,
unsigned lineNumber, unsigned columnNumber,
v8_inspector::V8StackTrace*) override;
friend class SendMessageToBackendTask;
friend class ConnectTask;
void connect();
void ConnectToContextGroup(int context_group_id,
v8_inspector::StringView state);
friend class DisconnectTask;
void disconnect(bool reset_inspector);
friend class CreateContextGroupTask;
int createContextGroup(
const IsolateData::SetupGlobalTasks& setup_global_tasks);
std::vector<int> GetSessionIds(int context_group_id);
std::unique_ptr<v8_inspector::V8Inspector> inspector_;
std::unique_ptr<v8_inspector::V8Inspector::Channel> channel_;
int last_session_id_ = 0;
std::map<int, std::unique_ptr<v8_inspector::V8InspectorSession>> sessions_;
std::map<int, std::unique_ptr<v8_inspector::StringBuffer>> states_;
std::map<v8_inspector::V8InspectorSession*, int> context_group_by_session_;
std::map<int, std::unique_ptr<v8_inspector::V8Inspector::Channel>> channels_;
TaskRunner* task_runner_;
v8::Isolate* isolate_;
v8::Global<v8::Value> memory_info_;
TaskRunner* task_runner_;
FrontendChannel* frontend_channel_;
bool current_time_set_for_test_ = false;
double current_time_ = 0.0;
bool log_console_api_message_calls_ = false;
......@@ -90,19 +81,4 @@ class InspectorClientImpl : public v8_inspector::V8InspectorClient {
DISALLOW_COPY_AND_ASSIGN(InspectorClientImpl);
};
class SendMessageToBackendExtension : public IsolateData::SetupGlobalTask {
public:
void Run(v8::Isolate* isolate, v8::Local<v8::ObjectTemplate> global) override;
static void set_backend_task_runner(TaskRunner* task_runner) {
backend_task_runner_ = task_runner;
}
private:
static void SendMessageToBackend(
const v8::FunctionCallbackInfo<v8::Value>& args);
static TaskRunner* backend_task_runner_;
};
#endif // V8_TEST_INSPECTOR_PROTOCOL_INSPECTOR_IMPL_H_
This diff is collapsed.
......@@ -10,6 +10,7 @@
namespace {
const int kIsolateDataIndex = 2;
const int kContextGroupIdIndex = 3;
v8::internal::Vector<uint16_t> ToVector(v8::Local<v8::String> str) {
v8::internal::Vector<uint16_t> buffer =
......@@ -22,7 +23,8 @@ v8::internal::Vector<uint16_t> ToVector(v8::Local<v8::String> str) {
IsolateData::IsolateData(TaskRunner* task_runner,
IsolateData::SetupGlobalTasks setup_global_tasks,
v8::StartupData* startup_data)
v8::StartupData* startup_data,
InspectorClientImpl::FrontendChannel* channel)
: task_runner_(task_runner),
setup_global_tasks_(std::move(setup_global_tasks)) {
v8::Isolate::CreateParams params;
......@@ -31,6 +33,8 @@ IsolateData::IsolateData(TaskRunner* task_runner,
params.snapshot_blob = startup_data;
isolate_ = v8::Isolate::New(params);
isolate_->SetMicrotasksPolicy(v8::MicrotasksPolicy::kScoped);
if (channel)
inspector_.reset(new InspectorClientImpl(isolate_, task_runner, channel));
}
IsolateData* IsolateData::FromContext(v8::Local<v8::Context> context) {
......@@ -39,6 +43,7 @@ IsolateData* IsolateData::FromContext(v8::Local<v8::Context> context) {
}
int IsolateData::CreateContextGroup() {
v8::HandleScope handle_scope(isolate_);
v8::Local<v8::ObjectTemplate> global_template =
v8::ObjectTemplate::New(isolate_);
for (auto it = setup_global_tasks_.begin(); it != setup_global_tasks_.end();
......@@ -49,7 +54,11 @@ int IsolateData::CreateContextGroup() {
v8::Context::New(isolate_, nullptr, global_template);
context->SetAlignedPointerInEmbedderData(kIsolateDataIndex, this);
int context_group_id = ++last_context_group_id_;
// Should be 2-byte aligned.
context->SetAlignedPointerInEmbedderData(
kContextGroupIdIndex, reinterpret_cast<void*>(context_group_id * 2));
contexts_[context_group_id].Reset(isolate_, context);
if (inspector_) inspector_->ContextCreated(context, context_group_id);
return context_group_id;
}
......@@ -57,6 +66,13 @@ v8::Local<v8::Context> IsolateData::GetContext(int context_group_id) {
return contexts_[context_group_id].Get(isolate_);
}
int IsolateData::GetContextGroupId(v8::Local<v8::Context> context) {
return static_cast<int>(
reinterpret_cast<intptr_t>(
context->GetAlignedPointerFromEmbedderData(kContextGroupIdIndex)) /
2);
}
void IsolateData::RegisterModule(v8::Local<v8::Context> context,
v8::internal::Vector<uint16_t> name,
v8::ScriptCompiler::Source* source) {
......
......@@ -11,6 +11,7 @@
#include "include/v8-platform.h"
#include "include/v8.h"
#include "src/vector.h"
#include "test/inspector/inspector-impl.h"
class TaskRunner;
......@@ -25,13 +26,16 @@ class IsolateData {
using SetupGlobalTasks = std::vector<std::unique_ptr<SetupGlobalTask>>;
IsolateData(TaskRunner* task_runner, SetupGlobalTasks setup_global_tasks,
v8::StartupData* startup_data);
v8::StartupData* startup_data,
InspectorClientImpl::FrontendChannel* channel);
static IsolateData* FromContext(v8::Local<v8::Context> context);
v8::Isolate* isolate() const { return isolate_; }
InspectorClientImpl* inspector() const { return inspector_.get(); }
TaskRunner* task_runner() const { return task_runner_; }
int CreateContextGroup();
v8::Local<v8::Context> GetContext(int context_group_id);
int GetContextGroupId(v8::Local<v8::Context> context);
void RegisterModule(v8::Local<v8::Context> context,
v8::internal::Vector<uint16_t> name,
v8::ScriptCompiler::Source* source);
......@@ -53,6 +57,7 @@ class IsolateData {
TaskRunner* task_runner_;
SetupGlobalTasks setup_global_tasks_;
v8::Isolate* isolate_;
std::unique_ptr<InspectorClientImpl> inspector_;
int last_context_group_id_ = 0;
std::map<int, v8::Global<v8::Context>> contexts_;
std::map<v8::internal::Vector<uint16_t>, v8::Global<v8::Module>,
......
......@@ -2,9 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
const id = ++InspectorTest._requestId;
const id = ++InspectorTest.session._requestId;
var command = { "method": "Runtime.evaluate", "params": { expression: "\"!!!\"" }, "id": id };
InspectorTest.sendRawCommand(id, JSON.stringify(command).replace("!!!", "\\u041F\\u0440\\u0438\\u0432\\u0435\\u0442 \\u043C\\u0438\\u0440"), step2);
InspectorTest.session.sendRawCommand(id, JSON.stringify(command).replace("!!!", "\\u041F\\u0440\\u0438\\u0432\\u0435\\u0442 \\u043C\\u0438\\u0440"), step2);
function step2(msg)
{
......
This diff is collapsed.
......@@ -4,24 +4,20 @@
InspectorTest.log('Checks createContext().');
InspectorTest.setupScriptMap();
Protocol.Runtime.onExecutionContextCreated(InspectorTest.logMessage);
Protocol.Debugger.onPaused((message) => {
InspectorTest.logSourceLocation(message.params.callFrames[0].location);
Protocol.Debugger.stepOut();
});
var executionContextIds = new Set();
Protocol.Debugger.onScriptParsed(message => executionContextIds.add(message.params.executionContextId));
var contextGroupId;
var contextGroup = InspectorTest.createContextGroup();
var session = InspectorTest.createSession(contextGroup);
setup(InspectorTest.session);
setup(session);
Protocol.Runtime.enable()
.then(() => contextGroupId = utils.createContextGroup())
.then(() => Protocol.Runtime.enable({}, contextGroupId))
.then(() => session.Protocol.Runtime.enable({}))
.then(() => Protocol.Debugger.enable())
.then(() => Protocol.Debugger.enable({}, contextGroupId))
.then(() => session.Protocol.Debugger.enable({}))
.then(InspectorTest.logMessage)
.then(() => {
Protocol.Runtime.evaluate({ expression: 'debugger;' })
Protocol.Runtime.evaluate({ expression: 'setTimeout(x => x * 2, 0)' }, contextGroupId);
Protocol.Runtime.evaluate({ expression: 'debugger;' });
session.Protocol.Runtime.evaluate({expression: 'setTimeout(x => x * 2, 0)'});
Protocol.Runtime.evaluate({ expression: 'setTimeout(x => x * 3, 0)' });
})
.then(() => InspectorTest.waitPendingTasks())
......@@ -29,14 +25,25 @@ Protocol.Runtime.enable()
InspectorTest.log(`Reported script's execution id: ${executionContextIds.size}`);
executionContextIds.clear();
})
.then(() => utils.reconnect())
.then(() => InspectorTest.session.reconnect())
.then(() => session.reconnect())
.then(() => {
Protocol.Runtime.evaluate({ expression: 'debugger;' })
Protocol.Runtime.evaluate({ expression: 'setTimeout(x => x * 2, 0)' }, contextGroupId);
session.Protocol.Runtime.evaluate({ expression: 'setTimeout(x => x * 2, 0)' });
Protocol.Runtime.evaluate({ expression: 'setTimeout(x => x * 3, 0)' });
})
.then(() => InspectorTest.waitPendingTasks())
.then(() => Protocol.Debugger.disable({}, contextGroupId))
.then(() => session.Protocol.Debugger.disable({}))
.then(() => Protocol.Debugger.disable({}))
.then(() => InspectorTest.log(`Reported script's execution id: ${executionContextIds.size}`))
.then(InspectorTest.completeTest);
function setup(session) {
session.Protocol.Runtime.onExecutionContextCreated(InspectorTest.logMessage);
InspectorTest.setupScriptMap(session);
session.Protocol.Debugger.onPaused((message) => {
InspectorTest.logSourceLocation(message.params.callFrames[0].location, session);
session.Protocol.Debugger.stepOut();
});
session.Protocol.Debugger.onScriptParsed(message => executionContextIds.add(message.params.executionContextId));
}
......@@ -56,9 +56,9 @@ InspectorTest.runTestSuite([
function testSetCustomObjectFormatterEnabled(next) {
Protocol.Runtime.onConsoleAPICalled(InspectorTest.logMessage);
// cleanup console message storage
reconnect();
Protocol.Runtime.enable()
Protocol.Runtime.discardConsoleEntries()
.then(reconnect)
.then(() => Protocol.Runtime.enable())
.then(() => Protocol.Runtime.setCustomObjectFormatterEnabled({ enabled: true }))
.then(reconnect)
.then(() => Protocol.Runtime.evaluate({ expression: 'console.log({ name: 42 })'}))
......@@ -73,5 +73,5 @@ InspectorTest.runTestSuite([
function reconnect() {
InspectorTest.logMessage('will reconnect..');
utils.reconnect();
InspectorTest.session.reconnect();
}
......@@ -17,7 +17,15 @@ void ReportUncaughtException(v8::Isolate* isolate,
CHECK(try_catch.HasCaught());
v8::HandleScope handle_scope(isolate);
std::string message = *v8::String::Utf8Value(try_catch.Message()->Get());
fprintf(stderr, "Unhandle exception: %s\n", message.data());
int line = try_catch.Message()
->GetLineNumber(isolate->GetCurrentContext())
.FromJust();
std::string source_line =
*v8::String::Utf8Value(try_catch.Message()
->GetSourceLine(isolate->GetCurrentContext())
.ToLocalChecked());
fprintf(stderr, "Unhandle exception: %s @%s[%d]\n", message.data(),
source_line.data(), line);
}
v8::internal::Vector<uint16_t> ToVector(v8::Local<v8::String> str) {
......@@ -32,10 +40,12 @@ v8::internal::Vector<uint16_t> ToVector(v8::Local<v8::String> str) {
TaskRunner::TaskRunner(IsolateData::SetupGlobalTasks setup_global_tasks,
bool catch_exceptions,
v8::base::Semaphore* ready_semaphore,
v8::StartupData* startup_data)
v8::StartupData* startup_data,
InspectorClientImpl::FrontendChannel* channel)
: Thread(Options("Task Runner")),
setup_global_tasks_(std::move(setup_global_tasks)),
startup_data_(startup_data),
channel_(channel),
catch_exceptions_(catch_exceptions),
ready_semaphore_(ready_semaphore),
data_(nullptr),
......@@ -47,13 +57,8 @@ TaskRunner::TaskRunner(IsolateData::SetupGlobalTasks setup_global_tasks,
TaskRunner::~TaskRunner() { Join(); }
void TaskRunner::Run() {
data_.reset(
new IsolateData(this, std::move(setup_global_tasks_), startup_data_));
v8::Isolate::Scope isolate_scope(isolate());
v8::HandleScope handle_scope(isolate());
default_context_group_id_ = data_->CreateContextGroup();
data_.reset(new IsolateData(this, std::move(setup_global_tasks_),
startup_data_, channel_));
if (ready_semaphore_) ready_semaphore_->Signal();
RunMessageLoop(false);
}
......@@ -66,7 +71,7 @@ void TaskRunner::RunMessageLoop(bool only_protocol) {
v8::Isolate::Scope isolate_scope(isolate());
if (catch_exceptions_) {
v8::TryCatch try_catch(isolate());
task->RunOnTaskRunner(this);
task->RunOnIsolate(data_.get());
delete task;
if (try_catch.HasCaught()) {
ReportUncaughtException(isolate(), try_catch);
......@@ -75,7 +80,7 @@ void TaskRunner::RunMessageLoop(bool only_protocol) {
_exit(0);
}
} else {
task->RunOnTaskRunner(this);
task->RunOnIsolate(data_.get());
delete task;
}
}
......@@ -115,44 +120,45 @@ TaskRunner::Task* TaskRunner::GetNext(bool only_protocol) {
return nullptr;
}
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);
}
AsyncTask::AsyncTask(IsolateData* data, const char* task_name)
: instrumenting_(data && task_name) {
if (!instrumenting_) return;
data->inspector()->inspector()->asyncTaskScheduled(
v8_inspector::StringView(reinterpret_cast<const uint8_t*>(task_name),
strlen(task_name)),
this, false);
}
void AsyncTask::Run() {
if (inspector_) inspector_->asyncTaskStarted(this);
if (instrumenting_) data()->inspector()->inspector()->asyncTaskStarted(this);
AsyncRun();
if (inspector_) inspector_->asyncTaskFinished(this);
if (instrumenting_) data()->inspector()->inspector()->asyncTaskFinished(this);
}
ExecuteStringTask::ExecuteStringTask(
IsolateData* data, int context_group_id, const char* task_name,
const v8::internal::Vector<uint16_t>& expression,
v8::Local<v8::String> name, v8::Local<v8::Integer> line_offset,
v8::Local<v8::Integer> column_offset, v8::Local<v8::Boolean> is_module,
const char* task_name, v8_inspector::V8Inspector* inspector)
: AsyncTask(task_name, inspector),
v8::Local<v8::Integer> column_offset, v8::Local<v8::Boolean> is_module)
: AsyncTask(data, task_name),
expression_(expression),
name_(ToVector(name)),
line_offset_(line_offset.As<v8::Int32>()->Value()),
column_offset_(column_offset.As<v8::Int32>()->Value()),
is_module_(is_module->Value()) {}
is_module_(is_module->Value()),
context_group_id_(context_group_id) {}
ExecuteStringTask::ExecuteStringTask(
const v8::internal::Vector<const char>& expression)
: AsyncTask(nullptr, nullptr), expression_utf8_(expression) {}
const v8::internal::Vector<const char>& expression, int context_group_id)
: AsyncTask(nullptr, nullptr),
expression_utf8_(expression),
context_group_id_(context_group_id) {}
void ExecuteStringTask::AsyncRun() {
v8::MicrotasksScope microtasks_scope(isolate(),
v8::MicrotasksScope::kRunMicrotasks);
v8::HandleScope handle_scope(isolate());
v8::Local<v8::Context> context = default_context();
v8::Local<v8::Context> context = data()->GetContext(context_group_id_);
v8::Context::Scope context_scope(context);
v8::Local<v8::String> name =
......@@ -193,7 +199,6 @@ void ExecuteStringTask::AsyncRun() {
v8::MaybeLocal<v8::Value> result;
result = script->Run(context);
} else {
IsolateData::FromContext(context)->RegisterModule(context, name_,
&scriptSource);
data()->RegisterModule(context, name_, &scriptSource);
}
}
......@@ -23,30 +23,27 @@ class TaskRunner : public v8::base::Thread {
public:
virtual ~Task() {}
virtual bool is_inspector_task() = 0;
void RunOnTaskRunner(TaskRunner* task_runner) {
task_runner_ = task_runner;
void RunOnIsolate(IsolateData* data) {
data_ = data;
Run();
task_runner_ = nullptr;
data_ = nullptr;
}
protected:
virtual void Run() = 0;
v8::Isolate* isolate() const { return task_runner_->data_->isolate(); }
v8::Local<v8::Context> default_context() const {
return task_runner_->data_->GetContext(
task_runner_->default_context_group_id_);
}
v8::Isolate* isolate() const { return data_->isolate(); }
IsolateData* data() const { return data_; }
private:
TaskRunner* task_runner_ = nullptr;
IsolateData* data_ = nullptr;
};
TaskRunner(IsolateData::SetupGlobalTasks setup_global_tasks,
bool catch_exceptions, v8::base::Semaphore* ready_semaphore,
v8::StartupData* startup_data);
v8::StartupData* startup_data,
InspectorClientImpl::FrontendChannel* channel);
virtual ~TaskRunner();
IsolateData* data() const { return data_.get(); }
int default_context_group_id() const { return default_context_group_id_; }
// Thread implementation.
void Run() override;
......@@ -66,10 +63,10 @@ class TaskRunner : public v8::base::Thread {
IsolateData::SetupGlobalTasks setup_global_tasks_;
v8::StartupData* startup_data_;
InspectorClientImpl::FrontendChannel* channel_;
bool catch_exceptions_;
v8::base::Semaphore* ready_semaphore_;
std::unique_ptr<IsolateData> data_;
int default_context_group_id_;
// deferred_queue_ combined with queue_ (in this order) have all tasks in the
// correct order. Sometimes we skip non-protocol tasks by moving them from
......@@ -87,26 +84,27 @@ class TaskRunner : public v8::base::Thread {
class AsyncTask : public TaskRunner::Task {
public:
AsyncTask(const char* task_name, v8_inspector::V8Inspector* inspector);
AsyncTask(IsolateData* data, const char* task_name);
virtual ~AsyncTask() = default;
protected:
virtual void AsyncRun() = 0;
void Run() override;
v8_inspector::V8Inspector* inspector_;
bool instrumenting_;
};
class ExecuteStringTask : public AsyncTask {
public:
ExecuteStringTask(const v8::internal::Vector<uint16_t>& expression,
ExecuteStringTask(IsolateData* data, int context_group_id,
const char* task_name,
const v8::internal::Vector<uint16_t>& expression,
v8::Local<v8::String> name,
v8::Local<v8::Integer> line_offset,
v8::Local<v8::Integer> column_offset,
v8::Local<v8::Boolean> is_module, const char* task_name,
v8_inspector::V8Inspector* inspector);
explicit ExecuteStringTask(
const v8::internal::Vector<const char>& expression);
v8::Local<v8::Boolean> is_module);
ExecuteStringTask(const v8::internal::Vector<const char>& expression,
int context_group_id);
bool is_inspector_task() override { return false; }
private:
......@@ -118,6 +116,7 @@ class ExecuteStringTask : public AsyncTask {
int32_t line_offset_ = 0;
int32_t column_offset_ = 0;
bool is_module_ = false;
int context_group_id_;
DISALLOW_COPY_AND_ASSIGN(ExecuteStringTask);
};
......
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