Commit e502665d authored by kozyatinskiy's avatar kozyatinskiy Committed by Commit bot

[inspector] added createContextGroup for tests

BUG=none
R=dgozman@chromium.org

Review-Url: https://codereview.chromium.org/2737603006
Cr-Commit-Position: refs/heads/master@{#43657}
parent 07ada64a
......@@ -124,6 +124,33 @@ class DisconnectTask : public TaskRunner::Task {
InspectorClientImpl* client_;
};
class CreateContextGroupTask : public TaskRunner::Task {
public:
CreateContextGroupTask(InspectorClientImpl* client,
v8::ExtensionConfiguration* extensions,
v8::base::Semaphore* ready_semaphore,
int* context_group_id)
: client_(client),
extensions_(extensions),
ready_semaphore_(ready_semaphore),
context_group_id_(context_group_id) {}
virtual ~CreateContextGroupTask() = default;
bool is_inspector_task() final { return true; }
void Run(v8::Isolate* isolate,
const v8::Global<v8::Context>& global_context) {
*context_group_id_ = client_->createContextGroup(extensions_);
if (ready_semaphore_) ready_semaphore_->Signal();
}
private:
InspectorClientImpl* client_;
v8::ExtensionConfiguration* extensions_;
v8::base::Semaphore* ready_semaphore_;
int* context_group_id_;
};
InspectorClientImpl::InspectorClientImpl(TaskRunner* task_runner,
FrontendChannel* frontend_channel,
v8::base::Semaphore* ready_semaphore)
......@@ -139,16 +166,30 @@ void InspectorClientImpl::connect(v8::Local<v8::Context> context) {
isolate_ = context->GetIsolate();
isolate_->AddMessageListener(MessageHandler);
channel_.reset(new ChannelImpl(frontend_channel_));
inspector_ = v8_inspector::V8Inspector::create(isolate_, this);
v8_inspector::StringView state =
state_ ? state_->string() : v8_inspector::StringView();
session_ = inspector_->connect(1, channel_.get(), state);
context->SetAlignedPointerInEmbedderData(kInspectorClientIndex, this);
inspector_->contextCreated(
v8_inspector::V8ContextInfo(context, 1, v8_inspector::StringView()));
context_.Reset(isolate_, context);
if (states_.empty()) {
int context_group_id = TaskRunner::GetContextGroupId(context);
v8_inspector::StringView state;
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()));
} else {
for (const auto& it : states_) {
int context_group_id = it.first;
v8::Local<v8::Context> context =
task_runner_->GetContext(context_group_id);
v8_inspector::StringView state = it.second->string();
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()));
}
}
states_.clear();
}
void InspectorClientImpl::scheduleReconnect(
......@@ -158,8 +199,31 @@ void InspectorClientImpl::scheduleReconnect(
}
void InspectorClientImpl::disconnect() {
state_ = session_->stateJSON();
session_.reset();
for (const auto& it : sessions_) {
states_[it.first] = it.second->stateJSON();
}
sessions_.clear();
}
void InspectorClientImpl::scheduleCreateContextGroup(
v8::ExtensionConfiguration* extensions,
v8::base::Semaphore* ready_semaphore, int* context_group_id) {
task_runner_->Append(new CreateContextGroupTask(
this, extensions, ready_semaphore, context_group_id));
}
int InspectorClientImpl::createContextGroup(
v8::ExtensionConfiguration* extensions) {
v8::HandleScope handle_scope(isolate_);
v8::Local<v8::Context> context = task_runner_->NewContextGroup();
context->SetAlignedPointerInEmbedderData(kInspectorClientIndex, this);
int context_group_id = TaskRunner::GetContextGroupId(context);
v8_inspector::StringView state;
sessions_[context_group_id] =
inspector_->connect(context_group_id, channel_.get(), state);
inspector_->contextCreated(v8_inspector::V8ContextInfo(
context, context_group_id, v8_inspector::StringView()));
return context_group_id;
}
bool InspectorClientImpl::formatAccessorsAsProperties(
......@@ -176,9 +240,10 @@ bool InspectorClientImpl::formatAccessorsAsProperties(
.FromMaybe(false);
}
v8::Local<v8::Context> InspectorClientImpl::ensureDefaultContextInGroup(int) {
v8::Local<v8::Context> InspectorClientImpl::ensureDefaultContextInGroup(
int context_group_id) {
CHECK(isolate_);
return context_.Get(isolate_);
return task_runner_->GetContext(context_group_id);
}
void InspectorClientImpl::setCurrentTimeMSForTest(double time) {
......@@ -206,14 +271,24 @@ v8_inspector::V8Inspector* InspectorClientImpl::InspectorFromContext(
v8_inspector::V8InspectorSession* InspectorClientImpl::SessionFromContext(
v8::Local<v8::Context> context) {
return InspectorClientFromContext(context)->session_.get();
int context_group_id = TaskRunner::GetContextGroupId(context);
return InspectorClientFromContext(context)->sessions_[context_group_id].get();
}
v8_inspector::V8InspectorSession* InspectorClientImpl::session(
int context_group_id) {
if (context_group_id) {
return sessions_[context_group_id].get();
} else {
return sessions_.begin()->second.get();
}
}
class SendMessageToBackendTask : public TaskRunner::Task {
public:
explicit SendMessageToBackendTask(
const v8::internal::Vector<uint16_t>& message)
: message_(message) {}
const v8::internal::Vector<uint16_t>& message, int context_group_id)
: message_(message), context_group_id_(context_group_id) {}
bool is_inspector_task() final { return true; }
......@@ -223,7 +298,13 @@ class SendMessageToBackendTask : public TaskRunner::Task {
{
v8::HandleScope handle_scope(isolate);
v8::Local<v8::Context> context = global_context.Get(isolate);
session = InspectorClientImpl::SessionFromContext(context);
if (!context_group_id_) {
session = InspectorClientImpl::SessionFromContext(context);
} else {
session = InspectorClientFromContext(context)
->sessions_[context_group_id_]
.get();
}
CHECK(session);
}
v8_inspector::StringView message_view(message_.start(), message_.length());
......@@ -232,6 +313,7 @@ class SendMessageToBackendTask : public TaskRunner::Task {
private:
v8::internal::Vector<uint16_t> message_;
int context_group_id_;
};
TaskRunner* SendMessageToBackendExtension::backend_task_runner_ = nullptr;
......@@ -246,7 +328,8 @@ SendMessageToBackendExtension::GetNativeFunctionTemplate(
void SendMessageToBackendExtension::SendMessageToBackend(
const v8::FunctionCallbackInfo<v8::Value>& args) {
CHECK(backend_task_runner_);
CHECK(args.Length() == 1 && args[0]->IsString());
CHECK(args.Length() == 2 && args[0]->IsString() && args[1]->IsInt32());
v8::Local<v8::String> message = args[0].As<v8::String>();
backend_task_runner_->Append(new SendMessageToBackendTask(ToVector(message)));
backend_task_runner_->Append(new SendMessageToBackendTask(
ToVector(message), args[1].As<v8::Int32>()->Value()));
}
......@@ -26,15 +26,19 @@ class InspectorClientImpl : public v8_inspector::V8InspectorClient {
virtual ~InspectorClientImpl();
void scheduleReconnect(v8::base::Semaphore* ready_semaphore);
void scheduleCreateContextGroup(v8::ExtensionConfiguration* extensions,
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);
void setCurrentTimeMSForTest(double time);
// context_group_id = 0 means default context group.
v8_inspector::V8InspectorSession* session(int context_group_id = 0);
v8_inspector::V8InspectorSession* session() const { return session_.get(); }
void setCurrentTimeMSForTest(double time);
private:
// V8InspectorClient implementation.
......@@ -51,14 +55,16 @@ class InspectorClientImpl : public v8_inspector::V8InspectorClient {
void connect(v8::Local<v8::Context> context);
friend class DisconnectTask;
void disconnect();
friend class CreateContextGroupTask;
int createContextGroup(v8::ExtensionConfiguration* extensions);
std::unique_ptr<v8_inspector::V8Inspector> inspector_;
std::unique_ptr<v8_inspector::V8InspectorSession> session_;
std::unique_ptr<v8_inspector::V8Inspector::Channel> channel_;
std::unique_ptr<v8_inspector::StringBuffer> state_;
std::map<int, std::unique_ptr<v8_inspector::V8InspectorSession>> sessions_;
std::map<int, std::unique_ptr<v8_inspector::StringBuffer>> states_;
v8::Isolate* isolate_;
v8::Global<v8::Context> context_;
TaskRunner* task_runner_;
FrontendChannel* frontend_channel_;
......
......@@ -59,7 +59,8 @@ class UtilsExtension : public v8::Extension {
"native function setCurrentTimeMSForTest();"
"native function schedulePauseOnNextStatement();"
"native function cancelPauseOnNextStatement();"
"native function reconnect();") {}
"native function reconnect();"
"native function createContextGroup();") {}
virtual v8::Local<v8::FunctionTemplate> GetNativeFunctionTemplate(
v8::Isolate* isolate, v8::Local<v8::String> name) {
v8::Local<v8::Context> context = isolate->GetCurrentContext();
......@@ -127,6 +128,13 @@ class UtilsExtension : public v8::Extension {
.ToLocalChecked())
.FromJust()) {
return v8::FunctionTemplate::New(isolate, UtilsExtension::Reconnect);
} else if (name->Equals(context, v8::String::NewFromUtf8(
isolate, "createContextGroup",
v8::NewStringType::kNormal)
.ToLocalChecked())
.FromJust()) {
return v8::FunctionTemplate::New(isolate,
UtilsExtension::CreateContextGroup);
}
return v8::Local<v8::FunctionTemplate>();
}
......@@ -280,6 +288,7 @@ class UtilsExtension : public v8::Extension {
fprintf(stderr, "Internal error: cancelPauseOnNextStatement().");
Exit();
}
v8::Local<v8::Context> context = args.GetIsolate()->GetCurrentContext();
inspector_client_->session()->cancelPauseOnNextStatement();
}
......@@ -292,6 +301,25 @@ class UtilsExtension : public v8::Extension {
inspector_client_->scheduleReconnect(&ready_semaphore);
ready_semaphore.Wait();
}
static void CreateContextGroup(
const v8::FunctionCallbackInfo<v8::Value>& args) {
if (args.Length() != 0) {
fprintf(stderr, "Internal error: createContextGroup().");
Exit();
}
const char* backend_extensions[] = {"v8_inspector/setTimeout",
"v8_inspector/inspector"};
v8::ExtensionConfiguration backend_configuration(
arraysize(backend_extensions), backend_extensions);
v8::base::Semaphore ready_semaphore(0);
int context_group_id = 0;
inspector_client_->scheduleCreateContextGroup(
&backend_configuration, &ready_semaphore, &context_group_id);
ready_semaphore.Wait();
args.GetReturnValue().Set(
v8::Int32::New(args.GetIsolate(), context_group_id));
}
};
TaskRunner* UtilsExtension::backend_runner_ = nullptr;
......
......@@ -15,7 +15,7 @@ Protocol = new Proxy({}, {
const eventPattern = /^on(ce)?([A-Z][A-Za-z0-9]+)/;
var match = eventPattern.exec(methodName);
if (!match) {
return (args) => InspectorTest._sendCommandPromise(`${agentName}.${methodName}`, args || {});
return (args, contextGroupId) => InspectorTest._sendCommandPromise(`${agentName}.${methodName}`, args || {}, contextGroupId);
} else {
var eventName = match[2];
eventName = eventName.charAt(0).toLowerCase() + eventName.slice(1);
......@@ -52,6 +52,8 @@ var utils = {};
this.cancelPauseOnNextStatement = null;
utils.reconnect = reconnect;
this.reconnect = null;
utils.createContextGroup = createContextGroup;
this.createContextGroup = null;
})();
InspectorTest.log = utils.print.bind(null);
......@@ -205,12 +207,12 @@ InspectorTest.startDumpingProtocolMessages = function()
InspectorTest._dumpInspectorProtocolMessages = true;
}
InspectorTest.sendRawCommand = function(requestId, command, handler)
InspectorTest.sendRawCommand = function(requestId, command, handler, contextGroupId)
{
if (InspectorTest._dumpInspectorProtocolMessages)
utils.print("frontend: " + command);
InspectorTest._dispatchTable.set(requestId, handler);
sendMessageToBackend(command);
sendMessageToBackend(command, contextGroupId || 0);
}
InspectorTest.checkExpectation = function(fail, name, messageObject)
......@@ -256,13 +258,13 @@ InspectorTest.runAsyncTestSuite = async function(testSuite) {
InspectorTest.completeTest();
}
InspectorTest._sendCommandPromise = function(method, params)
InspectorTest._sendCommandPromise = function(method, params, contextGroupId)
{
var requestId = ++InspectorTest._requestId;
var messageObject = { "id": requestId, "method": method, "params": params };
var fulfillCallback;
var promise = new Promise(fulfill => fulfillCallback = fulfill);
InspectorTest.sendRawCommand(requestId, JSON.stringify(messageObject), fulfillCallback);
InspectorTest.sendRawCommand(requestId, JSON.stringify(messageObject), fulfillCallback, contextGroupId);
return promise;
}
......
Checks createContext().
{
method : Runtime.executionContextCreated
params : {
context : {
id : 1
name :
origin :
}
}
}
{
method : Runtime.executionContextCreated
params : {
context : {
id : 2
name :
origin :
}
}
}
{
id : <messageId>
result : {
}
}
#debugger;
setTimeout(#x => x * 3, 0)
Reported script's execution id: 2
{
method : Runtime.executionContextCreated
params : {
context : {
id : 1
name :
origin :
}
}
}
{
method : Runtime.executionContextCreated
params : {
context : {
id : 2
name :
origin :
}
}
}
#debugger;
#debugger;
setTimeout(#x => x * 3, 0)
Reported script's execution id: 2
// Copyright 2017 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
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;
Protocol.Runtime.enable()
.then(() => contextGroupId = utils.createContextGroup())
.then(() => Protocol.Runtime.enable({}, contextGroupId))
.then(() => Protocol.Debugger.enable())
.then(() => Protocol.Debugger.enable({}, contextGroupId))
.then(InspectorTest.logMessage)
.then(() => {
Protocol.Runtime.evaluate({ expression: 'debugger;' })
Protocol.Runtime.evaluate({ expression: 'setTimeout(x => x * 2, 0)' }, contextGroupId);
Protocol.Runtime.evaluate({ expression: 'setTimeout(x => x * 3, 0)' });
})
.then(() => InspectorTest.waitPendingTasks())
.then(() => {
InspectorTest.log(`Reported script's execution id: ${executionContextIds.size}`);
executionContextIds.clear();
})
.then(() => utils.reconnect())
.then(() => {
Protocol.Runtime.evaluate({ expression: 'debugger;' })
Protocol.Runtime.evaluate({ expression: 'setTimeout(x => x * 2, 0)' }, contextGroupId);
Protocol.Runtime.evaluate({ expression: 'setTimeout(x => x * 3, 0)' });
})
.then(() => InspectorTest.waitPendingTasks())
.then(() => Protocol.Debugger.disable({}, contextGroupId))
.then(() => Protocol.Debugger.disable({}))
.then(() => InspectorTest.log(`Reported script's execution id: ${executionContextIds.size}`))
.then(InspectorTest.completeTest);
......@@ -13,6 +13,7 @@
namespace {
const int kTaskRunnerIndex = 2;
const int kContextGroupIdIndex = 3;
void ReportUncaughtException(v8::Isolate* isolate,
const v8::TryCatch& try_catch) {
......@@ -46,7 +47,7 @@ TaskRunner::TaskRunner(v8::ExtensionConfiguration* extensions,
TaskRunner::~TaskRunner() { Join(); }
void TaskRunner::InitializeContext() {
void TaskRunner::InitializeIsolate() {
v8::Isolate::CreateParams params;
params.array_buffer_allocator =
v8::ArrayBuffer::Allocator::NewDefaultAllocator();
......@@ -54,19 +55,36 @@ void TaskRunner::InitializeContext() {
isolate_->SetMicrotasksPolicy(v8::MicrotasksPolicy::kScoped);
v8::Isolate::Scope isolate_scope(isolate_);
v8::HandleScope handle_scope(isolate_);
NewContextGroup();
if (ready_semaphore_) ready_semaphore_->Signal();
}
v8::Local<v8::Context> TaskRunner::NewContextGroup() {
v8::Local<v8::ObjectTemplate> global_template =
v8::ObjectTemplate::New(isolate_);
v8::Local<v8::Context> context =
v8::Context::New(isolate_, extensions_, global_template);
context->SetAlignedPointerInEmbedderData(kTaskRunnerIndex, this);
context_.Reset(isolate_, context);
intptr_t 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);
return context;
}
if (ready_semaphore_) ready_semaphore_->Signal();
v8::Local<v8::Context> TaskRunner::GetContext(int context_group_id) {
return contexts_[context_group_id].Get(isolate_);
}
int TaskRunner::GetContextGroupId(v8::Local<v8::Context> context) {
return reinterpret_cast<intptr_t>(
context->GetAlignedPointerFromEmbedderData(kContextGroupIdIndex)) /
2;
}
void TaskRunner::Run() {
InitializeContext();
InitializeIsolate();
RunMessageLoop(false);
}
......@@ -78,7 +96,7 @@ void TaskRunner::RunMessageLoop(bool only_protocol) {
v8::Isolate::Scope isolate_scope(isolate_);
if (catch_exceptions_) {
v8::TryCatch try_catch(isolate_);
task->Run(isolate_, context_);
task->Run(isolate_, contexts_.begin()->second);
delete task;
if (try_catch.HasCaught()) {
ReportUncaughtException(isolate_, try_catch);
......@@ -87,7 +105,7 @@ void TaskRunner::RunMessageLoop(bool only_protocol) {
_exit(0);
}
} else {
task->Run(isolate_, context_);
task->Run(isolate_, contexts_.begin()->second);
delete task;
}
}
......
......@@ -52,6 +52,10 @@ class TaskRunner : public v8::base::Thread {
static TaskRunner* FromContext(v8::Local<v8::Context>);
v8::Local<v8::Context> NewContextGroup();
v8::Local<v8::Context> GetContext(int context_group_id);
static int GetContextGroupId(v8::Local<v8::Context> context);
void Terminate();
void RegisterModule(v8::internal::Vector<uint16_t> name,
......@@ -61,7 +65,7 @@ class TaskRunner : public v8::base::Thread {
v8::Local<v8::Module> referrer);
private:
void InitializeContext();
void InitializeIsolate();
Task* GetNext(bool only_protocol);
v8::ExtensionConfiguration* extensions_;
......@@ -69,7 +73,8 @@ class TaskRunner : public v8::base::Thread {
v8::base::Semaphore* ready_semaphore_;
v8::Isolate* isolate_;
v8::Global<v8::Context> context_;
intptr_t last_context_group_id_ = 0;
std::map<intptr_t, v8::Global<v8::Context>> contexts_;
// 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
......
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