Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(418)

Side by Side Diff: test/inspector/inspector-impl.cc

Issue 2890463004: [inspector] Refactor inspector test (Closed)
Patch Set: better crash fix Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « test/inspector/inspector-impl.h ('k') | test/inspector/inspector-test.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2016 the V8 project authors. All rights reserved. 1 // Copyright 2016 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "test/inspector/inspector-impl.h" 5 #include "test/inspector/inspector-impl.h"
6 6
7 #include "include/v8.h" 7 #include "include/v8.h"
8 8
9 #include "src/vector.h" 9 #include "src/vector.h"
10 #include "test/inspector/isolate-data.h"
11 #include "test/inspector/task-runner.h"
10 12
11 namespace { 13 namespace {
12 14
13 const int kInspectorClientIndex = 0;
14
15 class ChannelImpl final : public v8_inspector::V8Inspector::Channel { 15 class ChannelImpl final : public v8_inspector::V8Inspector::Channel {
16 public: 16 public:
17 explicit ChannelImpl(InspectorClientImpl::FrontendChannel* frontend_channel) 17 ChannelImpl(InspectorClientImpl::FrontendChannel* frontend_channel,
18 : frontend_channel_(frontend_channel) {} 18 int session_id)
19 : frontend_channel_(frontend_channel), session_id_(session_id) {}
19 virtual ~ChannelImpl() = default; 20 virtual ~ChannelImpl() = default;
20 21
21 private: 22 private:
22 void sendResponse( 23 void sendResponse(
23 int callId, 24 int callId,
24 std::unique_ptr<v8_inspector::StringBuffer> message) override { 25 std::unique_ptr<v8_inspector::StringBuffer> message) override {
25 frontend_channel_->SendMessageToFrontend(message->string()); 26 frontend_channel_->SendMessageToFrontend(session_id_, message->string());
26 } 27 }
27 void sendNotification( 28 void sendNotification(
28 std::unique_ptr<v8_inspector::StringBuffer> message) override { 29 std::unique_ptr<v8_inspector::StringBuffer> message) override {
29 frontend_channel_->SendMessageToFrontend(message->string()); 30 frontend_channel_->SendMessageToFrontend(session_id_, message->string());
30 } 31 }
31 void flushProtocolNotifications() override {} 32 void flushProtocolNotifications() override {}
32 33
33 InspectorClientImpl::FrontendChannel* frontend_channel_; 34 InspectorClientImpl::FrontendChannel* frontend_channel_;
35 int session_id_;
34 DISALLOW_COPY_AND_ASSIGN(ChannelImpl); 36 DISALLOW_COPY_AND_ASSIGN(ChannelImpl);
35 }; 37 };
36 38
37 InspectorClientImpl* InspectorClientFromContext(
38 v8::Local<v8::Context> context) {
39 InspectorClientImpl* inspector_client = static_cast<InspectorClientImpl*>(
40 context->GetAlignedPointerFromEmbedderData(kInspectorClientIndex));
41 CHECK(inspector_client);
42 return inspector_client;
43 }
44
45 v8::internal::Vector<uint16_t> ToVector(v8::Local<v8::String> str) { 39 v8::internal::Vector<uint16_t> ToVector(v8::Local<v8::String> str) {
46 v8::internal::Vector<uint16_t> buffer = 40 v8::internal::Vector<uint16_t> buffer =
47 v8::internal::Vector<uint16_t>::New(str->Length()); 41 v8::internal::Vector<uint16_t>::New(str->Length());
48 str->Write(buffer.start(), 0, str->Length()); 42 str->Write(buffer.start(), 0, str->Length());
49 return buffer; 43 return buffer;
50 } 44 }
51 45
52 void MessageHandler(v8::Local<v8::Message> message, 46 void MessageHandler(v8::Local<v8::Message> message,
53 v8::Local<v8::Value> exception) { 47 v8::Local<v8::Value> exception) {
54 v8::Isolate* isolate = v8::Isolate::GetCurrent(); 48 v8::Isolate* isolate = v8::Isolate::GetCurrent();
55 v8::Local<v8::Context> context = isolate->GetEnteredContext(); 49 v8::Local<v8::Context> context = isolate->GetEnteredContext();
56 if (context.IsEmpty()) return; 50 if (context.IsEmpty()) return;
57 v8_inspector::V8Inspector* inspector = 51 v8_inspector::V8Inspector* inspector =
58 InspectorClientImpl::InspectorFromContext(context); 52 IsolateData::FromContext(context)->inspector()->inspector();
59 53
60 v8::Local<v8::StackTrace> stack = message->GetStackTrace(); 54 v8::Local<v8::StackTrace> stack = message->GetStackTrace();
61 int script_id = 55 int script_id =
62 static_cast<int>(message->GetScriptOrigin().ScriptID()->Value()); 56 static_cast<int>(message->GetScriptOrigin().ScriptID()->Value());
63 if (!stack.IsEmpty() && stack->GetFrameCount() > 0) { 57 if (!stack.IsEmpty() && stack->GetFrameCount() > 0) {
64 int top_script_id = stack->GetFrame(0)->GetScriptId(); 58 int top_script_id = stack->GetFrame(0)->GetScriptId();
65 if (top_script_id == script_id) script_id = 0; 59 if (top_script_id == script_id) script_id = 0;
66 } 60 }
67 int line_number = message->GetLineNumber(context).FromMaybe(0); 61 int line_number = message->GetLineNumber(context).FromMaybe(0);
68 int column_number = 0; 62 int column_number = 0;
(...skipping 30 matching lines...) Expand all
99 .ToLocalChecked(); 93 .ToLocalChecked();
100 } 94 }
101 95
102 void Print(v8::Isolate* isolate, const v8_inspector::StringView& string) { 96 void Print(v8::Isolate* isolate, const v8_inspector::StringView& string) {
103 v8::Local<v8::String> v8_string = ToString(isolate, string); 97 v8::Local<v8::String> v8_string = ToString(isolate, string);
104 v8::String::Utf8Value utf8_string(v8_string); 98 v8::String::Utf8Value utf8_string(v8_string);
105 fwrite(*utf8_string, sizeof(**utf8_string), utf8_string.length(), stdout); 99 fwrite(*utf8_string, sizeof(**utf8_string), utf8_string.length(), stdout);
106 } 100 }
107 } // namespace 101 } // namespace
108 102
109 class ConnectTask : public TaskRunner::Task { 103 InspectorClientImpl::InspectorClientImpl(v8::Isolate* isolate,
110 public: 104 TaskRunner* task_runner,
111 ConnectTask(InspectorClientImpl* client, v8::base::Semaphore* ready_semaphore) 105 FrontendChannel* frontend_channel)
112 : client_(client), ready_semaphore_(ready_semaphore) {} 106 : task_runner_(task_runner),
113 virtual ~ConnectTask() = default; 107 isolate_(isolate),
114
115 bool is_inspector_task() final { return true; }
116
117 private:
118 void Run() override {
119 v8::HandleScope handle_scope(isolate());
120 client_->connect();
121 if (ready_semaphore_) ready_semaphore_->Signal();
122 }
123
124 InspectorClientImpl* client_;
125 v8::base::Semaphore* ready_semaphore_;
126 };
127
128 class DisconnectTask : public TaskRunner::Task {
129 public:
130 explicit DisconnectTask(InspectorClientImpl* client, bool reset_inspector,
131 v8::base::Semaphore* ready_semaphore)
132 : client_(client),
133 reset_inspector_(reset_inspector),
134 ready_semaphore_(ready_semaphore) {}
135 virtual ~DisconnectTask() = default;
136
137 bool is_inspector_task() final { return true; }
138
139 private:
140 void Run() override {
141 client_->disconnect(reset_inspector_);
142 if (ready_semaphore_) ready_semaphore_->Signal();
143 }
144
145 InspectorClientImpl* client_;
146 bool reset_inspector_;
147 v8::base::Semaphore* ready_semaphore_;
148 };
149
150 class CreateContextGroupTask : public TaskRunner::Task {
151 public:
152 CreateContextGroupTask(InspectorClientImpl* client,
153 IsolateData::SetupGlobalTasks setup_global_tasks,
154 v8::base::Semaphore* ready_semaphore,
155 int* context_group_id)
156 : client_(client),
157 setup_global_tasks_(std::move(setup_global_tasks)),
158 ready_semaphore_(ready_semaphore),
159 context_group_id_(context_group_id) {}
160 virtual ~CreateContextGroupTask() = default;
161
162 bool is_inspector_task() final { return true; }
163
164 private:
165 void Run() override {
166 *context_group_id_ = client_->createContextGroup(setup_global_tasks_);
167 if (ready_semaphore_) ready_semaphore_->Signal();
168 }
169
170 InspectorClientImpl* client_;
171 IsolateData::SetupGlobalTasks setup_global_tasks_;
172 v8::base::Semaphore* ready_semaphore_;
173 int* context_group_id_;
174 };
175
176 InspectorClientImpl::InspectorClientImpl(TaskRunner* task_runner,
177 FrontendChannel* frontend_channel,
178 v8::base::Semaphore* ready_semaphore)
179 : isolate_(nullptr),
180 task_runner_(task_runner),
181 frontend_channel_(frontend_channel) { 108 frontend_channel_(frontend_channel) {
182 task_runner_->Append(new ConnectTask(this, ready_semaphore)); 109 isolate_->AddMessageListener(MessageHandler);
110 inspector_ = v8_inspector::V8Inspector::create(isolate_, this);
183 } 111 }
184 112
185 InspectorClientImpl::~InspectorClientImpl() {} 113 InspectorClientImpl::~InspectorClientImpl() {}
186 114
187 void InspectorClientImpl::connect() { 115 int InspectorClientImpl::ConnectSession(int context_group_id,
188 isolate_ = task_runner_->data()->isolate(); 116 const v8_inspector::StringView& state) {
189 isolate_->AddMessageListener(MessageHandler); 117 int session_id = ++last_session_id_;
190 channel_.reset(new ChannelImpl(frontend_channel_)); 118 channels_[session_id].reset(new ChannelImpl(frontend_channel_, session_id));
191 inspector_ = v8_inspector::V8Inspector::create(isolate_, this); 119 sessions_[session_id] =
192 120 inspector_->connect(context_group_id, channels_[session_id].get(), state);
193 if (states_.empty()) { 121 context_group_by_session_[sessions_[session_id].get()] = context_group_id;
194 ConnectToContextGroup(task_runner_->default_context_group_id(), 122 return session_id;
195 v8_inspector::StringView());
196 } else {
197 for (const auto& it : states_)
198 ConnectToContextGroup(it.first, it.second->string());
199 }
200 states_.clear();
201 } 123 }
202 124
203 void InspectorClientImpl::ConnectToContextGroup( 125 std::unique_ptr<v8_inspector::StringBuffer>
204 int context_group_id, v8_inspector::StringView state) { 126 InspectorClientImpl::DisconnectSession(int session_id) {
205 v8::Local<v8::Context> context = 127 auto it = sessions_.find(session_id);
206 task_runner_->data()->GetContext(context_group_id); 128 CHECK(it != sessions_.end());
207 sessions_[context_group_id] = 129 context_group_by_session_.erase(it->second.get());
208 inspector_->connect(context_group_id, channel_.get(), state); 130 std::unique_ptr<v8_inspector::StringBuffer> result = it->second->stateJSON();
209 context->SetAlignedPointerInEmbedderData(kInspectorClientIndex, this); 131 sessions_.erase(it);
132 channels_.erase(session_id);
133 return result;
134 }
135
136 void InspectorClientImpl::SendMessage(int session_id,
137 const v8_inspector::StringView& message) {
138 auto it = sessions_.find(session_id);
139 if (it != sessions_.end()) it->second->dispatchProtocolMessage(message);
140 }
141
142 void InspectorClientImpl::BreakProgram(
143 int context_group_id, const v8_inspector::StringView& reason,
144 const v8_inspector::StringView& details) {
145 for (int session_id : GetSessionIds(context_group_id)) {
146 auto it = sessions_.find(session_id);
147 if (it != sessions_.end()) it->second->breakProgram(reason, details);
148 }
149 }
150
151 void InspectorClientImpl::SchedulePauseOnNextStatement(
152 int context_group_id, const v8_inspector::StringView& reason,
153 const v8_inspector::StringView& details) {
154 for (int session_id : GetSessionIds(context_group_id)) {
155 auto it = sessions_.find(session_id);
156 if (it != sessions_.end())
157 it->second->schedulePauseOnNextStatement(reason, details);
158 }
159 }
160
161 void InspectorClientImpl::CancelPauseOnNextStatement(int context_group_id) {
162 for (int session_id : GetSessionIds(context_group_id)) {
163 auto it = sessions_.find(session_id);
164 if (it != sessions_.end()) it->second->cancelPauseOnNextStatement();
165 }
166 }
167
168 void InspectorClientImpl::ContextCreated(v8::Local<v8::Context> context,
169 int context_group_id) {
210 v8_inspector::V8ContextInfo info(context, context_group_id, 170 v8_inspector::V8ContextInfo info(context, context_group_id,
211 v8_inspector::StringView()); 171 v8_inspector::StringView());
212 info.hasMemoryOnConsole = true; 172 info.hasMemoryOnConsole = true;
213 inspector_->contextCreated(info); 173 inspector_->contextCreated(info);
214 } 174 }
215 175
216 void InspectorClientImpl::scheduleReconnect( 176 void InspectorClientImpl::ContextDestroyed(v8::Local<v8::Context> context) {
217 v8::base::Semaphore* ready_semaphore) { 177 inspector_->contextDestroyed(context);
218 task_runner_->Append(
219 new DisconnectTask(this, /* reset_inspector */ true, nullptr));
220 task_runner_->Append(new ConnectTask(this, ready_semaphore));
221 } 178 }
222 179
223 void InspectorClientImpl::scheduleDisconnect( 180 std::vector<int> InspectorClientImpl::GetSessionIds(int context_group_id) {
224 v8::base::Semaphore* ready_semaphore) { 181 std::vector<int> result;
225 task_runner_->Append( 182 for (auto& it : sessions_) {
226 new DisconnectTask(this, /* reset_inspector */ false, ready_semaphore)); 183 if (context_group_by_session_[it.second.get()] == context_group_id)
227 } 184 result.push_back(it.first);
228
229 void InspectorClientImpl::disconnect(bool reset_inspector) {
230 for (const auto& it : sessions_) {
231 states_[it.first] = it.second->stateJSON();
232 } 185 }
233 sessions_.clear(); 186 return result;
234 if (reset_inspector) inspector_.reset();
235 }
236
237 void InspectorClientImpl::scheduleCreateContextGroup(
238 IsolateData::SetupGlobalTasks setup_global_tasks,
239 v8::base::Semaphore* ready_semaphore, int* context_group_id) {
240 task_runner_->Append(new CreateContextGroupTask(
241 this, std::move(setup_global_tasks), ready_semaphore, context_group_id));
242 }
243
244 int InspectorClientImpl::createContextGroup(
245 const IsolateData::SetupGlobalTasks& setup_global_tasks) {
246 v8::HandleScope handle_scope(isolate_);
247 int context_group_id = task_runner_->data()->CreateContextGroup();
248 v8::Local<v8::Context> context =
249 task_runner_->data()->GetContext(context_group_id);
250 context->SetAlignedPointerInEmbedderData(kInspectorClientIndex, this);
251 v8_inspector::StringView state;
252 sessions_[context_group_id] =
253 inspector_->connect(context_group_id, channel_.get(), state);
254 inspector_->contextCreated(v8_inspector::V8ContextInfo(
255 context, context_group_id, v8_inspector::StringView()));
256 return context_group_id;
257 } 187 }
258 188
259 bool InspectorClientImpl::formatAccessorsAsProperties( 189 bool InspectorClientImpl::formatAccessorsAsProperties(
260 v8::Local<v8::Value> object) { 190 v8::Local<v8::Value> object) {
261 v8::Isolate* isolate = v8::Isolate::GetCurrent(); 191 v8::Isolate* isolate = v8::Isolate::GetCurrent();
262 v8::Local<v8::Context> context = isolate->GetCurrentContext(); 192 v8::Local<v8::Context> context = isolate->GetCurrentContext();
263 v8::Local<v8::Private> shouldFormatAccessorsPrivate = v8::Private::ForApi( 193 v8::Local<v8::Private> shouldFormatAccessorsPrivate = v8::Private::ForApi(
264 isolate, v8::String::NewFromUtf8(isolate, "allowAccessorFormatting", 194 isolate, v8::String::NewFromUtf8(isolate, "allowAccessorFormatting",
265 v8::NewStringType::kNormal) 195 v8::NewStringType::kNormal)
266 .ToLocalChecked()); 196 .ToLocalChecked());
267 CHECK(object->IsObject()); 197 CHECK(object->IsObject());
268 return object.As<v8::Object>() 198 return object.As<v8::Object>()
269 ->HasPrivate(context, shouldFormatAccessorsPrivate) 199 ->HasPrivate(context, shouldFormatAccessorsPrivate)
270 .FromMaybe(false); 200 .FromMaybe(false);
271 } 201 }
272 202
273 v8::Local<v8::Context> InspectorClientImpl::ensureDefaultContextInGroup( 203 v8::Local<v8::Context> InspectorClientImpl::ensureDefaultContextInGroup(
274 int context_group_id) { 204 int context_group_id) {
275 CHECK(isolate_); 205 CHECK(isolate_);
276 return task_runner_->data()->GetContext(context_group_id); 206 return task_runner_->data()->GetContext(context_group_id);
277 } 207 }
278 208
279 void InspectorClientImpl::setCurrentTimeMSForTest(double time) { 209 void InspectorClientImpl::SetCurrentTimeMSForTest(double time) {
280 current_time_ = time; 210 current_time_ = time;
281 current_time_set_for_test_ = true; 211 current_time_set_for_test_ = true;
282 } 212 }
283 213
284 double InspectorClientImpl::currentTimeMS() { 214 double InspectorClientImpl::currentTimeMS() {
285 if (current_time_set_for_test_) return current_time_; 215 if (current_time_set_for_test_) return current_time_;
286 return v8::base::OS::TimeCurrentMillis(); 216 return v8::base::OS::TimeCurrentMillis();
287 } 217 }
288 218
289 void InspectorClientImpl::setMemoryInfoForTest( 219 void InspectorClientImpl::SetMemoryInfoForTest(
290 v8::Local<v8::Value> memory_info) { 220 v8::Local<v8::Value> memory_info) {
291 memory_info_.Reset(isolate_, memory_info); 221 memory_info_.Reset(isolate_, memory_info);
292 } 222 }
293 223
294 void InspectorClientImpl::setLogConsoleApiMessageCalls(bool log) { 224 void InspectorClientImpl::SetLogConsoleApiMessageCalls(bool log) {
295 log_console_api_message_calls_ = log; 225 log_console_api_message_calls_ = log;
296 } 226 }
297 227
298 v8::MaybeLocal<v8::Value> InspectorClientImpl::memoryInfo( 228 v8::MaybeLocal<v8::Value> InspectorClientImpl::memoryInfo(
299 v8::Isolate* isolate, v8::Local<v8::Context>) { 229 v8::Isolate* isolate, v8::Local<v8::Context>) {
300 if (memory_info_.IsEmpty()) return v8::MaybeLocal<v8::Value>(); 230 if (memory_info_.IsEmpty()) return v8::MaybeLocal<v8::Value>();
301 return memory_info_.Get(isolate); 231 return memory_info_.Get(isolate);
302 } 232 }
303 233
304 void InspectorClientImpl::runMessageLoopOnPause(int) { 234 void InspectorClientImpl::runMessageLoopOnPause(int) {
(...skipping 10 matching lines...) Expand all
315 const v8_inspector::StringView& url, unsigned lineNumber, 245 const v8_inspector::StringView& url, unsigned lineNumber,
316 unsigned columnNumber, v8_inspector::V8StackTrace* stack) { 246 unsigned columnNumber, v8_inspector::V8StackTrace* stack) {
317 if (!log_console_api_message_calls_) return; 247 if (!log_console_api_message_calls_) return;
318 Print(isolate_, message); 248 Print(isolate_, message);
319 fprintf(stdout, " ("); 249 fprintf(stdout, " (");
320 Print(isolate_, url); 250 Print(isolate_, url);
321 fprintf(stdout, ":%d:%d)", lineNumber, columnNumber); 251 fprintf(stdout, ":%d:%d)", lineNumber, columnNumber);
322 Print(isolate_, stack->toString()->string()); 252 Print(isolate_, stack->toString()->string());
323 fprintf(stdout, "\n"); 253 fprintf(stdout, "\n");
324 } 254 }
325
326 v8_inspector::V8Inspector* InspectorClientImpl::InspectorFromContext(
327 v8::Local<v8::Context> context) {
328 return InspectorClientFromContext(context)->inspector_.get();
329 }
330
331 v8_inspector::V8InspectorSession* InspectorClientImpl::SessionFromContext(
332 v8::Local<v8::Context> context) {
333 InspectorClientImpl* client = InspectorClientFromContext(context);
334 for (auto& it : client->sessions_) {
335 if (client->task_runner_->data()->GetContext(it.first) == context)
336 return it.second.get();
337 }
338 return nullptr;
339 }
340
341 v8_inspector::V8InspectorSession* InspectorClientImpl::session(
342 int context_group_id) {
343 if (context_group_id) {
344 return sessions_[context_group_id].get();
345 } else {
346 return sessions_.begin()->second.get();
347 }
348 }
349
350 class SendMessageToBackendTask : public TaskRunner::Task {
351 public:
352 explicit SendMessageToBackendTask(
353 const v8::internal::Vector<uint16_t>& message, int context_group_id)
354 : message_(message), context_group_id_(context_group_id) {}
355
356 bool is_inspector_task() final { return true; }
357
358 private:
359 void Run() override {
360 v8_inspector::V8InspectorSession* session = nullptr;
361 {
362 v8::HandleScope handle_scope(isolate());
363 if (!context_group_id_) {
364 session = InspectorClientImpl::SessionFromContext(default_context());
365 } else {
366 session = InspectorClientFromContext(default_context())
367 ->sessions_[context_group_id_]
368 .get();
369 }
370 if (!session) return;
371 }
372 v8_inspector::StringView message_view(message_.start(), message_.length());
373 session->dispatchProtocolMessage(message_view);
374 }
375
376 v8::internal::Vector<uint16_t> message_;
377 int context_group_id_;
378 };
379
380 TaskRunner* SendMessageToBackendExtension::backend_task_runner_ = nullptr;
381
382 void SendMessageToBackendExtension::Run(v8::Isolate* isolate,
383 v8::Local<v8::ObjectTemplate> global) {
384 global->Set(
385 v8::String::NewFromUtf8(isolate, "sendMessageToBackend",
386 v8::NewStringType::kNormal)
387 .ToLocalChecked(),
388 v8::FunctionTemplate::New(
389 isolate, &SendMessageToBackendExtension::SendMessageToBackend));
390 }
391
392 void SendMessageToBackendExtension::SendMessageToBackend(
393 const v8::FunctionCallbackInfo<v8::Value>& args) {
394 CHECK(backend_task_runner_);
395 CHECK(args.Length() == 2 && args[0]->IsString() && args[1]->IsInt32());
396 v8::Local<v8::String> message = args[0].As<v8::String>();
397 backend_task_runner_->Append(new SendMessageToBackendTask(
398 ToVector(message), args[1].As<v8::Int32>()->Value()));
399 }
OLDNEW
« no previous file with comments | « test/inspector/inspector-impl.h ('k') | test/inspector/inspector-test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698